From e589f9b7078e1c0191613cd736f598e81d2390de Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Thu, 11 Nov 2021 08:45:44 +0100 Subject: [PATCH 00001/11454] fs/ntfs3: Fix some memory leaks in an error handling path of 'log_replay()' All error handling paths lead to 'out' where many resources are freed. Do it as well here instead of a direct return, otherwise 'log', 'ra' and 'log->one_page_buf' (at least) will leak. Fixes: b46acd6a6a62 ("fs/ntfs3: Add NTFS journal") Signed-off-by: Christophe JAILLET Signed-off-by: Konstantin Komarov --- fs/ntfs3/fslog.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/fslog.c b/fs/ntfs3/fslog.c index 06492f088d60..915f42cf07bc 100644 --- a/fs/ntfs3/fslog.c +++ b/fs/ntfs3/fslog.c @@ -4085,8 +4085,10 @@ process_log: if (client == LFS_NO_CLIENT_LE) { /* Insert "NTFS" client LogFile. */ client = ra->client_idx[0]; - if (client == LFS_NO_CLIENT_LE) - return -EINVAL; + if (client == LFS_NO_CLIENT_LE) { + err = -EINVAL; + goto out; + } t16 = le16_to_cpu(client); cr = ca + t16; From e95113ed4d428219e3395044e29f5713fc446720 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 22 Oct 2021 17:37:52 +0300 Subject: [PATCH 00002/11454] fs/ntfs3: Keep preallocated only if option prealloc enabled If size of file was reduced, we still kept allocated blocks. This commit makes ntfs3 work as other fs like btrfs. Link: https://bugzilla.kernel.org/show_bug.cgi?id=214719 Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation") Reported-by: Ganapathi Kamath Tested-by: Ganapathi Kamath Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 43b1451bff53..3ac0482c6880 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -494,7 +494,7 @@ static int ntfs_truncate(struct inode *inode, loff_t new_size) down_write(&ni->file.run_lock); err = attr_set_size(ni, ATTR_DATA, NULL, 0, &ni->file.run, new_size, - &new_valid, true, NULL); + &new_valid, ni->mi.sbi->options->prealloc, NULL); up_write(&ni->file.run_lock); if (new_valid < ni->i_valid) From 87e21c99bad763524c953ff4d1a61ee19038ddc2 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 22 Oct 2021 18:15:36 +0300 Subject: [PATCH 00003/11454] fs/ntfs3: Restore ntfs_xattr_get_acl and ntfs_xattr_set_acl functions Apparently we need to maintain these functions with ntfs_get_acl_ex and ntfs_set_acl_ex. This commit fixes xfstest generic/099 Fixes: 95dd8b2c1ed0 ("fs/ntfs3: Remove unnecessary functions") Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index afd0ddad826f..56e774d0f56a 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -112,7 +112,7 @@ static int ntfs_read_ea(struct ntfs_inode *ni, struct EA_FULL **ea, return -ENOMEM; if (!size) { - ; + /* EA info persists, but xattr is empty. Looks like EA problem. */ } else if (attr_ea->non_res) { struct runs_tree run; @@ -619,6 +619,67 @@ int ntfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode, return ntfs_set_acl_ex(mnt_userns, inode, acl, type); } +static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns, + struct inode *inode, int type, void *buffer, + size_t size) +{ + struct posix_acl *acl; + int err; + + if (!(inode->i_sb->s_flags & SB_POSIXACL)) { + ntfs_inode_warn(inode, "add mount option \"acl\" to use acl"); + return -EOPNOTSUPP; + } + + acl = ntfs_get_acl(inode, type, false); + if (IS_ERR(acl)) + return PTR_ERR(acl); + + if (!acl) + return -ENODATA; + + err = posix_acl_to_xattr(mnt_userns, acl, buffer, size); + posix_acl_release(acl); + + return err; +} + +static int ntfs_xattr_set_acl(struct user_namespace *mnt_userns, + struct inode *inode, int type, const void *value, + size_t size) +{ + struct posix_acl *acl; + int err; + + if (!(inode->i_sb->s_flags & SB_POSIXACL)) { + ntfs_inode_warn(inode, "add mount option \"acl\" to use acl"); + return -EOPNOTSUPP; + } + + if (!inode_owner_or_capable(mnt_userns, inode)) + return -EPERM; + + if (!value) { + acl = NULL; + } else { + acl = posix_acl_from_xattr(mnt_userns, value, size); + if (IS_ERR(acl)) + return PTR_ERR(acl); + + if (acl) { + err = posix_acl_valid(mnt_userns, acl); + if (err) + goto release_and_out; + } + } + + err = ntfs_set_acl(mnt_userns, inode, acl, type); + +release_and_out: + posix_acl_release(acl); + return err; +} + /* * ntfs_init_acl - Initialize the ACLs of a new inode. * @@ -785,6 +846,23 @@ static int ntfs_getxattr(const struct xattr_handler *handler, struct dentry *de, goto out; } +#ifdef CONFIG_NTFS3_FS_POSIX_ACL + if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 && + !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS, + sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) || + (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 && + !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, + sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) { + /* TODO: init_user_ns? */ + err = ntfs_xattr_get_acl( + &init_user_ns, inode, + name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 + ? ACL_TYPE_ACCESS + : ACL_TYPE_DEFAULT, + buffer, size); + goto out; + } +#endif /* Deal with NTFS extended attribute. */ err = ntfs_get_ea(inode, name, name_len, buffer, size, NULL); @@ -897,6 +975,22 @@ set_new_fa: goto out; } +#ifdef CONFIG_NTFS3_FS_POSIX_ACL + if ((name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 && + !memcmp(name, XATTR_NAME_POSIX_ACL_ACCESS, + sizeof(XATTR_NAME_POSIX_ACL_ACCESS))) || + (name_len == sizeof(XATTR_NAME_POSIX_ACL_DEFAULT) - 1 && + !memcmp(name, XATTR_NAME_POSIX_ACL_DEFAULT, + sizeof(XATTR_NAME_POSIX_ACL_DEFAULT)))) { + err = ntfs_xattr_set_acl( + mnt_userns, inode, + name_len == sizeof(XATTR_NAME_POSIX_ACL_ACCESS) - 1 + ? ACL_TYPE_ACCESS + : ACL_TYPE_DEFAULT, + value, size); + goto out; + } +#endif /* Deal with NTFS extended attribute. */ err = ntfs_set_ea(inode, name, name_len, value, size, flags); From 2d44667c306e7806848a3478820f87343feb5421 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 22 Oct 2021 18:35:43 +0300 Subject: [PATCH 00004/11454] fs/ntfs3: Update i_ctime when xattr is added Ctime wasn't updated after setfacl command. This commit fixes xfstest generic/307 Fixes: be71b5cba2e6 ("fs/ntfs3: Add attrib operations") Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 56e774d0f56a..af818300493d 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -995,6 +995,9 @@ set_new_fa: err = ntfs_set_ea(inode, name, name_len, value, size, flags); out: + inode->i_ctime = current_time(inode); + mark_inode_dirty(inode); + return err; } From 3a2154b25a9f461a1848371b3e8f6f316434ae1f Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Fri, 22 Oct 2021 18:30:22 +0300 Subject: [PATCH 00005/11454] fs/ntfs3: Optimize locking in ntfs_save_wsl_perm Right now in ntfs_save_wsl_perm we lock/unlock 4 times. This commit fixes this situation. We add "locked" argument to ntfs_set_ea. Suggested-by: Kari Argillander Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index af818300493d..94a277615b62 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -259,7 +259,7 @@ out: static noinline int ntfs_set_ea(struct inode *inode, const char *name, size_t name_len, const void *value, - size_t val_size, int flags) + size_t val_size, int flags, bool locked) { struct ntfs_inode *ni = ntfs_i(inode); struct ntfs_sb_info *sbi = ni->mi.sbi; @@ -278,7 +278,8 @@ static noinline int ntfs_set_ea(struct inode *inode, const char *name, u64 new_sz; void *p; - ni_lock(ni); + if (!locked) + ni_lock(ni); run_init(&ea_run); @@ -467,7 +468,8 @@ update_ea: mark_inode_dirty(&ni->vfs_inode); out: - ni_unlock(ni); + if (!locked) + ni_unlock(ni); run_close(&ea_run); kfree(ea_all); @@ -598,7 +600,7 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, flags = 0; } - err = ntfs_set_ea(inode, name, name_len, value, size, flags); + err = ntfs_set_ea(inode, name, name_len, value, size, flags, 0); if (err == -ENODATA && !size) err = 0; /* Removing non existed xattr. */ if (!err) @@ -992,7 +994,7 @@ set_new_fa: } #endif /* Deal with NTFS extended attribute. */ - err = ntfs_set_ea(inode, name, name_len, value, size, flags); + err = ntfs_set_ea(inode, name, name_len, value, size, flags, 0); out: inode->i_ctime = current_time(inode); @@ -1010,35 +1012,37 @@ int ntfs_save_wsl_perm(struct inode *inode) { int err; __le32 value; + struct ntfs_inode *ni = ntfs_i(inode); - /* TODO: refactor this, so we don't lock 4 times in ntfs_set_ea */ + ni_lock(ni); value = cpu_to_le32(i_uid_read(inode)); err = ntfs_set_ea(inode, "$LXUID", sizeof("$LXUID") - 1, &value, - sizeof(value), 0); + sizeof(value), 0, true); /* true == already locked. */ if (err) goto out; value = cpu_to_le32(i_gid_read(inode)); err = ntfs_set_ea(inode, "$LXGID", sizeof("$LXGID") - 1, &value, - sizeof(value), 0); + sizeof(value), 0, true); if (err) goto out; value = cpu_to_le32(inode->i_mode); err = ntfs_set_ea(inode, "$LXMOD", sizeof("$LXMOD") - 1, &value, - sizeof(value), 0); + sizeof(value), 0, true); if (err) goto out; if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { value = cpu_to_le32(inode->i_rdev); err = ntfs_set_ea(inode, "$LXDEV", sizeof("$LXDEV") - 1, &value, - sizeof(value), 0); + sizeof(value), 0, true); if (err) goto out; } out: + ni_unlock(ni); /* In case of error should we delete all WSL xattr? */ return err; } From 9186d472ee780fabf74424756c4c00545166157e Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Wed, 24 Nov 2021 15:08:19 +0300 Subject: [PATCH 00006/11454] fs/ntfs3: In function ntfs_set_acl_ex do not change inode->i_mode if called from function ntfs_init_acl ntfs_init_acl sets mode. ntfs_init_acl calls ntfs_set_acl_ex. ntfs_set_acl_ex must not change this mode. Fixes xfstest generic/444 Fixes: be71b5cba2e6 ("fs/ntfs3: Add attrib operations") Reviewed-by: Joe Perches Signed-off-by: Konstantin Komarov --- fs/ntfs3/xattr.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index 94a277615b62..5e0e0280e70d 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -543,7 +543,7 @@ struct posix_acl *ntfs_get_acl(struct inode *inode, int type, bool rcu) static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, struct inode *inode, struct posix_acl *acl, - int type) + int type, bool init_acl) { const char *name; size_t size, name_len; @@ -556,8 +556,9 @@ static noinline int ntfs_set_acl_ex(struct user_namespace *mnt_userns, switch (type) { case ACL_TYPE_ACCESS: - if (acl) { - umode_t mode = inode->i_mode; + /* Do not change i_mode if we are in init_acl */ + if (acl && !init_acl) { + umode_t mode; err = posix_acl_update_mode(mnt_userns, inode, &mode, &acl); @@ -618,7 +619,7 @@ out: int ntfs_set_acl(struct user_namespace *mnt_userns, struct inode *inode, struct posix_acl *acl, int type) { - return ntfs_set_acl_ex(mnt_userns, inode, acl, type); + return ntfs_set_acl_ex(mnt_userns, inode, acl, type, false); } static int ntfs_xattr_get_acl(struct user_namespace *mnt_userns, @@ -699,7 +700,7 @@ int ntfs_init_acl(struct user_namespace *mnt_userns, struct inode *inode, if (default_acl) { err = ntfs_set_acl_ex(mnt_userns, inode, default_acl, - ACL_TYPE_DEFAULT); + ACL_TYPE_DEFAULT, true); posix_acl_release(default_acl); } else { inode->i_default_acl = NULL; @@ -710,7 +711,7 @@ int ntfs_init_acl(struct user_namespace *mnt_userns, struct inode *inode, else { if (!err) err = ntfs_set_acl_ex(mnt_userns, inode, acl, - ACL_TYPE_ACCESS); + ACL_TYPE_ACCESS, true); posix_acl_release(acl); } From 3880f2b816a7e4ca889b7e8a42e6c62c5706ed36 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 25 Oct 2021 18:31:28 +0300 Subject: [PATCH 00007/11454] fs/ntfs3: Fix fiemap + fix shrink file size (to remove preallocated space) Two problems: 1. ntfs3_setattr can't truncate preallocated space; 2. if allocated fragment "cross" valid size, then fragment splits into two parts: - normal part; - unwritten part (here we must return FIEMAP_EXTENT_LAST). Before this commit we returned FIEMAP_EXTENT_LAST for whole fragment. Fixes xfstest generic/092 Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation") Signed-off-by: Konstantin Komarov --- fs/ntfs3/file.c | 2 +- fs/ntfs3/frecord.c | 10 +++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 3ac0482c6880..6242708980d0 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -761,7 +761,7 @@ int ntfs3_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, } inode_dio_wait(inode); - if (attr->ia_size < oldsize) + if (attr->ia_size <= oldsize) err = ntfs_truncate(inode, attr->ia_size); else if (attr->ia_size > oldsize) err = ntfs_extend(inode, attr->ia_size, 0, NULL); diff --git a/fs/ntfs3/frecord.c b/fs/ntfs3/frecord.c index 6f47a9c17f89..18842998c8fa 100644 --- a/fs/ntfs3/frecord.c +++ b/fs/ntfs3/frecord.c @@ -1964,10 +1964,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, vcn += clen; - if (vbo + bytes >= end) { + if (vbo + bytes >= end) bytes = end - vbo; - flags |= FIEMAP_EXTENT_LAST; - } if (vbo + bytes <= valid) { ; @@ -1977,6 +1975,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, /* vbo < valid && valid < vbo + bytes */ u64 dlen = valid - vbo; + if (vbo + dlen >= end) + flags |= FIEMAP_EXTENT_LAST; + err = fiemap_fill_next_extent(fieinfo, vbo, lbo, dlen, flags); if (err < 0) @@ -1995,6 +1996,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, flags |= FIEMAP_EXTENT_UNWRITTEN; } + if (vbo + bytes >= end) + flags |= FIEMAP_EXTENT_LAST; + err = fiemap_fill_next_extent(fieinfo, vbo, lbo, bytes, flags); if (err < 0) break; From 114346978cf61de02832cc3cc68432a3de70fb38 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 25 Oct 2021 18:34:06 +0300 Subject: [PATCH 00008/11454] fs/ntfs3: Check new size for limits We must check size before trying to allocate. Size can be set for example by "ulimit -f". Fixes xfstest generic/228 Fixes: 4342306f0f0d ("fs/ntfs3: Add file operations and implementation") Reviewed-by: Kari Argillander Signed-off-by: Konstantin Komarov --- fs/ntfs3/file.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/fs/ntfs3/file.c b/fs/ntfs3/file.c index 6242708980d0..f8360f9bfaf0 100644 --- a/fs/ntfs3/file.c +++ b/fs/ntfs3/file.c @@ -661,7 +661,13 @@ static long ntfs_fallocate(struct file *file, int mode, loff_t vbo, loff_t len) /* * Normal file: Allocate clusters, do not change 'valid' size. */ - err = ntfs_set_size(inode, max(end, i_size)); + loff_t new_size = max(end, i_size); + + err = inode_newsize_ok(inode, new_size); + if (err) + goto out; + + err = ntfs_set_size(inode, new_size); if (err) goto out; From 52e00ea6b26e45fb8159e3b57cdde8d3f9bdd8e9 Mon Sep 17 00:00:00 2001 From: Konstantin Komarov Date: Mon, 25 Oct 2021 18:48:38 +0300 Subject: [PATCH 00009/11454] fs/ntfs3: Update valid size if -EIOCBQUEUED Update valid size if write is still in I/O queue. Fixes xfstest generic/240 Fixes: 82cae269cfa9 ("fs/ntfs3: Add initialization of super block") Signed-off-by: Konstantin Komarov --- fs/ntfs3/inode.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/ntfs3/inode.c b/fs/ntfs3/inode.c index 859951d785cb..879952254071 100644 --- a/fs/ntfs3/inode.c +++ b/fs/ntfs3/inode.c @@ -757,6 +757,7 @@ static ssize_t ntfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) loff_t vbo = iocb->ki_pos; loff_t end; int wr = iov_iter_rw(iter) & WRITE; + size_t iter_count = iov_iter_count(iter); loff_t valid; ssize_t ret; @@ -770,10 +771,13 @@ static ssize_t ntfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) wr ? ntfs_get_block_direct_IO_W : ntfs_get_block_direct_IO_R); - if (ret <= 0) + if (ret > 0) + end = vbo + ret; + else if (wr && ret == -EIOCBQUEUED) + end = vbo + iter_count; + else goto out; - end = vbo + ret; valid = ni->i_valid; if (wr) { if (end > valid && !S_ISBLK(inode->i_mode)) { From 6c00ef0d3c680c1d7a852c7a6a656df1851d2951 Mon Sep 17 00:00:00 2001 From: tangmeng Date: Thu, 27 Jan 2022 15:15:09 +0800 Subject: [PATCH 00010/11454] drivers/pcmcia: Fix typo in comment Replace unavaibale with unavailable. Signed-off-by: tangmeng Signed-off-by: Dominik Brodowski --- drivers/pcmcia/rsrc_nonstatic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 6b6c578b5f92..ad1141fddb4c 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -394,7 +394,7 @@ static int do_validate_mem(struct pcmcia_socket *s, * do_mem_probe() checks a memory region for use by the PCMCIA subsystem. * To do so, the area is split up into sensible parts, and then passed * into the @validate() function. Only if @validate() and @fallback() fail, - * the area is marked as unavaibale for use by the PCMCIA subsystem. The + * the area is marked as unavailable for use by the PCMCIA subsystem. The * function returns the size of the usable memory area. */ static int do_mem_probe(struct pcmcia_socket *s, u_long base, u_long num, From 3928cf08334ed895a31458cbebd8d4ec6d84c080 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 23 Jan 2022 09:40:31 -0800 Subject: [PATCH 00011/11454] pcmcia: db1xxx_ss: restrict to MIPS_DB1XXX boards When the MIPS_ALCHEMY board selection is MIPS_XXS1500 instead of MIPS_DB1XXX, the PCMCIA driver 'db1xxx_ss' has build errors due to missing DB1XXX symbols. The PCMCIA driver should be restricted to MIPS_DB1XXX instead of MIPS_ALCHEMY to fix this build error. ERROR: modpost: "bcsr_read" [drivers/pcmcia/db1xxx_ss.ko] undefined! ERROR: modpost: "bcsr_mod" [drivers/pcmcia/db1xxx_ss.ko] undefined! Fixes: 42a4f17dc356 ("MIPS: Alchemy: remove SOC_AU1X00 in favor of MIPS_ALCHEMY") Signed-off-by: Randy Dunlap Reported-by: kernel test robot Cc: Arnd Bergmann Cc: Daniel Vetter Cc: Kees Cook Cc: Thomas Bogendoerfer Cc: linux-mips@vger.kernel.org Acked-by: Manuel Lauss Signed-off-by: Dominik Brodowski --- drivers/pcmcia/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index ab53eab635f6..1740a63b814d 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -151,7 +151,7 @@ config TCIC config PCMCIA_ALCHEMY_DEVBOARD tristate "Alchemy Db/Pb1xxx PCMCIA socket services" - depends on MIPS_ALCHEMY && PCMCIA + depends on MIPS_DB1XXX && PCMCIA help Enable this driver of you want PCMCIA support on your Alchemy Db1000, Db/Pb1100, Db/Pb1500, Db/Pb1550, Db/Pb1200, DB1300 From cfa1e01ecf516511bfc0fa87f96aa19bc6ee401f Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 1 Feb 2022 19:06:26 +0100 Subject: [PATCH 00012/11454] net: ieee802154: ca8210: Fix lifs/sifs periods These periods are expressed in time units (microseconds) while 40 and 12 are the number of symbol durations these periods will last. We need to multiply them both with the symbol_duration in order to get these values in microseconds. Fixes: ded845a781a5 ("ieee802154: Add CA8210 IEEE 802.15.4 device driver") Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/r/20220201180629.93410-2-miquel.raynal@bootlin.com Signed-off-by: Stefan Schmidt --- drivers/net/ieee802154/ca8210.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index f3438d3e104a..2bc730fd260e 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -2975,8 +2975,8 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw) ca8210_hw->phy->cca.opt = NL802154_CCA_OPT_ENERGY_CARRIER_AND; ca8210_hw->phy->cca_ed_level = -9800; ca8210_hw->phy->symbol_duration = 16; - ca8210_hw->phy->lifs_period = 40; - ca8210_hw->phy->sifs_period = 12; + ca8210_hw->phy->lifs_period = 40 * ca8210_hw->phy->symbol_duration; + ca8210_hw->phy->sifs_period = 12 * ca8210_hw->phy->symbol_duration; ca8210_hw->flags = IEEE802154_HW_AFILT | IEEE802154_HW_OMIT_CKSUM | From 731cddce6dd110fb2cdee34eddb48599e7251517 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 1 Feb 2022 19:06:27 +0100 Subject: [PATCH 00013/11454] net: mac802154: Convert the symbol duration into nanoseconds Tdsym is often given in the spec as pretty small numbers in microseconds and hence was reflected in the code as symbol_duration and was stored as a u8. Actually, for UWB PHYs, the symbol duration is given in nanoseconds and are as precise as picoseconds. In order to handle better these PHYs, change the type of symbol_duration to u32 and store this value in nanoseconds. All the users of this variable are updated in a mechanical way. Signed-off-by: Miquel Raynal Acked-by: Alexander Aring Link: https://lore.kernel.org/r/20220201180629.93410-3-miquel.raynal@bootlin.com Signed-off-by: Stefan Schmidt --- drivers/net/ieee802154/at86rf230.c | 22 +++++++++++----------- drivers/net/ieee802154/atusb.c | 22 +++++++++++----------- drivers/net/ieee802154/ca8210.c | 2 +- drivers/net/ieee802154/mcr20a.c | 8 ++++---- include/net/cfg802154.h | 4 ++-- net/mac802154/main.c | 8 ++++---- 6 files changed, 33 insertions(+), 33 deletions(-) diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 4f5ef8a9a9a8..0264e43a1080 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1075,24 +1075,24 @@ at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel) if (channel == 0) { if (page == 0) { /* SUB:0 and BPSK:0 -> BPSK-20 */ - lp->hw->phy->symbol_duration = 50; + lp->hw->phy->symbol_duration = 50 * NSEC_PER_USEC; } else { /* SUB:1 and BPSK:0 -> BPSK-40 */ - lp->hw->phy->symbol_duration = 25; + lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC; } } else { if (page == 0) /* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */ - lp->hw->phy->symbol_duration = 40; + lp->hw->phy->symbol_duration = 40 * NSEC_PER_USEC; else /* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */ - lp->hw->phy->symbol_duration = 16; + lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; } - lp->hw->phy->lifs_period = IEEE802154_LIFS_PERIOD * - lp->hw->phy->symbol_duration; - lp->hw->phy->sifs_period = IEEE802154_SIFS_PERIOD * - lp->hw->phy->symbol_duration; + lp->hw->phy->lifs_period = + (IEEE802154_LIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000; + lp->hw->phy->sifs_period = + (IEEE802154_SIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000; return at86rf230_write_subreg(lp, SR_CHANNEL, channel); } @@ -1569,7 +1569,7 @@ at86rf230_detect_device(struct at86rf230_local *lp) lp->data = &at86rf231_data; lp->hw->phy->supported.channels[0] = 0x7FFF800; lp->hw->phy->current_channel = 11; - lp->hw->phy->symbol_duration = 16; + lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; lp->hw->phy->supported.tx_powers = at86rf231_powers; lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf231_powers); lp->hw->phy->supported.cca_ed_levels = at86rf231_ed_levels; @@ -1582,7 +1582,7 @@ at86rf230_detect_device(struct at86rf230_local *lp) lp->hw->phy->supported.channels[0] = 0x00007FF; lp->hw->phy->supported.channels[2] = 0x00007FF; lp->hw->phy->current_channel = 5; - lp->hw->phy->symbol_duration = 25; + lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC; lp->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH; lp->hw->phy->supported.tx_powers = at86rf212_powers; lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers); @@ -1594,7 +1594,7 @@ at86rf230_detect_device(struct at86rf230_local *lp) lp->data = &at86rf233_data; lp->hw->phy->supported.channels[0] = 0x7FFF800; lp->hw->phy->current_channel = 13; - lp->hw->phy->symbol_duration = 16; + lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; lp->hw->phy->supported.tx_powers = at86rf233_powers; lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf233_powers); lp->hw->phy->supported.cca_ed_levels = at86rf233_ed_levels; diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 07bafbf94680..abe27d1c51ca 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -625,24 +625,24 @@ static int hulusb_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) if (channel == 0) { if (page == 0) { /* SUB:0 and BPSK:0 -> BPSK-20 */ - lp->hw->phy->symbol_duration = 50; + lp->hw->phy->symbol_duration = 50 * NSEC_PER_USEC; } else { /* SUB:1 and BPSK:0 -> BPSK-40 */ - lp->hw->phy->symbol_duration = 25; + lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC; } } else { if (page == 0) /* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */ - lp->hw->phy->symbol_duration = 40; + lp->hw->phy->symbol_duration = 40 * NSEC_PER_USEC; else /* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */ - lp->hw->phy->symbol_duration = 16; + lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; } - lp->hw->phy->lifs_period = IEEE802154_LIFS_PERIOD * - lp->hw->phy->symbol_duration; - lp->hw->phy->sifs_period = IEEE802154_SIFS_PERIOD * - lp->hw->phy->symbol_duration; + lp->hw->phy->lifs_period = + (IEEE802154_LIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000; + lp->hw->phy->sifs_period = + (IEEE802154_SIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000; return atusb_write_subreg(lp, SR_CHANNEL, channel); } @@ -869,7 +869,7 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) chip = "AT86RF230"; atusb->hw->phy->supported.channels[0] = 0x7FFF800; atusb->hw->phy->current_channel = 11; /* reset default */ - atusb->hw->phy->symbol_duration = 16; + atusb->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; atusb->hw->phy->supported.tx_powers = atusb_powers; atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); hw->phy->supported.cca_ed_levels = atusb_ed_levels; @@ -879,7 +879,7 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) chip = "AT86RF231"; atusb->hw->phy->supported.channels[0] = 0x7FFF800; atusb->hw->phy->current_channel = 11; /* reset default */ - atusb->hw->phy->symbol_duration = 16; + atusb->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; atusb->hw->phy->supported.tx_powers = atusb_powers; atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); hw->phy->supported.cca_ed_levels = atusb_ed_levels; @@ -891,7 +891,7 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) atusb->hw->phy->supported.channels[0] = 0x00007FF; atusb->hw->phy->supported.channels[2] = 0x00007FF; atusb->hw->phy->current_channel = 5; - atusb->hw->phy->symbol_duration = 25; + atusb->hw->phy->symbol_duration = 25 * NSEC_PER_USEC; atusb->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH; atusb->hw->phy->supported.tx_powers = at86rf212_powers; atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers); diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index 2bc730fd260e..e88cdbf6673b 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -2974,7 +2974,7 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw) ca8210_hw->phy->cca.mode = NL802154_CCA_ENERGY_CARRIER; ca8210_hw->phy->cca.opt = NL802154_CCA_OPT_ENERGY_CARRIER_AND; ca8210_hw->phy->cca_ed_level = -9800; - ca8210_hw->phy->symbol_duration = 16; + ca8210_hw->phy->symbol_duration = 16 * NSEC_PER_USEC; ca8210_hw->phy->lifs_period = 40 * ca8210_hw->phy->symbol_duration; ca8210_hw->phy->sifs_period = 12 * ca8210_hw->phy->symbol_duration; ca8210_hw->flags = diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c index 383231b85464..c925e629ddf3 100644 --- a/drivers/net/ieee802154/mcr20a.c +++ b/drivers/net/ieee802154/mcr20a.c @@ -975,9 +975,9 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp) dev_dbg(printdev(lp), "%s\n", __func__); - phy->symbol_duration = 16; - phy->lifs_period = 40 * phy->symbol_duration; - phy->sifs_period = 12 * phy->symbol_duration; + phy->symbol_duration = 16 * NSEC_PER_USEC; + phy->lifs_period = (40 * phy->symbol_duration) / NSEC_PER_USEC; + phy->sifs_period = (12 * phy->symbol_duration) / NSEC_PER_USEC; hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | @@ -1006,7 +1006,7 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp) phy->current_page = 0; /* MCR20A default reset value */ phy->current_channel = 20; - phy->symbol_duration = 16; + phy->symbol_duration = 16 * NSEC_PER_USEC; phy->supported.tx_powers = mcr20a_powers; phy->supported.tx_powers_size = ARRAY_SIZE(mcr20a_powers); phy->cca_ed_level = phy->supported.cca_ed_levels[75]; diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 833672d6fbe4..92d4f178caca 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -203,8 +203,8 @@ struct wpan_phy { /* PHY depended MAC PIB values */ - /* 802.15.4 acronym: Tdsym in usec */ - u8 symbol_duration; + /* 802.15.4 acronym: Tdsym in nsec */ + u32 symbol_duration; /* lifs and sifs periods timing */ u16 lifs_period; u16 sifs_period; diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 520cedc594e1..53153367f9d0 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -131,10 +131,10 @@ static void ieee802154_setup_wpan_phy_pib(struct wpan_phy *wpan_phy) * Should be done when all drivers sets this value. */ - wpan_phy->lifs_period = IEEE802154_LIFS_PERIOD * - wpan_phy->symbol_duration; - wpan_phy->sifs_period = IEEE802154_SIFS_PERIOD * - wpan_phy->symbol_duration; + wpan_phy->lifs_period = + (IEEE802154_LIFS_PERIOD * wpan_phy->symbol_duration) / 1000; + wpan_phy->sifs_period = + (IEEE802154_SIFS_PERIOD * wpan_phy->symbol_duration) / 1000; } int ieee802154_register_hw(struct ieee802154_hw *hw) From 781830c800ddd19566846c634de09fadf37eafde Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 1 Feb 2022 19:06:28 +0100 Subject: [PATCH 00014/11454] net: mac802154: Set durations automatically As depicted in the IEEE 802.15.4 specification, modulation/bands are tight to a number of page/channels so we can for most of them derive the durations automatically. The two locations that must call this new helper to set the variou symbol durations are: - when manually requesting a channel change though the netlink interface - at PHY creation, once the device driver has set the default page/channel If an information is missing, the symbol duration is not touched, a debug message is eventually printed. This keeps the compatibility with the unconverted drivers for which it was too complicated for me to find their precise information. If they initially provided a symbol duration, it would be kept. If they don't, the symbol duration value is left untouched. Once the symbol duration derived, the lifs and sifs durations are updated as well. Signed-off-by: Miquel Raynal Acked-by: Alexander Aring Link: https://lore.kernel.org/r/20220201180629.93410-4-miquel.raynal@bootlin.com Signed-off-by: Stefan Schmidt --- include/net/cfg802154.h | 2 ++ net/mac802154/cfg.c | 1 + net/mac802154/main.c | 46 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/include/net/cfg802154.h b/include/net/cfg802154.h index 92d4f178caca..85f9e8417688 100644 --- a/include/net/cfg802154.h +++ b/include/net/cfg802154.h @@ -415,4 +415,6 @@ static inline const char *wpan_phy_name(struct wpan_phy *phy) return dev_name(&phy->dev); } +void ieee802154_configure_durations(struct wpan_phy *phy); + #endif /* __NET_CFG802154_H */ diff --git a/net/mac802154/cfg.c b/net/mac802154/cfg.c index fbeebe3bc31d..1e4a9f74ed43 100644 --- a/net/mac802154/cfg.c +++ b/net/mac802154/cfg.c @@ -118,6 +118,7 @@ ieee802154_set_channel(struct wpan_phy *wpan_phy, u8 page, u8 channel) if (!ret) { wpan_phy->current_page = page; wpan_phy->current_channel = channel; + ieee802154_configure_durations(wpan_phy); } return ret; diff --git a/net/mac802154/main.c b/net/mac802154/main.c index 53153367f9d0..5546ef86e231 100644 --- a/net/mac802154/main.c +++ b/net/mac802154/main.c @@ -113,6 +113,50 @@ ieee802154_alloc_hw(size_t priv_data_len, const struct ieee802154_ops *ops) } EXPORT_SYMBOL(ieee802154_alloc_hw); +void ieee802154_configure_durations(struct wpan_phy *phy) +{ + u32 duration = 0; + + switch (phy->current_page) { + case 0: + if (BIT(phy->current_page) & 0x1) + /* 868 MHz BPSK 802.15.4-2003: 20 ksym/s */ + duration = 50 * NSEC_PER_USEC; + else if (phy->current_page & 0x7FE) + /* 915 MHz BPSK 802.15.4-2003: 40 ksym/s */ + duration = 25 * NSEC_PER_USEC; + else if (phy->current_page & 0x7FFF800) + /* 2400 MHz O-QPSK 802.15.4-2006: 62.5 ksym/s */ + duration = 16 * NSEC_PER_USEC; + break; + case 2: + if (BIT(phy->current_page) & 0x1) + /* 868 MHz O-QPSK 802.15.4-2006: 25 ksym/s */ + duration = 40 * NSEC_PER_USEC; + else if (phy->current_page & 0x7FE) + /* 915 MHz O-QPSK 802.15.4-2006: 62.5 ksym/s */ + duration = 16 * NSEC_PER_USEC; + break; + case 3: + if (BIT(phy->current_page) & 0x3FFF) + /* 2.4 GHz CSS 802.15.4a-2007: 1/6 Msym/s */ + duration = 6 * NSEC_PER_USEC; + break; + default: + break; + } + + if (!duration) { + pr_debug("Unknown PHY symbol duration\n"); + return; + } + + phy->symbol_duration = duration; + phy->lifs_period = (IEEE802154_LIFS_PERIOD * phy->symbol_duration) / NSEC_PER_SEC; + phy->sifs_period = (IEEE802154_SIFS_PERIOD * phy->symbol_duration) / NSEC_PER_SEC; +} +EXPORT_SYMBOL(ieee802154_configure_durations); + void ieee802154_free_hw(struct ieee802154_hw *hw) { struct ieee802154_local *local = hw_to_local(hw); @@ -157,6 +201,8 @@ int ieee802154_register_hw(struct ieee802154_hw *hw) ieee802154_setup_wpan_phy_pib(local->phy); + ieee802154_configure_durations(local->phy); + if (!(hw->flags & IEEE802154_HW_CSMA_PARAMS)) { local->phy->supported.min_csma_backoffs = 4; local->phy->supported.max_csma_backoffs = 4; From b8e508f42138b42b44f65679d02aad3c200aff68 Mon Sep 17 00:00:00 2001 From: Miquel Raynal Date: Tue, 1 Feb 2022 19:06:29 +0100 Subject: [PATCH 00015/11454] net: ieee802154: Drop duration settings when the core does it already The core now knows how to set the symbol duration in a few cases, when drivers correctly advertise the protocols used on each channel. For these drivers, there is no more need to bother with symbol duration, lifs and sifs periods so just drop the duplicated code. Signed-off-by: Miquel Raynal Acked-by: Alexander Aring Link: https://lore.kernel.org/r/20220201180629.93410-5-miquel.raynal@bootlin.com Signed-off-by: Stefan Schmidt --- drivers/net/ieee802154/at86rf230.c | 33 ------------------------------ drivers/net/ieee802154/atusb.c | 33 ------------------------------ drivers/net/ieee802154/ca8210.c | 3 --- drivers/net/ieee802154/mcr20a.c | 5 ----- 4 files changed, 74 deletions(-) diff --git a/drivers/net/ieee802154/at86rf230.c b/drivers/net/ieee802154/at86rf230.c index 0264e43a1080..563031ce76f0 100644 --- a/drivers/net/ieee802154/at86rf230.c +++ b/drivers/net/ieee802154/at86rf230.c @@ -1064,36 +1064,6 @@ at86rf212_set_channel(struct at86rf230_local *lp, u8 page, u8 channel) if (rc < 0) return rc; - /* This sets the symbol_duration according frequency on the 212. - * TODO move this handling while set channel and page in cfg802154. - * We can do that, this timings are according 802.15.4 standard. - * If we do that in cfg802154, this is a more generic calculation. - * - * This should also protected from ifs_timer. Means cancel timer and - * init with a new value. For now, this is okay. - */ - if (channel == 0) { - if (page == 0) { - /* SUB:0 and BPSK:0 -> BPSK-20 */ - lp->hw->phy->symbol_duration = 50 * NSEC_PER_USEC; - } else { - /* SUB:1 and BPSK:0 -> BPSK-40 */ - lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC; - } - } else { - if (page == 0) - /* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */ - lp->hw->phy->symbol_duration = 40 * NSEC_PER_USEC; - else - /* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */ - lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; - } - - lp->hw->phy->lifs_period = - (IEEE802154_LIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000; - lp->hw->phy->sifs_period = - (IEEE802154_SIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000; - return at86rf230_write_subreg(lp, SR_CHANNEL, channel); } @@ -1569,7 +1539,6 @@ at86rf230_detect_device(struct at86rf230_local *lp) lp->data = &at86rf231_data; lp->hw->phy->supported.channels[0] = 0x7FFF800; lp->hw->phy->current_channel = 11; - lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; lp->hw->phy->supported.tx_powers = at86rf231_powers; lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf231_powers); lp->hw->phy->supported.cca_ed_levels = at86rf231_ed_levels; @@ -1582,7 +1551,6 @@ at86rf230_detect_device(struct at86rf230_local *lp) lp->hw->phy->supported.channels[0] = 0x00007FF; lp->hw->phy->supported.channels[2] = 0x00007FF; lp->hw->phy->current_channel = 5; - lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC; lp->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH; lp->hw->phy->supported.tx_powers = at86rf212_powers; lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers); @@ -1594,7 +1562,6 @@ at86rf230_detect_device(struct at86rf230_local *lp) lp->data = &at86rf233_data; lp->hw->phy->supported.channels[0] = 0x7FFF800; lp->hw->phy->current_channel = 13; - lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; lp->hw->phy->supported.tx_powers = at86rf233_powers; lp->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf233_powers); lp->hw->phy->supported.cca_ed_levels = at86rf233_ed_levels; diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index abe27d1c51ca..9b41c7654f6b 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -614,36 +614,6 @@ static int hulusb_set_channel(struct ieee802154_hw *hw, u8 page, u8 channel) if (rc < 0) return rc; - /* This sets the symbol_duration according frequency on the 212. - * TODO move this handling while set channel and page in cfg802154. - * We can do that, this timings are according 802.15.4 standard. - * If we do that in cfg802154, this is a more generic calculation. - * - * This should also protected from ifs_timer. Means cancel timer and - * init with a new value. For now, this is okay. - */ - if (channel == 0) { - if (page == 0) { - /* SUB:0 and BPSK:0 -> BPSK-20 */ - lp->hw->phy->symbol_duration = 50 * NSEC_PER_USEC; - } else { - /* SUB:1 and BPSK:0 -> BPSK-40 */ - lp->hw->phy->symbol_duration = 25 * NSEC_PER_USEC; - } - } else { - if (page == 0) - /* SUB:0 and BPSK:1 -> OQPSK-100/200/400 */ - lp->hw->phy->symbol_duration = 40 * NSEC_PER_USEC; - else - /* SUB:1 and BPSK:1 -> OQPSK-250/500/1000 */ - lp->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; - } - - lp->hw->phy->lifs_period = - (IEEE802154_LIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000; - lp->hw->phy->sifs_period = - (IEEE802154_SIFS_PERIOD * lp->hw->phy->symbol_duration) / 1000; - return atusb_write_subreg(lp, SR_CHANNEL, channel); } @@ -869,7 +839,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) chip = "AT86RF230"; atusb->hw->phy->supported.channels[0] = 0x7FFF800; atusb->hw->phy->current_channel = 11; /* reset default */ - atusb->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; atusb->hw->phy->supported.tx_powers = atusb_powers; atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); hw->phy->supported.cca_ed_levels = atusb_ed_levels; @@ -879,7 +848,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) chip = "AT86RF231"; atusb->hw->phy->supported.channels[0] = 0x7FFF800; atusb->hw->phy->current_channel = 11; /* reset default */ - atusb->hw->phy->symbol_duration = 16 * NSEC_PER_USEC; atusb->hw->phy->supported.tx_powers = atusb_powers; atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(atusb_powers); hw->phy->supported.cca_ed_levels = atusb_ed_levels; @@ -891,7 +859,6 @@ static int atusb_get_and_conf_chip(struct atusb *atusb) atusb->hw->phy->supported.channels[0] = 0x00007FF; atusb->hw->phy->supported.channels[2] = 0x00007FF; atusb->hw->phy->current_channel = 5; - atusb->hw->phy->symbol_duration = 25 * NSEC_PER_USEC; atusb->hw->phy->supported.lbt = NL802154_SUPPORTED_BOOL_BOTH; atusb->hw->phy->supported.tx_powers = at86rf212_powers; atusb->hw->phy->supported.tx_powers_size = ARRAY_SIZE(at86rf212_powers); diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c index e88cdbf6673b..fc74fa0f1ddd 100644 --- a/drivers/net/ieee802154/ca8210.c +++ b/drivers/net/ieee802154/ca8210.c @@ -2974,9 +2974,6 @@ static void ca8210_hw_setup(struct ieee802154_hw *ca8210_hw) ca8210_hw->phy->cca.mode = NL802154_CCA_ENERGY_CARRIER; ca8210_hw->phy->cca.opt = NL802154_CCA_OPT_ENERGY_CARRIER_AND; ca8210_hw->phy->cca_ed_level = -9800; - ca8210_hw->phy->symbol_duration = 16 * NSEC_PER_USEC; - ca8210_hw->phy->lifs_period = 40 * ca8210_hw->phy->symbol_duration; - ca8210_hw->phy->sifs_period = 12 * ca8210_hw->phy->symbol_duration; ca8210_hw->flags = IEEE802154_HW_AFILT | IEEE802154_HW_OMIT_CKSUM | diff --git a/drivers/net/ieee802154/mcr20a.c b/drivers/net/ieee802154/mcr20a.c index c925e629ddf3..2b4ba3f9ecd7 100644 --- a/drivers/net/ieee802154/mcr20a.c +++ b/drivers/net/ieee802154/mcr20a.c @@ -975,10 +975,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp) dev_dbg(printdev(lp), "%s\n", __func__); - phy->symbol_duration = 16 * NSEC_PER_USEC; - phy->lifs_period = (40 * phy->symbol_duration) / NSEC_PER_USEC; - phy->sifs_period = (12 * phy->symbol_duration) / NSEC_PER_USEC; - hw->flags = IEEE802154_HW_TX_OMIT_CKSUM | IEEE802154_HW_AFILT | IEEE802154_HW_PROMISCUOUS; @@ -1006,7 +1002,6 @@ static void mcr20a_hw_setup(struct mcr20a_local *lp) phy->current_page = 0; /* MCR20A default reset value */ phy->current_channel = 20; - phy->symbol_duration = 16 * NSEC_PER_USEC; phy->supported.tx_powers = mcr20a_powers; phy->supported.tx_powers_size = ARRAY_SIZE(mcr20a_powers); phy->cca_ed_level = phy->supported.cca_ed_levels[75]; From 1c4b5ecb7ea190fa3e9f9d6891e6c90b60e04f24 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 23 Feb 2022 08:47:20 +0100 Subject: [PATCH 00016/11454] remove the h8300 architecture Signed-off-by: Christoph Hellwig --- .../clock/renesas,h8300-div-clock.txt | 24 - .../devicetree/bindings/h8300/cpu.txt | 13 - .../renesas,h8300h-intc.txt | 22 - .../interrupt-controller/renesas,h8s-intc.txt | 22 - .../memory-controllers/renesas,h8300-bsc.yaml | 35 -- .../features/core/cBPF-JIT/arch-support.txt | 1 - .../features/core/eBPF-JIT/arch-support.txt | 1 - .../core/generic-idle-thread/arch-support.txt | 1 - .../core/jump-labels/arch-support.txt | 1 - .../core/thread-info-in-task/arch-support.txt | 1 - .../features/core/tracehook/arch-support.txt | 1 - .../features/debug/KASAN/arch-support.txt | 1 - .../debug/debug-vm-pgtable/arch-support.txt | 1 - .../debug/gcov-profile-all/arch-support.txt | 1 - .../features/debug/kcov/arch-support.txt | 1 - .../features/debug/kgdb/arch-support.txt | 1 - .../features/debug/kmemleak/arch-support.txt | 1 - .../debug/kprobes-on-ftrace/arch-support.txt | 1 - .../features/debug/kprobes/arch-support.txt | 1 - .../debug/kretprobes/arch-support.txt | 1 - .../features/debug/optprobes/arch-support.txt | 1 - .../debug/stackprotector/arch-support.txt | 1 - .../features/debug/uprobes/arch-support.txt | 1 - .../debug/user-ret-profiler/arch-support.txt | 1 - .../io/dma-contiguous/arch-support.txt | 1 - .../locking/cmpxchg-local/arch-support.txt | 1 - .../features/locking/lockdep/arch-support.txt | 1 - .../locking/queued-rwlocks/arch-support.txt | 1 - .../locking/queued-spinlocks/arch-support.txt | 1 - .../perf/kprobes-event/arch-support.txt | 1 - .../features/perf/perf-regs/arch-support.txt | 1 - .../perf/perf-stackdump/arch-support.txt | 1 - .../membarrier-sync-core/arch-support.txt | 1 - .../sched/numa-balancing/arch-support.txt | 1 - .../seccomp/seccomp-filter/arch-support.txt | 1 - .../time/arch-tick-broadcast/arch-support.txt | 1 - .../time/clockevents/arch-support.txt | 1 - .../time/context-tracking/arch-support.txt | 1 - .../time/irq-time-acct/arch-support.txt | 1 - .../time/virt-cpuacct/arch-support.txt | 1 - .../features/vm/ELF-ASLR/arch-support.txt | 1 - .../features/vm/PG_uncached/arch-support.txt | 1 - .../features/vm/THP/arch-support.txt | 1 - .../features/vm/TLB/arch-support.txt | 1 - .../features/vm/huge-vmap/arch-support.txt | 1 - .../features/vm/ioremap_prot/arch-support.txt | 1 - .../features/vm/pte_special/arch-support.txt | 1 - MAINTAINERS | 11 - arch/h8300/Kbuild | 5 - arch/h8300/Kconfig | 50 -- arch/h8300/Kconfig.cpu | 99 ---- arch/h8300/Kconfig.debug | 2 - arch/h8300/Makefile | 44 -- arch/h8300/boot/Makefile | 27 -- arch/h8300/boot/compressed/Makefile | 45 -- arch/h8300/boot/compressed/head.S | 49 -- arch/h8300/boot/compressed/misc.c | 76 --- arch/h8300/boot/compressed/vmlinux.lds | 35 -- arch/h8300/boot/compressed/vmlinux.scr | 9 - arch/h8300/boot/dts/Makefile | 6 - arch/h8300/boot/dts/edosk2674.dts | 108 ----- arch/h8300/boot/dts/h8300h_sim.dts | 97 ---- arch/h8300/boot/dts/h8s_sim.dts | 100 ---- arch/h8300/configs/edosk2674_defconfig | 48 -- arch/h8300/configs/h8300h-sim_defconfig | 48 -- arch/h8300/configs/h8s-sim_defconfig | 48 -- arch/h8300/include/asm/Kbuild | 8 - arch/h8300/include/asm/bitops.h | 179 -------- arch/h8300/include/asm/bug.h | 13 - arch/h8300/include/asm/byteorder.h | 7 - arch/h8300/include/asm/cache.h | 12 - arch/h8300/include/asm/elf.h | 102 ---- arch/h8300/include/asm/flat.h | 36 -- arch/h8300/include/asm/hash.h | 54 --- arch/h8300/include/asm/io.h | 67 --- arch/h8300/include/asm/irq.h | 25 - arch/h8300/include/asm/irqflags.h | 97 ---- arch/h8300/include/asm/kgdb.h | 45 -- arch/h8300/include/asm/mmu_context.h | 6 - arch/h8300/include/asm/page.h | 17 - arch/h8300/include/asm/page_offset.h | 2 - arch/h8300/include/asm/pgtable.h | 43 -- arch/h8300/include/asm/processor.h | 127 ----- arch/h8300/include/asm/ptrace.h | 39 -- arch/h8300/include/asm/segment.h | 40 -- arch/h8300/include/asm/signal.h | 23 - arch/h8300/include/asm/smp.h | 1 - arch/h8300/include/asm/string.h | 18 - arch/h8300/include/asm/switch_to.h | 52 --- arch/h8300/include/asm/syscall.h | 43 -- arch/h8300/include/asm/thread_info.h | 105 ----- arch/h8300/include/asm/tlb.h | 7 - arch/h8300/include/asm/traps.h | 41 -- arch/h8300/include/asm/user.h | 75 --- arch/h8300/include/asm/vmalloc.h | 4 - arch/h8300/include/uapi/asm/Kbuild | 2 - arch/h8300/include/uapi/asm/byteorder.h | 7 - arch/h8300/include/uapi/asm/posix_types.h | 13 - arch/h8300/include/uapi/asm/ptrace.h | 43 -- arch/h8300/include/uapi/asm/sigcontext.h | 19 - arch/h8300/include/uapi/asm/signal.h | 92 ---- arch/h8300/include/uapi/asm/unistd.h | 8 - arch/h8300/kernel/.gitignore | 2 - arch/h8300/kernel/Makefile | 22 - arch/h8300/kernel/asm-offsets.c | 70 --- arch/h8300/kernel/entry.S | 434 ------------------ arch/h8300/kernel/h8300_ksyms.c | 35 -- arch/h8300/kernel/head_ram.S | 61 --- arch/h8300/kernel/head_rom.S | 111 ----- arch/h8300/kernel/irq.c | 99 ---- arch/h8300/kernel/kgdb.c | 135 ------ arch/h8300/kernel/module.c | 71 --- arch/h8300/kernel/process.c | 173 ------- arch/h8300/kernel/ptrace.c | 200 -------- arch/h8300/kernel/ptrace_h.c | 256 ----------- arch/h8300/kernel/ptrace_s.c | 44 -- arch/h8300/kernel/setup.c | 213 --------- arch/h8300/kernel/signal.c | 287 ------------ arch/h8300/kernel/sim-console.c | 31 -- arch/h8300/kernel/syscalls.c | 15 - arch/h8300/kernel/traps.c | 156 ------- arch/h8300/kernel/vmlinux.lds.S | 69 --- arch/h8300/lib/Makefile | 9 - arch/h8300/lib/abs.S | 21 - arch/h8300/lib/ashldi3.c | 25 - arch/h8300/lib/ashrdi3.c | 25 - arch/h8300/lib/delay.c | 41 -- arch/h8300/lib/libgcc.h | 78 ---- arch/h8300/lib/lshrdi3.c | 24 - arch/h8300/lib/memcpy.S | 86 ---- arch/h8300/lib/memset.S | 70 --- arch/h8300/lib/moddivsi3.S | 73 --- arch/h8300/lib/modsi3.S | 73 --- arch/h8300/lib/muldi3.c | 45 -- arch/h8300/lib/mulsi3.S | 39 -- arch/h8300/lib/ucmpdi2.c | 18 - arch/h8300/lib/udivsi3.S | 77 ---- arch/h8300/mm/Makefile | 6 - arch/h8300/mm/fault.c | 57 --- arch/h8300/mm/init.c | 101 ---- arch/h8300/mm/memory.c | 53 --- drivers/clk/Makefile | 1 - drivers/clk/h8300/Makefile | 3 - drivers/clk/h8300/clk-div.c | 57 --- drivers/clk/h8300/clk-h8s2678.c | 145 ------ drivers/clocksource/Kconfig | 20 - drivers/clocksource/Makefile | 3 - drivers/clocksource/h8300_timer16.c | 192 -------- drivers/clocksource/h8300_timer8.c | 211 --------- drivers/clocksource/h8300_tpu.c | 158 ------- drivers/irqchip/Kconfig | 11 - drivers/irqchip/Makefile | 2 - drivers/irqchip/irq-renesas-h8300h.c | 94 ---- drivers/irqchip/irq-renesas-h8s.c | 102 ---- drivers/net/ethernet/smsc/Kconfig | 4 +- drivers/net/ethernet/smsc/smc91x.h | 11 - drivers/tty/serial/Kconfig | 5 +- init/Kconfig | 3 +- tools/arch/h8300/include/asm/bitsperlong.h | 15 - tools/arch/h8300/include/uapi/asm/mman.h | 7 - 160 files changed, 5 insertions(+), 6981 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/renesas,h8300-div-clock.txt delete mode 100644 Documentation/devicetree/bindings/h8300/cpu.txt delete mode 100644 Documentation/devicetree/bindings/interrupt-controller/renesas,h8300h-intc.txt delete mode 100644 Documentation/devicetree/bindings/interrupt-controller/renesas,h8s-intc.txt delete mode 100644 Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.yaml delete mode 100644 arch/h8300/Kbuild delete mode 100644 arch/h8300/Kconfig delete mode 100644 arch/h8300/Kconfig.cpu delete mode 100644 arch/h8300/Kconfig.debug delete mode 100644 arch/h8300/Makefile delete mode 100644 arch/h8300/boot/Makefile delete mode 100644 arch/h8300/boot/compressed/Makefile delete mode 100644 arch/h8300/boot/compressed/head.S delete mode 100644 arch/h8300/boot/compressed/misc.c delete mode 100644 arch/h8300/boot/compressed/vmlinux.lds delete mode 100644 arch/h8300/boot/compressed/vmlinux.scr delete mode 100644 arch/h8300/boot/dts/Makefile delete mode 100644 arch/h8300/boot/dts/edosk2674.dts delete mode 100644 arch/h8300/boot/dts/h8300h_sim.dts delete mode 100644 arch/h8300/boot/dts/h8s_sim.dts delete mode 100644 arch/h8300/configs/edosk2674_defconfig delete mode 100644 arch/h8300/configs/h8300h-sim_defconfig delete mode 100644 arch/h8300/configs/h8s-sim_defconfig delete mode 100644 arch/h8300/include/asm/Kbuild delete mode 100644 arch/h8300/include/asm/bitops.h delete mode 100644 arch/h8300/include/asm/bug.h delete mode 100644 arch/h8300/include/asm/byteorder.h delete mode 100644 arch/h8300/include/asm/cache.h delete mode 100644 arch/h8300/include/asm/elf.h delete mode 100644 arch/h8300/include/asm/flat.h delete mode 100644 arch/h8300/include/asm/hash.h delete mode 100644 arch/h8300/include/asm/io.h delete mode 100644 arch/h8300/include/asm/irq.h delete mode 100644 arch/h8300/include/asm/irqflags.h delete mode 100644 arch/h8300/include/asm/kgdb.h delete mode 100644 arch/h8300/include/asm/mmu_context.h delete mode 100644 arch/h8300/include/asm/page.h delete mode 100644 arch/h8300/include/asm/page_offset.h delete mode 100644 arch/h8300/include/asm/pgtable.h delete mode 100644 arch/h8300/include/asm/processor.h delete mode 100644 arch/h8300/include/asm/ptrace.h delete mode 100644 arch/h8300/include/asm/segment.h delete mode 100644 arch/h8300/include/asm/signal.h delete mode 100644 arch/h8300/include/asm/smp.h delete mode 100644 arch/h8300/include/asm/string.h delete mode 100644 arch/h8300/include/asm/switch_to.h delete mode 100644 arch/h8300/include/asm/syscall.h delete mode 100644 arch/h8300/include/asm/thread_info.h delete mode 100644 arch/h8300/include/asm/tlb.h delete mode 100644 arch/h8300/include/asm/traps.h delete mode 100644 arch/h8300/include/asm/user.h delete mode 100644 arch/h8300/include/asm/vmalloc.h delete mode 100644 arch/h8300/include/uapi/asm/Kbuild delete mode 100644 arch/h8300/include/uapi/asm/byteorder.h delete mode 100644 arch/h8300/include/uapi/asm/posix_types.h delete mode 100644 arch/h8300/include/uapi/asm/ptrace.h delete mode 100644 arch/h8300/include/uapi/asm/sigcontext.h delete mode 100644 arch/h8300/include/uapi/asm/signal.h delete mode 100644 arch/h8300/include/uapi/asm/unistd.h delete mode 100644 arch/h8300/kernel/.gitignore delete mode 100644 arch/h8300/kernel/Makefile delete mode 100644 arch/h8300/kernel/asm-offsets.c delete mode 100644 arch/h8300/kernel/entry.S delete mode 100644 arch/h8300/kernel/h8300_ksyms.c delete mode 100644 arch/h8300/kernel/head_ram.S delete mode 100644 arch/h8300/kernel/head_rom.S delete mode 100644 arch/h8300/kernel/irq.c delete mode 100644 arch/h8300/kernel/kgdb.c delete mode 100644 arch/h8300/kernel/module.c delete mode 100644 arch/h8300/kernel/process.c delete mode 100644 arch/h8300/kernel/ptrace.c delete mode 100644 arch/h8300/kernel/ptrace_h.c delete mode 100644 arch/h8300/kernel/ptrace_s.c delete mode 100644 arch/h8300/kernel/setup.c delete mode 100644 arch/h8300/kernel/signal.c delete mode 100644 arch/h8300/kernel/sim-console.c delete mode 100644 arch/h8300/kernel/syscalls.c delete mode 100644 arch/h8300/kernel/traps.c delete mode 100644 arch/h8300/kernel/vmlinux.lds.S delete mode 100644 arch/h8300/lib/Makefile delete mode 100644 arch/h8300/lib/abs.S delete mode 100644 arch/h8300/lib/ashldi3.c delete mode 100644 arch/h8300/lib/ashrdi3.c delete mode 100644 arch/h8300/lib/delay.c delete mode 100644 arch/h8300/lib/libgcc.h delete mode 100644 arch/h8300/lib/lshrdi3.c delete mode 100644 arch/h8300/lib/memcpy.S delete mode 100644 arch/h8300/lib/memset.S delete mode 100644 arch/h8300/lib/moddivsi3.S delete mode 100644 arch/h8300/lib/modsi3.S delete mode 100644 arch/h8300/lib/muldi3.c delete mode 100644 arch/h8300/lib/mulsi3.S delete mode 100644 arch/h8300/lib/ucmpdi2.c delete mode 100644 arch/h8300/lib/udivsi3.S delete mode 100644 arch/h8300/mm/Makefile delete mode 100644 arch/h8300/mm/fault.c delete mode 100644 arch/h8300/mm/init.c delete mode 100644 arch/h8300/mm/memory.c delete mode 100644 drivers/clk/h8300/Makefile delete mode 100644 drivers/clk/h8300/clk-div.c delete mode 100644 drivers/clk/h8300/clk-h8s2678.c delete mode 100644 drivers/clocksource/h8300_timer16.c delete mode 100644 drivers/clocksource/h8300_timer8.c delete mode 100644 drivers/clocksource/h8300_tpu.c delete mode 100644 drivers/irqchip/irq-renesas-h8300h.c delete mode 100644 drivers/irqchip/irq-renesas-h8s.c delete mode 100644 tools/arch/h8300/include/asm/bitsperlong.h delete mode 100644 tools/arch/h8300/include/uapi/asm/mman.h diff --git a/Documentation/devicetree/bindings/clock/renesas,h8300-div-clock.txt b/Documentation/devicetree/bindings/clock/renesas,h8300-div-clock.txt deleted file mode 100644 index 399e0da22348..000000000000 --- a/Documentation/devicetree/bindings/clock/renesas,h8300-div-clock.txt +++ /dev/null @@ -1,24 +0,0 @@ -* Renesas H8/300 divider clock - -Required Properties: - - - compatible: Must be "renesas,h8300-div-clock" - - - clocks: Reference to the parent clocks ("extal1" and "extal2") - - - #clock-cells: Must be 1 - - - reg: Base address and length of the divide rate selector - - - renesas,width: bit width of selector - -Example -------- - - cclk: cclk { - compatible = "renesas,h8300-div-clock"; - clocks = <&xclk>; - #clock-cells = <0>; - reg = <0xfee01b 2>; - renesas,width = <2>; - }; diff --git a/Documentation/devicetree/bindings/h8300/cpu.txt b/Documentation/devicetree/bindings/h8300/cpu.txt deleted file mode 100644 index 70cd58608f4b..000000000000 --- a/Documentation/devicetree/bindings/h8300/cpu.txt +++ /dev/null @@ -1,13 +0,0 @@ -* H8/300 CPU bindings - -Required properties: - -- compatible: Compatible property value should be "renesas,h8300". -- clock-frequency: Contains the clock frequency for CPU, in Hz. - -Example: - - cpu@0 { - compatible = "renesas,h8300"; - clock-frequency = <20000000>; - }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,h8300h-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,h8300h-intc.txt deleted file mode 100644 index 56e8d82aff34..000000000000 --- a/Documentation/devicetree/bindings/interrupt-controller/renesas,h8300h-intc.txt +++ /dev/null @@ -1,22 +0,0 @@ -* H8/300H Interrupt controller - -Required properties: - -- compatible: has to be "renesas,h8300h-intc", "renesas,h8300-intc" as fallback. -- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in - interrupts.txt in this directory -- regs: Base address of interrupt controller registers. - -Optional properties: - -- any properties, listed in interrupts.txt, and any standard resource allocation - properties - -Example: - - h8intc: interrupt-controller@fee012 { - compatible = "renesas,h8300h-intc", "renesas,h8300-intc"; - #interrupt-cells = <2>; - interrupt-controller; - reg = <0xfee012 7>; - }; diff --git a/Documentation/devicetree/bindings/interrupt-controller/renesas,h8s-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/renesas,h8s-intc.txt deleted file mode 100644 index faded2b1559b..000000000000 --- a/Documentation/devicetree/bindings/interrupt-controller/renesas,h8s-intc.txt +++ /dev/null @@ -1,22 +0,0 @@ -* H8S Interrupt controller - -Required properties: - -- compatible: has to be "renesas,h8s-intc", "renesas,h8300-intc" as fallback. -- #interrupt-cells: has to be <2>: an interrupt index and flags, as defined in - interrupts.txt in this directory -- regs: Base address of interrupt controller registers. - -Optional properties: - -- any properties, listed in interrupts.txt, and any standard resource allocation - properties - -Example: - - h8intc: interrupt-controller@fffe00 { - compatible = "renesas,h8s-intc", "renesas,h8300-intc"; - #interrupt-cells = <2>; - interrupt-controller; - reg = <0xfffe00 24>; - }; diff --git a/Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.yaml b/Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.yaml deleted file mode 100644 index 2b18cef99511..000000000000 --- a/Documentation/devicetree/bindings/memory-controllers/renesas,h8300-bsc.yaml +++ /dev/null @@ -1,35 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/memory-controllers/renesas,h8300-bsc.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: H8/300 bus controller - -maintainers: - - Krzysztof Kozlowski - - Yoshinori Sato - -properties: - compatible: - items: - - enum: - - renesas,h8300h-bsc - - renesas,h8s-bsc - - const: renesas,h8300-bsc - - reg: - maxItems: 1 - -required: - - compatible - - reg - -additionalProperties: false - -examples: - - | - memory-controller@fee01e { - compatible = "renesas,h8300h-bsc", "renesas,h8300-bsc"; - reg = <0xfee01e 8>; - }; diff --git a/Documentation/features/core/cBPF-JIT/arch-support.txt b/Documentation/features/core/cBPF-JIT/arch-support.txt index e59b5215402d..55b2aca6a2c3 100644 --- a/Documentation/features/core/cBPF-JIT/arch-support.txt +++ b/Documentation/features/core/cBPF-JIT/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | TODO | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/core/eBPF-JIT/arch-support.txt b/Documentation/features/core/eBPF-JIT/arch-support.txt index dcbd8679f514..92b723e897d7 100644 --- a/Documentation/features/core/eBPF-JIT/arch-support.txt +++ b/Documentation/features/core/eBPF-JIT/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/core/generic-idle-thread/arch-support.txt b/Documentation/features/core/generic-idle-thread/arch-support.txt index 4efcba7b5239..c1e69d518f1d 100644 --- a/Documentation/features/core/generic-idle-thread/arch-support.txt +++ b/Documentation/features/core/generic-idle-thread/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | ok | | ia64: | ok | | m68k: | TODO | diff --git a/Documentation/features/core/jump-labels/arch-support.txt b/Documentation/features/core/jump-labels/arch-support.txt index 0c801d1bd2da..968ffd3fa20b 100644 --- a/Documentation/features/core/jump-labels/arch-support.txt +++ b/Documentation/features/core/jump-labels/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/core/thread-info-in-task/arch-support.txt b/Documentation/features/core/thread-info-in-task/arch-support.txt index bc74d8beea72..cefb0ed6adca 100644 --- a/Documentation/features/core/thread-info-in-task/arch-support.txt +++ b/Documentation/features/core/thread-info-in-task/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/core/tracehook/arch-support.txt b/Documentation/features/core/tracehook/arch-support.txt index af34308fce7f..8e1ad2dc15d8 100644 --- a/Documentation/features/core/tracehook/arch-support.txt +++ b/Documentation/features/core/tracehook/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | ok | | ia64: | ok | | m68k: | TODO | diff --git a/Documentation/features/debug/KASAN/arch-support.txt b/Documentation/features/debug/KASAN/arch-support.txt index c244ac7eee26..72392302c543 100644 --- a/Documentation/features/debug/KASAN/arch-support.txt +++ b/Documentation/features/debug/KASAN/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt index fa83403b4aec..db10ff31805d 100644 --- a/Documentation/features/debug/debug-vm-pgtable/arch-support.txt +++ b/Documentation/features/debug/debug-vm-pgtable/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/gcov-profile-all/arch-support.txt b/Documentation/features/debug/gcov-profile-all/arch-support.txt index b39c1a5de3f3..8c972103d18c 100644 --- a/Documentation/features/debug/gcov-profile-all/arch-support.txt +++ b/Documentation/features/debug/gcov-profile-all/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/kcov/arch-support.txt b/Documentation/features/debug/kcov/arch-support.txt index 7e44013cc320..e0412ef3ed7d 100644 --- a/Documentation/features/debug/kcov/arch-support.txt +++ b/Documentation/features/debug/kcov/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/kgdb/arch-support.txt b/Documentation/features/debug/kgdb/arch-support.txt index 2cb0576f9180..2dfd383cbe55 100644 --- a/Documentation/features/debug/kgdb/arch-support.txt +++ b/Documentation/features/debug/kgdb/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | ok | | hexagon: | ok | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/kmemleak/arch-support.txt b/Documentation/features/debug/kmemleak/arch-support.txt index e9ac415f8aec..7408dc258f57 100644 --- a/Documentation/features/debug/kmemleak/arch-support.txt +++ b/Documentation/features/debug/kmemleak/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt index 96156e8802a7..fe707c04794a 100644 --- a/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt +++ b/Documentation/features/debug/kprobes-on-ftrace/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | TODO | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/kprobes/arch-support.txt b/Documentation/features/debug/kprobes/arch-support.txt index ee95ed61909a..7f4ef559ff60 100644 --- a/Documentation/features/debug/kprobes/arch-support.txt +++ b/Documentation/features/debug/kprobes/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | ok | | m68k: | TODO | diff --git a/Documentation/features/debug/kretprobes/arch-support.txt b/Documentation/features/debug/kretprobes/arch-support.txt index 612cb97d47b8..0eace8acbde1 100644 --- a/Documentation/features/debug/kretprobes/arch-support.txt +++ b/Documentation/features/debug/kretprobes/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | ok | | m68k: | TODO | diff --git a/Documentation/features/debug/optprobes/arch-support.txt b/Documentation/features/debug/optprobes/arch-support.txt index d6ff141a6122..b0cbb80e2138 100644 --- a/Documentation/features/debug/optprobes/arch-support.txt +++ b/Documentation/features/debug/optprobes/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | TODO | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/stackprotector/arch-support.txt b/Documentation/features/debug/stackprotector/arch-support.txt index ad4de22a71ab..7776884e9d0d 100644 --- a/Documentation/features/debug/stackprotector/arch-support.txt +++ b/Documentation/features/debug/stackprotector/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/uprobes/arch-support.txt b/Documentation/features/debug/uprobes/arch-support.txt index 8bd5548a4485..080257b34ecc 100644 --- a/Documentation/features/debug/uprobes/arch-support.txt +++ b/Documentation/features/debug/uprobes/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/debug/user-ret-profiler/arch-support.txt b/Documentation/features/debug/user-ret-profiler/arch-support.txt index 2a3fe812a5fa..8da784e2d8d1 100644 --- a/Documentation/features/debug/user-ret-profiler/arch-support.txt +++ b/Documentation/features/debug/user-ret-profiler/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | TODO | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/io/dma-contiguous/arch-support.txt b/Documentation/features/io/dma-contiguous/arch-support.txt index bece89586efa..6bd6ff52a0bd 100644 --- a/Documentation/features/io/dma-contiguous/arch-support.txt +++ b/Documentation/features/io/dma-contiguous/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/locking/cmpxchg-local/arch-support.txt b/Documentation/features/locking/cmpxchg-local/arch-support.txt index 52bdda004f5c..307d362622c4 100644 --- a/Documentation/features/locking/cmpxchg-local/arch-support.txt +++ b/Documentation/features/locking/cmpxchg-local/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/locking/lockdep/arch-support.txt b/Documentation/features/locking/lockdep/arch-support.txt index a8cd163c8b7e..ada677830246 100644 --- a/Documentation/features/locking/lockdep/arch-support.txt +++ b/Documentation/features/locking/lockdep/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | ok | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/locking/queued-rwlocks/arch-support.txt b/Documentation/features/locking/queued-rwlocks/arch-support.txt index 8c85949752b3..c000efd4b069 100644 --- a/Documentation/features/locking/queued-rwlocks/arch-support.txt +++ b/Documentation/features/locking/queued-rwlocks/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/locking/queued-spinlocks/arch-support.txt b/Documentation/features/locking/queued-spinlocks/arch-support.txt index 5f4e1b3841af..c4decfc115f5 100644 --- a/Documentation/features/locking/queued-spinlocks/arch-support.txt +++ b/Documentation/features/locking/queued-spinlocks/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/perf/kprobes-event/arch-support.txt b/Documentation/features/perf/kprobes-event/arch-support.txt index 78f3fe080f0e..b2e45810af06 100644 --- a/Documentation/features/perf/kprobes-event/arch-support.txt +++ b/Documentation/features/perf/kprobes-event/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | ok | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/perf/perf-regs/arch-support.txt b/Documentation/features/perf/perf-regs/arch-support.txt index 5bf3b1854a1f..86fa79b8e719 100644 --- a/Documentation/features/perf/perf-regs/arch-support.txt +++ b/Documentation/features/perf/perf-regs/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/perf/perf-stackdump/arch-support.txt b/Documentation/features/perf/perf-stackdump/arch-support.txt index d88659bb4fc1..9b76c8206b7f 100644 --- a/Documentation/features/perf/perf-stackdump/arch-support.txt +++ b/Documentation/features/perf/perf-stackdump/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/sched/membarrier-sync-core/arch-support.txt b/Documentation/features/sched/membarrier-sync-core/arch-support.txt index 883d33b265d6..4ba3b6308aed 100644 --- a/Documentation/features/sched/membarrier-sync-core/arch-support.txt +++ b/Documentation/features/sched/membarrier-sync-core/arch-support.txt @@ -34,7 +34,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/sched/numa-balancing/arch-support.txt b/Documentation/features/sched/numa-balancing/arch-support.txt index 9affb7c2c500..54814bbb87b2 100644 --- a/Documentation/features/sched/numa-balancing/arch-support.txt +++ b/Documentation/features/sched/numa-balancing/arch-support.txt @@ -11,7 +11,6 @@ | arm: | .. | | arm64: | ok | | csky: | .. | - | h8300: | .. | | hexagon: | .. | | ia64: | TODO | | m68k: | .. | diff --git a/Documentation/features/seccomp/seccomp-filter/arch-support.txt b/Documentation/features/seccomp/seccomp-filter/arch-support.txt index 26eec58ab819..e243eaa7696f 100644 --- a/Documentation/features/seccomp/seccomp-filter/arch-support.txt +++ b/Documentation/features/seccomp/seccomp-filter/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/time/arch-tick-broadcast/arch-support.txt b/Documentation/features/time/arch-tick-broadcast/arch-support.txt index 8dcaab070c7b..38f06a18bac3 100644 --- a/Documentation/features/time/arch-tick-broadcast/arch-support.txt +++ b/Documentation/features/time/arch-tick-broadcast/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/time/clockevents/arch-support.txt b/Documentation/features/time/clockevents/arch-support.txt index 9a81cb03b1fd..bf640aaed17b 100644 --- a/Documentation/features/time/clockevents/arch-support.txt +++ b/Documentation/features/time/clockevents/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | ok | | csky: | ok | - | h8300: | ok | | hexagon: | ok | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/time/context-tracking/arch-support.txt b/Documentation/features/time/context-tracking/arch-support.txt index 4ed116c2ec39..45bf771065b4 100644 --- a/Documentation/features/time/context-tracking/arch-support.txt +++ b/Documentation/features/time/context-tracking/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/time/irq-time-acct/arch-support.txt b/Documentation/features/time/irq-time-acct/arch-support.txt index bc30c15557c7..25eac3f7597c 100644 --- a/Documentation/features/time/irq-time-acct/arch-support.txt +++ b/Documentation/features/time/irq-time-acct/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | .. | | m68k: | TODO | diff --git a/Documentation/features/time/virt-cpuacct/arch-support.txt b/Documentation/features/time/virt-cpuacct/arch-support.txt index 050de43bbbb9..b71a91066e35 100644 --- a/Documentation/features/time/virt-cpuacct/arch-support.txt +++ b/Documentation/features/time/virt-cpuacct/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | ok | - | h8300: | TODO | | hexagon: | TODO | | ia64: | ok | | m68k: | TODO | diff --git a/Documentation/features/vm/ELF-ASLR/arch-support.txt b/Documentation/features/vm/ELF-ASLR/arch-support.txt index 2949c99fbb2f..64f387045b38 100644 --- a/Documentation/features/vm/ELF-ASLR/arch-support.txt +++ b/Documentation/features/vm/ELF-ASLR/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/vm/PG_uncached/arch-support.txt b/Documentation/features/vm/PG_uncached/arch-support.txt index 6cde38458596..334353455540 100644 --- a/Documentation/features/vm/PG_uncached/arch-support.txt +++ b/Documentation/features/vm/PG_uncached/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | TODO | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | ok | | m68k: | TODO | diff --git a/Documentation/features/vm/THP/arch-support.txt b/Documentation/features/vm/THP/arch-support.txt index 7dbd6967b37e..36b5dfb4f8d6 100644 --- a/Documentation/features/vm/THP/arch-support.txt +++ b/Documentation/features/vm/THP/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | .. | - | h8300: | .. | | hexagon: | .. | | ia64: | TODO | | m68k: | .. | diff --git a/Documentation/features/vm/TLB/arch-support.txt b/Documentation/features/vm/TLB/arch-support.txt index e1c3a4c4d107..7d0de7f173d5 100644 --- a/Documentation/features/vm/TLB/arch-support.txt +++ b/Documentation/features/vm/TLB/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | N/A | | csky: | TODO | - | h8300: | .. | | hexagon: | TODO | | ia64: | TODO | | m68k: | .. | diff --git a/Documentation/features/vm/huge-vmap/arch-support.txt b/Documentation/features/vm/huge-vmap/arch-support.txt index bc53905a0306..64e8e14e67e0 100644 --- a/Documentation/features/vm/huge-vmap/arch-support.txt +++ b/Documentation/features/vm/huge-vmap/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/vm/ioremap_prot/arch-support.txt b/Documentation/features/vm/ioremap_prot/arch-support.txt index 9a0c8783b84d..6bc7f77ef20d 100644 --- a/Documentation/features/vm/ioremap_prot/arch-support.txt +++ b/Documentation/features/vm/ioremap_prot/arch-support.txt @@ -11,7 +11,6 @@ | arm: | TODO | | arm64: | TODO | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/Documentation/features/vm/pte_special/arch-support.txt b/Documentation/features/vm/pte_special/arch-support.txt index 40b969f3a6bb..45463dac131f 100644 --- a/Documentation/features/vm/pte_special/arch-support.txt +++ b/Documentation/features/vm/pte_special/arch-support.txt @@ -11,7 +11,6 @@ | arm: | ok | | arm64: | ok | | csky: | TODO | - | h8300: | TODO | | hexagon: | TODO | | ia64: | TODO | | m68k: | TODO | diff --git a/MAINTAINERS b/MAINTAINERS index 777cd6fa2b3d..412382dfac68 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8395,17 +8395,6 @@ L: linux-efi@vger.kernel.org S: Maintained F: block/partitions/efi.* -H8/300 ARCHITECTURE -M: Yoshinori Sato -L: uclinux-h8-devel@lists.sourceforge.jp (moderated for non-subscribers) -S: Maintained -W: http://uclinux-h8.sourceforge.jp -T: git git://git.sourceforge.jp/gitroot/uclinux-h8/linux.git -F: arch/h8300/ -F: drivers/clk/h8300/ -F: drivers/clocksource/h8300_*.c -F: drivers/irqchip/irq-renesas-h8*.c - HABANALABS PCI DRIVER M: Oded Gabbay S: Supported diff --git a/arch/h8300/Kbuild b/arch/h8300/Kbuild deleted file mode 100644 index e4703f3534cc..000000000000 --- a/arch/h8300/Kbuild +++ /dev/null @@ -1,5 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-y += kernel/ mm/ boot/dts/ - -# for cleaning -subdir- += boot diff --git a/arch/h8300/Kconfig b/arch/h8300/Kconfig deleted file mode 100644 index 3e3e0f16f7e0..000000000000 --- a/arch/h8300/Kconfig +++ /dev/null @@ -1,50 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config H8300 - def_bool y - select ARCH_32BIT_OFF_T - select ARCH_HAS_BINFMT_FLAT - select BINFMT_FLAT_ARGVP_ENVP_ON_STACK - select BINFMT_FLAT_OLD_ALWAYS_RAM - select GENERIC_ATOMIC64 - select HAVE_UID16 - select VIRT_TO_BUS - select GENERIC_IRQ_SHOW - select FRAME_POINTER - select GENERIC_CPU_DEVICES - select MODULES_USE_ELF_RELA - select COMMON_CLK - select ARCH_WANT_FRAME_POINTERS - select OF - select OF_IRQ - select OF_EARLY_FLATTREE - select TIMER_OF - select H8300_TMR8 - select HAVE_KERNEL_GZIP - select HAVE_KERNEL_LZO - select HAVE_ARCH_KGDB - select HAVE_ARCH_HASH - select CPU_NO_EFFICIENT_FFS - select SET_FS - select UACCESS_MEMCPY - -config CPU_BIG_ENDIAN - def_bool y - -config GENERIC_HWEIGHT - def_bool y - -config NO_IOPORT_MAP - def_bool y - -config GENERIC_CSUM - def_bool y - -config HZ - int - default 100 - -config NR_CPUS - int - default 1 - -source "arch/h8300/Kconfig.cpu" diff --git a/arch/h8300/Kconfig.cpu b/arch/h8300/Kconfig.cpu deleted file mode 100644 index c30baa0499fc..000000000000 --- a/arch/h8300/Kconfig.cpu +++ /dev/null @@ -1,99 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -config CPU_H8300H - bool - -config CPU_H8S - bool - -config H83069 - bool - select CPU_H8300H - select H8300_TMR16 - select RENESAS_H8300H_INTC - -config H8S2678 - bool - select CPU_H8S - select H8300_TPU - select RENESAS_H8S_INTC - -config RAMKERNEL - bool - -config ROMKERNEL - bool - -menu "Processor type and features" - -choice -prompt "H8/300 platform" - -config H8300_AE3068 - bool "AE-3068/69" - select H83069 - select RAMKERNEL - help - AKI-H8/3068F / AKI-H8/3069F Flashmicom LAN Board Support - More Information. (Japanese Only) - - AE-3068/69 Evaluation Board Support - More Information. - - -config H8300_H8MAX - bool "H8MAX" - select H83069 - select RAMKERNEL - help - H8MAX Evaluation Board Support - More Information. (Japanese Only) - - -config H8300_KANEBEBE - bool "KaneBebe" - select H83069 - select RAMKERNEL - help - KaneBebe Evalition Board Support - More Information. (Japanese Only) - - -config H8300H_SIM - bool "H8/300H GDB Simulator" - select H83069 - select ROMKERNEL - help - GDB Simulator Support - More Information. - - -config H8S_EDOSK2674 - bool "EDOSK-2674" - select H8S2678 - select RAMKERNEL - help - Renesas EDOSK-2674 Evaluation Board Support - More Information. - - - -config H8S_SIM - bool "H8S GDB Simulator" - select H8S2678 - select ROMKERNEL - help - GDB Simulator Support - More Information. - - -endchoice - -config H8300_BUILTIN_DTB - string "Builtin DTB" - default "" - -config OFFSET - hex "Load offset" - default 0 - -endmenu diff --git a/arch/h8300/Kconfig.debug b/arch/h8300/Kconfig.debug deleted file mode 100644 index 295942fe3fd5..000000000000 --- a/arch/h8300/Kconfig.debug +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# dummy file, do not delete diff --git a/arch/h8300/Makefile b/arch/h8300/Makefile deleted file mode 100644 index 807f41e60ee4..000000000000 --- a/arch/h8300/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -# -# arch/h8300/Makefile -# -# This file is subject to the terms and conditions of the GNU General Public -# License. See the file "COPYING" in the main directory of this archive -# for more details. -# -# (C) Copyright 2002-2015 Yoshinori Sato -# - -KBUILD_DEFCONFIG := edosk2674_defconfig - -cflags-$(CONFIG_CPU_H8300H) := -mh -aflags-$(CONFIG_CPU_H8300H) := -mh -Wa,--mach=h8300h -ldflags-$(CONFIG_CPU_H8300H) := -mh8300helf_linux -cflags-$(CONFIG_CPU_H8S) := -ms -aflags-$(CONFIG_CPU_H8S) := -ms -Wa,--mach=h8300s -ldflags-$(CONFIG_CPU_H8S) := -mh8300self_linux - -KBUILD_CFLAGS += $(cflags-y) -KBUILD_CFLAGS += -mint32 -fno-builtin -KBUILD_CFLAGS += -D__linux__ -KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\" -KBUILD_AFLAGS += $(aflags-y) -KBUILD_LDFLAGS += $(ldflags-y) - -CHECKFLAGS += -msize-long - -ifeq ($(CROSS_COMPILE),) -CROSS_COMPILE := $(call cc-cross-prefix, h8300-unknown-linux- h8300-linux-) -endif - -libs-y += arch/$(ARCH)/lib/ - -boot := arch/h8300/boot - -vmlinux.srec vmlinux.bin zImage uImage.bin: vmlinux - $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@ - -define archhelp - @echo 'vmlinux.bin - Create raw binary' - @echo 'vmlinux.srec - Create srec binary' - @echo 'zImage - Compressed kernel image' -endef diff --git a/arch/h8300/boot/Makefile b/arch/h8300/boot/Makefile deleted file mode 100644 index 8e62df20ebf9..000000000000 --- a/arch/h8300/boot/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# arch/h8300/boot/Makefile - -targets := vmlinux.srec vmlinux.bin zImage -subdir- := compressed - -OBJCOPYFLAGS_vmlinux.srec := -Osrec -OBJCOPYFLAGS_vmlinux.bin := -Obinary -OBJCOPYFLAGS_zImage := -O binary -R .note -R .comment -R .stab -R .stabstr -S - -UIMAGE_LOADADDR = $(CONFIG_RAMBASE) -UIMAGE_ENTRYADDR = $(shell /bin/bash -c 'printf "0x%08x" \ - $$[$(CONFIG_RAMBASE) + $(CONFIG_OFFSET)]') - -$(obj)/vmlinux.srec $(obj)/vmlinux.bin: vmlinux FORCE - $(call if_changed,objcopy) - -$(obj)/zImage: $(obj)/compressed/vmlinux FORCE - $(call if_changed,objcopy) - -$(obj)/compressed/vmlinux: FORCE - $(Q)$(MAKE) $(build)=$(obj)/compressed $@ - -$(obj)/uImage.bin: $(obj)/vmlinux.bin - $(call if_changed,uimage,none) - -CLEAN_FILES += arch/$(ARCH)/vmlinux.bin arch/$(ARCH)/vmlinux.srec arch/$(ARCH)/uImage.bin diff --git a/arch/h8300/boot/compressed/Makefile b/arch/h8300/boot/compressed/Makefile deleted file mode 100644 index 6ab2fa5ba105..000000000000 --- a/arch/h8300/boot/compressed/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# linux/arch/sh/boot/compressed/Makefile -# -# create a compressed vmlinux image from the original vmlinux -# - -targets := vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o - -OBJECTS = $(obj)/head.o $(obj)/misc.o - -# -# IMAGE_OFFSET is the load offset of the compression loader -# Assign dummy values if these 2 variables are not defined, -# in order to suppress error message. -# -CONFIG_MEMORY_START ?= 0x00400000 -CONFIG_BOOT_LINK_OFFSET ?= 0x00280000 -IMAGE_OFFSET := $(shell printf "0x%08x" $$(($(CONFIG_MEMORY_START)+$(CONFIG_BOOT_LINK_OFFSET)))) - -LIBGCC := $(shell $(CROSS-COMPILE)$(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name 2>/dev/null) -LDFLAGS_vmlinux := -Ttext $(IMAGE_OFFSET) -estartup -T $(obj)/vmlinux.lds \ - --defsym output=$(CONFIG_MEMORY_START) - -$(obj)/vmlinux: $(OBJECTS) $(obj)/piggy.o $(LIBGCC) FORCE - $(call if_changed,ld) - -$(obj)/vmlinux.bin: vmlinux FORCE - $(call if_changed,objcopy) - -suffix-$(CONFIG_KERNEL_GZIP) := gzip -suffix-$(CONFIG_KERNEL_LZO) := lzo -compress-$(CONFIG_KERNEL_GZIP) := gzip -compress-$(CONFIG_KERNEL_LZO) := lzo_with_size - -$(obj)/vmlinux.bin.$(suffix-y): $(obj)/vmlinux.bin FORCE - $(call if_changed,$(compress-y)) - -LDFLAGS_piggy.o := -r --format binary --oformat elf32-h8300-linux -T -OBJCOPYFLAGS := -O binary - -$(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y) FORCE - $(call if_changed,ld) - -CFLAGS_misc.o = -O0 diff --git a/arch/h8300/boot/compressed/head.S b/arch/h8300/boot/compressed/head.S deleted file mode 100644 index 11ef509579cf..000000000000 --- a/arch/h8300/boot/compressed/head.S +++ /dev/null @@ -1,49 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * linux/arch/h8300/boot/compressed/head.S - * - * Copyright (C) 2006 Yoshinori Sato - */ - -#include - - .section .text..startup,"ax" - .global startup -startup: - mov.l #startup, sp - mov.l er0, er4 - mov.l #__sbss, er0 - mov.l #__ebss, er1 - sub.l er0, er1 - shlr er1 - shlr er1 - sub.l er2, er2 -1: - mov.l er2, @er0 - adds #4, er0 - dec.l #1, er1 - bne 1b - jsr @decompress_kernel - mov.l er4, er0 - jmp @output - - .align 9 -fake_headers_as_bzImage: - .word 0 - .ascii "HdrS" ; header signature - .word 0x0202 ; header version number (>= 0x0105) - ; or else old loadlin-1.5 will fail) - .word 0 ; default_switch - .word 0 ; SETUPSEG - .word 0x1000 - .word 0 ; pointing to kernel version string - .byte 0 ; = 0, old one (LILO, Loadlin, - ; 0xTV: T=0 for LILO - ; V = version - .byte 1 ; Load flags bzImage=1 - .word 0x8000 ; size to move, when setup is not - .long 0x100000 ; 0x100000 = default for big kernel - .long 0 ; address of loaded ramdisk image - .long 0 ; its size in bytes - - .end diff --git a/arch/h8300/boot/compressed/misc.c b/arch/h8300/boot/compressed/misc.c deleted file mode 100644 index 8915d8fe2e53..000000000000 --- a/arch/h8300/boot/compressed/misc.c +++ /dev/null @@ -1,76 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * arch/h8300/boot/compressed/misc.c - * - * This is a collection of several routines from gzip-1.0.3 - * adapted for Linux. - * - * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 - * - * Adapted for h8300 by Yoshinori Sato 2006 - */ - -#include - -/* - * gzip declarations - */ - -#define OF(args) args -#define STATIC static - -#undef memset -#undef memcpy -#define memzero(s, n) memset((s), (0), (n)) - -extern int _end; -static unsigned long free_mem_ptr; -static unsigned long free_mem_end_ptr; - -extern char input_data[]; -extern int input_len; -extern char output[]; - -#define HEAP_SIZE 0x10000 - -#ifdef CONFIG_KERNEL_GZIP -#include "../../../../lib/decompress_inflate.c" -#endif - -#ifdef CONFIG_KERNEL_LZO -#include "../../../../lib/decompress_unlzo.c" -#endif - -void *memset(void *s, int c, size_t n) -{ - int i; - char *ss = (char *)s; - - for (i = 0; i < n; i++) - ss[i] = c; - return s; -} - -void *memcpy(void *dest, const void *src, size_t n) -{ - int i; - char *d = (char *)dest, *s = (char *)src; - - for (i = 0; i < n; i++) - d[i] = s[i]; - return dest; -} - -static void error(char *x) -{ - while (1) - ; /* Halt */ -} - -void decompress_kernel(void) -{ - free_mem_ptr = (unsigned long)&_end; - free_mem_end_ptr = free_mem_ptr + HEAP_SIZE; - - __decompress(input_data, input_len, NULL, NULL, output, 0, NULL, error); -} diff --git a/arch/h8300/boot/compressed/vmlinux.lds b/arch/h8300/boot/compressed/vmlinux.lds deleted file mode 100644 index 7f7bb419ce15..000000000000 --- a/arch/h8300/boot/compressed/vmlinux.lds +++ /dev/null @@ -1,35 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -SECTIONS -{ - .text : - { - __stext = . ; - __text = .; - *(.text..startup) - *(.text) - __etext = . ; - } - - .rodata : - { - *(.rodata) - } - . = ALIGN(0x4) ; - .data : - - { - . = ALIGN(0x4) ; - __sdata = . ; - ___data_start = . ; - *(.data.*) - } - . = ALIGN(0x4) ; - .bss : - { - __sbss = . ; - *(.bss*) - . = ALIGN(0x4) ; - __ebss = . ; - } - _end = . ; -} diff --git a/arch/h8300/boot/compressed/vmlinux.scr b/arch/h8300/boot/compressed/vmlinux.scr deleted file mode 100644 index a084903603fe..000000000000 --- a/arch/h8300/boot/compressed/vmlinux.scr +++ /dev/null @@ -1,9 +0,0 @@ -SECTIONS -{ - .data : { - input_len = .; - LONG(input_data_end - input_data) input_data = .; - *(.data) - input_data_end = .; - } -} diff --git a/arch/h8300/boot/dts/Makefile b/arch/h8300/boot/dts/Makefile deleted file mode 100644 index c36bbd1f2592..000000000000 --- a/arch/h8300/boot/dts/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -obj-y += $(addsuffix .dtb.o, $(CONFIG_H8300_BUILTIN_DTB)) - -dtb-$(CONFIG_H8300H_SIM) := h8300h_sim.dtb -dtb-$(CONFIG_H8S_SIM) := h8s_sim.dtb -dtb-$(CONFIG_H8S_EDOSK2674) := edosk2674.dtb diff --git a/arch/h8300/boot/dts/edosk2674.dts b/arch/h8300/boot/dts/edosk2674.dts deleted file mode 100644 index d1733805ea67..000000000000 --- a/arch/h8300/boot/dts/edosk2674.dts +++ /dev/null @@ -1,108 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/dts-v1/; -/ { - compatible = "renesas,edosk2674"; - #address-cells = <1>; - #size-cells = <1>; - interrupt-parent = <&h8intc>; - - chosen { - bootargs = "console=ttySC2,38400"; - stdout-path = &sci2; - }; - aliases { - serial0 = &sci0; - serial1 = &sci1; - serial2 = &sci2; - }; - - xclk: oscillator { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <33333333>; - clock-output-names = "xtal"; - }; - pllclk: pllclk { - compatible = "renesas,h8s2678-pll-clock"; - clocks = <&xclk>; - #clock-cells = <0>; - reg = <0xffff3b 1>, <0xffff45 1>; - }; - core_clk: core_clk { - compatible = "renesas,h8300-div-clock"; - clocks = <&pllclk>; - #clock-cells = <0>; - reg = <0xffff3b 1>; - renesas,width = <3>; - }; - fclk: fclk { - compatible = "fixed-factor-clock"; - clocks = <&core_clk>; - #clock-cells = <0>; - clock-div = <1>; - clock-mult = <1>; - }; - - memory@400000 { - device_type = "memory"; - reg = <0x400000 0x800000>; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - cpu@0 { - compatible = "renesas,h8300"; - clock-frequency = <33333333>; - }; - }; - - h8intc: interrupt-controller@fffe00 { - compatible = "renesas,h8s-intc", "renesas,h8300-intc"; - #interrupt-cells = <2>; - interrupt-controller; - reg = <0xfffe00 24>; - }; - - bsc: memory-controller@fffec0 { - compatible = "renesas,h8s-bsc", "renesas,h8300-bsc"; - reg = <0xfffec0 24>; - }; - - tpu: timer@ffffe0 { - compatible = "renesas,tpu"; - reg = <0xffffe0 16>, <0xfffff0 12>; - clocks = <&fclk>; - clock-names = "fck"; - }; - - timer8: timer@ffffb0 { - compatible = "renesas,8bit-timer"; - reg = <0xffffb0 10>; - interrupts = <72 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; - - sci0: serial@ffff78 { - compatible = "renesas,sci"; - reg = <0xffff78 8>; - interrupts = <88 0>, <89 0>, <90 0>, <91 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; - sci1: serial@ffff80 { - compatible = "renesas,sci"; - reg = <0xffff80 8>; - interrupts = <92 0>, <93 0>, <94 0>, <95 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; - sci2: serial@ffff88 { - compatible = "renesas,sci"; - reg = <0xffff88 8>; - interrupts = <96 0>, <97 0>, <98 0>, <99 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; -}; diff --git a/arch/h8300/boot/dts/h8300h_sim.dts b/arch/h8300/boot/dts/h8300h_sim.dts deleted file mode 100644 index 595398b9d018..000000000000 --- a/arch/h8300/boot/dts/h8300h_sim.dts +++ /dev/null @@ -1,97 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/dts-v1/; -/ { - compatible = "gnu,gdbsim"; - #address-cells = <1>; - #size-cells = <1>; - interrupt-parent = <&h8intc>; - - chosen { - bootargs = "earlyprintk=h8300-sim"; - stdout-path = <&sci0>; - }; - aliases { - serial0 = &sci0; - serial1 = &sci1; - }; - - xclk: oscillator { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <20000000>; - clock-output-names = "xtal"; - }; - core_clk: core_clk { - compatible = "renesas,h8300-div-clock"; - clocks = <&xclk>; - #clock-cells = <0>; - reg = <0xfee01b 2>; - renesas,width = <2>; - }; - fclk: fclk { - compatible = "fixed-factor-clock"; - clocks = <&core_clk>; - #clock-cells = <0>; - clock-div = <1>; - clock-mult = <1>; - }; - - memory@400000 { - device_type = "memory"; - reg = <0x400000 0x400000>; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - cpu@0 { - compatible = "renesas,h8300"; - clock-frequency = <20000000>; - }; - }; - - h8intc: interrupt-controller@fee012 { - compatible = "renesas,h8300h-intc", "renesas,h8300-intc"; - #interrupt-cells = <2>; - interrupt-controller; - reg = <0xfee012 7>; - }; - - bsc: memory-controller@fee01e { - compatible = "renesas,h8300h-bsc", "renesas,h8300-bsc"; - reg = <0xfee01e 8>; - }; - - timer8: timer@ffff80 { - compatible = "renesas,8bit-timer"; - reg = <0xffff80 10>; - interrupts = <36 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; - - timer16: timer@ffff68 { - compatible = "renesas,16bit-timer"; - reg = <0xffff68 8>, <0xffff60 8>; - interrupts = <26 0>; - renesas,channel = <0>; - clocks = <&fclk>; - clock-names = "fck"; - }; - - sci0: serial@ffffb0 { - compatible = "renesas,sci"; - reg = <0xffffb0 8>; - interrupts = <52 0>, <53 0>, <54 0>, <55 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; - - sci1: serial@ffffb8 { - compatible = "renesas,sci"; - reg = <0xffffb8 8>; - interrupts = <56 0>, <57 0>, <58 0>, <59 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; -}; diff --git a/arch/h8300/boot/dts/h8s_sim.dts b/arch/h8300/boot/dts/h8s_sim.dts deleted file mode 100644 index 932cc3c5a81b..000000000000 --- a/arch/h8300/boot/dts/h8s_sim.dts +++ /dev/null @@ -1,100 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/dts-v1/; -/ { - compatible = "gnu,gdbsim"; - #address-cells = <1>; - #size-cells = <1>; - interrupt-parent = <&h8intc>; - - chosen { - bootargs = "earlyprintk=h8300-sim"; - stdout-path = <&sci0>; - }; - aliases { - serial0 = &sci0; - serial1 = &sci1; - }; - - xclk: oscillator { - #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <33333333>; - clock-output-names = "xtal"; - }; - pllclk: pllclk { - compatible = "renesas,h8s2678-pll-clock"; - clocks = <&xclk>; - #clock-cells = <0>; - reg = <0xfee03b 2>, <0xfee045 2>; - }; - core_clk: core_clk { - compatible = "renesas,h8300-div-clock"; - clocks = <&pllclk>; - #clock-cells = <0>; - reg = <0xfee03b 2>; - renesas,width = <3>; - }; - fclk: fclk { - compatible = "fixed-factor-clock"; - clocks = <&core_clk>; - #clock-cells = <0>; - clock-div = <1>; - clock-mult = <1>; - }; - - memory@400000 { - device_type = "memory"; - reg = <0x400000 0x800000>; - }; - - cpus { - #address-cells = <1>; - #size-cells = <0>; - cpu@0 { - compatible = "renesas,h8300"; - clock-frequency = <33333333>; - }; - }; - - h8intc: interrupt-controller@fffe00 { - compatible = "renesas,h8s-intc", "renesas,h8300-intc"; - #interrupt-cells = <2>; - interrupt-controller; - reg = <0xfffe00 24>; - }; - - bsc: memory-controller@fffec0 { - compatible = "renesas,h8s-bsc", "renesas,h8300-bsc"; - reg = <0xfffec0 24>; - }; - - tpu: timer@ffffe0 { - compatible = "renesas,tpu"; - reg = <0xffffe0 16>, <0xfffff0 12>; - clocks = <&fclk>; - clock-names = "fck"; - }; - - timer8: timer@ffffb0 { - compatible = "renesas,8bit-timer"; - reg = <0xffffb0 10>; - interrupts = <72 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; - - sci0: serial@ffff78 { - compatible = "renesas,sci"; - reg = <0xffff78 8>; - interrupts = <88 0>, <89 0>, <90 0>, <91 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; - sci1: serial@ffff80 { - compatible = "renesas,sci"; - reg = <0xffff80 8>; - interrupts = <92 0>, <93 0>, <94 0>, <95 0>; - clocks = <&fclk>; - clock-names = "fck"; - }; -}; diff --git a/arch/h8300/configs/edosk2674_defconfig b/arch/h8300/configs/edosk2674_defconfig deleted file mode 100644 index 23791dcf6c25..000000000000 --- a/arch/h8300/configs/edosk2674_defconfig +++ /dev/null @@ -1,48 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -# CONFIG_USELIB is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_UID16 is not set -# CONFIG_SYSFS_SYSCALL is not set -# CONFIG_KALLSYMS is not set -# CONFIG_BASE_FULL is not set -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set -# CONFIG_SIGNALFD is not set -# CONFIG_TIMERFD is not set -# CONFIG_EVENTFD is not set -# CONFIG_AIO is not set -# CONFIG_ADVISE_SYSCALLS is not set -CONFIG_EMBEDDED=y -# CONFIG_VM_EVENT_COUNTERS is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_SLOB=y -# CONFIG_BLOCK is not set -CONFIG_H8S_SIM=y -CONFIG_H8300_BUILTIN_DTB="h8s_sim" -# CONFIG_BINFMT_SCRIPT is not set -CONFIG_BINFMT_FLAT=y -# CONFIG_COREDUMP is not set -# CONFIG_UEVENT_HELPER is not set -# CONFIG_STANDALONE is not set -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -# CONFIG_ALLOW_DEV_COREDUMP is not set -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_UNIX98_PTYS is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_CONSOLE=y -# CONFIG_HW_RANDOM is not set -# CONFIG_HWMON is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_FILE_LOCKING is not set -# CONFIG_DNOTIFY is not set -# CONFIG_INOTIFY_USER is not set -# CONFIG_PROC_FS is not set -# CONFIG_SYSFS is not set -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_DEBUG_INFO=y -# CONFIG_ENABLE_MUST_CHECK is not set diff --git a/arch/h8300/configs/h8300h-sim_defconfig b/arch/h8300/configs/h8300h-sim_defconfig deleted file mode 100644 index 7fc9c2f0acc0..000000000000 --- a/arch/h8300/configs/h8300h-sim_defconfig +++ /dev/null @@ -1,48 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -# CONFIG_USELIB is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_UID16 is not set -# CONFIG_SYSFS_SYSCALL is not set -# CONFIG_KALLSYMS is not set -# CONFIG_BASE_FULL is not set -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set -# CONFIG_SIGNALFD is not set -# CONFIG_TIMERFD is not set -# CONFIG_EVENTFD is not set -# CONFIG_AIO is not set -# CONFIG_ADVISE_SYSCALLS is not set -CONFIG_EMBEDDED=y -# CONFIG_VM_EVENT_COUNTERS is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_SLOB=y -# CONFIG_BLOCK is not set -CONFIG_H8300H_SIM=y -CONFIG_H8300_BUILTIN_DTB="h8300h_sim" -# CONFIG_BINFMT_SCRIPT is not set -CONFIG_BINFMT_FLAT=y -# CONFIG_COREDUMP is not set -# CONFIG_UEVENT_HELPER is not set -# CONFIG_STANDALONE is not set -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -# CONFIG_ALLOW_DEV_COREDUMP is not set -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_UNIX98_PTYS is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_EARLYCON=y -# CONFIG_HW_RANDOM is not set -# CONFIG_HWMON is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_FILE_LOCKING is not set -# CONFIG_DNOTIFY is not set -# CONFIG_INOTIFY_USER is not set -# CONFIG_PROC_FS is not set -# CONFIG_SYSFS is not set -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_DEBUG_INFO=y -# CONFIG_ENABLE_MUST_CHECK is not set diff --git a/arch/h8300/configs/h8s-sim_defconfig b/arch/h8300/configs/h8s-sim_defconfig deleted file mode 100644 index 23791dcf6c25..000000000000 --- a/arch/h8300/configs/h8s-sim_defconfig +++ /dev/null @@ -1,48 +0,0 @@ -# CONFIG_LOCALVERSION_AUTO is not set -# CONFIG_USELIB is not set -CONFIG_CC_OPTIMIZE_FOR_SIZE=y -# CONFIG_UID16 is not set -# CONFIG_SYSFS_SYSCALL is not set -# CONFIG_KALLSYMS is not set -# CONFIG_BASE_FULL is not set -# CONFIG_FUTEX is not set -# CONFIG_EPOLL is not set -# CONFIG_SIGNALFD is not set -# CONFIG_TIMERFD is not set -# CONFIG_EVENTFD is not set -# CONFIG_AIO is not set -# CONFIG_ADVISE_SYSCALLS is not set -CONFIG_EMBEDDED=y -# CONFIG_VM_EVENT_COUNTERS is not set -# CONFIG_COMPAT_BRK is not set -CONFIG_SLOB=y -# CONFIG_BLOCK is not set -CONFIG_H8S_SIM=y -CONFIG_H8300_BUILTIN_DTB="h8s_sim" -# CONFIG_BINFMT_SCRIPT is not set -CONFIG_BINFMT_FLAT=y -# CONFIG_COREDUMP is not set -# CONFIG_UEVENT_HELPER is not set -# CONFIG_STANDALONE is not set -# CONFIG_PREVENT_FIRMWARE_BUILD is not set -# CONFIG_FW_LOADER is not set -# CONFIG_ALLOW_DEV_COREDUMP is not set -# CONFIG_INPUT is not set -# CONFIG_SERIO is not set -# CONFIG_VT is not set -# CONFIG_UNIX98_PTYS is not set -# CONFIG_LEGACY_PTYS is not set -# CONFIG_DEVKMEM is not set -CONFIG_SERIAL_SH_SCI=y -CONFIG_SERIAL_SH_SCI_CONSOLE=y -# CONFIG_HW_RANDOM is not set -# CONFIG_HWMON is not set -# CONFIG_USB_SUPPORT is not set -# CONFIG_FILE_LOCKING is not set -# CONFIG_DNOTIFY is not set -# CONFIG_INOTIFY_USER is not set -# CONFIG_PROC_FS is not set -# CONFIG_SYSFS is not set -# CONFIG_MISC_FILESYSTEMS is not set -CONFIG_DEBUG_INFO=y -# CONFIG_ENABLE_MUST_CHECK is not set diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild deleted file mode 100644 index e23139c8fc0d..000000000000 --- a/arch/h8300/include/asm/Kbuild +++ /dev/null @@ -1,8 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -generic-y += asm-offsets.h -generic-y += cmpxchg.h -generic-y += extable.h -generic-y += kvm_para.h -generic-y += mcs_spinlock.h -generic-y += parport.h -generic-y += spinlock.h diff --git a/arch/h8300/include/asm/bitops.h b/arch/h8300/include/asm/bitops.h deleted file mode 100644 index 4489e3d6edd3..000000000000 --- a/arch/h8300/include/asm/bitops.h +++ /dev/null @@ -1,179 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_BITOPS_H -#define _H8300_BITOPS_H - -/* - * Copyright 1992, Linus Torvalds. - * Copyright 2002, Yoshinori Sato - */ - -#include - -#include -#include -#include - -#ifdef __KERNEL__ - -#ifndef _LINUX_BITOPS_H -#error only can be included directly -#endif - -/* - * Function prototypes to keep gcc -Wall happy - */ - -/* - * ffz = Find First Zero in word. Undefined if no zero exists, - * so code should check against ~0UL first.. - */ -static inline unsigned long ffz(unsigned long word) -{ - unsigned long result; - - result = -1; - __asm__("1:\n\t" - "shlr.l %1\n\t" - "adds #1,%0\n\t" - "bcs 1b" - : "=r"(result),"=r"(word) - : "0"(result), "1"(word)); - return result; -} - -#define H8300_GEN_BITOP(FNAME, OP) \ -static inline void FNAME(int nr, volatile unsigned long *addr) \ -{ \ - unsigned char *b_addr; \ - unsigned char bit = nr & 7; \ - \ - b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \ - if (__builtin_constant_p(nr)) { \ - __asm__(OP " %1,%0" : "+WU"(*b_addr) : "i"(nr & 7)); \ - } else { \ - __asm__(OP " %s1,%0" : "+WU"(*b_addr) : "r"(bit)); \ - } \ -} - -H8300_GEN_BITOP(set_bit, "bset") -H8300_GEN_BITOP(clear_bit, "bclr") -H8300_GEN_BITOP(change_bit, "bnot") -#define __set_bit(nr, addr) set_bit((nr), (addr)) -#define __clear_bit(nr, addr) clear_bit((nr), (addr)) -#define __change_bit(nr, addr) change_bit((nr), (addr)) - -#undef H8300_GEN_BITOP - -static inline int test_bit(int nr, const volatile unsigned long *addr) -{ - int ret = 0; - unsigned char *b_addr; - unsigned char bit = nr & 7; - - b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); - if (__builtin_constant_p(nr)) { - __asm__("bld %Z2,%1\n\t" - "rotxl %0\n\t" - : "=r"(ret) - : "WU"(*b_addr), "i"(nr & 7), "0"(ret) : "cc"); - } else { - __asm__("btst %w2,%1\n\t" - "beq 1f\n\t" - "inc.l #1,%0\n" - "1:" - : "=r"(ret) - : "WU"(*b_addr), "r"(bit), "0"(ret) : "cc"); - } - return ret; -} - -#define __test_bit(nr, addr) test_bit(nr, addr) - -#define H8300_GEN_TEST_BITOP(FNNAME, OP) \ -static inline int FNNAME(int nr, void *addr) \ -{ \ - int retval = 0; \ - char ccrsave; \ - unsigned char *b_addr; \ - unsigned char bit = nr & 7; \ - \ - b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \ - if (__builtin_constant_p(nr)) { \ - __asm__("stc ccr,%s2\n\t" \ - "orc #0x80,ccr\n\t" \ - "bld %4,%1\n\t" \ - OP " %4,%1\n\t" \ - "rotxl.l %0\n\t" \ - "ldc %s2,ccr" \ - : "=r"(retval), "+WU" (*b_addr), "=&r"(ccrsave) \ - : "0"(retval), "i"(nr & 7) : "cc"); \ - } else { \ - __asm__("stc ccr,%t3\n\t" \ - "orc #0x80,ccr\n\t" \ - "btst %s3,%1\n\t" \ - OP " %s3,%1\n\t" \ - "beq 1f\n\t" \ - "inc.l #1,%0\n\t" \ - "1:\n" \ - "ldc %t3,ccr" \ - : "=r"(retval), "+WU" (*b_addr) \ - : "0" (retval), "r"(bit) : "cc"); \ - } \ - return retval; \ -} \ - \ -static inline int __ ## FNNAME(int nr, void *addr) \ -{ \ - int retval = 0; \ - unsigned char *b_addr; \ - unsigned char bit = nr & 7; \ - \ - b_addr = (unsigned char *)addr + ((nr >> 3) ^ 3); \ - if (__builtin_constant_p(nr)) { \ - __asm__("bld %3,%1\n\t" \ - OP " %3,%1\n\t" \ - "rotxl.l %0\n\t" \ - : "=r"(retval), "+WU"(*b_addr) \ - : "0" (retval), "i"(nr & 7)); \ - } else { \ - __asm__("btst %s3,%1\n\t" \ - OP " %s3,%1\n\t" \ - "beq 1f\n\t" \ - "inc.l #1,%0\n\t" \ - "1:" \ - : "=r"(retval), "+WU"(*b_addr) \ - : "0" (retval), "r"(bit)); \ - } \ - return retval; \ -} - -H8300_GEN_TEST_BITOP(test_and_set_bit, "bset") -H8300_GEN_TEST_BITOP(test_and_clear_bit, "bclr") -H8300_GEN_TEST_BITOP(test_and_change_bit, "bnot") -#undef H8300_GEN_TEST_BITOP - -#include - -static inline unsigned long __ffs(unsigned long word) -{ - unsigned long result; - - result = -1; - __asm__("1:\n\t" - "shlr.l %1\n\t" - "adds #1,%0\n\t" - "bcc 1b" - : "=r" (result),"=r"(word) - : "0"(result), "1"(word)); - return result; -} - -#include -#include -#include -#include -#include - -#endif /* __KERNEL__ */ - -#endif /* _H8300_BITOPS_H */ diff --git a/arch/h8300/include/asm/bug.h b/arch/h8300/include/asm/bug.h deleted file mode 100644 index 00fe5e966bb5..000000000000 --- a/arch/h8300/include/asm/bug.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_BUG_H -#define _H8300_BUG_H - -/* always true */ -#define is_valid_bugaddr(addr) (1) - -#include - -struct pt_regs; -extern void die(const char *str, struct pt_regs *fp, unsigned long err); - -#endif diff --git a/arch/h8300/include/asm/byteorder.h b/arch/h8300/include/asm/byteorder.h deleted file mode 100644 index 6eaa7ad5fc2c..000000000000 --- a/arch/h8300/include/asm/byteorder.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __H8300_BYTEORDER_H__ -#define __H8300_BYTEORDER_H__ - -#include - -#endif diff --git a/arch/h8300/include/asm/cache.h b/arch/h8300/include/asm/cache.h deleted file mode 100644 index 4243eb319acf..000000000000 --- a/arch/h8300/include/asm/cache.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ARCH_H8300_CACHE_H -#define __ARCH_H8300_CACHE_H - -/* bytes per L1 cache line */ -#define L1_CACHE_SHIFT 2 -#define L1_CACHE_BYTES (1 << L1_CACHE_SHIFT) - -#define __cacheline_aligned -#define ____cacheline_aligned - -#endif diff --git a/arch/h8300/include/asm/elf.h b/arch/h8300/include/asm/elf.h deleted file mode 100644 index 029647cda44c..000000000000 --- a/arch/h8300/include/asm/elf.h +++ /dev/null @@ -1,102 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_H8300_ELF_H -#define __ASM_H8300_ELF_H - -/* - * ELF register definitions.. - */ - -#include -#include - -typedef unsigned long elf_greg_t; - -#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t)) -typedef elf_greg_t elf_gregset_t[ELF_NGREG]; -typedef unsigned long elf_fpregset_t; - -/* - * This is used to ensure we don't load something for the wrong architecture. - */ -#define elf_check_arch(x) ((x)->e_machine == EM_H8_300) - -/* - * These are used to set parameters in the core dumps. - */ -#define ELF_CLASS ELFCLASS32 -#define ELF_DATA ELFDATA2MSB -#define ELF_ARCH EM_H8_300 -#if defined(CONFIG_CPU_H8300H) -#define ELF_CORE_EFLAGS 0x810000 -#endif -#if defined(CONFIG_CPU_H8S) -#define ELF_CORE_EFLAGS 0x820000 -#endif - -#define ELF_PLAT_INIT(_r) do { (_r)->er1 = 0; } while (0) - -#define ELF_EXEC_PAGESIZE 4096 - -/* This is the location that an ET_DYN program is loaded if exec'ed. Typical - use of this is to invoke "./ld.so someprog" to test out a new version of - the loader. We need to make sure that it is out of the way of the program - that it will "exec", and that there is sufficient room for the brk. */ - -#define ELF_ET_DYN_BASE 0xD0000000UL - -/* This yields a mask that user programs can use to figure out what - instruction set this cpu supports. */ - -#define ELF_HWCAP (0) - -/* This yields a string that ld.so will use to load implementation - specific libraries for optimization. This is more specific in - intent than poking at uname or /proc/cpuinfo. */ - -#define ELF_PLATFORM (NULL) - -#define R_H8_NONE 0 -#define R_H8_DIR32 1 -#define R_H8_DIR32_28 2 -#define R_H8_DIR32_24 3 -#define R_H8_DIR32_16 4 -#define R_H8_DIR32U 6 -#define R_H8_DIR32U_28 7 -#define R_H8_DIR32U_24 8 -#define R_H8_DIR32U_20 9 -#define R_H8_DIR32U_16 10 -#define R_H8_DIR24 11 -#define R_H8_DIR24_20 12 -#define R_H8_DIR24_16 13 -#define R_H8_DIR24U 14 -#define R_H8_DIR24U_20 15 -#define R_H8_DIR24U_16 16 -#define R_H8_DIR16 17 -#define R_H8_DIR16U 18 -#define R_H8_DIR16S_32 19 -#define R_H8_DIR16S_28 20 -#define R_H8_DIR16S_24 21 -#define R_H8_DIR16S_20 22 -#define R_H8_DIR16S 23 -#define R_H8_DIR8 24 -#define R_H8_DIR8U 25 -#define R_H8_DIR8Z_32 26 -#define R_H8_DIR8Z_28 27 -#define R_H8_DIR8Z_24 28 -#define R_H8_DIR8Z_20 29 -#define R_H8_DIR8Z_16 30 -#define R_H8_PCREL16 31 -#define R_H8_PCREL8 32 -#define R_H8_BPOS 33 -#define R_H8_PCREL32 34 -#define R_H8_GOT32O 35 -#define R_H8_GOT16O 36 -#define R_H8_DIR16A8 59 -#define R_H8_DIR16R8 60 -#define R_H8_DIR24A8 61 -#define R_H8_DIR24R8 62 -#define R_H8_DIR32A16 63 -#define R_H8_ABS32 65 -#define R_H8_ABS32A16 127 - -#endif diff --git a/arch/h8300/include/asm/flat.h b/arch/h8300/include/asm/flat.h deleted file mode 100644 index 78070f924177..000000000000 --- a/arch/h8300/include/asm/flat.h +++ /dev/null @@ -1,36 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * arch/h8300/asm/include/flat.h -- uClinux flat-format executables - */ - -#ifndef __H8300_FLAT_H__ -#define __H8300_FLAT_H__ - -#include - -/* - * on the H8 a couple of the relocations have an instruction in the - * top byte. As there can only be 24bits of address space, we just - * always preserve that 8bits at the top, when it isn't an instruction - * is is 0 (davidm@snapgear.com) - */ - -#define flat_get_relocate_addr(rel) (rel & ~0x00000001) -static inline int flat_get_addr_from_rp(u32 __user *rp, u32 relval, u32 flags, - u32 *addr) -{ - u32 val = get_unaligned((__force u32 *)rp); - if (!(flags & FLAT_FLAG_GOTPIC)) - val &= 0x00ffffff; - *addr = val; - return 0; -} - -static inline int flat_put_addr_at_rp(u32 __user *rp, u32 addr, u32 rel) -{ - u32 *p = (__force u32 *)rp; - put_unaligned((addr & 0x00ffffff) | (*(char *)p << 24), p); - return 0; -} - -#endif /* __H8300_FLAT_H__ */ diff --git a/arch/h8300/include/asm/hash.h b/arch/h8300/include/asm/hash.h deleted file mode 100644 index 2960b4c9e4ed..000000000000 --- a/arch/h8300/include/asm/hash.h +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _ASM_HASH_H -#define _ASM_HASH_H - -/* - * The later H8SX models have a 32x32-bit multiply, but the H8/300H - * and H8S have only 16x16->32. Since it's tolerably compact, this is - * basically an inlined version of the __mulsi3 code. Since the inputs - * are not expected to be small, it's also simplfied by skipping the - * early-out checks. - * - * (Since neither CPU has any multi-bit shift instructions, a - * shift-and-add version is a non-starter.) - * - * TODO: come up with an arch-specific version of the hashing in fs/namei.c, - * since that is heavily dependent on rotates. Which, as mentioned, suck - * horribly on H8. - */ - -#if defined(CONFIG_CPU_H300H) || defined(CONFIG_CPU_H8S) - -#define HAVE_ARCH__HASH_32 1 - -/* - * Multiply by k = 0x61C88647. Fitting this into three registers requires - * one extra instruction, but reducing register pressure will probably - * make that back and then some. - * - * GCC asm note: %e1 is the high half of operand %1, while %f1 is the - * low half. So if %1 is er4, then %e1 is e4 and %f1 is r4. - * - * This has been designed to modify x in place, since that's the most - * common usage, but preserve k, since hash_64() makes two calls in - * quick succession. - */ -static inline u32 __attribute_const__ __hash_32(u32 x) -{ - u32 temp; - - asm( "mov.w %e1,%f0" - "\n mulxu.w %f2,%0" /* klow * xhigh */ - "\n mov.w %f0,%e1" /* The extra instruction */ - "\n mov.w %f1,%f0" - "\n mulxu.w %e2,%0" /* khigh * xlow */ - "\n add.w %e1,%f0" - "\n mulxu.w %f2,%1" /* klow * xlow */ - "\n add.w %f0,%e1" - : "=&r" (temp), "=r" (x) - : "%r" (GOLDEN_RATIO_32), "1" (x)); - return x; -} - -#endif -#endif /* _ASM_HASH_H */ diff --git a/arch/h8300/include/asm/io.h b/arch/h8300/include/asm/io.h deleted file mode 100644 index 096d99580db6..000000000000 --- a/arch/h8300/include/asm/io.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_IO_H -#define _H8300_IO_H - -#ifdef __KERNEL__ - -#include - -/* H8/300 internal I/O functions */ - -#define __raw_readb __raw_readb -static inline u8 __raw_readb(const volatile void __iomem *addr) -{ - return *(volatile u8 *)addr; -} - -#define __raw_readw __raw_readw -static inline u16 __raw_readw(const volatile void __iomem *addr) -{ - return *(volatile u16 *)addr; -} - -#define __raw_readl __raw_readl -static inline u32 __raw_readl(const volatile void __iomem *addr) -{ - return *(volatile u32 *)addr; -} - -#define __raw_writeb __raw_writeb -static inline void __raw_writeb(u8 b, const volatile void __iomem *addr) -{ - *(volatile u8 *)addr = b; -} - -#define __raw_writew __raw_writew -static inline void __raw_writew(u16 b, const volatile void __iomem *addr) -{ - *(volatile u16 *)addr = b; -} - -#define __raw_writel __raw_writel -static inline void __raw_writel(u32 b, const volatile void __iomem *addr) -{ - *(volatile u32 *)addr = b; -} - -static inline void ctrl_bclr(int b, void __iomem *addr) -{ - if (__builtin_constant_p(b)) - __asm__("bclr %1,%0" : "+WU"(*(u8 *)addr): "i"(b)); - else - __asm__("bclr %w1,%0" : "+WU"(*(u8 *)addr): "r"(b)); -} - -static inline void ctrl_bset(int b, void __iomem *addr) -{ - if (__builtin_constant_p(b)) - __asm__("bset %1,%0" : "+WU"(*(u8 *)addr): "i"(b)); - else - __asm__("bset %w1,%0" : "+WU"(*(u8 *)addr): "r"(b)); -} - -#include - -#endif /* __KERNEL__ */ - -#endif /* _H8300_IO_H */ diff --git a/arch/h8300/include/asm/irq.h b/arch/h8300/include/asm/irq.h deleted file mode 100644 index 776cf06d7a59..000000000000 --- a/arch/h8300/include/asm/irq.h +++ /dev/null @@ -1,25 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_IRQ_H_ -#define _H8300_IRQ_H_ - -#if defined(CONFIG_CPU_H8300H) -#define NR_IRQS 64 -#define IRQ_CHIP h8300h_irq_chip -#define EXT_IRQ0 12 -#define EXT_IRQS 6 -#elif defined(CONFIG_CPU_H8S) -#define NR_IRQS 128 -#define IRQ_CHIP h8s_irq_chip -#define EXT_IRQ0 16 -#define EXT_IRQS 16 -#endif - -static inline int irq_canonicalize(int irq) -{ - return irq; -} - -void h8300_init_ipr(void); -extern struct irq_chip h8300h_irq_chip; -extern struct irq_chip h8s_irq_chip; -#endif /* _H8300_IRQ_H_ */ diff --git a/arch/h8300/include/asm/irqflags.h b/arch/h8300/include/asm/irqflags.h deleted file mode 100644 index 48756b7f405e..000000000000 --- a/arch/h8300/include/asm/irqflags.h +++ /dev/null @@ -1,97 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_IRQFLAGS_H -#define _H8300_IRQFLAGS_H - -#ifdef CONFIG_CPU_H8300H -typedef unsigned char h8300flags; - -static inline h8300flags arch_local_save_flags(void) -{ - h8300flags flags; - - __asm__ volatile ("stc ccr,%w0" : "=r" (flags)); - return flags; -} - -static inline void arch_local_irq_disable(void) -{ - __asm__ volatile ("orc #0xc0,ccr"); -} - -static inline void arch_local_irq_enable(void) -{ - __asm__ volatile ("andc #0x3f,ccr"); -} - -static inline h8300flags arch_local_irq_save(void) -{ - h8300flags flags; - - __asm__ volatile ("stc ccr,%w0\n\t" - "orc #0xc0,ccr" : "=r" (flags)); - return flags; -} - -static inline void arch_local_irq_restore(h8300flags flags) -{ - __asm__ volatile ("ldc %w0,ccr" : : "r" (flags) : "cc"); -} - -static inline int arch_irqs_disabled_flags(unsigned long flags) -{ - return (flags & 0xc0) == 0xc0; -} -#endif -#ifdef CONFIG_CPU_H8S -typedef unsigned short h8300flags; - -static inline h8300flags arch_local_save_flags(void) -{ - h8300flags flags; - - __asm__ volatile ("stc ccr,%w0\n\tstc exr,%x0" : "=r" (flags)); - return flags; -} - -static inline void arch_local_irq_disable(void) -{ - __asm__ volatile ("orc #0x80,ccr\n\t"); -} - -static inline void arch_local_irq_enable(void) -{ - __asm__ volatile ("andc #0x7f,ccr\n\t" - "andc #0xf0,exr\n\t"); -} - -static inline h8300flags arch_local_irq_save(void) -{ - h8300flags flags; - - __asm__ volatile ("stc ccr,%w0\n\t" - "stc exr,%x0\n\t" - "orc #0x80,ccr\n\t" - : "=r" (flags)); - return flags; -} - -static inline void arch_local_irq_restore(h8300flags flags) -{ - __asm__ volatile ("ldc %w0,ccr\n\t" - "ldc %x0,exr" - : : "r" (flags) : "cc"); -} - -static inline int arch_irqs_disabled_flags(h8300flags flags) -{ - return (flags & 0x0080) == 0x0080; -} - -#endif - -static inline int arch_irqs_disabled(void) -{ - return arch_irqs_disabled_flags(arch_local_save_flags()); -} - -#endif /* _H8300_IRQFLAGS_H */ diff --git a/arch/h8300/include/asm/kgdb.h b/arch/h8300/include/asm/kgdb.h deleted file mode 100644 index 726ff8fdfc18..000000000000 --- a/arch/h8300/include/asm/kgdb.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (C) 2015 Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#ifndef _ASM_H8300_KGDB_H -#define _ASM_H8300_KGDB_H - -#define CACHE_FLUSH_IS_SAFE 1 -#define BUFMAX 2048 - -enum regnames { - GDB_ER0, GDB_ER1, GDB_ER2, GDB_ER3, - GDB_ER4, GDB_ER5, GDB_ER6, GDB_SP, - GDB_CCR, GDB_PC, - GDB_CYCLLE, -#if defined(CONFIG_CPU_H8S) - GDB_EXR, -#endif - GDB_TICK, GDB_INST, -#if defined(CONFIG_CPU_H8S) - GDB_MACH, GDB_MACL, -#endif - /* do not change the last entry or anything below! */ - GDB_NUMREGBYTES, /* number of registers */ -}; - -#define GDB_SIZEOF_REG sizeof(u32) -#if defined(CONFIG_CPU_H8300H) -#define DBG_MAX_REG_NUM (13) -#elif defined(CONFIG_CPU_H8S) -#define DBG_MAX_REG_NUM (14) -#endif -#define NUMREGBYTES (DBG_MAX_REG_NUM * GDB_SIZEOF_REG) - -#define BREAK_INSTR_SIZE 2 -static inline void arch_kgdb_breakpoint(void) -{ - __asm__ __volatile__("trapa #2"); -} - -#endif /* _ASM_H8300_KGDB_H */ diff --git a/arch/h8300/include/asm/mmu_context.h b/arch/h8300/include/asm/mmu_context.h deleted file mode 100644 index a9f550f5b5ec..000000000000 --- a/arch/h8300/include/asm/mmu_context.h +++ /dev/null @@ -1,6 +0,0 @@ -#ifndef _ASM_H8300_MMU_CONTEXT_H -#define _ASM_H8300_MMU_CONTEXT_H - -#include - -#endif /* _ASM_H8300_MMU_CONTEXT_H */ diff --git a/arch/h8300/include/asm/page.h b/arch/h8300/include/asm/page.h deleted file mode 100644 index 53e037544239..000000000000 --- a/arch/h8300/include/asm/page.h +++ /dev/null @@ -1,17 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_PAGE_H -#define _H8300_PAGE_H - -#include -#include - -#define MAP_NR(addr) (((uintptr_t)(addr)-PAGE_OFFSET) >> PAGE_SHIFT) - -#ifndef __ASSEMBLY__ -extern unsigned long rom_length; -extern unsigned long memory_start; -extern unsigned long memory_end; -extern unsigned long _ramend; -#endif - -#endif diff --git a/arch/h8300/include/asm/page_offset.h b/arch/h8300/include/asm/page_offset.h deleted file mode 100644 index 888576d7cc2a..000000000000 --- a/arch/h8300/include/asm/page_offset.h +++ /dev/null @@ -1,2 +0,0 @@ - -#define PAGE_OFFSET_RAW 0x00000000 diff --git a/arch/h8300/include/asm/pgtable.h b/arch/h8300/include/asm/pgtable.h deleted file mode 100644 index ea833a5d8bcf..000000000000 --- a/arch/h8300/include/asm/pgtable.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_PGTABLE_H -#define _H8300_PGTABLE_H -#include -extern void paging_init(void); -#define PAGE_NONE __pgprot(0) /* these mean nothing to NO_MM */ -#define PAGE_SHARED __pgprot(0) /* these mean nothing to NO_MM */ -#define PAGE_COPY __pgprot(0) /* these mean nothing to NO_MM */ -#define PAGE_READONLY __pgprot(0) /* these mean nothing to NO_MM */ -#define PAGE_KERNEL __pgprot(0) /* these mean nothing to NO_MM */ -#define __swp_type(x) (0) -#define __swp_offset(x) (0) -#define __swp_entry(typ, off) ((swp_entry_t) { ((typ) | ((off) << 7)) }) -#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) -#define kern_addr_valid(addr) (1) -#define pgprot_writecombine(prot) (prot) -#define pgprot_noncached pgprot_writecombine - -static inline int pte_file(pte_t pte) { return 0; } -#define swapper_pg_dir ((pgd_t *) 0) -/* - * ZERO_PAGE is a global shared page that is always zero: used - * for zero-mapped memory areas etc.. - */ -#define ZERO_PAGE(vaddr) (virt_to_page(0)) - -/* - * These would be in other places but having them here reduces the diffs. - */ -extern unsigned int kobjsize(const void *objp); -extern int is_in_rom(unsigned long); - -/* - * All 32bit addresses are effectively valid for vmalloc... - * Sort of meaningless for non-VM targets. - */ -#define VMALLOC_START 0 -#define VMALLOC_END 0xffffffff - -#define arch_enter_lazy_cpu_mode() do {} while (0) - -#endif /* _H8300_PGTABLE_H */ diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h deleted file mode 100644 index 141a23eb62b7..000000000000 --- a/arch/h8300/include/asm/processor.h +++ /dev/null @@ -1,127 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * include/asm-h8300/processor.h - * - * Copyright (C) 2002 Yoshinori Sato - * - * Based on: linux/asm-m68nommu/processor.h - * - * Copyright (C) 1995 Hamish Macdonald - */ - -#ifndef __ASM_H8300_PROCESSOR_H -#define __ASM_H8300_PROCESSOR_H - -#include -#include -#include -#include - -static inline unsigned long rdusp(void) -{ - extern unsigned int _sw_usp; - - return _sw_usp; -} - -static inline void wrusp(unsigned long usp) -{ - extern unsigned int _sw_usp; - - _sw_usp = usp; -} - -/* - * User space process size: 3.75GB. This is hardcoded into a few places, - * so don't change it unless you know what you are doing. - */ -#define TASK_SIZE (0xFFFFFFFFUL) - -#ifdef __KERNEL__ -#define STACK_TOP TASK_SIZE -#define STACK_TOP_MAX STACK_TOP -#endif - -/* - * This decides where the kernel will search for a free chunk of vm - * space during mmap's. We won't be using it - */ -#define TASK_UNMAPPED_BASE 0 - -struct thread_struct { - unsigned long ksp; /* kernel stack pointer */ - unsigned long usp; /* user stack pointer */ - unsigned long ccr; /* saved status register */ - unsigned long esp0; /* points to SR of stack frame */ - struct { - unsigned short *addr; - unsigned short inst; - } breakinfo; -}; - -#define INIT_THREAD { \ - .ksp = sizeof(init_stack) + (unsigned long)init_stack, \ - .usp = 0, \ - .ccr = PS_S, \ - .esp0 = 0, \ - .breakinfo = { \ - .addr = (unsigned short *)-1, \ - .inst = 0 \ - } \ -} - -/* - * Do necessary setup to start up a newly executed thread. - * - * pass the data segment into user programs if it exists, - * it can't hurt anything as far as I can tell - */ -#if defined(CONFIG_CPU_H8300H) -#define start_thread(_regs, _pc, _usp) \ -do { \ - (_regs)->pc = (_pc); \ - (_regs)->ccr = 0x00; /* clear all flags */ \ - (_regs)->er5 = current->mm->start_data; /* GOT base */ \ - (_regs)->sp = ((unsigned long)(_usp)) - sizeof(unsigned long) * 3; \ -} while (0) -#endif -#if defined(CONFIG_CPU_H8S) -#define start_thread(_regs, _pc, _usp) \ -do { \ - (_regs)->pc = (_pc); \ - (_regs)->ccr = 0x00; /* clear kernel flag */ \ - (_regs)->exr = 0x78; /* enable all interrupts */ \ - (_regs)->er5 = current->mm->start_data; /* GOT base */ \ - /* 14 = space for retaddr(4), vector(4), er0(4) and exr(2) on stack */ \ - (_regs)->sp = ((unsigned long)(_usp)) - 14; \ -} while (0) -#endif - -/* Forward declaration, a strange C thing */ -struct task_struct; - -/* Free all resources held by a thread. */ -static inline void release_thread(struct task_struct *dead_task) -{ -} - -unsigned long __get_wchan(struct task_struct *p); - -#define KSTK_EIP(tsk) \ - ({ \ - unsigned long eip = 0; \ - if ((tsk)->thread.esp0 > PAGE_SIZE && \ - MAP_NR((tsk)->thread.esp0) < max_mapnr) \ - eip = ((struct pt_regs *) (tsk)->thread.esp0)->pc; \ - eip; }) - -#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp) - -#define cpu_relax() barrier() - -#define HARD_RESET_NOW() ({ \ - local_irq_disable(); \ - asm("jmp @@0"); \ -}) - -#endif diff --git a/arch/h8300/include/asm/ptrace.h b/arch/h8300/include/asm/ptrace.h deleted file mode 100644 index 66d383848ff1..000000000000 --- a/arch/h8300/include/asm/ptrace.h +++ /dev/null @@ -1,39 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_PTRACE_H -#define _H8300_PTRACE_H - -#include - -struct task_struct; - -#ifndef __ASSEMBLY__ -#ifndef PS_S -#define PS_S (0x10) -#endif - -#if defined(CONFIG_CPU_H8300H) -#define H8300_REGS_NO 11 -#endif -#if defined(CONFIG_CPU_H8S) -#define H8300_REGS_NO 12 -#endif - -#define arch_has_single_step() (1) - -#define user_mode(regs) (!((regs)->ccr & PS_S)) -#define instruction_pointer(regs) ((regs)->pc) -#define profile_pc(regs) instruction_pointer(regs) -#define user_stack_pointer(regs) ((regs)->sp) -#define current_pt_regs() ((struct pt_regs *) \ - (THREAD_SIZE + (unsigned long)current_thread_info()) - 1) -#define signal_pt_regs() ((struct pt_regs *)current->thread.esp0) -#define current_user_stack_pointer() rdusp() -#define task_pt_regs(task) \ - ((struct pt_regs *) (task_stack_page(task) + THREAD_SIZE) - 1) - -extern long h8300_get_reg(struct task_struct *task, int regno); -extern int h8300_put_reg(struct task_struct *task, int regno, - unsigned long data); - -#endif /* __ASSEMBLY__ */ -#endif /* _H8300_PTRACE_H */ diff --git a/arch/h8300/include/asm/segment.h b/arch/h8300/include/asm/segment.h deleted file mode 100644 index 37950725d9b9..000000000000 --- a/arch/h8300/include/asm/segment.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_SEGMENT_H -#define _H8300_SEGMENT_H - -/* define constants */ -#define USER_DATA (1) -#ifndef __USER_DS -#define __USER_DS (USER_DATA) -#endif -#define USER_PROGRAM (2) -#define SUPER_DATA (3) -#ifndef __KERNEL_DS -#define __KERNEL_DS (SUPER_DATA) -#endif -#define SUPER_PROGRAM (4) - -#ifndef __ASSEMBLY__ - -typedef struct { - unsigned long seg; -} mm_segment_t; - -#define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) -#define USER_DS MAKE_MM_SEG(__USER_DS) -#define KERNEL_DS MAKE_MM_SEG(__KERNEL_DS) - -/* - * Get/set the SFC/DFC registers for MOVES instructions - */ - -static inline mm_segment_t get_fs(void) -{ - return USER_DS; -} - -#define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) - -#endif /* __ASSEMBLY__ */ - -#endif /* _H8300_SEGMENT_H */ diff --git a/arch/h8300/include/asm/signal.h b/arch/h8300/include/asm/signal.h deleted file mode 100644 index a42f32ca530f..000000000000 --- a/arch/h8300/include/asm/signal.h +++ /dev/null @@ -1,23 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_SIGNAL_H -#define _H8300_SIGNAL_H - -#include - -/* Most things should be clean enough to redefine this at will, if care - is taken to make libc match. */ - -#define _NSIG 64 -#define _NSIG_BPW 32 -#define _NSIG_WORDS (_NSIG / _NSIG_BPW) - -typedef unsigned long old_sigset_t; /* at least 32 bits */ - -typedef struct { - unsigned long sig[_NSIG_WORDS]; -} sigset_t; - -#define __ARCH_HAS_SA_RESTORER -#include - -#endif /* _H8300_SIGNAL_H */ diff --git a/arch/h8300/include/asm/smp.h b/arch/h8300/include/asm/smp.h deleted file mode 100644 index 9e9bd7e58922..000000000000 --- a/arch/h8300/include/asm/smp.h +++ /dev/null @@ -1 +0,0 @@ -/* nothing required here yet */ diff --git a/arch/h8300/include/asm/string.h b/arch/h8300/include/asm/string.h deleted file mode 100644 index 78e45bb2fef0..000000000000 --- a/arch/h8300/include/asm/string.h +++ /dev/null @@ -1,18 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_STRING_H_ -#define _H8300_STRING_H_ - -#ifdef __KERNEL__ /* only set these up for kernel code */ - -#include -#include - -#define __HAVE_ARCH_MEMSET -extern void *memset(void *s, int c, size_t count); - -#define __HAVE_ARCH_MEMCPY -extern void *memcpy(void *d, const void *s, size_t count); - -#endif /* KERNEL */ - -#endif diff --git a/arch/h8300/include/asm/switch_to.h b/arch/h8300/include/asm/switch_to.h deleted file mode 100644 index 2b7e9555bcd1..000000000000 --- a/arch/h8300/include/asm/switch_to.h +++ /dev/null @@ -1,52 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_SWITCH_TO_H -#define _H8300_SWITCH_TO_H - -/* - * switch_to(n) should switch tasks to task ptr, first checking that - * ptr isn't the current task, in which case it does nothing. This - * also clears the TS-flag if the task we switched to has used the - * math co-processor latest. - */ -/* - * switch_to() saves the extra registers, that are not saved - * automatically by SAVE_SWITCH_STACK in resume(), ie. d0-d5 and - * a0-a1. Some of these are used by schedule() and its predecessors - * and so we might get see unexpected behaviors when a task returns - * with unexpected register values. - * - * syscall stores these registers itself and none of them are used - * by syscall after the function in the syscall has been called. - * - * Beware that resume now expects *next to be in d1 and the offset of - * tss to be in a1. This saves a few instructions as we no longer have - * to push them onto the stack and read them back right after. - * - * 02/17/96 - Jes Sorensen (jds@kom.auc.dk) - * - * Changed 96/09/19 by Andreas Schwab - * pass prev in a0, next in a1, offset of tss in d1, and whether - * the mm structures are shared in d2 (to avoid atc flushing). - * - * H8/300 Porting 2002/09/04 Yoshinori Sato - */ - -asmlinkage void resume(void); -#define switch_to(prev, next, last) \ -do { \ - void *_last; \ - __asm__ __volatile__( \ - "mov.l %1, er0\n\t" \ - "mov.l %2, er1\n\t" \ - "mov.l %3, er2\n\t" \ - "jsr @_resume\n\t" \ - "mov.l er2,%0\n\t" \ - : "=r" (_last) \ - : "r" (&(prev->thread)), \ - "r" (&(next->thread)), \ - "g" (prev) \ - : "cc", "er0", "er1", "er2", "er3"); \ - (last) = _last; \ -} while (0) - -#endif /* _H8300_SWITCH_TO_H */ diff --git a/arch/h8300/include/asm/syscall.h b/arch/h8300/include/asm/syscall.h deleted file mode 100644 index 01666b8bb263..000000000000 --- a/arch/h8300/include/asm/syscall.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_H8300_SYSCALLS_32_H -#define __ASM_H8300_SYSCALLS_32_H - -#ifdef __KERNEL__ - -#include -#include -#include -#include -#include - -static inline int -syscall_get_nr(struct task_struct *task, struct pt_regs *regs) -{ - return regs->orig_er0; -} - -static inline void -syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, - unsigned long *args) -{ - *args++ = regs->er1; - *args++ = regs->er2; - *args++ = regs->er3; - *args++ = regs->er4; - *args++ = regs->er5; - *args = regs->er6; -} - -static inline int -syscall_get_arch(struct task_struct *task) -{ - return AUDIT_ARCH_H8300; -} - - -/* Misc syscall related bits */ -asmlinkage long do_syscall_trace_enter(struct pt_regs *regs); -asmlinkage void do_syscall_trace_leave(struct pt_regs *regs); - -#endif /* __KERNEL__ */ -#endif /* __ASM_H8300_SYSCALLS_32_H */ diff --git a/arch/h8300/include/asm/thread_info.h b/arch/h8300/include/asm/thread_info.h deleted file mode 100644 index a518214d4ddd..000000000000 --- a/arch/h8300/include/asm/thread_info.h +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* thread_info.h: h8300 low-level thread information - * adapted from the i386 and PPC versions by Yoshinori Sato - * - * Copyright (C) 2002 David Howells (dhowells@redhat.com) - * - Incorporating suggestions made by Linus Torvalds and Dave Miller - */ - -#ifndef _ASM_THREAD_INFO_H -#define _ASM_THREAD_INFO_H - -#include -#include - -#ifdef __KERNEL__ - -/* - * Size of kernel stack for each process. This must be a power of 2... - */ -#define THREAD_SIZE_ORDER 1 -#define THREAD_SIZE 8192 /* 2 pages */ - -#ifndef __ASSEMBLY__ - -/* - * low level task data. - * If you change this, change the TI_* offsets below to match. - */ -struct thread_info { - struct task_struct *task; /* main task structure */ - unsigned long flags; /* low level flags */ - int cpu; /* cpu we're on */ - int preempt_count; /* 0 => preemptable, <0 => BUG */ - mm_segment_t addr_limit; -}; - -/* - * macros/functions for gaining access to the thread information structure - */ -#define INIT_THREAD_INFO(tsk) \ -{ \ - .task = &tsk, \ - .flags = 0, \ - .cpu = 0, \ - .preempt_count = INIT_PREEMPT_COUNT, \ - .addr_limit = KERNEL_DS, \ -} - -/* how to get the thread information struct from C */ -static inline struct thread_info *current_thread_info(void) -{ - struct thread_info *ti; - - __asm__("mov.l sp, %0\n\t" - "and.w %1, %T0" - : "=&r"(ti) - : "i" (~(THREAD_SIZE-1) & 0xffff)); - return ti; -} - -#endif /* __ASSEMBLY__ */ - -/* - * thread information flag bit numbers - */ -#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ -#define TIF_SIGPENDING 1 /* signal pending */ -#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ -#define TIF_SINGLESTEP 3 /* singlestepping active */ -#define TIF_MEMDIE 4 /* is terminating due to OOM killer */ -#define TIF_RESTORE_SIGMASK 5 /* restore signal mask in do_signal() */ -#define TIF_NOTIFY_RESUME 6 /* callback before returning to user */ -#define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ -#define TIF_SYSCALL_TRACEPOINT 8 /* for ftrace syscall instrumentation */ -#define TIF_POLLING_NRFLAG 9 /* true if poll_idle() is polling TIF_NEED_RESCHED */ -#define TIF_NOTIFY_SIGNAL 10 /* signal notifications exist */ - -/* as above, but as bit values */ -#define _TIF_SYSCALL_TRACE (1 << TIF_SYSCALL_TRACE) -#define _TIF_SIGPENDING (1 << TIF_SIGPENDING) -#define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) -#define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) -#define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) -#define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) -#define _TIF_SYSCALL_TRACEPOINT (1 << TIF_SYSCALL_TRACEPOINT) -#define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) -#define _TIF_NOTIFY_SIGNAL (1 << TIF_NOTIFY_SIGNAL) - -/* work to do in syscall trace */ -#define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \ - _TIF_SYSCALL_AUDIT | _TIF_SYSCALL_TRACEPOINT) - -/* work to do on any return to u-space */ -#define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \ - _TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \ - _TIF_SINGLESTEP | _TIF_NOTIFY_RESUME | \ - _TIF_SYSCALL_TRACEPOINT | _TIF_NOTIFY_SIGNAL) - -/* work to do on interrupt/exception return */ -#define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \ - _TIF_SYSCALL_AUDIT | _TIF_SINGLESTEP)) - -#endif /* __KERNEL__ */ - -#endif /* _ASM_THREAD_INFO_H */ diff --git a/arch/h8300/include/asm/tlb.h b/arch/h8300/include/asm/tlb.h deleted file mode 100644 index d8201ca31206..000000000000 --- a/arch/h8300/include/asm/tlb.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __H8300_TLB_H__ -#define __H8300_TLB_H__ - -#include - -#endif diff --git a/arch/h8300/include/asm/traps.h b/arch/h8300/include/asm/traps.h deleted file mode 100644 index 1c5a30ec2df8..000000000000 --- a/arch/h8300/include/asm/traps.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * linux/include/asm-h8300/traps.h - * - * Copyright (C) 2003 Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#ifndef _H8300_TRAPS_H -#define _H8300_TRAPS_H - -extern void _system_call(void); -extern void _interrupt_entry(void); -extern void _trace_break(void); -extern void _nmi(void); -extern void _interrupt_entry(void); - -extern unsigned long *_interrupt_redirect_table; - -#define JMP_OP 0x5a000000 -#define JSR_OP 0x5e000000 -#define VECTOR(address) ((JMP_OP)|((unsigned long)address)) -#define REDIRECT(address) ((JSR_OP)|((unsigned long)address)) -#define CPU_VECTOR ((unsigned long *)0x000000) -#define ADDR_MASK (0xffffff) - -#define TRACE_VEC 5 - -#define TRAP0_VEC 8 -#define TRAP1_VEC 9 -#define TRAP2_VEC 10 -#define TRAP3_VEC 11 - -extern char _start[], _etext[]; -#define check_kernel_text(addr) \ - ((addr >= (unsigned long)(_start)) && \ - (addr < (unsigned long)(_etext)) && !(addr & 1)) - -#endif /* _H8300_TRAPS_H */ diff --git a/arch/h8300/include/asm/user.h b/arch/h8300/include/asm/user.h deleted file mode 100644 index 2298909f24c6..000000000000 --- a/arch/h8300/include/asm/user.h +++ /dev/null @@ -1,75 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef _H8300_USER_H -#define _H8300_USER_H - -#include - -/* Core file format: The core file is written in such a way that gdb - can understand it and provide useful information to the user (under - linux we use the 'trad-core' bfd). There are quite a number of - obstacles to being able to view the contents of the floating point - registers, and until these are solved you will not be able to view the - contents of them. Actually, you can read in the core file and look at - the contents of the user struct to find out what the floating point - registers contain. - The actual file contents are as follows: - UPAGE: 1 page consisting of a user struct that tells gdb what is present - in the file. Directly after this is a copy of the task_struct, which - is currently not used by gdb, but it may come in useful at some point. - All of the registers are stored as part of the upage. The upage should - always be only one page. - DATA: The data area is stored. We use current->end_text to - current->brk to pick up all of the user variables, plus any memory - that may have been malloced. No attempt is made to determine if a page - is demand-zero or if a page is totally unused, we just cover the entire - range. All of the addresses are rounded in such a way that an integral - number of pages is written. - STACK: We need the stack information in order to get a meaningful - backtrace. We need to write the data from (esp) to - current->start_stack, so we round each of these off in order to be able - to write an integer number of pages. - The minimum core file size is 3 pages, or 12288 bytes. -*/ - -/* This is the old layout of "struct pt_regs" as of Linux 1.x, and - is still the layout used by user (the new pt_regs doesn't have - all registers). */ -struct user_regs_struct { - long er1, er2, er3, er4, er5, er6; - long er0; - long usp; - long orig_er0; - long ccr; - long pc; -}; - -/* When the kernel dumps core, it starts by dumping the user struct - - this will be used by gdb to figure out where the data and stack segments - are within the file, and what virtual addresses to use. */ -struct user { -/* We start with the registers, to mimic the way that "memory" is returned - from the ptrace(3,...) function. */ - struct user_regs_struct regs; /* Where the registers are actually stored */ -/* ptrace does not yet supply these. Someday.... */ -/* The rest of this junk is to help gdb figure out what goes where */ - unsigned long int u_tsize; /* Text segment size (pages). */ - unsigned long int u_dsize; /* Data segment size (pages). */ - unsigned long int u_ssize; /* Stack segment size (pages). */ - unsigned long start_code; /* Starting virtual address of text. */ - unsigned long start_stack; /* Starting virtual address of stack area. - This is actually the bottom of the stack, - the top of the stack is always found in the - esp register. */ - long int signal; /* Signal that caused the core dump. */ - int reserved; /* No longer used */ - unsigned long u_ar0; /* Used by gdb to help find the values for */ - /* the registers. */ - unsigned long magic; /* To uniquely identify a core file */ - char u_comm[32]; /* User command that was responsible */ -}; -#define NBPG PAGE_SIZE -#define UPAGES 1 -#define HOST_TEXT_START_ADDR (u.start_code) -#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) - -#endif diff --git a/arch/h8300/include/asm/vmalloc.h b/arch/h8300/include/asm/vmalloc.h deleted file mode 100644 index 08a55c1dfa23..000000000000 --- a/arch/h8300/include/asm/vmalloc.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef _ASM_H8300_VMALLOC_H -#define _ASM_H8300_VMALLOC_H - -#endif /* _ASM_H8300_VMALLOC_H */ diff --git a/arch/h8300/include/uapi/asm/Kbuild b/arch/h8300/include/uapi/asm/Kbuild deleted file mode 100644 index e78470141932..000000000000 --- a/arch/h8300/include/uapi/asm/Kbuild +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -generic-y += ucontext.h diff --git a/arch/h8300/include/uapi/asm/byteorder.h b/arch/h8300/include/uapi/asm/byteorder.h deleted file mode 100644 index 1fe2f9344458..000000000000 --- a/arch/h8300/include/uapi/asm/byteorder.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _H8300_BYTEORDER_H -#define _H8300_BYTEORDER_H - -#include - -#endif /* _H8300_BYTEORDER_H */ diff --git a/arch/h8300/include/uapi/asm/posix_types.h b/arch/h8300/include/uapi/asm/posix_types.h deleted file mode 100644 index 3efc9dd59476..000000000000 --- a/arch/h8300/include/uapi/asm/posix_types.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */ -#ifndef _UAPI_ASM_POSIX_TYPES_H -#define _UAPI_ASM_POSIX_TYPES_H - -/* h8300-unknown-linux required long */ -#define __kernel_size_t __kernel_size_t -typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; -typedef long __kernel_ptrdiff_t; - -#include - -#endif /* _UAPI_ASM_POSIX_TYPES_H */ diff --git a/arch/h8300/include/uapi/asm/ptrace.h b/arch/h8300/include/uapi/asm/ptrace.h deleted file mode 100644 index 78167f517ca4..000000000000 --- a/arch/h8300/include/uapi/asm/ptrace.h +++ /dev/null @@ -1,43 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_H8300_PTRACE_H -#define _UAPI_H8300_PTRACE_H - -#ifndef __ASSEMBLY__ - -#define PT_ER1 0 -#define PT_ER2 1 -#define PT_ER3 2 -#define PT_ER4 3 -#define PT_ER5 4 -#define PT_ER6 5 -#define PT_ER0 6 -#define PT_USP 7 -#define PT_ORIG_ER0 8 -#define PT_CCR 9 -#define PT_PC 10 -#define PT_EXR 11 - -/* this struct defines the way the registers are stored on the - stack during a system call. */ - -struct pt_regs { - long retpc; - long er4; - long er5; - long er6; - long er3; - long er2; - long er1; - long orig_er0; - long sp; - unsigned short ccr; - long er0; - long vector; -#if defined(__H8300S__) - unsigned short exr; -#endif - unsigned long pc; -} __attribute__((aligned(2), packed)); - -#endif /* __ASSEMBLY__ */ -#endif /* _UAPI_H8300_PTRACE_H */ diff --git a/arch/h8300/include/uapi/asm/sigcontext.h b/arch/h8300/include/uapi/asm/sigcontext.h deleted file mode 100644 index f77273c857d7..000000000000 --- a/arch/h8300/include/uapi/asm/sigcontext.h +++ /dev/null @@ -1,19 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _ASM_H8300_SIGCONTEXT_H -#define _ASM_H8300_SIGCONTEXT_H - -struct sigcontext { - unsigned long sc_mask; /* old sigmask */ - unsigned long sc_usp; /* old user stack pointer */ - unsigned long sc_er0; - unsigned long sc_er1; - unsigned long sc_er2; - unsigned long sc_er3; - unsigned long sc_er4; - unsigned long sc_er5; - unsigned long sc_er6; - unsigned short sc_ccr; - unsigned long sc_pc; -}; - -#endif diff --git a/arch/h8300/include/uapi/asm/signal.h b/arch/h8300/include/uapi/asm/signal.h deleted file mode 100644 index 2cd0dce2b6a6..000000000000 --- a/arch/h8300/include/uapi/asm/signal.h +++ /dev/null @@ -1,92 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef _UAPI_H8300_SIGNAL_H -#define _UAPI_H8300_SIGNAL_H - -#include - -/* Avoid too many header ordering problems. */ -struct siginfo; - -#ifndef __KERNEL__ -/* Here we must cater to libcs that poke about in kernel headers. */ - -#define NSIG 32 -typedef unsigned long sigset_t; - -#endif /* __KERNEL__ */ - -#define SIGHUP 1 -#define SIGINT 2 -#define SIGQUIT 3 -#define SIGILL 4 -#define SIGTRAP 5 -#define SIGABRT 6 -#define SIGIOT 6 -#define SIGBUS 7 -#define SIGFPE 8 -#define SIGKILL 9 -#define SIGUSR1 10 -#define SIGSEGV 11 -#define SIGUSR2 12 -#define SIGPIPE 13 -#define SIGALRM 14 -#define SIGTERM 15 -#define SIGSTKFLT 16 -#define SIGCHLD 17 -#define SIGCONT 18 -#define SIGSTOP 19 -#define SIGTSTP 20 -#define SIGTTIN 21 -#define SIGTTOU 22 -#define SIGURG 23 -#define SIGXCPU 24 -#define SIGXFSZ 25 -#define SIGVTALRM 26 -#define SIGPROF 27 -#define SIGWINCH 28 -#define SIGIO 29 -#define SIGPOLL SIGIO -/* -#define SIGLOST 29 -*/ -#define SIGPWR 30 -#define SIGSYS 31 -#define SIGUNUSED 31 - -/* These should not be considered constants from userland. */ -#define SIGRTMIN 32 -#define SIGRTMAX _NSIG - -#define SA_RESTORER 0x04000000 - -#define MINSIGSTKSZ 2048 -#define SIGSTKSZ 8192 - -#include - -#ifndef __KERNEL__ -/* Here we must cater to libcs that poke about in kernel headers. */ - -struct sigaction { - union { - __sighandler_t _sa_handler; - void (*_sa_sigaction)(int, struct siginfo *, void *); - } _u; - sigset_t sa_mask; - unsigned long sa_flags; - void (*sa_restorer)(void); -}; - -#define sa_handler _u._sa_handler -#define sa_sigaction _u._sa_sigaction - -#endif /* __KERNEL__ */ - -typedef struct sigaltstack { - void *ss_sp; - int ss_flags; - size_t ss_size; -} stack_t; - - -#endif /* _UAPI_H8300_SIGNAL_H */ diff --git a/arch/h8300/include/uapi/asm/unistd.h b/arch/h8300/include/uapi/asm/unistd.h deleted file mode 100644 index eb7bc0012af5..000000000000 --- a/arch/h8300/include/uapi/asm/unistd.h +++ /dev/null @@ -1,8 +0,0 @@ -#define __ARCH_NOMMU - -#define __ARCH_WANT_RENAMEAT -#define __ARCH_WANT_STAT64 -#define __ARCH_WANT_SET_GET_RLIMIT -#define __ARCH_WANT_TIME32_SYSCALLS - -#include diff --git a/arch/h8300/kernel/.gitignore b/arch/h8300/kernel/.gitignore deleted file mode 100644 index bbb90f92d051..000000000000 --- a/arch/h8300/kernel/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -vmlinux.lds diff --git a/arch/h8300/kernel/Makefile b/arch/h8300/kernel/Makefile deleted file mode 100644 index 307aa51576dd..000000000000 --- a/arch/h8300/kernel/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0 -# -# Makefile for the linux kernel. -# - -extra-y := vmlinux.lds - -obj-y := process.o traps.o ptrace.o \ - signal.o setup.o syscalls.o \ - irq.o entry.o - -obj-$(CONFIG_ROMKERNEL) += head_rom.o -obj-$(CONFIG_RAMKERNEL) += head_ram.o - -obj-$(CONFIG_MODULES) += module.o h8300_ksyms.o -obj-$(CONFIG_H8300H_SIM) += sim-console.o -obj-$(CONFIG_H8S_SIM) += sim-console.o - -obj-$(CONFIG_CPU_H8300H) += ptrace_h.o -obj-$(CONFIG_CPU_H8S) += ptrace_s.o - -obj-$(CONFIG_KGDB) += kgdb.o diff --git a/arch/h8300/kernel/asm-offsets.c b/arch/h8300/kernel/asm-offsets.c deleted file mode 100644 index 65571ee15132..000000000000 --- a/arch/h8300/kernel/asm-offsets.c +++ /dev/null @@ -1,70 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * This program is used to generate definitions needed by - * assembly language modules. - * - * We use the technique used in the OSF Mach kernel code: - * generate asm statements containing #defines, - * compile this file to assembler, and then extract the - * #defines from the assembly-language output. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -int main(void) -{ - /* offsets into the task struct */ - OFFSET(TASK_FLAGS, task_struct, flags); - OFFSET(TASK_PTRACE, task_struct, ptrace); - OFFSET(TASK_BLOCKED, task_struct, blocked); - OFFSET(TASK_THREAD, task_struct, thread); - OFFSET(TASK_THREAD_INFO, task_struct, stack); - OFFSET(TASK_MM, task_struct, mm); - OFFSET(TASK_ACTIVE_MM, task_struct, active_mm); - - /* offsets into the irq_cpustat_t struct */ - DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, - __softirq_pending)); - - /* offsets into the thread struct */ - OFFSET(THREAD_KSP, thread_struct, ksp); - OFFSET(THREAD_USP, thread_struct, usp); - OFFSET(THREAD_CCR, thread_struct, ccr); - - /* offsets into the pt_regs struct */ - DEFINE(LER0, offsetof(struct pt_regs, er0) - sizeof(long)); - DEFINE(LER1, offsetof(struct pt_regs, er1) - sizeof(long)); - DEFINE(LER2, offsetof(struct pt_regs, er2) - sizeof(long)); - DEFINE(LER3, offsetof(struct pt_regs, er3) - sizeof(long)); - DEFINE(LER4, offsetof(struct pt_regs, er4) - sizeof(long)); - DEFINE(LER5, offsetof(struct pt_regs, er5) - sizeof(long)); - DEFINE(LER6, offsetof(struct pt_regs, er6) - sizeof(long)); - DEFINE(LORIG, offsetof(struct pt_regs, orig_er0) - sizeof(long)); - DEFINE(LSP, offsetof(struct pt_regs, sp) - sizeof(long)); - DEFINE(LCCR, offsetof(struct pt_regs, ccr) - sizeof(long)); - DEFINE(LVEC, offsetof(struct pt_regs, vector) - sizeof(long)); -#if defined(CONFIG_CPU_H8S) - DEFINE(LEXR, offsetof(struct pt_regs, exr) - sizeof(long)); -#endif - DEFINE(LRET, offsetof(struct pt_regs, pc) - sizeof(long)); - - DEFINE(PT_PTRACED, PT_PTRACED); - - /* offsets in thread_info structure */ - OFFSET(TI_TASK, thread_info, task); - OFFSET(TI_FLAGS, thread_info, flags); - OFFSET(TI_CPU, thread_info, cpu); - OFFSET(TI_PRE, thread_info, preempt_count); -#ifdef CONFIG_PREEMPTION - DEFINE(TI_PRE_COUNT, offsetof(struct thread_info, preempt_count)); -#endif - - return 0; -} diff --git a/arch/h8300/kernel/entry.S b/arch/h8300/kernel/entry.S deleted file mode 100644 index c6e289b5f1f2..000000000000 --- a/arch/h8300/kernel/entry.S +++ /dev/null @@ -1,434 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * - * linux/arch/h8300/kernel/entry.S - * - * Yoshinori Sato - * David McCullough - * - */ - -/* - * entry.S - * include exception/interrupt gateway - * system call entry - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CPU_H8300H) -#define USERRET 8 -INTERRUPTS = 64 - .h8300h - .macro SHLL2 reg - shll.l \reg - shll.l \reg - .endm - .macro SHLR2 reg - shlr.l \reg - shlr.l \reg - .endm - .macro SAVEREGS - mov.l er0,@-sp - mov.l er1,@-sp - mov.l er2,@-sp - mov.l er3,@-sp - .endm - .macro RESTOREREGS - mov.l @sp+,er3 - mov.l @sp+,er2 - .endm - .macro SAVEEXR - .endm - .macro RESTOREEXR - .endm -#endif -#if defined(CONFIG_CPU_H8S) -#define USERRET 10 -#define USEREXR 8 -INTERRUPTS = 128 - .h8300s - .macro SHLL2 reg - shll.l #2,\reg - .endm - .macro SHLR2 reg - shlr.l #2,\reg - .endm - .macro SAVEREGS - stm.l er0-er3,@-sp - .endm - .macro RESTOREREGS - ldm.l @sp+,er2-er3 - .endm - .macro SAVEEXR - mov.w @(USEREXR:16,er0),r1 - mov.w r1,@(LEXR-LER3:16,sp) /* copy EXR */ - .endm - .macro RESTOREEXR - mov.w @(LEXR-LER1:16,sp),r1 /* restore EXR */ - mov.b r1l,r1h - mov.w r1,@(USEREXR:16,er0) - .endm -#endif - - -/* CPU context save/restore macros. */ - - .macro SAVE_ALL - mov.l er0,@-sp - stc ccr,r0l /* check kernel mode */ - btst #4,r0l - bne 5f - - /* user mode */ - mov.l sp,@_sw_usp - mov.l @sp,er0 /* restore saved er0 */ - orc #0x10,ccr /* switch kernel stack */ - mov.l @_sw_ksp,sp - sub.l #(LRET-LORIG),sp /* allocate LORIG - LRET */ - SAVEREGS - mov.l @_sw_usp,er0 - mov.l @(USERRET:16,er0),er1 /* copy the RET addr */ - mov.l er1,@(LRET-LER3:16,sp) - SAVEEXR - - mov.l @(LORIG-LER3:16,sp),er0 - mov.l er0,@(LER0-LER3:16,sp) /* copy ER0 */ - mov.w e1,r1 /* e1 highbyte = ccr */ - and #0xef,r1h /* mask mode? flag */ - bra 6f -5: - /* kernel mode */ - mov.l @sp,er0 /* restore saved er0 */ - subs #2,sp /* set dummy ccr */ - subs #4,sp /* set dummp sp */ - SAVEREGS - mov.w @(LRET-LER3:16,sp),r1 /* copy old ccr */ -6: - mov.b r1h,r1l - mov.b #0,r1h - mov.w r1,@(LCCR-LER3:16,sp) /* set ccr */ - mov.l @_sw_usp,er2 - mov.l er2,@(LSP-LER3:16,sp) /* set usp */ - mov.l er6,@-sp /* syscall arg #6 */ - mov.l er5,@-sp /* syscall arg #5 */ - mov.l er4,@-sp /* syscall arg #4 */ - .endm /* r1 = ccr */ - - .macro RESTORE_ALL - mov.l @sp+,er4 - mov.l @sp+,er5 - mov.l @sp+,er6 - RESTOREREGS - mov.w @(LCCR-LER1:16,sp),r0 /* check kernel mode */ - btst #4,r0l - bne 7f - - orc #0xc0,ccr - mov.l @(LSP-LER1:16,sp),er0 - mov.l @(LER0-LER1:16,sp),er1 /* restore ER0 */ - mov.l er1,@er0 - RESTOREEXR - mov.w @(LCCR-LER1:16,sp),r1 /* restore the RET addr */ - mov.b r1l,r1h - mov.b @(LRET+1-LER1:16,sp),r1l - mov.w r1,e1 - mov.w @(LRET+2-LER1:16,sp),r1 - mov.l er1,@(USERRET:16,er0) - - mov.l @sp+,er1 - add.l #(LRET-LER1),sp /* remove LORIG - LRET */ - mov.l sp,@_sw_ksp - andc #0xef,ccr /* switch to user mode */ - mov.l er0,sp - bra 8f -7: - mov.l @sp+,er1 - add.l #10,sp -8: - mov.l @sp+,er0 - adds #4,sp /* remove the sw created LVEC */ - rte - .endm - -.globl _system_call -.globl ret_from_exception -.globl ret_from_fork -.globl ret_from_kernel_thread -.globl ret_from_interrupt -.globl _interrupt_redirect_table -.globl _sw_ksp,_sw_usp -.globl _resume -.globl _interrupt_entry -.globl _trace_break -.globl _nmi - -#if defined(CONFIG_ROMKERNEL) - .section .int_redirect,"ax" -_interrupt_redirect_table: -#if defined(CONFIG_CPU_H8300H) - .rept 7 - .long 0 - .endr -#endif -#if defined(CONFIG_CPU_H8S) - .rept 5 - .long 0 - .endr - jmp @_trace_break - .long 0 -#endif - - jsr @_interrupt_entry /* NMI */ - jmp @_system_call /* TRAPA #0 (System call) */ - .long 0 -#if defined(CONFIG_KGDB) - jmp @_kgdb_trap -#else - .long 0 -#endif - jmp @_trace_break /* TRAPA #3 (breakpoint) */ - .rept INTERRUPTS-12 - jsr @_interrupt_entry - .endr -#endif -#if defined(CONFIG_RAMKERNEL) -.globl _interrupt_redirect_table - .section .bss -_interrupt_redirect_table: - .space 4 -#endif - - .section .text - .align 2 -_interrupt_entry: - SAVE_ALL -/* r1l is saved ccr */ - mov.l sp,er0 - add.l #LVEC,er0 - btst #4,r1l - bne 1f - /* user LVEC */ - mov.l @_sw_usp,er0 - adds #4,er0 -1: - mov.l @er0,er0 /* LVEC address */ -#if defined(CONFIG_ROMKERNEL) - sub.l #_interrupt_redirect_table,er0 -#endif -#if defined(CONFIG_RAMKERNEL) - mov.l @_interrupt_redirect_table,er1 - sub.l er1,er0 -#endif - SHLR2 er0 - dec.l #1,er0 - mov.l sp,er1 - subs #4,er1 /* adjust ret_pc */ -#if defined(CONFIG_CPU_H8S) - orc #7,exr -#endif - jsr @do_IRQ - jmp @ret_from_interrupt - -_system_call: - subs #4,sp /* dummy LVEC */ - SAVE_ALL - /* er0: syscall nr */ - andc #0xbf,ccr - mov.l er0,er4 - - /* save top of frame */ - mov.l sp,er0 - jsr @set_esp0 - andc #0x3f,ccr - mov.l sp,er2 - and.w #0xe000,r2 - mov.l @(TI_FLAGS:16,er2),er2 - and.w #_TIF_WORK_SYSCALL_MASK,r2 - beq 1f - mov.l sp,er0 - jsr @do_syscall_trace_enter -1: - cmp.l #__NR_syscalls,er4 - bcc badsys - SHLL2 er4 - mov.l #_sys_call_table,er0 - add.l er4,er0 - mov.l @er0,er4 - beq ret_from_exception:16 - mov.l @(LER1:16,sp),er0 - mov.l @(LER2:16,sp),er1 - mov.l @(LER3:16,sp),er2 - jsr @er4 - mov.l er0,@(LER0:16,sp) /* save the return value */ - mov.l sp,er2 - and.w #0xe000,r2 - mov.l @(TI_FLAGS:16,er2),er2 - and.w #_TIF_WORK_SYSCALL_MASK,r2 - beq 2f - mov.l sp,er0 - jsr @do_syscall_trace_leave -2: - orc #0xc0,ccr - bra resume_userspace - -badsys: - mov.l #-ENOSYS,er0 - mov.l er0,@(LER0:16,sp) - bra resume_userspace - -#if !defined(CONFIG_PREEMPTION) -#define resume_kernel restore_all -#endif - -ret_from_exception: -#if defined(CONFIG_PREEMPTION) - orc #0xc0,ccr -#endif -ret_from_interrupt: - mov.b @(LCCR+1:16,sp),r0l - btst #4,r0l - bne resume_kernel:16 /* return from kernel */ -resume_userspace: - andc #0xbf,ccr - mov.l sp,er4 - and.w #0xe000,r4 /* er4 <- current thread info */ - mov.l @(TI_FLAGS:16,er4),er1 - and.l #_TIF_WORK_MASK,er1 - beq restore_all:8 -work_pending: - btst #TIF_NEED_RESCHED,r1l - bne work_resched:8 - /* work notifysig */ - mov.l sp,er0 - subs #4,er0 /* er0: pt_regs */ - jsr @do_notify_resume - bra resume_userspace:8 -work_resched: - mov.l sp,er0 - jsr @set_esp0 - jsr @schedule - bra resume_userspace:8 -restore_all: - RESTORE_ALL /* Does RTE */ - -#if defined(CONFIG_PREEMPTION) -resume_kernel: - mov.l @(TI_PRE_COUNT:16,er4),er0 - bne restore_all:8 -need_resched: - mov.l @(TI_FLAGS:16,er4),er0 - btst #TIF_NEED_RESCHED,r0l - beq restore_all:8 - mov.b @(LCCR+1:16,sp),r0l /* Interrupt Enabled? */ - bmi restore_all:8 - mov.l sp,er0 - jsr @set_esp0 - jsr @preempt_schedule_irq - bra need_resched:8 -#endif - -ret_from_fork: - mov.l er2,er0 - jsr @schedule_tail - jmp @ret_from_exception - -ret_from_kernel_thread: - mov.l er2,er0 - jsr @schedule_tail - mov.l @(LER4:16,sp),er0 - mov.l @(LER5:16,sp),er1 - jsr @er1 - jmp @ret_from_exception - -_resume: - /* - * Beware - when entering resume, offset of tss is in d1, - * prev (the current task) is in a0, next (the new task) - * is in a1 and d2.b is non-zero if the mm structure is - * shared between the tasks, so don't change these - * registers until their contents are no longer needed. - */ - - /* save sr */ - sub.w r3,r3 - stc ccr,r3l - mov.w r3,@(THREAD_CCR+2:16,er0) - - /* disable interrupts */ - orc #0xc0,ccr - mov.l @_sw_usp,er3 - mov.l er3,@(THREAD_USP:16,er0) - mov.l sp,@(THREAD_KSP:16,er0) - - /* Skip address space switching if they are the same. */ - /* FIXME: what did we hack out of here, this does nothing! */ - - mov.l @(THREAD_USP:16,er1),er0 - mov.l er0,@_sw_usp - mov.l @(THREAD_KSP:16,er1),sp - - /* restore status register */ - mov.w @(THREAD_CCR+2:16,er1),r3 - - ldc r3l,ccr - rts - -_trace_break: - subs #4,sp - SAVE_ALL - sub.l er1,er1 - dec.l #1,er1 - mov.l er1,@(LORIG,sp) - mov.l sp,er0 - jsr @set_esp0 - mov.l @_sw_usp,er0 - mov.l @er0,er1 - mov.w @(-2:16,er1),r2 - cmp.w #0x5730,r2 - beq 1f - subs #2,er1 - mov.l er1,@er0 -1: - and.w #0xff,e1 - mov.l er1,er0 - jsr @trace_trap - jmp @ret_from_exception - -_nmi: - subs #4, sp - mov.l er0, @-sp - mov.l @_interrupt_redirect_table, er0 - add.l #8*4, er0 - mov.l er0, @(4,sp) - mov.l @sp+, er0 - jmp @_interrupt_entry - -#if defined(CONFIG_KGDB) -_kgdb_trap: - subs #4,sp - SAVE_ALL - mov.l sp,er0 - add.l #LRET,er0 - mov.l er0,@(LSP,sp) - jsr @set_esp0 - mov.l sp,er0 - subs #4,er0 - jsr @h8300_kgdb_trap - jmp @ret_from_exception -#endif - - .section .bss -_sw_ksp: - .space 4 -_sw_usp: - .space 4 - - .end diff --git a/arch/h8300/kernel/h8300_ksyms.c b/arch/h8300/kernel/h8300_ksyms.c deleted file mode 100644 index 853d6e886477..000000000000 --- a/arch/h8300/kernel/h8300_ksyms.c +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include - -/* - * libgcc functions - functions that are used internally by the - * compiler... (prototypes are not correct though, but that - * doesn't really matter since they're not versioned). - */ -asmlinkage long __ucmpdi2(long long, long long); -asmlinkage long long __ashldi3(long long, int); -asmlinkage long long __ashrdi3(long long, int); -asmlinkage long long __lshrdi3(long long, int); -asmlinkage long __divsi3(long, long); -asmlinkage long __modsi3(long, long); -asmlinkage unsigned long __umodsi3(unsigned long, unsigned long); -asmlinkage long long __muldi3(long long, long long); -asmlinkage long __mulsi3(long, long); -asmlinkage long __udivsi3(long, long); -asmlinkage void *memcpy(void *, const void *, size_t); -asmlinkage void *memset(void *, int, size_t); - - /* gcc lib functions */ -EXPORT_SYMBOL(__ucmpdi2); -EXPORT_SYMBOL(__ashldi3); -EXPORT_SYMBOL(__ashrdi3); -EXPORT_SYMBOL(__lshrdi3); -EXPORT_SYMBOL(__divsi3); -EXPORT_SYMBOL(__modsi3); -EXPORT_SYMBOL(__umodsi3); -EXPORT_SYMBOL(__muldi3); -EXPORT_SYMBOL(__mulsi3); -EXPORT_SYMBOL(__udivsi3); -EXPORT_SYMBOL(memcpy); -EXPORT_SYMBOL(memset); diff --git a/arch/h8300/kernel/head_ram.S b/arch/h8300/kernel/head_ram.S deleted file mode 100644 index dbf8429f5fab..000000000000 --- a/arch/h8300/kernel/head_ram.S +++ /dev/null @@ -1,61 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_CPU_H8300H) - .h8300h -#define SYSCR 0xfee012 -#define IRAMTOP 0xffff20 -#endif -#if defined(CONFIG_CPU_H8S) - .h8300s -#define INTCR 0xffff31 -#define IRAMTOP 0xffc000 -#endif - - __HEAD - .global _start -_start: - mov.l #IRAMTOP,sp - /* .bss clear */ - mov.l #_sbss,er5 - mov.l #_ebss,er4 - sub.l er5,er4 - shlr er4 - shlr er4 - sub.l er2,er2 -1: - mov.l er2,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b - jsr @h8300_fdt_init - - /* linux kernel start */ -#if defined(CONFIG_CPU_H8300H) - ldc #0xd0,ccr /* running kernel */ - mov.l #SYSCR,er0 - bclr #3,@er0 -#endif -#if defined(CONFIG_CPU_H8S) - ldc #0x07,exr - bclr #4,@INTCR:8 - bset #5,@INTCR:8 /* Interrupt mode 2 */ - ldc #0x90,ccr /* running kernel */ -#endif - mov.l #init_thread_union,sp - add.l #0x2000,sp - jsr @start_kernel - -1: - bra 1b - - .end diff --git a/arch/h8300/kernel/head_rom.S b/arch/h8300/kernel/head_rom.S deleted file mode 100644 index ab55a9cb2f36..000000000000 --- a/arch/h8300/kernel/head_rom.S +++ /dev/null @@ -1,111 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include -#include - -#if defined(CONFIG_CPU_H8300H) - .h8300h -#define SYSCR 0xfee012 -#define IRAMTOP 0xffff20 -#define NR_INT 64 -#endif -#if defined(CONFIG_CPU_H8S) - .h8300s -#define INTCR 0xffff31 -#define IRAMTOP 0xffc000 -#define NR_INT 128 -#endif - - __HEAD - .global _start -_start: - mov.l #IRAMTOP,sp -#if !defined(CONFIG_H8300H_SIM) && \ - !defined(CONFIG_H8S_SIM) - jsr @lowlevel_init - - /* copy .data */ - mov.l #_begin_data,er5 - mov.l #_sdata,er6 - mov.l #_edata,er4 - sub.l er6,er4 - shlr.l er4 - shlr.l er4 -1: - mov.l @er5+,er0 - mov.l er0,@er6 - adds #4,er6 - dec.l #1,er4 - bne 1b - /* .bss clear */ - mov.l #_sbss,er5 - mov.l #_ebss,er4 - sub.l er5,er4 - shlr er4 - shlr er4 - sub.l er0,er0 -1: - mov.l er0,@er5 - adds #4,er5 - dec.l #1,er4 - bne 1b -#else - /* get cmdline from gdb */ - jsr @0xcc - ;; er0 - argc - ;; er1 - argv - mov.l #command_line,er3 - adds #4,er1 - dec.l #1,er0 - beq 4f -1: - mov.l @er1+,er2 -2: - mov.b @er2+,r4l - beq 3f - mov.b r4l,@er3 - adds #1,er3 - bra 2b -3: - mov.b #' ',r4l - mov.b r4l,@er3 - adds #1,er3 - dec.l #1,er0 - bne 1b - subs #1,er3 - mov.b #0,r4l - mov.b r4l,@er3 -4: -#endif - sub.l er0,er0 - jsr @h8300_fdt_init - /* linux kernel start */ -#if defined(CONFIG_CPU_H8300H) - ldc #0xd0,ccr /* running kernel */ - mov.l #SYSCR,er0 - bclr #3,@er0 -#endif -#if defined(CONFIG_CPU_H8S) - ldc #0x07,exr - bclr #4,@INTCR:8 - bset #5,@INTCR:8 /* Interrupt mode 2 */ - ldc #0x90,ccr /* running kernel */ -#endif - mov.l #init_thread_union,sp - add.l #0x2000,sp - jsr @start_kernel - -1: - bra 1b - -#if defined(CONFIG_ROMKERNEL) - /* interrupt vector */ - .section .vectors,"ax" - .long _start - .long _start -vector = 2 - .rept NR_INT - 2 - .long _interrupt_redirect_table+vector*4 -vector = vector + 1 - .endr -#endif - .end diff --git a/arch/h8300/kernel/irq.c b/arch/h8300/kernel/irq.c deleted file mode 100644 index 8ad6d702cd0b..000000000000 --- a/arch/h8300/kernel/irq.c +++ /dev/null @@ -1,99 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/h8300/kernel/irq.c - * - * Copyright 2014-2015 Yoshinori Sato - */ - -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_RAMKERNEL -typedef void (*h8300_vector)(void); - -static const h8300_vector __initconst trap_table[] = { - 0, 0, 0, 0, - _trace_break, - 0, 0, - _nmi, - _system_call, - 0, 0, - _trace_break, -}; - -static unsigned long __init *get_vector_address(void) -{ - unsigned long *rom_vector = CPU_VECTOR; - unsigned long base, tmp; - int vec_no; - - base = rom_vector[EXT_IRQ0] & ADDR_MASK; - - /* check romvector format */ - for (vec_no = EXT_IRQ0 + 1; vec_no <= EXT_IRQ0+EXT_IRQS; vec_no++) { - if ((base+(vec_no - EXT_IRQ0)*4) != - (rom_vector[vec_no] & ADDR_MASK)) - return NULL; - } - - /* ramvector base address */ - base -= EXT_IRQ0*4; - - /* writerble? */ - tmp = ~(*(volatile unsigned long *)base); - (*(volatile unsigned long *)base) = tmp; - if ((*(volatile unsigned long *)base) != tmp) - return NULL; - return (unsigned long *)base; -} - -static void __init setup_vector(void) -{ - int i; - unsigned long *ramvec, *ramvec_p; - const h8300_vector *trap_entry; - - ramvec = get_vector_address(); - if (ramvec == NULL) - panic("interrupt vector serup failed."); - else - pr_debug("virtual vector at 0x%p\n", ramvec); - - /* create redirect table */ - ramvec_p = ramvec; - trap_entry = trap_table; - for (i = 0; i < NR_IRQS; i++) { - if (i < 12) { - if (*trap_entry) - *ramvec_p = VECTOR(*trap_entry); - ramvec_p++; - trap_entry++; - } else - *ramvec_p++ = REDIRECT(_interrupt_entry); - } - _interrupt_redirect_table = ramvec; -} -#else -void setup_vector(void) -{ - /* noting do */ -} -#endif - -void __init init_IRQ(void) -{ - setup_vector(); - irqchip_init(); -} - -asmlinkage void do_IRQ(int irq) -{ - irq_enter(); - generic_handle_irq(irq); - irq_exit(); -} diff --git a/arch/h8300/kernel/kgdb.c b/arch/h8300/kernel/kgdb.c deleted file mode 100644 index 602e478afbd5..000000000000 --- a/arch/h8300/kernel/kgdb.c +++ /dev/null @@ -1,135 +0,0 @@ -/* - * H8/300 KGDB support - * - * Copyright (C) 2015 Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include - -struct dbg_reg_def_t dbg_reg_def[DBG_MAX_REG_NUM] = { - { "er0", GDB_SIZEOF_REG, offsetof(struct pt_regs, er0) }, - { "er1", GDB_SIZEOF_REG, offsetof(struct pt_regs, er1) }, - { "er2", GDB_SIZEOF_REG, offsetof(struct pt_regs, er2) }, - { "er3", GDB_SIZEOF_REG, offsetof(struct pt_regs, er3) }, - { "er4", GDB_SIZEOF_REG, offsetof(struct pt_regs, er4) }, - { "er5", GDB_SIZEOF_REG, offsetof(struct pt_regs, er5) }, - { "er6", GDB_SIZEOF_REG, offsetof(struct pt_regs, er6) }, - { "sp", GDB_SIZEOF_REG, offsetof(struct pt_regs, sp) }, - { "ccr", GDB_SIZEOF_REG, offsetof(struct pt_regs, ccr) }, - { "pc", GDB_SIZEOF_REG, offsetof(struct pt_regs, pc) }, - { "cycles", GDB_SIZEOF_REG, -1 }, -#if defined(CONFIG_CPU_H8S) - { "exr", GDB_SIZEOF_REG, offsetof(struct pt_regs, exr) }, -#endif - { "tick", GDB_SIZEOF_REG, -1 }, - { "inst", GDB_SIZEOF_REG, -1 }, -}; - -char *dbg_get_reg(int regno, void *mem, struct pt_regs *regs) -{ - if (regno >= DBG_MAX_REG_NUM || regno < 0) - return NULL; - - switch (regno) { - case GDB_CCR: -#if defined(CONFIG_CPU_H8S) - case GDB_EXR: -#endif - *(u32 *)mem = *(u16 *)((void *)regs + - dbg_reg_def[regno].offset); - break; - default: - if (dbg_reg_def[regno].offset >= 0) - memcpy(mem, (void *)regs + dbg_reg_def[regno].offset, - dbg_reg_def[regno].size); - else - memset(mem, 0, dbg_reg_def[regno].size); - break; - } - return dbg_reg_def[regno].name; -} - -int dbg_set_reg(int regno, void *mem, struct pt_regs *regs) -{ - if (regno >= DBG_MAX_REG_NUM || regno < 0) - return -EINVAL; - - switch (regno) { - case GDB_CCR: -#if defined(CONFIG_CPU_H8S) - case GDB_EXR: -#endif - *(u16 *)((void *)regs + - dbg_reg_def[regno].offset) = *(u32 *)mem; - break; - default: - memcpy((void *)regs + dbg_reg_def[regno].offset, mem, - dbg_reg_def[regno].size); - } - return 0; -} - -asmlinkage void h8300_kgdb_trap(struct pt_regs *regs) -{ - regs->pc &= 0x00ffffff; - if (kgdb_handle_exception(10, SIGTRAP, 0, regs)) - return; - if (*(u16 *)(regs->pc) == *(u16 *)&arch_kgdb_ops.gdb_bpt_instr) - regs->pc += BREAK_INSTR_SIZE; - regs->pc |= regs->ccr << 24; -} - -void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p) -{ - memset((char *)gdb_regs, 0, NUMREGBYTES); - gdb_regs[GDB_SP] = p->thread.ksp; - gdb_regs[GDB_PC] = KSTK_EIP(p); -} - -void kgdb_arch_set_pc(struct pt_regs *regs, unsigned long pc) -{ - regs->pc = pc; -} - -int kgdb_arch_handle_exception(int vector, int signo, int err_code, - char *remcom_in_buffer, char *remcom_out_buffer, - struct pt_regs *regs) -{ - char *ptr; - unsigned long addr; - - switch (remcom_in_buffer[0]) { - case 's': - case 'c': - /* handle the optional parameters */ - ptr = &remcom_in_buffer[1]; - if (kgdb_hex2long(&ptr, &addr)) - regs->pc = addr; - - return 0; - } - - return -1; /* this means that we do not want to exit from the handler */ -} - -int kgdb_arch_init(void) -{ - return 0; -} - -void kgdb_arch_exit(void) -{ - /* Nothing to do */ -} - -const struct kgdb_arch arch_kgdb_ops = { - /* Breakpoint instruction: trapa #2 */ - .gdb_bpt_instr = { 0x57, 0x20 }, -}; diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c deleted file mode 100644 index cd802cc78d97..000000000000 --- a/arch/h8300/kernel/module.c +++ /dev/null @@ -1,71 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include -#include -#include -#include - -int apply_relocate_add(Elf32_Shdr *sechdrs, - const char *strtab, - unsigned int symindex, - unsigned int relsec, - struct module *me) -{ - unsigned int i; - Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; - - pr_debug("Applying relocate section %u to %u\n", relsec, - sechdrs[relsec].sh_info); - for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { - /* This is where to make the change */ - uint32_t *loc = - (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr - + rela[i].r_offset); - /* This is the symbol it is referring to. Note that all - undefined symbols have been resolved. */ - Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr - + ELF32_R_SYM(rela[i].r_info); - uint32_t v = sym->st_value + rela[i].r_addend; - - switch (ELF32_R_TYPE(rela[i].r_info)) { - case R_H8_DIR24R8: - loc = (uint32_t *)((uint32_t)loc - 1); - *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v); - break; - case R_H8_DIR24A8: - if (ELF32_R_SYM(rela[i].r_info)) - *loc += v; - break; - case R_H8_DIR32: - case R_H8_DIR32A16: - *loc += v; - break; - case R_H8_PCREL16: - v -= (unsigned long)loc + 2; - if ((Elf32_Sword)v > 0x7fff || - (Elf32_Sword)v < -(Elf32_Sword)0x8000) - goto overflow; - else - *(unsigned short *)loc = v; - break; - case R_H8_PCREL8: - v -= (unsigned long)loc + 1; - if ((Elf32_Sword)v > 0x7f || - (Elf32_Sword)v < -(Elf32_Sword)0x80) - goto overflow; - else - *(unsigned char *)loc = v; - break; - default: - pr_err("module %s: Unknown relocation: %u\n", - me->name, ELF32_R_TYPE(rela[i].r_info)); - return -ENOEXEC; - } - } - return 0; - overflow: - pr_err("module %s: relocation offset overflow: %08x\n", - me->name, rela[i].r_offset); - return -ENOEXEC; -} diff --git a/arch/h8300/kernel/process.c b/arch/h8300/kernel/process.c deleted file mode 100644 index 8833fa4f5d51..000000000000 --- a/arch/h8300/kernel/process.c +++ /dev/null @@ -1,173 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/h8300/kernel/process.c - * - * Yoshinori Sato - * - * Based on: - * - * linux/arch/m68knommu/kernel/process.c - * - * Copyright (C) 1998 D. Jeff Dionne , - * Kenneth Albanowski , - * The Silver Hammer Group, Ltd. - * - * linux/arch/m68k/kernel/process.c - * - * Copyright (C) 1995 Hamish Macdonald - * - * 68060 fixes by Jesper Skov - */ - -/* - * This file handles the architecture-dependent parts of process handling.. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -void (*pm_power_off)(void) = NULL; -EXPORT_SYMBOL(pm_power_off); - -asmlinkage void ret_from_fork(void); -asmlinkage void ret_from_kernel_thread(void); - -/* - * The idle loop on an H8/300.. - */ -void arch_cpu_idle(void) -{ - raw_local_irq_enable(); - __asm__("sleep"); -} - -void machine_restart(char *__unused) -{ - local_irq_disable(); - __asm__("jmp @@0"); -} - -void machine_halt(void) -{ - local_irq_disable(); - __asm__("sleep"); - for (;;) - ; -} - -void machine_power_off(void) -{ - local_irq_disable(); - __asm__("sleep"); - for (;;) - ; -} - -void show_regs(struct pt_regs *regs) -{ - show_regs_print_info(KERN_DEFAULT); - - pr_notice("\n"); - pr_notice("PC: %08lx Status: %02x\n", - regs->pc, regs->ccr); - pr_notice("ORIG_ER0: %08lx ER0: %08lx ER1: %08lx\n", - regs->orig_er0, regs->er0, regs->er1); - pr_notice("ER2: %08lx ER3: %08lx ER4: %08lx ER5: %08lx\n", - regs->er2, regs->er3, regs->er4, regs->er5); - pr_notice("ER6' %08lx ", regs->er6); - if (user_mode(regs)) - printk("USP: %08lx\n", rdusp()); - else - printk("\n"); -} - -void flush_thread(void) -{ -} - -int copy_thread(unsigned long clone_flags, unsigned long usp, - unsigned long topstk, struct task_struct *p, unsigned long tls) -{ - struct pt_regs *childregs; - - childregs = (struct pt_regs *) (THREAD_SIZE + task_stack_page(p)) - 1; - - if (unlikely(p->flags & (PF_KTHREAD | PF_IO_WORKER))) { - memset(childregs, 0, sizeof(struct pt_regs)); - childregs->retpc = (unsigned long) ret_from_kernel_thread; - childregs->er4 = topstk; /* arg */ - childregs->er5 = usp; /* fn */ - } else { - *childregs = *current_pt_regs(); - childregs->er0 = 0; - childregs->retpc = (unsigned long) ret_from_fork; - p->thread.usp = usp ?: rdusp(); - } - p->thread.ksp = (unsigned long)childregs; - - return 0; -} - -unsigned long __get_wchan(struct task_struct *p) -{ - unsigned long fp, pc; - unsigned long stack_page; - int count = 0; - - stack_page = (unsigned long)p; - fp = ((struct pt_regs *)p->thread.ksp)->er6; - do { - if (fp < stack_page+sizeof(struct thread_info) || - fp >= 8184+stack_page) - return 0; - pc = ((unsigned long *)fp)[1]; - if (!in_sched_functions(pc)) - return pc; - fp = *(unsigned long *) fp; - } while (count++ < 16); - return 0; -} - -/* generic sys_clone is not enough registers */ -asmlinkage int sys_clone(unsigned long __user *args) -{ - unsigned long clone_flags; - unsigned long newsp; - uintptr_t parent_tidptr; - uintptr_t child_tidptr; - struct kernel_clone_args kargs = {}; - - get_user(clone_flags, &args[0]); - get_user(newsp, &args[1]); - get_user(parent_tidptr, &args[2]); - get_user(child_tidptr, &args[3]); - - kargs.flags = (lower_32_bits(clone_flags) & ~CSIGNAL); - kargs.pidfd = (int __user *)parent_tidptr; - kargs.child_tid = (int __user *)child_tidptr; - kargs.parent_tid = (int __user *)parent_tidptr; - kargs.exit_signal = (lower_32_bits(clone_flags) & CSIGNAL); - kargs.stack = newsp; - - return kernel_clone(&kargs); -} diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c deleted file mode 100644 index a11db009d0ea..000000000000 --- a/arch/h8300/kernel/ptrace.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * linux/arch/h8300/kernel/ptrace.c - * - * Copyright 2015 Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of - * this archive for more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define CCR_MASK 0x6f /* mode/imask not set */ -#define EXR_MASK 0x80 /* modify only T */ - -#define PT_REG(r) offsetof(struct pt_regs, r) - -extern void user_disable_single_step(struct task_struct *child); - -/* Mapping from PT_xxx to the stack offset at which the register is - saved. Notice that usp has no stack-slot and needs to be treated - specially (see get_reg/put_reg below). */ -static const int register_offset[] = { - PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4), - PT_REG(er5), PT_REG(er6), PT_REG(er0), -1, - PT_REG(orig_er0), PT_REG(ccr), PT_REG(pc), -#if defined(CONFIG_CPU_H8S) - PT_REG(exr), -#endif -}; - -/* read register */ -long h8300_get_reg(struct task_struct *task, int regno) -{ - switch (regno) { - case PT_USP: - return task->thread.usp + sizeof(long)*2; - case PT_CCR: - case PT_EXR: - return *(unsigned short *)(task->thread.esp0 + - register_offset[regno]); - default: - return *(unsigned long *)(task->thread.esp0 + - register_offset[regno]); - } -} - -int h8300_put_reg(struct task_struct *task, int regno, unsigned long data) -{ - unsigned short oldccr; - unsigned short oldexr; - - switch (regno) { - case PT_USP: - task->thread.usp = data - sizeof(long)*2; - case PT_CCR: - oldccr = *(unsigned short *)(task->thread.esp0 + - register_offset[regno]); - oldccr &= ~CCR_MASK; - data &= CCR_MASK; - data |= oldccr; - *(unsigned short *)(task->thread.esp0 + - register_offset[regno]) = data; - break; - case PT_EXR: - oldexr = *(unsigned short *)(task->thread.esp0 + - register_offset[regno]); - oldccr &= ~EXR_MASK; - data &= EXR_MASK; - data |= oldexr; - *(unsigned short *)(task->thread.esp0 + - register_offset[regno]) = data; - break; - default: - *(unsigned long *)(task->thread.esp0 + - register_offset[regno]) = data; - break; - } - return 0; -} - -static int regs_get(struct task_struct *target, - const struct user_regset *regset, - struct membuf to) -{ - int r; - - BUILD_BUG_ON(sizeof(struct user_regs_struct) % sizeof(long) != 0); - for (r = 0; r < ELF_NGREG; r++) - membuf_store(&to, h8300_get_reg(target, r)); - - return 0; -} - -static int regs_set(struct task_struct *target, - const struct user_regset *regset, - unsigned int pos, unsigned int count, - const void *kbuf, const void __user *ubuf) -{ - int r; - int ret; - struct user_regs_struct regs; - long *reg; - - /* build user regs in buffer */ - BUILD_BUG_ON(sizeof(regs) % sizeof(long) != 0); - for (reg = (long *)®s, r = 0; r < sizeof(regs) / sizeof(long); r++) - *reg++ = h8300_get_reg(target, r); - - ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, - ®s, 0, sizeof(regs)); - if (ret) - return ret; - - /* write back to pt_regs */ - for (reg = (long *)®s, r = 0; r < sizeof(regs) / sizeof(long); r++) - h8300_put_reg(target, r, *reg++); - return 0; -} - -enum h8300_regset { - REGSET_GENERAL, -}; - -static const struct user_regset h8300_regsets[] = { - [REGSET_GENERAL] = { - .core_note_type = NT_PRSTATUS, - .n = ELF_NGREG, - .size = sizeof(long), - .align = sizeof(long), - .regset_get = regs_get, - .set = regs_set, - }, -}; - -static const struct user_regset_view user_h8300_native_view = { - .name = "h8300", - .e_machine = EM_H8_300, - .regsets = h8300_regsets, - .n = ARRAY_SIZE(h8300_regsets), -}; - -const struct user_regset_view *task_user_regset_view(struct task_struct *task) -{ - return &user_h8300_native_view; -} - -void ptrace_disable(struct task_struct *child) -{ - user_disable_single_step(child); -} - -long arch_ptrace(struct task_struct *child, long request, - unsigned long addr, unsigned long data) -{ - int ret; - - switch (request) { - default: - ret = ptrace_request(child, request, addr, data); - break; - } - return ret; -} - -asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) -{ - long ret = 0; - - if (test_thread_flag(TIF_SYSCALL_TRACE) && - tracehook_report_syscall_entry(regs)) - /* - * Tracing decided this syscall should not happen. - * We'll return a bogus call number to get an ENOSYS - * error, but leave the original number in regs->regs[0]. - */ - ret = -1L; - - audit_syscall_entry(regs->er1, regs->er2, regs->er3, - regs->er4, regs->er5); - - return ret ?: regs->er0; -} - -asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) -{ - int step; - - audit_syscall_exit(regs); - - step = test_thread_flag(TIF_SINGLESTEP); - if (step || test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, step); -} diff --git a/arch/h8300/kernel/ptrace_h.c b/arch/h8300/kernel/ptrace_h.c deleted file mode 100644 index 15db45a03b04..000000000000 --- a/arch/h8300/kernel/ptrace_h.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * ptrace cpu depend helper functions - * - * Copyright 2003, 2015 Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of - * this archive for more details. - */ - -#include -#include -#include - -#define BREAKINST 0x5730 /* trapa #3 */ - -/* disable singlestep */ -void user_disable_single_step(struct task_struct *child) -{ - if ((long)child->thread.breakinfo.addr != -1L) { - *(child->thread.breakinfo.addr) = child->thread.breakinfo.inst; - child->thread.breakinfo.addr = (unsigned short *)-1L; - } -} - -/* calculate next pc */ -enum jump_type {none, /* normal instruction */ - jabs, /* absolute address jump */ - ind, /* indirect address jump */ - ret, /* return to subrutine */ - reg, /* register indexed jump */ - relb, /* pc relative jump (byte offset) */ - relw, /* pc relative jump (word offset) */ - }; - -/* opcode decode table define - ptn: opcode pattern - msk: opcode bitmask - len: instruction length (<0 next table index) - jmp: jump operation mode */ -struct optable { - unsigned char bitpattern; - unsigned char bitmask; - signed char length; - signed char type; -} __packed __aligned(1); - -#define OPTABLE(ptn, msk, len, jmp) \ - { \ - .bitpattern = ptn, \ - .bitmask = msk, \ - .length = len, \ - .type = jmp, \ - } - -static const struct optable optable_0[] = { - OPTABLE(0x00, 0xff, 1, none), /* 0x00 */ - OPTABLE(0x01, 0xff, -1, none), /* 0x01 */ - OPTABLE(0x02, 0xfe, 1, none), /* 0x02-0x03 */ - OPTABLE(0x04, 0xee, 1, none), /* 0x04-0x05/0x14-0x15 */ - OPTABLE(0x06, 0xfe, 1, none), /* 0x06-0x07 */ - OPTABLE(0x08, 0xea, 1, none), /* 0x08-0x09/0x0c-0x0d/0x18-0x19/0x1c-0x1d */ - OPTABLE(0x0a, 0xee, 1, none), /* 0x0a-0x0b/0x1a-0x1b */ - OPTABLE(0x0e, 0xee, 1, none), /* 0x0e-0x0f/0x1e-0x1f */ - OPTABLE(0x10, 0xfc, 1, none), /* 0x10-0x13 */ - OPTABLE(0x16, 0xfe, 1, none), /* 0x16-0x17 */ - OPTABLE(0x20, 0xe0, 1, none), /* 0x20-0x3f */ - OPTABLE(0x40, 0xf0, 1, relb), /* 0x40-0x4f */ - OPTABLE(0x50, 0xfc, 1, none), /* 0x50-0x53 */ - OPTABLE(0x54, 0xfd, 1, ret), /* 0x54/0x56 */ - OPTABLE(0x55, 0xff, 1, relb), /* 0x55 */ - OPTABLE(0x57, 0xff, 1, none), /* 0x57 */ - OPTABLE(0x58, 0xfb, 2, relw), /* 0x58/0x5c */ - OPTABLE(0x59, 0xfb, 1, reg), /* 0x59/0x5b */ - OPTABLE(0x5a, 0xfb, 2, jabs), /* 0x5a/0x5e */ - OPTABLE(0x5b, 0xfb, 2, ind), /* 0x5b/0x5f */ - OPTABLE(0x60, 0xe8, 1, none), /* 0x60-0x67/0x70-0x77 */ - OPTABLE(0x68, 0xfa, 1, none), /* 0x68-0x69/0x6c-0x6d */ - OPTABLE(0x6a, 0xfe, -2, none), /* 0x6a-0x6b */ - OPTABLE(0x6e, 0xfe, 2, none), /* 0x6e-0x6f */ - OPTABLE(0x78, 0xff, 4, none), /* 0x78 */ - OPTABLE(0x79, 0xff, 2, none), /* 0x79 */ - OPTABLE(0x7a, 0xff, 3, none), /* 0x7a */ - OPTABLE(0x7b, 0xff, 2, none), /* 0x7b */ - OPTABLE(0x7c, 0xfc, 2, none), /* 0x7c-0x7f */ - OPTABLE(0x80, 0x80, 1, none), /* 0x80-0xff */ -}; - -static const struct optable optable_1[] = { - OPTABLE(0x00, 0xff, -3, none), /* 0x0100 */ - OPTABLE(0x40, 0xf0, -3, none), /* 0x0140-0x14f */ - OPTABLE(0x80, 0xf0, 1, none), /* 0x0180-0x018f */ - OPTABLE(0xc0, 0xc0, 2, none), /* 0x01c0-0x01ff */ -}; - -static const struct optable optable_2[] = { - OPTABLE(0x00, 0x20, 2, none), /* 0x6a0?/0x6a8?/0x6b0?/0x6b8? */ - OPTABLE(0x20, 0x20, 3, none), /* 0x6a2?/0x6aa?/0x6b2?/0x6ba? */ -}; - -static const struct optable optable_3[] = { - OPTABLE(0x69, 0xfb, 2, none), /* 0x010069/0x01006d/014069/0x01406d */ - OPTABLE(0x6b, 0xff, -4, none), /* 0x01006b/0x01406b */ - OPTABLE(0x6f, 0xff, 3, none), /* 0x01006f/0x01406f */ - OPTABLE(0x78, 0xff, 5, none), /* 0x010078/0x014078 */ -}; - -static const struct optable optable_4[] = { -/* 0x0100690?/0x01006d0?/0140690?/0x01406d0?/ - 0x0100698?/0x01006d8?/0140698?/0x01406d8? */ - OPTABLE(0x00, 0x78, 3, none), -/* 0x0100692?/0x01006d2?/0140692?/0x01406d2?/ - 0x010069a?/0x01006da?/014069a?/0x01406da? */ - OPTABLE(0x20, 0x78, 4, none), -}; - -static const struct optables_list { - const struct optable *ptr; - int size; -} optables[] = { -#define OPTABLES(no) \ - { \ - .ptr = optable_##no, \ - .size = sizeof(optable_##no) / sizeof(struct optable), \ - } - OPTABLES(0), - OPTABLES(1), - OPTABLES(2), - OPTABLES(3), - OPTABLES(4), - -}; - -const unsigned char condmask[] = { - 0x00, 0x40, 0x01, 0x04, 0x02, 0x08, 0x10, 0x20 -}; - -static int isbranch(struct task_struct *task, int reson) -{ - unsigned char cond = h8300_get_reg(task, PT_CCR); - - /* encode complex conditions */ - /* B4: N^V - B5: Z|(N^V) - B6: C|Z */ - __asm__("bld #3,%w0\n\t" - "bxor #1,%w0\n\t" - "bst #4,%w0\n\t" - "bor #2,%w0\n\t" - "bst #5,%w0\n\t" - "bld #2,%w0\n\t" - "bor #0,%w0\n\t" - "bst #6,%w0\n\t" - : "=&r"(cond) : "0"(cond) : "cc"); - cond &= condmask[reson >> 1]; - if (!(reson & 1)) - return cond == 0; - else - return cond != 0; -} - -static unsigned short *decode(struct task_struct *child, - const struct optable *op, - char *fetch_p, unsigned short *pc, - unsigned char inst) -{ - unsigned long addr; - unsigned long *sp; - int regno; - - switch (op->type) { - case none: - return (unsigned short *)pc + op->length; - case jabs: - addr = *(unsigned long *)pc; - return (unsigned short *)(addr & 0x00ffffff); - case ind: - addr = *pc & 0xff; - return (unsigned short *)(*(unsigned long *)addr); - case ret: - sp = (unsigned long *)h8300_get_reg(child, PT_USP); - /* user stack frames - | er0 | temporary saved - +--------+ - | exp | exception stack frames - +--------+ - | ret pc | userspace return address - */ - return (unsigned short *)(*(sp+2) & 0x00ffffff); - case reg: - regno = (*pc >> 4) & 0x07; - if (regno == 0) - addr = h8300_get_reg(child, PT_ER0); - else - addr = h8300_get_reg(child, regno-1 + PT_ER1); - return (unsigned short *)addr; - case relb: - if (inst == 0x55 || isbranch(child, inst & 0x0f)) - pc = (unsigned short *)((unsigned long)pc + - ((signed char)(*fetch_p))); - return pc+1; /* skip myself */ - case relw: - if (inst == 0x5c || isbranch(child, (*fetch_p & 0xf0) >> 4)) - pc = (unsigned short *)((unsigned long)pc + - ((signed short)(*(pc+1)))); - return pc+2; /* skip myself */ - default: - return NULL; - } -} - -static unsigned short *nextpc(struct task_struct *child, unsigned short *pc) -{ - const struct optable *op; - unsigned char *fetch_p; - int op_len; - unsigned char inst; - - op = optables[0].ptr; - op_len = optables[0].size; - fetch_p = (unsigned char *)pc; - inst = *fetch_p++; - do { - if ((inst & op->bitmask) == op->bitpattern) { - if (op->length < 0) { - op = optables[-op->length].ptr; - op_len = optables[-op->length].size + 1; - inst = *fetch_p++; - } else - return decode(child, op, fetch_p, pc, inst); - } else - op++; - } while (--op_len > 0); - return NULL; -} - -/* Set breakpoint(s) to simulate a single step from the current PC. */ - -void user_enable_single_step(struct task_struct *child) -{ - unsigned short *next; - - next = nextpc(child, (unsigned short *)h8300_get_reg(child, PT_PC)); - child->thread.breakinfo.addr = next; - child->thread.breakinfo.inst = *next; - *next = BREAKINST; -} - -asmlinkage void trace_trap(unsigned long bp) -{ - if ((unsigned long)current->thread.breakinfo.addr == bp) { - user_disable_single_step(current); - force_sig(SIGTRAP); - } else - force_sig(SIGILL); -} diff --git a/arch/h8300/kernel/ptrace_s.c b/arch/h8300/kernel/ptrace_s.c deleted file mode 100644 index ee21f37b7ed4..000000000000 --- a/arch/h8300/kernel/ptrace_s.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * linux/arch/h8300/kernel/ptrace_h8s.c - * ptrace cpu depend helper functions - * - * Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General - * Public License. See the file COPYING in the main directory of - * this archive for more details. - */ - -#include -#include -#include -#include - -#define CCR_MASK 0x6f -#define EXR_TRACE 0x80 - -/* disable singlestep */ -void user_disable_single_step(struct task_struct *child) -{ - unsigned char exr; - - exr = h8300_get_reg(child, PT_EXR); - exr &= ~EXR_TRACE; - h8300_put_reg(child, PT_EXR, exr); -} - -/* enable singlestep */ -void user_enable_single_step(struct task_struct *child) -{ - unsigned char exr; - - exr = h8300_get_reg(child, PT_EXR); - exr |= EXR_TRACE; - h8300_put_reg(child, PT_EXR, exr); -} - -asmlinkage void trace_trap(unsigned long bp) -{ - (void)bp; - force_sig(SIGTRAP); -} diff --git a/arch/h8300/kernel/setup.c b/arch/h8300/kernel/setup.c deleted file mode 100644 index 61091a76eb7e..000000000000 --- a/arch/h8300/kernel/setup.c +++ /dev/null @@ -1,213 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/h8300/kernel/setup.c - * - * Copyright (C) 2001-2014 Yoshinori Sato - */ - -/* - * This file handles the architecture-dependent parts of system setup - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if defined(CONFIG_CPU_H8300H) -#define CPU "H8/300H" -#elif defined(CONFIG_CPU_H8S) -#define CPU "H8S" -#else -#define CPU "Unknown" -#endif - -unsigned long memory_start; -unsigned long memory_end; -EXPORT_SYMBOL(memory_end); -static unsigned long freq; -extern char __dtb_start[]; - -#ifdef CONFIG_VT -struct screen_info screen_info; -#endif - -char __initdata command_line[COMMAND_LINE_SIZE]; - -void sim_console_register(void); - -void __init h8300_fdt_init(void *fdt, char *bootargs) -{ - if (!fdt) - fdt = __dtb_start; - else - strcpy(command_line, bootargs); - - early_init_dt_scan(fdt); - memblock_allow_resize(); -} - -static void __init bootmem_init(void) -{ - memory_end = memory_start = 0; - - /* Find main memory where is the kernel */ - memory_start = memblock_start_of_DRAM(); - memory_end = memblock_end_of_DRAM(); - - if (!memory_end) - panic("No memory!"); - - /* setup bootmem globals (we use no_bootmem, but mm still depends on this) */ - min_low_pfn = PFN_UP(memory_start); - max_low_pfn = PFN_DOWN(memory_end); - max_pfn = max_low_pfn; - - memblock_reserve(__pa(_stext), _end - _stext); - - early_init_fdt_reserve_self(); - early_init_fdt_scan_reserved_mem(); - - memblock_dump_all(); -} - -void __init setup_arch(char **cmdline_p) -{ - unflatten_and_copy_device_tree(); - - setup_initial_init_mm(_stext, _etext, _edata, NULL); - - pr_notice("\r\n\nuClinux " CPU "\n"); - pr_notice("Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n"); - - if (*command_line) - strcpy(boot_command_line, command_line); - *cmdline_p = boot_command_line; - - parse_early_param(); - - bootmem_init(); - /* - * get kmalloc into gear - */ - paging_init(); -} - -/* - * Get CPU information for use by the procfs. - */ - -static int show_cpuinfo(struct seq_file *m, void *v) -{ - char *cpu; - - cpu = CPU; - - seq_printf(m, "CPU:\t\t%s\n" - "Clock:\t\t%lu.%1luMHz\n" - "BogoMips:\t%lu.%02lu\n" - "Calibration:\t%lu loops\n", - cpu, - freq/1000, freq%1000, - (loops_per_jiffy*HZ)/500000, - ((loops_per_jiffy*HZ)/5000)%100, - (loops_per_jiffy*HZ)); - - return 0; -} - -static void *c_start(struct seq_file *m, loff_t *pos) -{ - return *pos < num_possible_cpus() ? - ((void *) 0x12345678) : NULL; -} - -static void *c_next(struct seq_file *m, void *v, loff_t *pos) -{ - ++*pos; - return c_start(m, pos); -} - -static void c_stop(struct seq_file *m, void *v) -{ -} - -const struct seq_operations cpuinfo_op = { - .start = c_start, - .next = c_next, - .stop = c_stop, - .show = show_cpuinfo, -}; - -#if defined(CONFIG_CPU_H8300H) -#define get_wait(base, addr) ({ \ - int baddr; \ - baddr = ((addr) / 0x200000 * 2); \ - w *= (readw((base) + 2) & (3 << baddr)) + 1; \ - }) -#endif -#if defined(CONFIG_CPU_H8S) -#define get_wait(base, addr) ({ \ - int baddr; \ - baddr = ((addr) / 0x200000 * 16); \ - w *= (readl((base) + 2) & (7 << baddr)) + 1; \ - }) -#endif - -static __init int access_timing(void) -{ - struct device_node *bsc; - void __iomem *base; - unsigned long addr = (unsigned long)&__delay; - int bit = 1 << (addr / 0x200000); - int w; - - bsc = of_find_compatible_node(NULL, NULL, "renesas,h8300-bsc"); - base = of_iomap(bsc, 0); - w = (readb(base + 0) & bit)?2:1; - if (readb(base + 1) & bit) - w *= get_wait(base, addr); - else - w *= 2; - return w * 3 / 2; -} - -void __init calibrate_delay(void) -{ - struct device_node *cpu; - int freq; - - cpu = of_find_compatible_node(NULL, NULL, "renesas,h8300"); - of_property_read_s32(cpu, "clock-frequency", &freq); - loops_per_jiffy = freq / HZ / (access_timing() * 2); - pr_cont("%lu.%02lu BogoMIPS (lpj=%lu)\n", - loops_per_jiffy / (500000 / HZ), - (loops_per_jiffy / (5000 / HZ)) % 100, loops_per_jiffy); -} - - -void __init time_init(void) -{ - of_clk_init(NULL); - timer_probe(); -} diff --git a/arch/h8300/kernel/signal.c b/arch/h8300/kernel/signal.c deleted file mode 100644 index 75a1c36b105a..000000000000 --- a/arch/h8300/kernel/signal.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * linux/arch/h8300/kernel/signal.c - * - * Copyright (C) 1991, 1992 Linus Torvalds - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -/* - * uClinux H8/300 support by Yoshinori Sato - * and David McCullough - * - * Based on - * Linux/m68k by Hamish Macdonald - */ - -/* - * ++roman (07/09/96): implemented signal stacks (specially for tosemu on - * Atari :-) Current limitation: Only one sigstack can be active at one time. - * If a second signal with SA_ONSTACK set arrives while working on a sigstack, - * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested - * signal handlers! - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * Do a signal return; undo the signal stack. - * - * Keep the return code on the stack quadword aligned! - * That makes the cache flush below easier. - */ - -struct rt_sigframe { - long dummy_er0; - long dummy_vector; -#if defined(CONFIG_CPU_H8S) - short dummy_exr; -#endif - long dummy_pc; - char *pretcode; - struct siginfo *pinfo; - void *puc; - unsigned char retcode[8]; - struct siginfo info; - struct ucontext uc; - int sig; -} __packed __aligned(2); - -static inline int -restore_sigcontext(struct sigcontext *usc, int *pd0) -{ - struct pt_regs *regs = current_pt_regs(); - int err = 0; - unsigned int ccr; - unsigned int usp; - unsigned int er0; - - /* Always make any pending restarted system calls return -EINTR */ - current->restart_block.fn = do_no_restart_syscall; - - /* restore passed registers */ -#define COPY(r) do { err |= get_user(regs->r, &usc->sc_##r); } while (0) - COPY(er1); - COPY(er2); - COPY(er3); - COPY(er5); - COPY(pc); - ccr = regs->ccr & 0x10; - COPY(ccr); -#undef COPY - regs->ccr &= 0xef; - regs->ccr |= ccr; - regs->orig_er0 = -1; /* disable syscall checks */ - err |= __get_user(usp, &usc->sc_usp); - regs->sp = usp; - - err |= __get_user(er0, &usc->sc_er0); - *pd0 = er0; - return err; -} - -asmlinkage int sys_rt_sigreturn(void) -{ - unsigned long usp = rdusp(); - struct rt_sigframe *frame = (struct rt_sigframe *)(usp - 4); - sigset_t set; - int er0; - - if (!access_ok(frame, sizeof(*frame))) - goto badframe; - if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) - goto badframe; - - set_current_blocked(&set); - - if (restore_sigcontext(&frame->uc.uc_mcontext, &er0)) - goto badframe; - - if (restore_altstack(&frame->uc.uc_stack)) - goto badframe; - - return er0; - -badframe: - force_sig(SIGSEGV); - return 0; -} - -static int setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs, - unsigned long mask) -{ - int err = 0; - - err |= __put_user(regs->er0, &sc->sc_er0); - err |= __put_user(regs->er1, &sc->sc_er1); - err |= __put_user(regs->er2, &sc->sc_er2); - err |= __put_user(regs->er3, &sc->sc_er3); - err |= __put_user(regs->er4, &sc->sc_er4); - err |= __put_user(regs->er5, &sc->sc_er5); - err |= __put_user(regs->er6, &sc->sc_er6); - err |= __put_user(rdusp(), &sc->sc_usp); - err |= __put_user(regs->pc, &sc->sc_pc); - err |= __put_user(regs->ccr, &sc->sc_ccr); - err |= __put_user(mask, &sc->sc_mask); - - return err; -} - -static inline void __user * -get_sigframe(struct ksignal *ksig, struct pt_regs *regs, size_t frame_size) -{ - return (void __user *)((sigsp(rdusp(), ksig) - frame_size) & -8UL); -} - -static int setup_rt_frame(struct ksignal *ksig, sigset_t *set, - struct pt_regs *regs) -{ - struct rt_sigframe *frame; - int err = 0; - unsigned char *ret; - - frame = get_sigframe(ksig, regs, sizeof(*frame)); - - if (!access_ok(frame, sizeof(*frame))) - return -EFAULT; - - if (ksig->ka.sa.sa_flags & SA_SIGINFO) - err |= copy_siginfo_to_user(&frame->info, &ksig->info); - - /* Create the ucontext. */ - err |= __put_user(0, &frame->uc.uc_flags); - err |= __put_user(0, &frame->uc.uc_link); - err |= __save_altstack(&frame->uc.uc_stack, rdusp()); - err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); - err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); - if (err) - return -EFAULT; - - /* Set up to return from userspace. */ - ret = (unsigned char *)&frame->retcode; - if (ksig->ka.sa.sa_flags & SA_RESTORER) - ret = (unsigned char *)(ksig->ka.sa.sa_restorer); - else { - /* sub.l er0,er0; mov.b #__NR_rt_sigreturn,r0l; trapa #0 */ - err |= __put_user(0x1a80f800 + (__NR_rt_sigreturn & 0xff), - (unsigned long *)(frame->retcode + 0)); - err |= __put_user(0x5700, - (unsigned short *)(frame->retcode + 4)); - } - err |= __put_user(ret, &frame->pretcode); - - if (err) - return -EFAULT; - - /* Set up registers for signal handler */ - regs->sp = (unsigned long)frame; - regs->pc = (unsigned long)ksig->ka.sa.sa_handler; - regs->er0 = ksig->sig; - regs->er1 = (unsigned long)&(frame->info); - regs->er2 = (unsigned long)&frame->uc; - regs->er5 = current->mm->start_data; /* GOT base */ - - return 0; -} - -static void -handle_restart(struct pt_regs *regs, struct k_sigaction *ka) -{ - switch (regs->er0) { - case -ERESTARTNOHAND: - if (!ka) - goto do_restart; - regs->er0 = -EINTR; - break; - case -ERESTART_RESTARTBLOCK: - if (!ka) { - regs->er0 = __NR_restart_syscall; - regs->pc -= 2; - } else - regs->er0 = -EINTR; - break; - case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->er0 = -EINTR; - break; - } - fallthrough; - case -ERESTARTNOINTR: -do_restart: - regs->er0 = regs->orig_er0; - regs->pc -= 2; - break; - } -} - -/* - * OK, we're invoking a handler - */ -static void -handle_signal(struct ksignal *ksig, struct pt_regs *regs) -{ - sigset_t *oldset = sigmask_to_save(); - int ret; - /* are we from a system call? */ - if (regs->orig_er0 >= 0) - handle_restart(regs, &ksig->ka); - - ret = setup_rt_frame(ksig, oldset, regs); - - signal_setup_done(ret, ksig, 0); -} - -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - */ -static void do_signal(struct pt_regs *regs) -{ - struct ksignal ksig; - - current->thread.esp0 = (unsigned long) regs; - - if (get_signal(&ksig)) { - /* Whee! Actually deliver the signal. */ - handle_signal(&ksig, regs); - return; - } - /* Did we come from a system call? */ - if (regs->orig_er0 >= 0) - handle_restart(regs, NULL); - - /* If there's no signal to deliver, we just restore the saved mask. */ - restore_saved_sigmask(); -} - -asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags) -{ - if (thread_info_flags & (_TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL)) - do_signal(regs); - - if (thread_info_flags & _TIF_NOTIFY_RESUME) - tracehook_notify_resume(regs); -} diff --git a/arch/h8300/kernel/sim-console.c b/arch/h8300/kernel/sim-console.c deleted file mode 100644 index 03aa35b1a08c..000000000000 --- a/arch/h8300/kernel/sim-console.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * arch/h8300/kernel/sim-console.c - * - * Copyright (C) 2015 Yoshinori Sato - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - */ -#include -#include -#include - -static void sim_write(struct console *con, const char *s, unsigned n) -{ - register const char *_ptr __asm__("er1") = s; - register const unsigned _len __asm__("er2") = n; - - __asm__("sub.l er0,er0\n\t" /* er0 = 1 (stdout) */ - "inc.l #1,er0\n\t" - ".byte 0x5e,0x00,0x00,0xc7\n\t" /* jsr @0xc7 (sys_write) */ - : : "g"(_ptr), "g"(_len):"er0"); -} - -static int __init sim_setup(struct earlycon_device *device, const char *opt) -{ - device->con->write = sim_write; - return 0; -} - -EARLYCON_DECLARE(h8sim, sim_setup); diff --git a/arch/h8300/kernel/syscalls.c b/arch/h8300/kernel/syscalls.c deleted file mode 100644 index 9022036fb3d2..000000000000 --- a/arch/h8300/kernel/syscalls.c +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include -#include -#include - -#undef __SYSCALL -#define __SYSCALL(nr, call) [nr] = (call), - -#define sys_mmap2 sys_mmap_pgoff - -asmlinkage int sys_rt_sigreturn(void); - -void *_sys_call_table[__NR_syscalls] = { -#include -}; diff --git a/arch/h8300/kernel/traps.c b/arch/h8300/kernel/traps.c deleted file mode 100644 index a92c39e03802..000000000000 --- a/arch/h8300/kernel/traps.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * linux/arch/h8300/boot/traps.c -- general exception handling code - * H8/300 support Yoshinori Sato - * - * Cloned from Linux/m68k. - * - * No original Copyright holder listed, - * Probable original (C) Roman Zippel (assigned DJD, 1999) - * - * Copyright 1999-2000 D. Jeff Dionne, - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -static DEFINE_SPINLOCK(die_lock); - -/* - * this must be called very early as the kernel might - * use some instruction that are emulated on the 060 - */ - -void __init base_trap_init(void) -{ -} - -asmlinkage void set_esp0(unsigned long ssp) -{ - current->thread.esp0 = ssp; -} - -/* - * Generic dumping code. Used for panic and debug. - */ - -static void dump(struct pt_regs *fp) -{ - unsigned long *sp; - unsigned char *tp; - int i; - - pr_info("\nCURRENT PROCESS:\n\n"); - pr_info("COMM=%s PID=%d\n", current->comm, current->pid); - if (current->mm) { - pr_info("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n", - (int) current->mm->start_code, - (int) current->mm->end_code, - (int) current->mm->start_data, - (int) current->mm->end_data, - (int) current->mm->end_data, - (int) current->mm->brk); - pr_info("USER-STACK=%08x KERNEL-STACK=%08lx\n\n", - (int) current->mm->start_stack, - (int) PAGE_SIZE+(unsigned long)current); - } - - show_regs(fp); - pr_info("\nCODE:"); - tp = ((unsigned char *) fp->pc) - 0x20; - for (sp = (unsigned long *) tp, i = 0; (i < 0x40); i += 4) { - if ((i % 0x10) == 0) - pr_info("\n%08x: ", (int) (tp + i)); - pr_info("%08x ", (int) *sp++); - } - pr_info("\n"); - - pr_info("\nKERNEL STACK:"); - tp = ((unsigned char *) fp) - 0x40; - for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) { - if ((i % 0x10) == 0) - pr_info("\n%08x: ", (int) (tp + i)); - pr_info("%08x ", (int) *sp++); - } - pr_info("\n"); - if (STACK_MAGIC != *(unsigned long *)((unsigned long)current+PAGE_SIZE)) - pr_info("(Possibly corrupted stack page??)\n"); - - pr_info("\n\n"); -} - -void die(const char *str, struct pt_regs *fp, unsigned long err) -{ - static int diecount; - - oops_enter(); - - console_verbose(); - spin_lock_irq(&die_lock); - report_bug(fp->pc, fp); - pr_crit("%s: %04lx [#%d] ", str, err & 0xffff, ++diecount); - dump(fp); - - spin_unlock_irq(&die_lock); - make_task_dead(SIGSEGV); -} - -static int kstack_depth_to_print = 24; - -void show_stack(struct task_struct *task, unsigned long *esp, const char *loglvl) -{ - unsigned long *stack, addr; - int i; - - if (esp == NULL) - esp = (unsigned long *) &esp; - - stack = esp; - - printk("%sStack from %08lx:", loglvl, (unsigned long)stack); - for (i = 0; i < kstack_depth_to_print; i++) { - if (((unsigned long)stack & (THREAD_SIZE - 1)) >= - THREAD_SIZE-4) - break; - if (i % 8 == 0) - printk("%s ", loglvl); - pr_cont(" %08lx", *stack++); - } - - printk("%s\nCall Trace:\n", loglvl); - i = 0; - stack = esp; - while (((unsigned long)stack & (THREAD_SIZE - 1)) < THREAD_SIZE-4) { - addr = *stack++; - /* - * If the address is either in the text segment of the - * kernel, or in the region which contains vmalloc'ed - * memory, it *may* be the address of a calling - * routine; if so, print it so that someone tracing - * down the cause of the crash will be able to figure - * out the call path that was taken. - */ - if (check_kernel_text(addr)) { - if (i % 4 == 0) - printk("%s ", loglvl); - pr_cont(" [<%08lx>]", addr); - i++; - } - } - printk("%s\n", loglvl); -} diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S deleted file mode 100644 index 6b1afc2f9b68..000000000000 --- a/arch/h8300/kernel/vmlinux.lds.S +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -#define RO_EXCEPTION_TABLE_ALIGN 16 - -#include -#include -#include - -#define ROMTOP 0x000000 -#define RAMTOP 0x400000 - -jiffies = jiffies_64 + 4; - -ENTRY(_start) - -SECTIONS -{ -#if defined(CONFIG_ROMKERNEL) - . = ROMTOP; - .vectors : - { - _vector = . ; - *(.vector*) - } -#else - . = RAMTOP; - _ramstart = .; - . = . + CONFIG_OFFSET; -#endif - _text = .; - HEAD_TEXT_SECTION - .text : { - _stext = . ; - TEXT_TEXT - SCHED_TEXT - CPUIDLE_TEXT - LOCK_TEXT -#if defined(CONFIG_ROMKERNEL) - *(.int_redirect) -#endif - _etext = . ; - } - RO_DATA(4) - ROMEND = .; -#if defined(CONFIG_ROMKERNEL) - . = RAMTOP; - _ramstart = .; -#define ADDR(x) ROMEND -#endif - _sdata = . ; - __data_start = . ; - RW_DATA(0, PAGE_SIZE, THREAD_SIZE) -#if defined(CONFIG_ROMKERNEL) -#undef ADDR -#endif - . = ALIGN(0x4) ; - __init_begin = .; - INIT_TEXT_SECTION(4) - INIT_DATA_SECTION(4) - __init_end = .; - _edata = . ; - _begin_data = LOADADDR(.data); - _sbss =.; - BSS_SECTION(0, 0 ,0) - _ebss =.; - _ramend = .; - _end = .; - DISCARDS -} diff --git a/arch/h8300/lib/Makefile b/arch/h8300/lib/Makefile deleted file mode 100644 index 5911c1fa856d..000000000000 --- a/arch/h8300/lib/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for H8/300-specific library files.. -# - -lib-y = memcpy.o memset.o abs.o \ - mulsi3.o udivsi3.o muldi3.o moddivsi3.o \ - ashldi3.o lshrdi3.o ashrdi3.o ucmpdi2.o \ - delay.o diff --git a/arch/h8300/lib/abs.S b/arch/h8300/lib/abs.S deleted file mode 100644 index 6e1a4ed3af53..000000000000 --- a/arch/h8300/lib/abs.S +++ /dev/null @@ -1,21 +0,0 @@ -;;; SPDX-License-Identifier: GPL-2.0 -;;; abs.S - -#include - -#if defined(CONFIG_CPU_H8300H) - .h8300h -#endif -#if defined(CONFIG_CPU_H8S) - .h8300s -#endif - .text -.global _abs - -;;; int abs(int n) -_abs: - mov.l er0,er0 - bpl 1f - neg.l er0 -1: - rts diff --git a/arch/h8300/lib/ashldi3.c b/arch/h8300/lib/ashldi3.c deleted file mode 100644 index 430720c0c5d8..000000000000 --- a/arch/h8300/lib/ashldi3.c +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include "libgcc.h" - -DWtype -__ashldi3(DWtype u, word_type b) -{ - const DWunion uu = {.ll = u}; - const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; - DWunion w; - - if (b == 0) - return u; - - if (bm <= 0) { - w.s.low = 0; - w.s.high = (UWtype) uu.s.low << -bm; - } else { - const UWtype carries = (UWtype) uu.s.low >> bm; - - w.s.low = (UWtype) uu.s.low << b; - w.s.high = ((UWtype) uu.s.high << b) | carries; - } - - return w.ll; -} diff --git a/arch/h8300/lib/ashrdi3.c b/arch/h8300/lib/ashrdi3.c deleted file mode 100644 index 2c6cd424eb3e..000000000000 --- a/arch/h8300/lib/ashrdi3.c +++ /dev/null @@ -1,25 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include "libgcc.h" - -DWtype __ashrdi3(DWtype u, word_type b) -{ - const DWunion uu = {.ll = u}; - const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; - DWunion w; - - if (b == 0) - return u; - - if (bm <= 0) { - /* w.s.high = 1..1 or 0..0 */ - w.s.high = uu.s.high >> (sizeof (Wtype) * BITS_PER_UNIT - 1); - w.s.low = uu.s.high >> -bm; - } else { - const UWtype carries = (UWtype) uu.s.high << bm; - - w.s.high = uu.s.high >> b; - w.s.low = ((UWtype) uu.s.low >> b) | carries; - } - - return w.ll; -} diff --git a/arch/h8300/lib/delay.c b/arch/h8300/lib/delay.c deleted file mode 100644 index f4277529a9b9..000000000000 --- a/arch/h8300/lib/delay.c +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * delay loops - * - * Copyright (C) 2015 Yoshinori Sato - */ - -#include -#include -#include -#include -#include - -void __delay(unsigned long cycles) -{ - __asm__ volatile ("1: dec.l #1,%0\n\t" - "bne 1b":"=r"(cycles):"0"(cycles)); -} -EXPORT_SYMBOL(__delay); - -void __const_udelay(unsigned long xloops) -{ - u64 loops; - - loops = (u64)xloops * loops_per_jiffy * HZ; - - __delay(loops >> 32); -} -EXPORT_SYMBOL(__const_udelay); - -void __udelay(unsigned long usecs) -{ - __const_udelay(usecs * 0x10C7UL); /* 2**32 / 1000000 (rounded up) */ -} -EXPORT_SYMBOL(__udelay); - -void __ndelay(unsigned long nsecs) -{ - __const_udelay(nsecs * 0x5UL); /* 2**32 / 1000000000 (rounded up) */ -} -EXPORT_SYMBOL(__ndelay); diff --git a/arch/h8300/lib/libgcc.h b/arch/h8300/lib/libgcc.h deleted file mode 100644 index b8bcf7035ff5..000000000000 --- a/arch/h8300/lib/libgcc.h +++ /dev/null @@ -1,78 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __H8300_LIBGCC_H__ -#define __H8300_LIBGCC_H__ - -#ifdef __ASSEMBLY__ -#define A0 r0 -#define A0L r0l -#define A0H r0h - -#define A1 r1 -#define A1L r1l -#define A1H r1h - -#define A2 r2 -#define A2L r2l -#define A2H r2h - -#define A3 r3 -#define A3L r3l -#define A3H r3h - -#define S0 r4 -#define S0L r4l -#define S0H r4h - -#define S1 r5 -#define S1L r5l -#define S1H r5h - -#define S2 r6 -#define S2L r6l -#define S2H r6h - -#define PUSHP push.l -#define POPP pop.l - -#define A0P er0 -#define A1P er1 -#define A2P er2 -#define A3P er3 -#define S0P er4 -#define S1P er5 -#define S2P er6 - -#define A0E e0 -#define A1E e1 -#define A2E e2 -#define A3E e3 -#else -#define Wtype SItype -#define UWtype USItype -#define HWtype SItype -#define UHWtype USItype -#define DWtype DItype -#define UDWtype UDItype -#define UWtype USItype -#define Wtype SItype -#define UWtype USItype -#define W_TYPE_SIZE (4 * BITS_PER_UNIT) -#define BITS_PER_UNIT (8) - -typedef int SItype __attribute__ ((mode (SI))); -typedef unsigned int USItype __attribute__ ((mode (SI))); -typedef int DItype __attribute__ ((mode (DI))); -typedef unsigned int UDItype __attribute__ ((mode (DI))); -struct DWstruct { - Wtype high, low; -}; -typedef union { - struct DWstruct s; - DWtype ll; -} DWunion; - -typedef int word_type __attribute__ ((mode (__word__))); - -#endif - -#endif diff --git a/arch/h8300/lib/lshrdi3.c b/arch/h8300/lib/lshrdi3.c deleted file mode 100644 index 8dbc861ca589..000000000000 --- a/arch/h8300/lib/lshrdi3.c +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include "libgcc.h" - -DWtype __lshrdi3(DWtype u, word_type b) -{ - const DWunion uu = {.ll = u}; - const word_type bm = (sizeof (Wtype) * BITS_PER_UNIT) - b; - DWunion w; - - if (b == 0) - return u; - - if (bm <= 0) { - w.s.high = 0; - w.s.low = (UWtype) uu.s.high >> -bm; - } else { - const UWtype carries = (UWtype) uu.s.high << bm; - - w.s.high = (UWtype) uu.s.high >> b; - w.s.low = ((UWtype) uu.s.low >> b) | carries; - } - - return w.ll; -} diff --git a/arch/h8300/lib/memcpy.S b/arch/h8300/lib/memcpy.S deleted file mode 100644 index f1cd67d5e3ea..000000000000 --- a/arch/h8300/lib/memcpy.S +++ /dev/null @@ -1,86 +0,0 @@ -;;; SPDX-License-Identifier: GPL-2.0 -;;; memcpy.S - -#include - -#if defined(CONFIG_CPU_H8300H) - .h8300h -#endif -#if defined(CONFIG_CPU_H8S) - .h8300s -#endif - .text -.global memcpy - -;;; void *memcpy(void *to, void *from, size_t n) -memcpy: - mov.l er2,er2 - bne 1f - rts -1: - ;; address check - bld #0,r0l - bxor #0,r1l - bcs 4f - mov.l er4,@-sp - mov.l er0,@-sp - btst #0,r0l - beq 1f - ;; (aligned even) odd address - mov.b @er1,r3l - mov.b r3l,@er0 - adds #1,er1 - adds #1,er0 - dec.l #1,er2 - beq 3f -1: - ;; n < sizeof(unsigned long) check - sub.l er4,er4 - adds #4,er4 ; loop count check value - cmp.l er4,er2 - blo 2f - ;; unsigned long copy -1: - mov.l @er1,er3 - mov.l er3,@er0 - adds #4,er0 - adds #4,er1 - subs #4,er2 - cmp.l er4,er2 - bcc 1b - ;; rest -2: - mov.l er2,er2 - beq 3f -1: - mov.b @er1,r3l - mov.b r3l,@er0 - adds #1,er1 - adds #1,er0 - dec.l #1,er2 - bne 1b -3: - mov.l @sp+,er0 - mov.l @sp+,er4 - rts - - ;; odd <- even / even <- odd -4: - mov.l er4,er3 - mov.l er2,er4 - mov.l er5,er2 - mov.l er1,er5 - mov.l er6,er1 - mov.l er0,er6 -1: - eepmov.w - mov.w r4,r4 - bne 1b - dec.w #1,e4 - bpl 1b - mov.l er1,er6 - mov.l er2,er5 - mov.l er3,er4 - rts - - .end diff --git a/arch/h8300/lib/memset.S b/arch/h8300/lib/memset.S deleted file mode 100644 index 2d1abc37fd08..000000000000 --- a/arch/h8300/lib/memset.S +++ /dev/null @@ -1,70 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* memset.S */ - -#include - -#if defined(CONFIG_CPU_H8300H) - .h8300h -#endif -#if defined(CONFIG_CPU_H8S) - .h8300s -#endif - .text - -.global memset -.global clear_user - -;;void *memset(*ptr, int c, size_t count) -;; ptr = er0 -;; c = er1(r1l) -;; count = er2 -memset: - btst #0,r0l - beq 2f - - ;; odd address -1: - mov.b r1l,@er0 - adds #1,er0 - dec.l #1,er2 - beq 6f - - ;; even address -2: - mov.l er2,er3 - cmp.l #4,er2 - blo 4f - ;; count>=4 -> count/4 -#if defined(CONFIG_CPU_H8300H) - shlr.l er2 - shlr.l er2 -#endif -#if defined(CONFIG_CPU_H8S) - shlr.l #2,er2 -#endif - ;; byte -> long - mov.b r1l,r1h - mov.w r1,e1 -3: - mov.l er1,@er0 - adds #4,er0 - dec.l #1,er2 - bne 3b -4: - ;; count % 4 - and.b #3,r3l - beq 6f -5: - mov.b r1l,@er0 - adds #1,er0 - dec.b r3l - bne 5b -6: - rts - -clear_user: - mov.l er1, er2 - sub.l er1, er1 - bra memset - - .end diff --git a/arch/h8300/lib/moddivsi3.S b/arch/h8300/lib/moddivsi3.S deleted file mode 100644 index 9e33ab0456c7..000000000000 --- a/arch/h8300/lib/moddivsi3.S +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include "libgcc.h" - -; numerator in A0/A1 -; denominator in A2/A3 - .global __modsi3 -__modsi3: - PUSHP S2P - bsr modnorm - bsr __divsi3 - mov.l er3,er0 - bra exitdiv - - .global __umodsi3 -__umodsi3: - bsr __udivsi3:16 - mov.l er3,er0 - rts - - .global __divsi3 -__divsi3: - PUSHP S2P - bsr divnorm - bsr __udivsi3:16 - - ; examine what the sign should be -exitdiv: - btst #3,S2L - beq reti - - ; should be -ve - neg.l A0P - -reti: - POPP S2P - rts - -divnorm: - mov.l A0P,A0P ; is the numerator -ve - stc ccr,S2L ; keep the sign in bit 3 of S2L - bge postive - - neg.l A0P ; negate arg - -postive: - mov.l A1P,A1P ; is the denominator -ve - bge postive2 - - neg.l A1P ; negate arg - xor.b #0x08,S2L ; toggle the result sign - -postive2: - rts - -;; Basically the same, except that the sign of the divisor determines -;; the sign. -modnorm: - mov.l A0P,A0P ; is the numerator -ve - stc ccr,S2L ; keep the sign in bit 3 of S2L - bge mpostive - - neg.l A0P ; negate arg - -mpostive: - mov.l A1P,A1P ; is the denominator -ve - bge mpostive2 - - neg.l A1P ; negate arg - -mpostive2: - rts - - .end diff --git a/arch/h8300/lib/modsi3.S b/arch/h8300/lib/modsi3.S deleted file mode 100644 index bdc8a002921d..000000000000 --- a/arch/h8300/lib/modsi3.S +++ /dev/null @@ -1,73 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include "libgcc.h" - -; numerator in A0/A1 -; denominator in A2/A3 - .global __modsi3 -__modsi3: - PUSHP S2P - bsr modnorm - bsr __divsi3 - mov.l er3,er0 - bra exitdiv - - .global __umodsi3 -__umodsi3: - bsr __udivsi3 - mov.l er3,er0 - rts - - .global __divsi3 -__divsi3: - PUSHP S2P - jsr divnorm - bsr __udivsi3 - - ; examine what the sign should be -exitdiv: - btst #3,S2L - beq reti - - ; should be -ve - neg.l A0P - -reti: - POPP S2P - rts - -divnorm: - mov.l A0P,A0P ; is the numerator -ve - stc ccr,S2L ; keep the sign in bit 3 of S2L - bge postive - - neg.l A0P ; negate arg - -postive: - mov.l A1P,A1P ; is the denominator -ve - bge postive2 - - neg.l A1P ; negate arg - xor.b #0x08,S2L ; toggle the result sign - -postive2: - rts - -;; Basically the same, except that the sign of the divisor determines -;; the sign. -modnorm: - mov.l A0P,A0P ; is the numerator -ve - stc ccr,S2L ; keep the sign in bit 3 of S2L - bge mpostive - - neg.l A0P ; negate arg - -mpostive: - mov.l A1P,A1P ; is the denominator -ve - bge mpostive2 - - neg.l A1P ; negate arg - -mpostive2: - rts - - .end diff --git a/arch/h8300/lib/muldi3.c b/arch/h8300/lib/muldi3.c deleted file mode 100644 index 9cb11b134e54..000000000000 --- a/arch/h8300/lib/muldi3.c +++ /dev/null @@ -1,45 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include "libgcc.h" - -#define __ll_B ((UWtype) 1 << (W_TYPE_SIZE / 2)) -#define __ll_lowpart(t) ((UWtype) (t) & (__ll_B - 1)) -#define __ll_highpart(t) ((UWtype) (t) >> (W_TYPE_SIZE / 2)) - -#define umul_ppmm(w1, w0, u, v) \ - do { \ - UWtype __x0, __x1, __x2, __x3; \ - UHWtype __ul, __vl, __uh, __vh; \ - __ul = __ll_lowpart(u); \ - __uh = __ll_highpart(u); \ - __vl = __ll_lowpart(v); \ - __vh = __ll_highpart(v); \ - __x0 = (UWtype) __ul * __vl; \ - __x1 = (UWtype) __ul * __vh; \ - __x2 = (UWtype) __uh * __vl; \ - __x3 = (UWtype) __uh * __vh; \ - __x1 += __ll_highpart(__x0); \ - __x1 += __x2; \ - if (__x1 < __x2) \ - __x3 += __ll_B; \ - (w1) = __x3 + __ll_highpart(__x1); \ - (w0) = __ll_lowpart(__x1) * __ll_B + __ll_lowpart(__x0); \ - } while (0) - -#define __umulsidi3(u, v) ( \ - { \ - DWunion __w; \ - umul_ppmm(__w.s.high, __w.s.low, u, v); \ - __w.ll; } \ - ) - -DWtype __muldi3(DWtype u, DWtype v) -{ - const DWunion uu = {.ll = u}; - const DWunion vv = {.ll = v}; - DWunion w = {.ll = __umulsidi3(uu.s.low, vv.s.low)}; - - w.s.high += ((UWtype) uu.s.low * (UWtype) vv.s.high - + (UWtype) uu.s.high * (UWtype) vv.s.low); - - return w.ll; -} diff --git a/arch/h8300/lib/mulsi3.S b/arch/h8300/lib/mulsi3.S deleted file mode 100644 index 5a062fd298d1..000000000000 --- a/arch/h8300/lib/mulsi3.S +++ /dev/null @@ -1,39 +0,0 @@ -; SPDX-License-Identifier: GPL-2.0 -; -; mulsi3 for H8/300H - based on Renesas SH implementation -; -; by Toshiyasu Morita -; -; Old code: -; -; 16b * 16b = 372 states (worst case) -; 32b * 32b = 724 states (worst case) -; -; New code: -; -; 16b * 16b = 48 states -; 16b * 32b = 72 states -; 32b * 32b = 92 states -; - - .global __mulsi3 -__mulsi3: - mov.w r1,r2 ; ( 2 states) b * d - mulxu r0,er2 ; (22 states) - - mov.w e0,r3 ; ( 2 states) a * d - beq L_skip1 ; ( 4 states) - mulxu r1,er3 ; (22 states) - add.w r3,e2 ; ( 2 states) - -L_skip1: - mov.w e1,r3 ; ( 2 states) c * b - beq L_skip2 ; ( 4 states) - mulxu r0,er3 ; (22 states) - add.w r3,e2 ; ( 2 states) - -L_skip2: - mov.l er2,er0 ; ( 2 states) - rts ; (10 states) - - .end diff --git a/arch/h8300/lib/ucmpdi2.c b/arch/h8300/lib/ucmpdi2.c deleted file mode 100644 index 9f646885f3d7..000000000000 --- a/arch/h8300/lib/ucmpdi2.c +++ /dev/null @@ -1,18 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -#include "libgcc.h" - -word_type __ucmpdi2(DWtype a, DWtype b) -{ - const DWunion au = {.ll = a}; - const DWunion bu = {.ll = b}; - - if ((UWtype) au.s.high < (UWtype) bu.s.high) - return 0; - else if ((UWtype) au.s.high > (UWtype) bu.s.high) - return 2; - if ((UWtype) au.s.low < (UWtype) bu.s.low) - return 0; - else if ((UWtype) au.s.low > (UWtype) bu.s.low) - return 2; - return 1; -} diff --git a/arch/h8300/lib/udivsi3.S b/arch/h8300/lib/udivsi3.S deleted file mode 100644 index b810aba8e100..000000000000 --- a/arch/h8300/lib/udivsi3.S +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#include "libgcc.h" - - ;; This function also computes the remainder and stores it in er3. - .global __udivsi3 -__udivsi3: - mov.w A1E,A1E ; denominator top word 0? - bne DenHighNonZero - - ; do it the easy way, see page 107 in manual - mov.w A0E,A2 - extu.l A2P - divxu.w A1,A2P - mov.w A2E,A0E - divxu.w A1,A0P - mov.w A0E,A3 - mov.w A2,A0E - extu.l A3P - rts - - ; er0 = er0 / er1 - ; er3 = er0 % er1 - ; trashes er1 er2 - ; expects er1 >= 2^16 -DenHighNonZero: - mov.l er0,er3 - mov.l er1,er2 -#ifdef CONFIG_CPU_H8300H -divmod_L21: - shlr.l er0 - shlr.l er2 ; make divisor < 2^16 - mov.w e2,e2 - bne divmod_L21 -#else - shlr.l #2,er2 ; make divisor < 2^16 - mov.w e2,e2 - beq divmod_L22A -divmod_L21: - shlr.l #2,er0 -divmod_L22: - shlr.l #2,er2 ; make divisor < 2^16 - mov.w e2,e2 - bne divmod_L21 -divmod_L22A: - rotxl.w r2 - bcs divmod_L23 - shlr.l er0 - bra divmod_L24 -divmod_L23: - rotxr.w r2 - shlr.l #2,er0 -divmod_L24: -#endif - ;; At this point, - ;; er0 contains shifted dividend - ;; er1 contains divisor - ;; er2 contains shifted divisor - ;; er3 contains dividend, later remainder - divxu.w r2,er0 ; r0 now contains the approximate quotient (AQ) - extu.l er0 - beq divmod_L25 - subs #1,er0 ; er0 = AQ - 1 - mov.w e1,r2 - mulxu.w r0,er2 ; er2 = upper (AQ - 1) * divisor - sub.w r2,e3 ; dividend - 65536 * er2 - mov.w r1,r2 - mulxu.w r0,er2 ; compute er3 = remainder (tentative) - sub.l er2,er3 ; er3 = dividend - (AQ - 1) * divisor -divmod_L25: - cmp.l er1,er3 ; is divisor < remainder? - blo divmod_L26 - adds #1,er0 - sub.l er1,er3 ; correct the remainder -divmod_L26: - rts - - .end diff --git a/arch/h8300/mm/Makefile b/arch/h8300/mm/Makefile deleted file mode 100644 index e85b5c91f5bc..000000000000 --- a/arch/h8300/mm/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -# -# Makefile for the linux h8300-specific parts of the memory manager. -# - -obj-y := init.o fault.o memory.o diff --git a/arch/h8300/mm/fault.c b/arch/h8300/mm/fault.c deleted file mode 100644 index b465441f490d..000000000000 --- a/arch/h8300/mm/fault.c +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/h8300/mm/fault.c - * - * Copyright (C) 1998 D. Jeff Dionne , - * Copyright (C) 2000 Lineo, Inc. (www.lineo.com) - * - * Based on: - * - * linux/arch/m68knommu/mm/fault.c - * linux/arch/m68k/mm/fault.c - * - * Copyright (C) 1995 Hamish Macdonald - */ - -#include -#include -#include -#include - - -void die(const char *str, struct pt_regs *fp, unsigned long err); - -/* - * This routine handles page faults. It determines the problem, and - * then passes it off to one of the appropriate routines. - * - * error_code: - * bit 0 == 0 means no page found, 1 means protection fault - * bit 1 == 0 means read, 1 means write - * - * If this routine detects a bad access, it returns 1, otherwise it - * returns 0. - */ -asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address, - unsigned long error_code) -{ -#ifdef DEBUG - pr_debug("regs->sr=%#x, regs->pc=%#lx, address=%#lx, %ld\n", - regs->sr, regs->pc, address, error_code); -#endif - -/* - * Oops. The kernel tried to access some bad page. We'll have to - * terminate things with extreme prejudice. - */ - if ((unsigned long) address < PAGE_SIZE) - pr_alert("Unable to handle kernel NULL pointer dereference"); - else - pr_alert("Unable to handle kernel access"); - printk(" at virtual address %08lx\n", address); - if (!user_mode(regs)) - die("Oops", regs, error_code); - make_task_dead(SIGKILL); - - return 1; -} diff --git a/arch/h8300/mm/init.c b/arch/h8300/mm/init.c deleted file mode 100644 index f7bf4693e3b2..000000000000 --- a/arch/h8300/mm/init.c +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/h8300/mm/init.c - * - * Copyright (C) 1998 D. Jeff Dionne , - * Kenneth Albanowski , - * Copyright (C) 2000 Lineo, Inc. (www.lineo.com) - * - * Based on: - * - * linux/arch/m68knommu/mm/init.c - * linux/arch/m68k/mm/init.c - * - * Copyright (C) 1995 Hamish Macdonald - * - * JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com) - * DEC/2000 -- linux 2.4 support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/* - * ZERO_PAGE is a special page that is used for zero-initialized - * data and COW. - */ -unsigned long empty_zero_page; - -/* - * paging_init() continues the virtual memory environment setup which - * was begun by the code in arch/head.S. - * The parameters are pointers to where to stick the starting and ending - * addresses of available kernel virtual memory. - */ -void __init paging_init(void) -{ - /* - * Make sure start_mem is page aligned, otherwise bootmem and - * page_alloc get different views og the world. - */ - unsigned long start_mem = PAGE_ALIGN(memory_start); - unsigned long end_mem = memory_end & PAGE_MASK; - - pr_debug("start_mem is %#lx\nvirtual_end is %#lx\n", - start_mem, end_mem); - - /* - * Initialize the bad page table and bad page to point - * to a couple of allocated pages. - */ - empty_zero_page = (unsigned long)memblock_alloc(PAGE_SIZE, PAGE_SIZE); - if (!empty_zero_page) - panic("%s: Failed to allocate %lu bytes align=0x%lx\n", - __func__, PAGE_SIZE, PAGE_SIZE); - - /* - * Set up SFC/DFC registers (user data space). - */ - set_fs(USER_DS); - - pr_debug("before free_area_init\n"); - - pr_debug("free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n", - start_mem, end_mem); - - { - unsigned long max_zone_pfn[MAX_NR_ZONES] = {0, }; - - max_zone_pfn[ZONE_NORMAL] = end_mem >> PAGE_SHIFT; - free_area_init(max_zone_pfn); - } -} - -void __init mem_init(void) -{ - pr_devel("Mem_init: start=%lx, end=%lx\n", memory_start, memory_end); - - high_memory = (void *) (memory_end & PAGE_MASK); - max_mapnr = MAP_NR(high_memory); - - /* this will put all low memory onto the freelists */ - memblock_free_all(); -} diff --git a/arch/h8300/mm/memory.c b/arch/h8300/mm/memory.c deleted file mode 100644 index 4a60e2b5eb96..000000000000 --- a/arch/h8300/mm/memory.c +++ /dev/null @@ -1,53 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/h8300/mm/memory.c - * - * Copyright (C) 2002 Yoshinori Sato , - * - * Based on: - * - * linux/arch/m68knommu/mm/memory.c - * - * Copyright (C) 1998 Kenneth Albanowski , - * Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com) - * - * Based on: - * - * linux/arch/m68k/mm/memory.c - * - * Copyright (C) 1995 Hamish Macdonald - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -void cache_clear(unsigned long paddr, int len) -{ -} - - -void cache_push(unsigned long paddr, int len) -{ -} - -void cache_push_v(unsigned long vaddr, int len) -{ -} - -/* - * Map some physical address range into the kernel address space. - */ - -unsigned long kernel_map(unsigned long paddr, unsigned long size, - int nocacheflag, unsigned long *memavailp) -{ - return paddr; -} diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 16e588630472..955fbce86843 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -81,7 +81,6 @@ obj-$(CONFIG_CLK_BAIKAL_T1) += baikal-t1/ obj-y += bcm/ obj-$(CONFIG_ARCH_BERLIN) += berlin/ obj-$(CONFIG_ARCH_DAVINCI) += davinci/ -obj-$(CONFIG_H8300) += h8300/ obj-$(CONFIG_ARCH_HISI) += hisilicon/ obj-y += imgtec/ obj-y += imx/ diff --git a/drivers/clk/h8300/Makefile b/drivers/clk/h8300/Makefile deleted file mode 100644 index 8078a0b79000..000000000000 --- a/drivers/clk/h8300/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -obj-y += clk-div.o -obj-$(CONFIG_H8S2678) += clk-h8s2678.o diff --git a/drivers/clk/h8300/clk-div.c b/drivers/clk/h8300/clk-div.c deleted file mode 100644 index 376be03bb546..000000000000 --- a/drivers/clk/h8300/clk-div.c +++ /dev/null @@ -1,57 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * H8/300 divide clock driver - * - * Copyright 2015 Yoshinori Sato - */ - -#include -#include -#include -#include -#include - -static DEFINE_SPINLOCK(clklock); - -static void __init h8300_div_clk_setup(struct device_node *node) -{ - unsigned int num_parents; - struct clk_hw *hw; - const char *clk_name = node->name; - const char *parent_name; - void __iomem *divcr = NULL; - int width; - int offset; - - num_parents = of_clk_get_parent_count(node); - if (!num_parents) { - pr_err("%s: no parent found\n", clk_name); - return; - } - - divcr = of_iomap(node, 0); - if (divcr == NULL) { - pr_err("%s: failed to map divide register\n", clk_name); - goto error; - } - offset = (unsigned long)divcr & 3; - offset = (3 - offset) * 8; - divcr = (void __iomem *)((unsigned long)divcr & ~3); - - parent_name = of_clk_get_parent_name(node, 0); - of_property_read_u32(node, "renesas,width", &width); - hw = clk_hw_register_divider(NULL, clk_name, parent_name, - CLK_SET_RATE_GATE, divcr, offset, width, - CLK_DIVIDER_POWER_OF_TWO, &clklock); - if (!IS_ERR(hw)) { - of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw); - return; - } - pr_err("%s: failed to register %s div clock (%ld)\n", - __func__, clk_name, PTR_ERR(hw)); -error: - if (divcr) - iounmap(divcr); -} - -CLK_OF_DECLARE(h8300_div_clk, "renesas,h8300-div-clock", h8300_div_clk_setup); diff --git a/drivers/clk/h8300/clk-h8s2678.c b/drivers/clk/h8300/clk-h8s2678.c deleted file mode 100644 index 67c495b67c18..000000000000 --- a/drivers/clk/h8300/clk-h8s2678.c +++ /dev/null @@ -1,145 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * H8S2678 clock driver - * - * Copyright 2015 Yoshinori Sato - */ - -#include -#include -#include -#include -#include -#include - -static DEFINE_SPINLOCK(clklock); - -#define MAX_FREQ 33333333 -#define MIN_FREQ 8000000 - -struct pll_clock { - struct clk_hw hw; - void __iomem *sckcr; - void __iomem *pllcr; -}; - -#define to_pll_clock(_hw) container_of(_hw, struct pll_clock, hw) - -static unsigned long pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct pll_clock *pll_clock = to_pll_clock(hw); - int mul = 1 << (readb(pll_clock->pllcr) & 3); - - return parent_rate * mul; -} - -static long pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - int i, m = -1; - long offset[3]; - - if (rate > MAX_FREQ) - rate = MAX_FREQ; - if (rate < MIN_FREQ) - rate = MIN_FREQ; - - for (i = 0; i < 3; i++) - offset[i] = abs(rate - (*prate * (1 << i))); - for (i = 0; i < 3; i++) - if (m < 0) - m = i; - else - m = (offset[i] < offset[m])?i:m; - - return *prate * (1 << m); -} - -static int pll_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int pll; - unsigned char val; - unsigned long flags; - struct pll_clock *pll_clock = to_pll_clock(hw); - - pll = ((rate / parent_rate) / 2) & 0x03; - spin_lock_irqsave(&clklock, flags); - val = readb(pll_clock->sckcr); - val |= 0x08; - writeb(val, pll_clock->sckcr); - val = readb(pll_clock->pllcr); - val &= ~0x03; - val |= pll; - writeb(val, pll_clock->pllcr); - spin_unlock_irqrestore(&clklock, flags); - return 0; -} - -static const struct clk_ops pll_ops = { - .recalc_rate = pll_recalc_rate, - .round_rate = pll_round_rate, - .set_rate = pll_set_rate, -}; - -static void __init h8s2678_pll_clk_setup(struct device_node *node) -{ - unsigned int num_parents; - const char *clk_name = node->name; - const char *parent_name; - struct pll_clock *pll_clock; - struct clk_init_data init; - int ret; - - num_parents = of_clk_get_parent_count(node); - if (!num_parents) { - pr_err("%s: no parent found\n", clk_name); - return; - } - - - pll_clock = kzalloc(sizeof(*pll_clock), GFP_KERNEL); - if (!pll_clock) - return; - - pll_clock->sckcr = of_iomap(node, 0); - if (pll_clock->sckcr == NULL) { - pr_err("%s: failed to map divide register\n", clk_name); - goto free_clock; - } - - pll_clock->pllcr = of_iomap(node, 1); - if (pll_clock->pllcr == NULL) { - pr_err("%s: failed to map multiply register\n", clk_name); - goto unmap_sckcr; - } - - parent_name = of_clk_get_parent_name(node, 0); - init.name = clk_name; - init.ops = &pll_ops; - init.flags = 0; - init.parent_names = &parent_name; - init.num_parents = 1; - pll_clock->hw.init = &init; - - ret = clk_hw_register(NULL, &pll_clock->hw); - if (ret) { - pr_err("%s: failed to register %s div clock (%d)\n", - __func__, clk_name, ret); - goto unmap_pllcr; - } - - of_clk_add_hw_provider(node, of_clk_hw_simple_get, &pll_clock->hw); - return; - -unmap_pllcr: - iounmap(pll_clock->pllcr); -unmap_sckcr: - iounmap(pll_clock->sckcr); -free_clock: - kfree(pll_clock); -} - -CLK_OF_DECLARE(h8s2678_div_clk, "renesas,h8s2678-pll-clock", - h8s2678_pll_clk_setup); diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index cfb8ea0df3b1..4aa0883b3534 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -567,26 +567,6 @@ config CLKSRC_PXA This enables OST0 support available on PXA and SA-11x0 platforms. -config H8300_TMR8 - bool "Clockevent timer for the H8300 platform" if COMPILE_TEST - depends on HAS_IOMEM - help - This enables the 8 bits timer for the H8300 platform. - -config H8300_TMR16 - bool "Clockevent timer for the H83069 platform" if COMPILE_TEST - depends on HAS_IOMEM - help - This enables the 16 bits timer for the H8300 platform with the - H83069 CPU. - -config H8300_TPU - bool "Clocksource for the H8300 platform" if COMPILE_TEST - depends on HAS_IOMEM - help - This enables the clocksource for the H8300 platform with the - H8S2678 CPU. - config CLKSRC_IMX_GPT bool "Clocksource using i.MX GPT" if COMPILE_TEST depends on (ARM || ARM64) && HAVE_CLK diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index fa5f624eadb6..8e81eadfbeeb 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -73,9 +73,6 @@ obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o obj-$(CONFIG_CLKSRC_IMX_TPM) += timer-imx-tpm.o obj-$(CONFIG_TIMER_IMX_SYS_CTR) += timer-imx-sysctr.o obj-$(CONFIG_ASM9260_TIMER) += asm9260_timer.o -obj-$(CONFIG_H8300_TMR8) += h8300_timer8.o -obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o -obj-$(CONFIG_H8300_TPU) += h8300_tpu.o obj-$(CONFIG_INGENIC_OST) += ingenic-ost.o obj-$(CONFIG_INGENIC_SYSOST) += ingenic-sysost.o obj-$(CONFIG_INGENIC_TIMER) += ingenic-timer.o diff --git a/drivers/clocksource/h8300_timer16.c b/drivers/clocksource/h8300_timer16.c deleted file mode 100644 index 86ca91451b2e..000000000000 --- a/drivers/clocksource/h8300_timer16.c +++ /dev/null @@ -1,192 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * H8/300 16bit Timer driver - * - * Copyright 2015 Yoshinori Sato - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define TSTR 0 -#define TISRC 6 - -#define TCR 0 -#define TCNT 2 - -#define bset(b, a) iowrite8(ioread8(a) | (1 << (b)), (a)) -#define bclr(b, a) iowrite8(ioread8(a) & ~(1 << (b)), (a)) - -struct timer16_priv { - struct clocksource cs; - unsigned long total_cycles; - void __iomem *mapbase; - void __iomem *mapcommon; - unsigned short cs_enabled; - unsigned char enb; - unsigned char ovf; - unsigned char ovie; -}; - -static unsigned long timer16_get_counter(struct timer16_priv *p) -{ - unsigned short v1, v2, v3; - unsigned char o1, o2; - - o1 = ioread8(p->mapcommon + TISRC) & p->ovf; - - /* Make sure the timer value is stable. Stolen from acpi_pm.c */ - do { - o2 = o1; - v1 = ioread16be(p->mapbase + TCNT); - v2 = ioread16be(p->mapbase + TCNT); - v3 = ioread16be(p->mapbase + TCNT); - o1 = ioread8(p->mapcommon + TISRC) & p->ovf; - } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) - || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); - - if (likely(!o1)) - return v2; - else - return v2 + 0x10000; -} - - -static irqreturn_t timer16_interrupt(int irq, void *dev_id) -{ - struct timer16_priv *p = (struct timer16_priv *)dev_id; - - bclr(p->ovf, p->mapcommon + TISRC); - p->total_cycles += 0x10000; - - return IRQ_HANDLED; -} - -static inline struct timer16_priv *cs_to_priv(struct clocksource *cs) -{ - return container_of(cs, struct timer16_priv, cs); -} - -static u64 timer16_clocksource_read(struct clocksource *cs) -{ - struct timer16_priv *p = cs_to_priv(cs); - unsigned long raw, value; - - value = p->total_cycles; - raw = timer16_get_counter(p); - - return value + raw; -} - -static int timer16_enable(struct clocksource *cs) -{ - struct timer16_priv *p = cs_to_priv(cs); - - WARN_ON(p->cs_enabled); - - p->total_cycles = 0; - iowrite16be(0x0000, p->mapbase + TCNT); - iowrite8(0x83, p->mapbase + TCR); - bset(p->ovie, p->mapcommon + TISRC); - bset(p->enb, p->mapcommon + TSTR); - - p->cs_enabled = true; - return 0; -} - -static void timer16_disable(struct clocksource *cs) -{ - struct timer16_priv *p = cs_to_priv(cs); - - WARN_ON(!p->cs_enabled); - - bclr(p->ovie, p->mapcommon + TISRC); - bclr(p->enb, p->mapcommon + TSTR); - - p->cs_enabled = false; -} - -static struct timer16_priv timer16_priv = { - .cs = { - .name = "h8300_16timer", - .rating = 200, - .read = timer16_clocksource_read, - .enable = timer16_enable, - .disable = timer16_disable, - .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, - }, -}; - -#define REG_CH 0 -#define REG_COMM 1 - -static int __init h8300_16timer_init(struct device_node *node) -{ - void __iomem *base[2]; - int ret, irq; - unsigned int ch; - struct clk *clk; - - clk = of_clk_get(node, 0); - if (IS_ERR(clk)) { - pr_err("failed to get clock for clocksource\n"); - return PTR_ERR(clk); - } - - ret = -ENXIO; - base[REG_CH] = of_iomap(node, 0); - if (!base[REG_CH]) { - pr_err("failed to map registers for clocksource\n"); - goto free_clk; - } - - base[REG_COMM] = of_iomap(node, 1); - if (!base[REG_COMM]) { - pr_err("failed to map registers for clocksource\n"); - goto unmap_ch; - } - - ret = -EINVAL; - irq = irq_of_parse_and_map(node, 0); - if (!irq) { - pr_err("failed to get irq for clockevent\n"); - goto unmap_comm; - } - - of_property_read_u32(node, "renesas,channel", &ch); - - timer16_priv.mapbase = base[REG_CH]; - timer16_priv.mapcommon = base[REG_COMM]; - timer16_priv.enb = ch; - timer16_priv.ovf = ch; - timer16_priv.ovie = 4 + ch; - - ret = request_irq(irq, timer16_interrupt, - IRQF_TIMER, timer16_priv.cs.name, &timer16_priv); - if (ret < 0) { - pr_err("failed to request irq %d of clocksource\n", irq); - goto unmap_comm; - } - - clocksource_register_hz(&timer16_priv.cs, - clk_get_rate(clk) / 8); - return 0; - -unmap_comm: - iounmap(base[REG_COMM]); -unmap_ch: - iounmap(base[REG_CH]); -free_clk: - clk_put(clk); - return ret; -} - -TIMER_OF_DECLARE(h8300_16bit, "renesas,16bit-timer", - h8300_16timer_init); diff --git a/drivers/clocksource/h8300_timer8.c b/drivers/clocksource/h8300_timer8.c deleted file mode 100644 index 47114c2a7cb5..000000000000 --- a/drivers/clocksource/h8300_timer8.c +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * linux/arch/h8300/kernel/cpu/timer/timer8.c - * - * Yoshinori Sato - * - * 8bit Timer driver - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define _8TCR 0 -#define _8TCSR 2 -#define TCORA 4 -#define TCORB 6 -#define _8TCNT 8 - -#define CMIEA 6 -#define CMFA 6 - -#define FLAG_STARTED (1 << 3) - -#define SCALE 64 - -#define bset(b, a) iowrite8(ioread8(a) | (1 << (b)), (a)) -#define bclr(b, a) iowrite8(ioread8(a) & ~(1 << (b)), (a)) - -struct timer8_priv { - struct clock_event_device ced; - void __iomem *mapbase; - unsigned long flags; - unsigned int rate; -}; - -static irqreturn_t timer8_interrupt(int irq, void *dev_id) -{ - struct timer8_priv *p = dev_id; - - if (clockevent_state_oneshot(&p->ced)) - iowrite16be(0x0000, p->mapbase + _8TCR); - - p->ced.event_handler(&p->ced); - - bclr(CMFA, p->mapbase + _8TCSR); - - return IRQ_HANDLED; -} - -static void timer8_set_next(struct timer8_priv *p, unsigned long delta) -{ - if (delta >= 0x10000) - pr_warn("delta out of range\n"); - bclr(CMIEA, p->mapbase + _8TCR); - iowrite16be(delta, p->mapbase + TCORA); - iowrite16be(0x0000, p->mapbase + _8TCNT); - bclr(CMFA, p->mapbase + _8TCSR); - bset(CMIEA, p->mapbase + _8TCR); -} - -static int timer8_enable(struct timer8_priv *p) -{ - iowrite16be(0xffff, p->mapbase + TCORA); - iowrite16be(0x0000, p->mapbase + _8TCNT); - iowrite16be(0x0c02, p->mapbase + _8TCR); - - return 0; -} - -static int timer8_start(struct timer8_priv *p) -{ - int ret; - - if ((p->flags & FLAG_STARTED)) - return 0; - - ret = timer8_enable(p); - if (!ret) - p->flags |= FLAG_STARTED; - - return ret; -} - -static void timer8_stop(struct timer8_priv *p) -{ - iowrite16be(0x0000, p->mapbase + _8TCR); -} - -static inline struct timer8_priv *ced_to_priv(struct clock_event_device *ced) -{ - return container_of(ced, struct timer8_priv, ced); -} - -static void timer8_clock_event_start(struct timer8_priv *p, unsigned long delta) -{ - timer8_start(p); - timer8_set_next(p, delta); -} - -static int timer8_clock_event_shutdown(struct clock_event_device *ced) -{ - timer8_stop(ced_to_priv(ced)); - return 0; -} - -static int timer8_clock_event_periodic(struct clock_event_device *ced) -{ - struct timer8_priv *p = ced_to_priv(ced); - - pr_info("%s: used for periodic clock events\n", ced->name); - timer8_stop(p); - timer8_clock_event_start(p, (p->rate + HZ/2) / HZ); - - return 0; -} - -static int timer8_clock_event_oneshot(struct clock_event_device *ced) -{ - struct timer8_priv *p = ced_to_priv(ced); - - pr_info("%s: used for oneshot clock events\n", ced->name); - timer8_stop(p); - timer8_clock_event_start(p, 0x10000); - - return 0; -} - -static int timer8_clock_event_next(unsigned long delta, - struct clock_event_device *ced) -{ - struct timer8_priv *p = ced_to_priv(ced); - - BUG_ON(!clockevent_state_oneshot(ced)); - timer8_set_next(p, delta - 1); - - return 0; -} - -static struct timer8_priv timer8_priv = { - .ced = { - .name = "h8300_8timer", - .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_next_event = timer8_clock_event_next, - .set_state_shutdown = timer8_clock_event_shutdown, - .set_state_periodic = timer8_clock_event_periodic, - .set_state_oneshot = timer8_clock_event_oneshot, - }, -}; - -static int __init h8300_8timer_init(struct device_node *node) -{ - void __iomem *base; - int irq, ret; - struct clk *clk; - - clk = of_clk_get(node, 0); - if (IS_ERR(clk)) { - pr_err("failed to get clock for clockevent\n"); - return PTR_ERR(clk); - } - - ret = -ENXIO; - base = of_iomap(node, 0); - if (!base) { - pr_err("failed to map registers for clockevent\n"); - goto free_clk; - } - - ret = -EINVAL; - irq = irq_of_parse_and_map(node, 0); - if (!irq) { - pr_err("failed to get irq for clockevent\n"); - goto unmap_reg; - } - - timer8_priv.mapbase = base; - - timer8_priv.rate = clk_get_rate(clk) / SCALE; - if (!timer8_priv.rate) { - pr_err("Failed to get rate for the clocksource\n"); - goto unmap_reg; - } - - if (request_irq(irq, timer8_interrupt, IRQF_TIMER, - timer8_priv.ced.name, &timer8_priv) < 0) { - pr_err("failed to request irq %d for clockevent\n", irq); - goto unmap_reg; - } - - clockevents_config_and_register(&timer8_priv.ced, - timer8_priv.rate, 1, 0x0000ffff); - - return 0; -unmap_reg: - iounmap(base); -free_clk: - clk_put(clk); - return ret; -} - -TIMER_OF_DECLARE(h8300_8bit, "renesas,8bit-timer", h8300_8timer_init); diff --git a/drivers/clocksource/h8300_tpu.c b/drivers/clocksource/h8300_tpu.c deleted file mode 100644 index 17d4ab0f6ad1..000000000000 --- a/drivers/clocksource/h8300_tpu.c +++ /dev/null @@ -1,158 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * H8S TPU Driver - * - * Copyright 2015 Yoshinori Sato - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TCR 0x0 -#define TSR 0x5 -#define TCNT 0x6 - -#define TCFV 0x10 - -struct tpu_priv { - struct clocksource cs; - void __iomem *mapbase1; - void __iomem *mapbase2; - raw_spinlock_t lock; - unsigned int cs_enabled; -}; - -static inline unsigned long read_tcnt32(struct tpu_priv *p) -{ - unsigned long tcnt; - - tcnt = ioread16be(p->mapbase1 + TCNT) << 16; - tcnt |= ioread16be(p->mapbase2 + TCNT); - return tcnt; -} - -static int tpu_get_counter(struct tpu_priv *p, unsigned long long *val) -{ - unsigned long v1, v2, v3; - int o1, o2; - - o1 = ioread8(p->mapbase1 + TSR) & TCFV; - - /* Make sure the timer value is stable. Stolen from acpi_pm.c */ - do { - o2 = o1; - v1 = read_tcnt32(p); - v2 = read_tcnt32(p); - v3 = read_tcnt32(p); - o1 = ioread8(p->mapbase1 + TSR) & TCFV; - } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) - || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); - - *val = v2; - return o1; -} - -static inline struct tpu_priv *cs_to_priv(struct clocksource *cs) -{ - return container_of(cs, struct tpu_priv, cs); -} - -static u64 tpu_clocksource_read(struct clocksource *cs) -{ - struct tpu_priv *p = cs_to_priv(cs); - unsigned long flags; - unsigned long long value; - - raw_spin_lock_irqsave(&p->lock, flags); - if (tpu_get_counter(p, &value)) - value += 0x100000000; - raw_spin_unlock_irqrestore(&p->lock, flags); - - return value; -} - -static int tpu_clocksource_enable(struct clocksource *cs) -{ - struct tpu_priv *p = cs_to_priv(cs); - - WARN_ON(p->cs_enabled); - - iowrite16be(0, p->mapbase1 + TCNT); - iowrite16be(0, p->mapbase2 + TCNT); - iowrite8(0x0f, p->mapbase1 + TCR); - iowrite8(0x03, p->mapbase2 + TCR); - - p->cs_enabled = true; - return 0; -} - -static void tpu_clocksource_disable(struct clocksource *cs) -{ - struct tpu_priv *p = cs_to_priv(cs); - - WARN_ON(!p->cs_enabled); - - iowrite8(0, p->mapbase1 + TCR); - iowrite8(0, p->mapbase2 + TCR); - p->cs_enabled = false; -} - -static struct tpu_priv tpu_priv = { - .cs = { - .name = "H8S_TPU", - .rating = 200, - .read = tpu_clocksource_read, - .enable = tpu_clocksource_enable, - .disable = tpu_clocksource_disable, - .mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8), - .flags = CLOCK_SOURCE_IS_CONTINUOUS, - }, -}; - -#define CH_L 0 -#define CH_H 1 - -static int __init h8300_tpu_init(struct device_node *node) -{ - void __iomem *base[2]; - struct clk *clk; - int ret = -ENXIO; - - clk = of_clk_get(node, 0); - if (IS_ERR(clk)) { - pr_err("failed to get clock for clocksource\n"); - return PTR_ERR(clk); - } - - base[CH_L] = of_iomap(node, CH_L); - if (!base[CH_L]) { - pr_err("failed to map registers for clocksource\n"); - goto free_clk; - } - base[CH_H] = of_iomap(node, CH_H); - if (!base[CH_H]) { - pr_err("failed to map registers for clocksource\n"); - goto unmap_L; - } - - tpu_priv.mapbase1 = base[CH_L]; - tpu_priv.mapbase2 = base[CH_H]; - - return clocksource_register_hz(&tpu_priv.cs, clk_get_rate(clk) / 64); - -unmap_L: - iounmap(base[CH_H]); -free_clk: - clk_put(clk); - return ret; -} - -TIMER_OF_DECLARE(h8300_tpu, "renesas,tpu", h8300_tpu_init); diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 7038957f4a77..95f5d14557f3 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -330,17 +330,6 @@ config INGENIC_TCU_IRQ If unsure, say N. -config RENESAS_H8300H_INTC - bool - select IRQ_DOMAIN - -config RENESAS_H8S_INTC - bool "Renesas H8S Interrupt Controller Support" if COMPILE_TEST - select IRQ_DOMAIN - help - Enable support for the Renesas H8/300 Interrupt Controller, as found - on Renesas H8S SoCs. - config IMX_GPCV2 bool select IRQ_DOMAIN diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index c1f611cbfbf8..e555dba371bf 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -70,8 +70,6 @@ obj-$(CONFIG_KEYSTONE_IRQ) += irq-keystone.o obj-$(CONFIG_MIPS_GIC) += irq-mips-gic.o obj-$(CONFIG_ARCH_MEDIATEK) += irq-mtk-sysirq.o irq-mtk-cirq.o obj-$(CONFIG_ARCH_DIGICOLOR) += irq-digicolor.o -obj-$(CONFIG_RENESAS_H8300H_INTC) += irq-renesas-h8300h.o -obj-$(CONFIG_RENESAS_H8S_INTC) += irq-renesas-h8s.o obj-$(CONFIG_ARCH_SA1100) += irq-sa11x0.o obj-$(CONFIG_INGENIC_IRQ) += irq-ingenic.o obj-$(CONFIG_INGENIC_TCU_IRQ) += irq-ingenic-tcu.o diff --git a/drivers/irqchip/irq-renesas-h8300h.c b/drivers/irqchip/irq-renesas-h8300h.c deleted file mode 100644 index 1054d74b7edd..000000000000 --- a/drivers/irqchip/irq-renesas-h8300h.c +++ /dev/null @@ -1,94 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * H8/300H interrupt controller driver - * - * Copyright 2015 Yoshinori Sato - */ - -#include -#include -#include -#include -#include -#include - -static const char ipr_bit[] = { - 7, 6, 5, 5, - 4, 4, 4, 4, 3, 3, 3, 3, - 2, 2, 2, 2, 1, 1, 1, 1, - 0, 0, 0, 0, 15, 15, 15, 15, - 14, 14, 14, 14, 13, 13, 13, 13, - -1, -1, -1, -1, 11, 11, 11, 11, - 10, 10, 10, 10, 9, 9, 9, 9, -}; - -static void __iomem *intc_baseaddr; - -#define IPR (intc_baseaddr + 6) - -static void h8300h_disable_irq(struct irq_data *data) -{ - int bit; - int irq = data->irq - 12; - - bit = ipr_bit[irq]; - if (bit >= 0) { - if (bit < 8) - ctrl_bclr(bit & 7, IPR); - else - ctrl_bclr(bit & 7, (IPR+1)); - } -} - -static void h8300h_enable_irq(struct irq_data *data) -{ - int bit; - int irq = data->irq - 12; - - bit = ipr_bit[irq]; - if (bit >= 0) { - if (bit < 8) - ctrl_bset(bit & 7, IPR); - else - ctrl_bset(bit & 7, (IPR+1)); - } -} - -struct irq_chip h8300h_irq_chip = { - .name = "H8/300H-INTC", - .irq_enable = h8300h_enable_irq, - .irq_disable = h8300h_disable_irq, -}; - -static int irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw_irq_num) -{ - irq_set_chip_and_handler(virq, &h8300h_irq_chip, handle_simple_irq); - - return 0; -} - -static const struct irq_domain_ops irq_ops = { - .map = irq_map, - .xlate = irq_domain_xlate_onecell, -}; - -static int __init h8300h_intc_of_init(struct device_node *intc, - struct device_node *parent) -{ - struct irq_domain *domain; - - intc_baseaddr = of_iomap(intc, 0); - BUG_ON(!intc_baseaddr); - - /* All interrupt priority low */ - writeb(0x00, IPR + 0); - writeb(0x00, IPR + 1); - - domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, NULL); - BUG_ON(!domain); - irq_set_default_host(domain); - return 0; -} - -IRQCHIP_DECLARE(h8300h_intc, "renesas,h8300h-intc", h8300h_intc_of_init); diff --git a/drivers/irqchip/irq-renesas-h8s.c b/drivers/irqchip/irq-renesas-h8s.c deleted file mode 100644 index 4e2461bae944..000000000000 --- a/drivers/irqchip/irq-renesas-h8s.c +++ /dev/null @@ -1,102 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * H8S interrupt controller driver - * - * Copyright 2015 Yoshinori Sato - */ - -#include -#include -#include -#include -#include - -static void *intc_baseaddr; -#define IPRA (intc_baseaddr) - -static const unsigned char ipr_table[] = { - 0x03, 0x02, 0x01, 0x00, 0x13, 0x12, 0x11, 0x10, /* 16 - 23 */ - 0x23, 0x22, 0x21, 0x20, 0x33, 0x32, 0x31, 0x30, /* 24 - 31 */ - 0x43, 0x42, 0x41, 0x40, 0x53, 0x53, 0x52, 0x52, /* 32 - 39 */ - 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, /* 40 - 47 */ - 0x50, 0x50, 0x50, 0x50, 0x63, 0x63, 0x63, 0x63, /* 48 - 55 */ - 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, /* 56 - 63 */ - 0x61, 0x61, 0x61, 0x61, 0x60, 0x60, 0x60, 0x60, /* 64 - 71 */ - 0x73, 0x73, 0x73, 0x73, 0x72, 0x72, 0x72, 0x72, /* 72 - 79 */ - 0x71, 0x71, 0x71, 0x71, 0x70, 0x83, 0x82, 0x81, /* 80 - 87 */ - 0x80, 0x80, 0x80, 0x80, 0x93, 0x93, 0x93, 0x93, /* 88 - 95 */ - 0x92, 0x92, 0x92, 0x92, 0x91, 0x91, 0x91, 0x91, /* 96 - 103 */ - 0x90, 0x90, 0x90, 0x90, 0xa3, 0xa3, 0xa3, 0xa3, /* 104 - 111 */ - 0xa2, 0xa2, 0xa2, 0xa2, 0xa1, 0xa1, 0xa1, 0xa1, /* 112 - 119 */ - 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, /* 120 - 127 */ -}; - -static void h8s_disable_irq(struct irq_data *data) -{ - int pos; - void __iomem *addr; - unsigned short pri; - int irq = data->irq; - - addr = IPRA + ((ipr_table[irq - 16] & 0xf0) >> 3); - pos = (ipr_table[irq - 16] & 0x0f) * 4; - pri = ~(0x000f << pos); - pri &= readw(addr); - writew(pri, addr); -} - -static void h8s_enable_irq(struct irq_data *data) -{ - int pos; - void __iomem *addr; - unsigned short pri; - int irq = data->irq; - - addr = IPRA + ((ipr_table[irq - 16] & 0xf0) >> 3); - pos = (ipr_table[irq - 16] & 0x0f) * 4; - pri = ~(0x000f << pos); - pri &= readw(addr); - pri |= 1 << pos; - writew(pri, addr); -} - -struct irq_chip h8s_irq_chip = { - .name = "H8S-INTC", - .irq_enable = h8s_enable_irq, - .irq_disable = h8s_disable_irq, -}; - -static __init int irq_map(struct irq_domain *h, unsigned int virq, - irq_hw_number_t hw_irq_num) -{ - irq_set_chip_and_handler(virq, &h8s_irq_chip, handle_simple_irq); - - return 0; -} - -static const struct irq_domain_ops irq_ops = { - .map = irq_map, - .xlate = irq_domain_xlate_onecell, -}; - -static int __init h8s_intc_of_init(struct device_node *intc, - struct device_node *parent) -{ - struct irq_domain *domain; - int n; - - intc_baseaddr = of_iomap(intc, 0); - BUG_ON(!intc_baseaddr); - - /* All interrupt priority is 0 (disable) */ - /* IPRA to IPRK */ - for (n = 0; n <= 'k' - 'a'; n++) - writew(0x0000, IPRA + (n * 2)); - - domain = irq_domain_add_linear(intc, NR_IRQS, &irq_ops, NULL); - BUG_ON(!domain); - irq_set_default_host(domain); - return 0; -} - -IRQCHIP_DECLARE(h8s_intc, "renesas,h8s-intc", h8s_intc_of_init); diff --git a/drivers/net/ethernet/smsc/Kconfig b/drivers/net/ethernet/smsc/Kconfig index 72e42a868346..2524c907f386 100644 --- a/drivers/net/ethernet/smsc/Kconfig +++ b/drivers/net/ethernet/smsc/Kconfig @@ -8,7 +8,7 @@ config NET_VENDOR_SMSC default y depends on ARM || ARM64 || ATARI_ETHERNAT || COLDFIRE || \ ISA || MAC || MIPS || NIOS2 || PCI || \ - PCMCIA || SUPERH || XTENSA || H8300 || COMPILE_TEST + PCMCIA || SUPERH || XTENSA || COMPILE_TEST help If you have a network (Ethernet) card belonging to this class, say Y. @@ -40,7 +40,7 @@ config SMC91X select MII depends on !OF || GPIOLIB depends on ARM || ARM64 || ATARI_ETHERNAT || COLDFIRE || \ - MIPS || NIOS2 || SUPERH || XTENSA || H8300 || COMPILE_TEST + MIPS || NIOS2 || SUPERH || XTENSA || COMPILE_TEST help This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it diff --git a/drivers/net/ethernet/smsc/smc91x.h b/drivers/net/ethernet/smsc/smc91x.h index 387539a8094b..c521ea8f94f2 100644 --- a/drivers/net/ethernet/smsc/smc91x.h +++ b/drivers/net/ethernet/smsc/smc91x.h @@ -182,17 +182,6 @@ static inline void mcf_outsw(void *a, unsigned char *p, int l) #define SMC_IRQ_FLAGS 0 -#elif defined(CONFIG_H8300) -#define SMC_CAN_USE_8BIT 1 -#define SMC_CAN_USE_16BIT 0 -#define SMC_CAN_USE_32BIT 0 -#define SMC_NOWAIT 0 - -#define SMC_inb(a, r) ioread8((a) + (r)) -#define SMC_outb(v, a, r) iowrite8(v, (a) + (r)) -#define SMC_insb(a, r, p, l) ioread8_rep((a) + (r), p, l) -#define SMC_outsb(a, r, p, l) iowrite8_rep((a) + (r), p, l) - #else /* diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 0e5ccb25bdb1..3eaf8fbd76f9 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -653,7 +653,7 @@ config SERIAL_IP22_ZILOG_CONSOLE config SERIAL_SH_SCI tristate "SuperH SCI(F) serial port support" - depends on SUPERH || ARCH_RENESAS || H8300 || COMPILE_TEST + depends on SUPERH || ARCH_RENESAS || COMPILE_TEST select SERIAL_CORE select SERIAL_MCTRL_GPIO if GPIOLIB @@ -662,7 +662,6 @@ config SERIAL_SH_SCI_NR_UARTS range 1 64 if 64BIT range 1 32 if !64BIT depends on SERIAL_SH_SCI - default "3" if H8300 default "10" if SUPERH default "18" if ARCH_RENESAS default "2" @@ -678,7 +677,7 @@ config SERIAL_SH_SCI_EARLYCON depends on SERIAL_SH_SCI=y select SERIAL_CORE_CONSOLE select SERIAL_EARLYCON - default ARCH_RENESAS || H8300 + default ARCH_RENESAS config SERIAL_SH_SCI_DMA bool "DMA support" if EXPERT diff --git a/init/Kconfig b/init/Kconfig index e9119bf54b1f..9a11d3755811 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -711,8 +711,7 @@ config IKHEADERS config LOG_BUF_SHIFT int "Kernel log buffer size (16 => 64KB, 17 => 128KB)" - range 12 25 if !H8300 - range 12 19 if H8300 + range 12 25 default 17 depends on PRINTK help diff --git a/tools/arch/h8300/include/asm/bitsperlong.h b/tools/arch/h8300/include/asm/bitsperlong.h deleted file mode 100644 index fa1508337ffc..000000000000 --- a/tools/arch/h8300/include/asm/bitsperlong.h +++ /dev/null @@ -1,15 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __ASM_H8300_BITS_PER_LONG -#define __ASM_H8300_BITS_PER_LONG - -#include - -#if !defined(__ASSEMBLY__) -/* h8300-unknown-linux required long */ -#define __kernel_size_t __kernel_size_t -typedef unsigned long __kernel_size_t; -typedef long __kernel_ssize_t; -typedef long __kernel_ptrdiff_t; -#endif - -#endif /* __ASM_H8300_BITS_PER_LONG */ diff --git a/tools/arch/h8300/include/uapi/asm/mman.h b/tools/arch/h8300/include/uapi/asm/mman.h deleted file mode 100644 index be7bbe0528d1..000000000000 --- a/tools/arch/h8300/include/uapi/asm/mman.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ -#ifndef TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H -#define TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H -#include -/* MAP_32BIT is undefined on h8300, fix it for perf */ -#define MAP_32BIT 0 -#endif From c6e7deb0f092616bd8cb19e8c436b212c64daaab Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 18 Jan 2022 13:55:43 +0200 Subject: [PATCH 00017/11454] drm/i915: Introduce new Tile 4 format This tiling layout uses 4KB tiles in a row-major layout. It has the same shape as Tile Y at two granularities: 4KB (128B x 32) and 64B (16B x 4). It only differs from Tile Y at the 256B granularity in between. At this granularity, Tile Y has a shape of 16B x 32 rows, but this tiling has a shape of 64B x 8 rows. Reviewed-by: Imre Deak Acked-by: Nanley Chery Signed-off-by: Stanislav Lisovskiy Link: https://patchwork.freedesktop.org/patch/msgid/20220118115544.15116-2-stanislav.lisovskiy@intel.com --- include/uapi/drm/drm_fourcc.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h index fc0c1454d275..b73fe6797fc3 100644 --- a/include/uapi/drm/drm_fourcc.h +++ b/include/uapi/drm/drm_fourcc.h @@ -572,6 +572,17 @@ extern "C" { */ #define I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC fourcc_mod_code(INTEL, 8) +/* + * Intel Tile 4 layout + * + * This is a tiled layout using 4KB tiles in a row-major layout. It has the same + * shape as Tile Y at two granularities: 4KB (128B x 32) and 64B (16B x 4). It + * only differs from Tile Y at the 256B granularity in between. At this + * granularity, Tile Y has a shape of 16B x 32 rows, but this tiling has a shape + * of 64B x 8 rows. + */ +#define I915_FORMAT_MOD_4_TILED fourcc_mod_code(INTEL, 9) + /* * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks * From 072ce4164f973bc762b25ce9a41636bffe75ab36 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Tue, 18 Jan 2022 13:55:44 +0200 Subject: [PATCH 00018/11454] drm/i915/dg2: Tile 4 plane format support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tile4 in bspec format is 4K tile organized into 64B subtiles with same basic shape as for legacy TileY which will be supported by Display13. v2: - Moved Tile4 associating struct for modifier/display to the beginning(Imre Deak) - Removed unneeded case I915_FORMAT_MOD_4_TILED modifier checks(Imre Deak) - Fixed I915_FORMAT_MOD_4_TILED to be 9 instead of 12 (Imre Deak) v3: - Rebased patch on top of new changes related to plane_caps. - Added static assert to check that PLANE_CTL_TILING_YF matches PLANE_CTL_TILING_4(Nanley Chery) - Fixed naming and layout description for Tile 4 in drm uapi header(Nanley Chery) v4: - Extracted drm_fourcc changes to separate patch(Nanley Chery) Reviewed-by: Imre Deak Cc: Matt Roper Cc: Maarten Lankhorst Signed-off-by: Stanislav Lisovskiy Signed-off-by: Matt Roper Signed-off-by: Juha-Pekka Heikkilä Link: https://patchwork.freedesktop.org/patch/msgid/20220118115544.15116-3-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 1 + drivers/gpu/drm/i915/display/intel_fb.c | 15 +++++++++++- drivers/gpu/drm/i915/display/intel_fb.h | 1 + drivers/gpu/drm/i915/display/intel_fbc.c | 1 + .../drm/i915/display/intel_plane_initial.c | 1 + .../drm/i915/display/skl_universal_plane.c | 23 ++++++++++++------- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_pci.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 1 + drivers/gpu/drm/i915/intel_device_info.h | 1 + drivers/gpu/drm/i915/intel_pm.c | 1 + 11 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 80b19c304c43..7bf24df20b14 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7458,6 +7458,7 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: + case I915_FORMAT_MOD_4_TILED: break; default: drm_dbg_kms(&i915->drm, diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 23cfe2e5ce2a..94c57facbb46 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -135,11 +135,16 @@ struct intel_modifier_desc { INTEL_PLANE_CAP_CCS_MC) #define INTEL_PLANE_CAP_TILING_MASK (INTEL_PLANE_CAP_TILING_X | \ INTEL_PLANE_CAP_TILING_Y | \ - INTEL_PLANE_CAP_TILING_Yf) + INTEL_PLANE_CAP_TILING_Yf | \ + INTEL_PLANE_CAP_TILING_4) #define INTEL_PLANE_CAP_TILING_NONE 0 static const struct intel_modifier_desc intel_modifiers[] = { { + .modifier = I915_FORMAT_MOD_4_TILED, + .display_ver = { 13, 13 }, + .plane_caps = INTEL_PLANE_CAP_TILING_4, + }, { .modifier = I915_FORMAT_MOD_Y_TILED_GEN12_MC_CCS, .display_ver = { 12, 13 }, .plane_caps = INTEL_PLANE_CAP_TILING_Y | INTEL_PLANE_CAP_CCS_MC, @@ -545,6 +550,12 @@ intel_tile_width_bytes(const struct drm_framebuffer *fb, int color_plane) return 128; else return 512; + case I915_FORMAT_MOD_4_TILED: + /* + * Each 4K tile consists of 64B(8*8) subtiles, with + * same shape as Y Tile(i.e 4*16B OWords) + */ + return 128; case I915_FORMAT_MOD_Y_TILED_CCS: if (intel_fb_is_ccs_aux_plane(fb, color_plane)) return 128; @@ -650,6 +661,7 @@ static unsigned int intel_fb_modifier_to_tiling(u64 fb_modifier) return I915_TILING_Y; case INTEL_PLANE_CAP_TILING_X: return I915_TILING_X; + case INTEL_PLANE_CAP_TILING_4: case INTEL_PLANE_CAP_TILING_Yf: case INTEL_PLANE_CAP_TILING_NONE: return I915_TILING_NONE; @@ -737,6 +749,7 @@ unsigned int intel_surf_alignment(const struct drm_framebuffer *fb, case I915_FORMAT_MOD_Y_TILED_CCS: case I915_FORMAT_MOD_Yf_TILED_CCS: case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_4_TILED: case I915_FORMAT_MOD_Yf_TILED: return 1 * 1024 * 1024; default: diff --git a/drivers/gpu/drm/i915/display/intel_fb.h b/drivers/gpu/drm/i915/display/intel_fb.h index ba9df8986c1e..12386f13a4e0 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.h +++ b/drivers/gpu/drm/i915/display/intel_fb.h @@ -27,6 +27,7 @@ struct intel_plane_state; #define INTEL_PLANE_CAP_TILING_X BIT(3) #define INTEL_PLANE_CAP_TILING_Y BIT(4) #define INTEL_PLANE_CAP_TILING_Yf BIT(5) +#define INTEL_PLANE_CAP_TILING_4 BIT(6) bool intel_fb_is_ccs_modifier(u64 modifier); bool intel_fb_is_rc_ccs_cc_modifier(u64 modifier); diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 87f4af3fd523..f7dca327c294 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -946,6 +946,7 @@ static bool tiling_is_valid(const struct intel_plane_state *plane_state) case I915_FORMAT_MOD_Y_TILED: case I915_FORMAT_MOD_Yf_TILED: return DISPLAY_VER(i915) >= 9; + case I915_FORMAT_MOD_4_TILED: case I915_FORMAT_MOD_X_TILED: return true; default: diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index d7b1de4cc205..e207d12286b5 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -127,6 +127,7 @@ intel_alloc_initial_plane_obj(struct intel_crtc *crtc, case DRM_FORMAT_MOD_LINEAR: case I915_FORMAT_MOD_X_TILED: case I915_FORMAT_MOD_Y_TILED: + case I915_FORMAT_MOD_4_TILED: break; default: drm_dbg(&dev_priv->drm, diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 1223075595ff..5299dfe68802 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -762,6 +762,8 @@ static u32 skl_plane_ctl_tiling(u64 fb_modifier) return PLANE_CTL_TILED_X; case I915_FORMAT_MOD_Y_TILED: return PLANE_CTL_TILED_Y; + case I915_FORMAT_MOD_4_TILED: + return PLANE_CTL_TILED_4; case I915_FORMAT_MOD_Y_TILED_CCS: case I915_FORMAT_MOD_Y_TILED_GEN12_RC_CCS_CC: return PLANE_CTL_TILED_Y | PLANE_CTL_RENDER_DECOMPRESSION_ENABLE; @@ -2011,9 +2013,7 @@ static bool gen12_plane_format_mod_supported(struct drm_plane *_plane, case DRM_FORMAT_Y216: case DRM_FORMAT_XVYU12_16161616: case DRM_FORMAT_XVYU16161616: - if (modifier == DRM_FORMAT_MOD_LINEAR || - modifier == I915_FORMAT_MOD_X_TILED || - modifier == I915_FORMAT_MOD_Y_TILED) + if (!intel_fb_is_ccs_modifier(modifier)) return true; fallthrough; default: @@ -2106,6 +2106,8 @@ static u8 skl_get_plane_caps(struct drm_i915_private *i915, caps |= INTEL_PLANE_CAP_TILING_Y; if (DISPLAY_VER(i915) < 12) caps |= INTEL_PLANE_CAP_TILING_Yf; + if (HAS_4TILE(i915)) + caps |= INTEL_PLANE_CAP_TILING_4; if (skl_plane_has_rc_ccs(i915, pipe, plane_id)) { caps |= INTEL_PLANE_CAP_CCS_RC; @@ -2278,6 +2280,7 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, unsigned int aligned_height; struct drm_framebuffer *fb; struct intel_framebuffer *intel_fb; + static_assert(PLANE_CTL_TILED_YF == PLANE_CTL_TILED_4); if (!plane->get_hw_state(plane, &pipe)) return; @@ -2340,11 +2343,15 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, else fb->modifier = I915_FORMAT_MOD_Y_TILED; break; - case PLANE_CTL_TILED_YF: - if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) - fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; - else - fb->modifier = I915_FORMAT_MOD_Yf_TILED; + case PLANE_CTL_TILED_YF: /* aka PLANE_CTL_TILED_4 on XE_LPD+ */ + if (HAS_4TILE(dev_priv)) { + fb->modifier = I915_FORMAT_MOD_4_TILED; + } else { + if (val & PLANE_CTL_RENDER_DECOMPRESSION_ENABLE) + fb->modifier = I915_FORMAT_MOD_Yf_TILED_CCS; + else + fb->modifier = I915_FORMAT_MOD_Yf_TILED; + } break; default: MISSING_CASE(tiling); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f600d1cb01b3..e71dcd2701ca 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1252,6 +1252,7 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define CMDPARSER_USES_GGTT(dev_priv) (GRAPHICS_VER(dev_priv) == 7) #define HAS_LLC(dev_priv) (INTEL_INFO(dev_priv)->has_llc) +#define HAS_4TILE(dev_priv) (INTEL_INFO(dev_priv)->has_4tile) #define HAS_SNOOP(dev_priv) (INTEL_INFO(dev_priv)->has_snoop) #define HAS_EDRAM(dev_priv) ((dev_priv)->edram_size_mb) #define HAS_SECURE_BATCHES(dev_priv) (GRAPHICS_VER(dev_priv) < 6) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 8246cbe9b01d..a95ae08b071c 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1046,6 +1046,7 @@ static const struct intel_device_info dg2_info = { DGFX_FEATURES, .graphics.rel = 55, .media.rel = 55, + .has_4tile = 1, PLATFORM(INTEL_DG2), .has_guc_deprivilege = 1, .has_64k_pages = 1, diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 2b8a3086ed35..5f6c307f476a 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4844,6 +4844,7 @@ #define PLANE_CTL_TILED_X REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 1) #define PLANE_CTL_TILED_Y REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 4) #define PLANE_CTL_TILED_YF REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5) +#define PLANE_CTL_TILED_4 REG_FIELD_PREP(PLANE_CTL_TILED_MASK, 5) #define PLANE_CTL_ASYNC_FLIP REG_BIT(9) #define PLANE_CTL_FLIP_HORIZONTAL REG_BIT(8) #define PLANE_CTL_MEDIA_DECOMPRESSION_ENABLE REG_BIT(4) /* TGL+ */ diff --git a/drivers/gpu/drm/i915/intel_device_info.h b/drivers/gpu/drm/i915/intel_device_info.h index 27dcfe6f2429..8026e805ff12 100644 --- a/drivers/gpu/drm/i915/intel_device_info.h +++ b/drivers/gpu/drm/i915/intel_device_info.h @@ -133,6 +133,7 @@ enum intel_ppgtt_type { func(has_64k_pages); \ func(gpu_reset_clobbers_display); \ func(has_reset_engine); \ + func(has_4tile); \ func(has_global_mocs); \ func(has_gt_uc); \ func(has_guc_deprivilege); \ diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 5af16ca4dabd..51308211618e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5415,6 +5415,7 @@ skl_compute_wm_params(const struct intel_crtc_state *crtc_state, } wp->y_tiled = modifier == I915_FORMAT_MOD_Y_TILED || + modifier == I915_FORMAT_MOD_4_TILED || modifier == I915_FORMAT_MOD_Yf_TILED || modifier == I915_FORMAT_MOD_Y_TILED_CCS || modifier == I915_FORMAT_MOD_Yf_TILED_CCS; From f8a005eb89720c913e59707d061a1b7e9c8b3358 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Feb 2022 08:23:59 +0200 Subject: [PATCH 00019/11454] drm/i915: Optimize icl+ universal plane programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On icl+ all plane registers are armed by PLANE_SURF, so we can move almost everything over into the update_noarm() hook. The PLANE_CTL write has to stay in the icl_update_arm() hook though as it still exhibits the somewhat annoying self-arming behaviour when the plane transitioning from disabled to enabled. We could either do a full split for skl+ vs. icl+, or we could try some other kind of split where we'd eg. keep most things in the skl+ functions and call them from the icl+ functions. I think a full split is probably the cleaner approach since we've anyway accumulated quite a bit of icl+ specific things, so that is what I opted to do. Some i915_update_info stats for tgl: before: after: Updates: 5043 Updates: 5043 | | 1us | 1us | |** |*** 4us |****** 4us |******** |********** |*********** 16us |*********** 16us |********** |**** |* 66us | 66us | | | 262us | 262us | | | 1ms | 1ms | | | 4ms | 4ms | | | 17ms | 17ms | | | Min update: 3494ns Min update: 2983ns Max update: 49491ns Max update: 39986ns Average update: 18031ns Average update: 13423ns Overruns > 100us: 0 Overruns > 100us: 0 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220210062403.18690-2-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- .../drm/i915/display/skl_universal_plane.c | 197 ++++++++++++++---- 1 file changed, 156 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index 5299dfe68802..e9418c421fb3 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -619,6 +619,25 @@ skl_plane_disable_arm(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + skl_write_plane_wm(plane, crtc_state); + + intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0); + intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void +icl_plane_disable_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + unsigned long irqflags; + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + if (icl_is_hdr_plane(dev_priv, plane_id)) intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0); @@ -1067,7 +1086,7 @@ static void icl_plane_csc_load_black(struct intel_plane *plane) intel_de_write_fw(i915, PLANE_CSC_POSTOFF(pipe, plane_id, 2), 0); } -static int skl_plane_color_plane(const struct intel_plane_state *plane_state) +static int icl_plane_color_plane(const struct intel_plane_state *plane_state) { /* Program the UV plane on planar master */ if (plane_state->planar_linked_plane && !plane_state->planar_slave) @@ -1084,9 +1103,7 @@ skl_plane_update_noarm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - int color_plane = skl_plane_color_plane(plane_state); - u32 stride = skl_plane_stride(plane_state, color_plane); - const struct drm_framebuffer *fb = plane_state->hw.fb; + u32 stride = skl_plane_stride(plane_state, 0); int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; @@ -1101,13 +1118,6 @@ skl_plane_update_noarm(struct intel_plane *plane, spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - /* - * FIXME: pxp session invalidation can hit any time even at time of commit - * or after the commit, display content will be garbage. - */ - if (plane_state->force_black) - icl_plane_csc_load_black(plane); - intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), PLANE_STRIDE_(stride)); intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id), @@ -1115,24 +1125,8 @@ skl_plane_update_noarm(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id), PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1)); - if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) { - intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 0), - lower_32_bits(plane_state->ccval)); - intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 1), - upper_32_bits(plane_state->ccval)); - } - - if (icl_is_hdr_plane(dev_priv, plane_id)) - intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), - plane_state->cus_ctl); - - if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id)) - icl_program_input_csc(plane, crtc_state, plane_state); - skl_write_plane_wm(plane, crtc_state); - intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } @@ -1144,14 +1138,13 @@ skl_plane_update_arm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - int color_plane = skl_plane_color_plane(plane_state); - u32 x = plane_state->view.color_plane[color_plane].x; - u32 y = plane_state->view.color_plane[color_plane].y; - u32 plane_color_ctl = 0; - u32 plane_ctl = plane_state->ctl; + u32 x = plane_state->view.color_plane[0].x; + u32 y = plane_state->view.color_plane[0].y; + u32 plane_ctl, plane_color_ctl = 0; unsigned long irqflags; - plane_ctl |= skl_plane_ctl_crtc(crtc_state); + plane_ctl = plane_state->ctl | + skl_plane_ctl_crtc(crtc_state); if (DISPLAY_VER(dev_priv) >= 10) plane_color_ctl = plane_state->color_ctl | @@ -1167,16 +1160,132 @@ skl_plane_update_arm(struct intel_plane *plane, PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x)); intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), - skl_plane_aux_dist(plane_state, color_plane)); + skl_plane_aux_dist(plane_state, 0)); - if (DISPLAY_VER(dev_priv) < 11) - intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id), - PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) | - PLANE_OFFSET_X(plane_state->view.color_plane[1].x)); + intel_de_write_fw(dev_priv, PLANE_AUX_OFFSET(pipe, plane_id), + PLANE_OFFSET_Y(plane_state->view.color_plane[1].y) | + PLANE_OFFSET_X(plane_state->view.color_plane[1].x)); if (DISPLAY_VER(dev_priv) >= 10) intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl); + /* + * Enable the scaler before the plane so that we don't + * get a catastrophic underrun even if the two operations + * end up happening in two different frames. + * + * TODO: split into noarm+arm pair + */ + if (plane_state->scaler_id >= 0) + skl_program_plane_scaler(plane, crtc_state, plane_state); + + /* + * The control register self-arms if the plane was previously + * disabled. Try to make the plane enable atomic by writing + * the control register just before the surface register. + */ + intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); + intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), + skl_plane_surf(plane_state, 0)); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void +icl_plane_update_noarm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + int color_plane = icl_plane_color_plane(plane_state); + u32 stride = skl_plane_stride(plane_state, color_plane); + const struct drm_framebuffer *fb = plane_state->hw.fb; + int crtc_x = plane_state->uapi.dst.x1; + int crtc_y = plane_state->uapi.dst.y1; + int x = plane_state->view.color_plane[color_plane].x; + int y = plane_state->view.color_plane[color_plane].y; + int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; + int src_h = drm_rect_height(&plane_state->uapi.src) >> 16; + u32 plane_color_ctl; + unsigned long irqflags; + + plane_color_ctl = plane_state->color_ctl | + glk_plane_color_ctl_crtc(crtc_state); + + /* The scaler will handle the output position */ + if (plane_state->scaler_id >= 0) { + crtc_x = 0; + crtc_y = 0; + } + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + + intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), + PLANE_STRIDE_(stride)); + intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id), + PLANE_POS_Y(crtc_y) | PLANE_POS_X(crtc_x)); + intel_de_write_fw(dev_priv, PLANE_SIZE(pipe, plane_id), + PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1)); + + intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state)); + intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state)); + intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state)); + + intel_de_write_fw(dev_priv, PLANE_OFFSET(pipe, plane_id), + PLANE_OFFSET_Y(y) | PLANE_OFFSET_X(x)); + + if (intel_fb_is_rc_ccs_cc_modifier(fb->modifier)) { + intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 0), + lower_32_bits(plane_state->ccval)); + intel_de_write_fw(dev_priv, PLANE_CC_VAL(pipe, plane_id, 1), + upper_32_bits(plane_state->ccval)); + } + + intel_de_write_fw(dev_priv, PLANE_AUX_DIST(pipe, plane_id), + skl_plane_aux_dist(plane_state, color_plane)); + + if (icl_is_hdr_plane(dev_priv, plane_id)) + intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), + plane_state->cus_ctl); + + intel_de_write_fw(dev_priv, PLANE_COLOR_CTL(pipe, plane_id), plane_color_ctl); + + if (fb->format->is_yuv && icl_is_hdr_plane(dev_priv, plane_id)) + icl_program_input_csc(plane, crtc_state, plane_state); + + skl_write_plane_wm(plane, crtc_state); + + /* + * FIXME: pxp session invalidation can hit any time even at time of commit + * or after the commit, display content will be garbage. + */ + if (plane_state->force_black) + icl_plane_csc_load_black(plane); + + intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane); + + spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); +} + +static void +icl_plane_update_arm(struct intel_plane *plane, + const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state) +{ + struct drm_i915_private *dev_priv = to_i915(plane->base.dev); + enum plane_id plane_id = plane->id; + enum pipe pipe = plane->pipe; + int color_plane = icl_plane_color_plane(plane_state); + u32 plane_ctl; + unsigned long irqflags; + + plane_ctl = plane_state->ctl | + skl_plane_ctl_crtc(crtc_state); + + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); + /* * Enable the scaler before the plane so that we don't * get a catastrophic underrun even if the two operations @@ -2164,9 +2273,15 @@ skl_universal_plane_create(struct drm_i915_private *dev_priv, } plane->max_stride = skl_plane_max_stride; - plane->update_noarm = skl_plane_update_noarm; - plane->update_arm = skl_plane_update_arm; - plane->disable_arm = skl_plane_disable_arm; + if (DISPLAY_VER(dev_priv) >= 11) { + plane->update_noarm = icl_plane_update_noarm; + plane->update_arm = icl_plane_update_arm; + plane->disable_arm = icl_plane_disable_arm; + } else { + plane->update_noarm = skl_plane_update_noarm; + plane->update_arm = skl_plane_update_arm; + plane->disable_arm = skl_plane_disable_arm; + } plane->get_hw_state = skl_plane_get_hw_state; plane->check_plane = skl_plane_check; From 14ad15296d1fd067e54ad04d96056fe0aed61f2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Feb 2022 08:24:00 +0200 Subject: [PATCH 00020/11454] drm/i915: Make skl+ universal plane registers unlocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the locks around most universal plane register writes. The lock isn't needed since each plane's register are neatly contained on their own cachelines. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220210062403.18690-3-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- .../drm/i915/display/skl_universal_plane.c | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index e9418c421fb3..fdade206f056 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -615,16 +615,11 @@ skl_plane_disable_arm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); skl_write_plane_wm(plane, crtc_state); intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0); intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -634,9 +629,6 @@ icl_plane_disable_arm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (icl_is_hdr_plane(dev_priv, plane_id)) intel_de_write_fw(dev_priv, PLANE_CUS_CTL(pipe, plane_id), 0); @@ -646,8 +638,6 @@ icl_plane_disable_arm(struct intel_plane *plane, intel_psr2_disable_plane_sel_fetch(plane, crtc_state); intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), 0); intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool @@ -1108,7 +1098,6 @@ skl_plane_update_noarm(struct intel_plane *plane, int crtc_y = plane_state->uapi.dst.y1; u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; - unsigned long irqflags; /* The scaler will handle the output position */ if (plane_state->scaler_id >= 0) { @@ -1116,8 +1105,6 @@ skl_plane_update_noarm(struct intel_plane *plane, crtc_y = 0; } - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), PLANE_STRIDE_(stride)); intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id), @@ -1126,8 +1113,6 @@ skl_plane_update_noarm(struct intel_plane *plane, PLANE_HEIGHT(src_h - 1) | PLANE_WIDTH(src_w - 1)); skl_write_plane_wm(plane, crtc_state); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -1141,7 +1126,6 @@ skl_plane_update_arm(struct intel_plane *plane, u32 x = plane_state->view.color_plane[0].x; u32 y = plane_state->view.color_plane[0].y; u32 plane_ctl, plane_color_ctl = 0; - unsigned long irqflags; plane_ctl = plane_state->ctl | skl_plane_ctl_crtc(crtc_state); @@ -1150,8 +1134,6 @@ skl_plane_update_arm(struct intel_plane *plane, plane_color_ctl = plane_state->color_ctl | glk_plane_color_ctl_crtc(crtc_state); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, PLANE_KEYVAL(pipe, plane_id), skl_plane_keyval(plane_state)); intel_de_write_fw(dev_priv, PLANE_KEYMSK(pipe, plane_id), skl_plane_keymsk(plane_state)); intel_de_write_fw(dev_priv, PLANE_KEYMAX(pipe, plane_id), skl_plane_keymax(plane_state)); @@ -1187,8 +1169,6 @@ skl_plane_update_arm(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), skl_plane_surf(plane_state, 0)); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -1209,7 +1189,6 @@ icl_plane_update_noarm(struct intel_plane *plane, int src_w = drm_rect_width(&plane_state->uapi.src) >> 16; int src_h = drm_rect_height(&plane_state->uapi.src) >> 16; u32 plane_color_ctl; - unsigned long irqflags; plane_color_ctl = plane_state->color_ctl | glk_plane_color_ctl_crtc(crtc_state); @@ -1220,8 +1199,6 @@ icl_plane_update_noarm(struct intel_plane *plane, crtc_y = 0; } - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, PLANE_STRIDE(pipe, plane_id), PLANE_STRIDE_(stride)); intel_de_write_fw(dev_priv, PLANE_POS(pipe, plane_id), @@ -1265,8 +1242,6 @@ icl_plane_update_noarm(struct intel_plane *plane, icl_plane_csc_load_black(plane); intel_psr2_program_plane_sel_fetch(plane, crtc_state, plane_state, color_plane); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -1279,13 +1254,10 @@ icl_plane_update_arm(struct intel_plane *plane, enum pipe pipe = plane->pipe; int color_plane = icl_plane_color_plane(plane_state); u32 plane_ctl; - unsigned long irqflags; plane_ctl = plane_state->ctl | skl_plane_ctl_crtc(crtc_state); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - /* * Enable the scaler before the plane so that we don't * get a catastrophic underrun even if the two operations @@ -1304,8 +1276,6 @@ icl_plane_update_arm(struct intel_plane *plane, intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), skl_plane_surf(plane_state, color_plane)); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -1315,7 +1285,6 @@ skl_plane_async_flip(struct intel_plane *plane, bool async_flip) { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); - unsigned long irqflags; enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; u32 plane_ctl = plane_state->ctl; @@ -1325,13 +1294,9 @@ skl_plane_async_flip(struct intel_plane *plane, if (async_flip) plane_ctl |= PLANE_CTL_ASYNC_FLIP; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, PLANE_CTL(pipe, plane_id), plane_ctl); intel_de_write_fw(dev_priv, PLANE_SURF(pipe, plane_id), skl_plane_surf(plane_state, 0)); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool intel_format_is_p01x(u32 format) From 0225a90981c83408e9606b52a65edee1c6891106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Feb 2022 11:26:04 +0200 Subject: [PATCH 00021/11454] drm/i915: Make cursor plane registers unlocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the locks around cursor plane register writes. The lock isn't needed since each plane's register are neatly contained on their own cachelines. The locking did have a secondary effect of disabling interrupts around the cursor registers writes though. If we drop that then we open outselves up for sceduling delays and whatnot while on the middle of the register writes. That increases the chance of not all the register writes land during the same frame. For normal atomic commits this is not a concern as the vblank evade mechanism anyway disables interrupts around the update, but the legacy cursor codepath does not. Technically we should do a vblank evade there as well, but so far no one has bothered to hook that up. So in the meantime let's put an explicit local irq disable/enable around the legacy cursor update to keep the race window minimal. v2: local_irq_{disable,enable}() for legacy cursor ioctl Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220211092604.393-1-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_cursor.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 2ade8fdd9bdd..b648be744cf2 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -255,7 +255,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane, { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); u32 cntl = 0, base = 0, pos = 0, size = 0; - unsigned long irqflags; if (plane_state && plane_state->uapi.visible) { unsigned int width = drm_rect_width(&plane_state->uapi.dst); @@ -270,8 +269,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane, pos = intel_cursor_position(plane_state); } - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - /* On these chipsets we can only modify the base/size/stride * whilst the cursor is disabled. */ @@ -290,8 +287,6 @@ static void i845_cursor_update_arm(struct intel_plane *plane, } else { intel_de_write_fw(dev_priv, CURPOS(PIPE_A), pos); } - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void i845_cursor_disable_arm(struct intel_plane *plane, @@ -492,7 +487,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; u32 cntl = 0, base = 0, pos = 0, fbc_ctl = 0; - unsigned long irqflags; if (plane_state && plane_state->uapi.visible) { int width = drm_rect_width(&plane_state->uapi.dst); @@ -508,8 +502,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane, pos = intel_cursor_position(plane_state); } - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - /* * On some platforms writing CURCNTR first will also * cause CURPOS to be armed by the CURBASE write. @@ -555,8 +547,6 @@ static void i9xx_cursor_update_arm(struct intel_plane *plane, intel_de_write_fw(dev_priv, CURPOS(pipe), pos); intel_de_write_fw(dev_priv, CURBASE(pipe), base); } - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void i9xx_cursor_disable_arm(struct intel_plane *plane, @@ -715,6 +705,14 @@ intel_legacy_cursor_update(struct drm_plane *_plane, */ crtc_state->active_planes = new_crtc_state->active_planes; + /* + * Technically we should do a vblank evasion here to make + * sure all the cursor registers update on the same frame. + * For now just make sure the register writes happen as + * quickly as possible to minimize the race window. + */ + local_irq_disable(); + if (new_plane_state->uapi.visible) { intel_plane_update_noarm(plane, crtc_state, new_plane_state); intel_plane_update_arm(plane, crtc_state, new_plane_state); @@ -722,6 +720,8 @@ intel_legacy_cursor_update(struct drm_plane *_plane, intel_plane_disable_arm(plane, crtc_state); } + local_irq_enable(); + intel_plane_unpin_fb(old_plane_state); out_free: From 7ad9993b2368f2a861f335184cd2bb1909f13827 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Feb 2022 08:24:02 +0200 Subject: [PATCH 00022/11454] drm/i915: Make most pre-skl primary plane registers unlocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the locks around most primary plane register writes. The lock isn't needed since each plane's register are neatly contained on their own cachelines. The one exception we have to make is DSPADDR/DSPSURF which is (ab)used to also trigger FBC nukes on pre-snb (since the hardware doesn't seem to have any dedicated mechanism to trigger nukes). So we need to keep the lock around it to protect against the rmw performed by the fbc code. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220210062403.18690-5-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/i9xx_plane.c | 24 +++++++++-------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/i9xx_plane.c b/drivers/gpu/drm/i915/display/i9xx_plane.c index a87b65cd41fd..af190bacdd97 100644 --- a/drivers/gpu/drm/i915/display/i9xx_plane.c +++ b/drivers/gpu/drm/i915/display/i9xx_plane.c @@ -418,9 +418,6 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane, { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPSTRIDE(i9xx_plane), plane_state->view.color_plane[0].mapping_stride); @@ -441,8 +438,6 @@ static void i9xx_plane_update_noarm(struct intel_plane *plane, intel_de_write_fw(dev_priv, DSPSIZE(i9xx_plane), DISP_HEIGHT(crtc_h - 1) | DISP_WIDTH(crtc_w - 1)); } - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void i9xx_plane_update_arm(struct intel_plane *plane, @@ -465,8 +460,6 @@ static void i9xx_plane_update_arm(struct intel_plane *plane, else dspaddr_offset = linear_offset; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - if (IS_CHERRYVIEW(dev_priv) && i9xx_plane == PLANE_B) { int crtc_x = plane_state->uapi.dst.x1; int crtc_y = plane_state->uapi.dst.y1; @@ -496,13 +489,15 @@ static void i9xx_plane_update_arm(struct intel_plane *plane, * the control register just before the surface register. */ intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + + /* lock to protect against rmw in fbc nuke */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (DISPLAY_VER(dev_priv) >= 4) intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); else intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } @@ -540,14 +535,14 @@ static void i9xx_plane_disable_arm(struct intel_plane *plane, */ dspcntr = i9xx_plane_ctl_crtc(crtc_state); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + + /* lock to protect against rmw in fbc nuke */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); if (DISPLAY_VER(dev_priv) >= 4) intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), 0); else intel_de_write_fw(dev_priv, DSPADDR(i9xx_plane), 0); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } @@ -566,8 +561,10 @@ g4x_primary_async_flip(struct intel_plane *plane, if (async_flip) dspcntr |= DISP_ASYNC_FLIP; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPCNTR(i9xx_plane), dspcntr); + + /* lock to protect against rmw in fbc nuke */ + spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPSURF(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); @@ -582,12 +579,9 @@ vlv_primary_async_flip(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); u32 dspaddr_offset = plane_state->view.color_plane[0].offset; enum i9xx_plane_id i9xx_plane = plane->i9xx_plane; - unsigned long irqflags; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DSPADDR_VLV(i9xx_plane), intel_plane_ggtt_offset(plane_state) + dspaddr_offset); - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void From 772ba8d68515fb8d5414eb714a1d4d446903eb13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Feb 2022 08:24:03 +0200 Subject: [PATCH 00023/11454] drm/i915: Make pre-skl sprite plane registers unlocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drop the locks around sprite plane register writes. The lock isn't needed since each plane's register are neatly contained on their own cachelines. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220210062403.18690-6-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_sprite.c | 45 --------------------- 1 file changed, 45 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index 2d71294aaceb..f6875a49b8cb 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -430,9 +430,6 @@ vlv_sprite_update_noarm(struct intel_plane *plane, int crtc_y = plane_state->uapi.dst.y1; u32 crtc_w = drm_rect_width(&plane_state->uapi.dst); u32 crtc_h = drm_rect_height(&plane_state->uapi.dst); - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPSTRIDE(pipe, plane_id), plane_state->view.color_plane[0].mapping_stride); @@ -440,8 +437,6 @@ vlv_sprite_update_noarm(struct intel_plane *plane, SP_POS_Y(crtc_y) | SP_POS_X(crtc_x)); intel_de_write_fw(dev_priv, SPSIZE(pipe, plane_id), SP_HEIGHT(crtc_h - 1) | SP_WIDTH(crtc_w - 1)); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -457,14 +452,11 @@ vlv_sprite_update_arm(struct intel_plane *plane, u32 x = plane_state->view.color_plane[0].x; u32 y = plane_state->view.color_plane[0].y; u32 sprctl, linear_offset; - unsigned long irqflags; sprctl = plane_state->ctl | vlv_sprite_ctl_crtc(crtc_state); linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B) chv_sprite_update_csc(plane_state); @@ -494,8 +486,6 @@ vlv_sprite_update_arm(struct intel_plane *plane, vlv_sprite_update_clrc(plane_state); vlv_sprite_update_gamma(plane_state); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -505,14 +495,9 @@ vlv_sprite_disable_arm(struct intel_plane *plane, struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; enum plane_id plane_id = plane->id; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPCNTR(pipe, plane_id), 0); intel_de_write_fw(dev_priv, SPSURF(pipe, plane_id), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool @@ -862,15 +847,12 @@ ivb_sprite_update_noarm(struct intel_plane *plane, u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; u32 sprscale = 0; - unsigned long irqflags; if (crtc_w != src_w || crtc_h != src_h) sprscale = SPRITE_SCALE_ENABLE | SPRITE_SRC_WIDTH(src_w - 1) | SPRITE_SRC_HEIGHT(src_h - 1); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, SPRSTRIDE(pipe), plane_state->view.color_plane[0].mapping_stride); intel_de_write_fw(dev_priv, SPRPOS(pipe), @@ -879,8 +861,6 @@ ivb_sprite_update_noarm(struct intel_plane *plane, SPRITE_HEIGHT(crtc_h - 1) | SPRITE_WIDTH(crtc_w - 1)); if (IS_IVYBRIDGE(dev_priv)) intel_de_write_fw(dev_priv, SPRSCALE(pipe), sprscale); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -895,14 +875,11 @@ ivb_sprite_update_arm(struct intel_plane *plane, u32 x = plane_state->view.color_plane[0].x; u32 y = plane_state->view.color_plane[0].y; u32 sprctl, linear_offset; - unsigned long irqflags; sprctl = plane_state->ctl | ivb_sprite_ctl_crtc(crtc_state); linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - if (key->flags) { intel_de_write_fw(dev_priv, SPRKEYVAL(pipe), key->min_value); intel_de_write_fw(dev_priv, SPRKEYMSK(pipe), @@ -931,8 +908,6 @@ ivb_sprite_update_arm(struct intel_plane *plane, intel_plane_ggtt_offset(plane_state) + sprsurf_offset); ivb_sprite_update_gamma(plane_state); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -941,17 +916,12 @@ ivb_sprite_disable_arm(struct intel_plane *plane, { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SPRCTL(pipe), 0); /* Disable the scaler */ if (IS_IVYBRIDGE(dev_priv)) intel_de_write_fw(dev_priv, SPRSCALE(pipe), 0); intel_de_write_fw(dev_priv, SPRSURF(pipe), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool @@ -1204,15 +1174,12 @@ g4x_sprite_update_noarm(struct intel_plane *plane, u32 src_w = drm_rect_width(&plane_state->uapi.src) >> 16; u32 src_h = drm_rect_height(&plane_state->uapi.src) >> 16; u32 dvsscale = 0; - unsigned long irqflags; if (crtc_w != src_w || crtc_h != src_h) dvsscale = DVS_SCALE_ENABLE | DVS_SRC_WIDTH(src_w - 1) | DVS_SRC_HEIGHT(src_h - 1); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - intel_de_write_fw(dev_priv, DVSSTRIDE(pipe), plane_state->view.color_plane[0].mapping_stride); intel_de_write_fw(dev_priv, DVSPOS(pipe), @@ -1220,8 +1187,6 @@ g4x_sprite_update_noarm(struct intel_plane *plane, intel_de_write_fw(dev_priv, DVSSIZE(pipe), DVS_HEIGHT(crtc_h - 1) | DVS_WIDTH(crtc_w - 1)); intel_de_write_fw(dev_priv, DVSSCALE(pipe), dvsscale); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -1236,14 +1201,11 @@ g4x_sprite_update_arm(struct intel_plane *plane, u32 x = plane_state->view.color_plane[0].x; u32 y = plane_state->view.color_plane[0].y; u32 dvscntr, linear_offset; - unsigned long irqflags; dvscntr = plane_state->ctl | g4x_sprite_ctl_crtc(crtc_state); linear_offset = intel_fb_xy_to_linear(x, y, plane_state, 0); - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - if (key->flags) { intel_de_write_fw(dev_priv, DVSKEYVAL(pipe), key->min_value); intel_de_write_fw(dev_priv, DVSKEYMSK(pipe), @@ -1267,8 +1229,6 @@ g4x_sprite_update_arm(struct intel_plane *plane, g4x_sprite_update_gamma(plane_state); else ilk_sprite_update_gamma(plane_state); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static void @@ -1277,16 +1237,11 @@ g4x_sprite_disable_arm(struct intel_plane *plane, { struct drm_i915_private *dev_priv = to_i915(plane->base.dev); enum pipe pipe = plane->pipe; - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, DVSCNTR(pipe), 0); /* Disable the scaler */ intel_de_write_fw(dev_priv, DVSSCALE(pipe), 0); intel_de_write_fw(dev_priv, DVSSURF(pipe), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } static bool From b4eb76d82a0ea92241f5079874a7aea10c5cc4ae Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Wed, 23 Feb 2022 08:54:21 -0800 Subject: [PATCH 00024/11454] drm/i915/dg2: Skip output init on PHY calibration failure If one of our PHYs fails to complete calibration, we should skip the general initialization of the corresponding output. Most likely this is going to happen on outputs that don't actually exist on the board; in theory we should have already decided to skip this output based on the VBT, but we can't always rely on the VBT being accurate. Cc: Lucas De Marchi Signed-off-by: Matt Roper Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220223165421.3949883-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 8 ++++++++ drivers/gpu/drm/i915/display/intel_snps_phy.c | 8 ++++++-- drivers/gpu/drm/i915/i915_drv.h | 12 ++++++++++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index e4260806c2a4..1cd394b0585e 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -4308,6 +4308,14 @@ void intel_ddi_init(struct drm_i915_private *dev_priv, enum port port) return; } + if (intel_phy_is_snps(dev_priv, phy) && + dev_priv->snps_phy_failed_calibration & BIT(phy)) { + drm_dbg_kms(&dev_priv->drm, + "SNPS PHY %c failed to calibrate; output will not be used.\n", + phy_name(phy)); + return; + } + dig_port = kzalloc(sizeof(*dig_port), GFP_KERNEL); if (!dig_port) return; diff --git a/drivers/gpu/drm/i915/display/intel_snps_phy.c b/drivers/gpu/drm/i915/display/intel_snps_phy.c index 7e6245b97fed..0dd4775e8195 100644 --- a/drivers/gpu/drm/i915/display/intel_snps_phy.c +++ b/drivers/gpu/drm/i915/display/intel_snps_phy.c @@ -32,10 +32,14 @@ void intel_snps_phy_wait_for_calibration(struct drm_i915_private *i915) if (!intel_phy_is_snps(i915, phy)) continue; + /* + * If calibration does not complete successfully, we'll remember + * which phy was affected and skip setup of the corresponding + * output later. + */ if (intel_de_wait_for_clear(i915, DG2_PHY_MISC(phy), DG2_PHY_DP_TX_ACK_MASK, 25)) - drm_err(&i915->drm, "SNPS PHY %c failed to calibrate after 25ms.\n", - phy_name(phy)); + i915->snps_phy_failed_calibration |= BIT(phy); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e71dcd2701ca..5cfe69b30841 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -837,8 +837,16 @@ struct drm_i915_private { bool irq_enabled; - /* perform PHY state sanity checks? */ - bool chv_phy_assert[2]; + union { + /* perform PHY state sanity checks? */ + bool chv_phy_assert[2]; + + /* + * DG2: Mask of PHYs that were not calibrated by the firmware + * and should not be used. + */ + u8 snps_phy_failed_calibration; + }; bool ipc_enabled; From 2ff5560e23c863b22afb7db01208a76d9f1d1046 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 23 Feb 2022 13:09:33 -0800 Subject: [PATCH 00025/11454] drm/i915/dmc: Do not try loading wrong DMC version Checking by >= DISPLAY_VER(12) made sense when the support for Tiger Lake was added. However now it only leads to wrong behavior when adding more platforms since it's expected they either don't have DMC to load or they have their own blob. Logs from DG2 loading on a CFL host, without having a DMC firmware defined: <6>[ 0.000000] DMI: Intel Corporation CoffeeLake Client Platform/CoffeeLake S UDIMM RVP, BIOS CNLSFWR1.R00.X220.B00.2103302221 03/30/2021 ... <6>[ 2.706607] pci 0000:03:00.0: [8086:56a0] type 00 class 0x030000 ... <7>[ 6.340397] i915 0000:03:00.0: [drm:intel_dmc_ucode_init [i915]] Loading i915/tgl_dmc_ver2_12.bin <7>[ 6.341841] i915 0000:03:00.0: [drm:intel_fbc_init [i915]] Sanitized enable_fbc value: 1 <3>[ 6.342432] genirq: Flags mismatch irq 0. 00000080 (i915) vs. 00015a00 (timer) <6>[ 6.346283] i915 0000:03:00.0: [drm] Finished loading DMC firmware i915/tgl_dmc_ver2_12.bin (v2.12) <3>[ 6.385756] i915 0000:03:00.0: Device initialization failed (-16) <5>[ 6.385778] i915 0000:03:00.0: Please file a bug on drm/i915; see https://gitlab.freedesktop.org/drm/intel/-/wikis/How-to-file-i915-bugs for details. <4>[ 6.385782] i915: probe of 0000:03:00.0 failed with error -16 TGL is the only platform left with DISPLAY_VER() == 12 that is not handled already in the if/else ladder, so handle it specifically. Signed-off-by: Lucas De Marchi Reviewed-by: Matt Roper Signed-off-by: Ramalingam C Link: https://patchwork.freedesktop.org/patch/msgid/20220223210933.3049143-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 7616a3906b9e..133476be6d28 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -697,7 +697,7 @@ void intel_dmc_ucode_init(struct drm_i915_private *dev_priv) dmc->fw_path = RKL_DMC_PATH; dmc->required_version = RKL_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; - } else if (DISPLAY_VER(dev_priv) >= 12) { + } else if (IS_TIGERLAKE(dev_priv)) { dmc->fw_path = TGL_DMC_PATH; dmc->required_version = TGL_DMC_VERSION_REQUIRED; dmc->max_fw_size = DISPLAY_VER12_DMC_MAX_FW_SIZE; From 53581504a8e216d435f114a4f2596ad0dfd902fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 24 Feb 2022 15:21:42 +0200 Subject: [PATCH 00026/11454] drm/i915: s/JSP2/ICP2/ PCH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This JSP2 PCH actually seems to be some special Apple specific ICP variant rather than a JSP. Make it so. Or at least all the references to it seem to be some Apple ICL machines. Didn't manage to find these PCI IDs in any public chipset docs unfortunately. The only thing we're losing here with this JSP->ICP change is Wa_14011294188, but based on the HSD that isn't actually needed on any ICP based design (including JSP), only TGP based stuff (including MCC) really need it. The documented w/a just never made that distinction because Windows didn't want to differentiate between JSP and MCC (not sure how they handle hpd/ddc/etc. then though...). Cc: stable@vger.kernel.org Cc: Matt Roper Cc: Vivek Kasireddy Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4226 Fixes: 943682e3bd19 ("drm/i915: Introduce Jasper Lake PCH") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220224132142.12927-1-ville.syrjala@linux.intel.com Acked-by: Vivek Kasireddy Tested-by: Tomas Bzatek --- drivers/gpu/drm/i915/intel_pch.c | 2 +- drivers/gpu/drm/i915/intel_pch.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c index 4f7a61d5502e..4cce044efde2 100644 --- a/drivers/gpu/drm/i915/intel_pch.c +++ b/drivers/gpu/drm/i915/intel_pch.c @@ -108,6 +108,7 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) /* Comet Lake V PCH is based on KBP, which is SPT compatible */ return PCH_SPT; case INTEL_PCH_ICP_DEVICE_ID_TYPE: + case INTEL_PCH_ICP2_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Ice Lake PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_ICELAKE(dev_priv)); return PCH_ICP; @@ -123,7 +124,6 @@ intel_pch_type(const struct drm_i915_private *dev_priv, unsigned short id) !IS_GEN9_BC(dev_priv)); return PCH_TGP; case INTEL_PCH_JSP_DEVICE_ID_TYPE: - case INTEL_PCH_JSP2_DEVICE_ID_TYPE: drm_dbg_kms(&dev_priv->drm, "Found Jasper Lake PCH\n"); drm_WARN_ON(&dev_priv->drm, !IS_JSL_EHL(dev_priv)); return PCH_JSP; diff --git a/drivers/gpu/drm/i915/intel_pch.h b/drivers/gpu/drm/i915/intel_pch.h index 6fd20408f7bf..b7a8cf409d48 100644 --- a/drivers/gpu/drm/i915/intel_pch.h +++ b/drivers/gpu/drm/i915/intel_pch.h @@ -50,11 +50,11 @@ enum intel_pch { #define INTEL_PCH_CMP2_DEVICE_ID_TYPE 0x0680 #define INTEL_PCH_CMP_V_DEVICE_ID_TYPE 0xA380 #define INTEL_PCH_ICP_DEVICE_ID_TYPE 0x3480 +#define INTEL_PCH_ICP2_DEVICE_ID_TYPE 0x3880 #define INTEL_PCH_MCC_DEVICE_ID_TYPE 0x4B00 #define INTEL_PCH_TGP_DEVICE_ID_TYPE 0xA080 #define INTEL_PCH_TGP2_DEVICE_ID_TYPE 0x4380 #define INTEL_PCH_JSP_DEVICE_ID_TYPE 0x4D80 -#define INTEL_PCH_JSP2_DEVICE_ID_TYPE 0x3880 #define INTEL_PCH_ADP_DEVICE_ID_TYPE 0x7A80 #define INTEL_PCH_ADP2_DEVICE_ID_TYPE 0x5180 #define INTEL_PCH_ADP3_DEVICE_ID_TYPE 0x7A00 From cccc71b552a1040ad3d738d7ec95570801fb0bf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:03 +0200 Subject: [PATCH 00027/11454] drm/i915: Avoid negative shift due to bigjoiner_pipes==0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bigjoiner_pipes==0 leads bigjoiner_master_pipe() to do BIT(ffs(0)-1) which is undefined behaviour. The code should actually still work fine since the only place we provoke that is intel_crtc_bigjoiner_slave_pipes() and it'll bitwise AND the result with 0, so doesn't really matter what we get out of bigjoiner_master_pipe(). But best not provoke undefined behaviour anyway. Reported-by: kernel test robot Fixes: a6e7a006f5d5 ("drm/i915: Change bigjoiner state tracking to use the pipe bitmask") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-2-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7bf24df20b14..666f922e6f34 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -346,7 +346,10 @@ static enum pipe bigjoiner_master_pipe(const struct intel_crtc_state *crtc_state u8 intel_crtc_bigjoiner_slave_pipes(const struct intel_crtc_state *crtc_state) { - return crtc_state->bigjoiner_pipes & ~BIT(bigjoiner_master_pipe(crtc_state)); + if (crtc_state->bigjoiner_pipes) + return crtc_state->bigjoiner_pipes & ~BIT(bigjoiner_master_pipe(crtc_state)); + else + return 0; } bool intel_crtc_is_bigjoiner_slave(const struct intel_crtc_state *crtc_state) From 6c6465fc33c5679a418fb06ff582cd38e68eb5e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:04 +0200 Subject: [PATCH 00028/11454] drm/i915: Fix cursor coordinates on bigjoiner slave MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adjust the cursor dst coordinates appripriately when it's on the bigjoiner slave pipe. intel_atomic_plane_check_clipping() already did this but with the cursor we discard those results (apart from uapi.visible and error checks) since the hardware will be doing the clipping for us. v2: Rebase due to bigjoiner bitmask usage Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-3-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_cursor.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index b648be744cf2..57ef9403f4e9 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -152,6 +152,9 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, /* Use the unclipped src/dst rectangles, which we program to hw */ plane_state->uapi.src = src; plane_state->uapi.dst = dst; + if (intel_crtc_is_bigjoiner_slave(crtc_state)) + drm_rect_translate(&plane_state->uapi.dst, + -crtc_state->pipe_src_w, 0); ret = intel_cursor_check_surface(plane_state); if (ret) From c2393a1d8bd1a69ff74ee769fa5d36e4900d4fba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:05 +0200 Subject: [PATCH 00029/11454] drm/i915: Remove nop bigjoiner state copy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We just copied over the whole master crtc state, including cpu_transcoder+has_audio. No need to copy those again. Also get rid of the unhelpful comment. Reviewed-by: Ankit Nautiyal Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-4-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 666f922e6f34..6e4b30a297d9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5593,12 +5593,9 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc); - /* Some fixups */ slave_crtc_state->uapi.mode_changed = master_crtc_state->uapi.mode_changed; slave_crtc_state->uapi.connectors_changed = master_crtc_state->uapi.connectors_changed; slave_crtc_state->uapi.active_changed = master_crtc_state->uapi.active_changed; - slave_crtc_state->cpu_transcoder = master_crtc_state->cpu_transcoder; - slave_crtc_state->has_audio = master_crtc_state->has_audio; return 0; } From 3dda9ee49ea5d332359ca372728ee13e570b7e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:06 +0200 Subject: [PATCH 00030/11454] drm/i915: Rename variables in intel_crtc_compute_config() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do the s/dev_priv/i915/ and s/pipe_config/crtc_state/ renames to intel_crtc_compute_config(). I want to start splitting this up a bit and doing the renames now avoids spreading these old nameing conventions elsewhere. No functional changes. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 50 ++++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6e4b30a297d9..31c9213cc27e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2791,16 +2791,16 @@ static void intel_encoder_get_config(struct intel_encoder *encoder, } static int intel_crtc_compute_config(struct intel_crtc *crtc, - struct intel_crtc_state *pipe_config) + struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - struct drm_display_mode *pipe_mode = &pipe_config->hw.pipe_mode; - int clock_limit = dev_priv->max_dotclk_freq; + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; + int clock_limit = i915->max_dotclk_freq; - drm_mode_copy(pipe_mode, &pipe_config->hw.adjusted_mode); + drm_mode_copy(pipe_mode, &crtc_state->hw.adjusted_mode); /* Adjust pipe_mode for bigjoiner, with half the horizontal mode */ - if (pipe_config->bigjoiner) { + if (crtc_state->bigjoiner) { pipe_mode->crtc_clock /= 2; pipe_mode->crtc_hdisplay /= 2; pipe_mode->crtc_hblank_start /= 2; @@ -2808,12 +2808,12 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, pipe_mode->crtc_hsync_start /= 2; pipe_mode->crtc_hsync_end /= 2; pipe_mode->crtc_htotal /= 2; - pipe_config->pipe_src_w /= 2; + crtc_state->pipe_src_w /= 2; } - if (pipe_config->splitter.enable) { - int n = pipe_config->splitter.link_count; - int overlap = pipe_config->splitter.pixel_overlap; + if (crtc_state->splitter.enable) { + int n = crtc_state->splitter.link_count; + int overlap = crtc_state->splitter.pixel_overlap; pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n; pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n; @@ -2826,8 +2826,8 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, intel_mode_from_crtc_timings(pipe_mode, pipe_mode); - if (DISPLAY_VER(dev_priv) < 4) { - clock_limit = dev_priv->max_cdclk_freq * 9 / 10; + if (DISPLAY_VER(i915) < 4) { + clock_limit = i915->max_cdclk_freq * 9 / 10; /* * Enable double wide mode when the dot clock @@ -2835,16 +2835,16 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, */ if (intel_crtc_supports_double_wide(crtc) && pipe_mode->crtc_clock > clock_limit) { - clock_limit = dev_priv->max_dotclk_freq; - pipe_config->double_wide = true; + clock_limit = i915->max_dotclk_freq; + crtc_state->double_wide = true; } } if (pipe_mode->crtc_clock > clock_limit) { - drm_dbg_kms(&dev_priv->drm, + drm_dbg_kms(&i915->drm, "requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n", pipe_mode->crtc_clock, clock_limit, - yesno(pipe_config->double_wide)); + yesno(crtc_state->double_wide)); return -EINVAL; } @@ -2854,25 +2854,25 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, * - LVDS dual channel mode * - Double wide pipe */ - if (pipe_config->pipe_src_w & 1) { - if (pipe_config->double_wide) { - drm_dbg_kms(&dev_priv->drm, + if (crtc_state->pipe_src_w & 1) { + if (crtc_state->double_wide) { + drm_dbg_kms(&i915->drm, "Odd pipe source width not supported with double wide pipe\n"); return -EINVAL; } - if (intel_crtc_has_type(pipe_config, INTEL_OUTPUT_LVDS) && - intel_is_dual_link_lvds(dev_priv)) { - drm_dbg_kms(&dev_priv->drm, + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && + intel_is_dual_link_lvds(i915)) { + drm_dbg_kms(&i915->drm, "Odd pipe source width not supported with dual link LVDS\n"); return -EINVAL; } } - intel_crtc_compute_pixel_rate(pipe_config); + intel_crtc_compute_pixel_rate(crtc_state); - if (pipe_config->has_pch_encoder) - return ilk_fdi_compute_config(crtc, pipe_config); + if (crtc_state->has_pch_encoder) + return ilk_fdi_compute_config(crtc, crtc_state); return 0; } From a8c0109c520092115fabdfa5dae340a7590b201a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:07 +0200 Subject: [PATCH 00031/11454] drm/i915: Extract intel_splitter_adjust_timings() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's not replicate the same piece of code to expand the MSO segment timings to full width in many places. Pull it into a helper Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 54 ++++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 31c9213cc27e..3129914e475c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2728,6 +2728,30 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) ilk_pipe_pixel_rate(crtc_state); } +static void intel_splitter_adjust_timings(const struct intel_crtc_state *crtc_state, + struct drm_display_mode *mode) +{ + int overlap = crtc_state->splitter.pixel_overlap; + int n = crtc_state->splitter.link_count; + + if (!crtc_state->splitter.enable) + return; + + /* + * eDP MSO uses segment timings from EDID for transcoder + * timings, but full mode for everything else. + * + * h_full = (h_segment - pixel_overlap) * link_count + */ + mode->crtc_hdisplay = (mode->crtc_hdisplay - overlap) * n; + mode->crtc_hblank_start = (mode->crtc_hblank_start - overlap) * n; + mode->crtc_hblank_end = (mode->crtc_hblank_end - overlap) * n; + mode->crtc_hsync_start = (mode->crtc_hsync_start - overlap) * n; + mode->crtc_hsync_end = (mode->crtc_hsync_end - overlap) * n; + mode->crtc_htotal = (mode->crtc_htotal - overlap) * n; + mode->crtc_clock *= n; +} + static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state) { struct drm_display_mode *mode = &crtc_state->hw.mode; @@ -2751,22 +2775,7 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state } if (crtc_state->splitter.enable) { - int n = crtc_state->splitter.link_count; - int overlap = crtc_state->splitter.pixel_overlap; - - /* - * eDP MSO uses segment timings from EDID for transcoder - * timings, but full mode for everything else. - * - * h_full = (h_segment - pixel_overlap) * link_count - */ - pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n; - pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n; - pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n; - pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n; - pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n; - pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n; - pipe_mode->crtc_clock *= n; + intel_splitter_adjust_timings(crtc_state, pipe_mode); intel_mode_from_crtc_timings(pipe_mode, pipe_mode); intel_mode_from_crtc_timings(adjusted_mode, pipe_mode); @@ -2811,18 +2820,7 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, crtc_state->pipe_src_w /= 2; } - if (crtc_state->splitter.enable) { - int n = crtc_state->splitter.link_count; - int overlap = crtc_state->splitter.pixel_overlap; - - pipe_mode->crtc_hdisplay = (pipe_mode->crtc_hdisplay - overlap) * n; - pipe_mode->crtc_hblank_start = (pipe_mode->crtc_hblank_start - overlap) * n; - pipe_mode->crtc_hblank_end = (pipe_mode->crtc_hblank_end - overlap) * n; - pipe_mode->crtc_hsync_start = (pipe_mode->crtc_hsync_start - overlap) * n; - pipe_mode->crtc_hsync_end = (pipe_mode->crtc_hsync_end - overlap) * n; - pipe_mode->crtc_htotal = (pipe_mode->crtc_htotal - overlap) * n; - pipe_mode->crtc_clock *= n; - } + intel_splitter_adjust_timings(crtc_state, pipe_mode); intel_mode_from_crtc_timings(pipe_mode, pipe_mode); From 0338ba69234be65d2afd518c9ed7ee81c39e52e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:08 +0200 Subject: [PATCH 00032/11454] drm/i915: Extract intel_bigjoiner_adjust_timings() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deduplicate the code to convert the full timings to per-pipe timings for bigjoiner usage. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-7-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 41 +++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3129914e475c..8800ef39722f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2728,6 +2728,21 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) ilk_pipe_pixel_rate(crtc_state); } +static void intel_bigjoiner_adjust_timings(const struct intel_crtc_state *crtc_state, + struct drm_display_mode *mode) +{ + if (!crtc_state->bigjoiner) + return; + + mode->crtc_clock /= 2; + mode->crtc_hdisplay /= 2; + mode->crtc_hblank_start /= 2; + mode->crtc_hblank_end /= 2; + mode->crtc_hsync_start /= 2; + mode->crtc_hsync_end /= 2; + mode->crtc_htotal /= 2; +} + static void intel_splitter_adjust_timings(const struct intel_crtc_state *crtc_state, struct drm_display_mode *mode) { @@ -2760,19 +2775,7 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state drm_mode_copy(pipe_mode, adjusted_mode); - if (crtc_state->bigjoiner) { - /* - * transcoder is programmed to the full mode, - * but pipe timings are half of the transcoder mode - */ - pipe_mode->crtc_hdisplay /= 2; - pipe_mode->crtc_hblank_start /= 2; - pipe_mode->crtc_hblank_end /= 2; - pipe_mode->crtc_hsync_start /= 2; - pipe_mode->crtc_hsync_end /= 2; - pipe_mode->crtc_htotal /= 2; - pipe_mode->crtc_clock /= 2; - } + intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); if (crtc_state->splitter.enable) { intel_splitter_adjust_timings(crtc_state, pipe_mode); @@ -2808,17 +2811,9 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, drm_mode_copy(pipe_mode, &crtc_state->hw.adjusted_mode); - /* Adjust pipe_mode for bigjoiner, with half the horizontal mode */ - if (crtc_state->bigjoiner) { - pipe_mode->crtc_clock /= 2; - pipe_mode->crtc_hdisplay /= 2; - pipe_mode->crtc_hblank_start /= 2; - pipe_mode->crtc_hblank_end /= 2; - pipe_mode->crtc_hsync_start /= 2; - pipe_mode->crtc_hsync_end /= 2; - pipe_mode->crtc_htotal /= 2; + intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); + if (crtc_state->bigjoiner) crtc_state->pipe_src_w /= 2; - } intel_splitter_adjust_timings(crtc_state, pipe_mode); From 9c1197a0f82d4a8a32e29ba4c3c044b5057376c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:09 +0200 Subject: [PATCH 00033/11454] drm/i915: Extract intel_crtc_compute_pipe_src() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_crtc_compute_config() doesn't really tell a unified story. Let's chunk it up into pieces. We'll start with intel_crtc_compute_pipe_src(). Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-8-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 62 ++++++++++++-------- 1 file changed, 39 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8800ef39722f..4d61f4bda4ca 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2802,18 +2802,55 @@ static void intel_encoder_get_config(struct intel_encoder *encoder, intel_crtc_readout_derived_state(crtc_state); } +static int intel_crtc_compute_pipe_src(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + if (crtc_state->bigjoiner) + crtc_state->pipe_src_w /= 2; + + /* + * Pipe horizontal size must be even in: + * - DVO ganged mode + * - LVDS dual channel mode + * - Double wide pipe + */ + if (crtc_state->pipe_src_w & 1) { + if (crtc_state->double_wide) { + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] Odd pipe source width not supported with double wide pipe\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } + + if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && + intel_is_dual_link_lvds(i915)) { + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] Odd pipe source width not supported with dual link LVDS\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } + } + + return 0; +} + static int intel_crtc_compute_config(struct intel_crtc *crtc, struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; int clock_limit = i915->max_dotclk_freq; + int ret; + + ret = intel_crtc_compute_pipe_src(crtc_state); + if (ret) + return ret; drm_mode_copy(pipe_mode, &crtc_state->hw.adjusted_mode); intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); - if (crtc_state->bigjoiner) - crtc_state->pipe_src_w /= 2; intel_splitter_adjust_timings(crtc_state, pipe_mode); @@ -2841,27 +2878,6 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, return -EINVAL; } - /* - * Pipe horizontal size must be even in: - * - DVO ganged mode - * - LVDS dual channel mode - * - Double wide pipe - */ - if (crtc_state->pipe_src_w & 1) { - if (crtc_state->double_wide) { - drm_dbg_kms(&i915->drm, - "Odd pipe source width not supported with double wide pipe\n"); - return -EINVAL; - } - - if (intel_crtc_has_type(crtc_state, INTEL_OUTPUT_LVDS) && - intel_is_dual_link_lvds(i915)) { - drm_dbg_kms(&i915->drm, - "Odd pipe source width not supported with dual link LVDS\n"); - return -EINVAL; - } - } - intel_crtc_compute_pixel_rate(crtc_state); if (crtc_state->has_pch_encoder) From 6f4cafdfe77c396d6029d80a645e949f62e670c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:10 +0200 Subject: [PATCH 00034/11454] drm/i915: Extract intel_crtc_compute_pipe_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull intel_crtc_compute_pipe_mode() out from intel_crtc_compute_config(). Since it's semi related we'll suck in the max dotclock/double wide checks in as well. And we'll pimp the debugs while at it. Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-9-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 28 ++++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 4d61f4bda4ca..3605e01b911c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2836,17 +2836,12 @@ static int intel_crtc_compute_pipe_src(struct intel_crtc_state *crtc_state) return 0; } -static int intel_crtc_compute_config(struct intel_crtc *crtc, - struct intel_crtc_state *crtc_state) +static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; int clock_limit = i915->max_dotclk_freq; - int ret; - - ret = intel_crtc_compute_pipe_src(crtc_state); - if (ret) - return ret; drm_mode_copy(pipe_mode, &crtc_state->hw.adjusted_mode); @@ -2872,12 +2867,29 @@ static int intel_crtc_compute_config(struct intel_crtc *crtc, if (pipe_mode->crtc_clock > clock_limit) { drm_dbg_kms(&i915->drm, - "requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n", + "[CRTC:%d:%s] requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n", + crtc->base.base.id, crtc->base.name, pipe_mode->crtc_clock, clock_limit, yesno(crtc_state->double_wide)); return -EINVAL; } + return 0; +} + +static int intel_crtc_compute_config(struct intel_crtc *crtc, + struct intel_crtc_state *crtc_state) +{ + int ret; + + ret = intel_crtc_compute_pipe_src(crtc_state); + if (ret) + return ret; + + ret = intel_crtc_compute_pipe_mode(crtc_state); + if (ret) + return ret; + intel_crtc_compute_pixel_rate(crtc_state); if (crtc_state->has_pch_encoder) From 2d0539575abb9dfda27eb7653bb442448fb8982a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:11 +0200 Subject: [PATCH 00035/11454] drm/i915: Fix MSO vs. bigjoiner timings confusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When calculating pipe_mode and when doing readout we need to order our steps correctly. 1. We start with adjusted_mode crtc timings being populated with the transcoder timings (either via readout or compute_config(). These will be per-segment for MSO. 2. For all other uses we want the full crtc timings so we ask intel_splitter_adjust_timings() to expand the per-segment numbers to their full glory 3. If bigjoiner is used we the divide the full numbers down to per-pipe numbers using intel_bigjoiner_adjust_timings() During readout we also have to reconstruct the adjusted_mode normal timings (ie. not the crtc_ stuff). These are supposed to reflect the full timings of the display. So we grab these between steps 2 and 3. The "user" mode readout (mainly done for fastboot purposes) should be whatever mode the user would have used had they asked us to do a modeset. We want the full timings for this as the per-segment timings are not suppoesed to be user visible. Also the user mode normal timings hdisplay/vdisplay need to match PIPESRC (that is where we get our PIPESRC size we doing a modeset with a user supplied mode). And we end up with - adjusted_mode normal timigns == full timings - adjusted_mode crtc timings == transcoder timings (per-segment timings for MSO, full timings otherwise) - pipe_mode normal/crtc timings == pipe timings (full timings divided by the number of bigjoiner pipes, if any) - user mode normal timings == full timings with hdisplay/vdisplay replaced with PIPESRC size - user mode crtc timings == full timings Yes, that is a lot of timings. One day we'll try to remove some of the ones we don't actually need to keep around... Reviewed-by: Manasi Navare Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-10-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 46 +++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3605e01b911c..b8d511360f9f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2773,25 +2773,33 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + /* + * Start with the adjusted_mode crtc timings, which + * have been filled with the transcoder timings. + */ drm_mode_copy(pipe_mode, adjusted_mode); - intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); + /* Expand MSO per-segment transcoder timings to full */ + intel_splitter_adjust_timings(crtc_state, pipe_mode); - if (crtc_state->splitter.enable) { - intel_splitter_adjust_timings(crtc_state, pipe_mode); + /* + * We want the full numbers in adjusted_mode normal timings, + * adjusted_mode crtc timings are left with the raw transcoder + * timings. + */ + intel_mode_from_crtc_timings(adjusted_mode, pipe_mode); - intel_mode_from_crtc_timings(pipe_mode, pipe_mode); - intel_mode_from_crtc_timings(adjusted_mode, pipe_mode); - } else { - intel_mode_from_crtc_timings(pipe_mode, pipe_mode); - intel_mode_from_crtc_timings(adjusted_mode, adjusted_mode); - } - - intel_crtc_compute_pixel_rate(crtc_state); - - drm_mode_copy(mode, adjusted_mode); + /* Populate the "user" mode with full numbers */ + drm_mode_copy(mode, pipe_mode); + intel_mode_from_crtc_timings(mode, mode); mode->hdisplay = crtc_state->pipe_src_w << crtc_state->bigjoiner; mode->vdisplay = crtc_state->pipe_src_h; + + /* Derive per-pipe timings in case bigjoiner is used */ + intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); + intel_mode_from_crtc_timings(pipe_mode, pipe_mode); + + intel_crtc_compute_pixel_rate(crtc_state); } static void intel_encoder_get_config(struct intel_encoder *encoder, @@ -2840,15 +2848,21 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; struct drm_display_mode *pipe_mode = &crtc_state->hw.pipe_mode; int clock_limit = i915->max_dotclk_freq; - drm_mode_copy(pipe_mode, &crtc_state->hw.adjusted_mode); - - intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); + /* + * Start with the adjusted_mode crtc timings, which + * have been filled with the transcoder timings. + */ + drm_mode_copy(pipe_mode, adjusted_mode); + /* Expand MSO per-segment transcoder timings to full */ intel_splitter_adjust_timings(crtc_state, pipe_mode); + /* Derive per-pipe timings in case bigjoiner is used */ + intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); intel_mode_from_crtc_timings(pipe_mode, pipe_mode); if (DISPLAY_VER(i915) < 4) { From 5c190e5394cc7773feaff1b54701a2c2f73ef011 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 23 Feb 2022 12:35:17 +0200 Subject: [PATCH 00036/11454] drm/i915/wm: use REG_FIELD_{PREP,GET} for PLANE_WM_BLOCKS_MASK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use REG_FIELD_{PREP,GET} for completeness, and to avoid bitwise operations with different sizes. v2: Also use REG_FIELD_GET in skl_wm_level_from_reg_val() (Ville) Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223103517.634229-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 51308211618e..b9d711246f1e 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5931,7 +5931,7 @@ static void skl_write_wm_level(struct drm_i915_private *dev_priv, val |= PLANE_WM_EN; if (level->ignore_lines) val |= PLANE_WM_IGNORE_LINES; - val |= level->blocks; + val |= REG_FIELD_PREP(PLANE_WM_BLOCKS_MASK, level->blocks); val |= REG_FIELD_PREP(PLANE_WM_LINES_MASK, level->lines); intel_de_write_fw(dev_priv, reg, val); @@ -6579,7 +6579,7 @@ static void skl_wm_level_from_reg_val(u32 val, struct skl_wm_level *level) { level->enable = val & PLANE_WM_EN; level->ignore_lines = val & PLANE_WM_IGNORE_LINES; - level->blocks = val & PLANE_WM_BLOCKS_MASK; + level->blocks = REG_FIELD_GET(PLANE_WM_BLOCKS_MASK, val); level->lines = REG_FIELD_GET(PLANE_WM_LINES_MASK, val); } From 492c1ae2f27c327ef8d0f2019cac66408a41d808 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 22 Feb 2022 18:51:30 +0200 Subject: [PATCH 00037/11454] drm/i915: Fix the VDSC_PW2 power domain enum value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The POWER_DOMAIN_TRANSCODER() macro depends on the POWER_DOMAIN_TRANSCODER_A/B .. DSI_A/C enum values to be consecutive, move POWER_DOMAIN_TRANSCODER_VDSC_PW2 after these to ensure this. The wrong order didn't cause a problem, since the DSI_A/C domains are in always-on power wells on all relevant platforms. The same power well ends up being enabled/disabled when the VDSC_PW2 domain is selected incorrectly. While at it add a code comment about enum values that need to stay consecutive. Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220222165137.1004194-2-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 4 ++-- drivers/gpu/drm/i915/display/intel_display_power.h | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 9ebae7ac3235..4ca0e61ca593 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -153,12 +153,12 @@ intel_display_power_domain_str(enum intel_display_power_domain domain) return "TRANSCODER_D"; case POWER_DOMAIN_TRANSCODER_EDP: return "TRANSCODER_EDP"; - case POWER_DOMAIN_TRANSCODER_VDSC_PW2: - return "TRANSCODER_VDSC_PW2"; case POWER_DOMAIN_TRANSCODER_DSI_A: return "TRANSCODER_DSI_A"; case POWER_DOMAIN_TRANSCODER_DSI_C: return "TRANSCODER_DSI_C"; + case POWER_DOMAIN_TRANSCODER_VDSC_PW2: + return "TRANSCODER_VDSC_PW2"; case POWER_DOMAIN_PORT_DDI_A_LANES: return "PORT_DDI_A_LANES"; case POWER_DOMAIN_PORT_DDI_B_LANES: diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index f6d0e6e73c6d..f28aa4b500c4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -14,6 +14,11 @@ struct drm_i915_private; struct i915_power_well; struct intel_encoder; +/* + * Keep the pipe, transcoder, port (DDI_LANES,DDI_IO,AUX) domain instances + * consecutive, so that the pipe,transcoder,port -> power domain macros + * work correctly. + */ enum intel_display_power_domain { POWER_DOMAIN_DISPLAY_CORE, POWER_DOMAIN_PIPE_A, @@ -29,10 +34,12 @@ enum intel_display_power_domain { POWER_DOMAIN_TRANSCODER_C, POWER_DOMAIN_TRANSCODER_D, POWER_DOMAIN_TRANSCODER_EDP, - /* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */ - POWER_DOMAIN_TRANSCODER_VDSC_PW2, POWER_DOMAIN_TRANSCODER_DSI_A, POWER_DOMAIN_TRANSCODER_DSI_C, + + /* VDSC/joining for eDP/DSI transcoder (ICL) or pipe A (TGL) */ + POWER_DOMAIN_TRANSCODER_VDSC_PW2, + POWER_DOMAIN_PORT_DDI_A_LANES, POWER_DOMAIN_PORT_DDI_B_LANES, POWER_DOMAIN_PORT_DDI_C_LANES, From 359441cdc5e7f872f3c53757606cdd6bd6b842df Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 22 Feb 2022 18:51:31 +0200 Subject: [PATCH 00038/11454] drm/i915: Sanitize open-coded power well enable()/disable() calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of open-coding the call of the power wells' enable()/disable() hooks use the corresponding helper functions. This will also ensure that the power well's cached-enable state is always up-to-date. Luckily the lack of this updating hasn't been a problem, since the state either didn't change (in intel_display_power_set_target_dc_state()), or got updated subsequently (for vlv_cmnlane_wa(), in the following intel_power_domains_sync_hw()). Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220222165137.1004194-3-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 4ca0e61ca593..bf3619ae9dad 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -1130,12 +1130,12 @@ void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv, * DC off power well to effect target DC state. */ if (!dc_off_enabled) - power_well->desc->ops->enable(dev_priv, power_well); + intel_power_well_enable(dev_priv, power_well); dev_priv->dmc.target_dc_state = state; if (!dc_off_enabled) - power_well->desc->ops->disable(dev_priv, power_well); + intel_power_well_disable(dev_priv, power_well); unlock: mutex_unlock(&power_domains->lock); @@ -6073,7 +6073,7 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) drm_dbg_kms(&dev_priv->drm, "toggling display PHY side reset\n"); /* cmnlane needs DPLL registers */ - disp2d->desc->ops->enable(dev_priv, disp2d); + intel_power_well_enable(dev_priv, disp2d); /* * From VLV2A0_DP_eDP_HDMI_DPIO_driver_vbios_notes_11.docx: @@ -6082,7 +6082,7 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) * Simply ungating isn't enough to reset the PHY enough to get * ports and lanes running. */ - cmn->desc->ops->disable(dev_priv, cmn); + intel_power_well_disable(dev_priv, cmn); } static bool vlv_punit_is_power_gated(struct drm_i915_private *dev_priv, u32 reg0) From a5c517331279916e99e4ea02a50bfdd578861651 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 22 Feb 2022 18:51:32 +0200 Subject: [PATCH 00039/11454] drm/i915: Remove redundant state verification during TypeC AUX power well disabling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit d5ce34da31456a ("drm/i915: Add state verification for the TypeC port mode") added a verification to the TypeC AUX power well enable()/disable() hooks to check if the TypeC port related to this power well is properly locked. If the disabling happens asynchronously the verification is skipped, since in this case the port is unlocked. The detection of asnychronous disabling doesn't work as intended though, since the power well's reference count is always 0 when its disable() hook is called (and since there won't be any domain reference held for this power well either, the verification is always skipped); remove the verification from the disable() hook for now. In the power well's enable() hook the power well's reference will be always >0 and there won't be any asynchronous disabling pending for it, so we can drop the async refcount check from there. No functional change. Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220222165137.1004194-4-imre.deak@intel.com --- .../drm/i915/display/intel_display_power.c | 32 +------------------ 1 file changed, 1 insertion(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index bf3619ae9dad..857dd9ddba35 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -636,28 +636,10 @@ icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv, #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM) -static u64 async_put_domains_mask(struct i915_power_domains *power_domains); - -static int power_well_async_ref_count(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - int refs = hweight64(power_well->desc->domains & - async_put_domains_mask(&dev_priv->power_domains)); - - drm_WARN_ON(&dev_priv->drm, refs > power_well->count); - - return refs; -} - static void icl_tc_port_assert_ref_held(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, struct intel_digital_port *dig_port) { - /* Bypass the check if all references are released asynchronously */ - if (power_well_async_ref_count(dev_priv, power_well) == - power_well->count) - return; - if (drm_WARN_ON(&dev_priv->drm, !dig_port)) return; @@ -748,18 +730,6 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, } } -static void -icl_tc_phy_aux_power_well_disable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well); - struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch); - - icl_tc_port_assert_ref_held(dev_priv, power_well, dig_port); - - hsw_power_well_disable(dev_priv, power_well); -} - static void icl_aux_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) @@ -782,7 +752,7 @@ icl_aux_power_well_disable(struct drm_i915_private *dev_priv, enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well); if (intel_phy_is_tc(dev_priv, phy)) - return icl_tc_phy_aux_power_well_disable(dev_priv, power_well); + return hsw_power_well_disable(dev_priv, power_well); else if (IS_ICELAKE(dev_priv)) return icl_combo_phy_aux_power_well_disable(dev_priv, power_well); From 314fe7dce4139e80fe3df834d1c451917a1b0bc0 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 22 Feb 2022 18:51:33 +0200 Subject: [PATCH 00040/11454] drm/i915: Move i915_power_well_regs struct into i915_power_well_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the i915_power_well_regs struct into i915_power_well_ops. Most of the power wells use the same ops/regs combination, so this saves some space and also simplifies the platform power domain->power well definitions. Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220222165137.1004194-5-imre.deak@intel.com --- .../drm/i915/display/intel_display_power.c | 256 +++++------------- 1 file changed, 73 insertions(+), 183 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 857dd9ddba35..32e4fc6a451e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -26,7 +26,15 @@ #include "intel_vga.h" #include "vlv_sideband.h" +struct i915_power_well_regs { + i915_reg_t bios; + i915_reg_t driver; + i915_reg_t kvmr; + i915_reg_t debug; +}; + struct i915_power_well_ops { + const struct i915_power_well_regs *regs; /* * Synchronize the well's hw state to match the current sw state, for * example enable/disable it based on the current refcount. Called @@ -53,13 +61,6 @@ struct i915_power_well_ops { struct i915_power_well *power_well); }; -struct i915_power_well_regs { - i915_reg_t bios; - i915_reg_t driver; - i915_reg_t kvmr; - i915_reg_t debug; -}; - /* Power well structure for haswell */ struct i915_power_well_desc { const char *name; @@ -83,7 +84,6 @@ struct i915_power_well_desc { enum dpio_phy phy; } bxt; struct { - const struct i915_power_well_regs *regs; /* * request/status flag index in the power well * constrol/status registers. @@ -438,7 +438,7 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well, bool timeout_expected) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; int enable_delay = power_well->desc->hsw.fixed_enable_delay; @@ -482,7 +482,7 @@ static u32 hsw_power_well_requesters(struct drm_i915_private *dev_priv, static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; bool disabled; u32 reqs; @@ -520,7 +520,7 @@ static void gen9_wait_for_power_well_fuses(struct drm_i915_private *dev_priv, static void hsw_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; u32 val; @@ -567,7 +567,7 @@ static void hsw_power_well_enable(struct drm_i915_private *dev_priv, static void hsw_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; u32 val; @@ -584,7 +584,7 @@ static void icl_combo_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well); u32 val; @@ -616,7 +616,7 @@ static void icl_combo_phy_aux_power_well_disable(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; enum phy phy = icl_aux_pw_to_phy(dev_priv, power_well); u32 val; @@ -688,7 +688,7 @@ icl_tc_phy_aux_power_well_enable(struct drm_i915_private *dev_priv, { enum aux_ch aux_ch = icl_aux_pw_to_ch(power_well); struct intel_digital_port *dig_port = aux_ch_to_digital_port(dev_priv, aux_ch); - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; bool is_tbt = power_well->desc->hsw.is_tc_tbt; bool timeout_expected; u32 val; @@ -768,7 +768,7 @@ icl_aux_power_well_disable(struct drm_i915_private *dev_priv, static bool hsw_power_well_enabled(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; enum i915_power_well_id id = power_well->desc->id; int pw_idx = power_well->desc->hsw.idx; u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx) | @@ -1178,7 +1178,7 @@ static void skl_enable_dc6(struct drm_i915_private *dev_priv) static void hsw_power_well_sync_hw(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - const struct i915_power_well_regs *regs = power_well->desc->hsw.regs; + const struct i915_power_well_regs *regs = power_well->desc->ops->regs; int pw_idx = power_well->desc->hsw.idx; u32 mask = HSW_PWR_WELL_CTL_REQ(pw_idx); u32 bios_req = intel_de_read(dev_priv, regs->bios); @@ -3250,7 +3250,15 @@ static const struct i915_power_well_desc i830_power_wells[] = { }, }; +static const struct i915_power_well_regs hsw_power_well_regs = { + .bios = HSW_PWR_WELL_CTL1, + .driver = HSW_PWR_WELL_CTL2, + .kvmr = HSW_PWR_WELL_CTL3, + .debug = HSW_PWR_WELL_CTL4, +}; + static const struct i915_power_well_ops hsw_power_well_ops = { + .regs = &hsw_power_well_regs, .sync_hw = hsw_power_well_sync_hw, .enable = hsw_power_well_enable, .disable = hsw_power_well_disable, @@ -3271,13 +3279,6 @@ static const struct i915_power_well_ops bxt_dpio_cmn_power_well_ops = { .is_enabled = bxt_dpio_cmn_power_well_enabled, }; -static const struct i915_power_well_regs hsw_power_well_regs = { - .bios = HSW_PWR_WELL_CTL1, - .driver = HSW_PWR_WELL_CTL2, - .kvmr = HSW_PWR_WELL_CTL3, - .debug = HSW_PWR_WELL_CTL4, -}; - static const struct i915_power_well_desc hsw_power_wells[] = { { .name = "always-on", @@ -3292,7 +3293,6 @@ static const struct i915_power_well_desc hsw_power_wells[] = { .ops = &hsw_power_well_ops, .id = HSW_DISP_PW_GLOBAL, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, .hsw.has_vga = true, }, @@ -3313,7 +3313,6 @@ static const struct i915_power_well_desc bdw_power_wells[] = { .ops = &hsw_power_well_ops, .id = HSW_DISP_PW_GLOBAL, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = HSW_PW_CTL_IDX_GLOBAL, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, @@ -3485,7 +3484,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -3498,7 +3496,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_MISC_IO, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_MISC_IO, }, }, @@ -3514,7 +3511,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, @@ -3527,7 +3523,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_A_E, }, }, @@ -3537,7 +3532,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_B, }, }, @@ -3547,7 +3541,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_C, }, }, @@ -3557,7 +3550,6 @@ static const struct i915_power_well_desc skl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_D, }, }, @@ -3579,7 +3571,6 @@ static const struct i915_power_well_desc bxt_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -3596,7 +3587,6 @@ static const struct i915_power_well_desc bxt_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, @@ -3639,7 +3629,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -3656,7 +3645,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_PW_2, .hsw.irq_pipe_mask = BIT(PIPE_B) | BIT(PIPE_C), .hsw.has_vga = true, @@ -3696,7 +3684,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = GLK_PW_CTL_IDX_AUX_A, }, }, @@ -3706,7 +3693,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = GLK_PW_CTL_IDX_AUX_B, }, }, @@ -3716,7 +3702,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = GLK_PW_CTL_IDX_AUX_C, }, }, @@ -3726,7 +3711,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = GLK_PW_CTL_IDX_DDI_A, }, }, @@ -3736,7 +3720,6 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_B, }, }, @@ -3746,31 +3729,39 @@ static const struct i915_power_well_desc glk_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = SKL_PW_CTL_IDX_DDI_C, }, }, }; -static const struct i915_power_well_ops icl_aux_power_well_ops = { - .sync_hw = hsw_power_well_sync_hw, - .enable = icl_aux_power_well_enable, - .disable = icl_aux_power_well_disable, - .is_enabled = hsw_power_well_enabled, -}; - static const struct i915_power_well_regs icl_aux_power_well_regs = { .bios = ICL_PWR_WELL_CTL_AUX1, .driver = ICL_PWR_WELL_CTL_AUX2, .debug = ICL_PWR_WELL_CTL_AUX4, }; +static const struct i915_power_well_ops icl_aux_power_well_ops = { + .regs = &icl_aux_power_well_regs, + .sync_hw = hsw_power_well_sync_hw, + .enable = icl_aux_power_well_enable, + .disable = icl_aux_power_well_disable, + .is_enabled = hsw_power_well_enabled, +}; + static const struct i915_power_well_regs icl_ddi_power_well_regs = { .bios = ICL_PWR_WELL_CTL_DDI1, .driver = ICL_PWR_WELL_CTL_DDI2, .debug = ICL_PWR_WELL_CTL_DDI4, }; +static const struct i915_power_well_ops icl_ddi_power_well_ops = { + .regs = &icl_ddi_power_well_regs, + .sync_hw = hsw_power_well_sync_hw, + .enable = hsw_power_well_enable, + .disable = hsw_power_well_disable, + .is_enabled = hsw_power_well_enabled, +}; + static const struct i915_power_well_desc icl_power_wells[] = { { .name = "always-on", @@ -3787,7 +3778,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -3804,7 +3794,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_2, .hsw.has_fuses = true, }, @@ -3815,7 +3804,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_3, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_3, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_vga = true, @@ -3825,60 +3813,54 @@ static const struct i915_power_well_desc icl_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, }, }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, }, }, { .name = "DDI C IO", .domains = ICL_DDI_IO_C_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_C, }, }, { .name = "DDI D IO", .domains = ICL_DDI_IO_D_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_D, }, }, { .name = "DDI E IO", .domains = ICL_DDI_IO_E_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_E, }, }, { .name = "DDI F IO", .domains = ICL_DDI_IO_F_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_F, }, }, @@ -3888,7 +3870,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, }, }, @@ -3898,7 +3879,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, }, }, @@ -3908,7 +3888,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_C, .hsw.is_tc_tbt = false, }, @@ -3919,7 +3898,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_D, .hsw.is_tc_tbt = false, }, @@ -3930,7 +3908,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_E, .hsw.is_tc_tbt = false, }, @@ -3941,7 +3918,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_F, .hsw.is_tc_tbt = false, }, @@ -3952,7 +3928,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT1, .hsw.is_tc_tbt = true, }, @@ -3963,7 +3938,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT2, .hsw.is_tc_tbt = true, }, @@ -3974,7 +3948,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT3, .hsw.is_tc_tbt = true, }, @@ -3985,7 +3958,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_TBT4, .hsw.is_tc_tbt = true, }, @@ -3996,7 +3968,6 @@ static const struct i915_power_well_desc icl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_4, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_C), @@ -4104,7 +4075,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -4121,7 +4091,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_2, .hsw.has_fuses = true, }, @@ -4132,7 +4101,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_3, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_3, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_vga = true, @@ -4142,90 +4110,81 @@ static const struct i915_power_well_desc tgl_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, } }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, } }, { .name = "DDI C IO", .domains = ICL_DDI_IO_C_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_C, } }, { .name = "DDI IO TC1", .domains = TGL_DDI_IO_TC1_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1, }, }, { .name = "DDI IO TC2", .domains = TGL_DDI_IO_TC2_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2, }, }, { .name = "DDI IO TC3", .domains = TGL_DDI_IO_TC3_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC3, }, }, { .name = "DDI IO TC4", .domains = TGL_DDI_IO_TC4_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC4, }, }, { .name = "DDI IO TC5", .domains = TGL_DDI_IO_TC5_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC5, }, }, { .name = "DDI IO TC6", .domains = TGL_DDI_IO_TC6_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC6, }, }, @@ -4241,7 +4200,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, }, }, @@ -4251,7 +4209,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, }, }, @@ -4261,7 +4218,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_C, }, }, @@ -4271,7 +4227,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1, .hsw.is_tc_tbt = false, }, @@ -4282,7 +4237,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2, .hsw.is_tc_tbt = false, }, @@ -4293,7 +4247,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC3, .hsw.is_tc_tbt = false, }, @@ -4304,7 +4257,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC4, .hsw.is_tc_tbt = false, }, @@ -4315,7 +4267,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC5, .hsw.is_tc_tbt = false, }, @@ -4326,7 +4277,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC6, .hsw.is_tc_tbt = false, }, @@ -4337,7 +4287,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT1, .hsw.is_tc_tbt = true, }, @@ -4348,7 +4297,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT2, .hsw.is_tc_tbt = true, }, @@ -4359,7 +4307,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT3, .hsw.is_tc_tbt = true, }, @@ -4370,7 +4317,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT4, .hsw.is_tc_tbt = true, }, @@ -4381,7 +4327,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT5, .hsw.is_tc_tbt = true, }, @@ -4392,7 +4337,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT6, .hsw.is_tc_tbt = true, }, @@ -4403,7 +4347,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_4, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_C), @@ -4415,7 +4358,6 @@ static const struct i915_power_well_desc tgl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_PW_5, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_D), @@ -4439,7 +4381,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -4456,7 +4397,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_3, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_3, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_vga = true, @@ -4469,7 +4409,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_4, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_C), @@ -4478,40 +4417,36 @@ static const struct i915_power_well_desc rkl_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, } }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, } }, { .name = "DDI IO TC1", .domains = TGL_DDI_IO_TC1_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1, }, }, { .name = "DDI IO TC2", .domains = TGL_DDI_IO_TC2_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2, }, }, @@ -4521,7 +4456,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, }, }, @@ -4531,7 +4465,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, }, }, @@ -4541,7 +4474,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1, }, }, @@ -4551,7 +4483,6 @@ static const struct i915_power_well_desc rkl_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2, }, }, @@ -4573,7 +4504,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -4590,7 +4520,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_2, .hsw.has_fuses = true, }, @@ -4601,7 +4530,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = ICL_DISP_PW_3, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_3, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_vga = true, @@ -4611,40 +4539,36 @@ static const struct i915_power_well_desc dg1_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, } }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, } }, { .name = "DDI IO TC1", .domains = TGL_DDI_IO_TC1_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1, }, }, { .name = "DDI IO TC2", .domains = TGL_DDI_IO_TC2_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2, }, }, @@ -4654,7 +4578,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, }, }, @@ -4664,7 +4587,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, }, }, @@ -4674,7 +4596,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1, .hsw.is_tc_tbt = false, }, @@ -4685,7 +4606,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2, .hsw.is_tc_tbt = false, }, @@ -4696,7 +4616,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_4, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_C), @@ -4708,7 +4627,6 @@ static const struct i915_power_well_desc dg1_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_PW_5, .hsw.has_fuses = true, .hsw.irq_pipe_mask = BIT(PIPE_D), @@ -4732,7 +4650,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_1, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_1, .hsw.has_fuses = true, }, @@ -4749,7 +4666,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = SKL_DISP_PW_2, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_PW_2, .hsw.has_vga = true, .hsw.has_fuses = true, @@ -4761,7 +4677,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_PW_A, .hsw.irq_pipe_mask = BIT(PIPE_A), .hsw.has_fuses = true, @@ -4773,7 +4688,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_PW_B, .hsw.irq_pipe_mask = BIT(PIPE_B), .hsw.has_fuses = true, @@ -4785,7 +4699,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_PW_C, .hsw.irq_pipe_mask = BIT(PIPE_C), .hsw.has_fuses = true, @@ -4797,7 +4710,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &hsw_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &hsw_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_PW_D, .hsw.irq_pipe_mask = BIT(PIPE_D), .hsw.has_fuses = true, @@ -4806,90 +4718,81 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { { .name = "DDI A IO", .domains = ICL_DDI_IO_A_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_A, } }, { .name = "DDI B IO", .domains = ICL_DDI_IO_B_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_B, } }, { .name = "DDI C IO", .domains = ICL_DDI_IO_C_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_DDI_C, } }, { .name = "DDI IO D_XELPD", .domains = XELPD_DDI_IO_D_XELPD_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_DDI_D, } }, { .name = "DDI IO E_XELPD", .domains = XELPD_DDI_IO_E_XELPD_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_DDI_E, } }, { .name = "DDI IO TC1", .domains = XELPD_DDI_IO_TC1_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC1, } }, { .name = "DDI IO TC2", .domains = XELPD_DDI_IO_TC2_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC2, } }, { .name = "DDI IO TC3", .domains = XELPD_DDI_IO_TC3_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC3, } }, { .name = "DDI IO TC4", .domains = XELPD_DDI_IO_TC4_POWER_DOMAINS, - .ops = &hsw_power_well_ops, + .ops = &icl_ddi_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_ddi_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_DDI_TC4, } }, @@ -4899,7 +4802,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_A, .hsw.fixed_enable_delay = 600, }, @@ -4910,7 +4812,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_B, .hsw.fixed_enable_delay = 600, }, @@ -4921,7 +4822,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = ICL_PW_CTL_IDX_AUX_C, .hsw.fixed_enable_delay = 600, }, @@ -4932,7 +4832,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_AUX_D, .hsw.fixed_enable_delay = 600, }, @@ -4943,7 +4842,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = XELPD_PW_CTL_IDX_AUX_E, }, }, @@ -4953,7 +4851,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC1, .hsw.fixed_enable_delay = 600, }, @@ -4964,7 +4861,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC2, }, }, @@ -4974,7 +4870,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC3, }, }, @@ -4984,7 +4879,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TC4, }, }, @@ -4994,7 +4888,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT1, .hsw.is_tc_tbt = true, }, @@ -5005,7 +4898,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT2, .hsw.is_tc_tbt = true, }, @@ -5016,7 +4908,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT3, .hsw.is_tc_tbt = true, }, @@ -5027,7 +4918,6 @@ static const struct i915_power_well_desc xelpd_power_wells[] = { .ops = &icl_aux_power_well_ops, .id = DISP_PW_ID_NONE, { - .hsw.regs = &icl_aux_power_well_regs, .hsw.idx = TGL_PW_CTL_IDX_AUX_TBT4, .hsw.is_tc_tbt = true, }, From ef1e170891904f0339af8fffbaad990243c7125b Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 22 Feb 2022 18:51:34 +0200 Subject: [PATCH 00041/11454] drm/i915: Move power well get/put/enable/disable functions to a new file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the power well get/put/enable/disable hooks to the new intel_display_power_well.c file. The motivation is to reduce the clutter in intel_display_power.c, keeping the functionality related to power domains in that file and moving the low-level power well functionality to intel_display_power_well.c. No functional change. Suggested-by: Jani Nikula Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220222165137.1004194-6-imre.deak@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + .../drm/i915/display/intel_display_power.c | 127 +----------------- .../i915/display/intel_display_power_well.c | 41 ++++++ .../i915/display/intel_display_power_well.h | 115 ++++++++++++++++ 4 files changed, 158 insertions(+), 126 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_display_power_well.c create mode 100644 drivers/gpu/drm/i915/display/intel_display_power_well.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 9d588d936e3d..1a771ee5b1d0 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -212,6 +212,7 @@ i915-y += \ display/intel_cursor.o \ display/intel_display.o \ display/intel_display_power.o \ + display/intel_display_power_well.o \ display/intel_dmc.o \ display/intel_dpio_phy.o \ display/intel_dpll.o \ diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 32e4fc6a451e..a18895a9aa42 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -11,6 +11,7 @@ #include "intel_crt.h" #include "intel_de.h" #include "intel_display_power.h" +#include "intel_display_power_well.h" #include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dpio_phy.h" @@ -26,98 +27,6 @@ #include "intel_vga.h" #include "vlv_sideband.h" -struct i915_power_well_regs { - i915_reg_t bios; - i915_reg_t driver; - i915_reg_t kvmr; - i915_reg_t debug; -}; - -struct i915_power_well_ops { - const struct i915_power_well_regs *regs; - /* - * Synchronize the well's hw state to match the current sw state, for - * example enable/disable it based on the current refcount. Called - * during driver init and resume time, possibly after first calling - * the enable/disable handlers. - */ - void (*sync_hw)(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well); - /* - * Enable the well and resources that depend on it (for example - * interrupts located on the well). Called after the 0->1 refcount - * transition. - */ - void (*enable)(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well); - /* - * Disable the well and resources that depend on it. Called after - * the 1->0 refcount transition. - */ - void (*disable)(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well); - /* Returns the hw enabled state. */ - bool (*is_enabled)(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well); -}; - -/* Power well structure for haswell */ -struct i915_power_well_desc { - const char *name; - bool always_on; - u64 domains; - /* unique identifier for this power well */ - enum i915_power_well_id id; - /* - * Arbitraty data associated with this power well. Platform and power - * well specific. - */ - union { - struct { - /* - * request/status flag index in the PUNIT power well - * control/status registers. - */ - u8 idx; - } vlv; - struct { - enum dpio_phy phy; - } bxt; - struct { - /* - * request/status flag index in the power well - * constrol/status registers. - */ - u8 idx; - /* Mask of pipes whose IRQ logic is backed by the pw */ - u8 irq_pipe_mask; - /* - * Instead of waiting for the status bit to ack enables, - * just wait a specific amount of time and then consider - * the well enabled. - */ - u16 fixed_enable_delay; - /* The pw is backing the VGA functionality */ - bool has_vga:1; - bool has_fuses:1; - /* - * The pw is for an ICL+ TypeC PHY port in - * Thunderbolt mode. - */ - bool is_tc_tbt:1; - } hsw; - }; - const struct i915_power_well_ops *ops; -}; - -struct i915_power_well { - const struct i915_power_well_desc *desc; - /* power well enable/disable usage count */ - int count; - /* cached hw enabled state */ - bool hw_enabled; -}; - bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, enum i915_power_well_id power_well_id); @@ -259,40 +168,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain) } } -static void intel_power_well_enable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - drm_dbg_kms(&dev_priv->drm, "enabling %s\n", power_well->desc->name); - power_well->desc->ops->enable(dev_priv, power_well); - power_well->hw_enabled = true; -} - -static void intel_power_well_disable(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - drm_dbg_kms(&dev_priv->drm, "disabling %s\n", power_well->desc->name); - power_well->hw_enabled = false; - power_well->desc->ops->disable(dev_priv, power_well); -} - -static void intel_power_well_get(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - if (!power_well->count++) - intel_power_well_enable(dev_priv, power_well); -} - -static void intel_power_well_put(struct drm_i915_private *dev_priv, - struct i915_power_well *power_well) -{ - drm_WARN(&dev_priv->drm, !power_well->count, - "Use count on power well %s is already zero", - power_well->desc->name); - - if (!--power_well->count) - intel_power_well_disable(dev_priv, power_well); -} - /** * __intel_display_power_is_enabled - unlocked check for a power domain * @dev_priv: i915 device instance diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c new file mode 100644 index 000000000000..e21190854fa0 --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + */ + +#include "i915_drv.h" +#include "intel_display_power_well.h" + +void intel_power_well_enable(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + drm_dbg_kms(&i915->drm, "enabling %s\n", power_well->desc->name); + power_well->desc->ops->enable(i915, power_well); + power_well->hw_enabled = true; +} + +void intel_power_well_disable(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + drm_dbg_kms(&i915->drm, "disabling %s\n", power_well->desc->name); + power_well->hw_enabled = false; + power_well->desc->ops->disable(i915, power_well); +} + +void intel_power_well_get(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + if (!power_well->count++) + intel_power_well_enable(i915, power_well); +} + +void intel_power_well_put(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + drm_WARN(&i915->drm, !power_well->count, + "Use count on power well %s is already zero", + power_well->desc->name); + + if (!--power_well->count) + intel_power_well_disable(i915, power_well); +} diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h new file mode 100644 index 000000000000..bc77de3a8d4f --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h @@ -0,0 +1,115 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ +#ifndef __INTEL_DISPLAY_POWER_WELL_H__ +#define __INTEL_DISPLAY_POWER_WELL_H__ + +#include + +#include "intel_display.h" +#include "intel_display_power.h" + +struct drm_i915_private; + +struct i915_power_well_regs { + i915_reg_t bios; + i915_reg_t driver; + i915_reg_t kvmr; + i915_reg_t debug; +}; + +struct i915_power_well_ops { + const struct i915_power_well_regs *regs; + /* + * Synchronize the well's hw state to match the current sw state, for + * example enable/disable it based on the current refcount. Called + * during driver init and resume time, possibly after first calling + * the enable/disable handlers. + */ + void (*sync_hw)(struct drm_i915_private *i915, + struct i915_power_well *power_well); + /* + * Enable the well and resources that depend on it (for example + * interrupts located on the well). Called after the 0->1 refcount + * transition. + */ + void (*enable)(struct drm_i915_private *i915, + struct i915_power_well *power_well); + /* + * Disable the well and resources that depend on it. Called after + * the 1->0 refcount transition. + */ + void (*disable)(struct drm_i915_private *i915, + struct i915_power_well *power_well); + /* Returns the hw enabled state. */ + bool (*is_enabled)(struct drm_i915_private *i915, + struct i915_power_well *power_well); +}; + +struct i915_power_well_desc { + const char *name; + bool always_on; + u64 domains; + /* unique identifier for this power well */ + enum i915_power_well_id id; + /* + * Arbitraty data associated with this power well. Platform and power + * well specific. + */ + union { + struct { + /* + * request/status flag index in the PUNIT power well + * control/status registers. + */ + u8 idx; + } vlv; + struct { + enum dpio_phy phy; + } bxt; + struct { + /* + * request/status flag index in the power well + * constrol/status registers. + */ + u8 idx; + /* Mask of pipes whose IRQ logic is backed by the pw */ + u8 irq_pipe_mask; + /* + * Instead of waiting for the status bit to ack enables, + * just wait a specific amount of time and then consider + * the well enabled. + */ + u16 fixed_enable_delay; + /* The pw is backing the VGA functionality */ + bool has_vga:1; + bool has_fuses:1; + /* + * The pw is for an ICL+ TypeC PHY port in + * Thunderbolt mode. + */ + bool is_tc_tbt:1; + } hsw; + }; + const struct i915_power_well_ops *ops; +}; + +struct i915_power_well { + const struct i915_power_well_desc *desc; + /* power well enable/disable usage count */ + int count; + /* cached hw enabled state */ + bool hw_enabled; +}; + +void intel_power_well_enable(struct drm_i915_private *i915, + struct i915_power_well *power_well); +void intel_power_well_disable(struct drm_i915_private *i915, + struct i915_power_well *power_well); +void intel_power_well_get(struct drm_i915_private *i915, + struct i915_power_well *power_well); +void intel_power_well_put(struct drm_i915_private *i915, + struct i915_power_well *power_well); + +#endif From 90cf356bb4eb46a9f71248a28b2a5f1983a78a10 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 22 Feb 2022 18:51:35 +0200 Subject: [PATCH 00042/11454] drm/i915: Add function to call a power well's sync_hw() hook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a function to call a power well's sync_hw() hook, instead of open-coding the same, as a step towards making the low-level power well internals (i915_power_well_ops/desc structs) hidden. The cached-enable state should be always up-to-date, so update it whenever sync_hw() is called. No functional change. Suggested-by: Jani Nikula Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220222165137.1004194-7-imre.deak@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 7 ++----- drivers/gpu/drm/i915/display/intel_display_power_well.c | 8 ++++++++ drivers/gpu/drm/i915/display/intel_display_power_well.h | 2 ++ 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index a18895a9aa42..b8b914d8f0b5 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5016,11 +5016,8 @@ static void intel_power_domains_sync_hw(struct drm_i915_private *dev_priv) struct i915_power_well *power_well; mutex_lock(&power_domains->lock); - for_each_power_well(dev_priv, power_well) { - power_well->desc->ops->sync_hw(dev_priv, power_well); - power_well->hw_enabled = - power_well->desc->ops->is_enabled(dev_priv, power_well); - } + for_each_power_well(dev_priv, power_well) + intel_power_well_sync_hw(dev_priv, power_well); mutex_unlock(&power_domains->lock); } diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index e21190854fa0..63b97bcc64bc 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -22,6 +22,14 @@ void intel_power_well_disable(struct drm_i915_private *i915, power_well->desc->ops->disable(i915, power_well); } +void intel_power_well_sync_hw(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + power_well->desc->ops->sync_hw(i915, power_well); + power_well->hw_enabled = + power_well->desc->ops->is_enabled(i915, power_well); +} + void intel_power_well_get(struct drm_i915_private *i915, struct i915_power_well *power_well) { diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h index bc77de3a8d4f..ba5bbd36f7fc 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.h +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h @@ -107,6 +107,8 @@ void intel_power_well_enable(struct drm_i915_private *i915, struct i915_power_well *power_well); void intel_power_well_disable(struct drm_i915_private *i915, struct i915_power_well *power_well); +void intel_power_well_sync_hw(struct drm_i915_private *i915, + struct i915_power_well *power_well); void intel_power_well_get(struct drm_i915_private *i915, struct i915_power_well *power_well); void intel_power_well_put(struct drm_i915_private *i915, From 3ab5e051cb329745ef2fd0053906f345ed82979d Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 22 Feb 2022 18:51:36 +0200 Subject: [PATCH 00043/11454] drm/i915: Add functions to get a power well's state/name/domains/mask/refcount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add functions to get a power well's actual- and cached-enabled state, name, domain mask and refcount, as a step towards making the low-level power well internals (i915_power_well_ops/desc structs) hidden. No functional change. Suggested-by: Jani Nikula Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220222165137.1004194-8-imre.deak@intel.com --- .../drm/i915/display/intel_display_power.c | 69 +++++++++---------- .../i915/display/intel_display_power_well.c | 31 +++++++++ .../i915/display/intel_display_power_well.h | 7 ++ 3 files changed, 72 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index b8b914d8f0b5..a7aa4a427723 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -192,10 +192,10 @@ bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv, is_enabled = true; for_each_power_domain_well_reverse(dev_priv, power_well, BIT_ULL(domain)) { - if (power_well->desc->always_on) + if (intel_power_well_is_always_on(power_well)) continue; - if (!power_well->hw_enabled) { + if (!intel_power_well_is_enabled_cached(power_well)) { is_enabled = false; break; } @@ -331,7 +331,7 @@ static void hsw_wait_for_power_well_enable(struct drm_i915_private *dev_priv, if (intel_de_wait_for_set(dev_priv, regs->driver, HSW_PWR_WELL_CTL_STATE(pw_idx), 1)) { drm_dbg_kms(&dev_priv->drm, "%s power well enable timeout\n", - power_well->desc->name); + intel_power_well_name(power_well)); drm_WARN_ON(&dev_priv->drm, !timeout_expected); @@ -379,7 +379,7 @@ static void hsw_wait_for_power_well_disable(struct drm_i915_private *dev_priv, drm_dbg_kms(&dev_priv->drm, "%s forced on (bios:%d driver:%d kvmr:%d debug:%d)\n", - power_well->desc->name, + intel_power_well_name(power_well), !!(reqs & 1), !!(reqs & 2), !!(reqs & 4), !!(reqs & 8)); } @@ -968,8 +968,7 @@ void intel_display_power_set_target_dc_state(struct drm_i915_private *dev_priv, if (state == dev_priv->dmc.target_dc_state) goto unlock; - dc_off_enabled = power_well->desc->ops->is_enabled(dev_priv, - power_well); + dc_off_enabled = intel_power_well_is_enabled(dev_priv, power_well); /* * If DC off power well is disabled, need to enable and disable the * DC off power well to effect target DC state. @@ -1091,17 +1090,17 @@ static void bxt_verify_ddi_phy_power_wells(struct drm_i915_private *dev_priv) struct i915_power_well *power_well; power_well = lookup_power_well(dev_priv, BXT_DISP_PW_DPIO_CMN_A); - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy); power_well = lookup_power_well(dev_priv, VLV_DISP_PW_DPIO_CMN_BC); - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy); if (IS_GEMINILAKE(dev_priv)) { power_well = lookup_power_well(dev_priv, GLK_DISP_PW_DPIO_CMN_C); - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) bxt_ddi_phy_verify_state(dev_priv, power_well->desc->bxt.phy); } @@ -1227,7 +1226,7 @@ static bool i830_pipes_power_well_enabled(struct drm_i915_private *dev_priv, static void i830_pipes_power_well_sync_hw(struct drm_i915_private *dev_priv, struct i915_power_well *power_well) { - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) i830_pipes_power_well_enable(dev_priv, power_well); else i830_pipes_power_well_disable(dev_priv, power_well); @@ -1500,7 +1499,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv) PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 0) | PHY_STATUS_SPLINE_LDO(DPIO_PHY1, DPIO_CH0, 1)); - if (cmn_bc->desc->ops->is_enabled(dev_priv, cmn_bc)) { + if (intel_power_well_is_enabled(dev_priv, cmn_bc)) { phy_status |= PHY_POWERGOOD(DPIO_PHY0); /* this assumes override is only used to enable lanes */ @@ -1541,7 +1540,7 @@ static void assert_chv_phy_status(struct drm_i915_private *dev_priv) phy_status |= PHY_STATUS_SPLINE_LDO(DPIO_PHY0, DPIO_CH1, 1); } - if (cmn_d->desc->ops->is_enabled(dev_priv, cmn_d)) { + if (intel_power_well_is_enabled(dev_priv, cmn_d)) { phy_status |= PHY_POWERGOOD(DPIO_PHY1); /* this assumes override is only used to enable lanes */ @@ -3335,12 +3334,10 @@ bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, enum i915_power_well_id power_well_id) { struct i915_power_well *power_well; - bool ret; power_well = lookup_power_well(dev_priv, power_well_id); - ret = power_well->desc->ops->is_enabled(dev_priv, power_well); - return ret; + return intel_power_well_is_enabled(dev_priv, power_well); } static const struct i915_power_well_desc skl_power_wells[] = { @@ -3910,7 +3907,7 @@ static void tgl_tc_cold_off_power_well_sync_hw(struct drm_i915_private *i915, struct i915_power_well *power_well) { - if (power_well->count > 0) + if (intel_power_well_refcount(power_well) > 0) tgl_tc_cold_off_power_well_enable(i915, power_well); else tgl_tc_cold_off_power_well_disable(i915, power_well); @@ -3924,7 +3921,7 @@ tgl_tc_cold_off_power_well_is_enabled(struct drm_i915_private *dev_priv, * Not the correctly implementation but there is no way to just read it * from PCODE, so returning count to avoid state mismatch errors */ - return power_well->count; + return intel_power_well_refcount(power_well); } static const struct i915_power_well_ops tgl_tc_cold_off_ops = { @@ -5730,7 +5727,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv) * override and set the lane powerdown bits accding to the * current lane status. */ - if (cmn_bc->desc->ops->is_enabled(dev_priv, cmn_bc)) { + if (intel_power_well_is_enabled(dev_priv, cmn_bc)) { u32 status = intel_de_read(dev_priv, DPLL(PIPE_A)); unsigned int mask; @@ -5761,7 +5758,7 @@ static void chv_phy_control_init(struct drm_i915_private *dev_priv) dev_priv->chv_phy_assert[DPIO_PHY0] = true; } - if (cmn_d->desc->ops->is_enabled(dev_priv, cmn_d)) { + if (intel_power_well_is_enabled(dev_priv, cmn_d)) { u32 status = intel_de_read(dev_priv, DPIO_PHY_STATUS); unsigned int mask; @@ -5797,8 +5794,8 @@ static void vlv_cmnlane_wa(struct drm_i915_private *dev_priv) lookup_power_well(dev_priv, VLV_DISP_PW_DISP2D); /* If the display might be already active skip this */ - if (cmn->desc->ops->is_enabled(dev_priv, cmn) && - disp2d->desc->ops->is_enabled(dev_priv, disp2d) && + if (intel_power_well_is_enabled(dev_priv, cmn) && + intel_power_well_is_enabled(dev_priv, disp2d) && intel_de_read(dev_priv, DPIO_CTL) & DPIO_CMNRST) return; @@ -5965,12 +5962,12 @@ void intel_power_domains_sanitize_state(struct drm_i915_private *i915) for_each_power_well_reverse(i915, power_well) { if (power_well->desc->always_on || power_well->count || - !power_well->desc->ops->is_enabled(i915, power_well)) + !intel_power_well_is_enabled(i915, power_well)) continue; drm_dbg_kms(&i915->drm, "BIOS left unused %s power well enabled, disabling it\n", - power_well->desc->name); + intel_power_well_name(power_well)); intel_power_well_disable(i915, power_well); } @@ -6109,9 +6106,9 @@ static void intel_power_domains_dump_info(struct drm_i915_private *i915) enum intel_display_power_domain domain; drm_dbg(&i915->drm, "%-25s %d\n", - power_well->desc->name, power_well->count); + intel_power_well_name(power_well), intel_power_well_refcount(power_well)); - for_each_power_domain(domain, power_well->desc->domains) + for_each_power_domain(domain, intel_power_well_domains(power_well)) drm_dbg(&i915->drm, " %-23s %d\n", intel_display_power_domain_str(domain), power_domains->domain_use_count[domain]); @@ -6144,23 +6141,25 @@ static void intel_power_domains_verify_state(struct drm_i915_private *i915) int domains_count; bool enabled; - enabled = power_well->desc->ops->is_enabled(i915, power_well); - if ((power_well->count || power_well->desc->always_on) != + enabled = intel_power_well_is_enabled(i915, power_well); + if ((intel_power_well_refcount(power_well) || + intel_power_well_is_always_on(power_well)) != enabled) drm_err(&i915->drm, "power well %s state mismatch (refcount %d/enabled %d)", - power_well->desc->name, - power_well->count, enabled); + intel_power_well_name(power_well), + intel_power_well_refcount(power_well), enabled); domains_count = 0; - for_each_power_domain(domain, power_well->desc->domains) + for_each_power_domain(domain, intel_power_well_domains(power_well)) domains_count += power_domains->domain_use_count[domain]; - if (power_well->count != domains_count) { + if (intel_power_well_refcount(power_well) != domains_count) { drm_err(&i915->drm, "power well %s refcount/domain refcount mismatch " "(refcount %d/domains refcount %d)\n", - power_well->desc->name, power_well->count, + intel_power_well_name(power_well), + intel_power_well_refcount(power_well), domains_count); dump_domain_info = true; } @@ -6265,10 +6264,10 @@ void intel_display_power_debug(struct drm_i915_private *i915, struct seq_file *m enum intel_display_power_domain power_domain; power_well = &power_domains->power_wells[i]; - seq_printf(m, "%-25s %d\n", power_well->desc->name, - power_well->count); + seq_printf(m, "%-25s %d\n", intel_power_well_name(power_well), + intel_power_well_refcount(power_well)); - for_each_power_domain(power_domain, power_well->desc->domains) + for_each_power_domain(power_domain, intel_power_well_domains(power_well)) seq_printf(m, " %-23s %d\n", intel_display_power_domain_str(power_domain), power_domains->domain_use_count[power_domain]); diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 63b97bcc64bc..415ad193a8e8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -47,3 +47,34 @@ void intel_power_well_put(struct drm_i915_private *i915, if (!--power_well->count) intel_power_well_disable(i915, power_well); } + +bool intel_power_well_is_enabled(struct drm_i915_private *i915, + struct i915_power_well *power_well) +{ + return power_well->desc->ops->is_enabled(i915, power_well); +} + +bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well) +{ + return power_well->hw_enabled; +} + +bool intel_power_well_is_always_on(struct i915_power_well *power_well) +{ + return power_well->desc->always_on; +} + +const char *intel_power_well_name(struct i915_power_well *power_well) +{ + return power_well->desc->name; +} + +u64 intel_power_well_domains(struct i915_power_well *power_well) +{ + return power_well->desc->domains; +} + +int intel_power_well_refcount(struct i915_power_well *power_well) +{ + return power_well->count; +} diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h index ba5bbd36f7fc..43affbdbc48c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.h +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h @@ -113,5 +113,12 @@ void intel_power_well_get(struct drm_i915_private *i915, struct i915_power_well *power_well); void intel_power_well_put(struct drm_i915_private *i915, struct i915_power_well *power_well); +bool intel_power_well_is_enabled(struct drm_i915_private *i915, + struct i915_power_well *power_well); +bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well); +bool intel_power_well_is_always_on(struct i915_power_well *power_well); +const char *intel_power_well_name(struct i915_power_well *power_well); +u64 intel_power_well_domains(struct i915_power_well *power_well); +int intel_power_well_refcount(struct i915_power_well *power_well); #endif From 47f16fe53545289e2e90e59a1c4679c87e833cf9 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 22 Feb 2022 18:51:37 +0200 Subject: [PATCH 00044/11454] drm/i915: Move intel_display_power_well_is_enabled() to intel_display_power_well.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move intel_display_power_well_is_enabled() to intel_power_well.c, as a step towards making the low-level power well internals (i915_power_well_ops/desc structs) hidden. Eventually the call to this function and in general accessing power wells directly from elsewhere in the driver should be replaced by the use of power domains. No functional change. Suggested-by: Jani Nikula Cc: Jani Nikula Signed-off-by: Imre Deak Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220222165137.1004194-9-imre.deak@intel.com --- .../drm/i915/display/intel_display_debugfs.c | 1 + .../drm/i915/display/intel_display_power.c | 36 ------------------- .../drm/i915/display/intel_display_power.h | 26 -------------- .../i915/display/intel_display_power_well.c | 33 +++++++++++++++++ .../i915/display/intel_display_power_well.h | 31 +++++++++++++++- drivers/gpu/drm/i915/display/intel_hdcp.c | 1 + 6 files changed, 65 insertions(+), 63 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index ffe6822d7414..78752ce46639 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -10,6 +10,7 @@ #include "intel_de.h" #include "intel_display_debugfs.h" #include "intel_display_power.h" +#include "intel_display_power_well.h" #include "intel_display_types.h" #include "intel_dmc.h" #include "intel_dp.h" diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index a7aa4a427723..e8e8ce13aa96 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -27,9 +27,6 @@ #include "intel_vga.h" #include "vlv_sideband.h" -bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, - enum i915_power_well_id power_well_id); - const char * intel_display_power_domain_str(enum intel_display_power_domain domain) { @@ -918,29 +915,6 @@ static void assert_dmc_loaded(struct drm_i915_private *dev_priv) "DMC HTP Not fine\n"); } -static struct i915_power_well * -lookup_power_well(struct drm_i915_private *dev_priv, - enum i915_power_well_id power_well_id) -{ - struct i915_power_well *power_well; - - for_each_power_well(dev_priv, power_well) - if (power_well->desc->id == power_well_id) - return power_well; - - /* - * It's not feasible to add error checking code to the callers since - * this condition really shouldn't happen and it doesn't even make sense - * to abort things like display initialization sequences. Just return - * the first power well and hope the WARN gets reported so we can fix - * our driver. - */ - drm_WARN(&dev_priv->drm, 1, - "Power well %d not defined for this platform\n", - power_well_id); - return &dev_priv->power_domains.power_wells[0]; -} - /** * intel_display_power_set_target_dc_state - Set target dc state. * @dev_priv: i915 device @@ -3330,16 +3304,6 @@ static const struct i915_power_well_desc chv_power_wells[] = { }, }; -bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, - enum i915_power_well_id power_well_id) -{ - struct i915_power_well *power_well; - - power_well = lookup_power_well(dev_priv, power_well_id); - - return intel_power_well_is_enabled(dev_priv, power_well); -} - static const struct i915_power_well_desc skl_power_wells[] = { { .name = "always-on", diff --git a/drivers/gpu/drm/i915/display/intel_display_power.h b/drivers/gpu/drm/i915/display/intel_display_power.h index f28aa4b500c4..ced384b0a165 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.h +++ b/drivers/gpu/drm/i915/display/intel_display_power.h @@ -132,30 +132,6 @@ enum intel_display_power_domain { POWER_DOMAIN_NUM, }; -/* - * i915_power_well_id: - * - * IDs used to look up power wells. Power wells accessed directly bypassing - * the power domains framework must be assigned a unique ID. The rest of power - * wells must be assigned DISP_PW_ID_NONE. - */ -enum i915_power_well_id { - DISP_PW_ID_NONE, - - VLV_DISP_PW_DISP2D, - BXT_DISP_PW_DPIO_CMN_A, - VLV_DISP_PW_DPIO_CMN_BC, - GLK_DISP_PW_DPIO_CMN_C, - CHV_DISP_PW_DPIO_CMN_D, - HSW_DISP_PW_GLOBAL, - SKL_DISP_PW_MISC_IO, - SKL_DISP_PW_1, - SKL_DISP_PW_2, - ICL_DISP_PW_3, - SKL_DISP_DC_OFF, - TGL_DISP_PW_TC_COLD_OFF, -}; - #define POWER_DOMAIN_PIPE(pipe) ((pipe) + POWER_DOMAIN_PIPE_A) #define POWER_DOMAIN_PIPE_PANEL_FITTER(pipe) \ ((pipe) + POWER_DOMAIN_PIPE_A_PANEL_FITTER) @@ -239,8 +215,6 @@ intel_display_power_domain_str(enum intel_display_power_domain domain); bool intel_display_power_is_enabled(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); -bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, - enum i915_power_well_id power_well_id); bool __intel_display_power_is_enabled(struct drm_i915_private *dev_priv, enum intel_display_power_domain domain); intel_wakeref_t intel_display_power_get(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.c b/drivers/gpu/drm/i915/display/intel_display_power_well.c index 415ad193a8e8..2a0fb9d9c60f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.c +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.c @@ -6,6 +6,29 @@ #include "i915_drv.h" #include "intel_display_power_well.h" +struct i915_power_well * +lookup_power_well(struct drm_i915_private *i915, + enum i915_power_well_id power_well_id) +{ + struct i915_power_well *power_well; + + for_each_power_well(i915, power_well) + if (power_well->desc->id == power_well_id) + return power_well; + + /* + * It's not feasible to add error checking code to the callers since + * this condition really shouldn't happen and it doesn't even make sense + * to abort things like display initialization sequences. Just return + * the first power well and hope the WARN gets reported so we can fix + * our driver. + */ + drm_WARN(&i915->drm, 1, + "Power well %d not defined for this platform\n", + power_well_id); + return &i915->power_domains.power_wells[0]; +} + void intel_power_well_enable(struct drm_i915_private *i915, struct i915_power_well *power_well) { @@ -59,6 +82,16 @@ bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well) return power_well->hw_enabled; } +bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, + enum i915_power_well_id power_well_id) +{ + struct i915_power_well *power_well; + + power_well = lookup_power_well(dev_priv, power_well_id); + + return intel_power_well_is_enabled(dev_priv, power_well); +} + bool intel_power_well_is_always_on(struct i915_power_well *power_well) { return power_well->desc->always_on; diff --git a/drivers/gpu/drm/i915/display/intel_display_power_well.h b/drivers/gpu/drm/i915/display/intel_display_power_well.h index 43affbdbc48c..9a3756fdcf7f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power_well.h +++ b/drivers/gpu/drm/i915/display/intel_display_power_well.h @@ -8,9 +8,33 @@ #include #include "intel_display.h" -#include "intel_display_power.h" struct drm_i915_private; +struct i915_power_well; + +/* + * i915_power_well_id: + * + * IDs used to look up power wells. Power wells accessed directly bypassing + * the power domains framework must be assigned a unique ID. The rest of power + * wells must be assigned DISP_PW_ID_NONE. + */ +enum i915_power_well_id { + DISP_PW_ID_NONE, + + VLV_DISP_PW_DISP2D, + BXT_DISP_PW_DPIO_CMN_A, + VLV_DISP_PW_DPIO_CMN_BC, + GLK_DISP_PW_DPIO_CMN_C, + CHV_DISP_PW_DPIO_CMN_D, + HSW_DISP_PW_GLOBAL, + SKL_DISP_PW_MISC_IO, + SKL_DISP_PW_1, + SKL_DISP_PW_2, + ICL_DISP_PW_3, + SKL_DISP_DC_OFF, + TGL_DISP_PW_TC_COLD_OFF, +}; struct i915_power_well_regs { i915_reg_t bios; @@ -103,6 +127,9 @@ struct i915_power_well { bool hw_enabled; }; +struct i915_power_well *lookup_power_well(struct drm_i915_private *i915, + enum i915_power_well_id id); + void intel_power_well_enable(struct drm_i915_private *i915, struct i915_power_well *power_well); void intel_power_well_disable(struct drm_i915_private *i915, @@ -116,6 +143,8 @@ void intel_power_well_put(struct drm_i915_private *i915, bool intel_power_well_is_enabled(struct drm_i915_private *i915, struct i915_power_well *power_well); bool intel_power_well_is_enabled_cached(struct i915_power_well *power_well); +bool intel_display_power_well_is_enabled(struct drm_i915_private *dev_priv, + enum i915_power_well_id power_well_id); bool intel_power_well_is_always_on(struct i915_power_well *power_well); const char *intel_power_well_name(struct i915_power_well *power_well); u64 intel_power_well_domains(struct i915_power_well *power_well); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index e1ecf38db0ef..4de4c174a987 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -20,6 +20,7 @@ #include "intel_connector.h" #include "intel_de.h" #include "intel_display_power.h" +#include "intel_display_power_well.h" #include "intel_display_types.h" #include "intel_hdcp.h" #include "intel_pcode.h" From 17003d109e6cd08d4db5f6525a1023537ce6c743 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 23 Feb 2022 12:09:23 +0000 Subject: [PATCH 00045/11454] drm/i915: make a handful of read-only arrays static const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't populate the read-only arrays on the stack but instead make them static const and signed 8 bit ints. Also makes the object code a little smaller. Reformat the statements to clear up checkpatch warning. Signed-off-by: Colin Ian King Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223120923.239867-1-colin.i.king@gmail.com --- drivers/gpu/drm/i915/display/intel_vdsc.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index 545eff5bf158..e7120900bc45 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -378,10 +378,18 @@ calculate_rc_params(struct rc_parameters *rc, { int bpc = vdsc_cfg->bits_per_component; int bpp = vdsc_cfg->bits_per_pixel >> 4; - int ofs_und6[] = { 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 }; - int ofs_und8[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 }; - int ofs_und12[] = { 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 }; - int ofs_und15[] = { 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 }; + static const s8 ofs_und6[] = { + 0, -2, -2, -4, -6, -6, -8, -8, -8, -10, -10, -12, -12, -12, -12 + }; + static const s8 ofs_und8[] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 + }; + static const s8 ofs_und12[] = { + 2, 0, 0, -2, -4, -6, -8, -8, -8, -10, -10, -10, -12, -12, -12 + }; + static const s8 ofs_und15[] = { + 10, 8, 6, 4, 2, 0, -2, -4, -6, -8, -10, -10, -12, -12, -12 + }; int qp_bpc_modifier = (bpc - 8) * 2; u32 res, buf_i, bpp_i; From 01fabda8e3d62e9f45b6f2a86869fa02e5587ddf Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 25 Feb 2022 15:46:28 -0800 Subject: [PATCH 00046/11454] drm/i915: Use str_yes_no() Remove the local yesno() implementation and adopt the str_yes_no() from linux/string_helpers.h. Signed-off-by: Lucas De Marchi Acked-by: Daniel Vetter Acked-by: Jani Nikula Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220225234631.3725943-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 23 +++---- .../drm/i915/display/intel_display_debugfs.c | 65 +++++++++++-------- .../drm/i915/display/intel_display_trace.h | 6 +- drivers/gpu/drm/i915/display/intel_dp.c | 12 ++-- drivers/gpu/drm/i915/display/intel_fbc.c | 4 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 3 +- drivers/gpu/drm/i915/display/intel_sprite.c | 6 +- .../gpu/drm/i915/gem/selftests/huge_pages.c | 9 +-- .../drm/i915/gem/selftests/i915_gem_context.c | 7 +- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 9 +-- .../drm/i915/gt/intel_execlists_submission.c | 7 +- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 3 +- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 52 ++++++++------- drivers/gpu/drm/i915/gt/intel_reset.c | 3 +- drivers/gpu/drm/i915/gt/intel_rps.c | 13 ++-- drivers/gpu/drm/i915/gt/intel_sseu.c | 9 ++- drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c | 10 +-- drivers/gpu/drm/i915/gt/selftest_timeline.c | 3 +- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 3 +- drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c | 3 +- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 10 +-- drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c | 20 +++--- drivers/gpu/drm/i915/i915_debugfs.c | 15 +++-- drivers/gpu/drm/i915/i915_gpu_error.c | 9 +-- drivers/gpu/drm/i915/i915_params.c | 5 +- drivers/gpu/drm/i915/i915_utils.h | 5 -- drivers/gpu/drm/i915/intel_device_info.c | 8 ++- drivers/gpu/drm/i915/intel_dram.c | 10 +-- drivers/gpu/drm/i915/intel_pm.c | 10 +-- drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c | 4 +- drivers/gpu/drm/i915/selftests/i915_active.c | 3 +- 31 files changed, 201 insertions(+), 148 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b8d511360f9f..938354dc6f16 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -2884,7 +2885,7 @@ static int intel_crtc_compute_pipe_mode(struct intel_crtc_state *crtc_state) "[CRTC:%d:%s] requested pixel clock (%d kHz) too high (max: %d kHz, double wide: %s)\n", crtc->base.base.id, crtc->base.name, pipe_mode->crtc_clock, clock_limit, - yesno(crtc_state->double_wide)); + str_yes_no(crtc_state->double_wide)); return -EINVAL; } @@ -5261,7 +5262,7 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state) drm_dbg_kms(&i915->drm, "[PLANE:%d:%s] fb: [NOFB], visible: %s\n", plane->base.base.id, plane->base.name, - yesno(plane_state->uapi.visible)); + str_yes_no(plane_state->uapi.visible)); return; } @@ -5269,7 +5270,7 @@ static void intel_dump_plane_state(const struct intel_plane_state *plane_state) "[PLANE:%d:%s] fb: [FB:%d] %ux%u format = %p4cc modifier = 0x%llx, visible: %s\n", plane->base.base.id, plane->base.name, fb->base.id, fb->width, fb->height, &fb->format->format, - fb->modifier, yesno(plane_state->uapi.visible)); + fb->modifier, str_yes_no(plane_state->uapi.visible)); drm_dbg_kms(&i915->drm, "\trotation: 0x%x, scaler: %d\n", plane_state->hw.rotation, plane_state->scaler_id); if (plane_state->uapi.visible) @@ -5292,7 +5293,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] enable: %s %s\n", crtc->base.base.id, crtc->base.name, - yesno(pipe_config->hw.enable), context); + str_yes_no(pipe_config->hw.enable), context); if (!pipe_config->hw.enable) goto dump_planes; @@ -5300,7 +5301,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, snprintf_output_types(buf, sizeof(buf), pipe_config->output_types); drm_dbg_kms(&dev_priv->drm, "active: %s, output_types: %s (0x%x), output format: %s\n", - yesno(pipe_config->hw.active), + str_yes_no(pipe_config->hw.active), buf, pipe_config->output_types, output_formats(pipe_config->output_format)); @@ -5370,7 +5371,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, intel_dump_dp_vsc_sdp(dev_priv, &pipe_config->infoframes.vsc); drm_dbg_kms(&dev_priv->drm, "vrr: %s, vmin: %d, vmax: %d, pipeline full: %d, guardband: %d flipline: %d, vmin vblank: %d, vmax vblank: %d\n", - yesno(pipe_config->vrr.enable), + str_yes_no(pipe_config->vrr.enable), pipe_config->vrr.vmin, pipe_config->vrr.vmax, pipe_config->vrr.pipeline_full, pipe_config->vrr.guardband, pipe_config->vrr.flipline, @@ -5412,7 +5413,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, "pch pfit: " DRM_RECT_FMT ", %s, force thru: %s\n", DRM_RECT_ARG(&pipe_config->pch_pfit.dst), enableddisabled(pipe_config->pch_pfit.enabled), - yesno(pipe_config->pch_pfit.force_thru)); + str_yes_no(pipe_config->pch_pfit.force_thru)); drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i\n", pipe_config->ips_enabled, pipe_config->double_wide); @@ -6058,8 +6059,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, if (current_config->name != pipe_config->name) { \ pipe_config_mismatch(fastset, crtc, __stringify(name), \ "(expected %s, found %s)", \ - yesno(current_config->name), \ - yesno(pipe_config->name)); \ + str_yes_no(current_config->name), \ + str_yes_no(pipe_config->name)); \ ret = false; \ } \ } while (0) @@ -6075,8 +6076,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, } else { \ pipe_config_mismatch(fastset, crtc, __stringify(name), \ "unable to verify whether state matches exactly, forcing modeset (expected %s, found %s)", \ - yesno(current_config->name), \ - yesno(pipe_config->name)); \ + str_yes_no(current_config->name), \ + str_yes_no(pipe_config->name)); \ ret = false; \ } \ } while (0) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 78752ce46639..c7717472cf9d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -3,6 +3,8 @@ * Copyright © 2020 Intel Corporation */ +#include + #include #include @@ -53,7 +55,7 @@ static int i915_ips_status(struct seq_file *m, void *unused) wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); seq_printf(m, "Enabled by kernel parameter: %s\n", - yesno(dev_priv->params.enable_ips)); + str_yes_no(dev_priv->params.enable_ips)); if (DISPLAY_VER(dev_priv) >= 8) { seq_puts(m, "Currently: unknown\n"); @@ -261,7 +263,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) bool enabled; u32 val; - seq_printf(m, "Sink support: %s", yesno(psr->sink_support)); + seq_printf(m, "Sink support: %s", str_yes_no(psr->sink_support)); if (psr->sink_support) seq_printf(m, " [0x%02x]", intel_dp->psr_dpcd[0]); seq_puts(m, "\n"); @@ -280,7 +282,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) if (!psr->enabled) { seq_printf(m, "PSR sink not reliable: %s\n", - yesno(psr->sink_not_reliable)); + str_yes_no(psr->sink_not_reliable)); goto unlock; } @@ -447,13 +449,17 @@ static int i915_dmc_info(struct seq_file *m, void *unused) wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); - seq_printf(m, "fw loaded: %s\n", yesno(intel_dmc_has_payload(dev_priv))); + seq_printf(m, "fw loaded: %s\n", + str_yes_no(intel_dmc_has_payload(dev_priv))); seq_printf(m, "path: %s\n", dmc->fw_path); seq_printf(m, "Pipe A fw support: %s\n", - yesno(GRAPHICS_VER(dev_priv) >= 12)); - seq_printf(m, "Pipe A fw loaded: %s\n", yesno(dmc->dmc_info[DMC_FW_PIPEA].payload)); - seq_printf(m, "Pipe B fw support: %s\n", yesno(IS_ALDERLAKE_P(dev_priv))); - seq_printf(m, "Pipe B fw loaded: %s\n", yesno(dmc->dmc_info[DMC_FW_PIPEB].payload)); + str_yes_no(GRAPHICS_VER(dev_priv) >= 12)); + seq_printf(m, "Pipe A fw loaded: %s\n", + str_yes_no(dmc->dmc_info[DMC_FW_PIPEA].payload)); + seq_printf(m, "Pipe B fw support: %s\n", + str_yes_no(IS_ALDERLAKE_P(dev_priv))); + seq_printf(m, "Pipe B fw loaded: %s\n", + str_yes_no(dmc->dmc_info[DMC_FW_PIPEB].payload)); if (!intel_dmc_has_payload(dev_priv)) goto out; @@ -578,7 +584,8 @@ static void intel_dp_info(struct seq_file *m, const struct drm_property_blob *edid = intel_connector->base.edid_blob_ptr; seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]); - seq_printf(m, "\taudio support: %s\n", yesno(intel_dp->has_audio)); + seq_printf(m, "\taudio support: %s\n", + str_yes_no(intel_dp->has_audio)); if (intel_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) intel_panel_info(m, &intel_connector->panel); @@ -591,7 +598,7 @@ static void intel_dp_mst_info(struct seq_file *m, { bool has_audio = intel_connector->port->has_audio; - seq_printf(m, "\taudio support: %s\n", yesno(has_audio)); + seq_printf(m, "\taudio support: %s\n", str_yes_no(has_audio)); } static void intel_hdmi_info(struct seq_file *m, @@ -600,7 +607,8 @@ static void intel_hdmi_info(struct seq_file *m, struct intel_encoder *intel_encoder = intel_attached_encoder(intel_connector); struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(intel_encoder); - seq_printf(m, "\taudio support: %s\n", yesno(intel_hdmi->has_audio)); + seq_printf(m, "\taudio support: %s\n", + str_yes_no(intel_hdmi->has_audio)); } static void intel_lvds_info(struct seq_file *m, @@ -758,7 +766,7 @@ static void intel_plane_hw_info(struct seq_file *m, struct intel_plane *plane) DRM_RECT_FP_FMT ", dst=" DRM_RECT_FMT ", rotation=%s\n", fb->base.id, &fb->format->format, fb->modifier, fb->width, fb->height, - yesno(plane_state->uapi.visible), + str_yes_no(plane_state->uapi.visible), DRM_RECT_FP_ARG(&plane_state->uapi.src), DRM_RECT_ARG(&plane_state->uapi.dst), rot_str); @@ -797,7 +805,7 @@ static void intel_scaler_info(struct seq_file *m, struct intel_crtc *crtc) &crtc_state->scaler_state.scalers[i]; seq_printf(m, ", scalers[%d]: use=%s, mode=%x", - i, yesno(sc->in_use), sc->mode); + i, str_yes_no(sc->in_use), sc->mode); } seq_puts(m, "\n"); } else { @@ -920,12 +928,12 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) crtc->base.base.id, crtc->base.name); seq_printf(m, "\tuapi: enable=%s, active=%s, mode=" DRM_MODE_FMT "\n", - yesno(crtc_state->uapi.enable), - yesno(crtc_state->uapi.active), + str_yes_no(crtc_state->uapi.enable), + str_yes_no(crtc_state->uapi.active), DRM_MODE_ARG(&crtc_state->uapi.mode)); seq_printf(m, "\thw: enable=%s, active=%s\n", - yesno(crtc_state->hw.enable), yesno(crtc_state->hw.active)); + str_yes_no(crtc_state->hw.enable), str_yes_no(crtc_state->hw.active)); seq_printf(m, "\tadjusted_mode=" DRM_MODE_FMT "\n", DRM_MODE_ARG(&crtc_state->hw.adjusted_mode)); seq_printf(m, "\tpipe__mode=" DRM_MODE_FMT "\n", @@ -933,7 +941,7 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) seq_printf(m, "\tpipe src size=%dx%d, dither=%s, bpp=%d\n", crtc_state->pipe_src_w, crtc_state->pipe_src_h, - yesno(crtc_state->dither), crtc_state->pipe_bpp); + str_yes_no(crtc_state->dither), crtc_state->pipe_bpp); intel_scaler_info(m, crtc); @@ -949,8 +957,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) intel_plane_info(m, crtc); seq_printf(m, "\tunderrun reporting: cpu=%s pch=%s\n", - yesno(!crtc->cpu_fifo_underrun_disabled), - yesno(!crtc->pch_fifo_underrun_disabled)); + str_yes_no(!crtc->cpu_fifo_underrun_disabled), + str_yes_no(!crtc->pch_fifo_underrun_disabled)); crtc_updates_info(m, crtc, "\t"); } @@ -1006,7 +1014,8 @@ static int i915_shared_dplls_info(struct seq_file *m, void *unused) seq_printf(m, "DPLL%i: %s, id: %i\n", i, pll->info->name, pll->info->id); seq_printf(m, " pipe_mask: 0x%x, active: 0x%x, on: %s\n", - pll->state.pipe_mask, pll->active_mask, yesno(pll->on)); + pll->state.pipe_mask, pll->active_mask, + str_yes_no(pll->on)); seq_printf(m, " tracked hardware state:\n"); seq_printf(m, " dpll: 0x%08x\n", pll->state.hw_state.dpll); seq_printf(m, " dpll_md: 0x%08x\n", @@ -1048,7 +1057,7 @@ static int i915_ipc_status_show(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = m->private; seq_printf(m, "Isochronous Priority Control: %s\n", - yesno(dev_priv->ipc_enabled)); + str_yes_no(dev_priv->ipc_enabled)); return 0; } @@ -1157,7 +1166,7 @@ static void drrs_status_per_crtc(struct seq_file *m, drrs->type == SEAMLESS_DRRS_SUPPORT) supported = true; - seq_printf(m, "\tDRRS Supported: %s\n", yesno(supported)); + seq_printf(m, "\tDRRS Supported: %s\n", str_yes_no(supported)); } drm_connector_list_iter_end(&conn_iter); @@ -1741,7 +1750,7 @@ static int i915_hpd_storm_ctl_show(struct seq_file *m, void *data) seq_printf(m, "Threshold: %d\n", hotplug->hpd_storm_threshold); seq_printf(m, "Detected: %s\n", - yesno(delayed_work_pending(&hotplug->reenable_work))); + str_yes_no(delayed_work_pending(&hotplug->reenable_work))); return 0; } @@ -1815,7 +1824,7 @@ static int i915_hpd_short_storm_ctl_show(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = m->private; seq_printf(m, "Enabled: %s\n", - yesno(dev_priv->hotplug.hpd_short_storm_enabled)); + str_yes_no(dev_priv->hotplug.hpd_short_storm_enabled)); return 0; } @@ -2210,14 +2219,14 @@ static int i915_dsc_fec_support_show(struct seq_file *m, void *data) intel_dp = intel_attached_dp(to_intel_connector(connector)); crtc_state = to_intel_crtc_state(crtc->state); seq_printf(m, "DSC_Enabled: %s\n", - yesno(crtc_state->dsc.compression_enable)); + str_yes_no(crtc_state->dsc.compression_enable)); seq_printf(m, "DSC_Sink_Support: %s\n", - yesno(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd))); + str_yes_no(drm_dp_sink_supports_dsc(intel_dp->dsc_dpcd))); seq_printf(m, "Force_DSC_Enable: %s\n", - yesno(intel_dp->force_dsc_en)); + str_yes_no(intel_dp->force_dsc_en)); if (!intel_dp_is_edp(intel_dp)) seq_printf(m, "FEC_Sink_Support: %s\n", - yesno(drm_dp_sink_supports_fec(intel_dp->fec_capable))); + str_yes_no(drm_dp_sink_supports_fec(intel_dp->fec_capable))); } while (try_again); drm_modeset_drop_locks(&ctx); diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index f05f0f9b5103..dcdd242fffd9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -210,9 +210,9 @@ TRACE_EVENT(g4x_wm, TP_printk("pipe %c, frame=%u, scanline=%u, wm %d/%d/%d, sr %s/%d/%d/%d, hpll %s/%d/%d/%d, fbc %s", pipe_name(__entry->pipe), __entry->frame, __entry->scanline, __entry->primary, __entry->sprite, __entry->cursor, - yesno(__entry->cxsr), __entry->sr_plane, __entry->sr_cursor, __entry->sr_fbc, - yesno(__entry->hpll), __entry->hpll_plane, __entry->hpll_cursor, __entry->hpll_fbc, - yesno(__entry->fbc)) + str_yes_no(__entry->cxsr), __entry->sr_plane, __entry->sr_cursor, __entry->sr_fbc, + str_yes_no(__entry->hpll), __entry->hpll_plane, __entry->hpll_cursor, __entry->hpll_fbc, + str_yes_no(__entry->fbc)) ); TRACE_EVENT(vlv_wm, diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 1046e7fe310a..6ffa5b28b976 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -2787,8 +2788,9 @@ intel_dp_configure_mst(struct intel_dp *intel_dp) drm_dbg_kms(&i915->drm, "[ENCODER:%d:%s] MST support: port: %s, sink: %s, modparam: %s\n", encoder->base.base.id, encoder->base.name, - yesno(intel_dp_mst_source_support(intel_dp)), yesno(sink_can_mst), - yesno(i915->params.enable_dp_mst)); + str_yes_no(intel_dp_mst_source_support(intel_dp)), + str_yes_no(sink_can_mst), + str_yes_no(i915->params.enable_dp_mst)); if (!intel_dp_mst_source_support(intel_dp)) return; @@ -4375,9 +4377,9 @@ intel_dp_update_420(struct intel_dp *intel_dp) drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] RGB->YcbCr conversion? %s, YCbCr 4:2:0 allowed? %s, YCbCr 4:4:4->4:2:0 conversion? %s\n", connector->base.base.id, connector->base.name, - yesno(intel_dp->dfp.rgb_to_ycbcr), - yesno(connector->base.ycbcr_420_allowed), - yesno(intel_dp->dfp.ycbcr_444_to_420)); + str_yes_no(intel_dp->dfp.rgb_to_ycbcr), + str_yes_no(connector->base.ycbcr_420_allowed), + str_yes_no(intel_dp->dfp.ycbcr_444_to_420)); } static void diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index f7dca327c294..142280b6ce6d 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -38,6 +38,8 @@ * forcibly disable it to allow proper screen updates. */ +#include + #include #include "i915_drv.h" @@ -1744,7 +1746,7 @@ static int intel_fbc_debugfs_status_show(struct seq_file *m, void *unused) if (fbc->active) { seq_puts(m, "FBC enabled\n"); seq_printf(m, "Compressing: %s\n", - yesno(intel_fbc_is_compressing(fbc))); + str_yes_no(intel_fbc_is_compressing(fbc))); } else { seq_printf(m, "FBC disabled: %s\n", fbc->no_fbc_reason); } diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index 1aa5bdc7b0dc..f3e688f739f3 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -2628,7 +2629,7 @@ bool intel_hdmi_handle_sink_scrambling(struct intel_encoder *encoder, drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] scrambling=%s, TMDS bit clock ratio=1/%d\n", connector->base.id, connector->name, - yesno(scrambling), high_tmds_clock_ratio ? 40 : 10); + str_yes_no(scrambling), high_tmds_clock_ratio ? 40 : 10); /* Set TMDS bit clock ratio to 1/40 or 1/10, and enable/disable scrambling */ return drm_scdc_set_high_tmds_clock_ratio(adapter, diff --git a/drivers/gpu/drm/i915/display/intel_sprite.c b/drivers/gpu/drm/i915/display/intel_sprite.c index f6875a49b8cb..7c0df80612d0 100644 --- a/drivers/gpu/drm/i915/display/intel_sprite.c +++ b/drivers/gpu/drm/i915/display/intel_sprite.c @@ -30,6 +30,8 @@ * support. */ +#include + #include #include #include @@ -96,13 +98,13 @@ int intel_plane_check_src_coordinates(struct intel_plane_state *plane_state) if (src_x % hsub || src_w % hsub) { drm_dbg_kms(&i915->drm, "src x/w (%u, %u) must be a multiple of %u (rotated: %s)\n", - src_x, src_w, hsub, yesno(rotated)); + src_x, src_w, hsub, str_yes_no(rotated)); return -EINVAL; } if (src_y % vsub || src_h % vsub) { drm_dbg_kms(&i915->drm, "src y/h (%u, %u) must be a multiple of %u (rotated: %s)\n", - src_y, src_h, vsub, yesno(rotated)); + src_y, src_h, vsub, str_yes_no(rotated)); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index 8424ee8c5eb8..c490c5624924 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -5,6 +5,7 @@ */ #include +#include #include "i915_selftest.h" @@ -804,7 +805,7 @@ static int igt_mock_ppgtt_huge_fill(void *arg) if (vma->resource->page_sizes_gtt != expected_gtt) { pr_err("gtt=%u, expected=%u, size=%zd, single=%s\n", vma->resource->page_sizes_gtt, expected_gtt, - obj->base.size, yesno(!!single)); + obj->base.size, str_yes_no(!!single)); err = -EINVAL; break; } @@ -960,7 +961,7 @@ static int igt_mock_ppgtt_64K(void *arg) if (vma->resource->page_sizes_gtt != expected_gtt) { pr_err("gtt=%u, expected=%u, i=%d, single=%s\n", vma->resource->page_sizes_gtt, - expected_gtt, i, yesno(!!single)); + expected_gtt, i, str_yes_no(!!single)); err = -EINVAL; goto out_vma_unpin; } @@ -1647,14 +1648,14 @@ static int igt_shrink_thp(void *arg) I915_SHRINK_WRITEBACK); if (should_swap == i915_gem_object_has_pages(obj)) { pr_err("unexpected pages mismatch, should_swap=%s\n", - yesno(should_swap)); + str_yes_no(should_swap)); err = -EINVAL; goto out_put; } if (should_swap == (obj->mm.page_sizes.sg || obj->mm.page_sizes.phys)) { pr_err("unexpected residual page-size bits, should_swap=%s\n", - yesno(should_swap)); + str_yes_no(should_swap)); err = -EINVAL; goto out_put; } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c index bd60d42238fb..2cdd8f2c002f 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_context.c @@ -5,6 +5,7 @@ */ #include +#include #include "gem/i915_gem_internal.h" #include "gem/i915_gem_pm.h" @@ -700,7 +701,7 @@ static int igt_ctx_exec(void *arg) pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n", ndwords, dw, max_dwords(obj), engine->name, - yesno(i915_gem_context_has_full_ppgtt(ctx)), + str_yes_no(i915_gem_context_has_full_ppgtt(ctx)), err); intel_context_put(ce); kernel_context_close(ctx); @@ -834,7 +835,7 @@ static int igt_shared_ctx_exec(void *arg) pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n", ndwords, dw, max_dwords(obj), engine->name, - yesno(i915_gem_context_has_full_ppgtt(ctx)), + str_yes_no(i915_gem_context_has_full_ppgtt(ctx)), err); intel_context_put(ce); kernel_context_close(ctx); @@ -1413,7 +1414,7 @@ static int igt_ctx_readonly(void *arg) pr_err("Failed to fill dword %lu [%lu/%lu] with gpu (%s) [full-ppgtt? %s], err=%d\n", ndwords, dw, max_dwords(obj), ce->engine->name, - yesno(i915_gem_context_has_full_ppgtt(ctx)), + str_yes_no(i915_gem_context_has_full_ppgtt(ctx)), err); i915_gem_context_unlock_engines(ctx); goto out_file; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index e53008b4dd05..0afb0bb8cf95 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -3,6 +3,8 @@ * Copyright © 2016 Intel Corporation */ +#include + #include #include "gem/i915_gem_context.h" @@ -1630,8 +1632,7 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine, u8 read, write; drm_printf(m, "\tExeclist tasklet queued? %s (%s), preempt? %s, timeslice? %s\n", - yesno(test_bit(TASKLET_STATE_SCHED, - &engine->sched_engine->tasklet.state)), + str_yes_no(test_bit(TASKLET_STATE_SCHED, &engine->sched_engine->tasklet.state)), enableddisabled(!atomic_read(&engine->sched_engine->tasklet.count)), repr_timer(&engine->execlists.preempt), repr_timer(&engine->execlists.timer)); @@ -1893,7 +1894,7 @@ void intel_engine_dump(struct intel_engine_cs *engine, drm_printf(m, "\tAwake? %d\n", atomic_read(&engine->wakeref.count)); drm_printf(m, "\tBarriers?: %s\n", - yesno(!llist_empty(&engine->barrier_tasks))); + str_yes_no(!llist_empty(&engine->barrier_tasks))); drm_printf(m, "\tLatency: %luus\n", ewma__engine_latency_read(&engine->latency)); if (intel_engine_supports_stats(engine)) @@ -1935,7 +1936,7 @@ void intel_engine_dump(struct intel_engine_cs *engine, drm_printf(m, "HWSP:\n"); hexdump(m, engine->status_page.addr, PAGE_SIZE); - drm_printf(m, "Idle? %s\n", yesno(intel_engine_is_idle(engine))); + drm_printf(m, "Idle? %s\n", str_yes_no(intel_engine_is_idle(engine))); intel_engine_print_breadcrumbs(engine, m); } diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 961d795220a3..42bfbafad32a 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -107,6 +107,7 @@ * */ #include +#include #include "i915_drv.h" #include "i915_trace.h" @@ -1331,11 +1332,11 @@ static void execlists_dequeue(struct intel_engine_cs *engine) } else if (timeslice_expired(engine, last)) { ENGINE_TRACE(engine, "expired:%s last=%llx:%lld, prio=%d, hint=%d, yield?=%s\n", - yesno(timer_expired(&execlists->timer)), + str_yes_no(timer_expired(&execlists->timer)), last->fence.context, last->fence.seqno, rq_prio(last), sched_engine->queue_priority_hint, - yesno(timeslice_yield(execlists, last))); + str_yes_no(timeslice_yield(execlists, last))); /* * Consume this timeslice; ensure we start a new one. @@ -1423,7 +1424,7 @@ static void execlists_dequeue(struct intel_engine_cs *engine) __i915_request_is_complete(rq) ? "!" : __i915_request_has_started(rq) ? "*" : "", - yesno(engine != ve->siblings[0])); + str_yes_no(engine != ve->siblings[0])); WRITE_ONCE(ve->request, NULL); WRITE_ONCE(ve->base.sched_engine->queue_priority_hint, INT_MIN); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index c0fa41e4c803..e4ecc17889d3 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -3,6 +3,7 @@ * Copyright © 2019 Intel Corporation */ +#include #include #include "i915_drv.h" @@ -157,7 +158,7 @@ static void gt_sanitize(struct intel_gt *gt, bool force) enum intel_engine_id id; intel_wakeref_t wakeref; - GT_TRACE(gt, "force:%s", yesno(force)); + GT_TRACE(gt, "force:%s", str_yes_no(force)); /* Use a raw wakeref to avoid calling intel_display_power_get early */ wakeref = intel_runtime_pm_get(gt->uncore->rpm); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 37765919fe32..4a1c74b8de05 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -5,6 +5,7 @@ */ #include +#include #include "i915_drv.h" #include "i915_reg.h" @@ -105,7 +106,7 @@ static int vlv_drpc(struct seq_file *m) rcctl1 = intel_uncore_read(uncore, GEN6_RC_CONTROL); seq_printf(m, "RC6 Enabled: %s\n", - yesno(rcctl1 & (GEN7_RC_CTL_TO_MODE | + str_yes_no(rcctl1 & (GEN7_RC_CTL_TO_MODE | GEN6_RC_CTL_EI_MODE(1)))); seq_printf(m, "Render Power Well: %s\n", (pw_status & VLV_GTLC_PW_RENDER_STATUS_MASK) ? "Up" : "Down"); @@ -140,19 +141,19 @@ static int gen6_drpc(struct seq_file *m) snb_pcode_read(i915, GEN6_PCODE_READ_RC6VIDS, &rc6vids, NULL); seq_printf(m, "RC1e Enabled: %s\n", - yesno(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); + str_yes_no(rcctl1 & GEN6_RC_CTL_RC1e_ENABLE)); seq_printf(m, "RC6 Enabled: %s\n", - yesno(rcctl1 & GEN6_RC_CTL_RC6_ENABLE)); + str_yes_no(rcctl1 & GEN6_RC_CTL_RC6_ENABLE)); if (GRAPHICS_VER(i915) >= 9) { seq_printf(m, "Render Well Gating Enabled: %s\n", - yesno(gen9_powergate_enable & GEN9_RENDER_PG_ENABLE)); + str_yes_no(gen9_powergate_enable & GEN9_RENDER_PG_ENABLE)); seq_printf(m, "Media Well Gating Enabled: %s\n", - yesno(gen9_powergate_enable & GEN9_MEDIA_PG_ENABLE)); + str_yes_no(gen9_powergate_enable & GEN9_MEDIA_PG_ENABLE)); } seq_printf(m, "Deep RC6 Enabled: %s\n", - yesno(rcctl1 & GEN6_RC_CTL_RC6p_ENABLE)); + str_yes_no(rcctl1 & GEN6_RC_CTL_RC6p_ENABLE)); seq_printf(m, "Deepest RC6 Enabled: %s\n", - yesno(rcctl1 & GEN6_RC_CTL_RC6pp_ENABLE)); + str_yes_no(rcctl1 & GEN6_RC_CTL_RC6pp_ENABLE)); seq_puts(m, "Current RC state: "); switch (gt_core_status & GEN6_RCn_MASK) { case GEN6_RC0: @@ -176,7 +177,7 @@ static int gen6_drpc(struct seq_file *m) } seq_printf(m, "Core Power Down: %s\n", - yesno(gt_core_status & GEN6_CORE_CPD_STATE_MASK)); + str_yes_no(gt_core_status & GEN6_CORE_CPD_STATE_MASK)); if (GRAPHICS_VER(i915) >= 9) { seq_printf(m, "Render Power Well: %s\n", (gen9_powergate_status & @@ -216,16 +217,17 @@ static int ilk_drpc(struct seq_file *m) rstdbyctl = intel_uncore_read(uncore, RSTDBYCTL); crstandvid = intel_uncore_read16(uncore, CRSTANDVID); - seq_printf(m, "HD boost: %s\n", yesno(rgvmodectl & MEMMODE_BOOST_EN)); + seq_printf(m, "HD boost: %s\n", + str_yes_no(rgvmodectl & MEMMODE_BOOST_EN)); seq_printf(m, "Boost freq: %d\n", (rgvmodectl & MEMMODE_BOOST_FREQ_MASK) >> MEMMODE_BOOST_FREQ_SHIFT); seq_printf(m, "HW control enabled: %s\n", - yesno(rgvmodectl & MEMMODE_HWIDLE_EN)); + str_yes_no(rgvmodectl & MEMMODE_HWIDLE_EN)); seq_printf(m, "SW control enabled: %s\n", - yesno(rgvmodectl & MEMMODE_SWMODE_EN)); + str_yes_no(rgvmodectl & MEMMODE_SWMODE_EN)); seq_printf(m, "Gated voltage change: %s\n", - yesno(rgvmodectl & MEMMODE_RCLK_GATE)); + str_yes_no(rgvmodectl & MEMMODE_RCLK_GATE)); seq_printf(m, "Starting frequency: P%d\n", (rgvmodectl & MEMMODE_FSTART_MASK) >> MEMMODE_FSTART_SHIFT); seq_printf(m, "Max P-state: P%d\n", @@ -234,7 +236,7 @@ static int ilk_drpc(struct seq_file *m) seq_printf(m, "RS1 VID: %d\n", (crstandvid & 0x3f)); seq_printf(m, "RS2 VID: %d\n", ((crstandvid >> 8) & 0x3f)); seq_printf(m, "Render standby enabled: %s\n", - yesno(!(rstdbyctl & RCX_SW_EXIT))); + str_yes_no(!(rstdbyctl & RCX_SW_EXIT))); seq_puts(m, "Current RS state: "); switch (rstdbyctl & RSX_STATUS_MASK) { case RSX_STATUS_ON: @@ -307,12 +309,11 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p) rpmodectl = intel_uncore_read(uncore, GEN6_RP_CONTROL); drm_printf(p, "Video Turbo Mode: %s\n", - yesno(rpmodectl & GEN6_RP_MEDIA_TURBO)); + str_yes_no(rpmodectl & GEN6_RP_MEDIA_TURBO)); drm_printf(p, "HW control enabled: %s\n", - yesno(rpmodectl & GEN6_RP_ENABLE)); + str_yes_no(rpmodectl & GEN6_RP_ENABLE)); drm_printf(p, "SW control enabled: %s\n", - yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == - GEN6_RP_MEDIA_SW_MODE)); + str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE)); vlv_punit_get(i915); freq_sts = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); @@ -417,12 +418,11 @@ void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *p) pm_mask = intel_uncore_read(uncore, GEN6_PMINTRMSK); drm_printf(p, "Video Turbo Mode: %s\n", - yesno(rpmodectl & GEN6_RP_MEDIA_TURBO)); + str_yes_no(rpmodectl & GEN6_RP_MEDIA_TURBO)); drm_printf(p, "HW control enabled: %s\n", - yesno(rpmodectl & GEN6_RP_ENABLE)); + str_yes_no(rpmodectl & GEN6_RP_ENABLE)); drm_printf(p, "SW control enabled: %s\n", - yesno((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == - GEN6_RP_MEDIA_SW_MODE)); + str_yes_no((rpmodectl & GEN6_RP_MEDIA_MODE_MASK) == GEN6_RP_MEDIA_SW_MODE)); drm_printf(p, "PM IER=0x%08x IMR=0x%08x, MASK=0x%08x\n", pm_ier, pm_imr, pm_mask); @@ -542,7 +542,7 @@ static int llc_show(struct seq_file *m, void *data) intel_wakeref_t wakeref; int gpu_freq, ia_freq; - seq_printf(m, "LLC: %s\n", yesno(HAS_LLC(i915))); + seq_printf(m, "LLC: %s\n", str_yes_no(HAS_LLC(i915))); seq_printf(m, "%s: %uMB\n", edram ? "eDRAM" : "eLLC", i915->edram_size_mb); @@ -604,10 +604,12 @@ static int rps_boost_show(struct seq_file *m, void *data) struct drm_i915_private *i915 = gt->i915; struct intel_rps *rps = >->rps; - seq_printf(m, "RPS enabled? %s\n", yesno(intel_rps_is_enabled(rps))); - seq_printf(m, "RPS active? %s\n", yesno(intel_rps_is_active(rps))); + seq_printf(m, "RPS enabled? %s\n", + str_yes_no(intel_rps_is_enabled(rps))); + seq_printf(m, "RPS active? %s\n", + str_yes_no(intel_rps_is_active(rps))); seq_printf(m, "GPU busy? %s, %llums\n", - yesno(gt->awake), + str_yes_no(gt->awake), ktime_to_ms(intel_gt_get_awake_time(gt))); seq_printf(m, "Boosts outstanding? %d\n", atomic_read(&rps->num_waiters)); diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 82713264b96c..a6ae213c7d89 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -5,6 +5,7 @@ #include #include +#include #include "display/intel_display.h" #include "display/intel_overlay.h" @@ -137,7 +138,7 @@ void __i915_request_reset(struct i915_request *rq, bool guilty) { bool banned = false; - RQ_TRACE(rq, "guilty? %s\n", yesno(guilty)); + RQ_TRACE(rq, "guilty? %s\n", str_yes_no(guilty)); GEM_BUG_ON(__i915_request_is_complete(rq)); rcu_read_lock(); /* protect the GEM context */ diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index fd95449ed46d..f691b7614437 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -3,6 +3,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include #include "i915_drv.h" @@ -772,7 +774,8 @@ static void gen6_rps_set_thresholds(struct intel_rps *rps, u8 val) void intel_rps_mark_interactive(struct intel_rps *rps, bool interactive) { - GT_TRACE(rps_to_gt(rps), "mark interactive: %s\n", yesno(interactive)); + GT_TRACE(rps_to_gt(rps), "mark interactive: %s\n", + str_yes_no(interactive)); mutex_lock(&rps->power.mutex); if (interactive) { @@ -1279,7 +1282,8 @@ static bool chv_rps_enable(struct intel_rps *rps) drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, "GPLL not enabled\n"); - drm_dbg(&i915->drm, "GPLL enabled? %s\n", yesno(val & GPLLENABLE)); + drm_dbg(&i915->drm, "GPLL enabled? %s\n", + str_yes_no(val & GPLLENABLE)); drm_dbg(&i915->drm, "GPU status: 0x%08x\n", val); return rps_reset(rps); @@ -1380,7 +1384,8 @@ static bool vlv_rps_enable(struct intel_rps *rps) drm_WARN_ONCE(&i915->drm, (val & GPLLENABLE) == 0, "GPLL not enabled\n"); - drm_dbg(&i915->drm, "GPLL enabled? %s\n", yesno(val & GPLLENABLE)); + drm_dbg(&i915->drm, "GPLL enabled? %s\n", + str_yes_no(val & GPLLENABLE)); drm_dbg(&i915->drm, "GPU status: 0x%08x\n", val); return rps_reset(rps); @@ -1772,7 +1777,7 @@ static void rps_work(struct work_struct *work) GT_TRACE(gt, "pm_iir:%x, client_boost:%s, last:%d, cur:%x, min:%x, max:%x\n", - pm_iir, yesno(client_boost), + pm_iir, str_yes_no(client_boost), adj, new_freq, min, max); if (client_boost && new_freq < rps->boost_freq) { diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c index 29118c652811..4ae8356dcc2a 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.c +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c @@ -3,6 +3,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include "i915_drv.h" #include "intel_engine_regs.h" #include "intel_gt_regs.h" @@ -700,10 +702,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p) drm_printf(p, "EU total: %u\n", sseu->eu_total); drm_printf(p, "EU per subslice: %u\n", sseu->eu_per_subslice); drm_printf(p, "has slice power gating: %s\n", - yesno(sseu->has_slice_pg)); + str_yes_no(sseu->has_slice_pg)); drm_printf(p, "has subslice power gating: %s\n", - yesno(sseu->has_subslice_pg)); - drm_printf(p, "has EU power gating: %s\n", yesno(sseu->has_eu_pg)); + str_yes_no(sseu->has_subslice_pg)); + drm_printf(p, "has EU power gating: %s\n", + str_yes_no(sseu->has_eu_pg)); } void intel_sseu_print_topology(const struct sseu_dev_info *sseu, diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c index 903626f106ea..a9d5bc49f361 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c @@ -4,6 +4,8 @@ * Copyright © 2020 Intel Corporation */ +#include + #include "i915_drv.h" #include "intel_gt_debugfs.h" #include "intel_gt_regs.h" @@ -226,16 +228,16 @@ static void i915_print_sseu_info(struct seq_file *m, if (!is_available_info) return; - seq_printf(m, " Has Pooled EU: %s\n", yesno(has_pooled_eu)); + seq_printf(m, " Has Pooled EU: %s\n", str_yes_no(has_pooled_eu)); if (has_pooled_eu) seq_printf(m, " Min EU in pool: %u\n", sseu->min_eu_in_pool); seq_printf(m, " Has Slice Power Gating: %s\n", - yesno(sseu->has_slice_pg)); + str_yes_no(sseu->has_slice_pg)); seq_printf(m, " Has Subslice Power Gating: %s\n", - yesno(sseu->has_subslice_pg)); + str_yes_no(sseu->has_subslice_pg)); seq_printf(m, " Has EU Power Gating: %s\n", - yesno(sseu->has_eu_pg)); + str_yes_no(sseu->has_eu_pg)); } /* diff --git a/drivers/gpu/drm/i915/gt/selftest_timeline.c b/drivers/gpu/drm/i915/gt/selftest_timeline.c index 0410c402f2a3..522d0190509c 100644 --- a/drivers/gpu/drm/i915/gt/selftest_timeline.c +++ b/drivers/gpu/drm/i915/gt/selftest_timeline.c @@ -4,6 +4,7 @@ */ #include +#include #include "intel_context.h" #include "intel_engine_heartbeat.h" @@ -209,7 +210,7 @@ static int __igt_sync(struct intel_timeline *tl, if (__intel_timeline_sync_is_later(tl, ctx, p->seqno) != p->expected) { pr_err("%s: %s(ctx=%llu, seqno=%u) expected passed %s but failed\n", - name, p->name, ctx, p->seqno, yesno(p->expected)); + name, p->name, ctx, p->seqno, str_yes_no(p->expected)); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index b53f61f3101f..8a99c2e624c2 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -4,6 +4,7 @@ */ #include +#include #include "gt/intel_gt.h" #include "i915_drv.h" @@ -477,7 +478,7 @@ int intel_guc_log_create(struct intel_guc_log *log) log->level = __get_default_log_level(log); DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n", log->level, enableddisabled(log->level), - yesno(GUC_LOG_LEVEL_IS_VERBOSE(log->level)), + str_yes_no(GUC_LOG_LEVEL_IS_VERBOSE(log->level)), GUC_LOG_LEVEL_TO_VERBOSITY(log->level)); return 0; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c index b3d28b003b73..766744602d75 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_slpc.c @@ -4,6 +4,7 @@ */ #include +#include #include "i915_drv.h" #include "i915_reg.h" @@ -718,7 +719,7 @@ int intel_guc_slpc_print_info(struct intel_guc_slpc *slpc, struct drm_printer *p drm_printf(p, "\tSLPC state: %s\n", slpc_get_state_string(slpc)); drm_printf(p, "\tGTPERF task active: %s\n", - yesno(slpc_tasks->status & SLPC_GTPERF_TASK_ENABLED)); + str_yes_no(slpc_tasks->status & SLPC_GTPERF_TASK_ENABLED)); drm_printf(p, "\tMax freq: %u MHz\n", slpc_decode_max_freq(slpc)); drm_printf(p, "\tMin freq: %u MHz\n", diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index da199aa6989f..8e756d4c2c16 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -3,6 +3,8 @@ * Copyright © 2016-2019 Intel Corporation */ +#include + #include "gt/intel_gt.h" #include "gt/intel_reset.h" #include "intel_guc.h" @@ -78,10 +80,10 @@ static void __confirm_options(struct intel_uc *uc) drm_dbg(&i915->drm, "enable_guc=%d (guc:%s submission:%s huc:%s slpc:%s)\n", i915->params.enable_guc, - yesno(intel_uc_wants_guc(uc)), - yesno(intel_uc_wants_guc_submission(uc)), - yesno(intel_uc_wants_huc(uc)), - yesno(intel_uc_wants_guc_slpc(uc))); + str_yes_no(intel_uc_wants_guc(uc)), + str_yes_no(intel_uc_wants_guc_submission(uc)), + str_yes_no(intel_uc_wants_huc(uc)), + str_yes_no(intel_uc_wants_guc_slpc(uc))); if (i915->params.enable_guc == 0) { GEM_BUG_ON(intel_uc_wants_guc(uc)); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c index c2f7924295e7..284d6fbc2d08 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_debugfs.c @@ -4,6 +4,8 @@ */ #include +#include + #include #include "gt/intel_gt_debugfs.h" @@ -18,17 +20,17 @@ static int uc_usage_show(struct seq_file *m, void *data) struct drm_printer p = drm_seq_file_printer(m); drm_printf(&p, "[guc] supported:%s wanted:%s used:%s\n", - yesno(intel_uc_supports_guc(uc)), - yesno(intel_uc_wants_guc(uc)), - yesno(intel_uc_uses_guc(uc))); + str_yes_no(intel_uc_supports_guc(uc)), + str_yes_no(intel_uc_wants_guc(uc)), + str_yes_no(intel_uc_uses_guc(uc))); drm_printf(&p, "[huc] supported:%s wanted:%s used:%s\n", - yesno(intel_uc_supports_huc(uc)), - yesno(intel_uc_wants_huc(uc)), - yesno(intel_uc_uses_huc(uc))); + str_yes_no(intel_uc_supports_huc(uc)), + str_yes_no(intel_uc_wants_huc(uc)), + str_yes_no(intel_uc_uses_huc(uc))); drm_printf(&p, "[submission] supported:%s wanted:%s used:%s\n", - yesno(intel_uc_supports_guc_submission(uc)), - yesno(intel_uc_wants_guc_submission(uc)), - yesno(intel_uc_uses_guc_submission(uc))); + str_yes_no(intel_uc_supports_guc_submission(uc)), + str_yes_no(intel_uc_wants_guc_submission(uc)), + str_yes_no(intel_uc_uses_guc_submission(uc))); return 0; } diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 946bbe57bfe5..2323f489150f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -28,6 +28,7 @@ #include #include +#include #include @@ -455,9 +456,11 @@ static int i915_rps_boost_info(struct seq_file *m, void *data) struct drm_i915_private *dev_priv = node_to_i915(m->private); struct intel_rps *rps = &to_gt(dev_priv)->rps; - seq_printf(m, "RPS enabled? %s\n", yesno(intel_rps_is_enabled(rps))); - seq_printf(m, "RPS active? %s\n", yesno(intel_rps_is_active(rps))); - seq_printf(m, "GPU busy? %s\n", yesno(to_gt(dev_priv)->awake)); + seq_printf(m, "RPS enabled? %s\n", + str_yes_no(intel_rps_is_enabled(rps))); + seq_printf(m, "RPS active? %s\n", + str_yes_no(intel_rps_is_active(rps))); + seq_printf(m, "GPU busy? %s\n", str_yes_no(to_gt(dev_priv)->awake)); seq_printf(m, "Boosts outstanding? %d\n", atomic_read(&rps->num_waiters)); seq_printf(m, "Interactive? %d\n", READ_ONCE(rps->power.interactive)); @@ -490,9 +493,9 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused) seq_printf(m, "Runtime power status: %s\n", enableddisabled(!dev_priv->power_domains.init_wakeref)); - seq_printf(m, "GPU idle: %s\n", yesno(!to_gt(dev_priv)->awake)); + seq_printf(m, "GPU idle: %s\n", str_yes_no(!to_gt(dev_priv)->awake)); seq_printf(m, "IRQs disabled: %s\n", - yesno(!intel_irqs_enabled(dev_priv))); + str_yes_no(!intel_irqs_enabled(dev_priv))); #ifdef CONFIG_PM seq_printf(m, "Usage count: %d\n", atomic_read(&dev_priv->drm.dev->power.usage_count)); @@ -522,7 +525,7 @@ static int i915_engine_info(struct seq_file *m, void *unused) wakeref = intel_runtime_pm_get(&i915->runtime_pm); seq_printf(m, "GT awake? %s [%d], %llums\n", - yesno(to_gt(i915)->awake), + str_yes_no(to_gt(i915)->awake), atomic_read(&to_gt(i915)->wakeref.count), ktime_to_ms(intel_gt_get_awake_time(to_gt(i915)))); seq_printf(m, "CS timestamp frequency: %u Hz, %d ns\n", diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 1d042551619e..4967e79806f8 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -719,7 +720,7 @@ static void err_print_gt(struct drm_i915_error_state_buf *m, const struct intel_engine_coredump *ee; int i; - err_printf(m, "GT awake: %s\n", yesno(gt->awake)); + err_printf(m, "GT awake: %s\n", str_yes_no(gt->awake)); err_printf(m, "EIR: 0x%08x\n", gt->eir); err_printf(m, "IER: 0x%08x\n", gt->ier); for (i = 0; i < gt->ngtier; i++) @@ -827,14 +828,14 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, struct intel_dmc *dmc = &m->i915->dmc; err_printf(m, "DMC loaded: %s\n", - yesno(intel_dmc_has_payload(m->i915) != 0)); + str_yes_no(intel_dmc_has_payload(m->i915) != 0)); err_printf(m, "DMC fw version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version), DMC_VERSION_MINOR(dmc->version)); } - err_printf(m, "RPM wakelock: %s\n", yesno(error->wakelock)); - err_printf(m, "PM suspended: %s\n", yesno(error->suspended)); + err_printf(m, "RPM wakelock: %s\n", str_yes_no(error->wakelock)); + err_printf(m, "PM suspended: %s\n", str_yes_no(error->suspended)); if (error->gt) err_print_gt(m, error->gt); diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index 525ae832aa9a..a28b10bc20ad 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -22,6 +22,8 @@ * IN THE SOFTWARE. */ +#include + #include #include "i915_params.h" @@ -211,7 +213,8 @@ static __always_inline void _print_param(struct drm_printer *p, const void *x) { if (!__builtin_strcmp(type, "bool")) - drm_printf(p, "i915.%s=%s\n", name, yesno(*(const bool *)x)); + drm_printf(p, "i915.%s=%s\n", name, + str_yes_no(*(const bool *)x)); else if (!__builtin_strcmp(type, "int")) drm_printf(p, "i915.%s=%d\n", name, *(const int *)x); else if (!__builtin_strcmp(type, "unsigned int")) diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index bfafd0afd117..c62b64012369 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -399,11 +399,6 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) #define MBps(x) KBps(1000 * (x)) #define GBps(x) ((u64)1000 * MBps((x))) -static inline const char *yesno(bool v) -{ - return v ? "yes" : "no"; -} - static inline const char *onoff(bool v) { return v ? "on" : "off"; diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 94da5aa37391..88f29ac11ddd 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -22,6 +22,8 @@ * */ +#include + #include #include @@ -110,11 +112,11 @@ void intel_device_info_print_static(const struct intel_device_info *info, drm_printf(p, "ppgtt-type: %d\n", info->ppgtt_type); drm_printf(p, "dma_mask_size: %u\n", info->dma_mask_size); -#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->name)) +#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->name)) DEV_INFO_FOR_EACH_FLAG(PRINT_FLAG); #undef PRINT_FLAG -#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, yesno(info->display.name)) +#define PRINT_FLAG(name) drm_printf(p, "%s: %s\n", #name, str_yes_no(info->display.name)) DEV_INFO_DISPLAY_FOR_EACH_FLAG(PRINT_FLAG); #undef PRINT_FLAG } @@ -400,6 +402,6 @@ void intel_driver_caps_print(const struct intel_driver_caps *caps, struct drm_printer *p) { drm_printf(p, "Has logical contexts? %s\n", - yesno(caps->has_logical_contexts)); + str_yes_no(caps->has_logical_contexts)); drm_printf(p, "scheduler: %x\n", caps->scheduler); } diff --git a/drivers/gpu/drm/i915/intel_dram.c b/drivers/gpu/drm/i915/intel_dram.c index 174c95c3e10f..2b9e7833da96 100644 --- a/drivers/gpu/drm/i915/intel_dram.c +++ b/drivers/gpu/drm/i915/intel_dram.c @@ -3,6 +3,8 @@ * Copyright © 2020 Intel Corporation */ +#include + #include "i915_drv.h" #include "i915_reg.h" #include "intel_dram.h" @@ -136,7 +138,7 @@ skl_dram_get_dimm_info(struct drm_i915_private *i915, drm_dbg_kms(&i915->drm, "CH%u DIMM %c size: %u Gb, width: X%u, ranks: %u, 16Gb DIMMs: %s\n", channel, dimm_name, dimm->size, dimm->width, dimm->ranks, - yesno(skl_is_16gb_dimm(dimm))); + str_yes_no(skl_is_16gb_dimm(dimm))); } static int @@ -165,7 +167,7 @@ skl_dram_get_channel_info(struct drm_i915_private *i915, skl_is_16gb_dimm(&ch->dimm_s); drm_dbg_kms(&i915->drm, "CH%u ranks: %u, 16Gb DIMMs: %s\n", - channel, ch->ranks, yesno(ch->is_16gb_dimm)); + channel, ch->ranks, str_yes_no(ch->is_16gb_dimm)); return 0; } @@ -214,7 +216,7 @@ skl_dram_get_channels_info(struct drm_i915_private *i915) dram_info->symmetric_memory = intel_is_dram_symmetric(&ch0, &ch1); drm_dbg_kms(&i915->drm, "Memory configuration is symmetric? %s\n", - yesno(dram_info->symmetric_memory)); + str_yes_no(dram_info->symmetric_memory)); return 0; } @@ -492,7 +494,7 @@ void intel_dram_detect(struct drm_i915_private *i915) drm_dbg_kms(&i915->drm, "DRAM channels: %u\n", dram_info->num_channels); drm_dbg_kms(&i915->drm, "Watermark level 0 adjustment needed: %s\n", - yesno(dram_info->wm_lv_0_adjust_needed)); + str_yes_no(dram_info->wm_lv_0_adjust_needed)); } static u32 gen9_edram_size_mb(struct drm_i915_private *i915, u32 cap) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index b9d711246f1e..11a60b967d1b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -26,6 +26,7 @@ */ #include +#include #include #include @@ -6191,8 +6192,8 @@ skl_compute_ddb(struct intel_atomic_state *state) old_dbuf_state->enabled_slices, new_dbuf_state->enabled_slices, INTEL_INFO(dev_priv)->dbuf.slice_mask, - yesno(old_dbuf_state->joined_mbus), - yesno(new_dbuf_state->joined_mbus)); + str_yes_no(old_dbuf_state->joined_mbus), + str_yes_no(new_dbuf_state->joined_mbus)); } for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { @@ -6694,7 +6695,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) crtc->base.base.id, crtc->base.name, dbuf_state->slices[pipe], dbuf_state->ddb[pipe].start, dbuf_state->ddb[pipe].end, dbuf_state->active_pipes, - yesno(dbuf_state->joined_mbus)); + str_yes_no(dbuf_state->joined_mbus)); } dbuf_state->enabled_slices = dev_priv->dbuf.enabled_slices; @@ -7005,7 +7006,8 @@ void g4x_wm_get_hw_state(struct drm_i915_private *dev_priv) "Initial HPLL watermarks: plane=%d, SR cursor=%d fbc=%d\n", wm->hpll.plane, wm->hpll.cursor, wm->hpll.fbc); drm_dbg_kms(&dev_priv->drm, "Initial SR=%s HPLL=%s FBC=%s\n", - yesno(wm->cxsr), yesno(wm->hpll_en), yesno(wm->fbc_en)); + str_yes_no(wm->cxsr), str_yes_no(wm->hpll_en), + str_yes_no(wm->fbc_en)); } void g4x_wm_sanitize(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c b/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c index 10e1e45471f1..c9da1015eb42 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_debugfs.c @@ -4,6 +4,8 @@ */ #include +#include + #include #include "gt/intel_gt_debugfs.h" @@ -22,7 +24,7 @@ static int pxp_info_show(struct seq_file *m, void *data) return 0; } - drm_printf(&p, "active: %s\n", yesno(intel_pxp_is_active(pxp))); + drm_printf(&p, "active: %s\n", str_yes_no(intel_pxp_is_active(pxp))); drm_printf(&p, "instance counter: %u\n", pxp->key_instance); return 0; diff --git a/drivers/gpu/drm/i915/selftests/i915_active.c b/drivers/gpu/drm/i915/selftests/i915_active.c index 2dac9be1de58..b61fe850e924 100644 --- a/drivers/gpu/drm/i915/selftests/i915_active.c +++ b/drivers/gpu/drm/i915/selftests/i915_active.c @@ -5,6 +5,7 @@ */ #include +#include #include "gem/i915_gem_pm.h" #include "gt/intel_gt.h" @@ -280,7 +281,7 @@ void i915_active_print(struct i915_active *ref, struct drm_printer *m) drm_printf(m, "active %ps:%ps\n", ref->active, ref->retire); drm_printf(m, "\tcount: %d\n", atomic_read(&ref->count)); drm_printf(m, "\tpreallocated barriers? %s\n", - yesno(!llist_empty(&ref->preallocated_barriers))); + str_yes_no(!llist_empty(&ref->preallocated_barriers))); if (i915_active_acquire_if_busy(ref)) { struct active_node *it, *n; From 707c3a7d99b1a6c483ac773a6327972144152c92 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 25 Feb 2022 15:46:29 -0800 Subject: [PATCH 00047/11454] drm/i915: Use str_enable_disable() Remove the local enabledisable() implementation and adopt the str_enable_disable() from linux/string_helpers.h. Signed-off-by: Lucas De Marchi Acked-by: Daniel Vetter Acked-by: Jani Nikula Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220225234631.3725943-2-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 4 +++- drivers/gpu/drm/i915/display/intel_display_power.c | 4 +++- drivers/gpu/drm/i915/display/intel_dp.c | 8 ++++---- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 3 ++- drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c | 4 +++- drivers/gpu/drm/i915/i915_utils.h | 5 ----- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 1cd394b0585e..3e6d86a54850 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -25,6 +25,8 @@ * */ +#include + #include #include @@ -2152,7 +2154,7 @@ static void intel_dp_sink_set_msa_timing_par_ignore_state(struct intel_dp *intel enable ? DP_MSA_TIMING_PAR_IGNORE_EN : 0) <= 0) drm_dbg_kms(&i915->drm, "Failed to %s MSA_TIMING_PAR_IGNORE in the sink\n", - enabledisable(enable)); + str_enable_disable(enable)); } static void intel_dp_sink_set_fec_ready(struct intel_dp *intel_dp, diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index e8e8ce13aa96..3dc859032bac 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -3,6 +3,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include "i915_drv.h" #include "i915_irq.h" #include "intel_cdclk.h" @@ -4996,7 +4998,7 @@ static void gen9_dbuf_slice_set(struct drm_i915_private *dev_priv, state = intel_de_read(dev_priv, reg) & DBUF_POWER_STATE; drm_WARN(&dev_priv->drm, enable != state, "DBuf slice %d power %s timeout!\n", - slice, enabledisable(enable)); + slice, str_enable_disable(enable)); } void gen9_dbuf_slices_update(struct drm_i915_private *dev_priv, diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6ffa5b28b976..d6ef33096bb6 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1977,7 +1977,7 @@ void intel_dp_sink_set_decompression_state(struct intel_dp *intel_dp, if (ret < 0) drm_dbg_kms(&i915->drm, "Failed to %s sink decompression state\n", - enabledisable(enable)); + str_enable_disable(enable)); } static void @@ -2453,7 +2453,7 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, if (drm_dp_dpcd_writeb(&intel_dp->aux, DP_PROTOCOL_CONVERTER_CONTROL_0, tmp) != 1) drm_dbg_kms(&i915->drm, "Failed to %s protocol converter HDMI mode\n", - enabledisable(intel_dp->has_hdmi_sink)); + str_enable_disable(intel_dp->has_hdmi_sink)); tmp = crtc_state->output_format == INTEL_OUTPUT_FORMAT_YCBCR444 && intel_dp->dfp.ycbcr_444_to_420 ? DP_CONVERSION_TO_YCBCR420_ENABLE : 0; @@ -2462,7 +2462,7 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, DP_PROTOCOL_CONVERTER_CONTROL_1, tmp) != 1) drm_dbg_kms(&i915->drm, "Failed to %s protocol converter YCbCr 4:2:0 conversion mode\n", - enabledisable(intel_dp->dfp.ycbcr_444_to_420)); + str_enable_disable(intel_dp->dfp.ycbcr_444_to_420)); tmp = 0; if (intel_dp->dfp.rgb_to_ycbcr) { @@ -2500,7 +2500,7 @@ void intel_dp_configure_protocol_converter(struct intel_dp *intel_dp, if (drm_dp_pcon_convert_rgb_to_ycbcr(&intel_dp->aux, tmp) < 0) drm_dbg_kms(&i915->drm, "Failed to %s protocol converter RGB->YCbCr conversion mode\n", - enabledisable(tmp)); + str_enable_disable(tmp)); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index 2f7fc87a78e1..ba5c46f61d14 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include "i915_drv.h" @@ -170,7 +171,7 @@ static int ct_control_enable(struct intel_guc_ct *ct, bool enable) GUC_CTB_CONTROL_ENABLE : GUC_CTB_CONTROL_DISABLE); if (unlikely(err)) CT_PROBE_ERROR(ct, "Failed to control/%s CTB (%pe)\n", - enabledisable(enable), ERR_PTR(err)); + str_enable_disable(enable), ERR_PTR(err)); return err; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c index fc805d466d99..f8fc90ea71e7 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c @@ -3,6 +3,8 @@ * Copyright © 2021 Intel Corporation */ +#include + #include "intel_guc_rc.h" #include "gt/intel_gt.h" #include "i915_drv.h" @@ -59,7 +61,7 @@ static int __guc_rc_control(struct intel_guc *guc, bool enable) ret = guc_action_control_gucrc(guc, enable); if (ret) { drm_err(drm, "Failed to %s GuC RC (%pe)\n", - enabledisable(enable), ERR_PTR(ret)); + str_enable_disable(enable), ERR_PTR(ret)); return ret; } diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index c62b64012369..06aac2be49ee 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -404,11 +404,6 @@ static inline const char *onoff(bool v) return v ? "on" : "off"; } -static inline const char *enabledisable(bool v) -{ - return v ? "enable" : "disable"; -} - static inline const char *enableddisabled(bool v) { return v ? "enabled" : "disabled"; From ff9fbe7ce1c13dc472ac4a5cb22064a37aeca69a Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 25 Feb 2022 15:46:30 -0800 Subject: [PATCH 00048/11454] drm/i915: Use str_enabled_disabled() Remove the local enableddisabled() implementation and adopt the str_enabled_disabled() from linux/string_helpers.h. Signed-off-by: Lucas De Marchi Acked-by: Daniel Vetter Acked-by: Jani Nikula Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220225234631.3725943-3-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/intel_backlight.c | 3 ++- drivers/gpu/drm/i915/display/intel_display.c | 16 ++++++++-------- .../gpu/drm/i915/display/intel_display_debugfs.c | 8 ++++---- drivers/gpu/drm/i915/display/intel_dsi_vbt.c | 7 ++++--- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 3 ++- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_uc.c | 4 ++-- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_driver.c | 4 +++- drivers/gpu/drm/i915/i915_utils.h | 6 +----- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 14 files changed, 33 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_backlight.c b/drivers/gpu/drm/i915/display/intel_backlight.c index 98f7ea44042f..c8e1fc53a881 100644 --- a/drivers/gpu/drm/i915/display/intel_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_backlight.c @@ -5,6 +5,7 @@ #include #include +#include #include "intel_backlight.h" #include "intel_connector.h" @@ -1633,7 +1634,7 @@ int intel_backlight_setup(struct intel_connector *connector, enum pipe pipe) drm_dbg_kms(&dev_priv->drm, "Connector %s backlight initialized, %s, brightness %u/%u\n", connector->base.name, - enableddisabled(panel->backlight.enabled), + str_enabled_disabled(panel->backlight.enabled), panel->backlight.level, panel->backlight.max); return 0; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 938354dc6f16..2283c7bad2cd 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2981,8 +2981,8 @@ static void intel_panel_sanitize_ssc(struct drm_i915_private *dev_priv) if (dev_priv->vbt.lvds_use_ssc != bios_lvds_use_ssc) { drm_dbg_kms(&dev_priv->drm, "SSC %s by BIOS, overriding VBT which says %s\n", - enableddisabled(bios_lvds_use_ssc), - enableddisabled(dev_priv->vbt.lvds_use_ssc)); + str_enabled_disabled(bios_lvds_use_ssc), + str_enabled_disabled(dev_priv->vbt.lvds_use_ssc)); dev_priv->vbt.lvds_use_ssc = bios_lvds_use_ssc; } } @@ -5324,7 +5324,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, pipe_config->bigjoiner_pipes); drm_dbg_kms(&dev_priv->drm, "splitter: %s, link count %d, overlap %d\n", - enableddisabled(pipe_config->splitter.enable), + str_enabled_disabled(pipe_config->splitter.enable), pipe_config->splitter.link_count, pipe_config->splitter.pixel_overlap); @@ -5412,7 +5412,7 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, drm_dbg_kms(&dev_priv->drm, "pch pfit: " DRM_RECT_FMT ", %s, force thru: %s\n", DRM_RECT_ARG(&pipe_config->pch_pfit.dst), - enableddisabled(pipe_config->pch_pfit.enabled), + str_enabled_disabled(pipe_config->pch_pfit.enabled), str_yes_no(pipe_config->pch_pfit.force_thru)); drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i\n", @@ -10068,7 +10068,7 @@ static void readout_plane_state(struct drm_i915_private *dev_priv) drm_dbg_kms(&dev_priv->drm, "[PLANE:%d:%s] hw state readout: %s, pipe %c\n", plane->base.base.id, plane->base.name, - enableddisabled(visible), pipe_name(pipe)); + str_enabled_disabled(visible), pipe_name(pipe)); } for_each_intel_crtc(&dev_priv->drm, crtc) { @@ -10114,7 +10114,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] hw state readout: %s\n", crtc->base.base.id, crtc->base.name, - enableddisabled(crtc_state->hw.active)); + str_enabled_disabled(crtc_state->hw.active)); } cdclk_state->active_pipes = dbuf_state->active_pipes = active_pipes; @@ -10158,7 +10158,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) drm_dbg_kms(&dev_priv->drm, "[ENCODER:%d:%s] hw state readout: %s, pipe %c\n", encoder->base.base.id, encoder->base.name, - enableddisabled(encoder->base.crtc), + str_enabled_disabled(encoder->base.crtc), pipe_name(pipe)); } @@ -10196,7 +10196,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] hw state readout: %s\n", connector->base.base.id, connector->base.name, - enableddisabled(connector->base.encoder)); + str_enabled_disabled(connector->base.encoder)); } drm_connector_list_iter_end(&conn_iter); diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index c7717472cf9d..ac141c911685 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -95,7 +95,7 @@ static int i915_sr_status(struct seq_file *m, void *unused) intel_display_power_put(dev_priv, POWER_DOMAIN_INIT, wakeref); - seq_printf(m, "self-refresh: %s\n", enableddisabled(sr_enabled)); + seq_printf(m, "self-refresh: %s\n", str_enabled_disabled(sr_enabled)); return 0; } @@ -297,7 +297,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) enabled = val & EDP_PSR_ENABLE; } seq_printf(m, "Source PSR ctl: %s [0x%08x]\n", - enableddisabled(enabled), val); + str_enabled_disabled(enabled), val); psr_source_status(intel_dp, m); seq_printf(m, "Busy frontbuffer bits: 0x%08x\n", psr->busy_frontbuffer_bits); @@ -344,7 +344,7 @@ static int intel_psr_status(struct seq_file *m, struct intel_dp *intel_dp) } seq_printf(m, "PSR2 selective fetch: %s\n", - enableddisabled(psr->psr2_sel_fetch_enabled)); + str_enabled_disabled(psr->psr2_sel_fetch_enabled)); } unlock: @@ -1269,7 +1269,7 @@ static int i915_lpsp_status(struct seq_file *m, void *unused) return 0; } - seq_printf(m, "LPSP: %s\n", enableddisabled(lpsp_enabled)); + seq_printf(m, "LPSP: %s\n", str_enabled_disabled(lpsp_enabled)); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c index 6b4a27372c82..f370e9c4350d 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi_vbt.c +++ b/drivers/gpu/drm/i915/display/intel_dsi_vbt.c @@ -30,6 +30,7 @@ #include #include #include +#include #include @@ -686,9 +687,9 @@ void intel_dsi_log_params(struct intel_dsi *intel_dsi) intel_dsi->burst_mode_ratio); drm_dbg_kms(&i915->drm, "Reset timer %d\n", intel_dsi->rst_timer_val); drm_dbg_kms(&i915->drm, "Eot %s\n", - enableddisabled(intel_dsi->eotp_pkt)); + str_enabled_disabled(intel_dsi->eotp_pkt)); drm_dbg_kms(&i915->drm, "Clockstop %s\n", - enableddisabled(!intel_dsi->clock_stop)); + str_enabled_disabled(!intel_dsi->clock_stop)); drm_dbg_kms(&i915->drm, "Mode %s\n", intel_dsi->operation_mode ? "command" : "video"); if (intel_dsi->dual_link == DSI_DUAL_LINK_FRONT_BACK) @@ -715,7 +716,7 @@ void intel_dsi_log_params(struct intel_dsi *intel_dsi) drm_dbg_kms(&i915->drm, "HS to LP Clock Count 0x%x\n", intel_dsi->clk_hs_to_lp_count); drm_dbg_kms(&i915->drm, "BTA %s\n", - enableddisabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA))); + str_enabled_disabled(!(intel_dsi->video_frmt_cfg_bits & DISABLE_VIDEO_BTA))); } bool intel_dsi_vbt_init(struct intel_dsi *intel_dsi, u16 panel_id) diff --git a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c index 209cf265bf74..9dc9dccf7b09 100644 --- a/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/gt/intel_breadcrumbs.c @@ -4,6 +4,7 @@ */ #include +#include #include #include @@ -512,7 +513,7 @@ void intel_engine_print_breadcrumbs(struct intel_engine_cs *engine, if (!b) return; - drm_printf(p, "IRQ: %s\n", enableddisabled(b->irq_armed)); + drm_printf(p, "IRQ: %s\n", str_enabled_disabled(b->irq_armed)); if (!list_empty(&b->signalers)) print_signals(b, p); } diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 0afb0bb8cf95..501e7b37bc26 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1633,7 +1633,7 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine, drm_printf(m, "\tExeclist tasklet queued? %s (%s), preempt? %s, timeslice? %s\n", str_yes_no(test_bit(TASKLET_STATE_SCHED, &engine->sched_engine->tasklet.state)), - enableddisabled(!atomic_read(&engine->sched_engine->tasklet.count)), + str_enabled_disabled(!atomic_read(&engine->sched_engine->tasklet.count)), repr_timer(&engine->execlists.preempt), repr_timer(&engine->execlists.timer)); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c index ba5c46f61d14..f01325cd1b62 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ct.c @@ -1203,7 +1203,7 @@ void intel_guc_ct_event_handler(struct intel_guc_ct *ct) void intel_guc_ct_print_info(struct intel_guc_ct *ct, struct drm_printer *p) { - drm_printf(p, "CT %s\n", enableddisabled(ct->enabled)); + drm_printf(p, "CT %s\n", str_enabled_disabled(ct->enabled)); if (!ct->enabled) return; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index 8a99c2e624c2..a24dc6441872 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -477,7 +477,7 @@ int intel_guc_log_create(struct intel_guc_log *log) log->level = __get_default_log_level(log); DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n", - log->level, enableddisabled(log->level), + log->level, str_enabled_disabled(log->level), str_yes_no(GUC_LOG_LEVEL_IS_VERBOSE(log->level)), GUC_LOG_LEVEL_TO_VERBOSITY(log->level)); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c index f8fc90ea71e7..e00661fb0853 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_rc.c @@ -66,7 +66,7 @@ static int __guc_rc_control(struct intel_guc *guc, bool enable) } drm_info(>->i915->drm, "GuC RC: %s\n", - enableddisabled(enable)); + str_enabled_disabled(enable)); return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc.c b/drivers/gpu/drm/i915/gt/uc/intel_uc.c index 8e756d4c2c16..8c9ef690ac9d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc.c @@ -524,9 +524,9 @@ static int __uc_init_hw(struct intel_uc *uc) } drm_info(&i915->drm, "GuC submission %s\n", - enableddisabled(intel_uc_uses_guc_submission(uc))); + str_enabled_disabled(intel_uc_uses_guc_submission(uc))); drm_info(&i915->drm, "GuC SLPC %s\n", - enableddisabled(intel_uc_uses_guc_slpc(uc))); + str_enabled_disabled(intel_uc_uses_guc_slpc(uc))); return 0; diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 2323f489150f..747fe9f41e1f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -491,7 +491,7 @@ static int i915_runtime_pm_status(struct seq_file *m, void *unused) seq_puts(m, "Runtime power management not supported\n"); seq_printf(m, "Runtime power status: %s\n", - enableddisabled(!dev_priv->power_domains.init_wakeref)); + str_enabled_disabled(!dev_priv->power_domains.init_wakeref)); seq_printf(m, "GPU idle: %s\n", str_yes_no(!to_gt(dev_priv)->awake)); seq_printf(m, "IRQs disabled: %s\n", diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 1c67ff735f18..13e6530a3227 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -752,7 +753,8 @@ static void i915_driver_unregister(struct drm_i915_private *dev_priv) void i915_print_iommu_status(struct drm_i915_private *i915, struct drm_printer *p) { - drm_printf(p, "iommu: %s\n", enableddisabled(intel_vtd_active(i915))); + drm_printf(p, "iommu: %s\n", + str_enabled_disabled(intel_vtd_active(i915))); } static void i915_welcome_messages(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 06aac2be49ee..6d26920d0632 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -404,11 +405,6 @@ static inline const char *onoff(bool v) return v ? "on" : "off"; } -static inline const char *enableddisabled(bool v) -{ - return v ? "enabled" : "disabled"; -} - void add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint); static inline void __add_taint_for_CI(unsigned int taint) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 11a60b967d1b..97af7ce6b22b 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -419,8 +419,8 @@ static bool _intel_set_memory_cxsr(struct drm_i915_private *dev_priv, bool enabl trace_intel_memory_cxsr(dev_priv, was_enabled, enable); drm_dbg_kms(&dev_priv->drm, "memory self-refresh is %s (was %s)\n", - enableddisabled(enable), - enableddisabled(was_enabled)); + str_enabled_disabled(enable), + str_enabled_disabled(was_enabled)); return was_enabled; } From f79a568add12affc44152455fd7f7502aeea8e31 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Fri, 25 Feb 2022 15:46:31 -0800 Subject: [PATCH 00049/11454] drm/i915: Use str_on_off() Remove the local onoff() implementation and adopt the str_on_off() from linux/string_helpers.h. Signed-off-by: Lucas De Marchi Acked-by: Daniel Vetter Acked-by: Jani Nikula Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220225234631.3725943-4-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/display/g4x_dp.c | 6 ++++-- drivers/gpu/drm/i915/display/intel_display.c | 7 ++++--- drivers/gpu/drm/i915/display/intel_display_trace.h | 3 ++- drivers/gpu/drm/i915/display/intel_dpll.c | 3 ++- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 7 +++++-- drivers/gpu/drm/i915/display/intel_fdi.c | 8 +++++--- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 3 ++- drivers/gpu/drm/i915/gt/intel_rc6.c | 5 +++-- drivers/gpu/drm/i915/i915_utils.h | 5 ----- drivers/gpu/drm/i915/vlv_suspend.c | 3 ++- 10 files changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index f67bbaaad8e0..22345051e667 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -5,6 +5,8 @@ * DisplayPort support for G4x,ILK,SNB,IVB,VLV,CHV (HSW+ handled by the DDI code). */ +#include + #include "g4x_dp.h" #include "intel_audio.h" #include "intel_backlight.h" @@ -192,7 +194,7 @@ static void assert_dp_port(struct intel_dp *intel_dp, bool state) I915_STATE_WARN(cur_state != state, "[ENCODER:%d:%s] state assertion failure (expected %s, current %s)\n", dig_port->base.base.base.id, dig_port->base.base.name, - onoff(state), onoff(cur_state)); + str_on_off(state), str_on_off(cur_state)); } #define assert_dp_port_disabled(d) assert_dp_port((d), false) @@ -202,7 +204,7 @@ static void assert_edp_pll(struct drm_i915_private *dev_priv, bool state) I915_STATE_WARN(cur_state != state, "eDP PLL state assertion failure (expected %s, current %s)\n", - onoff(state), onoff(cur_state)); + str_on_off(state), str_on_off(cur_state)); } #define assert_edp_pll_enabled(d) assert_edp_pll((d), true) #define assert_edp_pll_disabled(d) assert_edp_pll((d), false) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2283c7bad2cd..6cae58f921a5 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -401,7 +401,7 @@ static void wait_for_pipe_scanline_moving(struct intel_crtc *crtc, bool state) if (wait_for(pipe_scanline_is_moving(dev_priv, pipe) == state, 100)) drm_err(&dev_priv->drm, "pipe %c scanline %s wait timed out\n", - pipe_name(pipe), onoff(state)); + pipe_name(pipe), str_on_off(state)); } static void intel_wait_for_pipe_scanline_stopped(struct intel_crtc *crtc) @@ -457,7 +457,7 @@ void assert_transcoder(struct drm_i915_private *dev_priv, I915_STATE_WARN(cur_state != state, "transcoder %s assertion failure (expected %s, current %s)\n", transcoder_name(cpu_transcoder), - onoff(state), onoff(cur_state)); + str_on_off(state), str_on_off(cur_state)); } static void assert_plane(struct intel_plane *plane, bool state) @@ -469,7 +469,8 @@ static void assert_plane(struct intel_plane *plane, bool state) I915_STATE_WARN(cur_state != state, "%s assertion failure (expected %s, current %s)\n", - plane->base.name, onoff(state), onoff(cur_state)); + plane->base.name, str_on_off(state), + str_on_off(cur_state)); } #define assert_plane_enabled(p) assert_plane(p, true) diff --git a/drivers/gpu/drm/i915/display/intel_display_trace.h b/drivers/gpu/drm/i915/display/intel_display_trace.h index dcdd242fffd9..2dd5a4b7f5d8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_trace.h +++ b/drivers/gpu/drm/i915/display/intel_display_trace.h @@ -9,6 +9,7 @@ #if !defined(__INTEL_DISPLAY_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) #define __INTEL_DISPLAY_TRACE_H__ +#include #include #include @@ -161,7 +162,7 @@ TRACE_EVENT(intel_memory_cxsr, ), TP_printk("%s->%s, pipe A: frame=%u, scanline=%u, pipe B: frame=%u, scanline=%u, pipe C: frame=%u, scanline=%u", - onoff(__entry->old), onoff(__entry->new), + str_on_off(__entry->old), str_on_off(__entry->new), __entry->frame[PIPE_A], __entry->scanline[PIPE_A], __entry->frame[PIPE_B], __entry->scanline[PIPE_B], __entry->frame[PIPE_C], __entry->scanline[PIPE_C]) diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 14f5ffe27d05..0ae37fdbf2a5 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -4,6 +4,7 @@ */ #include +#include #include "intel_crtc.h" #include "intel_de.h" @@ -1945,7 +1946,7 @@ static void assert_pll(struct drm_i915_private *dev_priv, cur_state = intel_de_read(dev_priv, DPLL(pipe)) & DPLL_VCO_ENABLE; I915_STATE_WARN(cur_state != state, "PLL state assertion failure (expected %s, current %s)\n", - onoff(state), onoff(cur_state)); + str_on_off(state), str_on_off(cur_state)); } void assert_pll_enabled(struct drm_i915_private *i915, enum pipe pipe) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 569903d47aea..f10eae7a75c6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -21,6 +21,8 @@ * DEALINGS IN THE SOFTWARE. */ +#include + #include "intel_de.h" #include "intel_display_types.h" #include "intel_dpio_phy.h" @@ -178,13 +180,14 @@ void assert_shared_dpll(struct drm_i915_private *dev_priv, struct intel_dpll_hw_state hw_state; if (drm_WARN(&dev_priv->drm, !pll, - "asserting DPLL %s with no DPLL\n", onoff(state))) + "asserting DPLL %s with no DPLL\n", str_on_off(state))) return; cur_state = intel_dpll_get_hw_state(dev_priv, pll, &hw_state); I915_STATE_WARN(cur_state != state, "%s assertion failure (expected %s, current %s)\n", - pll->info->name, onoff(state), onoff(cur_state)); + pll->info->name, str_on_off(state), + str_on_off(cur_state)); } static enum tc_port icl_pll_id_to_tc_port(enum intel_dpll_id id) diff --git a/drivers/gpu/drm/i915/display/intel_fdi.c b/drivers/gpu/drm/i915/display/intel_fdi.c index 4e4b43669b14..67d2484afbaa 100644 --- a/drivers/gpu/drm/i915/display/intel_fdi.c +++ b/drivers/gpu/drm/i915/display/intel_fdi.c @@ -3,6 +3,8 @@ * Copyright © 2020 Intel Corporation */ +#include + #include "intel_atomic.h" #include "intel_crtc.h" #include "intel_ddi.h" @@ -34,7 +36,7 @@ static void assert_fdi_tx(struct drm_i915_private *dev_priv, } I915_STATE_WARN(cur_state != state, "FDI TX state assertion failure (expected %s, current %s)\n", - onoff(state), onoff(cur_state)); + str_on_off(state), str_on_off(cur_state)); } void assert_fdi_tx_enabled(struct drm_i915_private *i915, enum pipe pipe) @@ -55,7 +57,7 @@ static void assert_fdi_rx(struct drm_i915_private *dev_priv, cur_state = intel_de_read(dev_priv, FDI_RX_CTL(pipe)) & FDI_RX_ENABLE; I915_STATE_WARN(cur_state != state, "FDI RX state assertion failure (expected %s, current %s)\n", - onoff(state), onoff(cur_state)); + str_on_off(state), str_on_off(cur_state)); } void assert_fdi_rx_enabled(struct drm_i915_private *i915, enum pipe pipe) @@ -93,7 +95,7 @@ static void assert_fdi_rx_pll(struct drm_i915_private *i915, cur_state = intel_de_read(i915, FDI_RX_CTL(pipe)) & FDI_RX_PLL_ENABLE; I915_STATE_WARN(cur_state != state, "FDI RX PLL assertion failure (expected %s, current %s)\n", - onoff(state), onoff(cur_state)); + str_on_off(state), str_on_off(cur_state)); } void assert_fdi_rx_pll_enabled(struct drm_i915_private *i915, enum pipe pipe) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index df880f44700a..1385b46aeb26 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -26,6 +26,7 @@ */ #include +#include #include "i915_drv.h" #include "intel_de.h" @@ -581,7 +582,7 @@ static void assert_dsi_pll(struct drm_i915_private *i915, bool state) I915_STATE_WARN(cur_state != state, "DSI PLL state assertion failure (expected %s, current %s)\n", - onoff(state), onoff(cur_state)); + str_on_off(state), str_on_off(cur_state)); } void assert_dsi_pll_enabled(struct drm_i915_private *i915) diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 6df359c534fe..63db136cbc27 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -4,6 +4,7 @@ */ #include +#include #include "i915_drv.h" #include "i915_reg.h" @@ -430,8 +431,8 @@ static bool bxt_check_bios_rc6_setup(struct intel_rc6 *rc6) rc_sw_target >>= RC_SW_TARGET_STATE_SHIFT; drm_dbg(&i915->drm, "BIOS enabled RC states: " "HW_CTRL %s HW_RC6 %s SW_TARGET_STATE %x\n", - onoff(rc_ctl & GEN6_RC_CTL_HW_ENABLE), - onoff(rc_ctl & GEN6_RC_CTL_RC6_ENABLE), + str_on_off(rc_ctl & GEN6_RC_CTL_HW_ENABLE), + str_on_off(rc_ctl & GEN6_RC_CTL_RC6_ENABLE), rc_sw_target); if (!(intel_uncore_read(uncore, RC6_LOCATION) & RC6_CTX_IN_DRAM)) { diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 6d26920d0632..3ff9611ff81c 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -400,11 +400,6 @@ wait_remaining_ms_from_jiffies(unsigned long timestamp_jiffies, int to_wait_ms) #define MBps(x) KBps(1000 * (x)) #define GBps(x) ((u64)1000 * MBps((x))) -static inline const char *onoff(bool v) -{ - return v ? "on" : "off"; -} - void add_taint_for_CI(struct drm_i915_private *i915, unsigned int taint); static inline void __add_taint_for_CI(unsigned int taint) { diff --git a/drivers/gpu/drm/i915/vlv_suspend.c b/drivers/gpu/drm/i915/vlv_suspend.c index 1d9da32195c2..664fde244f59 100644 --- a/drivers/gpu/drm/i915/vlv_suspend.c +++ b/drivers/gpu/drm/i915/vlv_suspend.c @@ -3,6 +3,7 @@ * Copyright © 2020 Intel Corporation */ +#include #include #include @@ -375,7 +376,7 @@ static void vlv_wait_for_gt_wells(struct drm_i915_private *dev_priv, if (vlv_wait_for_pw_status(dev_priv, mask, val)) drm_dbg(&dev_priv->drm, "timeout waiting for GT wells to go %s\n", - onoff(wait_for_on)); + str_on_off(wait_for_on)); } static void vlv_check_no_gt_access(struct drm_i915_private *i915) From 0a967f5bfd9134b89681cae58deb222e20840e76 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Wed, 2 Mar 2022 10:02:56 +0530 Subject: [PATCH 00050/11454] iommu/vt-d: Add RPLS to quirk list to skip TE disabling The VT-d spec requires (10.4.4 Global Command Register, TE field) that: Hardware implementations supporting DMA draining must drain any in-flight DMA read/write requests queued within the Root-Complex before completing the translation enable command and reflecting the status of the command through the TES field in the Global Status register. Unfortunately, some integrated graphic devices fail to do so after some kind of power state transition. As the result, the system might stuck in iommu_disable_translati on(), waiting for the completion of TE transition. This adds RPLS to a quirk list for those devices and skips TE disabling if the qurik hits. Link: https://gitlab.freedesktop.org/drm/intel/-/issues/4898 Tested-by: Raviteja Goud Talla Cc: Rodrigo Vivi Acked-by: Lu Baolu Signed-off-by: Tejas Upadhyay Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20220302043256.191529-1-tejaskumarx.surendrakumar.upadhyay@intel.com --- drivers/iommu/intel/iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c index 92fea3fbbb11..be9487516617 100644 --- a/drivers/iommu/intel/iommu.c +++ b/drivers/iommu/intel/iommu.c @@ -5743,7 +5743,7 @@ static void quirk_igfx_skip_te_disable(struct pci_dev *dev) ver = (dev->device >> 8) & 0xff; if (ver != 0x45 && ver != 0x46 && ver != 0x4c && ver != 0x4e && ver != 0x8a && ver != 0x98 && - ver != 0x9a) + ver != 0x9a && ver != 0xa7) return; if (risky_device(dev)) From 09550c7fcde1e0d50dde1093abdf54d9de06a2bf Mon Sep 17 00:00:00 2001 From: Swathi Dhanavanthri Date: Wed, 2 Mar 2022 15:11:19 -0800 Subject: [PATCH 00051/11454] drm/i915/display/adlp: Remove code related to underrun recovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is not supported for ADLP and is not needed. Signed-off-by: Swathi Dhanavanthri Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220302231119.16876-1-swathi.dhanavanthri@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 21 -------------------- 1 file changed, 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6cae58f921a5..541797a2ff9e 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3595,12 +3595,8 @@ static void hsw_set_transconf(const struct intel_crtc_state *crtc_state) static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - const struct intel_crtc_scaler_state *scaler_state = - &crtc_state->scaler_state; - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 val = 0; - int i; switch (crtc_state->pipe_bpp) { case 18: @@ -3639,23 +3635,6 @@ static void bdw_set_pipemisc(const struct intel_crtc_state *crtc_state) if (DISPLAY_VER(dev_priv) >= 12) val |= PIPEMISC_PIXEL_ROUNDING_TRUNC; - if (IS_ALDERLAKE_P(dev_priv)) { - bool scaler_in_use = false; - - for (i = 0; i < crtc->num_scalers; i++) { - if (!scaler_state->scalers[i].in_use) - continue; - - scaler_in_use = true; - break; - } - - intel_de_rmw(dev_priv, PIPE_MISC2(crtc->pipe), - PIPE_MISC2_BUBBLE_COUNTER_MASK, - scaler_in_use ? PIPE_MISC2_BUBBLE_COUNTER_SCALER_EN : - PIPE_MISC2_BUBBLE_COUNTER_SCALER_DIS); - } - intel_de_write(dev_priv, PIPEMISC(crtc->pipe), val); } From 5708fe0db0edfaaf6ef83106a4404bc102afe129 Mon Sep 17 00:00:00 2001 From: Lee Shawn C Date: Thu, 3 Mar 2022 16:38:02 +0800 Subject: [PATCH 00052/11454] drm/i915: update new TMDS clock setting defined by VBT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VBT 249 update to support more TMDS clock rate 3.00G, 3.40G and 5.94G. Refer to this new definition to configure max TMDS clock rate for HDMI driver. BSpec: 20124 v2: new subject Cc: Jani Nikula Cc: Ville Syrjala Cc: Ankit Nautiyal Signed-off-by: Lee Shawn C Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303083802.5071-1-shawn.c.lee@intel.com --- drivers/gpu/drm/i915/display/intel_bios.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_vbt_defs.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 40b5e7ed12c2..a559a1914588 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -1955,6 +1955,12 @@ static int _intel_bios_max_tmds_clock(const struct intel_bios_encoder_data *devd fallthrough; case HDMI_MAX_DATA_RATE_PLATFORM: return 0; + case HDMI_MAX_DATA_RATE_594: + return 594000; + case HDMI_MAX_DATA_RATE_340: + return 340000; + case HDMI_MAX_DATA_RATE_300: + return 300000; case HDMI_MAX_DATA_RATE_297: return 297000; case HDMI_MAX_DATA_RATE_165: diff --git a/drivers/gpu/drm/i915/display/intel_vbt_defs.h b/drivers/gpu/drm/i915/display/intel_vbt_defs.h index b9397d9363c5..e0508990df48 100644 --- a/drivers/gpu/drm/i915/display/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/display/intel_vbt_defs.h @@ -289,6 +289,9 @@ struct bdb_general_features { #define HDMI_MAX_DATA_RATE_PLATFORM 0 /* 204 */ #define HDMI_MAX_DATA_RATE_297 1 /* 204 */ #define HDMI_MAX_DATA_RATE_165 2 /* 204 */ +#define HDMI_MAX_DATA_RATE_594 3 /* 249 */ +#define HDMI_MAX_DATA_RATE_340 4 /* 249 */ +#define HDMI_MAX_DATA_RATE_300 5 /* 249 */ #define LEGACY_CHILD_DEVICE_CONFIG_SIZE 33 From 8d5516d18b323cf7274d1cf5fe76f4a691f879c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jouni=20H=C3=B6gander?= Date: Fri, 25 Feb 2022 09:02:28 +0200 Subject: [PATCH 00053/11454] drm/i915/psr: Set "SF Partial Frame Enable" also on full update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we are observing occasional screen flickering when PSR2 selective fetch is enabled. More specifically glitch seems to happen on full frame update when cursor moves to coords x = -1 or y = -1. According to Bspec SF Single full frame should not be set if SF Partial Frame Enable is not set. This happened to be true for ADLP as PSR2_MAN_TRK_CTL_ENABLE is always set and for ADL_P it's actually "SF Partial Frame Enable" (Bit 31). Setting "SF Partial Frame Enable" bit also on full update seems to fix screen flickering. Also make code more clear by setting PSR2_MAN_TRK_CTL_ENABLE only if not on ADL_P. Bit 31 has different meaning in ADL_P. Bspec: 49274 v2: Fix Mihai Harpau email address v3: Modify commit message and remove unnecessary comment Tested-by: Lyude Paul Fixes: 7f6002e58025 ("drm/i915/display: Enable PSR2 selective fetch by default") Reported-by: Lyude Paul Cc: Mihai Harpau Cc: José Roberto de Souza Cc: Ville Syrjälä Bugzilla: https://gitlab.freedesktop.org/drm/intel/-/issues/5077 Signed-off-by: Jouni Högander Reviewed-by: José Roberto de Souza Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220225070228.855138-1-jouni.hogander@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 16 ++++++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index 2e0b092f4b6b..b6b7bb5be5ae 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1439,6 +1439,13 @@ static inline u32 man_trk_ctl_single_full_frame_bit_get(struct drm_i915_private PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME; } +static inline u32 man_trk_ctl_partial_frame_bit_get(struct drm_i915_private *dev_priv) +{ + return IS_ALDERLAKE_P(dev_priv) ? + ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE : + PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE; +} + static void psr_force_hw_tracking_exit(struct intel_dp *intel_dp) { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); @@ -1543,7 +1550,13 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - u32 val = PSR2_MAN_TRK_CTL_ENABLE; + u32 val = 0; + + if (!IS_ALDERLAKE_P(dev_priv)) + val = PSR2_MAN_TRK_CTL_ENABLE; + + /* SF partial frame enable has to be set even on full update */ + val |= man_trk_ctl_partial_frame_bit_get(dev_priv); if (full_update) { /* @@ -1563,7 +1576,6 @@ static void psr2_man_trk_ctl_calc(struct intel_crtc_state *crtc_state, } else { drm_WARN_ON(crtc_state->uapi.crtc->dev, clip->y1 % 4 || clip->y2 % 4); - val |= PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE; val |= PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(clip->y1 / 4 + 1); val |= PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(clip->y2 / 4 + 1); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5f6c307f476a..ad962c9b9d66 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2316,6 +2316,7 @@ #define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_START_ADDR_MASK, val) #define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK REG_GENMASK(12, 0) #define ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR(val) REG_FIELD_PREP(ADLP_PSR2_MAN_TRK_CTL_SU_REGION_END_ADDR_MASK, val) +#define ADLP_PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE REG_BIT(31) #define ADLP_PSR2_MAN_TRK_CTL_SF_SINGLE_FULL_FRAME REG_BIT(14) #define ADLP_PSR2_MAN_TRK_CTL_SF_CONTINUOS_FULL_FRAME REG_BIT(13) From 9c95f96392d99e5915838e0ca83b25bad3f93e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Thu, 24 Feb 2022 12:25:23 -0800 Subject: [PATCH 00054/11454] drm/i915/display: Allow users to disable PSR2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some users are suffering with PSR2 issues that are under debug or issues that were root caused to panel firmware bugs, to make life of those users easier here adding a option to disable PSR2 with kernel parameters so they can still benefit from PSR1 power savings. Using the same enable_psr that is current used to turn the whole feature on or off and allowing user to select up to what PSR version it should enable. Right now users only set this parameter to 0 when they want to disable PSR1 and PSR2 or don't add it at all leaving it to per-chip behavior so it should not cause a bad impact on users. v2: - changing enable_psr values (Ville and Rodrigo) Link: https://gitlab.freedesktop.org/drm/intel/-/issues/4951 Cc: Jouni Högander Cc: Rodrigo Vivi Cc: Ville Syrjälä Signed-off-by: José Roberto de Souza Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220224202523.993560-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 4 ++++ drivers/gpu/drm/i915/i915_params.c | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index b6b7bb5be5ae..bbd581ed0815 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -100,11 +100,15 @@ static bool psr_global_enabled(struct intel_dp *intel_dp) static bool psr2_global_enabled(struct intel_dp *intel_dp) { + struct drm_i915_private *i915 = dp_to_i915(intel_dp); + switch (intel_dp->psr.debug & I915_PSR_DEBUG_MODE_MASK) { case I915_PSR_DEBUG_DISABLE: case I915_PSR_DEBUG_FORCE_PSR1: return false; default: + if (i915->params.enable_psr == 1) + return false; return true; } } diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index a28b10bc20ad..1930487e5f09 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -96,7 +96,7 @@ i915_param_named_unsafe(enable_hangcheck, bool, 0400, i915_param_named_unsafe(enable_psr, int, 0400, "Enable PSR " - "(0=disabled, 1=enabled) " + "(0=disabled, 1=enable up to PSR1, 2=enable up to PSR2) " "Default: -1 (use per-chip default)"); i915_param_named(psr_safest_params, bool, 0400, From 98bf4f47a86c7b4edf85ebaa3016615c0bb71fb5 Mon Sep 17 00:00:00 2001 From: Stanislav Lisovskiy Date: Thu, 9 Dec 2021 16:18:17 +0200 Subject: [PATCH 00055/11454] drm/i915/dg2: Use I915_BO_ALLOC_CONTIGUOUS flag for DPT Do mapping using CONTIGUOUS flag - otherwise i915_gem_object_is_contiguous warn is triggered. Signed-off-by: Stanislav Lisovskiy Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20211209141817.16038-1-stanislav.lisovskiy@intel.com --- drivers/gpu/drm/i915/display/intel_dpt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index 05dd7dba3a5c..15b2716172f7 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -249,7 +249,7 @@ intel_dpt_create(struct intel_framebuffer *fb) size = round_up(size * sizeof(gen8_pte_t), I915_GTT_PAGE_SIZE); if (HAS_LMEM(i915)) - dpt_obj = i915_gem_object_create_lmem(i915, size, 0); + dpt_obj = i915_gem_object_create_lmem(i915, size, I915_BO_ALLOC_CONTIGUOUS); else dpt_obj = i915_gem_object_create_stolen(i915, size); if (IS_ERR(dpt_obj)) From 6475e106821babc0dc478a9cb3fc3973739c43fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Feb 2022 12:55:29 +0200 Subject: [PATCH 00056/11454] drm/i915: Don't skip ddb allocation if data_rate==0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit data_rate==0 no longer means a plane is disabled, it could also mean we want to use the minimum ddb allocation for it. Hence we can't bail out early during ddb allocation or else we'll simply forget to allocate any ddb for such planes. Cc: Stanislav Lisovskiy Fixes: 6a4d8cc6bbbf ("drm/i915: Don't allocate extra ddb during async flip for DG2") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220214105532.13049-2-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/intel_pm.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 97af7ce6b22b..f70eb10ab24d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5146,12 +5146,15 @@ skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter, const struct skl_wm_level *wm, u64 data_rate) { - u16 extra; + u16 extra = 0; - extra = min_t(u16, iter->size, - DIV64_U64_ROUND_UP(iter->size * data_rate, iter->data_rate)); - iter->size -= extra; - iter->data_rate -= data_rate; + if (data_rate) { + extra = min_t(u16, iter->size, + DIV64_U64_ROUND_UP(iter->size * data_rate, + iter->data_rate)); + iter->size -= extra; + iter->data_rate -= data_rate; + } return wm->min_ddb_alloc + extra; } @@ -5194,9 +5197,6 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb_y[PLANE_CURSOR], alloc->end - iter.total[PLANE_CURSOR], alloc->end); - if (iter.data_rate == 0) - return 0; - /* * Find the highest watermark level for which we can satisfy the block * requirement of active planes. @@ -5235,6 +5235,10 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, return -EINVAL; } + /* avoid the WARN later when we don't allocate any extra DDB */ + if (iter.data_rate == 0) + iter.size = 0; + /* * Grant each plane the blocks it requires at the highest achievable * watermark level, plus an extra share of the leftover blocks @@ -5247,20 +5251,10 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, if (plane_id == PLANE_CURSOR) continue; - /* - * We've accounted for all active planes; remaining planes are - * all disabled. - */ - if (iter.data_rate == 0) - break; - iter.total[plane_id] = skl_allocate_plane_ddb(&iter, &wm->wm[level], crtc_state->plane_data_rate[plane_id]); - if (iter.data_rate == 0) - break; - iter.uv_total[plane_id] = skl_allocate_plane_ddb(&iter, &wm->uv_wm[level], crtc_state->uv_plane_data_rate[plane_id]); From b0b2bed2a1305c8f977c6b7d5fa162773693a212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Feb 2022 12:55:30 +0200 Subject: [PATCH 00057/11454] drm/i915: Check async flip capability early on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since the async flip state check is done very late and thus it can see potentially all the planes in the state (due to the wm/ddb optimization) we need to move the "can the requested plane do async flips at all?" check much earlier. For this purpose we introduce intel_async_flip_check_uapi() that gets called early during the atomic check. And for good measure we'll throw in a couple of basic checks: - is the crtc active? - was a modeset flagged? - is+was the plane enabled? Though atm all of those should be guaranteed by the fact that the async flip can only be requested through the legacy page flip ioctl. Cc: Stanislav Lisovskiy Fixes: c3639f3be480 ("drm/i915: Use wm0 only during async flips for DG2") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220214105532.13049-3-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_display.c | 79 ++++++++++++++++++-- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 541797a2ff9e..3976e00dfa04 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7414,7 +7414,7 @@ static void kill_bigjoiner_slave(struct intel_atomic_state *state, * Correspondingly, support is currently added for primary plane only. * * Async flip can only change the plane surface address, so anything else - * changing is rejected from the intel_atomic_check_async() function. + * changing is rejected from the intel_async_flip_check_hw() function. * Once this check is cleared, flip done interrupt is enabled using * the intel_crtc_enable_flip_done() function. * @@ -7424,7 +7424,65 @@ static void kill_bigjoiner_slave(struct intel_atomic_state *state, * correspond to the last vblank and have no relation to the actual time when * the flip done event was sent. */ -static int intel_atomic_check_async(struct intel_atomic_state *state, struct intel_crtc *crtc) +static int intel_async_flip_check_uapi(struct intel_atomic_state *state, + struct intel_crtc *crtc) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); + const struct intel_plane_state *old_plane_state; + struct intel_plane_state *new_plane_state; + struct intel_plane *plane; + int i; + + if (!new_crtc_state->uapi.async_flip) + return 0; + + if (!new_crtc_state->uapi.active) { + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] not active\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } + + if (intel_crtc_needs_modeset(new_crtc_state)) { + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] modeset required\n", + crtc->base.base.id, crtc->base.name); + return -EINVAL; + } + + for_each_oldnew_intel_plane_in_state(state, plane, old_plane_state, + new_plane_state, i) { + if (plane->pipe != crtc->pipe) + continue; + + /* + * TODO: Async flip is only supported through the page flip IOCTL + * as of now. So support currently added for primary plane only. + * Support for other planes on platforms on which supports + * this(vlv/chv and icl+) should be added when async flip is + * enabled in the atomic IOCTL path. + */ + if (!plane->async_flip) { + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] async flip not supported\n", + plane->base.base.id, plane->base.name); + return -EINVAL; + } + + if (!old_plane_state->uapi.fb || !new_plane_state->uapi.fb) { + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] no old or new framebuffer\n", + plane->base.base.id, plane->base.name); + return -EINVAL; + } + } + + return 0; +} + +static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct intel_crtc *crtc) { struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_crtc_state *old_crtc_state, *new_crtc_state; @@ -7435,6 +7493,9 @@ static int intel_atomic_check_async(struct intel_atomic_state *state, struct int old_crtc_state = intel_atomic_get_old_crtc_state(state, crtc); new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); + if (!new_crtc_state->uapi.async_flip) + return 0; + if (intel_crtc_needs_modeset(new_crtc_state)) { drm_dbg_kms(&i915->drm, "Modeset Required. Async flip not supported\n"); return -EINVAL; @@ -7630,6 +7691,12 @@ static int intel_atomic_check(struct drm_device *dev, if (ret) goto fail; + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + ret = intel_async_flip_check_uapi(state, crtc); + if (ret) + return ret; + } + ret = intel_bigjoiner_add_affected_crtcs(state); if (ret) goto fail; @@ -7786,11 +7853,9 @@ static int intel_atomic_check(struct drm_device *dev, for_each_oldnew_intel_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) { - if (new_crtc_state->uapi.async_flip) { - ret = intel_atomic_check_async(state, crtc); - if (ret) - goto fail; - } + ret = intel_async_flip_check_hw(state, crtc); + if (ret) + goto fail; if (!intel_crtc_needs_modeset(new_crtc_state) && !new_crtc_state->update_pipe) From 2e08437160d1e8f2cd3f0d56d59e74423602116e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Feb 2022 12:55:31 +0200 Subject: [PATCH 00058/11454] drm/i915: Fix the async flip wm0/ddb optimization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current implementation of the async flip wm0/ddb optimization does not work at all. The biggest problem is that we skip the whole intel_pipe_update_{start,end}() dance and thus never actually complete the commit that is trying to do the wm/ddb change. To fix this we need to move the do_async_flip flag to the crtc state since we handle commits per-pipe, not per-plane. Also since all planes can now be included in the first/last "async flip" (which gets converted to a sync flip to do the wm/ddb mangling) we need to be more careful when checking if the plane state is async flip comptatible. Only planes doing the async flip should be checked and other planes are perfectly fine not adhereing to any async flip related limitations. However for subsequent commits which are actually going do the async flip in hardware we want to make sure no other planes are in the state. That should never happen assuming we did our job correctly, so we'll toss in a WARN to make sure we catch any bugs here. Cc: Stanislav Lisovskiy Fixes: c3639f3be480 ("drm/i915: Use wm0 only during async flips for DG2") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220214105532.13049-4-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_atomic.c | 1 + .../gpu/drm/i915/display/intel_atomic_plane.c | 7 ++-- drivers/gpu/drm/i915/display/intel_crtc.c | 4 +- drivers/gpu/drm/i915/display/intel_display.c | 38 +++++++++++-------- .../drm/i915/display/intel_display_types.h | 6 +-- 5 files changed, 31 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic.c b/drivers/gpu/drm/i915/display/intel_atomic.c index e0667d163266..40da7910f845 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic.c +++ b/drivers/gpu/drm/i915/display/intel_atomic.c @@ -262,6 +262,7 @@ intel_crtc_duplicate_state(struct drm_crtc *crtc) crtc_state->preload_luts = false; crtc_state->inherited = false; crtc_state->wm.need_postvbl_update = false; + crtc_state->do_async_flip = false; crtc_state->fb_bits = 0; crtc_state->update_planes = 0; crtc_state->dsb = NULL; diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index c53aa6a4c7a0..5712688232fb 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -110,7 +110,6 @@ intel_plane_duplicate_state(struct drm_plane *plane) intel_state->ggtt_vma = NULL; intel_state->dpt_vma = NULL; intel_state->flags = 0; - intel_state->do_async_flip = false; /* add reference to fb */ if (intel_state->hw.fb) @@ -506,7 +505,7 @@ static int intel_plane_atomic_calc_changes(const struct intel_crtc_state *old_cr new_crtc_state->disable_lp_wm = true; if (intel_plane_do_async_flip(plane, old_crtc_state, new_crtc_state)) - new_plane_state->do_async_flip = true; + new_crtc_state->do_async_flip = true; return 0; } @@ -678,7 +677,7 @@ void intel_plane_update_arm(struct intel_plane *plane, trace_intel_plane_update_arm(&plane->base, crtc); - if (plane_state->do_async_flip) + if (crtc_state->do_async_flip && plane->async_flip) plane->async_flip(plane, crtc_state, plane_state, true); else plane->update_arm(plane, crtc_state, plane_state); @@ -703,7 +702,7 @@ void intel_crtc_planes_update_noarm(struct intel_atomic_state *state, struct intel_plane *plane; int i; - if (new_crtc_state->uapi.async_flip) + if (new_crtc_state->do_async_flip) return; /* diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 08ee3e17ee5c..65827481c1b1 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -485,7 +485,7 @@ void intel_pipe_update_start(struct intel_crtc_state *new_crtc_state) intel_crtc_has_type(new_crtc_state, INTEL_OUTPUT_DSI); DEFINE_WAIT(wait); - if (new_crtc_state->uapi.async_flip) + if (new_crtc_state->do_async_flip) return; if (intel_crtc_needs_vblank_work(new_crtc_state)) @@ -630,7 +630,7 @@ void intel_pipe_update_end(struct intel_crtc_state *new_crtc_state) ktime_t end_vbl_time = ktime_get(); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - if (new_crtc_state->uapi.async_flip) + if (new_crtc_state->do_async_flip) return; trace_intel_pipe_update_end(crtc, end_vbl_count, scanline_end); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3976e00dfa04..41c08fa853c4 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1265,10 +1265,8 @@ static void intel_crtc_enable_flip_done(struct intel_atomic_state *state, int i; for_each_new_intel_plane_in_state(state, plane, plane_state, i) { - if (plane->enable_flip_done && - plane->pipe == crtc->pipe && - update_planes & BIT(plane->id) && - plane_state->do_async_flip) + if (plane->pipe == crtc->pipe && + update_planes & BIT(plane->id)) plane->enable_flip_done(plane); } } @@ -1284,10 +1282,8 @@ static void intel_crtc_disable_flip_done(struct intel_atomic_state *state, int i; for_each_new_intel_plane_in_state(state, plane, plane_state, i) { - if (plane->disable_flip_done && - plane->pipe == crtc->pipe && - update_planes & BIT(plane->id) && - plane_state->do_async_flip) + if (plane->pipe == crtc->pipe && + update_planes & BIT(plane->id)) plane->disable_flip_done(plane); } } @@ -7517,14 +7513,24 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in continue; /* - * TODO: Async flip is only supported through the page flip IOCTL - * as of now. So support currently added for primary plane only. - * Support for other planes on platforms on which supports - * this(vlv/chv and icl+) should be added when async flip is - * enabled in the atomic IOCTL path. + * Only async flip capable planes should be in the state + * if we're really about to ask the hardware to perform + * an async flip. We should never get this far otherwise. + */ + if (drm_WARN_ON(&i915->drm, + new_crtc_state->do_async_flip && !plane->async_flip)) + return -EINVAL; + + /* + * Only check async flip capable planes other planes + * may be involved in the initial commit due to + * the wm0/ddb optimization. + * + * TODO maybe should track which planes actually + * were requested to do the async flip... */ if (!plane->async_flip) - return -EINVAL; + continue; /* * FIXME: This check is kept generic for all platforms. @@ -8477,7 +8483,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_dbuf_pre_plane_update(state); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { - if (new_crtc_state->uapi.async_flip) + if (new_crtc_state->do_async_flip) intel_crtc_enable_flip_done(state, crtc); } @@ -8503,7 +8509,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) drm_atomic_helper_wait_for_flip_done(dev, &state->base); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { - if (new_crtc_state->uapi.async_flip) + if (new_crtc_state->do_async_flip) intel_crtc_disable_flip_done(state, crtc); } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index b50d0e6efe21..776b3e6662f2 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -613,9 +613,6 @@ struct intel_plane_state { struct intel_fb_view view; - /* Indicates if async flip is required */ - bool do_async_flip; - /* Plane pxp decryption state */ bool decrypt; @@ -951,6 +948,9 @@ struct intel_crtc_state { bool preload_luts; bool inherited; /* state inherited from BIOS? */ + /* Ask the hardware to actually async flip? */ + bool do_async_flip; + /* Pipe source size (ie. panel fitter input size) * All planes will be positioned inside this space, * and get clipped at the edges. */ From 6b4e414ce8dab7042a002f861b7bcae50a1e2b6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Feb 2022 12:55:32 +0200 Subject: [PATCH 00059/11454] drm/i915: Pimp async flip debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Print the offending plane/crtc id+name in the async flip debugs. Cc: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220214105532.13049-5-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_display.c | 59 ++++++++++++++------ 1 file changed, 42 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 41c08fa853c4..10d483ce04a7 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -7492,18 +7492,24 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in if (!new_crtc_state->uapi.async_flip) return 0; - if (intel_crtc_needs_modeset(new_crtc_state)) { - drm_dbg_kms(&i915->drm, "Modeset Required. Async flip not supported\n"); + if (!new_crtc_state->hw.active) { + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] not active\n", + crtc->base.base.id, crtc->base.name); return -EINVAL; } - if (!new_crtc_state->hw.active) { - drm_dbg_kms(&i915->drm, "CRTC inactive\n"); + if (intel_crtc_needs_modeset(new_crtc_state)) { + drm_dbg_kms(&i915->drm, + "[CRTC:%d:%s] modeset required\n", + crtc->base.base.id, crtc->base.name); return -EINVAL; } + if (old_crtc_state->active_planes != new_crtc_state->active_planes) { drm_dbg_kms(&i915->drm, - "Active planes cannot be changed during async flip\n"); + "[CRTC:%d:%s] Active planes cannot be in async flip\n", + crtc->base.base.id, crtc->base.name); return -EINVAL; } @@ -7545,75 +7551,94 @@ static int intel_async_flip_check_hw(struct intel_atomic_state *state, struct in break; default: drm_dbg_kms(&i915->drm, - "Linear memory/CCS does not support async flips\n"); + "[PLANE:%d:%s] Modifier does not support async flips\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (new_plane_state->hw.fb->format->num_planes > 1) { drm_dbg_kms(&i915->drm, - "Planar formats not supported with async flips\n"); + "[PLANE:%d:%s] Planar formats do not support async flips\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (old_plane_state->view.color_plane[0].mapping_stride != new_plane_state->view.color_plane[0].mapping_stride) { - drm_dbg_kms(&i915->drm, "Stride cannot be changed in async flip\n"); + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] Stride cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (old_plane_state->hw.fb->modifier != new_plane_state->hw.fb->modifier) { drm_dbg_kms(&i915->drm, - "Framebuffer modifiers cannot be changed in async flip\n"); + "[PLANE:%d:%s] Modifier cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (old_plane_state->hw.fb->format != new_plane_state->hw.fb->format) { drm_dbg_kms(&i915->drm, - "Framebuffer format cannot be changed in async flip\n"); + "[PLANE:%d:%s] Pixel format cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (old_plane_state->hw.rotation != new_plane_state->hw.rotation) { - drm_dbg_kms(&i915->drm, "Rotation cannot be changed in async flip\n"); + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] Rotation cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (!drm_rect_equals(&old_plane_state->uapi.src, &new_plane_state->uapi.src) || !drm_rect_equals(&old_plane_state->uapi.dst, &new_plane_state->uapi.dst)) { drm_dbg_kms(&i915->drm, - "Plane size/co-ordinates cannot be changed in async flip\n"); + "[PLANE:%d:%s] Size/co-ordinates cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (old_plane_state->hw.alpha != new_plane_state->hw.alpha) { - drm_dbg_kms(&i915->drm, "Alpha value cannot be changed in async flip\n"); + drm_dbg_kms(&i915->drm, + "[PLANES:%d:%s] Alpha value cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (old_plane_state->hw.pixel_blend_mode != new_plane_state->hw.pixel_blend_mode) { drm_dbg_kms(&i915->drm, - "Pixel blend mode cannot be changed in async flip\n"); + "[PLANE:%d:%s] Pixel blend mode cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (old_plane_state->hw.color_encoding != new_plane_state->hw.color_encoding) { drm_dbg_kms(&i915->drm, - "Color encoding cannot be changed in async flip\n"); + "[PLANE:%d:%s] Color encoding cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; } if (old_plane_state->hw.color_range != new_plane_state->hw.color_range) { - drm_dbg_kms(&i915->drm, "Color range cannot be changed in async flip\n"); + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] Color range cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; } /* plane decryption is allow to change only in synchronous flips */ - if (old_plane_state->decrypt != new_plane_state->decrypt) + if (old_plane_state->decrypt != new_plane_state->decrypt) { + drm_dbg_kms(&i915->drm, + "[PLANE:%d:%s] Decryption cannot be changed in async flip\n", + plane->base.base.id, plane->base.name); return -EINVAL; + } } return 0; From 2046e733e125fa58ed997f3d26d43543faf82c95 Mon Sep 17 00:00:00 2001 From: Guo Zhengkui Date: Mon, 28 Feb 2022 22:23:50 +0800 Subject: [PATCH 00060/11454] drm/nouveau/instmem: fix uninitialized_var.cocci warning Fix following coccicheck warning: drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c:316:11-12: WARNING this kind of initialization is deprecated. `void *map = map` has the same form of uninitialized_var() macro. I remove the redundant assignement. It has been tested with gcc (Debian 8.3.0-6) 8.3.0. The patch which removed uninitialized_var() is: https://lore.kernel.org/all/20121028102007.GA7547@gmail.com/ And there is very few "/* GCC */" comments in the Linux kernel code now. Signed-off-by: Guo Zhengkui Reviewed-by: Lyude Paul Signed-off-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20220228142352.18006-1-guozhengkui@vivo.com --- drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c index 96aca0edfa3c..c51bac76174c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/instmem/nv50.c @@ -313,7 +313,7 @@ nv50_instobj_dtor(struct nvkm_memory *memory) struct nv50_instobj *iobj = nv50_instobj(memory); struct nvkm_instmem *imem = &iobj->imem->base; struct nvkm_vma *bar; - void *map = map; + void *map; mutex_lock(&imem->mutex); if (likely(iobj->lru.next)) From 02942b4213f30bed4291e2b53d9073a98839f45a Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 1 Mar 2022 16:33:50 -0800 Subject: [PATCH 00061/11454] drm/i915/guc: Do not conflate lrc_desc with GuC id for registration The LRC descriptor pool is going away. So, stop using it as a check for context registration, use the GuC id instead (being the thing that actually gets registered with the GuC). Also, rename the set/clear/query helper functions for context id mappings to better reflect their purpose and to differentiate from other registration related helper functions. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20220302003357.4188363-2-John.C.Harrison@Intel.com --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 69 ++++++++++--------- 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 1ce7e04aa837..ab368853fdf9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -511,31 +511,20 @@ static inline bool guc_submission_initialized(struct intel_guc *guc) return !!guc->lrc_desc_pool_vaddr; } -static inline void reset_lrc_desc(struct intel_guc *guc, u32 id) +static inline void _reset_lrc_desc(struct intel_guc *guc, u32 id) { - if (likely(guc_submission_initialized(guc))) { - struct guc_lrc_desc *desc = __get_lrc_desc(guc, id); - unsigned long flags; + struct guc_lrc_desc *desc = __get_lrc_desc(guc, id); - memset(desc, 0, sizeof(*desc)); - - /* - * xarray API doesn't have xa_erase_irqsave wrapper, so calling - * the lower level functions directly. - */ - xa_lock_irqsave(&guc->context_lookup, flags); - __xa_erase(&guc->context_lookup, id); - xa_unlock_irqrestore(&guc->context_lookup, flags); - } + memset(desc, 0, sizeof(*desc)); } -static inline bool lrc_desc_registered(struct intel_guc *guc, u32 id) +static inline bool ctx_id_mapped(struct intel_guc *guc, u32 id) { return __get_context(guc, id); } -static inline void set_lrc_desc_registered(struct intel_guc *guc, u32 id, - struct intel_context *ce) +static inline void set_ctx_id_mapping(struct intel_guc *guc, u32 id, + struct intel_context *ce) { unsigned long flags; @@ -548,6 +537,24 @@ static inline void set_lrc_desc_registered(struct intel_guc *guc, u32 id, xa_unlock_irqrestore(&guc->context_lookup, flags); } +static inline void clr_ctx_id_mapping(struct intel_guc *guc, u32 id) +{ + unsigned long flags; + + if (unlikely(!guc_submission_initialized(guc))) + return; + + _reset_lrc_desc(guc, id); + + /* + * xarray API doesn't have xa_erase_irqsave wrapper, so calling + * the lower level functions directly. + */ + xa_lock_irqsave(&guc->context_lookup, flags); + __xa_erase(&guc->context_lookup, id); + xa_unlock_irqrestore(&guc->context_lookup, flags); +} + static void decr_outstanding_submission_g2h(struct intel_guc *guc) { if (atomic_dec_and_test(&guc->outstanding_submission_g2h)) @@ -792,7 +799,7 @@ static int __guc_wq_item_append(struct i915_request *rq) GEM_BUG_ON(!atomic_read(&ce->guc_id.ref)); GEM_BUG_ON(context_guc_id_invalid(ce)); GEM_BUG_ON(context_wait_for_deregister_to_register(ce)); - GEM_BUG_ON(!lrc_desc_registered(ce_to_guc(ce), ce->guc_id.id)); + GEM_BUG_ON(!ctx_id_mapped(ce_to_guc(ce), ce->guc_id.id)); /* Insert NOOP if this work queue item will wrap the tail pointer. */ if (wqi_size > wq_space_until_wrap(ce)) { @@ -920,7 +927,7 @@ register_context: if (submit) { struct intel_context *ce = request_to_scheduling_context(last); - if (unlikely(!lrc_desc_registered(guc, ce->guc_id.id) && + if (unlikely(!ctx_id_mapped(guc, ce->guc_id.id) && !intel_context_is_banned(ce))) { ret = guc_lrc_desc_pin(ce, false); if (unlikely(ret == -EPIPE)) { @@ -1884,7 +1891,7 @@ static bool need_tasklet(struct intel_guc *guc, struct i915_request *rq) return submission_disabled(guc) || guc->stalled_request || !i915_sched_engine_is_empty(sched_engine) || - !lrc_desc_registered(guc, ce->guc_id.id); + !ctx_id_mapped(guc, ce->guc_id.id); } static void guc_submit_request(struct i915_request *rq) @@ -1941,7 +1948,7 @@ static void __release_guc_id(struct intel_guc *guc, struct intel_context *ce) else ida_simple_remove(&guc->submission_state.guc_ids, ce->guc_id.id); - reset_lrc_desc(guc, ce->guc_id.id); + clr_ctx_id_mapping(guc, ce->guc_id.id); set_context_guc_id_invalid(ce); } if (!list_empty(&ce->guc_id.link)) @@ -2237,10 +2244,10 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) GEM_BUG_ON(i915_gem_object_is_lmem(guc->ct.vma->obj) != i915_gem_object_is_lmem(ce->ring->vma->obj)); - context_registered = lrc_desc_registered(guc, desc_idx); + context_registered = ctx_id_mapped(guc, desc_idx); - reset_lrc_desc(guc, desc_idx); - set_lrc_desc_registered(guc, desc_idx, ce); + clr_ctx_id_mapping(guc, desc_idx); + set_ctx_id_mapping(guc, desc_idx, ce); desc = __get_lrc_desc(guc, desc_idx); desc->engine_class = engine_class_to_guc_class(engine->class); @@ -2311,7 +2318,7 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) } spin_unlock_irqrestore(&ce->guc_state.lock, flags); if (unlikely(disabled)) { - reset_lrc_desc(guc, desc_idx); + clr_ctx_id_mapping(guc, desc_idx); return 0; /* Will get registered later */ } @@ -2327,9 +2334,9 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) with_intel_runtime_pm(runtime_pm, wakeref) ret = register_context(ce, loop); if (unlikely(ret == -EBUSY)) { - reset_lrc_desc(guc, desc_idx); + clr_ctx_id_mapping(guc, desc_idx); } else if (unlikely(ret == -ENODEV)) { - reset_lrc_desc(guc, desc_idx); + clr_ctx_id_mapping(guc, desc_idx); ret = 0; /* Will get registered later */ } } @@ -2516,7 +2523,7 @@ static bool context_cant_unblock(struct intel_context *ce) return (ce->guc_state.sched_state & SCHED_STATE_NO_UNBLOCK) || context_guc_id_invalid(ce) || - !lrc_desc_registered(ce_to_guc(ce), ce->guc_id.id) || + !ctx_id_mapped(ce_to_guc(ce), ce->guc_id.id) || !intel_context_is_pinned(ce); } @@ -2686,7 +2693,7 @@ static inline void guc_lrc_desc_unpin(struct intel_context *ce) bool disabled; GEM_BUG_ON(!intel_gt_pm_is_awake(gt)); - GEM_BUG_ON(!lrc_desc_registered(guc, ce->guc_id.id)); + GEM_BUG_ON(!ctx_id_mapped(guc, ce->guc_id.id)); GEM_BUG_ON(ce != __get_context(guc, ce->guc_id.id)); GEM_BUG_ON(context_enabled(ce)); @@ -2803,7 +2810,7 @@ static void guc_context_destroy(struct kref *kref) */ spin_lock_irqsave(&guc->submission_state.lock, flags); destroy = submission_disabled(guc) || context_guc_id_invalid(ce) || - !lrc_desc_registered(guc, ce->guc_id.id); + !ctx_id_mapped(guc, ce->guc_id.id); if (likely(!destroy)) { if (!list_empty(&ce->guc_id.link)) list_del_init(&ce->guc_id.link); @@ -3046,7 +3053,7 @@ static void guc_signal_context_fence(struct intel_context *ce) static bool context_needs_register(struct intel_context *ce, bool new_guc_id) { return (new_guc_id || test_bit(CONTEXT_LRCA_DIRTY, &ce->flags) || - !lrc_desc_registered(ce_to_guc(ce), ce->guc_id.id)) && + !ctx_id_mapped(ce_to_guc(ce), ce->guc_id.id)) && !submission_disabled(ce_to_guc(ce)); } From 09570c5010411b51348b83af08c83a080bf59830 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 1 Mar 2022 16:33:51 -0800 Subject: [PATCH 00062/11454] drm/i915/guc: Add an explicit 'submission_initialized' flag The LRC descriptor pool is going away. So, stop using it as a check for whether submission has been initialised or not. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20220302003357.4188363-3-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 8 +++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index bf7079480d47..e439e6c1ac8b 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -138,6 +138,8 @@ struct intel_guc { bool submission_supported; /** @submission_selected: tracks whether the user enabled GuC submission */ bool submission_selected; + /** @submission_initialized: tracks whether GuC submission has been initialised */ + bool submission_initialized; /** * @rc_supported: tracks whether we support GuC rc on the current platform */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index ab368853fdf9..76310ee3a08f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -508,7 +508,7 @@ static void guc_lrc_desc_pool_destroy(struct intel_guc *guc) static inline bool guc_submission_initialized(struct intel_guc *guc) { - return !!guc->lrc_desc_pool_vaddr; + return guc->submission_initialized; } static inline void _reset_lrc_desc(struct intel_guc *guc, u32 id) @@ -1813,7 +1813,7 @@ int intel_guc_submission_init(struct intel_guc *guc) struct intel_gt *gt = guc_to_gt(guc); int ret; - if (guc->lrc_desc_pool) + if (guc->submission_initialized) return 0; ret = guc_lrc_desc_pool_create(guc); @@ -1832,19 +1832,21 @@ int intel_guc_submission_init(struct intel_guc *guc) guc->timestamp.ping_delay = (POLL_TIME_CLKS / gt->clock_frequency + 1) * HZ; guc->timestamp.shift = gpm_timestamp_shift(gt); + guc->submission_initialized = true; return 0; } void intel_guc_submission_fini(struct intel_guc *guc) { - if (!guc->lrc_desc_pool) + if (!guc->submission_initialized) return; guc_flush_destroyed_contexts(guc); guc_lrc_desc_pool_destroy(guc); i915_sched_engine_put(guc->sched_engine); bitmap_free(guc->submission_state.guc_ids_bitmap); + guc->submission_initialized = false; } static inline void queue_request(struct i915_sched_engine *sched_engine, From d124902242241171b704d051ef2830dd344dff84 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 1 Mar 2022 16:33:52 -0800 Subject: [PATCH 00063/11454] drm/i915/guc: Better name for context id limit The LRC descriptor pool is going away. So, stop using it as the limit for how many context ids are available. Instead, size the pool according to the number of contexts allowed. Note that this is just a naming change, the actual limit is identical in value. While at it, also update a kzalloc(sizeof()*count) to be a kcalloc(count,size). Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20220302003357.4188363-4-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/intel_context.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 4 ++-- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 16 ++++++++-------- drivers/gpu/drm/i915/gt/uc/selftest_guc.c | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_context.c b/drivers/gpu/drm/i915/gt/intel_context.c index 5d0ec7c49b6a..d87145b8fca0 100644 --- a/drivers/gpu/drm/i915/gt/intel_context.c +++ b/drivers/gpu/drm/i915/gt/intel_context.c @@ -400,7 +400,7 @@ intel_context_init(struct intel_context *ce, struct intel_engine_cs *engine) INIT_LIST_HEAD(&ce->guc_state.fences); INIT_LIST_HEAD(&ce->guc_state.requests); - ce->guc_id.id = GUC_INVALID_LRC_ID; + ce->guc_id.id = GUC_INVALID_CONTEXT_ID; INIT_LIST_HEAD(&ce->guc_id.link); INIT_LIST_HEAD(&ce->destroyed_link); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 4b300b6cc0f9..a4a6136b3616 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -32,8 +32,8 @@ #define GUC_CLIENT_PRIORITY_NORMAL 3 #define GUC_CLIENT_PRIORITY_NUM 4 -#define GUC_MAX_LRC_DESCRIPTORS 65535 -#define GUC_INVALID_LRC_ID GUC_MAX_LRC_DESCRIPTORS +#define GUC_MAX_CONTEXT_ID 65535 +#define GUC_INVALID_CONTEXT_ID GUC_MAX_CONTEXT_ID #define GUC_RENDER_ENGINE 0 #define GUC_VIDEO_ENGINE 1 diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 76310ee3a08f..e639c3295c42 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -351,12 +351,12 @@ request_to_scheduling_context(struct i915_request *rq) static inline bool context_guc_id_invalid(struct intel_context *ce) { - return ce->guc_id.id == GUC_INVALID_LRC_ID; + return ce->guc_id.id == GUC_INVALID_CONTEXT_ID; } static inline void set_context_guc_id_invalid(struct intel_context *ce) { - ce->guc_id.id = GUC_INVALID_LRC_ID; + ce->guc_id.id = GUC_INVALID_CONTEXT_ID; } static inline struct intel_guc *ce_to_guc(struct intel_context *ce) @@ -471,7 +471,7 @@ static struct guc_lrc_desc *__get_lrc_desc(struct intel_guc *guc, u32 index) { struct guc_lrc_desc *base = guc->lrc_desc_pool_vaddr; - GEM_BUG_ON(index >= GUC_MAX_LRC_DESCRIPTORS); + GEM_BUG_ON(index >= GUC_MAX_CONTEXT_ID); return &base[index]; } @@ -480,7 +480,7 @@ static inline struct intel_context *__get_context(struct intel_guc *guc, u32 id) { struct intel_context *ce = xa_load(&guc->context_lookup, id); - GEM_BUG_ON(id >= GUC_MAX_LRC_DESCRIPTORS); + GEM_BUG_ON(id >= GUC_MAX_CONTEXT_ID); return ce; } @@ -491,7 +491,7 @@ static int guc_lrc_desc_pool_create(struct intel_guc *guc) int ret; size = PAGE_ALIGN(sizeof(struct guc_lrc_desc) * - GUC_MAX_LRC_DESCRIPTORS); + GUC_MAX_CONTEXT_ID); ret = intel_guc_allocate_and_map_vma(guc, size, &guc->lrc_desc_pool, (void **)&guc->lrc_desc_pool_vaddr); if (ret) @@ -2428,7 +2428,7 @@ static void __guc_context_sched_disable(struct intel_guc *guc, GUC_CONTEXT_DISABLE }; - GEM_BUG_ON(guc_id == GUC_INVALID_LRC_ID); + GEM_BUG_ON(guc_id == GUC_INVALID_CONTEXT_ID); GEM_BUG_ON(intel_context_is_child(ce)); trace_intel_context_sched_disable(ce); @@ -3844,7 +3844,7 @@ void intel_guc_submission_init_early(struct intel_guc *guc) spin_lock_init(&guc->timestamp.lock); INIT_DELAYED_WORK(&guc->timestamp.work, guc_timestamp_ping); - guc->submission_state.num_guc_ids = GUC_MAX_LRC_DESCRIPTORS; + guc->submission_state.num_guc_ids = GUC_MAX_CONTEXT_ID; guc->submission_supported = __guc_submission_supported(guc); guc->submission_selected = __guc_submission_selected(guc); } @@ -3854,7 +3854,7 @@ g2h_context_lookup(struct intel_guc *guc, u32 desc_idx) { struct intel_context *ce; - if (unlikely(desc_idx >= GUC_MAX_LRC_DESCRIPTORS)) { + if (unlikely(desc_idx >= GUC_MAX_CONTEXT_ID)) { drm_err(&guc_to_gt(guc)->i915->drm, "Invalid desc_idx %u", desc_idx); return NULL; diff --git a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c index a115894d5896..1df71d0796ae 100644 --- a/drivers/gpu/drm/i915/gt/uc/selftest_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/selftest_guc.c @@ -148,7 +148,7 @@ static int intel_guc_steal_guc_ids(void *arg) struct i915_request *spin_rq = NULL, *rq, *last = NULL; int number_guc_id_stolen = guc->number_guc_id_stolen; - ce = kzalloc(sizeof(*ce) * GUC_MAX_LRC_DESCRIPTORS, GFP_KERNEL); + ce = kcalloc(GUC_MAX_CONTEXT_ID, sizeof(*ce), GFP_KERNEL); if (!ce) { pr_err("Context array allocation failed\n"); return -ENOMEM; From 58ea7d620c5ebc8f6181bf08d82aa44d2ec8af96 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 1 Mar 2022 16:33:53 -0800 Subject: [PATCH 00064/11454] drm/i915/guc: Split guc_lrc_desc_pin apart The LRC descriptor pool is going away. Further, the function that was populating it was also doing a bunch of logic about the context registration sequence. So, split that code apart into separate state setup and try to register functions. Note that some of those 'try to register' code paths actually undo the state setup and leave it to be redone again later (with potentially different values). This is inefficient. The next patch will correct this. Also, move a comment about ignoring return values to the place where the return values are actually ignored. v2: Move some more splitting from a later patch (and do it correctly). Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20220302003357.4188363-5-John.C.Harrison@Intel.com --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 54 +++++++++++-------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index e639c3295c42..83924e5d74a1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -631,7 +631,7 @@ int intel_guc_wait_for_idle(struct intel_guc *guc, long timeout) true, timeout); } -static int guc_lrc_desc_pin(struct intel_context *ce, bool loop); +static int try_context_registration(struct intel_context *ce, bool loop); static int __guc_add_request(struct intel_guc *guc, struct i915_request *rq) { @@ -929,7 +929,7 @@ register_context: if (unlikely(!ctx_id_mapped(guc, ce->guc_id.id) && !intel_context_is_banned(ce))) { - ret = guc_lrc_desc_pin(ce, false); + ret = try_context_registration(ce, false); if (unlikely(ret == -EPIPE)) { goto deadlk; } else if (ret == -EBUSY) { @@ -2224,20 +2224,15 @@ static void guc_context_policy_init(struct intel_engine_cs *engine, desc->preemption_timeout = engine->props.preempt_timeout_ms * 1000; } -static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) +static void prepare_context_registration_info(struct intel_context *ce) { struct intel_engine_cs *engine = ce->engine; - struct intel_runtime_pm *runtime_pm = engine->uncore->rpm; struct intel_guc *guc = &engine->gt->uc.guc; u32 desc_idx = ce->guc_id.id; struct guc_lrc_desc *desc; - bool context_registered; - intel_wakeref_t wakeref; struct intel_context *child; - int ret = 0; GEM_BUG_ON(!engine->mask); - GEM_BUG_ON(!sched_state_is_init(ce)); /* * Ensure LRC + CT vmas are is same region as write barrier is done @@ -2246,11 +2241,6 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) GEM_BUG_ON(i915_gem_object_is_lmem(guc->ct.vma->obj) != i915_gem_object_is_lmem(ce->ring->vma->obj)); - context_registered = ctx_id_mapped(guc, desc_idx); - - clr_ctx_id_mapping(guc, desc_idx); - set_ctx_id_mapping(guc, desc_idx, ce); - desc = __get_lrc_desc(guc, desc_idx); desc->engine_class = engine_class_to_guc_class(engine->class); desc->engine_submit_mask = engine->logical_mask; @@ -2295,6 +2285,26 @@ static int guc_lrc_desc_pin(struct intel_context *ce, bool loop) clear_children_join_go_memory(ce); } +} + +static int try_context_registration(struct intel_context *ce, bool loop) +{ + struct intel_engine_cs *engine = ce->engine; + struct intel_runtime_pm *runtime_pm = engine->uncore->rpm; + struct intel_guc *guc = &engine->gt->uc.guc; + intel_wakeref_t wakeref; + u32 desc_idx = ce->guc_id.id; + bool context_registered; + int ret = 0; + + GEM_BUG_ON(!sched_state_is_init(ce)); + + context_registered = ctx_id_mapped(guc, desc_idx); + + clr_ctx_id_mapping(guc, desc_idx); + set_ctx_id_mapping(guc, desc_idx, ce); + + prepare_context_registration_info(ce); /* * The context_lookup xarray is used to determine if the hardware @@ -3132,7 +3142,7 @@ static int guc_request_alloc(struct i915_request *rq) if (unlikely(ret < 0)) return ret; if (context_needs_register(ce, !!ret)) { - ret = guc_lrc_desc_pin(ce, true); + ret = try_context_registration(ce, true); if (unlikely(ret)) { /* unwind */ if (ret == -EPIPE) { disable_submission(guc); @@ -3623,9 +3633,17 @@ static void guc_set_default_submission(struct intel_engine_cs *engine) static inline void guc_kernel_context_pin(struct intel_guc *guc, struct intel_context *ce) { + /* + * Note: we purposefully do not check the returns below because + * the registration can only fail if a reset is just starting. + * This is called at the end of reset so presumably another reset + * isn't happening and even it did this code would be run again. + */ + if (context_guc_id_invalid(ce)) pin_guc_id(guc, ce); - guc_lrc_desc_pin(ce, true); + + try_context_registration(ce, true); } static inline void guc_init_lrc_mapping(struct intel_guc *guc) @@ -3643,13 +3661,7 @@ static inline void guc_init_lrc_mapping(struct intel_guc *guc) * Also, after a reset the of the GuC we want to make sure that the * information shared with GuC is properly reset. The kernel LRCs are * not attached to the gem_context, so they need to be added separately. - * - * Note: we purposefully do not check the return of guc_lrc_desc_pin, - * because that function can only fail if a reset is just starting. This - * is at the end of reset so presumably another reset isn't happening - * and even it did this code would be run again. */ - for_each_engine(engine, gt, id) { struct intel_context *ce; From 8e2e9c435e2bdcf3cbd53a0e82877616ae9a513a Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 1 Mar 2022 16:33:54 -0800 Subject: [PATCH 00065/11454] drm/i915/guc: Move lrc desc setup to where it is needed The LRC descriptor was being initialised early on in the context registration sequence. It could then be determined that the actual registration needs to be delayed and the descriptor would be wiped out. This is inefficient, so move the setup to later in the process after the point of no return. v2: Move some split changes into the split patch (and do them correctly). Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20220302003357.4188363-6-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 83924e5d74a1..19e45963a444 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2140,6 +2140,8 @@ static int __guc_action_register_context(struct intel_guc *guc, 0, loop); } +static void prepare_context_registration_info(struct intel_context *ce); + static int register_context(struct intel_context *ce, bool loop) { struct intel_guc *guc = ce_to_guc(ce); @@ -2150,6 +2152,8 @@ static int register_context(struct intel_context *ce, bool loop) GEM_BUG_ON(intel_context_is_child(ce)); trace_intel_context_register(ce); + prepare_context_registration_info(ce); + if (intel_context_is_parent(ce)) ret = __guc_action_register_multi_lrc(guc, ce, ce->guc_id.id, offset, loop); @@ -2304,8 +2308,6 @@ static int try_context_registration(struct intel_context *ce, bool loop) clr_ctx_id_mapping(guc, desc_idx); set_ctx_id_mapping(guc, desc_idx, ce); - prepare_context_registration_info(ce); - /* * The context_lookup xarray is used to determine if the hardware * context is currently registered. There are two cases in which it From 77dcbffbb5d6f822b0679f8a29242487c7c0bbb4 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 1 Mar 2022 16:33:55 -0800 Subject: [PATCH 00066/11454] drm/i915/guc: Rename desc_idx to ctx_id The LRC descriptor pool is going away. So, stop naming context ids as descriptor pool indecies. While at it, add a bunch of missing line feeds to some error messages. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20220302003357.4188363-7-John.C.Harrison@Intel.com --- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 52 +++++++++---------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 19e45963a444..e224e6dafcd0 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -2232,7 +2232,7 @@ static void prepare_context_registration_info(struct intel_context *ce) { struct intel_engine_cs *engine = ce->engine; struct intel_guc *guc = &engine->gt->uc.guc; - u32 desc_idx = ce->guc_id.id; + u32 ctx_id = ce->guc_id.id; struct guc_lrc_desc *desc; struct intel_context *child; @@ -2245,7 +2245,7 @@ static void prepare_context_registration_info(struct intel_context *ce) GEM_BUG_ON(i915_gem_object_is_lmem(guc->ct.vma->obj) != i915_gem_object_is_lmem(ce->ring->vma->obj)); - desc = __get_lrc_desc(guc, desc_idx); + desc = __get_lrc_desc(guc, ctx_id); desc->engine_class = engine_class_to_guc_class(engine->class); desc->engine_submit_mask = engine->logical_mask; desc->hw_context_desc = ce->lrc.lrca; @@ -2297,16 +2297,16 @@ static int try_context_registration(struct intel_context *ce, bool loop) struct intel_runtime_pm *runtime_pm = engine->uncore->rpm; struct intel_guc *guc = &engine->gt->uc.guc; intel_wakeref_t wakeref; - u32 desc_idx = ce->guc_id.id; + u32 ctx_id = ce->guc_id.id; bool context_registered; int ret = 0; GEM_BUG_ON(!sched_state_is_init(ce)); - context_registered = ctx_id_mapped(guc, desc_idx); + context_registered = ctx_id_mapped(guc, ctx_id); - clr_ctx_id_mapping(guc, desc_idx); - set_ctx_id_mapping(guc, desc_idx, ce); + clr_ctx_id_mapping(guc, ctx_id); + set_ctx_id_mapping(guc, ctx_id, ce); /* * The context_lookup xarray is used to determine if the hardware @@ -2332,7 +2332,7 @@ static int try_context_registration(struct intel_context *ce, bool loop) } spin_unlock_irqrestore(&ce->guc_state.lock, flags); if (unlikely(disabled)) { - clr_ctx_id_mapping(guc, desc_idx); + clr_ctx_id_mapping(guc, ctx_id); return 0; /* Will get registered later */ } @@ -2348,9 +2348,9 @@ static int try_context_registration(struct intel_context *ce, bool loop) with_intel_runtime_pm(runtime_pm, wakeref) ret = register_context(ce, loop); if (unlikely(ret == -EBUSY)) { - clr_ctx_id_mapping(guc, desc_idx); + clr_ctx_id_mapping(guc, ctx_id); } else if (unlikely(ret == -ENODEV)) { - clr_ctx_id_mapping(guc, desc_idx); + clr_ctx_id_mapping(guc, ctx_id); ret = 0; /* Will get registered later */ } } @@ -3864,26 +3864,26 @@ void intel_guc_submission_init_early(struct intel_guc *guc) } static inline struct intel_context * -g2h_context_lookup(struct intel_guc *guc, u32 desc_idx) +g2h_context_lookup(struct intel_guc *guc, u32 ctx_id) { struct intel_context *ce; - if (unlikely(desc_idx >= GUC_MAX_CONTEXT_ID)) { + if (unlikely(ctx_id >= GUC_MAX_CONTEXT_ID)) { drm_err(&guc_to_gt(guc)->i915->drm, - "Invalid desc_idx %u", desc_idx); + "Invalid ctx_id %u\n", ctx_id); return NULL; } - ce = __get_context(guc, desc_idx); + ce = __get_context(guc, ctx_id); if (unlikely(!ce)) { drm_err(&guc_to_gt(guc)->i915->drm, - "Context is NULL, desc_idx %u", desc_idx); + "Context is NULL, ctx_id %u\n", ctx_id); return NULL; } if (unlikely(intel_context_is_child(ce))) { drm_err(&guc_to_gt(guc)->i915->drm, - "Context is child, desc_idx %u", desc_idx); + "Context is child, ctx_id %u\n", ctx_id); return NULL; } @@ -3895,14 +3895,14 @@ int intel_guc_deregister_done_process_msg(struct intel_guc *guc, u32 len) { struct intel_context *ce; - u32 desc_idx = msg[0]; + u32 ctx_id = msg[0]; if (unlikely(len < 1)) { - drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len); + drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u\n", len); return -EPROTO; } - ce = g2h_context_lookup(guc, desc_idx); + ce = g2h_context_lookup(guc, ctx_id); if (unlikely(!ce)) return -EPROTO; @@ -3946,14 +3946,14 @@ int intel_guc_sched_done_process_msg(struct intel_guc *guc, { struct intel_context *ce; unsigned long flags; - u32 desc_idx = msg[0]; + u32 ctx_id = msg[0]; if (unlikely(len < 2)) { - drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len); + drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u\n", len); return -EPROTO; } - ce = g2h_context_lookup(guc, desc_idx); + ce = g2h_context_lookup(guc, ctx_id); if (unlikely(!ce)) return -EPROTO; @@ -3961,8 +3961,8 @@ int intel_guc_sched_done_process_msg(struct intel_guc *guc, (!context_pending_enable(ce) && !context_pending_disable(ce)))) { drm_err(&guc_to_gt(guc)->i915->drm, - "Bad context sched_state 0x%x, desc_idx %u", - ce->guc_state.sched_state, desc_idx); + "Bad context sched_state 0x%x, ctx_id %u\n", + ce->guc_state.sched_state, ctx_id); return -EPROTO; } @@ -4060,14 +4060,14 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, { struct intel_context *ce; unsigned long flags; - int desc_idx; + int ctx_id; if (unlikely(len != 1)) { drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len); return -EPROTO; } - desc_idx = msg[0]; + ctx_id = msg[0]; /* * The context lookup uses the xarray but lookups only require an RCU lock @@ -4076,7 +4076,7 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, * asynchronously until the reset is done. */ xa_lock_irqsave(&guc->context_lookup, flags); - ce = g2h_context_lookup(guc, desc_idx); + ce = g2h_context_lookup(guc, ctx_id); if (ce) intel_context_get(ce); xa_unlock_irqrestore(&guc->context_lookup, flags); From d4de9a3eaede440717244672ddc16114e388bc2f Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 1 Mar 2022 16:33:56 -0800 Subject: [PATCH 00067/11454] drm/i915/guc: Drop obsolete H2G definitions The CTB registration process changed significantly a while back using a single KLV based H2G. So drop the original and now obsolete H2G definitions. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20220302003357.4188363-8-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h index 7afdadc7656f..e77f955435ce 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h @@ -131,8 +131,6 @@ enum intel_guc_action { INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000, INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502, INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503, - INTEL_GUC_ACTION_REGISTER_COMMAND_TRANSPORT_BUFFER = 0x4505, - INTEL_GUC_ACTION_DEREGISTER_COMMAND_TRANSPORT_BUFFER = 0x4506, INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE = 0x4600, INTEL_GUC_ACTION_REGISTER_CONTEXT_MULTI_LRC = 0x4601, INTEL_GUC_ACTION_CLIENT_SOFT_RESET = 0x5507, From e1dd871442c05ad5f53bc1eac22f71b53eb48a8a Mon Sep 17 00:00:00 2001 From: John Harrison Date: Tue, 1 Mar 2022 16:33:57 -0800 Subject: [PATCH 00068/11454] drm/i915/guc: Fix potential invalid pointer dereferences when decoding G2Hs Some G2H handlers were reading the context id field from the payload before checking the payload met the minimum length required. Signed-off-by: John Harrison Reviewed-by: Daniele Ceraolo Spurio Link: https://patchwork.freedesktop.org/patch/msgid/20220302003357.4188363-9-John.C.Harrison@Intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index e224e6dafcd0..9d8a271b7a24 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -3895,12 +3895,13 @@ int intel_guc_deregister_done_process_msg(struct intel_guc *guc, u32 len) { struct intel_context *ce; - u32 ctx_id = msg[0]; + u32 ctx_id; if (unlikely(len < 1)) { drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u\n", len); return -EPROTO; } + ctx_id = msg[0]; ce = g2h_context_lookup(guc, ctx_id); if (unlikely(!ce)) @@ -3946,12 +3947,13 @@ int intel_guc_sched_done_process_msg(struct intel_guc *guc, { struct intel_context *ce; unsigned long flags; - u32 ctx_id = msg[0]; + u32 ctx_id; if (unlikely(len < 2)) { drm_err(&guc_to_gt(guc)->i915->drm, "Invalid length %u\n", len); return -EPROTO; } + ctx_id = msg[0]; ce = g2h_context_lookup(guc, ctx_id); if (unlikely(!ce)) From 8d80cceecdd98de6d2281d39d6571a1fe08e5af9 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Thu, 3 Mar 2022 17:02:52 +0530 Subject: [PATCH 00069/11454] drm/i915/adl-n: Add stepping info Add ADL-N stepping-substepping info in accordance to BSpec. Bspec: 68397 Cc: Matt Roper Signed-off-by: Tejas Upadhyay Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220303113252.212873-1-tejaskumarx.surendrakumar.upadhyay@intel.com --- drivers/gpu/drm/i915/intel_step.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_step.c b/drivers/gpu/drm/i915/intel_step.c index ac1a796b2808..b6561f97578d 100644 --- a/drivers/gpu/drm/i915/intel_step.c +++ b/drivers/gpu/drm/i915/intel_step.c @@ -131,6 +131,10 @@ static const struct intel_step_info adls_rpls_revids[] = { [0xC] = { COMMON_GT_MEDIA_STEP(D0), .display_step = STEP_C0 }, }; +static const struct intel_step_info adlp_n_revids[] = { + [0x0] = { COMMON_GT_MEDIA_STEP(A0), .display_step = STEP_D0 }, +}; + void intel_step_init(struct drm_i915_private *i915) { const struct intel_step_info *revids = NULL; @@ -150,6 +154,9 @@ void intel_step_init(struct drm_i915_private *i915) } else if (IS_XEHPSDV(i915)) { revids = xehpsdv_revids; size = ARRAY_SIZE(xehpsdv_revids); + } else if (IS_ADLP_N(i915)) { + revids = adlp_n_revids; + size = ARRAY_SIZE(adlp_n_revids); } else if (IS_ALDERLAKE_P(i915)) { revids = adlp_revids; size = ARRAY_SIZE(adlp_revids); From 69e807a5a9ffe595853277cb00d7d3fdd583b0fa Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 3 Mar 2022 20:19:27 +0200 Subject: [PATCH 00070/11454] drm/i915/gmbus: combine gmbus pin lookups to one function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Combine the platform specific if ladders for array lookup and size checks into one. This is cleaner and avoids duplication, but hopefully also helps any static analyzers that seem to have trouble with the bounds checks. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303181931.1661767-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_gmbus.c | 76 ++++++++++------------ 1 file changed, 36 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 2fad03250661..9cbf7f9a1e2e 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -106,51 +106,47 @@ static const struct gmbus_pin gmbus_pins_dg2[] = { [GMBUS_PIN_9_TC1_ICP] = { "tc1", GPIOJ }, }; -/* pin is expected to be valid */ -static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *dev_priv, +static const struct gmbus_pin *get_gmbus_pin(struct drm_i915_private *i915, unsigned int pin) { - if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG2) - return &gmbus_pins_dg2[pin]; - else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) - return &gmbus_pins_dg1[pin]; - else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - return &gmbus_pins_icp[pin]; - else if (HAS_PCH_CNP(dev_priv)) - return &gmbus_pins_cnp[pin]; - else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - return &gmbus_pins_bxt[pin]; - else if (DISPLAY_VER(dev_priv) == 9) - return &gmbus_pins_skl[pin]; - else if (IS_BROADWELL(dev_priv)) - return &gmbus_pins_bdw[pin]; - else - return &gmbus_pins[pin]; + const struct gmbus_pin *pins; + size_t size; + + if (INTEL_PCH_TYPE(i915) >= PCH_DG2) { + pins = gmbus_pins_dg2; + size = ARRAY_SIZE(gmbus_pins_dg2); + } else if (INTEL_PCH_TYPE(i915) >= PCH_DG1) { + pins = gmbus_pins_dg1; + size = ARRAY_SIZE(gmbus_pins_dg1); + } else if (INTEL_PCH_TYPE(i915) >= PCH_ICP) { + pins = gmbus_pins_icp; + size = ARRAY_SIZE(gmbus_pins_icp); + } else if (HAS_PCH_CNP(i915)) { + pins = gmbus_pins_cnp; + size = ARRAY_SIZE(gmbus_pins_cnp); + } else if (IS_GEMINILAKE(i915) || IS_BROXTON(i915)) { + pins = gmbus_pins_bxt; + size = ARRAY_SIZE(gmbus_pins_bxt); + } else if (DISPLAY_VER(i915) == 9) { + pins = gmbus_pins_skl; + size = ARRAY_SIZE(gmbus_pins_skl); + } else if (IS_BROADWELL(i915)) { + pins = gmbus_pins_bdw; + size = ARRAY_SIZE(gmbus_pins_bdw); + } else { + pins = gmbus_pins; + size = ARRAY_SIZE(gmbus_pins); + } + + if (pin >= size || !pins[pin].name) + return NULL; + + return &pins[pin]; } -bool intel_gmbus_is_valid_pin(struct drm_i915_private *dev_priv, - unsigned int pin) +bool intel_gmbus_is_valid_pin(struct drm_i915_private *i915, unsigned int pin) { - unsigned int size; - - if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG2) - size = ARRAY_SIZE(gmbus_pins_dg2); - else if (INTEL_PCH_TYPE(dev_priv) >= PCH_DG1) - size = ARRAY_SIZE(gmbus_pins_dg1); - else if (INTEL_PCH_TYPE(dev_priv) >= PCH_ICP) - size = ARRAY_SIZE(gmbus_pins_icp); - else if (HAS_PCH_CNP(dev_priv)) - size = ARRAY_SIZE(gmbus_pins_cnp); - else if (IS_GEMINILAKE(dev_priv) || IS_BROXTON(dev_priv)) - size = ARRAY_SIZE(gmbus_pins_bxt); - else if (DISPLAY_VER(dev_priv) == 9) - size = ARRAY_SIZE(gmbus_pins_skl); - else if (IS_BROADWELL(dev_priv)) - size = ARRAY_SIZE(gmbus_pins_bdw); - else - size = ARRAY_SIZE(gmbus_pins); - - return pin < size && get_gmbus_pin(dev_priv, pin)->name; + return get_gmbus_pin(i915, pin); } /* Intel GPIO access functions */ From 39a8c428fedf5675475ac4c7a1dabaedb3358c77 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 3 Mar 2022 20:19:28 +0200 Subject: [PATCH 00071/11454] drm/i915/gmbus: reduce gmbus pin lookups in gmbus setup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid separate pin lookups for validity and name. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303181931.1661767-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_gmbus.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 9cbf7f9a1e2e..9dc66447d308 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -876,7 +876,10 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) init_waitqueue_head(&dev_priv->gmbus_wait_queue); for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { - if (!intel_gmbus_is_valid_pin(dev_priv, pin)) + const struct gmbus_pin *gmbus_pin; + + gmbus_pin = get_gmbus_pin(dev_priv, pin); + if (!gmbus_pin) continue; bus = &dev_priv->gmbus[pin]; @@ -885,8 +888,7 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) bus->adapter.class = I2C_CLASS_DDC; snprintf(bus->adapter.name, sizeof(bus->adapter.name), - "i915 gmbus %s", - get_gmbus_pin(dev_priv, pin)->name); + "i915 gmbus %s", gmbus_pin->name); bus->adapter.dev.parent = &pdev->dev; bus->dev_priv = dev_priv; From 65cd963ea239a9c4bf0e5fdf9a86213908276554 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 3 Mar 2022 20:19:29 +0200 Subject: [PATCH 00072/11454] drm/i915/gmbus: pass gpio reg to intel_gpio_setup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid the additional gmbus lookup on the pin. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303181931.1661767-3-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_gmbus.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 9dc66447d308..fd908e524875 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -322,14 +322,13 @@ intel_gpio_post_xfer(struct i2c_adapter *adapter) } static void -intel_gpio_setup(struct intel_gmbus *bus, unsigned int pin) +intel_gpio_setup(struct intel_gmbus *bus, i915_reg_t gpio_reg) { - struct drm_i915_private *dev_priv = bus->dev_priv; struct i2c_algo_bit_data *algo; algo = &bus->bit_algo; - bus->gpio_reg = GPIO(get_gmbus_pin(dev_priv, pin)->gpio); + bus->gpio_reg = gpio_reg; bus->adapter.algo_data = algo; algo->setsda = set_data; algo->setscl = set_clock; @@ -909,7 +908,7 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) if (IS_I830(dev_priv)) bus->force_bit = 1; - intel_gpio_setup(bus, pin); + intel_gpio_setup(bus, GPIO(gmbus_pin->gpio)); ret = i2c_add_adapter(&bus->adapter); if (ret) From 63a78bbb418c6e047bd002616bd4de9add0b6974 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 3 Mar 2022 20:19:30 +0200 Subject: [PATCH 00073/11454] drm/i915/gmbus: alloc intel_gmbus dynamically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allocate the individual intel_gmbus structs dynamically. This lets us hide struct intel_gmbus inside intel_gmbus.c completely. Also use the cleanup function on the error path to avoid duplication. Leave #include in i915_drv.h for now, as it pulls in a bunch of implicit dependencies. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303181931.1661767-4-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_gmbus.c | 42 +++++++++++++++------- drivers/gpu/drm/i915/i915_drv.h | 14 ++------ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index fd908e524875..2bb3494b93e2 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -38,6 +38,16 @@ #include "intel_display_types.h" #include "intel_gmbus.h" +struct intel_gmbus { + struct i2c_adapter adapter; +#define GMBUS_FORCE_BIT_RETRY (1U << 31) + u32 force_bit; + u32 reg0; + i915_reg_t gpio_reg; + struct i2c_algo_bit_data bit_algo; + struct drm_i915_private *dev_priv; +}; + struct gmbus_pin { const char *name; enum i915_gpio gpio; @@ -881,7 +891,11 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) if (!gmbus_pin) continue; - bus = &dev_priv->gmbus[pin]; + bus = kzalloc(sizeof(*bus), GFP_KERNEL); + if (!bus) { + ret = -ENOMEM; + goto err; + } bus->adapter.owner = THIS_MODULE; bus->adapter.class = I2C_CLASS_DDC; @@ -911,8 +925,12 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) intel_gpio_setup(bus, GPIO(gmbus_pin->gpio)); ret = i2c_add_adapter(&bus->adapter); - if (ret) + if (ret) { + kfree(bus); goto err; + } + + dev_priv->gmbus[pin] = bus; } intel_gmbus_reset(dev_priv); @@ -920,24 +938,19 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) return 0; err: - while (pin--) { - if (!intel_gmbus_is_valid_pin(dev_priv, pin)) - continue; + intel_gmbus_teardown(dev_priv); - bus = &dev_priv->gmbus[pin]; - i2c_del_adapter(&bus->adapter); - } return ret; } struct i2c_adapter *intel_gmbus_get_adapter(struct drm_i915_private *dev_priv, unsigned int pin) { - if (drm_WARN_ON(&dev_priv->drm, - !intel_gmbus_is_valid_pin(dev_priv, pin))) + if (drm_WARN_ON(&dev_priv->drm, pin >= ARRAY_SIZE(dev_priv->gmbus) || + !dev_priv->gmbus[pin])) return NULL; - return &dev_priv->gmbus[pin].adapter; + return &dev_priv->gmbus[pin]->adapter; } void intel_gmbus_force_bit(struct i2c_adapter *adapter, bool force_bit) @@ -969,10 +982,13 @@ void intel_gmbus_teardown(struct drm_i915_private *dev_priv) unsigned int pin; for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { - if (!intel_gmbus_is_valid_pin(dev_priv, pin)) + bus = dev_priv->gmbus[pin]; + if (!bus) continue; - bus = &dev_priv->gmbus[pin]; i2c_del_adapter(&bus->adapter); + + kfree(bus); + dev_priv->gmbus[pin] = NULL; } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5cfe69b30841..c0a71cd85632 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -35,7 +35,6 @@ #include #include -#include #include #include @@ -99,6 +98,7 @@ struct intel_dpll_funcs; struct intel_encoder; struct intel_fbdev; struct intel_fdi_funcs; +struct intel_gmbus; struct intel_hotplug_funcs; struct intel_initial_plane_config; struct intel_limit; @@ -231,16 +231,6 @@ struct i915_drrs { #define QUIRK_INCREASE_DDI_DISABLED_TIME (1<<7) #define QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK (1<<8) -struct intel_gmbus { - struct i2c_adapter adapter; -#define GMBUS_FORCE_BIT_RETRY (1U << 31) - u32 force_bit; - u32 reg0; - i915_reg_t gpio_reg; - struct i2c_algo_bit_data bit_algo; - struct drm_i915_private *dev_priv; -}; - struct i915_suspend_saved_registers { u32 saveDSPARB; u32 saveSWF0[16]; @@ -510,7 +500,7 @@ struct drm_i915_private { struct intel_dmc dmc; - struct intel_gmbus gmbus[GMBUS_NUM_PINS]; + struct intel_gmbus *gmbus[GMBUS_NUM_PINS]; /** gmbus_mutex protects against concurrent usage of the single hw gmbus * controller on different i2c buses. */ From e9b67ec2d38aef0987975b95f57ac56947895819 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 3 Mar 2022 20:19:31 +0200 Subject: [PATCH 00074/11454] drm/i915: include linux/highmem.h and linux/swap.h where needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Include linux/highmem.h and linux/swap.h explicitly where needed so we can drop the linux/i2c.h include from i915_drv.h where it pulled in the dependencies implicitly. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303181931.1661767-5-jani.nikula@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_context.c | 1 + drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 3 ++- drivers/gpu/drm/i915/gem/i915_gem_object.c | 1 + drivers/gpu/drm/i915/gem/selftests/huge_pages.c | 1 + drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c | 1 + drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c | 2 ++ drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c | 1 + drivers/gpu/drm/i915/i915_cmd_parser.c | 2 ++ drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_gpu_error.c | 1 + 10 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index bc6d59df064d..7087fdf191e6 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -64,6 +64,7 @@ * */ +#include #include #include diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index d42f437149c9..b9427d82bbc7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -4,8 +4,9 @@ * Copyright © 2008,2010 Intel Corporation */ -#include #include +#include +#include #include #include diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c index 2d593d573ef1..9aad7ebde3e7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c @@ -22,6 +22,7 @@ * */ +#include #include #include diff --git a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c index c490c5624924..e2eb5a2dfb30 100644 --- a/drivers/gpu/drm/i915/gem/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/gem/selftests/huge_pages.c @@ -6,6 +6,7 @@ #include #include +#include #include "i915_selftest.h" diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c index 8ae1a1530bd8..6dc83255e4f3 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_mman.c @@ -4,6 +4,7 @@ * Copyright © 2016 Intel Corporation */ +#include #include #include "gem/i915_gem_internal.h" diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c index 76880fb8fc19..6ebda3d65086 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt_fencing.c @@ -3,6 +3,8 @@ * Copyright © 2008-2015 Intel Corporation */ +#include + #include "i915_drv.h" #include "i915_reg.h" #include "i915_scatterlist.h" diff --git a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c index c88113044494..541f180aaa29 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_uc_fw.c @@ -5,6 +5,7 @@ #include #include +#include #include #include diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index 5f6e41636655..f93e6122f247 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -25,6 +25,8 @@ * */ +#include + #include #include "gt/intel_engine.h" diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c0a71cd85632..b9f9168280e8 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -34,7 +34,6 @@ #include -#include #include #include diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 4967e79806f8..5e09a4e4b01a 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -28,6 +28,7 @@ */ #include +#include #include #include #include From fc3785fb56a27304c769af730d079f4337d4dc76 Mon Sep 17 00:00:00 2001 From: Arunpravin Date: Fri, 4 Mar 2022 01:46:02 +0530 Subject: [PATCH 00075/11454] drm/selftests: fix a shift-out-of-bounds bug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pass the correct size value computed using the max_order. [ 68.124177][ T1] UBSAN: shift-out-of-bounds in include/linux/log2.h:67:13 [ 68.125333][ T1] shift exponent 4294967295 is too large for 32-bit type 'long unsigned int' [ 68.126563][ T1] CPU: 0 PID: 1 Comm: swapper Not tainted 5.17.0-rc2-00311-g39ec47bbfd5d #2 [ 68.127758][ T1] Call Trace: [ 68.128187][ T1] dump_stack_lvl (lib/dump_stack.c:108) [ 68.128793][ T1] dump_stack (lib/dump_stack.c:114) [ 68.129331][ T1] ubsan_epilogue (lib/ubsan.c:152) [ 68.129958][ T1] __ubsan_handle_shift_out_of_bounds.cold (arch/x86/include/asm/smap.h:85) [ 68.130791][ T1] ? drm_block_alloc+0x28/0x80 [ 68.131582][ T1] ? rcu_read_lock_sched_held (kernel/rcu/update.c:125) [ 68.132215][ T1] ? kmem_cache_alloc (include/trace/events/kmem.h:54 mm/slab.c:3501) [ 68.132878][ T1] ? mark_free+0x2e/0x80 [ 68.133524][ T1] drm_buddy_init.cold (include/linux/log2.h:67 drivers/gpu/drm/drm_buddy.c:131) [ 68.134145][ T1] ? test_drm_cmdline_init (drivers/gpu/drm/selftests/test-drm_buddy.c:87) [ 68.134770][ T1] igt_buddy_alloc_limit (drivers/gpu/drm/selftests/test-drm_buddy.c:30) [ 68.135472][ T1] ? vprintk_default (kernel/printk/printk.c:2257) [ 68.136057][ T1] ? test_drm_cmdline_init (drivers/gpu/drm/selftests/test-drm_buddy.c:87) [ 68.136812][ T1] test_drm_buddy_init (drivers/gpu/drm/selftests/drm_selftest.c:77 drivers/gpu/drm/selftests/test-drm_buddy.c:95) [ 68.137475][ T1] do_one_initcall (init/main.c:1300) [ 68.138111][ T1] ? parse_args (kernel/params.c:609 kernel/params.c:146 kernel/params.c:188) [ 68.138717][ T1] do_basic_setup (init/main.c:1372 init/main.c:1389 init/main.c:1408) [ 68.139366][ T1] kernel_init_freeable (init/main.c:1617) [ 68.140040][ T1] ? rest_init (init/main.c:1494) [ 68.140634][ T1] kernel_init (init/main.c:1504) [ 68.141155][ T1] ret_from_fork (arch/x86/entry/entry_32.S:772) [ 68.141607][ T1] ================================================================================ [ 68.146730][ T1] ------------[ cut here ]------------ [ 68.147460][ T1] kernel BUG at drivers/gpu/drm/drm_buddy.c:140! [ 68.148280][ T1] invalid opcode: 0000 [#1] [ 68.148895][ T1] CPU: 0 PID: 1 Comm: swapper Not tainted 5.17.0-rc2-00311-g39ec47bbfd5d #2 [ 68.149896][ T1] EIP: drm_buddy_init (drivers/gpu/drm/drm_buddy.c:140 (discriminator 1)) For more details: https://lists.01.org/hyperkitty/list/lkp@lists.01.org/thread/FDIF3HCILZNN5UQAZMOR7E3MQSMHHKWU/ Signed-off-by: Arunpravin Reported-by: kernel test robot Acked-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20220303201602.2365-1-Arunpravin.PaneerSelvam@amd.com Signed-off-by: Christian König --- drivers/gpu/drm/selftests/test-drm_buddy.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c index fa997f89522b..913cbd7eae04 100644 --- a/drivers/gpu/drm/selftests/test-drm_buddy.c +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c @@ -902,14 +902,13 @@ err_fini: static int igt_buddy_alloc_limit(void *arg) { - u64 end, size = U64_MAX, start = 0; + u64 size = U64_MAX, start = 0; struct drm_buddy_block *block; unsigned long flags = 0; LIST_HEAD(allocated); struct drm_buddy mm; int err; - size = end = round_down(size, 4096); err = drm_buddy_init(&mm, size, PAGE_SIZE); if (err) return err; @@ -921,7 +920,8 @@ static int igt_buddy_alloc_limit(void *arg) goto out_fini; } - err = drm_buddy_alloc_blocks(&mm, start, end, size, + size = mm.chunk_size << mm.max_order; + err = drm_buddy_alloc_blocks(&mm, start, size, size, PAGE_SIZE, &allocated, flags); if (unlikely(err)) From f9576e36c6b4f070d0b95fd968c1a73fec5a193b Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 3 Mar 2022 14:34:34 -0800 Subject: [PATCH 00076/11454] drm/i915/xehp: Support platforms with CCS engines but no RCS In the past we've always assumed that an RCS engine is present on every platform. However now that we have compute engines there may be platforms that have CCS engines but no RCS, or platforms that are designed to have both, but have the RCS engine fused off. Various engine-centric initialization that only needs to be done a single time for the group of RCS+CCS engines can't rely on being setup with the RCS now; instead we add a I915_ENGINE_FIRST_RENDER_COMPUTE flag that will be assigned to a single engine in the group; whichever engine has this flag will be responsible for some of the general setup (RCU_MODE programming, initialization of certain workarounds, etc.). Signed-off-by: Matt Roper Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220303223435.2793124-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 5 +++++ drivers/gpu/drm/i915/gt/intel_engine_types.h | 2 ++ drivers/gpu/drm/i915/gt/intel_execlists_submission.c | 2 +- drivers/gpu/drm/i915/gt/intel_workarounds.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 2 ++ 7 files changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index e1aa78b20d2d..d26cef970f40 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -434,6 +434,11 @@ static int intel_engine_setup(struct intel_gt *gt, enum intel_engine_id id, if (GRAPHICS_VER(i915) == 12 && engine->class == RENDER_CLASS) engine->props.preempt_timeout_ms = 0; + if ((engine->class == COMPUTE_CLASS && !RCS_MASK(engine->gt) && + __ffs(CCS_MASK(engine->gt)) == engine->instance) || + engine->class == RENDER_CLASS) + engine->flags |= I915_ENGINE_FIRST_RENDER_COMPUTE; + /* features common between engines sharing EUs */ if (engine->class == RENDER_CLASS || engine->class == COMPUTE_CLASS) { engine->flags |= I915_ENGINE_HAS_RCS_REG_STATE; diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 19ff8758e34d..4fbf45a74ec0 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -97,6 +97,7 @@ struct i915_ctx_workarounds { #define I915_MAX_VCS 8 #define I915_MAX_VECS 4 #define I915_MAX_CCS 4 +#define I915_MAX_RCS 1 /* * Engine IDs definitions. @@ -526,6 +527,7 @@ struct intel_engine_cs { #define I915_ENGINE_WANT_FORCED_PREEMPTION BIT(8) #define I915_ENGINE_HAS_RCS_REG_STATE BIT(9) #define I915_ENGINE_HAS_EU_PRIORITY BIT(10) +#define I915_ENGINE_FIRST_RENDER_COMPUTE BIT(11) unsigned int flags; /* diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 3e0c81f06bd0..ba42bede183c 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2911,7 +2911,7 @@ static int execlists_resume(struct intel_engine_cs *engine) enable_execlists(engine); - if (engine->class == RENDER_CLASS) + if (engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) xehp_enable_ccs_engines(engine); return 0; diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index c014b40d2e9f..beca8735bae5 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -2633,7 +2633,7 @@ engine_init_workarounds(struct intel_engine_cs *engine, struct i915_wa_list *wal * to a single RCS/CCS engine's workaround list since * they're reset as part of the general render domain reset. */ - if (engine->class == RENDER_CLASS) + if (engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) general_render_compute_wa_init(engine, wal); if (engine->class == RENDER_CLASS) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 9bb551b83e7a..32c2053f2f08 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -335,7 +335,7 @@ static int guc_mmio_regset_init(struct temp_regset *regset, ret |= GUC_MMIO_REG_ADD(regset, RING_HWS_PGA(base), false); ret |= GUC_MMIO_REG_ADD(regset, RING_IMR(base), false); - if (engine->class == RENDER_CLASS && + if ((engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) && CCS_MASK(engine->gt)) ret |= GUC_MMIO_REG_ADD(regset, GEN12_RCU_MODE, true); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 9d8a271b7a24..9ec03234d2c2 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -3616,7 +3616,7 @@ static int guc_resume(struct intel_engine_cs *engine) setup_hwsp(engine); start_engine(engine); - if (engine->class == RENDER_CLASS) + if (engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) xehp_enable_ccs_engines(engine); return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index d134838b3458..57643639b092 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1237,6 +1237,8 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, ((gt)->info.engine_mask & \ GENMASK(first__ + count__ - 1, first__)) >> first__; \ }) +#define RCS_MASK(gt) \ + ENGINE_INSTANCES_MASK(gt, RCS0, I915_MAX_RCS) #define VDBOX_MASK(gt) \ ENGINE_INSTANCES_MASK(gt, VCS0, I915_MAX_VCS) #define VEBOX_MASK(gt) \ From 18ac067bcbde92518a1fc3c0605d030fc3e3f94b Mon Sep 17 00:00:00 2001 From: Stuart Summers Date: Thu, 3 Mar 2022 14:34:35 -0800 Subject: [PATCH 00077/11454] drm/i915: Add RCS mask to GuC ADS params If RCS is not enumerated, GuC will return invalid parameters. Make sure we do not send RCS supported when we have not enumerated it. Cc: Vinay Belgaumkar Signed-off-by: Stuart Summers Signed-off-by: Matt Roper Reviewed-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20220303223435.2793124-2-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index 32c2053f2f08..acc4a3766dc1 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -433,7 +433,7 @@ static void guc_mmio_reg_state_init(struct intel_guc *guc) static void fill_engine_enable_masks(struct intel_gt *gt, struct iosys_map *info_map) { - info_map_write(info_map, engine_enabled_masks[GUC_RENDER_CLASS], 1); + info_map_write(info_map, engine_enabled_masks[GUC_RENDER_CLASS], RCS_MASK(gt)); info_map_write(info_map, engine_enabled_masks[GUC_COMPUTE_CLASS], CCS_MASK(gt)); info_map_write(info_map, engine_enabled_masks[GUC_BLITTER_CLASS], 1); info_map_write(info_map, engine_enabled_masks[GUC_VIDEO_CLASS], VDBOX_MASK(gt)); From 85f50a373fac7c3c34fec5ebed77852de445d2fa Mon Sep 17 00:00:00 2001 From: Madhumitha Tolakanahalli Pradeep Date: Wed, 23 Feb 2022 14:28:01 -0800 Subject: [PATCH 00078/11454] drm/i915/dmc: Update DMC to v2.16 on ADL-P Changes since v2.14: - Release Notes for v2.15 Fix for corruption issue when DC States are enabled. - Release Notes for v2.16 Fix for cases with flip queue and DC6v are enabled. Signed-off-by: Madhumitha Tolakanahalli Pradeep Reviewed-by: Radhakrishna Sripada Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220223222801.397632-2-madhumitha.tolakanahalli.pradeep@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 133476be6d28..a719c0f379ba 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -47,8 +47,8 @@ #define DISPLAY_VER12_DMC_MAX_FW_SIZE ICL_DMC_MAX_FW_SIZE -#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 14) -#define ADLP_DMC_VERSION_REQUIRED DMC_VERSION(2, 14) +#define ADLP_DMC_PATH DMC_PATH(adlp, 2, 16) +#define ADLP_DMC_VERSION_REQUIRED DMC_VERSION(2, 16) MODULE_FIRMWARE(ADLP_DMC_PATH); #define ADLS_DMC_PATH DMC_PATH(adls, 2, 01) From 50c335f94d71c8b68560abf3fe273962111adcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 21 Feb 2022 13:03:53 +0200 Subject: [PATCH 00079/11454] drm/i915: Move framestart_delay to crtc_state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We need to make framestart_delay dynamic for DRRS on PCH ports. To that end move it into the crtc state. As a bonus we get state check+dump for it. Will also allow us to get rid of the somewhat questionable framestart_delay sanitation code. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220221110356.5532-1-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 40 ++++++++++++++----- .../drm/i915/display/intel_display_types.h | 2 + .../gpu/drm/i915/display/intel_pch_display.c | 15 +++---- drivers/gpu/drm/i915/display/intel_vrr.c | 4 +- drivers/gpu/drm/i915/i915_drv.h | 2 - 5 files changed, 42 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 10d483ce04a7..7b0a87759852 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1866,7 +1866,7 @@ static void hsw_set_frame_start_delay(const struct intel_crtc_state *crtc_state) val = intel_de_read(dev_priv, reg); val &= ~HSW_FRAME_START_DELAY_MASK; - val |= HSW_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + val |= HSW_FRAME_START_DELAY(crtc_state->framestart_delay - 1); intel_de_write(dev_priv, reg, val); } @@ -3244,7 +3244,7 @@ static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) pipeconf |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); - pipeconf |= PIPECONF_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + pipeconf |= PIPECONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1); intel_de_write(dev_priv, PIPECONF(crtc->pipe), pipeconf); intel_de_posting_read(dev_priv, PIPECONF(crtc->pipe)); @@ -3434,6 +3434,8 @@ static bool i9xx_get_pipe_config(struct intel_crtc *crtc, pipe_config->gamma_mode = REG_FIELD_GET(PIPECONF_GAMMA_MODE_MASK_I9XX, tmp); + pipe_config->framestart_delay = REG_FIELD_GET(PIPECONF_FRAME_START_DELAY_MASK, tmp) + 1; + if (IS_CHERRYVIEW(dev_priv)) pipe_config->cgm_mode = intel_de_read(dev_priv, CGM_PIPE_MODE(crtc->pipe)); @@ -3559,7 +3561,7 @@ static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state) val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); - val |= PIPECONF_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + val |= PIPECONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1); intel_de_write(dev_priv, PIPECONF(pipe), val); intel_de_posting_read(dev_priv, PIPECONF(pipe)); @@ -3846,6 +3848,8 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc, pipe_config->gamma_mode = REG_FIELD_GET(PIPECONF_GAMMA_MODE_MASK_ILK, tmp); + pipe_config->framestart_delay = REG_FIELD_GET(PIPECONF_FRAME_START_DELAY_MASK, tmp) + 1; + pipe_config->csc_mode = intel_de_read(dev_priv, PIPE_CSC_MODE(crtc->pipe)); @@ -4281,6 +4285,15 @@ static bool hsw_get_pipe_config(struct intel_crtc *crtc, pipe_config->pixel_multiplier = 1; } + if (!transcoder_is_dsi(pipe_config->cpu_transcoder)) { + tmp = intel_de_read(dev_priv, CHICKEN_TRANS(pipe_config->cpu_transcoder)); + + pipe_config->framestart_delay = REG_FIELD_GET(HSW_FRAME_START_DELAY_MASK, tmp) + 1; + } else { + /* no idea if this is correct */ + pipe_config->framestart_delay = 1; + } + out: intel_display_power_put_all_in_set(dev_priv, &power_domain_set); @@ -5318,6 +5331,9 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, &pipe_config->dp_m2_n2); } + drm_dbg_kms(&dev_priv->drm, "framestart delay: %d\n", + pipe_config->framestart_delay); + drm_dbg_kms(&dev_priv->drm, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", pipe_config->has_audio, pipe_config->has_infoframe, @@ -5666,6 +5682,8 @@ intel_modeset_pipe_config(struct intel_atomic_state *state, pipe_config->cpu_transcoder = (enum transcoder) to_intel_crtc(crtc)->pipe; + pipe_config->framestart_delay = 1; + /* * Sanitize sync polarity flags based on requested ones. If neither * positive or negative polarity is requested, treat this as meaning @@ -6203,6 +6221,8 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(output_types); + PIPE_CONF_CHECK_I(framestart_delay); + PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay); PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal); PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hblank_start); @@ -9612,8 +9632,6 @@ int intel_modeset_init_noirq(struct drm_i915_private *i915) i915->flip_wq = alloc_workqueue("i915_flip", WQ_HIGHPRI | WQ_UNBOUND, WQ_UNBOUND_MAX_ACTIVE); - i915->framestart_delay = 1; /* 1-4 */ - i915->window2_delay = 0; /* No DSB so no window2 delay */ intel_mode_config_init(i915); @@ -9917,12 +9935,14 @@ static bool has_pch_trancoder(struct drm_i915_private *dev_priv, (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A); } -static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc_state) +static void intel_sanitize_frame_start_delay(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + crtc_state->framestart_delay = 1; + if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) { i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder); @@ -9933,7 +9953,7 @@ static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc val = intel_de_read(dev_priv, reg); val &= ~HSW_FRAME_START_DELAY_MASK; - val |= HSW_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + val |= HSW_FRAME_START_DELAY(crtc_state->framestart_delay - 1); intel_de_write(dev_priv, reg, val); } else { i915_reg_t reg = PIPECONF(cpu_transcoder); @@ -9941,7 +9961,7 @@ static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc val = intel_de_read(dev_priv, reg); val &= ~PIPECONF_FRAME_START_DELAY_MASK; - val |= PIPECONF_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + val |= PIPECONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1); intel_de_write(dev_priv, reg, val); } @@ -9954,7 +9974,7 @@ static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc val = intel_de_read(dev_priv, reg); val &= ~TRANS_FRAME_START_DELAY_MASK; - val |= TRANS_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + val |= TRANS_FRAME_START_DELAY(crtc_state->framestart_delay - 1); intel_de_write(dev_priv, reg, val); } else { enum pipe pch_transcoder = intel_crtc_pch_transcoder(crtc); @@ -9963,7 +9983,7 @@ static void intel_sanitize_frame_start_delay(const struct intel_crtc_state *crtc val = intel_de_read(dev_priv, reg); val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; - val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1); intel_de_write(dev_priv, reg, val); } } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 776b3e6662f2..593aa7444a49 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1154,6 +1154,8 @@ struct intel_crtc_state { /* bitmask of planes that will be updated during the commit */ u8 update_planes; + u8 framestart_delay; /* 1-4 */ + struct { u32 enable; u32 gcp; diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 9192769e3337..00232dab217d 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -181,7 +181,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) val |= TRANS_CHICKEN2_TIMING_OVERRIDE; /* Configure frame start delay to match the CPU */ val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; - val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1); intel_de_write(dev_priv, reg, val); } @@ -192,7 +192,7 @@ static void ilk_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) if (HAS_PCH_IBX(dev_priv)) { /* Configure frame start delay to match the CPU */ val &= ~TRANS_FRAME_START_DELAY_MASK; - val |= TRANS_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + val |= TRANS_FRAME_START_DELAY(crtc_state->framestart_delay - 1); /* * Make the BPC in transcoder be consistent with @@ -466,9 +466,11 @@ void ilk_pch_get_config(struct intel_crtc_state *crtc_state) ilk_pch_clock_get(crtc_state); } -static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, - enum transcoder cpu_transcoder) +static void lpt_enable_pch_transcoder(const struct intel_crtc_state *crtc_state) { + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; u32 val, pipeconf_val; /* FDI must be feeding us bits for PCH ports */ @@ -480,7 +482,7 @@ static void lpt_enable_pch_transcoder(struct drm_i915_private *dev_priv, val |= TRANS_CHICKEN2_TIMING_OVERRIDE; /* Configure frame start delay to match the CPU */ val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; - val |= TRANS_CHICKEN2_FRAME_START_DELAY(dev_priv->framestart_delay - 1); + val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1); intel_de_write(dev_priv, TRANS_CHICKEN2(PIPE_A), val); val = TRANS_ENABLE; @@ -521,7 +523,6 @@ void lpt_pch_enable(struct intel_atomic_state *state, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct intel_crtc_state *crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; assert_pch_transcoder_disabled(dev_priv, PIPE_A); @@ -530,7 +531,7 @@ void lpt_pch_enable(struct intel_atomic_state *state, /* Set transcoder timing. */ ilk_pch_transcoder_set_timings(crtc_state, PIPE_A); - lpt_enable_pch_transcoder(dev_priv, cpu_transcoder); + lpt_enable_pch_transcoder(crtc_state); } void lpt_pch_disable(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_vrr.c b/drivers/gpu/drm/i915/display/intel_vrr.c index 139e8936edc5..396f2f994fa0 100644 --- a/drivers/gpu/drm/i915/display/intel_vrr.c +++ b/drivers/gpu/drm/i915/display/intel_vrr.c @@ -69,9 +69,9 @@ static int intel_vrr_vblank_exit_length(const struct intel_crtc_state *crtc_stat /* The hw imposes the extra scanline before frame start */ if (DISPLAY_VER(i915) >= 13) - return crtc_state->vrr.guardband + i915->framestart_delay + 1; + return crtc_state->vrr.guardband + crtc_state->framestart_delay + 1; else - return crtc_state->vrr.pipeline_full + i915->framestart_delay + 1; + return crtc_state->vrr.pipeline_full + crtc_state->framestart_delay + 1; } int intel_vrr_vmin_vblank_start(const struct intel_crtc_state *crtc_state) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b9f9168280e8..29cc6f7bebf2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -814,8 +814,6 @@ struct drm_i915_private { struct file *mmap_singleton; } gem; - u8 framestart_delay; - /* Window2 specifies time required to program DSB (Window2) in number of scan lines */ u8 window2_delay; From 6561a9d6381355df23b1ef1980609124a628eff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 21 Feb 2022 13:03:54 +0200 Subject: [PATCH 00080/11454] drm/i915: Remove framestart_delay sanitation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we track framestart_delay in the crtc state with readout and state checker support we can remove the explicit framestart_delay sanitation code. Also I'm not convinced reprogramming this while the pipe is running is even valid. CHICKEN_TRANS (hsw+) and TRANS_CHICKEN2 (cpt+) docs at least make no mention of double buffering which seems to imply that live reprogramming is not supported. On older platforms PIPECONF and PCH_TRANSCONF (ibx) are double buffered though, so might be that we could do this on the older platforms. But doesn't really make sense to special case old platforms for this. So from now on if the BIOS has misprogrammed this we shall simply do a full modeset at boot to fix it up. Such systems will of course lose fastboot, but I think less code (and less uncertainty what reprogramming this on a running pipe will even do) outweighs that. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220221110356.5532-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 56 -------------------- 1 file changed, 56 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7b0a87759852..ad4a631833d8 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -9935,59 +9935,6 @@ static bool has_pch_trancoder(struct drm_i915_private *dev_priv, (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A); } -static void intel_sanitize_frame_start_delay(struct intel_crtc_state *crtc_state) -{ - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; - - crtc_state->framestart_delay = 1; - - if (DISPLAY_VER(dev_priv) >= 9 || - IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv)) { - i915_reg_t reg = CHICKEN_TRANS(cpu_transcoder); - u32 val; - - if (transcoder_is_dsi(cpu_transcoder)) - return; - - val = intel_de_read(dev_priv, reg); - val &= ~HSW_FRAME_START_DELAY_MASK; - val |= HSW_FRAME_START_DELAY(crtc_state->framestart_delay - 1); - intel_de_write(dev_priv, reg, val); - } else { - i915_reg_t reg = PIPECONF(cpu_transcoder); - u32 val; - - val = intel_de_read(dev_priv, reg); - val &= ~PIPECONF_FRAME_START_DELAY_MASK; - val |= PIPECONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1); - intel_de_write(dev_priv, reg, val); - } - - if (!crtc_state->has_pch_encoder) - return; - - if (HAS_PCH_IBX(dev_priv)) { - i915_reg_t reg = PCH_TRANSCONF(crtc->pipe); - u32 val; - - val = intel_de_read(dev_priv, reg); - val &= ~TRANS_FRAME_START_DELAY_MASK; - val |= TRANS_FRAME_START_DELAY(crtc_state->framestart_delay - 1); - intel_de_write(dev_priv, reg, val); - } else { - enum pipe pch_transcoder = intel_crtc_pch_transcoder(crtc); - i915_reg_t reg = TRANS_CHICKEN2(pch_transcoder); - u32 val; - - val = intel_de_read(dev_priv, reg); - val &= ~TRANS_CHICKEN2_FRAME_START_DELAY_MASK; - val |= TRANS_CHICKEN2_FRAME_START_DELAY(crtc_state->framestart_delay - 1); - intel_de_write(dev_priv, reg, val); - } -} - static void intel_sanitize_crtc(struct intel_crtc *crtc, struct drm_modeset_acquire_ctx *ctx) { @@ -9998,9 +9945,6 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, if (crtc_state->hw.active) { struct intel_plane *plane; - /* Clear any frame start delays used for debugging left by the BIOS */ - intel_sanitize_frame_start_delay(crtc_state); - /* Disable everything but the primary plane */ for_each_intel_plane_on_crtc(dev, crtc, plane) { const struct intel_plane_state *plane_state = From 108a112f5ebaf9481af805a32167f8ce805e3608 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 21 Feb 2022 13:03:55 +0200 Subject: [PATCH 00081/11454] drm/i915: Relocate ibx pch port sanitation code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the ibx pch port sanitation code into intel_pch_display.c where it now belongs. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220221110356.5532-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 63 +---------------- .../gpu/drm/i915/display/intel_pch_display.c | 67 +++++++++++++++++++ .../gpu/drm/i915/display/intel_pch_display.h | 3 + 3 files changed, 71 insertions(+), 62 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index ad4a631833d8..b00084dc53cb 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -10362,66 +10362,6 @@ static void intel_early_display_was(struct drm_i915_private *dev_priv) } } -static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv, - enum port port, i915_reg_t hdmi_reg) -{ - u32 val = intel_de_read(dev_priv, hdmi_reg); - - if (val & SDVO_ENABLE || - (val & SDVO_PIPE_SEL_MASK) == SDVO_PIPE_SEL(PIPE_A)) - return; - - drm_dbg_kms(&dev_priv->drm, - "Sanitizing transcoder select for HDMI %c\n", - port_name(port)); - - val &= ~SDVO_PIPE_SEL_MASK; - val |= SDVO_PIPE_SEL(PIPE_A); - - intel_de_write(dev_priv, hdmi_reg, val); -} - -static void ibx_sanitize_pch_dp_port(struct drm_i915_private *dev_priv, - enum port port, i915_reg_t dp_reg) -{ - u32 val = intel_de_read(dev_priv, dp_reg); - - if (val & DP_PORT_EN || - (val & DP_PIPE_SEL_MASK) == DP_PIPE_SEL(PIPE_A)) - return; - - drm_dbg_kms(&dev_priv->drm, - "Sanitizing transcoder select for DP %c\n", - port_name(port)); - - val &= ~DP_PIPE_SEL_MASK; - val |= DP_PIPE_SEL(PIPE_A); - - intel_de_write(dev_priv, dp_reg, val); -} - -static void ibx_sanitize_pch_ports(struct drm_i915_private *dev_priv) -{ - /* - * The BIOS may select transcoder B on some of the PCH - * ports even it doesn't enable the port. This would trip - * assert_pch_dp_disabled() and assert_pch_hdmi_disabled(). - * Sanitize the transcoder select bits to prevent that. We - * assume that the BIOS never actually enabled the port, - * because if it did we'd actually have to toggle the port - * on and back off to make the transcoder A select stick - * (see. intel_dp_link_down(), intel_disable_hdmi(), - * intel_disable_sdvo()). - */ - ibx_sanitize_pch_dp_port(dev_priv, PORT_B, PCH_DP_B); - ibx_sanitize_pch_dp_port(dev_priv, PORT_C, PCH_DP_C); - ibx_sanitize_pch_dp_port(dev_priv, PORT_D, PCH_DP_D); - - /* PCH SDVOB multiplex with HDMIB */ - ibx_sanitize_pch_hdmi_port(dev_priv, PORT_B, PCH_HDMIB); - ibx_sanitize_pch_hdmi_port(dev_priv, PORT_C, PCH_HDMIC); - ibx_sanitize_pch_hdmi_port(dev_priv, PORT_D, PCH_HDMID); -} /* Scan out the current hw modeset state, * and sanitizes it to the current state @@ -10443,8 +10383,7 @@ intel_modeset_setup_hw_state(struct drm_device *dev, /* HW state is read out, now we need to sanitize this mess. */ get_encoder_power_domains(dev_priv); - if (HAS_PCH_IBX(dev_priv)) - ibx_sanitize_pch_ports(dev_priv); + intel_pch_sanitize(dev_priv); /* * intel_sanitize_plane_mapping() may need to do vblank diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 00232dab217d..43e717f4f8e7 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -88,6 +88,67 @@ static void assert_pch_transcoder_disabled(struct drm_i915_private *dev_priv, pipe_name(pipe)); } +static void ibx_sanitize_pch_hdmi_port(struct drm_i915_private *dev_priv, + enum port port, i915_reg_t hdmi_reg) +{ + u32 val = intel_de_read(dev_priv, hdmi_reg); + + if (val & SDVO_ENABLE || + (val & SDVO_PIPE_SEL_MASK) == SDVO_PIPE_SEL(PIPE_A)) + return; + + drm_dbg_kms(&dev_priv->drm, + "Sanitizing transcoder select for HDMI %c\n", + port_name(port)); + + val &= ~SDVO_PIPE_SEL_MASK; + val |= SDVO_PIPE_SEL(PIPE_A); + + intel_de_write(dev_priv, hdmi_reg, val); +} + +static void ibx_sanitize_pch_dp_port(struct drm_i915_private *dev_priv, + enum port port, i915_reg_t dp_reg) +{ + u32 val = intel_de_read(dev_priv, dp_reg); + + if (val & DP_PORT_EN || + (val & DP_PIPE_SEL_MASK) == DP_PIPE_SEL(PIPE_A)) + return; + + drm_dbg_kms(&dev_priv->drm, + "Sanitizing transcoder select for DP %c\n", + port_name(port)); + + val &= ~DP_PIPE_SEL_MASK; + val |= DP_PIPE_SEL(PIPE_A); + + intel_de_write(dev_priv, dp_reg, val); +} + +static void ibx_sanitize_pch_ports(struct drm_i915_private *dev_priv) +{ + /* + * The BIOS may select transcoder B on some of the PCH + * ports even it doesn't enable the port. This would trip + * assert_pch_dp_disabled() and assert_pch_hdmi_disabled(). + * Sanitize the transcoder select bits to prevent that. We + * assume that the BIOS never actually enabled the port, + * because if it did we'd actually have to toggle the port + * on and back off to make the transcoder A select stick + * (see. intel_dp_link_down(), intel_disable_hdmi(), + * intel_disable_sdvo()). + */ + ibx_sanitize_pch_dp_port(dev_priv, PORT_B, PCH_DP_B); + ibx_sanitize_pch_dp_port(dev_priv, PORT_C, PCH_DP_C); + ibx_sanitize_pch_dp_port(dev_priv, PORT_D, PCH_DP_D); + + /* PCH SDVOB multiplex with HDMIB */ + ibx_sanitize_pch_hdmi_port(dev_priv, PORT_B, PCH_HDMIB); + ibx_sanitize_pch_hdmi_port(dev_priv, PORT_C, PCH_HDMIC); + ibx_sanitize_pch_hdmi_port(dev_priv, PORT_D, PCH_HDMID); +} + static void intel_pch_transcoder_set_m1_n1(struct intel_crtc *crtc, const struct intel_link_m_n *m_n) { @@ -564,3 +625,9 @@ void lpt_pch_get_config(struct intel_crtc_state *crtc_state) crtc_state->hw.adjusted_mode.crtc_clock = lpt_get_iclkip(dev_priv); } + +void intel_pch_sanitize(struct drm_i915_private *i915) +{ + if (HAS_PCH_IBX(i915)) + ibx_sanitize_pch_ports(i915); +} diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h index 749473d99320..4ef033bb5807 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.h +++ b/drivers/gpu/drm/i915/display/intel_pch_display.h @@ -6,6 +6,7 @@ #ifndef _INTEL_PCH_DISPLAY_H_ #define _INTEL_PCH_DISPLAY_H_ +struct drm_i915_private; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; @@ -32,4 +33,6 @@ void intel_pch_transcoder_get_m1_n1(struct intel_crtc *crtc, void intel_pch_transcoder_get_m2_n2(struct intel_crtc *crtc, struct intel_link_m_n *m_n); +void intel_pch_sanitize(struct drm_i915_private *i915); + #endif From a97087026d0ef0cb1a915f94c78bca5dbabdb201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 21 Feb 2022 13:03:56 +0200 Subject: [PATCH 00082/11454] drm/i915: Relocate a few more pch transcoder bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move intel_crtc_pch_transcoder() and has_pch_trancoder() to a more appropritate place (intel_pch_display.c). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220221110356.5532-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 19 +------------------ drivers/gpu/drm/i915/display/intel_display.h | 1 - drivers/gpu/drm/i915/display/intel_dp.c | 1 + .../gpu/drm/i915/display/intel_pch_display.c | 17 +++++++++++++++++ .../gpu/drm/i915/display/intel_pch_display.h | 7 +++++++ 5 files changed, 26 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index b00084dc53cb..92b9781bcf2f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -519,16 +519,6 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv, expected_mask); } -enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - - if (HAS_PCH_LPT(dev_priv)) - return PIPE_A; - else - return crtc->pipe; -} - void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); @@ -9928,13 +9918,6 @@ static struct intel_connector *intel_encoder_find_connector(struct intel_encoder return NULL; } -static bool has_pch_trancoder(struct drm_i915_private *dev_priv, - enum pipe pch_transcoder) -{ - return HAS_PCH_IBX(dev_priv) || HAS_PCH_CPT(dev_priv) || - (HAS_PCH_LPT_H(dev_priv) && pch_transcoder == PIPE_A); -} - static void intel_sanitize_crtc(struct intel_crtc *crtc, struct drm_modeset_acquire_ctx *ctx) { @@ -9989,7 +9972,7 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, * PCH transcoders B and C would prevent enabling the south * error interrupt (see cpt_can_enable_serr_int()). */ - if (has_pch_trancoder(dev_priv, crtc->pipe)) + if (intel_has_pch_trancoder(dev_priv, crtc->pipe)) crtc->pch_fifo_underrun_disabled = true; } } diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 11d6134c53c8..8513703086b7 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -565,7 +565,6 @@ void intel_enable_transcoder(const struct intel_crtc_state *new_crtc_state); void intel_disable_transcoder(const struct intel_crtc_state *old_crtc_state); void i830_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); void i830_disable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe); -enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc); int vlv_get_hpll_vco(struct drm_i915_private *dev_priv); int vlv_get_cck_clock(struct drm_i915_private *dev_priv, const char *name, u32 reg, int ref_freq); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index d6ef33096bb6..eab2d1f5ec59 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -68,6 +68,7 @@ #include "intel_lspcon.h" #include "intel_lvds.h" #include "intel_panel.h" +#include "intel_pch_display.h" #include "intel_pps.h" #include "intel_psr.h" #include "intel_tc.h" diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.c b/drivers/gpu/drm/i915/display/intel_pch_display.c index 43e717f4f8e7..837152dca063 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.c +++ b/drivers/gpu/drm/i915/display/intel_pch_display.c @@ -14,6 +14,23 @@ #include "intel_pps.h" #include "intel_sdvo.h" +bool intel_has_pch_trancoder(struct drm_i915_private *i915, + enum pipe pch_transcoder) +{ + return HAS_PCH_IBX(i915) || HAS_PCH_CPT(i915) || + (HAS_PCH_LPT_H(i915) && pch_transcoder == PIPE_A); +} + +enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + if (HAS_PCH_LPT(i915)) + return PIPE_A; + else + return crtc->pipe; +} + static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv, enum pipe pipe, enum port port, i915_reg_t dp_reg) diff --git a/drivers/gpu/drm/i915/display/intel_pch_display.h b/drivers/gpu/drm/i915/display/intel_pch_display.h index 4ef033bb5807..41a63413cb3d 100644 --- a/drivers/gpu/drm/i915/display/intel_pch_display.h +++ b/drivers/gpu/drm/i915/display/intel_pch_display.h @@ -6,12 +6,19 @@ #ifndef _INTEL_PCH_DISPLAY_H_ #define _INTEL_PCH_DISPLAY_H_ +#include + +enum pipe; struct drm_i915_private; struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; struct intel_link_m_n; +bool intel_has_pch_trancoder(struct drm_i915_private *i915, + enum pipe pch_transcoder); +enum pipe intel_crtc_pch_transcoder(struct intel_crtc *crtc); + void ilk_pch_pre_enable(struct intel_atomic_state *state, struct intel_crtc *crtc); void ilk_pch_enable(struct intel_atomic_state *state, From 4a1e1758b2db6c9dbbbf138abb1c1df4e7a3e30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 1 Mar 2022 19:31:18 +0200 Subject: [PATCH 00083/11454] drm/i915: Nuke skl_wrpll_context_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can trivially replace skl_wrpll_context_init() with a single designated initializer. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220301173128.6988-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index f10eae7a75c6..0a7687fd8096 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -1333,13 +1333,6 @@ struct skl_wrpll_context { unsigned int p; /* chosen divider */ }; -static void skl_wrpll_context_init(struct skl_wrpll_context *ctx) -{ - memset(ctx, 0, sizeof(*ctx)); - - ctx->min_deviation = U64_MAX; -} - /* DCO freq must be within +1%/-6% of the DCO central freq */ #define SKL_DCO_MAX_PDEVIATION 100 #define SKL_DCO_MAX_NDEVIATION 600 @@ -1522,12 +1515,12 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, { even_dividers, ARRAY_SIZE(even_dividers) }, { odd_dividers, ARRAY_SIZE(odd_dividers) }, }; - struct skl_wrpll_context ctx; + struct skl_wrpll_context ctx = { + .min_deviation = U64_MAX, + }; unsigned int dco, d, i; unsigned int p0, p1, p2; - skl_wrpll_context_init(&ctx); - for (d = 0; d < ARRAY_SIZE(dividers); d++) { for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) { for (i = 0; i < dividers[d].n_dividers; i++) { From fe70b262e781de9949a6c26b50767867d9da71b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 1 Mar 2022 19:31:19 +0200 Subject: [PATCH 00084/11454] drm/i915: Move a bunch of stuff into rodata from the stack MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Toss a bunch if constants into .rodata drom the stack. Also shrink the types of some of the arrays to reduce the size. bloat-o-meter -c intel_dpll_mgr.o: add/remove: 0/0 grow/shrink: 0/2 up/down: 0/-86 (-86) Function old new delta icl_get_dplls 3393 3372 -21 skl_get_dpll 2069 2004 -65 Total: Before=28029, After=27943, chg -0.31% add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0) Data old new delta Total: Before=17, After=17, chg +0.00% add/remove: 2/0 grow/shrink: 0/2 up/down: 28/-129 (-101) RO Data old new delta dco_central_freq - 24 +24 div1_vals - 4 +4 odd_dividers 28 7 -21 even_dividers 144 36 -108 Total: Before=3600, After=3499, chg -2.81% Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220301173128.6988-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 0a7687fd8096..6250a42517a6 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -1498,18 +1498,17 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, int ref_clock, struct skl_wrpll_params *wrpll_params) { - u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */ - u64 dco_central_freq[3] = { 8400000000ULL, - 9000000000ULL, - 9600000000ULL }; - static const int even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, - 24, 28, 30, 32, 36, 40, 42, 44, - 48, 52, 54, 56, 60, 64, 66, 68, - 70, 72, 76, 78, 80, 84, 88, 90, - 92, 96, 98 }; - static const int odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 }; + static const u64 dco_central_freq[3] = { 8400000000ULL, + 9000000000ULL, + 9600000000ULL }; + static const u8 even_dividers[] = { 4, 6, 8, 10, 12, 14, 16, 18, 20, + 24, 28, 30, 32, 36, 40, 42, 44, + 48, 52, 54, 56, 60, 64, 66, 68, + 70, 72, 76, 78, 80, 84, 88, 90, + 92, 96, 98 }; + static const u8 odd_dividers[] = { 3, 5, 7, 9, 15, 21, 35 }; static const struct { - const int *list; + const u8 *list; int n_dividers; } dividers[] = { { even_dividers, ARRAY_SIZE(even_dividers) }, @@ -1520,6 +1519,7 @@ skl_ddi_calculate_wrpll(int clock /* in Hz */, }; unsigned int dco, d, i; unsigned int p0, p1, p2; + u64 afe_clock = clock * 5; /* AFE Clock is 5x Pixel clock */ for (d = 0; d < ARRAY_SIZE(dividers); d++) { for (dco = 0; dco < ARRAY_SIZE(dco_central_freq); dco++) { @@ -2754,8 +2754,8 @@ static bool icl_mg_pll_find_divisors(int clock_khz, bool is_dp, bool use_ssc, struct intel_dpll_hw_state *state, bool is_dkl) { + static const u8 div1_vals[] = { 7, 5, 3, 2 }; u32 dco_min_freq, dco_max_freq; - int div1_vals[] = {7, 5, 3, 2}; unsigned int i; int div2; From 2dfac87c7c4ae55cf49d656b77a06d85414f0344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 1 Mar 2022 19:31:20 +0200 Subject: [PATCH 00085/11454] drm/i915: Clean up some struct/array initializers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the simple '= {}' form to initialize empty arrays/structs. Also add some missing whitespace. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220301173128.6988-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 6250a42517a6..566b0066d6fd 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -835,7 +835,7 @@ hsw_ddi_calculate_wrpll(int clock /* in Hz */, { u64 freq2k; unsigned p, n2, r2; - struct hsw_wrpll_rnp best = { 0, 0, 0 }; + struct hsw_wrpll_rnp best = {}; unsigned budget; freq2k = clock / 100; @@ -1570,8 +1570,8 @@ skip_remaining_dividers: static bool skl_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); + struct skl_wrpll_params wrpll_params = {}; u32 ctrl1, cfgcr1, cfgcr2; - struct skl_wrpll_params wrpll_params = { 0, }; /* * See comment in intel_dpll_hw_state to understand why we always use 0 @@ -2098,13 +2098,13 @@ struct bxt_clk_div { /* pre-calculated values for DP linkrates */ static const struct bxt_clk_div bxt_dp_clk_val[] = { - {162000, 4, 2, 32, 1677722, 1, 1}, - {270000, 4, 1, 27, 0, 0, 1}, - {540000, 2, 1, 27, 0, 0, 1}, - {216000, 3, 2, 32, 1677722, 1, 1}, - {243000, 4, 1, 24, 1258291, 1, 1}, - {324000, 4, 1, 32, 1677722, 1, 1}, - {432000, 3, 1, 32, 1677722, 1, 1} + { 162000, 4, 2, 32, 1677722, 1, 1 }, + { 270000, 4, 1, 27, 0, 0, 1 }, + { 540000, 2, 1, 27, 0, 0, 1 }, + { 216000, 3, 2, 32, 1677722, 1, 1 }, + { 243000, 4, 1, 24, 1258291, 1, 1 }, + { 324000, 4, 1, 32, 1677722, 1, 1 }, + { 432000, 3, 1, 32, 1677722, 1, 1 } }; static bool From 392f662b930dcadede4e184fc4a40c9db953a2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 1 Mar 2022 19:31:22 +0200 Subject: [PATCH 00086/11454] drm/i915: Remove bxt m2_frac_en MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the pointless m2_frac_en from bxt_clk_div. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220301173128.6988-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 566b0066d6fd..c1d857616a34 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2090,7 +2090,6 @@ struct bxt_clk_div { u32 p2; u32 m2_int; u32 m2_frac; - bool m2_frac_en; u32 n; int vco; @@ -2098,13 +2097,13 @@ struct bxt_clk_div { /* pre-calculated values for DP linkrates */ static const struct bxt_clk_div bxt_dp_clk_val[] = { - { 162000, 4, 2, 32, 1677722, 1, 1 }, - { 270000, 4, 1, 27, 0, 0, 1 }, - { 540000, 2, 1, 27, 0, 0, 1 }, - { 216000, 3, 2, 32, 1677722, 1, 1 }, - { 243000, 4, 1, 24, 1258291, 1, 1 }, - { 324000, 4, 1, 32, 1677722, 1, 1 }, - { 432000, 3, 1, 32, 1677722, 1, 1 } + { 162000, 4, 2, 32, 1677722, 1 }, + { 270000, 4, 1, 27, 0, 1 }, + { 540000, 2, 1, 27, 0, 1 }, + { 216000, 3, 2, 32, 1677722, 1 }, + { 243000, 4, 1, 24, 1258291, 1 }, + { 324000, 4, 1, 32, 1677722, 1 }, + { 432000, 3, 1, 32, 1677722, 1 } }; static bool @@ -2133,7 +2132,6 @@ bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state, clk_div->n = best_clock.n; clk_div->m2_int = best_clock.m2 >> 22; clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1); - clk_div->m2_frac_en = clk_div->m2_frac != 0; clk_div->vco = best_clock.vco; @@ -2206,7 +2204,7 @@ static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n); dpll_hw_state->pll2 = clk_div->m2_frac; - if (clk_div->m2_frac_en) + if (clk_div->m2_frac) dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE; dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef); From 0fa1d65e7dda66f12f703b2f00146d836211acc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 1 Mar 2022 19:31:23 +0200 Subject: [PATCH 00087/11454] drm/i915: Use designated initializers for bxt_dp_clk_val[] MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use designated initializers to make it clear what is what, and to decouple us from the specific ordering of the members. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220301173128.6988-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index c1d857616a34..4595795d694f 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2097,13 +2097,13 @@ struct bxt_clk_div { /* pre-calculated values for DP linkrates */ static const struct bxt_clk_div bxt_dp_clk_val[] = { - { 162000, 4, 2, 32, 1677722, 1 }, - { 270000, 4, 1, 27, 0, 1 }, - { 540000, 2, 1, 27, 0, 1 }, - { 216000, 3, 2, 32, 1677722, 1 }, - { 243000, 4, 1, 24, 1258291, 1 }, - { 324000, 4, 1, 32, 1677722, 1 }, - { 432000, 3, 1, 32, 1677722, 1 } + { .clock = 162000, .p1 = 4, .p2 = 2, .m2_int = 32, .m2_frac = 1677722, .n = 1, }, + { .clock = 270000, .p1 = 4, .p2 = 1, .m2_int = 27, .m2_frac = 0, .n = 1, }, + { .clock = 540000, .p1 = 2, .p2 = 1, .m2_int = 27, .m2_frac = 0, .n = 1, }, + { .clock = 216000, .p1 = 3, .p2 = 2, .m2_int = 32, .m2_frac = 1677722, .n = 1, }, + { .clock = 243000, .p1 = 4, .p2 = 1, .m2_int = 24, .m2_frac = 1258291, .n = 1, }, + { .clock = 324000, .p1 = 4, .p2 = 1, .m2_int = 32, .m2_frac = 1677722, .n = 1, }, + { .clock = 432000, .p1 = 3, .p2 = 1, .m2_int = 32, .m2_frac = 1677722, .n = 1, }, }; static bool From 26111a161ab56e7033d3b3086270c5a1dcfe0f2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:12 +0200 Subject: [PATCH 00088/11454] drm/i915: Start tracking PIPESRC as a drm_rect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of just having the pipe_src_{w,h} let's use a full drm_rect for it. This will be particularly useful to astract away some bigjoiner details. v2: No hweight() stuff yet Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-11-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- .../gpu/drm/i915/display/intel_atomic_plane.c | 15 ++-- drivers/gpu/drm/i915/display/intel_cursor.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 55 ++++++++++----- .../drm/i915/display/intel_display_debugfs.c | 4 +- .../drm/i915/display/intel_display_types.h | 2 +- drivers/gpu/drm/i915/display/intel_overlay.c | 12 ++-- drivers/gpu/drm/i915/display/intel_panel.c | 70 +++++++++---------- drivers/gpu/drm/i915/display/skl_scaler.c | 12 ++-- .../drm/i915/display/skl_universal_plane.c | 2 +- 9 files changed, 96 insertions(+), 78 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 5712688232fb..0eae08e389c5 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -802,8 +802,8 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, struct drm_framebuffer *fb = plane_state->hw.fb; struct drm_rect *src = &plane_state->uapi.src; struct drm_rect *dst = &plane_state->uapi.dst; + const struct drm_rect *clip = &crtc_state->pipe_src; unsigned int rotation = plane_state->hw.rotation; - struct drm_rect clip = {}; int hscale, vscale; if (!fb) { @@ -823,28 +823,23 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, return -ERANGE; } - if (crtc_state->hw.enable) { - clip.x2 = crtc_state->pipe_src_w; - clip.y2 = crtc_state->pipe_src_h; - } - /* right side of the image is on the slave crtc, adjust dst to match */ if (intel_crtc_is_bigjoiner_slave(crtc_state)) - drm_rect_translate(dst, -crtc_state->pipe_src_w, 0); + drm_rect_translate(dst, -drm_rect_width(&crtc_state->pipe_src), 0); /* * FIXME: This might need further adjustment for seamless scaling * with phase information, for the 2p2 and 2p1 scenarios. */ - plane_state->uapi.visible = drm_rect_clip_scaled(src, dst, &clip); + plane_state->uapi.visible = drm_rect_clip_scaled(src, dst, clip); drm_rect_rotate_inv(src, fb->width << 16, fb->height << 16, rotation); if (!can_position && plane_state->uapi.visible && - !drm_rect_equals(dst, &clip)) { + !drm_rect_equals(dst, clip)) { drm_dbg_kms(&i915->drm, "Plane must cover entire CRTC\n"); drm_rect_debug_print("dst: ", dst, false); - drm_rect_debug_print("clip: ", &clip, false); + drm_rect_debug_print("clip: ", clip, false); return -EINVAL; } diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 57ef9403f4e9..9026f3fbf9e5 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -154,7 +154,7 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, plane_state->uapi.dst = dst; if (intel_crtc_is_bigjoiner_slave(crtc_state)) drm_rect_translate(&plane_state->uapi.dst, - -crtc_state->pipe_src_w, 0); + -drm_rect_width(&crtc_state->pipe_src), 0); ret = intel_cursor_check_surface(plane_state); if (ret) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 92b9781bcf2f..e019023b8f3a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -2675,8 +2675,8 @@ static u32 ilk_pipe_pixel_rate(const struct intel_crtc_state *crtc_state) return pixel_rate; drm_rect_init(&src, 0, 0, - crtc_state->pipe_src_w << 16, - crtc_state->pipe_src_h << 16); + drm_rect_width(&crtc_state->pipe_src) << 16, + drm_rect_height(&crtc_state->pipe_src) << 16); return intel_adjusted_rate(&src, &crtc_state->pch_pfit.dst, pixel_rate); @@ -2780,8 +2780,8 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state /* Populate the "user" mode with full numbers */ drm_mode_copy(mode, pipe_mode); intel_mode_from_crtc_timings(mode, mode); - mode->hdisplay = crtc_state->pipe_src_w << crtc_state->bigjoiner; - mode->vdisplay = crtc_state->pipe_src_h; + mode->hdisplay = drm_rect_width(&crtc_state->pipe_src) << crtc_state->bigjoiner; + mode->vdisplay = drm_rect_height(&crtc_state->pipe_src); /* Derive per-pipe timings in case bigjoiner is used */ intel_bigjoiner_adjust_timings(crtc_state, pipe_mode); @@ -2798,13 +2798,26 @@ static void intel_encoder_get_config(struct intel_encoder *encoder, intel_crtc_readout_derived_state(crtc_state); } +static void intel_bigjoiner_compute_pipe_src(struct intel_crtc_state *crtc_state) +{ + int width, height; + + if (!crtc_state->bigjoiner) + return; + + width = drm_rect_width(&crtc_state->pipe_src); + height = drm_rect_height(&crtc_state->pipe_src); + + drm_rect_init(&crtc_state->pipe_src, 0, 0, + width / 2, height); +} + static int intel_crtc_compute_pipe_src(struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *i915 = to_i915(crtc->base.dev); - if (crtc_state->bigjoiner) - crtc_state->pipe_src_w /= 2; + intel_bigjoiner_compute_pipe_src(crtc_state); /* * Pipe horizontal size must be even in: @@ -2812,7 +2825,7 @@ static int intel_crtc_compute_pipe_src(struct intel_crtc_state *crtc_state) * - LVDS dual channel mode * - Double wide pipe */ - if (crtc_state->pipe_src_w & 1) { + if (drm_rect_width(&crtc_state->pipe_src) & 1) { if (crtc_state->double_wide) { drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] Odd pipe source width not supported with double wide pipe\n", @@ -3099,14 +3112,15 @@ static void intel_set_pipe_src_size(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + int width = drm_rect_width(&crtc_state->pipe_src); + int height = drm_rect_height(&crtc_state->pipe_src); enum pipe pipe = crtc->pipe; /* pipesrc controls the size that is scaled from, which should * always be the user's requested size. */ intel_de_write(dev_priv, PIPESRC(pipe), - PIPESRC_WIDTH(crtc_state->pipe_src_w - 1) | - PIPESRC_HEIGHT(crtc_state->pipe_src_h - 1)); + PIPESRC_WIDTH(width - 1) | PIPESRC_HEIGHT(height - 1)); } static bool intel_pipe_is_interlaced(const struct intel_crtc_state *crtc_state) @@ -3177,8 +3191,10 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc, u32 tmp; tmp = intel_de_read(dev_priv, PIPESRC(crtc->pipe)); - pipe_config->pipe_src_w = REG_FIELD_GET(PIPESRC_WIDTH_MASK, tmp) + 1; - pipe_config->pipe_src_h = REG_FIELD_GET(PIPESRC_HEIGHT_MASK, tmp) + 1; + + drm_rect_init(&pipe_config->pipe_src, 0, 0, + REG_FIELD_GET(PIPESRC_WIDTH_MASK, tmp) + 1, + REG_FIELD_GET(PIPESRC_HEIGHT_MASK, tmp) + 1); } static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) @@ -5369,9 +5385,8 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, drm_mode_debug_printmodeline(&pipe_config->hw.pipe_mode); intel_dump_crtc_timings(dev_priv, &pipe_config->hw.pipe_mode); drm_dbg_kms(&dev_priv->drm, - "port clock: %d, pipe src size: %dx%d, pixel rate %d\n", - pipe_config->port_clock, - pipe_config->pipe_src_w, pipe_config->pipe_src_h, + "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d\n", + pipe_config->port_clock, DRM_RECT_ARG(&pipe_config->pipe_src), pipe_config->pixel_rate); drm_dbg_kms(&dev_priv->drm, "linetime: %d, ips linetime: %d\n", @@ -5666,6 +5681,7 @@ intel_modeset_pipe_config(struct intel_atomic_state *state, struct drm_i915_private *i915 = to_i915(pipe_config->uapi.crtc->dev); struct drm_connector *connector; struct drm_connector_state *connector_state; + int pipe_src_w, pipe_src_h; int base_bpp, ret, i; bool retry = true; @@ -5703,8 +5719,9 @@ intel_modeset_pipe_config(struct intel_atomic_state *state, * can be changed by the connectors in the below retry loop. */ drm_mode_get_hv_timing(&pipe_config->hw.mode, - &pipe_config->pipe_src_w, - &pipe_config->pipe_src_h); + &pipe_src_w, &pipe_src_h); + drm_rect_init(&pipe_config->pipe_src, 0, 0, + pipe_src_w, pipe_src_h); for_each_new_connector_in_state(&state->base, connector, connector_state, i) { struct intel_encoder *encoder = @@ -6283,8 +6300,10 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_BOOL(pch_pfit.force_thru); if (!fastset) { - PIPE_CONF_CHECK_I(pipe_src_w); - PIPE_CONF_CHECK_I(pipe_src_h); + PIPE_CONF_CHECK_I(pipe_src.x1); + PIPE_CONF_CHECK_I(pipe_src.y1); + PIPE_CONF_CHECK_I(pipe_src.x2); + PIPE_CONF_CHECK_I(pipe_src.y2); PIPE_CONF_CHECK_BOOL(pch_pfit.enabled); if (current_config->pch_pfit.enabled) { diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index ac141c911685..cd0e3a43328e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -939,8 +939,8 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) seq_printf(m, "\tpipe__mode=" DRM_MODE_FMT "\n", DRM_MODE_ARG(&crtc_state->hw.pipe_mode)); - seq_printf(m, "\tpipe src size=%dx%d, dither=%s, bpp=%d\n", - crtc_state->pipe_src_w, crtc_state->pipe_src_h, + seq_printf(m, "\tpipe src=" DRM_RECT_FMT ", dither=%s, bpp=%d\n", + DRM_RECT_ARG(&crtc_state->pipe_src), str_yes_no(crtc_state->dither), crtc_state->pipe_bpp); intel_scaler_info(m, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 593aa7444a49..bcc9c9d5b16c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -954,7 +954,7 @@ struct intel_crtc_state { /* Pipe source size (ie. panel fitter input size) * All planes will be positioned inside this space, * and get clipped at the edges. */ - int pipe_src_w, pipe_src_h; + struct drm_rect pipe_src; /* * Pipe pixel rate, adjusted for diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 76845d34ad0c..631e1f1dc5e6 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -960,14 +960,16 @@ static int check_overlay_dst(struct intel_overlay *overlay, { const struct intel_crtc_state *pipe_config = overlay->crtc->config; + int pipe_src_w = drm_rect_width(&pipe_config->pipe_src); + int pipe_src_h = drm_rect_height(&pipe_config->pipe_src); if (rec->dst_height == 0 || rec->dst_width == 0) return -EINVAL; - if (rec->dst_x < pipe_config->pipe_src_w && - rec->dst_x + rec->dst_width <= pipe_config->pipe_src_w && - rec->dst_y < pipe_config->pipe_src_h && - rec->dst_y + rec->dst_height <= pipe_config->pipe_src_h) + if (rec->dst_x < pipe_src_w && + rec->dst_x + rec->dst_width <= pipe_src_w && + rec->dst_y < pipe_src_h && + rec->dst_y + rec->dst_height <= pipe_src_h) return 0; else return -EINVAL; @@ -1160,7 +1162,7 @@ int intel_overlay_put_image_ioctl(struct drm_device *dev, void *data, crtc->overlay = overlay; /* line too wide, i.e. one-line-mode */ - if (crtc->config->pipe_src_w > 1024 && + if (drm_rect_width(&crtc->config->pipe_src) > 1024 && crtc->config->gmch_pfit.control & PFIT_ENABLE) { overlay->pfit_active = true; update_pfit_vscale_ratio(overlay); diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index a0c8e43db5eb..6cd6d4fdd5ad 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -205,18 +205,20 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, { const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); int x, y, width, height; /* Native modes don't need fitting */ - if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w && - adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h && + if (adjusted_mode->crtc_hdisplay == pipe_src_w && + adjusted_mode->crtc_vdisplay == pipe_src_h && crtc_state->output_format != INTEL_OUTPUT_FORMAT_YCBCR420) return 0; switch (conn_state->scaling_mode) { case DRM_MODE_SCALE_CENTER: - width = crtc_state->pipe_src_w; - height = crtc_state->pipe_src_h; + width = pipe_src_w; + height = pipe_src_h; x = (adjusted_mode->crtc_hdisplay - width + 1)/2; y = (adjusted_mode->crtc_vdisplay - height + 1)/2; break; @@ -224,19 +226,17 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, case DRM_MODE_SCALE_ASPECT: /* Scale but preserve the aspect ratio */ { - u32 scaled_width = adjusted_mode->crtc_hdisplay - * crtc_state->pipe_src_h; - u32 scaled_height = crtc_state->pipe_src_w - * adjusted_mode->crtc_vdisplay; + u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h; + u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay; if (scaled_width > scaled_height) { /* pillar */ - width = scaled_height / crtc_state->pipe_src_h; + width = scaled_height / pipe_src_h; if (width & 1) width++; x = (adjusted_mode->crtc_hdisplay - width + 1) / 2; y = 0; height = adjusted_mode->crtc_vdisplay; } else if (scaled_width < scaled_height) { /* letter */ - height = scaled_width / crtc_state->pipe_src_w; + height = scaled_width / pipe_src_w; if (height & 1) height++; y = (adjusted_mode->crtc_vdisplay - height + 1) / 2; @@ -251,8 +251,8 @@ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, break; case DRM_MODE_SCALE_NONE: - WARN_ON(adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w); - WARN_ON(adjusted_mode->crtc_vdisplay != crtc_state->pipe_src_h); + WARN_ON(adjusted_mode->crtc_hdisplay != pipe_src_w); + WARN_ON(adjusted_mode->crtc_vdisplay != pipe_src_h); fallthrough; case DRM_MODE_SCALE_FULLSCREEN: x = y = 0; @@ -333,10 +333,10 @@ static void i965_scale_aspect(struct intel_crtc_state *crtc_state, { const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - u32 scaled_width = adjusted_mode->crtc_hdisplay * - crtc_state->pipe_src_h; - u32 scaled_height = crtc_state->pipe_src_w * - adjusted_mode->crtc_vdisplay; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h; + u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay; /* 965+ is easy, it does everything in hw */ if (scaled_width > scaled_height) @@ -345,7 +345,7 @@ static void i965_scale_aspect(struct intel_crtc_state *crtc_state, else if (scaled_width < scaled_height) *pfit_control |= PFIT_ENABLE | PFIT_SCALING_LETTER; - else if (adjusted_mode->crtc_hdisplay != crtc_state->pipe_src_w) + else if (adjusted_mode->crtc_hdisplay != pipe_src_w) *pfit_control |= PFIT_ENABLE | PFIT_SCALING_AUTO; } @@ -354,10 +354,10 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state, u32 *border) { struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; - u32 scaled_width = adjusted_mode->crtc_hdisplay * - crtc_state->pipe_src_h; - u32 scaled_height = crtc_state->pipe_src_w * - adjusted_mode->crtc_vdisplay; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); + u32 scaled_width = adjusted_mode->crtc_hdisplay * pipe_src_h; + u32 scaled_height = pipe_src_w * adjusted_mode->crtc_vdisplay; u32 bits; /* @@ -367,12 +367,11 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state, */ if (scaled_width > scaled_height) { /* pillar */ centre_horizontally(adjusted_mode, - scaled_height / - crtc_state->pipe_src_h); + scaled_height / pipe_src_h); *border = LVDS_BORDER_ENABLE; - if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay) { - bits = panel_fitter_scaling(crtc_state->pipe_src_h, + if (pipe_src_h != adjusted_mode->crtc_vdisplay) { + bits = panel_fitter_scaling(pipe_src_h, adjusted_mode->crtc_vdisplay); *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | @@ -383,12 +382,11 @@ static void i9xx_scale_aspect(struct intel_crtc_state *crtc_state, } } else if (scaled_width < scaled_height) { /* letter */ centre_vertically(adjusted_mode, - scaled_width / - crtc_state->pipe_src_w); + scaled_width / pipe_src_w); *border = LVDS_BORDER_ENABLE; - if (crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) { - bits = panel_fitter_scaling(crtc_state->pipe_src_w, + if (pipe_src_w != adjusted_mode->crtc_hdisplay) { + bits = panel_fitter_scaling(pipe_src_w, adjusted_mode->crtc_hdisplay); *pfit_pgm_ratios |= (bits << PFIT_HORIZ_SCALE_SHIFT | @@ -413,10 +411,12 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); + int pipe_src_h = drm_rect_height(&crtc_state->pipe_src); /* Native modes don't need fitting */ - if (adjusted_mode->crtc_hdisplay == crtc_state->pipe_src_w && - adjusted_mode->crtc_vdisplay == crtc_state->pipe_src_h) + if (adjusted_mode->crtc_hdisplay == pipe_src_w && + adjusted_mode->crtc_vdisplay == pipe_src_h) goto out; switch (conn_state->scaling_mode) { @@ -425,8 +425,8 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, * For centered modes, we have to calculate border widths & * heights and modify the values programmed into the CRTC. */ - centre_horizontally(adjusted_mode, crtc_state->pipe_src_w); - centre_vertically(adjusted_mode, crtc_state->pipe_src_h); + centre_horizontally(adjusted_mode, pipe_src_w); + centre_vertically(adjusted_mode, pipe_src_h); border = LVDS_BORDER_ENABLE; break; case DRM_MODE_SCALE_ASPECT: @@ -442,8 +442,8 @@ static int gmch_panel_fitting(struct intel_crtc_state *crtc_state, * Full scaling, even if it changes the aspect ratio. * Fortunately this is all done for us in hw. */ - if (crtc_state->pipe_src_h != adjusted_mode->crtc_vdisplay || - crtc_state->pipe_src_w != adjusted_mode->crtc_hdisplay) { + if (pipe_src_h != adjusted_mode->crtc_vdisplay || + pipe_src_w != adjusted_mode->crtc_hdisplay) { pfit_control |= PFIT_ENABLE; if (DISPLAY_VER(dev_priv) >= 4) pfit_control |= PFIT_SCALING_AUTO; diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index c2e94118566b..998128bac8c0 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -197,7 +197,8 @@ int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state) return skl_update_scaler(crtc_state, !crtc_state->hw.active, SKL_CRTC_INDEX, &crtc_state->scaler_state.scaler_id, - crtc_state->pipe_src_w, crtc_state->pipe_src_h, + drm_rect_width(&crtc_state->pipe_src), + drm_rect_height(&crtc_state->pipe_src), width, height, NULL, 0, crtc_state->pch_pfit.enabled); } @@ -400,10 +401,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); const struct intel_crtc_scaler_state *scaler_state = &crtc_state->scaler_state; - struct drm_rect src = { - .x2 = crtc_state->pipe_src_w << 16, - .y2 = crtc_state->pipe_src_h << 16, - }; const struct drm_rect *dst = &crtc_state->pch_pfit.dst; u16 uv_rgb_hphase, uv_rgb_vphase; enum pipe pipe = crtc->pipe; @@ -413,6 +410,7 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) int y = dst->y1; int hscale, vscale; unsigned long irqflags; + struct drm_rect src; int id; u32 ps_ctrl; @@ -423,6 +421,10 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) crtc_state->scaler_state.scaler_id < 0)) return; + drm_rect_init(&src, 0, 0, + drm_rect_width(&crtc_state->pipe_src) << 16, + drm_rect_height(&crtc_state->pipe_src) << 16); + hscale = drm_rect_calc_hscale(&src, dst, 0, INT_MAX); vscale = drm_rect_calc_vscale(&src, dst, 0, INT_MAX); diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index fdade206f056..d8a756a812f6 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -1401,7 +1401,7 @@ static int skl_plane_check_dst_coordinates(const struct intel_crtc_state *crtc_s to_i915(plane_state->uapi.plane->dev); int crtc_x = plane_state->uapi.dst.x1; int crtc_w = drm_rect_width(&plane_state->uapi.dst); - int pipe_src_w = crtc_state->pipe_src_w; + int pipe_src_w = drm_rect_width(&crtc_state->pipe_src); /* * Display WA #1175: glk From 4d1b53dfbf2445a7cf35ca18c90c2c6712fea163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:13 +0200 Subject: [PATCH 00089/11454] drm/i915: Eliminate bigjoiner boolean MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we now have the bigjoiner_pipes bitmask the boolean is redundant. Get rid of it. Also, populating bigjoiner_pipes already during encoder->compute_config() allows us to use it much earlier during the state calculation as well. The initial aim is to use it in intel_crtc_compute_config(). v2: Move the hweight(bigjoiner_pipes) stuff to a later patch Reviewed-by: Ankit Nautiyal #v1 Reviewed-by: Manasi Navare #v1 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-12-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_cursor.c | 2 +- drivers/gpu/drm/i915/display/intel_display.c | 52 ++++++++----------- .../drm/i915/display/intel_display_debugfs.c | 2 +- .../drm/i915/display/intel_display_types.h | 3 -- drivers/gpu/drm/i915/display/intel_dp.c | 13 ++--- drivers/gpu/drm/i915/display/intel_vdsc.c | 8 +-- .../drm/i915/display/skl_universal_plane.c | 2 +- 7 files changed, 37 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 9026f3fbf9e5..24a42be1b1c5 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -630,7 +630,7 @@ intel_legacy_cursor_update(struct drm_plane *_plane, * FIXME bigjoiner fastpath would be good */ if (!crtc_state->hw.active || intel_crtc_needs_modeset(crtc_state) || - crtc_state->update_pipe || crtc_state->bigjoiner) + crtc_state->update_pipe || crtc_state->bigjoiner_pipes) goto slow; /* diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e019023b8f3a..6d94a9c6eec2 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1918,7 +1918,7 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, if (drm_WARN_ON(&dev_priv->drm, crtc->active)) return; - if (!new_crtc_state->bigjoiner) { + if (!new_crtc_state->bigjoiner_pipes) { intel_encoders_pre_pll_enable(state, crtc); if (new_crtc_state->shared_dpll) @@ -2719,7 +2719,7 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) static void intel_bigjoiner_adjust_timings(const struct intel_crtc_state *crtc_state, struct drm_display_mode *mode) { - if (!crtc_state->bigjoiner) + if (!crtc_state->bigjoiner_pipes) return; mode->crtc_clock /= 2; @@ -2780,7 +2780,7 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state /* Populate the "user" mode with full numbers */ drm_mode_copy(mode, pipe_mode); intel_mode_from_crtc_timings(mode, mode); - mode->hdisplay = drm_rect_width(&crtc_state->pipe_src) << crtc_state->bigjoiner; + mode->hdisplay = drm_rect_width(&crtc_state->pipe_src) << !!crtc_state->bigjoiner_pipes; mode->vdisplay = drm_rect_height(&crtc_state->pipe_src); /* Derive per-pipe timings in case bigjoiner is used */ @@ -2802,7 +2802,7 @@ static void intel_bigjoiner_compute_pipe_src(struct intel_crtc_state *crtc_state { int width, height; - if (!crtc_state->bigjoiner) + if (!crtc_state->bigjoiner_pipes) return; width = drm_rect_width(&crtc_state->pipe_src); @@ -4190,7 +4190,6 @@ static void intel_bigjoiner_get_config(struct intel_crtc_state *crtc_state) if (((master_pipes | slave_pipes) & BIT(pipe)) == 0) return; - crtc_state->bigjoiner = true; crtc_state->bigjoiner_pipes = BIT(get_bigjoiner_master_pipe(pipe, master_pipes, slave_pipes)) | get_bigjoiner_slave_pipes(pipe, master_pipes, slave_pipes); @@ -5600,6 +5599,9 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, master_crtc); struct intel_crtc_state *saved_state; + WARN_ON(master_crtc_state->bigjoiner_pipes != + slave_crtc_state->bigjoiner_pipes); + saved_state = kmemdup(master_crtc_state, sizeof(*saved_state), GFP_KERNEL); if (!saved_state) return -ENOMEM; @@ -5630,6 +5632,9 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, slave_crtc_state->uapi.connectors_changed = master_crtc_state->uapi.connectors_changed; slave_crtc_state->uapi.active_changed = master_crtc_state->uapi.active_changed; + WARN_ON(master_crtc_state->bigjoiner_pipes != + slave_crtc_state->bigjoiner_pipes); + return 0; } @@ -6405,7 +6410,6 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(sync_mode_slaves_mask); PIPE_CONF_CHECK_I(master_transcoder); - PIPE_CONF_CHECK_BOOL(bigjoiner); PIPE_CONF_CHECK_X(bigjoiner_pipes); PIPE_CONF_CHECK_I(dsc.compression_enable); @@ -7336,32 +7340,26 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state, struct intel_crtc_state *master_crtc_state = intel_atomic_get_new_crtc_state(state, master_crtc); struct intel_crtc *slave_crtc; - u8 slave_pipes; - /* - * TODO: encoder.compute_config() may be the best - * place to populate the bitmask for the master crtc. - * For now encoder.compute_config() just flags things - * as needing bigjoiner and we populate the bitmask - * here. - */ - WARN_ON(master_crtc_state->bigjoiner_pipes); - - if (!master_crtc_state->bigjoiner) + if (!master_crtc_state->bigjoiner_pipes) return 0; - slave_pipes = BIT(master_crtc->pipe + 1); + /* sanity check */ + if (drm_WARN_ON(&i915->drm, + master_crtc->pipe != bigjoiner_master_pipe(master_crtc_state))) + return -EINVAL; - if (slave_pipes & ~bigjoiner_pipes(i915)) { + if (master_crtc_state->bigjoiner_pipes & ~bigjoiner_pipes(i915)) { drm_dbg_kms(&i915->drm, "[CRTC:%d:%s] Cannot act as big joiner master " - "(need 0x%x as slave pipes, only 0x%x possible)\n", + "(need 0x%x as pipes, only 0x%x possible)\n", master_crtc->base.base.id, master_crtc->base.name, - slave_pipes, bigjoiner_pipes(i915)); + master_crtc_state->bigjoiner_pipes, bigjoiner_pipes(i915)); return -EINVAL; } - for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, slave_pipes) { + for_each_intel_crtc_in_pipe_mask(&i915->drm, slave_crtc, + intel_crtc_bigjoiner_slave_pipes(master_crtc_state)) { struct intel_crtc_state *slave_crtc_state; int ret; @@ -7395,10 +7393,8 @@ static int intel_atomic_check_bigjoiner(struct intel_atomic_state *state, slave_crtc->base.base.id, slave_crtc->base.name, master_crtc->base.base.id, master_crtc->base.name); - master_crtc_state->bigjoiner_pipes = - BIT(master_crtc->pipe) | BIT(slave_crtc->pipe); slave_crtc_state->bigjoiner_pipes = - BIT(master_crtc->pipe) | BIT(slave_crtc->pipe); + master_crtc_state->bigjoiner_pipes; ret = copy_bigjoiner_crtc_state_modeset(state, slave_crtc); if (ret) @@ -7421,13 +7417,11 @@ static void kill_bigjoiner_slave(struct intel_atomic_state *state, struct intel_crtc_state *slave_crtc_state = intel_atomic_get_new_crtc_state(state, slave_crtc); - slave_crtc_state->bigjoiner = false; slave_crtc_state->bigjoiner_pipes = 0; intel_crtc_copy_uapi_to_hw_state_modeset(state, slave_crtc); } - master_crtc_state->bigjoiner = false; master_crtc_state->bigjoiner_pipes = 0; } @@ -7840,7 +7834,7 @@ static int intel_atomic_check(struct drm_device *dev, } } - if (new_crtc_state->bigjoiner) { + if (new_crtc_state->bigjoiner_pipes) { if (intel_pipes_need_modeset(state, new_crtc_state->bigjoiner_pipes)) { new_crtc_state->uapi.mode_changed = true; new_crtc_state->update_pipe = false; @@ -10176,7 +10170,7 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) intel_encoder_get_config(encoder, crtc_state); /* read out to slave crtc as well for bigjoiner */ - if (crtc_state->bigjoiner) { + if (crtc_state->bigjoiner_pipes) { struct intel_crtc *slave_crtc; /* encoder should read be linked to bigjoiner master */ diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index cd0e3a43328e..41b81d5dd5f4 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -945,7 +945,7 @@ static void intel_crtc_info(struct seq_file *m, struct intel_crtc *crtc) intel_scaler_info(m, crtc); - if (crtc_state->bigjoiner) + if (crtc_state->bigjoiner_pipes) seq_printf(m, "\tLinked to 0x%x pipes as a %s\n", crtc_state->bigjoiner_pipes, intel_crtc_is_bigjoiner_slave(crtc_state) ? "slave" : "master"); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index bcc9c9d5b16c..5e8d7394a394 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1181,9 +1181,6 @@ struct intel_crtc_state { /* enable pipe csc? */ bool csc_enable; - /* enable pipe big joiner? */ - bool bigjoiner; - /* big joiner pipe bitmask */ u8 bigjoiner_pipes; diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index eab2d1f5ec59..619546441eae 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1426,13 +1426,13 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, pipe_config->lane_count, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, - pipe_config->bigjoiner, + pipe_config->bigjoiner_pipes, pipe_bpp); dsc_dp_slice_count = intel_dp_dsc_get_slice_count(intel_dp, adjusted_mode->crtc_clock, adjusted_mode->crtc_hdisplay, - pipe_config->bigjoiner); + pipe_config->bigjoiner_pipes); if (!dsc_max_output_bpp || !dsc_dp_slice_count) { drm_dbg_kms(&dev_priv->drm, "Compressed BPP/Slice Count not supported\n"); @@ -1466,7 +1466,7 @@ static int intel_dp_dsc_compute_config(struct intel_dp *intel_dp, * then we need to use 2 VDSC instances. */ if (adjusted_mode->crtc_clock > dev_priv->max_cdclk_freq || - pipe_config->bigjoiner) { + pipe_config->bigjoiner_pipes) { if (pipe_config->dsc.slice_count < 2) { drm_dbg_kms(&dev_priv->drm, "Cannot split stream to use 2 VDSC instances\n"); @@ -1502,6 +1502,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, struct drm_connector_state *conn_state) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); + struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); const struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); @@ -1539,7 +1540,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, if (intel_dp_need_bigjoiner(intel_dp, adjusted_mode->crtc_hdisplay, adjusted_mode->crtc_clock)) - pipe_config->bigjoiner = true; + pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); /* * Optimize for slow and wide for everything, because there are some @@ -1552,8 +1553,8 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, * onwards pipe joiner can be enabled without compression. */ drm_dbg_kms(&i915->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en); - if (ret || intel_dp->force_dsc_en || (DISPLAY_VER(i915) < 13 && - pipe_config->bigjoiner)) { + if (ret || intel_dp->force_dsc_en || + (DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes)) { ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, conn_state, &limits); if (ret < 0) diff --git a/drivers/gpu/drm/i915/display/intel_vdsc.c b/drivers/gpu/drm/i915/display/intel_vdsc.c index e7120900bc45..e59c29ab1300 100644 --- a/drivers/gpu/drm/i915/display/intel_vdsc.c +++ b/drivers/gpu/drm/i915/display/intel_vdsc.c @@ -587,7 +587,7 @@ static void intel_dsc_pps_configure(const struct intel_crtc_state *crtc_state) u8 num_vdsc_instances = (crtc_state->dsc.dsc_split) ? 2 : 1; int i = 0; - if (crtc_state->bigjoiner) + if (crtc_state->bigjoiner_pipes) num_vdsc_instances *= 2; /* Populate PICTURE_PARAMETER_SET_0 registers */ @@ -1121,7 +1121,7 @@ void intel_uncompressed_joiner_enable(const struct intel_crtc_state *crtc_state) struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); u32 dss_ctl1_val = 0; - if (crtc_state->bigjoiner && !crtc_state->dsc.compression_enable) { + if (crtc_state->bigjoiner_pipes && !crtc_state->dsc.compression_enable) { if (intel_crtc_is_bigjoiner_slave(crtc_state)) dss_ctl1_val |= UNCOMPRESSED_JOINER_SLAVE; else @@ -1148,7 +1148,7 @@ void intel_dsc_enable(const struct intel_crtc_state *crtc_state) dss_ctl2_val |= RIGHT_BRANCH_VDSC_ENABLE; dss_ctl1_val |= JOINER_ENABLE; } - if (crtc_state->bigjoiner) { + if (crtc_state->bigjoiner_pipes) { dss_ctl1_val |= BIG_JOINER_ENABLE; if (!intel_crtc_is_bigjoiner_slave(crtc_state)) dss_ctl1_val |= MASTER_BIG_JOINER_ENABLE; @@ -1164,7 +1164,7 @@ void intel_dsc_disable(const struct intel_crtc_state *old_crtc_state) /* Disable only if either of them is enabled */ if (old_crtc_state->dsc.compression_enable || - old_crtc_state->bigjoiner) { + old_crtc_state->bigjoiner_pipes) { intel_de_write(dev_priv, dss_ctl1_reg(crtc, old_crtc_state->cpu_transcoder), 0); intel_de_write(dev_priv, dss_ctl2_reg(crtc, old_crtc_state->cpu_transcoder), 0); } diff --git a/drivers/gpu/drm/i915/display/skl_universal_plane.c b/drivers/gpu/drm/i915/display/skl_universal_plane.c index d8a756a812f6..c57fca1fe678 100644 --- a/drivers/gpu/drm/i915/display/skl_universal_plane.c +++ b/drivers/gpu/drm/i915/display/skl_universal_plane.c @@ -2367,7 +2367,7 @@ skl_get_initial_plane_config(struct intel_crtc *crtc, drm_WARN_ON(dev, pipe != crtc->pipe); - if (crtc_state->bigjoiner) { + if (crtc_state->bigjoiner_pipes) { drm_dbg_kms(&dev_priv->drm, "Unsupported bigjoiner configuration for initial FB\n"); return; From 8b986e2a051c2910851d3661a8419721028d2f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:14 +0200 Subject: [PATCH 00090/11454] drm/i915: Use bigjoiner_pipes more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the hardcoded 2 pipe assumptions when we're massaging pipe_mode and the pipe_src rect to be suitable for bigjoiner. Instead we can just count the number of pipes in the bitmask. v2: Introduce intel_bigjoiner_num_pipes() Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-13-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_display.c | 31 +++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6d94a9c6eec2..7a11f2224662 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -369,6 +369,11 @@ bool intel_crtc_is_bigjoiner_master(const struct intel_crtc_state *crtc_state) crtc->pipe == bigjoiner_master_pipe(crtc_state); } +static int intel_bigjoiner_num_pipes(const struct intel_crtc_state *crtc_state) +{ + return hweight8(crtc_state->bigjoiner_pipes); +} + struct intel_crtc *intel_master_crtc(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); @@ -2719,16 +2724,18 @@ static void intel_crtc_compute_pixel_rate(struct intel_crtc_state *crtc_state) static void intel_bigjoiner_adjust_timings(const struct intel_crtc_state *crtc_state, struct drm_display_mode *mode) { - if (!crtc_state->bigjoiner_pipes) + int num_pipes = intel_bigjoiner_num_pipes(crtc_state); + + if (num_pipes < 2) return; - mode->crtc_clock /= 2; - mode->crtc_hdisplay /= 2; - mode->crtc_hblank_start /= 2; - mode->crtc_hblank_end /= 2; - mode->crtc_hsync_start /= 2; - mode->crtc_hsync_end /= 2; - mode->crtc_htotal /= 2; + mode->crtc_clock /= num_pipes; + mode->crtc_hdisplay /= num_pipes; + mode->crtc_hblank_start /= num_pipes; + mode->crtc_hblank_end /= num_pipes; + mode->crtc_hsync_start /= num_pipes; + mode->crtc_hsync_end /= num_pipes; + mode->crtc_htotal /= num_pipes; } static void intel_splitter_adjust_timings(const struct intel_crtc_state *crtc_state, @@ -2780,7 +2787,8 @@ static void intel_crtc_readout_derived_state(struct intel_crtc_state *crtc_state /* Populate the "user" mode with full numbers */ drm_mode_copy(mode, pipe_mode); intel_mode_from_crtc_timings(mode, mode); - mode->hdisplay = drm_rect_width(&crtc_state->pipe_src) << !!crtc_state->bigjoiner_pipes; + mode->hdisplay = drm_rect_width(&crtc_state->pipe_src) * + (intel_bigjoiner_num_pipes(crtc_state) ?: 1); mode->vdisplay = drm_rect_height(&crtc_state->pipe_src); /* Derive per-pipe timings in case bigjoiner is used */ @@ -2800,16 +2808,17 @@ static void intel_encoder_get_config(struct intel_encoder *encoder, static void intel_bigjoiner_compute_pipe_src(struct intel_crtc_state *crtc_state) { + int num_pipes = intel_bigjoiner_num_pipes(crtc_state); int width, height; - if (!crtc_state->bigjoiner_pipes) + if (num_pipes < 2) return; width = drm_rect_width(&crtc_state->pipe_src); height = drm_rect_height(&crtc_state->pipe_src); drm_rect_init(&crtc_state->pipe_src, 0, 0, - width / 2, height); + width / num_pipes, height); } static int intel_crtc_compute_pipe_src(struct intel_crtc_state *crtc_state) From 09077bc3116581f4d1cb961ec359ad56586e370b Mon Sep 17 00:00:00 2001 From: Nikita Yushchenko Date: Sat, 25 Dec 2021 09:31:51 +0300 Subject: [PATCH 00091/11454] drm/bridge_connector: enable HPD by default if supported Hotplug events reported by bridge drivers over drm_bridge_hpd_notify() get ignored unless somebody calls drm_bridge_hpd_enable(). When the connector for the bridge is bridge_connector, such a call is done from drm_bridge_connector_enable_hpd(). However drm_bridge_connector_enable_hpd() is never called on init paths, documentation suggests that it is intended for suspend/resume paths. In result, once encoders are switched to bridge_connector, bridge-detected HPD stops working. This patch adds a call to that API on init path. This fixes HDMI HPD with rcar-du + adv7513 case when adv7513 reports HPD events via interrupts. Fixes: c24110a8fd09 ("drm: rcar-du: Use drm_bridge_connector_init() helper") Signed-off-by: Nikita Yushchenko Signed-off-by: Paul Cercueil Tested-by: Kieran Bingham Reviewed-by: Kieran Bingham Reviewed-by: Laurent Pinchart Link: https://patchwork.freedesktop.org/patch/msgid/20211225063151.2110878-1-nikita.yoush@cogentembedded.com --- drivers/gpu/drm/drm_bridge_connector.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_bridge_connector.c b/drivers/gpu/drm/drm_bridge_connector.c index 60923cdfe8e1..6b3dad03d77d 100644 --- a/drivers/gpu/drm/drm_bridge_connector.c +++ b/drivers/gpu/drm/drm_bridge_connector.c @@ -384,8 +384,10 @@ struct drm_connector *drm_bridge_connector_init(struct drm_device *drm, connector_type, ddc); drm_connector_helper_add(connector, &drm_bridge_connector_helper_funcs); - if (bridge_connector->bridge_hpd) + if (bridge_connector->bridge_hpd) { connector->polled = DRM_CONNECTOR_POLL_HPD; + drm_bridge_connector_enable_hpd(connector); + } else if (bridge_connector->bridge_detect) connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT; From a4a072d98d8c2370476de3b5f0c94f2cf2fd35bf Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Fri, 25 Feb 2022 21:51:33 +0100 Subject: [PATCH 00092/11454] sysfb: Make config option dependencies explicit efifb and vesafb requires sysfb implicitly but this is not stated in Kconfig. Add the dependency. With that all drivers that require sysfb depend on it so it can default to disabled. Signed-off-by: Michal Suchanek Reviewed-by: Javier Martinez Canillas Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/a0fa41e9186653e4c41ad0a28259e5cdc71b1f66.1645822213.git.msuchanek@suse.de --- drivers/firmware/Kconfig | 5 ++--- drivers/video/fbdev/Kconfig | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 75cb91055c17..5265eca74ba1 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -218,12 +218,11 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT config SYSFB bool - default y - depends on X86 || EFI config SYSFB_SIMPLEFB bool "Mark VGA/VBE/EFI FB as generic system framebuffer" - depends on SYSFB + depends on X86 || EFI + select SYSFB help Firmwares often provide initial graphics framebuffers so the BIOS, bootloader or kernel can show basic video-output during boot for diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 6ed5e608dd04..5851ee6d5502 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -628,6 +628,7 @@ config FB_VESA select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT select FB_BOOT_VESA_SUPPORT + select SYSFB help This is the frame buffer device driver for generic VESA 2.0 compliant graphic cards. The older VESA 1.2 cards are not supported. @@ -641,6 +642,7 @@ config FB_EFI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT + select SYSFB help This is the EFI frame buffer device driver. If the firmware on your platform is EFI 1.10 or UEFI 2.0, select Y to add support for From 8b766b0f8eece55155146f7628610ce54a065e0f Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Fri, 25 Feb 2022 21:51:34 +0100 Subject: [PATCH 00093/11454] sysfb: Enable boot time VESA graphic mode selection Since switch to simplefb/simpledrm VESA graphic mode selection with vga= kernel parameter is no longer available with legacy BIOS. The x86 realmode boot code enables the VESA graphic modes when option FB_BOOT_VESA_SUPPORT is enabled. This option is selected by vesafb but not simplefb/simpledrm. To enable use of VESA modes with simplefb in legacy BIOS boot mode drop dependency of BOOT_VESA_SUPPORT on FB, also drop the FB_ prefix. Select the option from sysfb rather than the drivers that depend on it. The BOOT_VESA_SUPPORT is not specific to framebuffer but rather to x86 platform, move it from fbdev to x86 Kconfig. Fixes: e3263ab389a7 ("x86: provide platform-devices for boot-framebuffers") Signed-off-by: Michal Suchanek Reviewed-by: Javier Martinez Canillas Acked-by: Borislav Petkov Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/948c39940a4e99f5b43bdbcbe537faae71a43e1d.1645822213.git.msuchanek@suse.de --- arch/x86/Kconfig | 6 ++++++ arch/x86/boot/video-vesa.c | 4 ++-- drivers/firmware/Kconfig | 1 + drivers/video/fbdev/Kconfig | 12 ++---------- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9f5bd41bf660..cceb1aab0486 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -942,6 +942,12 @@ config GART_IOMMU If unsure, say Y. +config BOOT_VESA_SUPPORT + bool + help + If true, at least one selected framebuffer driver can take advantage + of VESA video modes set at an early boot stage via the vga= parameter. + config MAXSMP bool "Enable Maximum number of SMP Processors and NUMA Nodes" depends on X86_64 && SMP && DEBUG_KERNEL diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index 7e185977a984..c2c6d35e3a43 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c @@ -83,7 +83,7 @@ static int vesa_probe(void) (vminfo.memory_layout == 4 || vminfo.memory_layout == 6) && vminfo.memory_planes == 1) { -#ifdef CONFIG_FB_BOOT_VESA_SUPPORT +#ifdef CONFIG_BOOT_VESA_SUPPORT /* Graphics mode, color, linear frame buffer supported. Only register the mode if if framebuffer is configured, however, @@ -121,7 +121,7 @@ static int vesa_set_mode(struct mode_info *mode) if ((vminfo.mode_attr & 0x15) == 0x05) { /* It's a supported text mode */ is_graphic = 0; -#ifdef CONFIG_FB_BOOT_VESA_SUPPORT +#ifdef CONFIG_BOOT_VESA_SUPPORT } else if ((vminfo.mode_attr & 0x99) == 0x99) { /* It's a graphics mode with linear frame buffer */ is_graphic = 1; diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 5265eca74ba1..be42ae6f079e 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -218,6 +218,7 @@ config QCOM_SCM_DOWNLOAD_MODE_DEFAULT config SYSFB bool + select BOOT_VESA_SUPPORT config SYSFB_SIMPLEFB bool "Mark VGA/VBE/EFI FB as generic system framebuffer" diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig index 5851ee6d5502..01cf070f24f3 100644 --- a/drivers/video/fbdev/Kconfig +++ b/drivers/video/fbdev/Kconfig @@ -66,13 +66,6 @@ config FB_DDC select I2C_ALGOBIT select I2C -config FB_BOOT_VESA_SUPPORT - bool - depends on FB - help - If true, at least one selected framebuffer driver can take advantage - of VESA video modes set at an early boot stage via the vga= parameter. - config FB_CFB_FILLRECT tristate depends on FB @@ -627,7 +620,6 @@ config FB_VESA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_BOOT_VESA_SUPPORT select SYSFB help This is the frame buffer device driver for generic VESA 2.0 @@ -1053,7 +1045,7 @@ config FB_INTEL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_BOOT_VESA_SUPPORT if FB_INTEL = y + select BOOT_VESA_SUPPORT if FB_INTEL = y depends on !DRM_I915 help This driver supports the on-board graphics built in to the Intel @@ -1380,7 +1372,7 @@ config FB_SIS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_BOOT_VESA_SUPPORT if FB_SIS = y + select BOOT_VESA_SUPPORT if FB_SIS = y select FB_SIS_300 if !FB_SIS_315 help This is the frame buffer device driver for the SiS 300, 315, 330 From fd8be27e50e04f6e80af0f3e327cced525558256 Mon Sep 17 00:00:00 2001 From: Michal Suchanek Date: Fri, 25 Feb 2022 21:51:35 +0100 Subject: [PATCH 00094/11454] efifb: Remove redundant efifb_setup_from_dmi stub efifb is the only user of efifb_setup_from_dmi which is provided by sysfb which is selected by efifb. That makes the stub redundant. Signed-off-by: Michal Suchanek Reviewed-by: Javier Martinez Canillas Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/7416c439d68e9e96068ea5c77e05c99c7df41750.1645822213.git.msuchanek@suse.de --- include/linux/efi.h | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/linux/efi.h b/include/linux/efi.h index ccd4d3f91c98..0cbbc4103632 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h @@ -1329,10 +1329,6 @@ static inline struct efi_mokvar_table_entry *efi_mokvar_entry_find( } #endif -#ifdef CONFIG_SYSFB extern void efifb_setup_from_dmi(struct screen_info *si, const char *opt); -#else -static inline void efifb_setup_from_dmi(struct screen_info *si, const char *opt) { } -#endif #endif /* _LINUX_EFI_H */ From dcb62550c4e46a9af18c7e5876bc1189c7115329 Mon Sep 17 00:00:00 2001 From: Gwan-gyeong Mun Date: Fri, 25 Feb 2022 15:13:15 +0200 Subject: [PATCH 00095/11454] drm/i915/dmabuf: Update dma_buf_ops.unmap_dma_buf callback to use drm_gem_unmap_dma_buf() The dma_buf_ops.unmap_dma_buf callback used in i915, i915_gem_unmap_dma_buf(), has the same code as drm_gem_unmap_dma_buf(). In order to eliminate defining and using duplicate function, it updates the dma_buf_ops.unmap_dma_buf callback to use drm_gem_unmap_dma_buf(). Signed-off-by: Gwan-gyeong Mun Reviewed-by: Nirmoy Das Signed-off-by: Ramalingam C Link: https://patchwork.freedesktop.org/patch/msgid/20220225131316.1433515-2-gwan-gyeong.mun@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index 13917231ae81..af899ae1f3c7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -66,15 +66,6 @@ err: return ERR_PTR(ret); } -static void i915_gem_unmap_dma_buf(struct dma_buf_attachment *attachment, - struct sg_table *sg, - enum dma_data_direction dir) -{ - dma_unmap_sgtable(attachment->dev, sg, dir, DMA_ATTR_SKIP_CPU_SYNC); - sg_free_table(sg); - kfree(sg); -} - static int i915_gem_dmabuf_vmap(struct dma_buf *dma_buf, struct iosys_map *map) { @@ -209,7 +200,7 @@ static const struct dma_buf_ops i915_dmabuf_ops = { .attach = i915_gem_dmabuf_attach, .detach = i915_gem_dmabuf_detach, .map_dma_buf = i915_gem_map_dma_buf, - .unmap_dma_buf = i915_gem_unmap_dma_buf, + .unmap_dma_buf = drm_gem_unmap_dma_buf, .release = drm_gem_dmabuf_release, .mmap = i915_gem_dmabuf_mmap, .vmap = i915_gem_dmabuf_vmap, From d028a7690d872d4720628c7475dbd1a25cfa73df Mon Sep 17 00:00:00 2001 From: Gwan-gyeong Mun Date: Fri, 25 Feb 2022 15:13:16 +0200 Subject: [PATCH 00096/11454] drm/i915/dmabuf: Fix prime_mmap to work when using LMEM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current implementation of i915 prime mmap only works when initializing drm_i915_gem_object with shmem_region. When using LMEM, drm_i915_gem_object is initialized with ttm_system_region. In order to make prime mmap work even this case, when using LMEM (when using ttm in i915), dma_buf_ops.mmap callback function calls drm_gem_prime_mmap(). drm_gem_prime_mmap() of drm core calls internally i915_gem_mmap() so that prime mmap can perform normally. The fake offset is processed inside drm_gem_prime_mmap(). Testcase: igt/prime_mmap Cc: Thomas Hellström Cc: Matthew Auld Signed-off-by: Gwan-gyeong Mun Reviewed-by: Nirmoy Das Signed-off-by: Ramalingam C Link: https://patchwork.freedesktop.org/patch/msgid/20220225131316.1433515-3-gwan-gyeong.mun@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index af899ae1f3c7..f5062d0c6333 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -93,11 +93,15 @@ static void i915_gem_dmabuf_vunmap(struct dma_buf *dma_buf, static int i915_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) { struct drm_i915_gem_object *obj = dma_buf_to_obj(dma_buf); + struct drm_i915_private *i915 = to_i915(obj->base.dev); int ret; if (obj->base.size < vma->vm_end - vma->vm_start) return -EINVAL; + if (HAS_LMEM(i915)) + return drm_gem_prime_mmap(&obj->base, vma); + if (!obj->base.filp) return -ENODEV; From e1a7ab4fca0caa0d637d08a2440592637c0a3675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Fri, 4 Mar 2022 09:26:39 +0100 Subject: [PATCH 00097/11454] drm/i915: Remove the vm open count MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit vms are not getting properly closed. Rather than fixing that, Remove the vm open count and instead rely on the vm refcount. The vm open count existed solely to break the strong references the vmas had on the vms. Now instead make those references weak and ensure vmas are destroyed when the vm is destroyed. Unfortunately if the vm destructor and the object destructor both wants to destroy a vma, that may lead to a race in that the vm destructor just unbinds the vma and leaves the actual vma destruction to the object destructor. However in order for the object destructor to ensure the vma is unbound it needs to grab the vm mutex. In order to keep the vm mutex alive until the object destructor is done with it, somewhat hackishly grab a vm_resv refcount that is released late in the vma destruction process, when the vm mutex is no longer needed. v2: Address review-comments from Niranjana - Clarify that the struct i915_address_space::skip_pte_rewrite is a hack and should ideally be replaced in an upcoming patch. - Remove an unneeded continue in clear_vm_list and update comment. v3: - Documentation update - Commit message formatting Co-developed-by: Niranjana Vishwanathapura Signed-off-by: Niranjana Vishwanathapura Signed-off-by: Thomas Hellström Reviewed-by: Niranjana Vishwanathapura Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220304082641.308069-2-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/i915/display/intel_dpt.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_context.c | 29 ++----- .../gpu/drm/i915/gem/i915_gem_execbuffer.c | 6 ++ .../gpu/drm/i915/gem/selftests/mock_context.c | 5 +- drivers/gpu/drm/i915/gt/gen6_ppgtt.c | 2 +- drivers/gpu/drm/i915/gt/intel_ggtt.c | 30 +++---- drivers/gpu/drm/i915/gt/intel_gtt.c | 54 ++++++++---- drivers/gpu/drm/i915/gt/intel_gtt.h | 56 ++++-------- drivers/gpu/drm/i915/gt/selftest_execlists.c | 86 +++++++++---------- drivers/gpu/drm/i915/i915_gem.c | 6 +- drivers/gpu/drm/i915/i915_vma.c | 63 ++++++++++---- drivers/gpu/drm/i915/i915_vma_resource.c | 2 +- drivers/gpu/drm/i915/i915_vma_resource.h | 6 ++ drivers/gpu/drm/i915/i915_vma_types.h | 7 ++ drivers/gpu/drm/i915/selftests/i915_gem_gtt.c | 4 +- 15 files changed, 192 insertions(+), 166 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpt.c b/drivers/gpu/drm/i915/display/intel_dpt.c index 05dd7dba3a5c..3af4930c1095 100644 --- a/drivers/gpu/drm/i915/display/intel_dpt.c +++ b/drivers/gpu/drm/i915/display/intel_dpt.c @@ -300,5 +300,5 @@ void intel_dpt_destroy(struct i915_address_space *vm) { struct i915_dpt *dpt = i915_vm_to_dpt(vm); - i915_vm_close(&dpt->vm); + i915_vm_put(&dpt->vm); } diff --git a/drivers/gpu/drm/i915/gem/i915_gem_context.c b/drivers/gpu/drm/i915/gem/i915_gem_context.c index 9ae294eb7fb4..0aaddb8da40f 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_context.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_context.c @@ -1466,8 +1466,6 @@ static void set_closed_name(struct i915_gem_context *ctx) static void context_close(struct i915_gem_context *ctx) { - struct i915_address_space *vm; - /* Flush any concurrent set_engines() */ mutex_lock(&ctx->engines_mutex); unpin_engines(__context_engines_static(ctx)); @@ -1479,19 +1477,6 @@ static void context_close(struct i915_gem_context *ctx) set_closed_name(ctx); - vm = ctx->vm; - if (vm) { - /* i915_vm_close drops the final reference, which is a bit too - * early and could result in surprises with concurrent - * operations racing with thist ctx close. Keep a full reference - * until the end. - */ - i915_vm_get(vm); - i915_vm_close(vm); - } - - ctx->file_priv = ERR_PTR(-EBADF); - /* * The LUT uses the VMA as a backpointer to unref the object, * so we need to clear the LUT before we close all the VMA (inside @@ -1499,6 +1484,8 @@ static void context_close(struct i915_gem_context *ctx) */ lut_close(ctx); + ctx->file_priv = ERR_PTR(-EBADF); + spin_lock(&ctx->i915->gem.contexts.lock); list_del(&ctx->link); spin_unlock(&ctx->i915->gem.contexts.lock); @@ -1597,12 +1584,8 @@ i915_gem_create_context(struct drm_i915_private *i915, } vm = &ppgtt->vm; } - if (vm) { - ctx->vm = i915_vm_open(vm); - - /* i915_vm_open() takes a reference */ - i915_vm_put(vm); - } + if (vm) + ctx->vm = vm; mutex_init(&ctx->engines_mutex); if (pc->num_user_engines >= 0) { @@ -1652,7 +1635,7 @@ err_engines: free_engines(e); err_vm: if (ctx->vm) - i915_vm_close(ctx->vm); + i915_vm_put(ctx->vm); err_ctx: kfree(ctx); return ERR_PTR(err); @@ -1836,7 +1819,7 @@ static int get_ppgtt(struct drm_i915_file_private *file_priv, if (err) return err; - i915_vm_open(vm); + i915_vm_get(vm); GEM_BUG_ON(id == 0); /* reserved for invalid/unassigned ppgtt */ args->value = id; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index d42f437149c9..3dd69832c4c5 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -2691,6 +2691,11 @@ eb_select_engine(struct i915_execbuffer *eb) if (err) goto err; + if (!i915_vm_tryget(ce->vm)) { + err = -ENOENT; + goto err; + } + eb->context = ce; eb->gt = ce->engine->gt; @@ -2714,6 +2719,7 @@ eb_put_engine(struct i915_execbuffer *eb) { struct intel_context *child; + i915_vm_put(eb->context->vm); intel_gt_pm_put(eb->gt); for_each_child(eb->context, child) intel_context_put(child); diff --git a/drivers/gpu/drm/i915/gem/selftests/mock_context.c b/drivers/gpu/drm/i915/gem/selftests/mock_context.c index 6d6082b5f31f..8ac6726ec16b 100644 --- a/drivers/gpu/drm/i915/gem/selftests/mock_context.c +++ b/drivers/gpu/drm/i915/gem/selftests/mock_context.c @@ -42,8 +42,7 @@ mock_context(struct drm_i915_private *i915, if (!ppgtt) goto err_free; - ctx->vm = i915_vm_open(&ppgtt->vm); - i915_vm_put(&ppgtt->vm); + ctx->vm = &ppgtt->vm; } mutex_init(&ctx->engines_mutex); @@ -59,7 +58,7 @@ mock_context(struct drm_i915_private *i915, err_vm: if (ctx->vm) - i915_vm_close(ctx->vm); + i915_vm_put(ctx->vm); err_free: kfree(ctx); return NULL; diff --git a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c index 871fe7bda0e0..1bb766c79dcb 100644 --- a/drivers/gpu/drm/i915/gt/gen6_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen6_ppgtt.c @@ -322,7 +322,7 @@ int gen6_ppgtt_pin(struct i915_ppgtt *base, struct i915_gem_ww_ctx *ww) struct gen6_ppgtt *ppgtt = to_gen6_ppgtt(base); int err; - GEM_BUG_ON(!atomic_read(&ppgtt->base.vm.open)); + GEM_BUG_ON(!kref_read(&ppgtt->base.vm.ref)); /* * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 8850d4e0f9cc..04191fe2ee34 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -126,7 +126,7 @@ static bool needs_idle_maps(struct drm_i915_private *i915) void i915_ggtt_suspend_vm(struct i915_address_space *vm) { struct i915_vma *vma, *vn; - int open; + int save_skip_rewrite; drm_WARN_ON(&vm->i915->drm, !vm->is_ggtt && !vm->is_dpt); @@ -135,8 +135,12 @@ retry: mutex_lock(&vm->mutex); - /* Skip rewriting PTE on VMA unbind. */ - open = atomic_xchg(&vm->open, 0); + /* + * Skip rewriting PTE on VMA unbind. + * FIXME: Use an argument to i915_vma_unbind() instead? + */ + save_skip_rewrite = vm->skip_pte_rewrite; + vm->skip_pte_rewrite = true; list_for_each_entry_safe(vma, vn, &vm->bound_list, vm_link) { struct drm_i915_gem_object *obj = vma->obj; @@ -154,16 +158,14 @@ retry: */ i915_gem_object_get(obj); - atomic_set(&vm->open, open); mutex_unlock(&vm->mutex); i915_gem_object_lock(obj, NULL); - open = i915_vma_unbind(vma); + GEM_WARN_ON(i915_vma_unbind(vma)); i915_gem_object_unlock(obj); - - GEM_WARN_ON(open); - i915_gem_object_put(obj); + + vm->skip_pte_rewrite = save_skip_rewrite; goto retry; } @@ -179,7 +181,7 @@ retry: vm->clear_range(vm, 0, vm->total); - atomic_set(&vm->open, open); + vm->skip_pte_rewrite = save_skip_rewrite; mutex_unlock(&vm->mutex); } @@ -773,13 +775,13 @@ static void ggtt_cleanup_hw(struct i915_ggtt *ggtt) { struct i915_vma *vma, *vn; - atomic_set(&ggtt->vm.open, 0); - flush_workqueue(ggtt->vm.i915->wq); i915_gem_drain_freed_objects(ggtt->vm.i915); mutex_lock(&ggtt->vm.mutex); + ggtt->vm.skip_pte_rewrite = true; + list_for_each_entry_safe(vma, vn, &ggtt->vm.bound_list, vm_link) { struct drm_i915_gem_object *obj = vma->obj; bool trylock; @@ -1307,16 +1309,12 @@ bool i915_ggtt_resume_vm(struct i915_address_space *vm) { struct i915_vma *vma; bool write_domain_objs = false; - int open; drm_WARN_ON(&vm->i915->drm, !vm->is_ggtt && !vm->is_dpt); /* First fill our portion of the GTT with scratch pages */ vm->clear_range(vm, 0, vm->total); - /* Skip rewriting PTE on VMA unbind. */ - open = atomic_xchg(&vm->open, 0); - /* clflush objects bound into the GGTT and rebind them. */ list_for_each_entry(vma, &vm->bound_list, vm_link) { struct drm_i915_gem_object *obj = vma->obj; @@ -1333,8 +1331,6 @@ bool i915_ggtt_resume_vm(struct i915_address_space *vm) } } - atomic_set(&vm->open, open); - return write_domain_objs; } diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 4bcdfcab3642..4f70d512a000 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -97,32 +97,52 @@ int map_pt_dma_locked(struct i915_address_space *vm, struct drm_i915_gem_object return 0; } -void __i915_vm_close(struct i915_address_space *vm) +static void clear_vm_list(struct list_head *list) { struct i915_vma *vma, *vn; - if (!atomic_dec_and_mutex_lock(&vm->open, &vm->mutex)) - return; - - list_for_each_entry_safe(vma, vn, &vm->bound_list, vm_link) { + list_for_each_entry_safe(vma, vn, list, vm_link) { struct drm_i915_gem_object *obj = vma->obj; - if (!kref_get_unless_zero(&obj->base.refcount)) { + if (!i915_gem_object_get_rcu(obj)) { /* - * Unbind the dying vma to ensure the bound_list + * Object is dying, but has not yet cleared its + * vma list. + * Unbind the dying vma to ensure our list * is completely drained. We leave the destruction to - * the object destructor. + * the object destructor to avoid the vma + * disappearing under it. */ atomic_and(~I915_VMA_PIN_MASK, &vma->flags); WARN_ON(__i915_vma_unbind(vma)); - continue; + + /* Remove from the unbound list */ + list_del_init(&vma->vm_link); + + /* + * Delay the vm and vm mutex freeing until the + * object is done with destruction. + */ + i915_vm_resv_get(vma->vm); + vma->vm_ddestroy = true; + } else { + i915_vma_destroy_locked(vma); + i915_gem_object_put(obj); } - /* Keep the obj (and hence the vma) alive as _we_ destroy it */ - i915_vma_destroy_locked(vma); - i915_gem_object_put(obj); } +} + +static void __i915_vm_close(struct i915_address_space *vm) +{ + mutex_lock(&vm->mutex); + + clear_vm_list(&vm->bound_list); + clear_vm_list(&vm->unbound_list); + + /* Check for must-fix unanticipated side-effects */ GEM_BUG_ON(!list_empty(&vm->bound_list)); + GEM_BUG_ON(!list_empty(&vm->unbound_list)); mutex_unlock(&vm->mutex); } @@ -144,7 +164,6 @@ int i915_vm_lock_objects(struct i915_address_space *vm, void i915_address_space_fini(struct i915_address_space *vm) { drm_mm_takedown(&vm->mm); - mutex_destroy(&vm->mutex); } /** @@ -152,7 +171,8 @@ void i915_address_space_fini(struct i915_address_space *vm) * @kref: Pointer to the &i915_address_space.resv_ref member. * * This function is called when the last lock sharer no longer shares the - * &i915_address_space._resv lock. + * &i915_address_space._resv lock, and also if we raced when + * destroying a vma by the vma destruction */ void i915_vm_resv_release(struct kref *kref) { @@ -160,6 +180,8 @@ void i915_vm_resv_release(struct kref *kref) container_of(kref, typeof(*vm), resv_ref); dma_resv_fini(&vm->_resv); + mutex_destroy(&vm->mutex); + kfree(vm); } @@ -168,6 +190,8 @@ static void __i915_vm_release(struct work_struct *work) struct i915_address_space *vm = container_of(work, struct i915_address_space, release_work); + __i915_vm_close(vm); + /* Synchronize async unbinds. */ i915_vma_resource_bind_dep_sync_all(vm); @@ -201,7 +225,6 @@ void i915_address_space_init(struct i915_address_space *vm, int subclass) vm->pending_unbind = RB_ROOT_CACHED; INIT_WORK(&vm->release_work, __i915_vm_release); - atomic_set(&vm->open, 1); /* * The vm->mutex must be reclaim safe (for use in the shrinker). @@ -245,6 +268,7 @@ void i915_address_space_init(struct i915_address_space *vm, int subclass) vm->mm.head_node.color = I915_COLOR_UNEVICTABLE; INIT_LIST_HEAD(&vm->bound_list); + INIT_LIST_HEAD(&vm->unbound_list); } void *__px_vaddr(struct drm_i915_gem_object *p) diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index 9d83c2d3959c..4529b5e9f6e6 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -240,15 +240,6 @@ struct i915_address_space { unsigned int bind_async_flags; - /* - * Each active user context has its own address space (in full-ppgtt). - * Since the vm may be shared between multiple contexts, we count how - * many contexts keep us "open". Once open hits zero, we are closed - * and do not allow any new attachments, and proceed to shutdown our - * vma and page directories. - */ - atomic_t open; - struct mutex mutex; /* protects vma and our lists */ struct kref resv_ref; /* kref to keep the reservation lock alive. */ @@ -263,6 +254,11 @@ struct i915_address_space { */ struct list_head bound_list; + /** + * List of vmas not yet bound or evicted. + */ + struct list_head unbound_list; + /* Global GTT */ bool is_ggtt:1; @@ -272,6 +268,9 @@ struct i915_address_space { /* Some systems support read-only mappings for GGTT and/or PPGTT */ bool has_read_only:1; + /* Skip pte rewrite on unbind for suspend. Protected by @mutex */ + bool skip_pte_rewrite:1; + u8 top; u8 pd_shift; u8 scratch_order; @@ -446,6 +445,17 @@ i915_vm_get(struct i915_address_space *vm) return vm; } +static inline struct i915_address_space * +i915_vm_tryget(struct i915_address_space *vm) +{ + return kref_get_unless_zero(&vm->ref) ? vm : NULL; +} + +static inline void assert_vm_alive(struct i915_address_space *vm) +{ + GEM_BUG_ON(!kref_read(&vm->ref)); +} + /** * i915_vm_resv_get - Obtain a reference on the vm's reservation lock * @vm: The vm whose reservation lock we want to share. @@ -476,34 +486,6 @@ static inline void i915_vm_resv_put(struct i915_address_space *vm) kref_put(&vm->resv_ref, i915_vm_resv_release); } -static inline struct i915_address_space * -i915_vm_open(struct i915_address_space *vm) -{ - GEM_BUG_ON(!atomic_read(&vm->open)); - atomic_inc(&vm->open); - return i915_vm_get(vm); -} - -static inline bool -i915_vm_tryopen(struct i915_address_space *vm) -{ - if (atomic_add_unless(&vm->open, 1, 0)) - return i915_vm_get(vm); - - return false; -} - -void __i915_vm_close(struct i915_address_space *vm); - -static inline void -i915_vm_close(struct i915_address_space *vm) -{ - GEM_BUG_ON(!atomic_read(&vm->open)); - __i915_vm_close(vm); - - i915_vm_put(vm); -} - void i915_address_space_init(struct i915_address_space *vm, int subclass); void i915_address_space_fini(struct i915_address_space *vm); diff --git a/drivers/gpu/drm/i915/gt/selftest_execlists.c b/drivers/gpu/drm/i915/gt/selftest_execlists.c index 72d5faab8f9a..09f8cd2d0e2c 100644 --- a/drivers/gpu/drm/i915/gt/selftest_execlists.c +++ b/drivers/gpu/drm/i915/gt/selftest_execlists.c @@ -1736,15 +1736,9 @@ static int live_preempt(void *arg) enum intel_engine_id id; int err = -ENOMEM; - if (igt_spinner_init(&spin_hi, gt)) - return -ENOMEM; - - if (igt_spinner_init(&spin_lo, gt)) - goto err_spin_hi; - ctx_hi = kernel_context(gt->i915, NULL); if (!ctx_hi) - goto err_spin_lo; + return -ENOMEM; ctx_hi->sched.priority = I915_CONTEXT_MAX_USER_PRIORITY; ctx_lo = kernel_context(gt->i915, NULL); @@ -1752,6 +1746,12 @@ static int live_preempt(void *arg) goto err_ctx_hi; ctx_lo->sched.priority = I915_CONTEXT_MIN_USER_PRIORITY; + if (igt_spinner_init(&spin_hi, gt)) + goto err_ctx_lo; + + if (igt_spinner_init(&spin_lo, gt)) + goto err_spin_hi; + for_each_engine(engine, gt, id) { struct igt_live_test t; struct i915_request *rq; @@ -1761,14 +1761,14 @@ static int live_preempt(void *arg) if (igt_live_test_begin(&t, gt->i915, __func__, engine->name)) { err = -EIO; - goto err_ctx_lo; + goto err_spin_lo; } rq = spinner_create_request(&spin_lo, ctx_lo, engine, MI_ARB_CHECK); if (IS_ERR(rq)) { err = PTR_ERR(rq); - goto err_ctx_lo; + goto err_spin_lo; } i915_request_add(rq); @@ -1777,7 +1777,7 @@ static int live_preempt(void *arg) GEM_TRACE_DUMP(); intel_gt_set_wedged(gt); err = -EIO; - goto err_ctx_lo; + goto err_spin_lo; } rq = spinner_create_request(&spin_hi, ctx_hi, engine, @@ -1785,7 +1785,7 @@ static int live_preempt(void *arg) if (IS_ERR(rq)) { igt_spinner_end(&spin_lo); err = PTR_ERR(rq); - goto err_ctx_lo; + goto err_spin_lo; } i915_request_add(rq); @@ -1794,7 +1794,7 @@ static int live_preempt(void *arg) GEM_TRACE_DUMP(); intel_gt_set_wedged(gt); err = -EIO; - goto err_ctx_lo; + goto err_spin_lo; } igt_spinner_end(&spin_hi); @@ -1802,19 +1802,19 @@ static int live_preempt(void *arg) if (igt_live_test_end(&t)) { err = -EIO; - goto err_ctx_lo; + goto err_spin_lo; } } err = 0; -err_ctx_lo: - kernel_context_close(ctx_lo); -err_ctx_hi: - kernel_context_close(ctx_hi); err_spin_lo: igt_spinner_fini(&spin_lo); err_spin_hi: igt_spinner_fini(&spin_hi); +err_ctx_lo: + kernel_context_close(ctx_lo); +err_ctx_hi: + kernel_context_close(ctx_hi); return err; } @@ -1828,20 +1828,20 @@ static int live_late_preempt(void *arg) enum intel_engine_id id; int err = -ENOMEM; - if (igt_spinner_init(&spin_hi, gt)) - return -ENOMEM; - - if (igt_spinner_init(&spin_lo, gt)) - goto err_spin_hi; - ctx_hi = kernel_context(gt->i915, NULL); if (!ctx_hi) - goto err_spin_lo; + return -ENOMEM; ctx_lo = kernel_context(gt->i915, NULL); if (!ctx_lo) goto err_ctx_hi; + if (igt_spinner_init(&spin_hi, gt)) + goto err_ctx_lo; + + if (igt_spinner_init(&spin_lo, gt)) + goto err_spin_hi; + /* Make sure ctx_lo stays before ctx_hi until we trigger preemption. */ ctx_lo->sched.priority = 1; @@ -1854,14 +1854,14 @@ static int live_late_preempt(void *arg) if (igt_live_test_begin(&t, gt->i915, __func__, engine->name)) { err = -EIO; - goto err_ctx_lo; + goto err_spin_lo; } rq = spinner_create_request(&spin_lo, ctx_lo, engine, MI_ARB_CHECK); if (IS_ERR(rq)) { err = PTR_ERR(rq); - goto err_ctx_lo; + goto err_spin_lo; } i915_request_add(rq); @@ -1875,7 +1875,7 @@ static int live_late_preempt(void *arg) if (IS_ERR(rq)) { igt_spinner_end(&spin_lo); err = PTR_ERR(rq); - goto err_ctx_lo; + goto err_spin_lo; } i915_request_add(rq); @@ -1898,19 +1898,19 @@ static int live_late_preempt(void *arg) if (igt_live_test_end(&t)) { err = -EIO; - goto err_ctx_lo; + goto err_spin_lo; } } err = 0; -err_ctx_lo: - kernel_context_close(ctx_lo); -err_ctx_hi: - kernel_context_close(ctx_hi); err_spin_lo: igt_spinner_fini(&spin_lo); err_spin_hi: igt_spinner_fini(&spin_hi); +err_ctx_lo: + kernel_context_close(ctx_lo); +err_ctx_hi: + kernel_context_close(ctx_hi); return err; err_wedged: @@ -1918,7 +1918,7 @@ err_wedged: igt_spinner_end(&spin_lo); intel_gt_set_wedged(gt); err = -EIO; - goto err_ctx_lo; + goto err_spin_lo; } struct preempt_client { @@ -3382,12 +3382,9 @@ static int live_preempt_timeout(void *arg) if (!intel_has_reset_engine(gt)) return 0; - if (igt_spinner_init(&spin_lo, gt)) - return -ENOMEM; - ctx_hi = kernel_context(gt->i915, NULL); if (!ctx_hi) - goto err_spin_lo; + return -ENOMEM; ctx_hi->sched.priority = I915_CONTEXT_MAX_USER_PRIORITY; ctx_lo = kernel_context(gt->i915, NULL); @@ -3395,6 +3392,9 @@ static int live_preempt_timeout(void *arg) goto err_ctx_hi; ctx_lo->sched.priority = I915_CONTEXT_MIN_USER_PRIORITY; + if (igt_spinner_init(&spin_lo, gt)) + goto err_ctx_lo; + for_each_engine(engine, gt, id) { unsigned long saved_timeout; struct i915_request *rq; @@ -3406,21 +3406,21 @@ static int live_preempt_timeout(void *arg) MI_NOOP); /* preemption disabled */ if (IS_ERR(rq)) { err = PTR_ERR(rq); - goto err_ctx_lo; + goto err_spin_lo; } i915_request_add(rq); if (!igt_wait_for_spinner(&spin_lo, rq)) { intel_gt_set_wedged(gt); err = -EIO; - goto err_ctx_lo; + goto err_spin_lo; } rq = igt_request_alloc(ctx_hi, engine); if (IS_ERR(rq)) { igt_spinner_end(&spin_lo); err = PTR_ERR(rq); - goto err_ctx_lo; + goto err_spin_lo; } /* Flush the previous CS ack before changing timeouts */ @@ -3440,7 +3440,7 @@ static int live_preempt_timeout(void *arg) intel_gt_set_wedged(gt); i915_request_put(rq); err = -ETIME; - goto err_ctx_lo; + goto err_spin_lo; } igt_spinner_end(&spin_lo); @@ -3448,12 +3448,12 @@ static int live_preempt_timeout(void *arg) } err = 0; +err_spin_lo: + igt_spinner_fini(&spin_lo); err_ctx_lo: kernel_context_close(ctx_lo); err_ctx_hi: kernel_context_close(ctx_hi); -err_spin_lo: - igt_spinner_fini(&spin_lo); return err; } diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2e10187cd0a0..dd84ebabb50f 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -142,8 +142,6 @@ try_again: while (!ret && (vma = list_first_entry_or_null(&obj->vma.list, struct i915_vma, obj_link))) { - struct i915_address_space *vm = vma->vm; - list_move_tail(&vma->obj_link, &still_in_list); if (!i915_vma_is_bound(vma, I915_VMA_BIND_MASK)) continue; @@ -154,7 +152,7 @@ try_again: } ret = -EAGAIN; - if (!i915_vm_tryopen(vm)) + if (!i915_vm_tryget(vma->vm)) break; /* Prevent vma being freed by i915_vma_parked as we unbind */ @@ -186,7 +184,7 @@ try_again: __i915_vma_put(vma); } - i915_vm_close(vm); + i915_vm_put(vma->vm); spin_lock(&obj->vma.lock); } list_splice_init(&still_in_list, &obj->vma.list); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 94fcdb7bd21d..cfa8a212b4dd 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -47,7 +47,7 @@ static inline void assert_vma_held_evict(const struct i915_vma *vma) * This is the only exception to the requirement of the object lock * being held. */ - if (atomic_read(&vma->vm->open)) + if (kref_read(&vma->vm->ref)) assert_object_held_shared(vma->obj); } @@ -113,6 +113,7 @@ vma_create(struct drm_i915_gem_object *obj, struct i915_vma *pos = ERR_PTR(-E2BIG); struct i915_vma *vma; struct rb_node *rb, **p; + int err; /* The aliasing_ppgtt should never be used directly! */ GEM_BUG_ON(vm == &vm->gt->ggtt->alias->vm); @@ -122,7 +123,6 @@ vma_create(struct drm_i915_gem_object *obj, return ERR_PTR(-ENOMEM); kref_init(&vma->ref); - vma->vm = i915_vm_get(vm); vma->ops = &vm->vma_ops; vma->obj = obj; vma->size = obj->base.size; @@ -138,6 +138,8 @@ vma_create(struct drm_i915_gem_object *obj, } INIT_LIST_HEAD(&vma->closed_link); + INIT_LIST_HEAD(&vma->obj_link); + RB_CLEAR_NODE(&vma->obj_node); if (view && view->type != I915_GGTT_VIEW_NORMAL) { vma->ggtt_view = *view; @@ -163,8 +165,16 @@ vma_create(struct drm_i915_gem_object *obj, GEM_BUG_ON(!IS_ALIGNED(vma->size, I915_GTT_PAGE_SIZE)); - spin_lock(&obj->vma.lock); + err = mutex_lock_interruptible(&vm->mutex); + if (err) { + pos = ERR_PTR(err); + goto err_vma; + } + vma->vm = vm; + list_add_tail(&vma->vm_link, &vm->unbound_list); + + spin_lock(&obj->vma.lock); if (i915_is_ggtt(vm)) { if (unlikely(overflows_type(vma->size, u32))) goto err_unlock; @@ -222,13 +232,15 @@ vma_create(struct drm_i915_gem_object *obj, list_add_tail(&vma->obj_link, &obj->vma.list); spin_unlock(&obj->vma.lock); + mutex_unlock(&vm->mutex); return vma; err_unlock: spin_unlock(&obj->vma.lock); + list_del_init(&vma->vm_link); + mutex_unlock(&vm->mutex); err_vma: - i915_vm_put(vm); i915_vma_free(vma); return pos; } @@ -279,7 +291,7 @@ i915_vma_instance(struct drm_i915_gem_object *obj, struct i915_vma *vma; GEM_BUG_ON(view && !i915_is_ggtt_or_dpt(vm)); - GEM_BUG_ON(!atomic_read(&vm->open)); + GEM_BUG_ON(!kref_read(&vm->ref)); spin_lock(&obj->vma.lock); vma = i915_vma_lookup(obj, vm, view); @@ -322,7 +334,6 @@ static void __vma_release(struct dma_fence_work *work) i915_gem_object_put(vw->pinned); i915_vm_free_pt_stash(vw->vm, &vw->stash); - i915_vm_put(vw->vm); if (vw->vma_res) i915_vma_resource_put(vw->vma_res); } @@ -841,7 +852,7 @@ i915_vma_insert(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, GEM_BUG_ON(!drm_mm_node_allocated(&vma->node)); GEM_BUG_ON(!i915_gem_valid_gtt_space(vma, color)); - list_add_tail(&vma->vm_link, &vma->vm->bound_list); + list_move_tail(&vma->vm_link, &vma->vm->bound_list); return 0; } @@ -857,7 +868,7 @@ i915_vma_detach(struct i915_vma *vma) * vma, we can drop its hold on the backing storage and allow * it to be reaped by the shrinker. */ - list_del(&vma->vm_link); + list_move_tail(&vma->vm_link, &vma->vm->unbound_list); } static bool try_qad_pin(struct i915_vma *vma, unsigned int flags) @@ -1373,8 +1384,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, goto err_rpm; } - work->vm = i915_vm_get(vma->vm); - + work->vm = vma->vm; dma_fence_work_chain(&work->base, moving); /* Allocate enough page directories to used PTE */ @@ -1622,7 +1632,6 @@ void i915_vma_release(struct kref *ref) { struct i915_vma *vma = container_of(ref, typeof(*vma), ref); - i915_vm_put(vma->vm); i915_active_fini(&vma->active); GEM_WARN_ON(vma->resource); i915_vma_free(vma); @@ -1638,7 +1647,7 @@ static void force_unbind(struct i915_vma *vma) GEM_BUG_ON(drm_mm_node_allocated(&vma->node)); } -static void release_references(struct i915_vma *vma) +static void release_references(struct i915_vma *vma, bool vm_ddestroy) { struct drm_i915_gem_object *obj = vma->obj; @@ -1648,10 +1657,14 @@ static void release_references(struct i915_vma *vma) list_del(&vma->obj_link); if (!RB_EMPTY_NODE(&vma->obj_node)) rb_erase(&vma->obj_node, &obj->vma.tree); + spin_unlock(&obj->vma.lock); __i915_vma_remove_closed(vma); + if (vm_ddestroy) + i915_vm_resv_put(vma->vm); + __i915_vma_put(vma); } @@ -1667,8 +1680,12 @@ static void release_references(struct i915_vma *vma) * - __i915_gem_object_pages_fini() * - __i915_vm_close() - Blocks the above function by taking a reference on * the object. - * - __i915_vma_parked() - Blocks the above functions by taking an open-count on - * the vm and a reference on the object. + * - __i915_vma_parked() - Blocks the above functions by taking a reference + * on the vm and a reference on the object. Also takes the object lock so + * destruction from __i915_vma_parked() can be blocked by holding the + * object lock. Since the object lock is only allowed from within i915 with + * an object refcount, holding the object lock also implicitly blocks the + * vma freeing from __i915_gem_object_pages_fini(). * * Because of locks taken during destruction, a vma is also guaranteed to * stay alive while the following locks are held if it was looked up while @@ -1685,15 +1702,21 @@ void i915_vma_destroy_locked(struct i915_vma *vma) lockdep_assert_held(&vma->vm->mutex); force_unbind(vma); - release_references(vma); + list_del_init(&vma->vm_link); + release_references(vma, false); } void i915_vma_destroy(struct i915_vma *vma) { + bool vm_ddestroy; + mutex_lock(&vma->vm->mutex); force_unbind(vma); + list_del_init(&vma->vm_link); + vm_ddestroy = vma->vm_ddestroy; + vma->vm_ddestroy = false; mutex_unlock(&vma->vm->mutex); - release_references(vma); + release_references(vma, vm_ddestroy); } void i915_vma_parked(struct intel_gt *gt) @@ -1711,7 +1734,7 @@ void i915_vma_parked(struct intel_gt *gt) if (!kref_get_unless_zero(&obj->base.refcount)) continue; - if (!i915_vm_tryopen(vm)) { + if (!i915_vm_tryget(vm)) { i915_gem_object_put(obj); continue; } @@ -1737,7 +1760,7 @@ void i915_vma_parked(struct intel_gt *gt) } i915_gem_object_put(obj); - i915_vm_close(vm); + i915_vm_put(vm); } } @@ -1888,7 +1911,9 @@ struct dma_fence *__i915_vma_evict(struct i915_vma *vma, bool async) /* If vm is not open, unbind is a nop. */ vma_res->needs_wakeref = i915_vma_is_bound(vma, I915_VMA_GLOBAL_BIND) && - atomic_read(&vma->vm->open); + kref_read(&vma->vm->ref); + vma_res->skip_pte_rewrite = !kref_read(&vma->vm->ref) || + vma->vm->skip_pte_rewrite; trace_i915_vma_unbind(vma); unbind_fence = i915_vma_resource_unbind(vma_res); diff --git a/drivers/gpu/drm/i915/i915_vma_resource.c b/drivers/gpu/drm/i915/i915_vma_resource.c index 57ae92ba8af1..27c55027387a 100644 --- a/drivers/gpu/drm/i915/i915_vma_resource.c +++ b/drivers/gpu/drm/i915/i915_vma_resource.c @@ -178,7 +178,7 @@ static void i915_vma_resource_unbind_work(struct work_struct *work) bool lockdep_cookie; lockdep_cookie = dma_fence_begin_signalling(); - if (likely(atomic_read(&vm->open))) + if (likely(!vma_res->skip_pte_rewrite)) vma_res->ops->unbind_vma(vm, vma_res); dma_fence_end_signalling(lockdep_cookie); diff --git a/drivers/gpu/drm/i915/i915_vma_resource.h b/drivers/gpu/drm/i915/i915_vma_resource.h index 25913913baa6..5d8427caa2ba 100644 --- a/drivers/gpu/drm/i915/i915_vma_resource.h +++ b/drivers/gpu/drm/i915/i915_vma_resource.h @@ -62,6 +62,11 @@ struct i915_page_sizes { * deferred to a work item awaiting unsignaled fences. This is a hack. * (dma_fence_work uses a fence flag for this, but this seems slightly * cleaner). + * @needs_wakeref: Whether a wakeref is needed during unbind. Since we can't + * take a wakeref in the dma-fence signalling critical path, it needs to be + * taken when the unbind is scheduled. + * @skip_pte_rewrite: During ggtt suspend and vm takedown pte rewriting + * needs to be skipped for unbind. * * The lifetime of a struct i915_vma_resource is from a binding request to * the actual possible asynchronous unbind has completed. @@ -113,6 +118,7 @@ struct i915_vma_resource { bool allocated:1; bool immediate_unbind:1; bool needs_wakeref:1; + bool skip_pte_rewrite:1; }; bool i915_vma_resource_hold(struct i915_vma_resource *vma_res, diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h index 88370dadca82..eac36be184e5 100644 --- a/drivers/gpu/drm/i915/i915_vma_types.h +++ b/drivers/gpu/drm/i915/i915_vma_types.h @@ -271,6 +271,13 @@ struct i915_vma { #define I915_VMA_PAGES_ACTIVE (BIT(24) | 1) atomic_t pages_count; /* number of active binds to the pages */ + /** + * Whether we hold a reference on the vm dma_resv lock to temporarily + * block vm freeing until the vma is destroyed. + * Protected by the vm mutex. + */ + bool vm_ddestroy; + /** * Support different GGTT views into the same object. * This means there can be multiple VMA mappings per object and per VM. diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index ab751192eb3b..5c9bfa409ff5 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -1205,7 +1205,7 @@ static int exercise_ppgtt(struct drm_i915_private *dev_priv, goto out_free; } GEM_BUG_ON(offset_in_page(ppgtt->vm.total)); - GEM_BUG_ON(!atomic_read(&ppgtt->vm.open)); + assert_vm_alive(&ppgtt->vm); err = func(&ppgtt->vm, 0, ppgtt->vm.total, end_time); @@ -1438,7 +1438,7 @@ static void track_vma_bind(struct i915_vma *vma) vma->resource->bi.pages = vma->pages; mutex_lock(&vma->vm->mutex); - list_add_tail(&vma->vm_link, &vma->vm->bound_list); + list_move_tail(&vma->vm_link, &vma->vm->bound_list); mutex_unlock(&vma->vm->mutex); } From d93939730347360db0afe6a4367451b6f84ab7b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Fri, 4 Mar 2022 09:26:40 +0100 Subject: [PATCH 00098/11454] drm/i915: Remove the vma refcount MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that i915_vma_parked() is taking the object lock on vma destruction, and the only user of the vma refcount, i915_gem_object_unbind() also takes the object lock, remove the vma refcount. v3: Documentation update. Signed-off-by: Thomas Hellström Reviewed-by: Niranjana Vishwanathapura Link: https://patchwork.freedesktop.org/patch/msgid/20220304082641.308069-3-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/i915/i915_gem.c | 17 +++++++++++++---- drivers/gpu/drm/i915/i915_vma.c | 17 +++-------------- drivers/gpu/drm/i915/i915_vma.h | 14 -------------- drivers/gpu/drm/i915/i915_vma_types.h | 1 - 4 files changed, 16 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index dd84ebabb50f..c26110abcc0b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -151,14 +151,25 @@ try_again: break; } + /* + * Requiring the vm destructor to take the object lock + * before destroying a vma would help us eliminate the + * i915_vm_tryget() here, AND thus also the barrier stuff + * at the end. That's an easy fix, but sleeping locks in + * a kthread should generally be avoided. + */ ret = -EAGAIN; if (!i915_vm_tryget(vma->vm)) break; - /* Prevent vma being freed by i915_vma_parked as we unbind */ - vma = __i915_vma_get(vma); spin_unlock(&obj->vma.lock); + /* + * Since i915_vma_parked() takes the object lock + * before vma destruction, it won't race us here, + * and destroy the vma from under us. + */ + if (vma) { bool vm_trylock = !!(flags & I915_GEM_OBJECT_UNBIND_VM_TRYLOCK); ret = -EBUSY; @@ -180,8 +191,6 @@ try_again: ret = i915_vma_unbind(vma); } } - - __i915_vma_put(vma); } i915_vm_put(vma->vm); diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index cfa8a212b4dd..249a38585289 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -122,7 +122,6 @@ vma_create(struct drm_i915_gem_object *obj, if (vma == NULL) return ERR_PTR(-ENOMEM); - kref_init(&vma->ref); vma->ops = &vm->vma_ops; vma->obj = obj; vma->size = obj->base.size; @@ -1628,15 +1627,6 @@ void i915_vma_reopen(struct i915_vma *vma) __i915_vma_remove_closed(vma); } -void i915_vma_release(struct kref *ref) -{ - struct i915_vma *vma = container_of(ref, typeof(*vma), ref); - - i915_active_fini(&vma->active); - GEM_WARN_ON(vma->resource); - i915_vma_free(vma); -} - static void force_unbind(struct i915_vma *vma) { if (!drm_mm_node_allocated(&vma->node)) @@ -1665,7 +1655,9 @@ static void release_references(struct i915_vma *vma, bool vm_ddestroy) if (vm_ddestroy) i915_vm_resv_put(vma->vm); - __i915_vma_put(vma); + i915_active_fini(&vma->active); + GEM_WARN_ON(vma->resource); + i915_vma_free(vma); } /** @@ -1693,9 +1685,6 @@ static void release_references(struct i915_vma *vma, bool vm_ddestroy) * - vm->mutex * - obj->vma.lock * - gt->closed_lock - * - * A vma user can also temporarily keep the vma alive while holding a vma - * reference. */ void i915_vma_destroy_locked(struct i915_vma *vma) { diff --git a/drivers/gpu/drm/i915/i915_vma.h b/drivers/gpu/drm/i915/i915_vma.h index 67ae7341c7e0..6034991d89fe 100644 --- a/drivers/gpu/drm/i915/i915_vma.h +++ b/drivers/gpu/drm/i915/i915_vma.h @@ -222,20 +222,6 @@ void i915_vma_unlink_ctx(struct i915_vma *vma); void i915_vma_close(struct i915_vma *vma); void i915_vma_reopen(struct i915_vma *vma); -static inline struct i915_vma *__i915_vma_get(struct i915_vma *vma) -{ - if (kref_get_unless_zero(&vma->ref)) - return vma; - - return NULL; -} - -void i915_vma_release(struct kref *ref); -static inline void __i915_vma_put(struct i915_vma *vma) -{ - kref_put(&vma->ref, i915_vma_release); -} - void i915_vma_destroy_locked(struct i915_vma *vma); void i915_vma_destroy(struct i915_vma *vma); diff --git a/drivers/gpu/drm/i915/i915_vma_types.h b/drivers/gpu/drm/i915/i915_vma_types.h index eac36be184e5..be6e028c3b57 100644 --- a/drivers/gpu/drm/i915/i915_vma_types.h +++ b/drivers/gpu/drm/i915/i915_vma_types.h @@ -211,7 +211,6 @@ struct i915_vma { * handles (but same file) for execbuf, i.e. the number of aliases * that exist in the ctx->handle_vmas LUT for this vma. */ - struct kref ref; atomic_t open_count; atomic_t flags; /** From eb950819218af113b57cd5cd3441af4077a9baaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Hellstr=C3=B6m?= Date: Fri, 4 Mar 2022 09:26:41 +0100 Subject: [PATCH 00099/11454] drm/i915/gem: Remove some unnecessary code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test for vma should always return true, and when assigning -EBUSY to ret, the variable should already have that value. Signed-off-by: Thomas Hellström Reviewed-by: Niranjana Vishwanathapura Link: https://patchwork.freedesktop.org/patch/msgid/20220304082641.308069-4-thomas.hellstrom@linux.intel.com --- drivers/gpu/drm/i915/i915_gem.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c26110abcc0b..9747924cc57b 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -118,6 +118,7 @@ int i915_gem_object_unbind(struct drm_i915_gem_object *obj, unsigned long flags) { struct intel_runtime_pm *rpm = &to_i915(obj->base.dev)->runtime_pm; + bool vm_trylock = !!(flags & I915_GEM_OBJECT_UNBIND_VM_TRYLOCK); LIST_HEAD(still_in_list); intel_wakeref_t wakeref; struct i915_vma *vma; @@ -170,26 +171,21 @@ try_again: * and destroy the vma from under us. */ - if (vma) { - bool vm_trylock = !!(flags & I915_GEM_OBJECT_UNBIND_VM_TRYLOCK); - ret = -EBUSY; - if (flags & I915_GEM_OBJECT_UNBIND_ASYNC) { - assert_object_held(vma->obj); - ret = i915_vma_unbind_async(vma, vm_trylock); - } + ret = -EBUSY; + if (flags & I915_GEM_OBJECT_UNBIND_ASYNC) { + assert_object_held(vma->obj); + ret = i915_vma_unbind_async(vma, vm_trylock); + } - if (ret == -EBUSY && (flags & I915_GEM_OBJECT_UNBIND_ACTIVE || - !i915_vma_is_active(vma))) { - if (vm_trylock) { - if (mutex_trylock(&vma->vm->mutex)) { - ret = __i915_vma_unbind(vma); - mutex_unlock(&vma->vm->mutex); - } else { - ret = -EBUSY; - } - } else { - ret = i915_vma_unbind(vma); + if (ret == -EBUSY && (flags & I915_GEM_OBJECT_UNBIND_ACTIVE || + !i915_vma_is_active(vma))) { + if (vm_trylock) { + if (mutex_trylock(&vma->vm->mutex)) { + ret = __i915_vma_unbind(vma); + mutex_unlock(&vma->vm->mutex); } + } else { + ret = i915_vma_unbind(vma); } } From 892bfb8a604d464925edca9a5c3d2b2062c2124d Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Fri, 4 Mar 2022 09:59:33 +0000 Subject: [PATCH 00100/11454] drm/i915/fbdev: fixup setting screen_size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since we are actually mapping the object and not the vma, when dealing with LMEM, we should be careful and use the backing store size here, since the vma->node.size could have all kinds of funny padding constraints, which could result in us writing to OOB address. v2(Chris): - Prefer vma->size here, which should be the backing store size. Some more rework is needed here to stop using node.size in some other places. Signed-off-by: Matthew Auld Cc: Stanislav Lisovskiy Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20220304095934.925036-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/display/intel_fbdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fbdev.c b/drivers/gpu/drm/i915/display/intel_fbdev.c index 2cd62a187df3..221336178991 100644 --- a/drivers/gpu/drm/i915/display/intel_fbdev.c +++ b/drivers/gpu/drm/i915/display/intel_fbdev.c @@ -279,7 +279,7 @@ static int intelfb_create(struct drm_fb_helper *helper, /* Our framebuffer is the entirety of fbdev's system memory */ info->fix.smem_start = (unsigned long)(ggtt->gmadr.start + vma->node.start); - info->fix.smem_len = vma->node.size; + info->fix.smem_len = vma->size; } vaddr = i915_vma_pin_iomap(vma); @@ -290,7 +290,7 @@ static int intelfb_create(struct drm_fb_helper *helper, goto out_unpin; } info->screen_base = vaddr; - info->screen_size = vma->node.size; + info->screen_size = vma->size; drm_fb_helper_fill_info(info, &ifbdev->helper, sizes); From 71abfcbeae3e8b48c40c0ff58cec907269b7db73 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 4 Mar 2022 12:14:25 +0200 Subject: [PATCH 00101/11454] drm/i915/gmbus: move some local bus variables within loops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Limit the scope. Suggested-by: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220304101426.1891347-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_gmbus.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 2bb3494b93e2..8f26528c3dc7 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -868,7 +868,6 @@ static const struct i2c_lock_operations gmbus_lock_ops = { int intel_gmbus_setup(struct drm_i915_private *dev_priv) { struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); - struct intel_gmbus *bus; unsigned int pin; int ret; @@ -886,6 +885,7 @@ int intel_gmbus_setup(struct drm_i915_private *dev_priv) for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { const struct gmbus_pin *gmbus_pin; + struct intel_gmbus *bus; gmbus_pin = get_gmbus_pin(dev_priv, pin); if (!gmbus_pin) @@ -978,10 +978,11 @@ bool intel_gmbus_is_forced_bit(struct i2c_adapter *adapter) void intel_gmbus_teardown(struct drm_i915_private *dev_priv) { - struct intel_gmbus *bus; unsigned int pin; for (pin = 0; pin < ARRAY_SIZE(dev_priv->gmbus); pin++) { + struct intel_gmbus *bus; + bus = dev_priv->gmbus[pin]; if (!bus) continue; From 17e571fe720dae18eb5e743b0e6217f235d5338c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 4 Mar 2022 12:14:26 +0200 Subject: [PATCH 00102/11454] drm/i915/gmbus: use to_intel_gmbus() instead of open coding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a helper for getting at the enclosing gmbus struct from the embedded i2c_adapter, use it. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220304101426.1891347-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_gmbus.c | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_gmbus.c b/drivers/gpu/drm/i915/display/intel_gmbus.c index 8f26528c3dc7..21281a7bdc17 100644 --- a/drivers/gpu/drm/i915/display/intel_gmbus.c +++ b/drivers/gpu/drm/i915/display/intel_gmbus.c @@ -300,9 +300,7 @@ static void set_data(void *data, int state_high) static int intel_gpio_pre_xfer(struct i2c_adapter *adapter) { - struct intel_gmbus *bus = container_of(adapter, - struct intel_gmbus, - adapter); + struct intel_gmbus *bus = to_intel_gmbus(adapter); struct drm_i915_private *dev_priv = bus->dev_priv; intel_gmbus_reset(dev_priv); @@ -319,9 +317,7 @@ intel_gpio_pre_xfer(struct i2c_adapter *adapter) static void intel_gpio_post_xfer(struct i2c_adapter *adapter) { - struct intel_gmbus *bus = container_of(adapter, - struct intel_gmbus, - adapter); + struct intel_gmbus *bus = to_intel_gmbus(adapter); struct drm_i915_private *dev_priv = bus->dev_priv; set_data(bus, 1); @@ -619,9 +615,7 @@ static int do_gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num, u32 gmbus0_source) { - struct intel_gmbus *bus = container_of(adapter, - struct intel_gmbus, - adapter); + struct intel_gmbus *bus = to_intel_gmbus(adapter); struct drm_i915_private *dev_priv = bus->dev_priv; int i = 0, inc, try = 0; int ret = 0; @@ -751,8 +745,7 @@ out: static int gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) { - struct intel_gmbus *bus = - container_of(adapter, struct intel_gmbus, adapter); + struct intel_gmbus *bus = to_intel_gmbus(adapter); struct drm_i915_private *dev_priv = bus->dev_priv; intel_wakeref_t wakeref; int ret; @@ -776,8 +769,7 @@ gmbus_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, int num) int intel_gmbus_output_aksv(struct i2c_adapter *adapter) { - struct intel_gmbus *bus = - container_of(adapter, struct intel_gmbus, adapter); + struct intel_gmbus *bus = to_intel_gmbus(adapter); struct drm_i915_private *dev_priv = bus->dev_priv; u8 cmd = DRM_HDCP_DDC_AKSV; u8 buf[DRM_HDCP_KSV_LEN] = { 0 }; From 833124a0d1698912f47090683908484a1a937a13 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Fri, 4 Mar 2022 09:59:34 +0000 Subject: [PATCH 00103/11454] drm/i915: limit the async bind to bind_async_flags MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the vm doesn't request async binding, like for example with the dpt, then we should be able to skip the async path and avoid calling i915_vm_lock_objects() altogether. Currently if we have a moving fence set for the BO(even though it might have signalled), we still take the async patch regardless of the bind_async setting, and then later still end up just doing i915_gem_object_wait_moving_fence() anyway. Alternatively we would need to add dummy scratch object which can be locked, just for the dpt. Suggested-by: Thomas Hellström Signed-off-by: Matthew Auld Cc: Stanislav Lisovskiy Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20220304095934.925036-2-matthew.auld@intel.com --- drivers/gpu/drm/i915/i915_vma.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index 249a38585289..a3fee872465d 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -1370,8 +1370,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, if (flags & PIN_GLOBAL) wakeref = intel_runtime_pm_get(&vma->vm->i915->runtime_pm); - moving = vma->obj ? i915_gem_object_get_moving_fence(vma->obj) : NULL; - if (flags & vma->vm->bind_async_flags || moving) { + if (flags & vma->vm->bind_async_flags) { /* lock VM */ err = i915_vm_lock_objects(vma->vm, ww); if (err) @@ -1384,6 +1383,8 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, } work->vm = vma->vm; + + moving = vma->obj ? i915_gem_object_get_moving_fence(vma->obj) : NULL; dma_fence_work_chain(&work->base, moving); /* Allocate enough page directories to used PTE */ From e4b3ee71ec2a6378ce9d4f4a3160b00921241f48 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Fri, 4 Mar 2022 17:42:52 +0000 Subject: [PATCH 00104/11454] drm/i915: stop checking for NULL vma->obj MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is no longer possible since e6e1a304d759 ("drm/i915: vma is always backed by an object."). Signed-off-by: Matthew Auld Cc: Thomas Hellström Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20220304174252.1000238-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/i915_vma.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c index a3fee872465d..34e2608211f5 100644 --- a/drivers/gpu/drm/i915/i915_vma.c +++ b/drivers/gpu/drm/i915/i915_vma.c @@ -525,21 +525,18 @@ int i915_vma_bind(struct i915_vma *vma, if (!work->vma_res->bi.pages_rsgt) work->pinned = i915_gem_object_get(vma->obj); } else { - if (vma->obj) { - ret = i915_gem_object_wait_moving_fence(vma->obj, true); - if (ret) { - i915_vma_resource_free(vma->resource); - vma->resource = NULL; + ret = i915_gem_object_wait_moving_fence(vma->obj, true); + if (ret) { + i915_vma_resource_free(vma->resource); + vma->resource = NULL; - return ret; - } + return ret; } vma->ops->bind_vma(vma->vm, NULL, vma->resource, cache_level, bind_flags); } - if (vma->obj) - set_bit(I915_BO_WAS_BOUND_BIT, &vma->obj->flags); + set_bit(I915_BO_WAS_BOUND_BIT, &vma->obj->flags); atomic_or(bind_flags, &vma->flags); return 0; @@ -1384,7 +1381,7 @@ int i915_vma_pin_ww(struct i915_vma *vma, struct i915_gem_ww_ctx *ww, work->vm = vma->vm; - moving = vma->obj ? i915_gem_object_get_moving_fence(vma->obj) : NULL; + moving = i915_gem_object_get_moving_fence(vma->obj); dma_fence_work_chain(&work->base, moving); /* Allocate enough page directories to used PTE */ From f6e68388443ff50088e224b3a75090bdc0403be6 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 3 Mar 2022 13:44:56 +0100 Subject: [PATCH 00105/11454] drm: Drop commas after SoC match table sentinels It does not make sense to have a comma after a sentinel, as any new elements must be added before the sentinel. Signed-off-by: Geert Uytterhoeven Reviewed-by: Neil Armstrong Acked-by: Martin Blumenstingl Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/298f0644275d7d0b4aa3ee7143756a2431a4900c.1646311443.git.geert+renesas@glider.be --- drivers/gpu/drm/bridge/nwl-dsi.c | 2 +- drivers/gpu/drm/meson/meson_drv.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 71b24e2d64f5..14c763e1fa6f 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -1155,7 +1155,7 @@ MODULE_DEVICE_TABLE(of, nwl_dsi_dt_ids); static const struct soc_device_attribute nwl_dsi_quirks_match[] = { { .soc_id = "i.MX8MQ", .revision = "2.0", .data = (void *)E11418_HS_MODE_QUIRK }, - { /* sentinel. */ }, + { /* sentinel. */ } }; static int nwl_dsi_probe(struct platform_device *pdev) diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 93a7a033a3e8..6c2b0c90b69e 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -168,7 +168,7 @@ static const struct meson_drm_soc_attr meson_drm_soc_attrs[] = { }, .attrs = (const struct soc_device_attribute []) { { .soc_id = "GXL (S805*)", }, - { /* sentinel */ }, + { /* sentinel */ } } }, }; From 016d1ca3f6ad05676fd9e418715ddce1f4ab5a73 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 7 Mar 2022 15:54:58 +0300 Subject: [PATCH 00106/11454] drm/selftests: missing error code in igt_buddy_alloc_smoke() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the error code to -ENOMEM if drm_random_order() fails. Fixes: e6ff5ef81170 ("drm/selftests: add drm buddy smoke testcase") Signed-off-by: Dan Carpenter Reviewed-by: Arunpravin Signed-off-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20220307125458.GA16710@kili --- drivers/gpu/drm/selftests/test-drm_buddy.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/selftests/test-drm_buddy.c b/drivers/gpu/drm/selftests/test-drm_buddy.c index 913cbd7eae04..aca0c491040f 100644 --- a/drivers/gpu/drm/selftests/test-drm_buddy.c +++ b/drivers/gpu/drm/selftests/test-drm_buddy.c @@ -488,8 +488,10 @@ static int igt_buddy_alloc_smoke(void *arg) } order = drm_random_order(mm.max_order + 1, &prng); - if (!order) + if (!order) { + err = -ENOMEM; goto out_fini; + } for (i = 0; i <= mm.max_order; ++i) { struct drm_buddy_block *block; From 8f2a3970c969d0d8d7289a4c65edcedafc16fd92 Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Mon, 7 Mar 2022 17:56:12 +0800 Subject: [PATCH 00107/11454] drm/omap: fix NULL but dereferenced coccicheck error Fix the following coccicheck warning: ./drivers/gpu/drm/omapdrm/omap_overlay.c:89:22-25: ERROR: r_ovl is NULL but dereferenced. Here should be ovl->idx rather than r_ovl->idx. Fixes: e02b5cc9e898ad ("drm/omap: Add a 'right overlay' to plane state") Signed-off-by: Wan Jiabing Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20220307095612.409090-1-wanjiabing@vivo.com --- drivers/gpu/drm/omapdrm/omap_overlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/omapdrm/omap_overlay.c b/drivers/gpu/drm/omapdrm/omap_overlay.c index 10730c9b2752..b0bc9ad2ef73 100644 --- a/drivers/gpu/drm/omapdrm/omap_overlay.c +++ b/drivers/gpu/drm/omapdrm/omap_overlay.c @@ -86,7 +86,7 @@ int omap_overlay_assign(struct drm_atomic_state *s, struct drm_plane *plane, r_ovl = omap_plane_find_free_overlay(s->dev, overlay_map, caps, fourcc); if (!r_ovl) { - overlay_map[r_ovl->idx] = NULL; + overlay_map[ovl->idx] = NULL; *overlay = NULL; return -ENOMEM; } From 8a0982b60f5a4a66c8a28eed37769021c20d8c50 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 21 Feb 2022 10:58:57 +0100 Subject: [PATCH 00108/11454] drm/komeda: plane: switch to plane reset helper komeda_plane_reset() does the state initialisation by copying a lot of the code found in the __drm_atomic_helper_plane_reset(). Let's switch to that helper and reduce the boilerplate. Cc: Brian Starkey Cc: "James (Qian) Wang" Cc: Liviu Dudau Cc: Mihail Atanassov Signed-off-by: Maxime Ripard Acked-by: Liviu Dudau Link: https://patchwork.freedesktop.org/patch/msgid/20220221095918.18763-2-maxime@cerno.tech --- drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c index d63d83800a8a..1778f6e1ea56 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c @@ -145,14 +145,10 @@ static void komeda_plane_reset(struct drm_plane *plane) state = kzalloc(sizeof(*state), GFP_KERNEL); if (state) { - state->base.rotation = DRM_MODE_ROTATE_0; - state->base.pixel_blend_mode = DRM_MODE_BLEND_PREMULTI; - state->base.alpha = DRM_BLEND_ALPHA_OPAQUE; + __drm_atomic_helper_plane_reset(plane, &state->base); state->base.zpos = kplane->layer->base.id; state->base.color_encoding = DRM_COLOR_YCBCR_BT601; state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; - plane->state = &state->base; - plane->state->plane = plane; } } From c410976a72823015341ffeeebede36e4a9a08eb2 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 21 Feb 2022 10:59:05 +0100 Subject: [PATCH 00109/11454] drm/komeda: plane: Remove redundant zpos initialisation The komeda KMS driver will call drm_plane_create_zpos_property() with an init value of the plane index. Since the initial value wasn't carried over in the state, the driver had to set it again in komeda_plane_reset(). However, the helpers have been adjusted to set it properly at reset, so this is not needed anymore. Cc: Brian Starkey Cc: "James (Qian) Wang" Cc: Liviu Dudau Cc: Mihail Atanassov Signed-off-by: Maxime Ripard Acked-by: Liviu Dudau Link: https://patchwork.freedesktop.org/patch/msgid/20220221095918.18763-10-maxime@cerno.tech --- drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c index 1778f6e1ea56..383bb2039bd4 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c @@ -135,7 +135,6 @@ static void komeda_plane_destroy(struct drm_plane *plane) static void komeda_plane_reset(struct drm_plane *plane) { struct komeda_plane_state *state; - struct komeda_plane *kplane = to_kplane(plane); if (plane->state) __drm_atomic_helper_plane_destroy_state(plane->state); @@ -146,7 +145,6 @@ static void komeda_plane_reset(struct drm_plane *plane) state = kzalloc(sizeof(*state), GFP_KERNEL); if (state) { __drm_atomic_helper_plane_reset(plane, &state->base); - state->base.zpos = kplane->layer->base.id; state->base.color_encoding = DRM_COLOR_YCBCR_BT601; state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; } From e026f2880235025643fd7d68dbe972d544d7f44f Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 21 Feb 2022 10:59:15 +0100 Subject: [PATCH 00110/11454] drm/komeda: plane: Remove redundant color encoding and range initialisation The komeda KMS driver will call drm_plane_create_color_properties() with a default encoding and range values of BT601 and Limited Range, respectively. Since the initial value wasn't carried over in the state, the driver had to set it again in komeda_plane_reset(). However, the helpers have been adjusted to set it properly at reset, so this is not needed anymore. Cc: Brian Starkey Cc: "James (Qian) Wang" Cc: Liviu Dudau Cc: Mihail Atanassov Signed-off-by: Maxime Ripard Acked-by: Liviu Dudau Link: https://patchwork.freedesktop.org/patch/msgid/20220221095918.18763-20-maxime@cerno.tech --- drivers/gpu/drm/arm/display/komeda/komeda_plane.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c index 383bb2039bd4..541949f2d44a 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c @@ -143,11 +143,8 @@ static void komeda_plane_reset(struct drm_plane *plane) plane->state = NULL; state = kzalloc(sizeof(*state), GFP_KERNEL); - if (state) { + if (state) __drm_atomic_helper_plane_reset(plane, &state->base); - state->base.color_encoding = DRM_COLOR_YCBCR_BT601; - state->base.color_range = DRM_COLOR_YCBCR_LIMITED_RANGE; - } } static struct drm_plane_state * From bbefe708816a6c559bf170031e99bca32c0743e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 28 Feb 2022 19:26:00 +0100 Subject: [PATCH 00111/11454] drm/bridge: nxp-ptn3460: switch to devm_drm_of_get_bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function "drm_of_find_panel_or_bridge" has been deprecated in favor of "devm_drm_of_get_bridge". Switch to the new function and reduce boilerplate. Signed-off-by: José Expósito Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220228182600.22463-1-jose.exposito89@gmail.com --- drivers/gpu/drm/bridge/nxp-ptn3460.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index e941c1132598..1ab91f4e057b 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -263,7 +263,6 @@ static int ptn3460_probe(struct i2c_client *client, struct device *dev = &client->dev; struct ptn3460_bridge *ptn_bridge; struct drm_bridge *panel_bridge; - struct drm_panel *panel; int ret; ptn_bridge = devm_kzalloc(dev, sizeof(*ptn_bridge), GFP_KERNEL); @@ -271,11 +270,7 @@ static int ptn3460_probe(struct i2c_client *client, return -ENOMEM; } - ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, NULL); - if (ret) - return ret; - - panel_bridge = devm_drm_panel_bridge_add(dev, panel); + panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); if (IS_ERR(panel_bridge)) return PTR_ERR(panel_bridge); From 55ad1a56b4f991f9879f4f5019f485fa713426ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 28 Feb 2022 19:29:04 +0100 Subject: [PATCH 00112/11454] drm/bridge: parade-ps8622: switch to devm_drm_of_get_bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function "drm_of_find_panel_or_bridge" has been deprecated in favor of "devm_drm_of_get_bridge". Switch to the new function and reduce boilerplate. Signed-off-by: José Expósito Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220228182904.22982-1-jose.exposito89@gmail.com --- drivers/gpu/drm/bridge/parade-ps8622.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index 614b19f0f1b7..37b308850b4e 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -452,18 +452,13 @@ static int ps8622_probe(struct i2c_client *client, struct device *dev = &client->dev; struct ps8622_bridge *ps8622; struct drm_bridge *panel_bridge; - struct drm_panel *panel; int ret; ps8622 = devm_kzalloc(dev, sizeof(*ps8622), GFP_KERNEL); if (!ps8622) return -ENOMEM; - ret = drm_of_find_panel_or_bridge(dev->of_node, 0, 0, &panel, NULL); - if (ret) - return ret; - - panel_bridge = devm_drm_panel_bridge_add(dev, panel); + panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 0, 0); if (IS_ERR(panel_bridge)) return PTR_ERR(panel_bridge); From 5486eac81004febf512c6d344cd8f612a1e597ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 28 Feb 2022 19:31:31 +0100 Subject: [PATCH 00113/11454] drm/bridge: parade-ps8640: switch to devm_drm_of_get_bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function "drm_of_find_panel_or_bridge" has been deprecated in favor of "devm_drm_of_get_bridge". Switch to the new function and reduce boilerplate. Signed-off-by: José Expósito Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220228183131.23494-1-jose.exposito89@gmail.com --- drivers/gpu/drm/bridge/parade-ps8640.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpu/drm/bridge/parade-ps8640.c b/drivers/gpu/drm/bridge/parade-ps8640.c index 3f17337ee389..9766cbbd62ad 100644 --- a/drivers/gpu/drm/bridge/parade-ps8640.c +++ b/drivers/gpu/drm/bridge/parade-ps8640.c @@ -589,7 +589,6 @@ static int ps8640_probe(struct i2c_client *client) struct device *dev = &client->dev; struct device_node *np = dev->of_node; struct ps8640 *ps_bridge; - struct drm_panel *panel; int ret; u32 i; @@ -674,13 +673,7 @@ static int ps8640_probe(struct i2c_client *client) devm_of_dp_aux_populate_ep_devices(&ps_bridge->aux); /* port@1 is ps8640 output port */ - ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL); - if (ret < 0) - return ret; - if (!panel) - return -ENODEV; - - ps_bridge->panel_bridge = devm_drm_panel_bridge_add(dev, panel); + ps_bridge->panel_bridge = devm_drm_of_get_bridge(dev, np, 1, 0); if (IS_ERR(ps_bridge->panel_bridge)) return PTR_ERR(ps_bridge->panel_bridge); From 0d9c5e6733a773ce590a1b08a446daca04781c57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 28 Feb 2022 19:33:42 +0100 Subject: [PATCH 00114/11454] drm/bridge: tc358762: switch to devm_drm_of_get_bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function "drm_of_find_panel_or_bridge" has been deprecated in favor of "devm_drm_of_get_bridge". Switch to the new function and reduce boilerplate. Signed-off-by: José Expósito Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220228183342.24129-1-jose.exposito89@gmail.com --- drivers/gpu/drm/bridge/tc358762.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358762.c b/drivers/gpu/drm/bridge/tc358762.c index 1bfdfc6affaf..7870aceb0a6d 100644 --- a/drivers/gpu/drm/bridge/tc358762.c +++ b/drivers/gpu/drm/bridge/tc358762.c @@ -179,15 +179,8 @@ static int tc358762_parse_dt(struct tc358762 *ctx) { struct drm_bridge *panel_bridge; struct device *dev = ctx->dev; - struct drm_panel *panel; - int ret; - - ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); - if (ret) - return ret; - - panel_bridge = devm_drm_panel_bridge_add(dev, panel); + panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 1, 0); if (IS_ERR(panel_bridge)) return PTR_ERR(panel_bridge); From aec9a8576eecaf4a75f29ade79e679f171edf622 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 28 Feb 2022 19:35:37 +0100 Subject: [PATCH 00115/11454] drm/bridge: tc358775: switch to devm_drm_of_get_bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function "drm_of_find_panel_or_bridge" has been deprecated in favor of "devm_drm_of_get_bridge". Switch to the new function and reduce boilerplate. Signed-off-by: José Expósito Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220228183537.24600-1-jose.exposito89@gmail.com --- drivers/gpu/drm/bridge/tc358775.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c index 695af3badcc7..b987e5ac80f0 100644 --- a/drivers/gpu/drm/bridge/tc358775.c +++ b/drivers/gpu/drm/bridge/tc358775.c @@ -649,7 +649,6 @@ static int tc_attach_host(struct tc_data *tc) static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; - struct drm_panel *panel; struct tc_data *tc; int ret; @@ -660,14 +659,8 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->dev = dev; tc->i2c = client; - ret = drm_of_find_panel_or_bridge(dev->of_node, TC358775_LVDS_OUT0, - 0, &panel, NULL); - if (ret < 0) - return ret; - if (!panel) - return -ENODEV; - - tc->panel_bridge = devm_drm_panel_bridge_add(dev, panel); + tc->panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, + TC358775_LVDS_OUT0, 0); if (IS_ERR(tc->panel_bridge)) return PTR_ERR(tc->panel_bridge); From c1b16fbd1698d07bbb0b0ddc3da5a7f1f0854edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 28 Feb 2022 19:37:24 +0100 Subject: [PATCH 00116/11454] drm/bridge: ti-sn65dsi83: switch to devm_drm_of_get_bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function "drm_of_find_panel_or_bridge" has been deprecated in favor of "devm_drm_of_get_bridge". Switch to the new function and reduce boilerplate. Signed-off-by: José Expósito Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220228183724.25030-1-jose.exposito89@gmail.com --- drivers/gpu/drm/bridge/ti-sn65dsi83.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi83.c b/drivers/gpu/drm/bridge/ti-sn65dsi83.c index 19daaddd29a4..c2afef97c2b2 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi83.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi83.c @@ -565,7 +565,6 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model) struct drm_bridge *panel_bridge; struct device *dev = ctx->dev; struct device_node *endpoint; - struct drm_panel *panel; int ret; endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, 0); @@ -605,15 +604,10 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model) } } - ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, &panel_bridge); - if (ret < 0) + panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node, 2, 0); + if (IS_ERR(panel_bridge)) { + ret = PTR_ERR(panel_bridge); goto err_put_node; - if (panel) { - panel_bridge = devm_drm_panel_bridge_add(dev, panel); - if (IS_ERR(panel_bridge)) { - ret = PTR_ERR(panel_bridge); - goto err_put_node; - } } ctx->panel_bridge = panel_bridge; From c64fa77dd4609cb8cd53fbb73b02434ae8212c7a Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 3 Mar 2022 10:02:29 +0000 Subject: [PATCH 00117/11454] drm/i915/gtt: reduce overzealous alignment constraints for GGTT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently this will enforce both 2M alignment and padding for any LMEM pages inserted into the GGTT. However, this was only meant to be applied to the compact-pt layout with the ppGTT. For the GGTT we can reduce the alignment and padding to 64K. Bspec: 45015 Fixes: 87bd701ee268 ("drm/i915: enforce min GTT alignment for discrete cards") Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Robert Beckett Cc: Ramalingam C Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20220303100229.839282-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/gt/intel_gtt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 4f70d512a000..aed6de2d5a79 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -257,7 +257,8 @@ void i915_address_space_init(struct i915_address_space *vm, int subclass) memset64(vm->min_alignment, I915_GTT_MIN_ALIGNMENT, ARRAY_SIZE(vm->min_alignment)); - if (HAS_64K_PAGES(vm->i915) && NEEDS_COMPACT_PT(vm->i915)) { + if (HAS_64K_PAGES(vm->i915) && NEEDS_COMPACT_PT(vm->i915) && + subclass == VM_CLASS_PPGTT) { vm->min_alignment[INTEL_MEMORY_LOCAL] = I915_GTT_PAGE_SIZE_2M; vm->min_alignment[INTEL_MEMORY_STOLEN_LOCAL] = I915_GTT_PAGE_SIZE_2M; } else if (HAS_64K_PAGES(vm->i915)) { From 2ed38cec5606dfe50893b36a1363379f9609e0bb Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Wed, 2 Feb 2022 17:31:54 +0000 Subject: [PATCH 00118/11454] drm/i915: opportunistically apply ALLOC_CONTIGIOUS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It looks like this code was accidentally dropped at some point(in a slightly different form), so add it back. The gist is that if we know the allocation will be one single chunk, then we can just annotate the BO with I915_BO_ALLOC_CONTIGUOUS, even if the user doesn't bother. In the future this should allow us to avoid using vmap for such objects, in some upcoming patches. v2(Thomas): - Tweak the commit message to mention the future motivation Signed-off-by: Matthew Auld Cc: Thomas Hellström Reviewed-by: Thomas Hellström Link: https://patchwork.freedesktop.org/patch/msgid/20220202173154.3758970-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_region.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c index 6cf94469d5a8..c9b2e8b91053 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_region.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c @@ -62,6 +62,9 @@ i915_gem_object_create_region(struct intel_memory_region *mem, size = round_up(size, default_page_size); + if (default_page_size == size) + flags |= I915_BO_ALLOC_CONTIGUOUS; + GEM_BUG_ON(!size); GEM_BUG_ON(!IS_ALIGNED(size, I915_GTT_MIN_ALIGNMENT)); From 07b58d61275ebbb39b678d18f7c4e472050b13eb Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 8 Feb 2022 15:12:28 +0000 Subject: [PATCH 00119/11454] drm/doc: pull in drm_buddy.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure we pull in the kernel-doc for this. Reported-by: Daniel Vetter Signed-off-by: Matthew Auld Cc: Arunpravin Cc: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20220208151228.344997-1-matthew.auld@intel.com Signed-off-by: Christian König Reviewed-by: Christian König --- Documentation/gpu/drm-mm.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/gpu/drm-mm.rst b/Documentation/gpu/drm-mm.rst index 198bcc1affa1..f32ccce5722d 100644 --- a/Documentation/gpu/drm-mm.rst +++ b/Documentation/gpu/drm-mm.rst @@ -466,6 +466,15 @@ DRM MM Range Allocator Function References .. kernel-doc:: drivers/gpu/drm/drm_mm.c :export: +DRM Buddy Allocator +=================== + +DRM Buddy Function References +----------------------------- + +.. kernel-doc:: drivers/gpu/drm/drm_buddy.c + :export: + DRM Cache Handling and Fast WC memcpy() ======================================= From 6639fabb16852b2473c4c78c38a3b18689eb6ac3 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 28 Feb 2022 21:29:52 -0800 Subject: [PATCH 00120/11454] drm/i915/xehp: Drop aux table invalidation on FlatCCS platforms Platforms with FlatCCS do not use auxiliary planes for compression control data and thus do not need traditional aux table invalidation (and the registers no longer even exist). Original-author: CQ Tang Signed-off-by: Matt Roper Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220301052952.1706597-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 28 ++++++++++++++++-------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index b1b9c3fd7bf9..36148887c699 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -236,7 +236,7 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) if (mode & EMIT_INVALIDATE) { u32 flags = 0; - u32 *cs; + u32 *cs, count; flags |= PIPE_CONTROL_COMMAND_CACHE_INVALIDATE; flags |= PIPE_CONTROL_TLB_INVALIDATE; @@ -254,7 +254,12 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) if (engine->class == COMPUTE_CLASS) flags &= ~PIPE_CONTROL_3D_FLAGS; - cs = intel_ring_begin(rq, 8 + 4); + if (!HAS_FLAT_CCS(rq->engine->i915)) + count = 8 + 4; + else + count = 8; + + cs = intel_ring_begin(rq, count); if (IS_ERR(cs)) return PTR_ERR(cs); @@ -267,8 +272,10 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) cs = gen8_emit_pipe_control(cs, flags, LRC_PPHWSP_SCRATCH_ADDR); - /* hsdes: 1809175790 */ - cs = gen12_emit_aux_table_inv(GEN12_GFX_CCS_AUX_NV, cs); + if (!HAS_FLAT_CCS(rq->engine->i915)) { + /* hsdes: 1809175790 */ + cs = gen12_emit_aux_table_inv(GEN12_GFX_CCS_AUX_NV, cs); + } *cs++ = preparser_disable(false); intel_ring_advance(rq, cs); @@ -283,12 +290,15 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) u32 cmd, *cs; cmd = 4; - if (mode & EMIT_INVALIDATE) + if (mode & EMIT_INVALIDATE) { cmd += 2; - if (mode & EMIT_INVALIDATE) - aux_inv = rq->engine->mask & ~BIT(BCS0); - if (aux_inv) - cmd += 2 * hweight32(aux_inv) + 2; + + if (!HAS_FLAT_CCS(rq->engine->i915)) { + aux_inv = rq->engine->mask & ~BIT(BCS0); + if (aux_inv) + cmd += 2 * hweight32(aux_inv) + 2; + } + } cs = intel_ring_begin(rq, cmd); if (IS_ERR(cs)) From dc55e35f9e810f23dd69cfdc91a3d636023f57a2 Mon Sep 17 00:00:00 2001 From: Alexey Gladkov Date: Mon, 14 Feb 2022 19:18:14 +0100 Subject: [PATCH 00121/11454] ipc: Store mqueue sysctls in the ipc namespace Right now, the mqueue sysctls take ipc namespaces into account in a rather hacky way. This works in most cases, but does not respect the user namespace. Within the user namespace, the user cannot change the /proc/sys/fs/mqueue/* parametres. This poses a problem in the rootless containers. To solve this I changed the implementation of the mqueue sysctls just like some other sysctls. So far, the changes do not provide additional access to files. This will be done in a future patch. v3: * Don't implemenet set_permissions to keep the current behavior. v2: * Fixed compilation problem if CONFIG_POSIX_MQUEUE_SYSCTL is not specified. Reported-by: kernel test robot Signed-off-by: Alexey Gladkov Link: https://lkml.kernel.org/r/b0ccbb2489119f1f20c737cf1930c3a9c4e4243a.1644862280.git.legion@kernel.org Signed-off-by: Eric W. Biederman --- include/linux/ipc_namespace.h | 16 +++-- ipc/mq_sysctl.c | 127 ++++++++++++++++++---------------- ipc/mqueue.c | 10 ++- ipc/namespace.c | 6 ++ 4 files changed, 91 insertions(+), 68 deletions(-) diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index b75395ec8d52..fa787d97d60a 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h @@ -10,6 +10,7 @@ #include #include #include +#include struct user_namespace; @@ -63,6 +64,9 @@ struct ipc_namespace { unsigned int mq_msg_default; unsigned int mq_msgsize_default; + struct ctl_table_set mq_set; + struct ctl_table_header *mq_sysctls; + /* user_ns which owns the ipc ns */ struct user_namespace *user_ns; struct ucounts *ucounts; @@ -169,14 +173,18 @@ static inline void put_ipc_ns(struct ipc_namespace *ns) #ifdef CONFIG_POSIX_MQUEUE_SYSCTL -struct ctl_table_header; -extern struct ctl_table_header *mq_register_sysctl_table(void); +void retire_mq_sysctls(struct ipc_namespace *ns); +bool setup_mq_sysctls(struct ipc_namespace *ns); #else /* CONFIG_POSIX_MQUEUE_SYSCTL */ -static inline struct ctl_table_header *mq_register_sysctl_table(void) +static inline void retire_mq_sysctls(struct ipc_namespace *ns) { - return NULL; +} + +static inline bool setup_mq_sysctls(struct ipc_namespace *ns) +{ + return true; } #endif /* CONFIG_POSIX_MQUEUE_SYSCTL */ diff --git a/ipc/mq_sysctl.c b/ipc/mq_sysctl.c index 72a92a08c848..fbf6a8b93a26 100644 --- a/ipc/mq_sysctl.c +++ b/ipc/mq_sysctl.c @@ -9,39 +9,9 @@ #include #include -#ifdef CONFIG_PROC_SYSCTL -static void *get_mq(struct ctl_table *table) -{ - char *which = table->data; - struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; - which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; - return which; -} - -static int proc_mq_dointvec(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ctl_table mq_table; - memcpy(&mq_table, table, sizeof(mq_table)); - mq_table.data = get_mq(table); - - return proc_dointvec(&mq_table, write, buffer, lenp, ppos); -} - -static int proc_mq_dointvec_minmax(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ctl_table mq_table; - memcpy(&mq_table, table, sizeof(mq_table)); - mq_table.data = get_mq(table); - - return proc_dointvec_minmax(&mq_table, write, buffer, - lenp, ppos); -} -#else -#define proc_mq_dointvec NULL -#define proc_mq_dointvec_minmax NULL -#endif +#include +#include +#include static int msg_max_limit_min = MIN_MSGMAX; static int msg_max_limit_max = HARD_MSGMAX; @@ -55,14 +25,14 @@ static struct ctl_table mq_sysctls[] = { .data = &init_ipc_ns.mq_queues_max, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_mq_dointvec, + .proc_handler = proc_dointvec, }, { .procname = "msg_max", .data = &init_ipc_ns.mq_msg_max, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_mq_dointvec_minmax, + .proc_handler = proc_dointvec_minmax, .extra1 = &msg_max_limit_min, .extra2 = &msg_max_limit_max, }, @@ -71,7 +41,7 @@ static struct ctl_table mq_sysctls[] = { .data = &init_ipc_ns.mq_msgsize_max, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_mq_dointvec_minmax, + .proc_handler = proc_dointvec_minmax, .extra1 = &msg_maxsize_limit_min, .extra2 = &msg_maxsize_limit_max, }, @@ -80,7 +50,7 @@ static struct ctl_table mq_sysctls[] = { .data = &init_ipc_ns.mq_msg_default, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_mq_dointvec_minmax, + .proc_handler = proc_dointvec_minmax, .extra1 = &msg_max_limit_min, .extra2 = &msg_max_limit_max, }, @@ -89,32 +59,73 @@ static struct ctl_table mq_sysctls[] = { .data = &init_ipc_ns.mq_msgsize_default, .maxlen = sizeof(int), .mode = 0644, - .proc_handler = proc_mq_dointvec_minmax, + .proc_handler = proc_dointvec_minmax, .extra1 = &msg_maxsize_limit_min, .extra2 = &msg_maxsize_limit_max, }, {} }; -static struct ctl_table mq_sysctl_dir[] = { - { - .procname = "mqueue", - .mode = 0555, - .child = mq_sysctls, - }, - {} -}; - -static struct ctl_table mq_sysctl_root[] = { - { - .procname = "fs", - .mode = 0555, - .child = mq_sysctl_dir, - }, - {} -}; - -struct ctl_table_header *mq_register_sysctl_table(void) +static struct ctl_table_set *set_lookup(struct ctl_table_root *root) { - return register_sysctl_table(mq_sysctl_root); + return ¤t->nsproxy->ipc_ns->mq_set; +} + +static int set_is_seen(struct ctl_table_set *set) +{ + return ¤t->nsproxy->ipc_ns->mq_set == set; +} + +static struct ctl_table_root set_root = { + .lookup = set_lookup, +}; + +bool setup_mq_sysctls(struct ipc_namespace *ns) +{ + struct ctl_table *tbl; + + setup_sysctl_set(&ns->mq_set, &set_root, set_is_seen); + + tbl = kmemdup(mq_sysctls, sizeof(mq_sysctls), GFP_KERNEL); + if (tbl) { + int i; + + for (i = 0; i < ARRAY_SIZE(mq_sysctls); i++) { + if (tbl[i].data == &init_ipc_ns.mq_queues_max) + tbl[i].data = &ns->mq_queues_max; + + else if (tbl[i].data == &init_ipc_ns.mq_msg_max) + tbl[i].data = &ns->mq_msg_max; + + else if (tbl[i].data == &init_ipc_ns.mq_msgsize_max) + tbl[i].data = &ns->mq_msgsize_max; + + else if (tbl[i].data == &init_ipc_ns.mq_msg_default) + tbl[i].data = &ns->mq_msg_default; + + else if (tbl[i].data == &init_ipc_ns.mq_msgsize_default) + tbl[i].data = &ns->mq_msgsize_default; + else + tbl[i].data = NULL; + } + + ns->mq_sysctls = __register_sysctl_table(&ns->mq_set, "fs/mqueue", tbl); + } + if (!ns->mq_sysctls) { + kfree(tbl); + retire_sysctl_set(&ns->mq_set); + return false; + } + + return true; +} + +void retire_mq_sysctls(struct ipc_namespace *ns) +{ + struct ctl_table *tbl; + + tbl = ns->mq_sysctls->ctl_table_arg; + unregister_sysctl_table(ns->mq_sysctls); + retire_sysctl_set(&ns->mq_set); + kfree(tbl); } diff --git a/ipc/mqueue.c b/ipc/mqueue.c index 5becca9be867..1b4a3be71636 100644 --- a/ipc/mqueue.c +++ b/ipc/mqueue.c @@ -163,8 +163,6 @@ static void remove_notification(struct mqueue_inode_info *info); static struct kmem_cache *mqueue_inode_cachep; -static struct ctl_table_header *mq_sysctl_table; - static inline struct mqueue_inode_info *MQUEUE_I(struct inode *inode) { return container_of(inode, struct mqueue_inode_info, vfs_inode); @@ -1713,8 +1711,10 @@ static int __init init_mqueue_fs(void) if (mqueue_inode_cachep == NULL) return -ENOMEM; - /* ignore failures - they are not fatal */ - mq_sysctl_table = mq_register_sysctl_table(); + if (!setup_mq_sysctls(&init_ipc_ns)) { + pr_warn("sysctl registration failed\n"); + return -ENOMEM; + } error = register_filesystem(&mqueue_fs_type); if (error) @@ -1731,8 +1731,6 @@ static int __init init_mqueue_fs(void) out_filesystem: unregister_filesystem(&mqueue_fs_type); out_sysctl: - if (mq_sysctl_table) - unregister_sysctl_table(mq_sysctl_table); kmem_cache_destroy(mqueue_inode_cachep); return error; } diff --git a/ipc/namespace.c b/ipc/namespace.c index ae83f0f2651b..f760243ca685 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -59,6 +59,10 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns, if (err) goto fail_put; + err = -ENOMEM; + if (!setup_mq_sysctls(ns)) + goto fail_put; + sem_init_ns(ns); msg_init_ns(ns); shm_init_ns(ns); @@ -125,6 +129,8 @@ static void free_ipc_ns(struct ipc_namespace *ns) msg_exit_ns(ns); shm_exit_ns(ns); + retire_mq_sysctls(ns); + dec_ipc_namespaces(ns->ucounts); put_user_ns(ns->user_ns); ns_free_inum(&ns->ns); From 1f5c135ee509e89e0cc274333a65f73c62cb16e5 Mon Sep 17 00:00:00 2001 From: Alexey Gladkov Date: Mon, 14 Feb 2022 19:18:15 +0100 Subject: [PATCH 00122/11454] ipc: Store ipc sysctls in the ipc namespace The ipc sysctls are not available for modification inside the user namespace. Following the mqueue sysctls, we changed the implementation to be more userns friendly. So far, the changes do not provide additional access to files. This will be done in a future patch. Signed-off-by: Alexey Gladkov Link: https://lkml.kernel.org/r/be6f9d014276f4dddd0c3aa05a86052856c1c555.1644862280.git.legion@kernel.org Signed-off-by: Eric W. Biederman --- include/linux/ipc_namespace.h | 21 ++++ ipc/ipc_sysctl.c | 197 ++++++++++++++++++++++------------ ipc/namespace.c | 4 + 3 files changed, 151 insertions(+), 71 deletions(-) diff --git a/include/linux/ipc_namespace.h b/include/linux/ipc_namespace.h index fa787d97d60a..e3e8c8662b49 100644 --- a/include/linux/ipc_namespace.h +++ b/include/linux/ipc_namespace.h @@ -67,6 +67,9 @@ struct ipc_namespace { struct ctl_table_set mq_set; struct ctl_table_header *mq_sysctls; + struct ctl_table_set ipc_set; + struct ctl_table_header *ipc_sysctls; + /* user_ns which owns the ipc ns */ struct user_namespace *user_ns; struct ucounts *ucounts; @@ -188,4 +191,22 @@ static inline bool setup_mq_sysctls(struct ipc_namespace *ns) } #endif /* CONFIG_POSIX_MQUEUE_SYSCTL */ + +#ifdef CONFIG_SYSVIPC_SYSCTL + +bool setup_ipc_sysctls(struct ipc_namespace *ns); +void retire_ipc_sysctls(struct ipc_namespace *ns); + +#else /* CONFIG_SYSVIPC_SYSCTL */ + +static inline void retire_ipc_sysctls(struct ipc_namespace *ns) +{ +} + +static inline bool setup_ipc_sysctls(struct ipc_namespace *ns) +{ + return true; +} + +#endif /* CONFIG_SYSVIPC_SYSCTL */ #endif diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c index f101c171753f..15210ac47e9e 100644 --- a/ipc/ipc_sysctl.c +++ b/ipc/ipc_sysctl.c @@ -13,43 +13,22 @@ #include #include #include +#include #include "util.h" -static void *get_ipc(struct ctl_table *table) -{ - char *which = table->data; - struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns; - which = (which - (char *)&init_ipc_ns) + (char *)ipc_ns; - return which; -} - -static int proc_ipc_dointvec(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ctl_table ipc_table; - - memcpy(&ipc_table, table, sizeof(ipc_table)); - ipc_table.data = get_ipc(table); - - return proc_dointvec(&ipc_table, write, buffer, lenp, ppos); -} - -static int proc_ipc_dointvec_minmax(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ctl_table ipc_table; - - memcpy(&ipc_table, table, sizeof(ipc_table)); - ipc_table.data = get_ipc(table); - - return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); -} - static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { - struct ipc_namespace *ns = current->nsproxy->ipc_ns; - int err = proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); + struct ipc_namespace *ns = table->extra1; + struct ctl_table ipc_table; + int err; + + memcpy(&ipc_table, table, sizeof(ipc_table)); + + ipc_table.extra1 = SYSCTL_ZERO; + ipc_table.extra2 = SYSCTL_ONE; + + err = proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); if (err < 0) return err; @@ -58,17 +37,6 @@ static int proc_ipc_dointvec_minmax_orphans(struct ctl_table *table, int write, return err; } -static int proc_ipc_doulongvec_minmax(struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos) -{ - struct ctl_table ipc_table; - memcpy(&ipc_table, table, sizeof(ipc_table)); - ipc_table.data = get_ipc(table); - - return proc_doulongvec_minmax(&ipc_table, write, buffer, - lenp, ppos); -} - static int proc_ipc_auto_msgmni(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { @@ -87,11 +55,17 @@ static int proc_ipc_auto_msgmni(struct ctl_table *table, int write, static int proc_ipc_sem_dointvec(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { + struct ipc_namespace *ns = table->extra1; + struct ctl_table ipc_table; int ret, semmni; - struct ipc_namespace *ns = current->nsproxy->ipc_ns; + + memcpy(&ipc_table, table, sizeof(ipc_table)); + + ipc_table.extra1 = NULL; + ipc_table.extra2 = NULL; semmni = ns->sem_ctls[3]; - ret = proc_ipc_dointvec(table, write, buffer, lenp, ppos); + ret = proc_dointvec(table, write, buffer, lenp, ppos); if (!ret) ret = sem_check_semmni(current->nsproxy->ipc_ns); @@ -108,12 +82,18 @@ static int proc_ipc_sem_dointvec(struct ctl_table *table, int write, static int proc_ipc_dointvec_minmax_checkpoint_restore(struct ctl_table *table, int write, void *buffer, size_t *lenp, loff_t *ppos) { - struct user_namespace *user_ns = current->nsproxy->ipc_ns->user_ns; + struct ipc_namespace *ns = table->extra1; + struct ctl_table ipc_table; - if (write && !checkpoint_restore_ns_capable(user_ns)) + if (write && !checkpoint_restore_ns_capable(ns->user_ns)) return -EPERM; - return proc_ipc_dointvec_minmax(table, write, buffer, lenp, ppos); + memcpy(&ipc_table, table, sizeof(ipc_table)); + + ipc_table.extra1 = SYSCTL_ZERO; + ipc_table.extra2 = SYSCTL_INT_MAX; + + return proc_dointvec_minmax(&ipc_table, write, buffer, lenp, ppos); } #endif @@ -121,27 +101,27 @@ int ipc_mni = IPCMNI; int ipc_mni_shift = IPCMNI_SHIFT; int ipc_min_cycle = RADIX_TREE_MAP_SIZE; -static struct ctl_table ipc_kern_table[] = { +static struct ctl_table ipc_sysctls[] = { { .procname = "shmmax", .data = &init_ipc_ns.shm_ctlmax, .maxlen = sizeof(init_ipc_ns.shm_ctlmax), .mode = 0644, - .proc_handler = proc_ipc_doulongvec_minmax, + .proc_handler = proc_doulongvec_minmax, }, { .procname = "shmall", .data = &init_ipc_ns.shm_ctlall, .maxlen = sizeof(init_ipc_ns.shm_ctlall), .mode = 0644, - .proc_handler = proc_ipc_doulongvec_minmax, + .proc_handler = proc_doulongvec_minmax, }, { .procname = "shmmni", .data = &init_ipc_ns.shm_ctlmni, .maxlen = sizeof(init_ipc_ns.shm_ctlmni), .mode = 0644, - .proc_handler = proc_ipc_dointvec_minmax, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = &ipc_mni, }, @@ -151,15 +131,13 @@ static struct ctl_table ipc_kern_table[] = { .maxlen = sizeof(init_ipc_ns.shm_rmid_forced), .mode = 0644, .proc_handler = proc_ipc_dointvec_minmax_orphans, - .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_ONE, }, { .procname = "msgmax", .data = &init_ipc_ns.msg_ctlmax, .maxlen = sizeof(init_ipc_ns.msg_ctlmax), .mode = 0644, - .proc_handler = proc_ipc_dointvec_minmax, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_INT_MAX, }, @@ -168,7 +146,7 @@ static struct ctl_table ipc_kern_table[] = { .data = &init_ipc_ns.msg_ctlmni, .maxlen = sizeof(init_ipc_ns.msg_ctlmni), .mode = 0644, - .proc_handler = proc_ipc_dointvec_minmax, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = &ipc_mni, }, @@ -186,7 +164,7 @@ static struct ctl_table ipc_kern_table[] = { .data = &init_ipc_ns.msg_ctlmnb, .maxlen = sizeof(init_ipc_ns.msg_ctlmnb), .mode = 0644, - .proc_handler = proc_ipc_dointvec_minmax, + .proc_handler = proc_dointvec_minmax, .extra1 = SYSCTL_ZERO, .extra2 = SYSCTL_INT_MAX, }, @@ -204,8 +182,6 @@ static struct ctl_table ipc_kern_table[] = { .maxlen = sizeof(init_ipc_ns.ids[IPC_SEM_IDS].next_id), .mode = 0666, .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore, - .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_INT_MAX, }, { .procname = "msg_next_id", @@ -213,8 +189,6 @@ static struct ctl_table ipc_kern_table[] = { .maxlen = sizeof(init_ipc_ns.ids[IPC_MSG_IDS].next_id), .mode = 0666, .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore, - .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_INT_MAX, }, { .procname = "shm_next_id", @@ -222,25 +196,106 @@ static struct ctl_table ipc_kern_table[] = { .maxlen = sizeof(init_ipc_ns.ids[IPC_SHM_IDS].next_id), .mode = 0666, .proc_handler = proc_ipc_dointvec_minmax_checkpoint_restore, - .extra1 = SYSCTL_ZERO, - .extra2 = SYSCTL_INT_MAX, }, #endif {} }; -static struct ctl_table ipc_root_table[] = { - { - .procname = "kernel", - .mode = 0555, - .child = ipc_kern_table, - }, - {} +static struct ctl_table_set *set_lookup(struct ctl_table_root *root) +{ + return ¤t->nsproxy->ipc_ns->ipc_set; +} + +static int set_is_seen(struct ctl_table_set *set) +{ + return ¤t->nsproxy->ipc_ns->ipc_set == set; +} + +static struct ctl_table_root set_root = { + .lookup = set_lookup, }; +bool setup_ipc_sysctls(struct ipc_namespace *ns) +{ + struct ctl_table *tbl; + + setup_sysctl_set(&ns->ipc_set, &set_root, set_is_seen); + + tbl = kmemdup(ipc_sysctls, sizeof(ipc_sysctls), GFP_KERNEL); + if (tbl) { + int i; + + for (i = 0; i < ARRAY_SIZE(ipc_sysctls); i++) { + if (tbl[i].data == &init_ipc_ns.shm_ctlmax) { + tbl[i].data = &ns->shm_ctlmax; + + } else if (tbl[i].data == &init_ipc_ns.shm_ctlall) { + tbl[i].data = &ns->shm_ctlall; + + } else if (tbl[i].data == &init_ipc_ns.shm_ctlmni) { + tbl[i].data = &ns->shm_ctlmni; + + } else if (tbl[i].data == &init_ipc_ns.shm_rmid_forced) { + tbl[i].data = &ns->shm_rmid_forced; + tbl[i].extra1 = ns; + + } else if (tbl[i].data == &init_ipc_ns.msg_ctlmax) { + tbl[i].data = &ns->msg_ctlmax; + + } else if (tbl[i].data == &init_ipc_ns.msg_ctlmni) { + tbl[i].data = &ns->msg_ctlmni; + + } else if (tbl[i].data == &init_ipc_ns.msg_ctlmnb) { + tbl[i].data = &ns->msg_ctlmnb; + + } else if (tbl[i].data == &init_ipc_ns.sem_ctls) { + tbl[i].data = &ns->sem_ctls; + tbl[i].extra1 = ns; +#ifdef CONFIG_CHECKPOINT_RESTORE + } else if (tbl[i].data == &init_ipc_ns.ids[IPC_SEM_IDS].next_id) { + tbl[i].data = &ns->ids[IPC_SEM_IDS].next_id; + tbl[i].extra1 = ns; + + } else if (tbl[i].data == &init_ipc_ns.ids[IPC_MSG_IDS].next_id) { + tbl[i].data = &ns->ids[IPC_MSG_IDS].next_id; + tbl[i].extra1 = ns; + + } else if (tbl[i].data == &init_ipc_ns.ids[IPC_SHM_IDS].next_id) { + tbl[i].data = &ns->ids[IPC_SHM_IDS].next_id; + tbl[i].extra1 = ns; +#endif + } else { + tbl[i].data = NULL; + } + } + + ns->ipc_sysctls = __register_sysctl_table(&ns->ipc_set, "kernel", tbl); + } + if (!ns->ipc_sysctls) { + kfree(tbl); + retire_sysctl_set(&ns->ipc_set); + return false; + } + + return true; +} + +void retire_ipc_sysctls(struct ipc_namespace *ns) +{ + struct ctl_table *tbl; + + tbl = ns->ipc_sysctls->ctl_table_arg; + unregister_sysctl_table(ns->ipc_sysctls); + retire_sysctl_set(&ns->ipc_set); + kfree(tbl); +} + static int __init ipc_sysctl_init(void) { - register_sysctl_table(ipc_root_table); + if (!setup_ipc_sysctls(&init_ipc_ns)) { + pr_warn("ipc sysctl registration failed\n"); + return -ENOMEM; + } return 0; } diff --git a/ipc/namespace.c b/ipc/namespace.c index f760243ca685..754f3237194a 100644 --- a/ipc/namespace.c +++ b/ipc/namespace.c @@ -63,6 +63,9 @@ static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns, if (!setup_mq_sysctls(ns)) goto fail_put; + if (!setup_ipc_sysctls(ns)) + goto fail_put; + sem_init_ns(ns); msg_init_ns(ns); shm_init_ns(ns); @@ -130,6 +133,7 @@ static void free_ipc_ns(struct ipc_namespace *ns) shm_exit_ns(ns); retire_mq_sysctls(ns); + retire_ipc_sysctls(ns); dec_ipc_namespaces(ns->ucounts); put_user_ns(ns->user_ns); From d296089b5bc3bc23eddb73efd04ac56b0c2a898b Mon Sep 17 00:00:00 2001 From: Changcheng Deng Date: Tue, 8 Mar 2022 09:16:55 +0000 Subject: [PATCH 00123/11454] drm/i915/dsi: use min_t() to make code cleaner Use min_t() in order to make code cleaner. Reported-by: Zeal Robot Signed-off-by: Changcheng Deng Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20220308091655.2078825-1-deng.changcheng@zte.com.cn --- drivers/gpu/drm/i915/display/vlv_dsi_pll.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c index 1385b46aeb26..5894b0138343 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi_pll.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi_pll.c @@ -394,10 +394,7 @@ static void glk_dsi_program_esc_clock(struct drm_device *dev, /* Calculate TXESC2 divider */ div2_value = DIV_ROUND_UP(div1_value, txesc1_div); - if (div2_value < 10) - txesc2_div = div2_value; - else - txesc2_div = 10; + txesc2_div = min_t(u32, div2_value, 10); intel_de_write(dev_priv, MIPIO_TXESC_CLK_DIV1, (1 << (txesc1_div - 1)) & GLK_TX_ESC_CLK_DIV1_MASK); From 471e201f543559e2cb19b182b680ebf04d80ee31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 24 Nov 2021 16:07:52 +0100 Subject: [PATCH 00124/11454] dt-bindings: display: sitronix, st7735r: Fix backlight in example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The backlight property was lost during conversion to yaml in commit abdd9e3705c8 ("dt-bindings: display: sitronix,st7735r: Convert to DT schema"). Put it back. Fixes: abdd9e3705c8 ("dt-bindings: display: sitronix,st7735r: Convert to DT schema") Signed-off-by: Noralf Trønnes Acked-by: Rob Herring Reviewed-by: Geert Uytterhoeven Acked-by: David Lechner Link: https://patchwork.freedesktop.org/patch/msgid/20211124150757.17929-2-noralf@tronnes.org --- Documentation/devicetree/bindings/display/sitronix,st7735r.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml index 0cebaaefda03..419c3b2ac5a6 100644 --- a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml +++ b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml @@ -72,6 +72,7 @@ examples: dc-gpios = <&gpio 43 GPIO_ACTIVE_HIGH>; reset-gpios = <&gpio 80 GPIO_ACTIVE_HIGH>; rotation = <270>; + backlight = <&backlight>; }; }; From a2e8cbb27722b0992aceb93b35e9d9433d8a758e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 24 Nov 2021 16:07:53 +0100 Subject: [PATCH 00125/11454] dt-bindings: display: sitronix, st7735r: Make reset-gpios optional MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are other ways than using a gpio to reset the controller so make this property optional. Signed-off-by: Noralf Trønnes Acked-by: Rob Herring Acked-by: David Lechner Link: https://patchwork.freedesktop.org/patch/msgid/20211124150757.17929-3-noralf@tronnes.org --- Documentation/devicetree/bindings/display/sitronix,st7735r.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml index 419c3b2ac5a6..f81d0d0d51fe 100644 --- a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml +++ b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml @@ -48,7 +48,6 @@ required: - compatible - reg - dc-gpios - - reset-gpios additionalProperties: false From df0a9e8d3008050f61241f471c70438ef1e90a1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noralf=20Tr=C3=B8nnes?= Date: Wed, 24 Nov 2021 16:07:54 +0100 Subject: [PATCH 00126/11454] dt-bindings: display: sitronix, st7735r: Remove spi-max-frequency limit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The datasheet lists the minimum Serial clock cycle (Write) as 66ns which is 15MHz. Mostly it can do much better than that and is in fact often run at 32MHz. With a clever driver that runs configuration commands at a low speed and only the pixel data at the maximum speed the configuration can't be messed up by transfer errors and the speed is only limited by the amount of pixel glitches that one is able to tolerate. Signed-off-by: Noralf Trønnes Acked-by: Rob Herring Acked-by: David Lechner Link: https://patchwork.freedesktop.org/patch/msgid/20211124150757.17929-4-noralf@tronnes.org --- .../devicetree/bindings/display/sitronix,st7735r.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml index f81d0d0d51fe..157b1a7b18f9 100644 --- a/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml +++ b/Documentation/devicetree/bindings/display/sitronix,st7735r.yaml @@ -32,15 +32,13 @@ properties: - okaya,rh128128t - const: sitronix,st7715r - spi-max-frequency: - maximum: 32000000 - dc-gpios: maxItems: 1 description: Display data/command selection (D/CX) backlight: true reg: true + spi-max-frequency: true reset-gpios: true rotation: true From 1498915233dde830061e008ad639b482fd76f93d Mon Sep 17 00:00:00 2001 From: Rex-BC Chen Date: Wed, 9 Mar 2022 15:36:35 +0800 Subject: [PATCH 00127/11454] drm/dsi: transfer DSI HS packets ending at the same time Since a HS transmission is composed of an arbitrary number of bytes that may not be an integer multiple of lanes, some lanes may run out of data before others. (Defined in 6.1.3 of mipi_DSI_specification_v.01-02-00) However, for some DSI RX devices (for example, anx7625), there is a limitation that packet number should be the same on all DSI lanes. In other words, they need to end a HS at the same time. Because this limitation is for some specific DSI RX devices, it is more reasonable to put the enable control in these DSI RX drivers. If DSI TX driver knows the information, they can adjust the setting for this situation. Signed-off-by: Jitao Shi Signed-off-by: Rex-BC Chen Acked-by: AngeloGioacchino Del Regno Reviewed-by: Andrzej Hajda Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220309073637.3591-2-rex-bc.chen@mediatek.com --- include/drm/drm_mipi_dsi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/drm/drm_mipi_dsi.h b/include/drm/drm_mipi_dsi.h index 147e51b6d241..51e09a1a106a 100644 --- a/include/drm/drm_mipi_dsi.h +++ b/include/drm/drm_mipi_dsi.h @@ -137,6 +137,8 @@ struct mipi_dsi_host *of_find_mipi_dsi_host_by_node(struct device_node *node); #define MIPI_DSI_CLOCK_NON_CONTINUOUS BIT(10) /* transmit data in low power */ #define MIPI_DSI_MODE_LPM BIT(11) +/* transmit data ending at the same time for all lanes within one hsync */ +#define MIPI_DSI_HS_PKT_END_ALIGNED BIT(12) enum mipi_dsi_pixel_format { MIPI_DSI_FMT_RGB888, From 7d8d0b4dcc535357d44ddeff154508f147c14e2a Mon Sep 17 00:00:00 2001 From: Rex-BC Chen Date: Wed, 9 Mar 2022 15:36:36 +0800 Subject: [PATCH 00128/11454] drm/mediatek: implement the DSI HS packets aligned Some DSI RX devices (for example, anx7625) require last alignment of packets on all lanes after each row of data is sent. Otherwise, there will be some issues of shift or scroll for screen. Take horizontal_sync_active_byte for a example, we roundup the HSA packet data to lane number, and the subtraction of 2 is the packet data value added by the roundup operation, making the long packets are integer multiples of lane number. This value (2) varies with the lane number, and that is the reason we do this operation when the lane number is 4. In the previous operation of function "mtk_dsi_config_vdo_timing", the length of HSA and HFP data packets has been adjusted to an integration multiple of lane number. Since the number of RGB data packets cannot be guaranteed to be an integer multiple of lane number, we modify the data packet length of HBP so that the number of HBP + RGB is equal to the lane number. So after sending a line of data (HSA + HBP + RGB + HFP), the data lanes are aligned. Signed-off-by: Jitao Shi Signed-off-by: Rex-BC Chen Signed-off-by: Xinlei Lee Reviewed-by: Andrzej Hajda Reviewed-by: AngeloGioacchino Del Regno Acked-by: Chun-Kuang Hu Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220309073637.3591-3-rex-bc.chen@mediatek.com --- drivers/gpu/drm/mediatek/mtk_dsi.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index 5d90d2eb0019..e91b3fff4342 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -500,6 +500,18 @@ static void mtk_dsi_config_vdo_timing(struct mtk_dsi *dsi) DRM_WARN("HFP + HBP less than d-phy, FPS will under 60Hz\n"); } + if ((dsi->mode_flags & MIPI_DSI_HS_PKT_END_ALIGNED) && + (dsi->lanes == 4)) { + horizontal_sync_active_byte = + roundup(horizontal_sync_active_byte, dsi->lanes) - 2; + horizontal_frontporch_byte = + roundup(horizontal_frontporch_byte, dsi->lanes) - 2; + horizontal_backporch_byte = + roundup(horizontal_backporch_byte, dsi->lanes) - 2; + horizontal_backporch_byte -= + (vm->hactive * dsi_tmp_buf_bpp + 2) % dsi->lanes; + } + writel(horizontal_sync_active_byte, dsi->regs + DSI_HSA_WC); writel(horizontal_backporch_byte, dsi->regs + DSI_HBP_WC); writel(horizontal_frontporch_byte, dsi->regs + DSI_HFP_WC); From 4404cdb59b336279b7dcb40c5ef01dbcdbebc941 Mon Sep 17 00:00:00 2001 From: Rex-BC Chen Date: Wed, 9 Mar 2022 15:36:37 +0800 Subject: [PATCH 00129/11454] drm/bridge: anx7625: config hs packets end aligned to avoid screen shift This device requires the packets on lanes aligned at the end to fix screen shift or scroll. Signed-off-by: Jitao Shi Signed-off-by: Rex-BC Chen Acked-by: AngeloGioacchino Del Regno Reviewed-by: Xin Ji Reviewed-by: Andrzej Hajda Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220309073637.3591-4-rex-bc.chen@mediatek.com --- drivers/gpu/drm/bridge/analogix/anx7625.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 31ecf5626f1d..4043192c0369 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -2011,7 +2011,8 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx) dsi->format = MIPI_DSI_FMT_RGB888; dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | - MIPI_DSI_MODE_VIDEO_HSE; + MIPI_DSI_MODE_VIDEO_HSE | + MIPI_DSI_HS_PKT_END_ALIGNED; ret = devm_mipi_dsi_attach(dev, dsi); if (ret) { From d583e752732421b26fef0d65020565f3bef12248 Mon Sep 17 00:00:00 2001 From: Tom Rix Date: Thu, 3 Mar 2022 12:19:43 -0800 Subject: [PATCH 00130/11454] drm/bridge: anx7625: check the return on anx7625_aux_trans Clang static analysis reports this issue anx7625.c:876:13: warning: The left operand of '&' is a garbage value if (!(bcap & 0xOA01)) { ~~~~ ^ bcap is only set by a successful call to anx7625_aux_trans(). So check. Fixes: cd1637c7e480 ("drm/bridge: anx7625: add HDCP support") Signed-off-by: Tom Rix Fixes: adca62ec370c ("drm/bridge: anx7625: Support reading edid through aux channel") Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220303201943.501746-1-trix@redhat.com Reviewed-by: Robert Foss --- drivers/gpu/drm/bridge/analogix/anx7625.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 4043192c0369..69122bea4c1e 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -874,7 +874,10 @@ static int anx7625_hdcp_enable(struct anx7625_data *ctx) } /* Read downstream capability */ - anx7625_aux_trans(ctx, DP_AUX_NATIVE_READ, 0x68028, 1, &bcap); + ret = anx7625_aux_trans(ctx, DP_AUX_NATIVE_READ, 0x68028, 1, &bcap); + if (ret < 0) + return ret; + if (!(bcap & 0x01)) { pr_warn("downstream not support HDCP 1.4, cap(%x).\n", bcap); return 0; From 14a28e79f5f6c756f281a021555f1b7578a67098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 28 Feb 2022 19:39:54 +0100 Subject: [PATCH 00131/11454] drm/bridge: ti-sn65dsi86: switch to devm_drm_of_get_bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function "drm_of_find_panel_or_bridge" has been deprecated in favor of "devm_drm_of_get_bridge". Switch to the new function and reduce boilerplate. Signed-off-by: José Expósito Reviewed-by: Kieran Bingham Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220228183955.25508-1-jose.exposito89@gmail.com --- drivers/gpu/drm/bridge/ti-sn65dsi86.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index 38616aab12ac..ca7f63d71147 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1188,15 +1188,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev, { struct ti_sn65dsi86 *pdata = dev_get_drvdata(adev->dev.parent); struct device_node *np = pdata->dev->of_node; - struct drm_panel *panel; int ret; - ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL); - if (ret) - return dev_err_probe(&adev->dev, ret, - "could not find any panel node\n"); - - pdata->next_bridge = devm_drm_panel_bridge_add(pdata->dev, panel); + pdata->next_bridge = devm_drm_of_get_bridge(pdata->dev, np, 1, 0); if (IS_ERR(pdata->next_bridge)) { DRM_ERROR("failed to create panel bridge\n"); return PTR_ERR(pdata->next_bridge); From efb37e66b7572ce4696aa0ac21675e17d6b9a17d Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 9 Mar 2022 00:07:57 +0800 Subject: [PATCH 00132/11454] drm: ssd130x: Fix COM scan direction register mask The SSD130x's command to toggle COM scan direction uses bit 3 and only bit 3 to set the direction of the scanout. The driver has an incorrect GENMASK(3, 2), causing the setting to be set on bit 2, rendering it ineffective. Fix the mask to only bit 3, so that the requested setting is applied correctly. Fixes: a61732e80867 ("drm: Add driver for Solomon SSD130x OLED displays") Signed-off-by: Chen-Yu Tsai Acked-by: Javier Martinez Canillas Tested-by: Geert Uytterhoeven Reviewed-by: Geert Uytterhoeven Signed-off-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20220308160758.26060-1-wens@kernel.org --- drivers/gpu/drm/solomon/ssd130x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 85cab9271585..73e5a39f7fa3 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -61,7 +61,7 @@ #define SSD130X_SET_COM_PINS_CONFIG 0xda #define SSD130X_SET_VCOMH 0xdb -#define SSD130X_SET_COM_SCAN_DIR_MASK GENMASK(3, 2) +#define SSD130X_SET_COM_SCAN_DIR_MASK GENMASK(3, 3) #define SSD130X_SET_COM_SCAN_DIR_SET(val) FIELD_PREP(SSD130X_SET_COM_SCAN_DIR_MASK, (val)) #define SSD130X_SET_CLOCK_DIV_MASK GENMASK(3, 0) #define SSD130X_SET_CLOCK_DIV_SET(val) FIELD_PREP(SSD130X_SET_CLOCK_DIV_MASK, (val)) From a134109c301736ea2ac5054ba3c29c30c87f6ba7 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Wed, 9 Mar 2022 00:07:58 +0800 Subject: [PATCH 00133/11454] drm: ssd130x: Always apply segment remap setting Currently the ssd130x driver only sets the segment remap setting when the device tree requests it; it however does not clear the setting if it is not requested. This leads to the setting incorrectly persisting if the hardware is always on and has no reset GPIO wired. This might happen when a developer is trying to find the correct settings for an unknown module, and cause the developer to get confused because the settings from the device tree are not consistently applied. Make the driver apply the segment remap setting consistently, setting the value correctly based on the device tree setting. This also makes this setting's behavior consistent with the other settings, which are always applied. Fixes: a61732e80867 ("drm: Add driver for Solomon SSD130x OLED displays") Signed-off-by: Chen-Yu Tsai Acked-by: Javier Martinez Canillas Signed-off-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20220308160758.26060-2-wens@kernel.org --- drivers/gpu/drm/solomon/ssd130x.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 73e5a39f7fa3..a95ab7e5bbf0 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -48,7 +48,7 @@ #define SSD130X_CONTRAST 0x81 #define SSD130X_SET_LOOKUP_TABLE 0x91 #define SSD130X_CHARGE_PUMP 0x8d -#define SSD130X_SEG_REMAP_ON 0xa1 +#define SSD130X_SET_SEG_REMAP 0xa0 #define SSD130X_DISPLAY_OFF 0xae #define SSD130X_SET_MULTIPLEX_RATIO 0xa8 #define SSD130X_DISPLAY_ON 0xaf @@ -61,6 +61,8 @@ #define SSD130X_SET_COM_PINS_CONFIG 0xda #define SSD130X_SET_VCOMH 0xdb +#define SSD130X_SET_SEG_REMAP_MASK GENMASK(0, 0) +#define SSD130X_SET_SEG_REMAP_SET(val) FIELD_PREP(SSD130X_SET_SEG_REMAP_MASK, (val)) #define SSD130X_SET_COM_SCAN_DIR_MASK GENMASK(3, 3) #define SSD130X_SET_COM_SCAN_DIR_SET(val) FIELD_PREP(SSD130X_SET_COM_SCAN_DIR_MASK, (val)) #define SSD130X_SET_CLOCK_DIV_MASK GENMASK(3, 0) @@ -235,7 +237,7 @@ static void ssd130x_power_off(struct ssd130x_device *ssd130x) static int ssd130x_init(struct ssd130x_device *ssd130x) { - u32 precharge, dclk, com_invdir, compins, chargepump; + u32 precharge, dclk, com_invdir, compins, chargepump, seg_remap; int ret; /* Set initial contrast */ @@ -244,11 +246,11 @@ static int ssd130x_init(struct ssd130x_device *ssd130x) return ret; /* Set segment re-map */ - if (ssd130x->seg_remap) { - ret = ssd130x_write_cmd(ssd130x, 1, SSD130X_SEG_REMAP_ON); - if (ret < 0) - return ret; - } + seg_remap = (SSD130X_SET_SEG_REMAP | + SSD130X_SET_SEG_REMAP_SET(ssd130x->seg_remap)); + ret = ssd130x_write_cmd(ssd130x, 1, seg_remap); + if (ret < 0) + return ret; /* Set COM direction */ com_invdir = (SSD130X_SET_COM_SCAN_DIR | From 9e82ea0fb1dfc6eef917ff69f909b39dbaa38702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Exp=C3=B3sito?= Date: Mon, 21 Feb 2022 08:28:35 +0100 Subject: [PATCH 00134/11454] drm/bridge: anx7625: switch to devm_drm_of_get_bridge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The function "drm_of_find_panel_or_bridge" has been deprecated in favor of "devm_drm_of_get_bridge". Switch to the new function and reduce boilerplate. Signed-off-by: José Expósito Reviewed-by: Maxime Ripard Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220221072835.10032-1-jose.exposito89@gmail.com --- drivers/gpu/drm/bridge/analogix/anx7625.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 69122bea4c1e..9a2a19ad4202 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -1611,8 +1611,6 @@ static int anx7625_parse_dt(struct device *dev, struct anx7625_platform_data *pdata) { struct device_node *np = dev->of_node, *ep0; - struct drm_panel *panel; - int ret; int bus_type, mipi_lanes; anx7625_get_swing_setting(dev, pdata); @@ -1649,18 +1647,14 @@ static int anx7625_parse_dt(struct device *dev, if (of_property_read_bool(np, "analogix,audio-enable")) pdata->audio_en = 1; - ret = drm_of_find_panel_or_bridge(np, 1, 0, &panel, NULL); - if (ret < 0) { - if (ret == -ENODEV) + pdata->panel_bridge = devm_drm_of_get_bridge(dev, np, 1, 0); + if (IS_ERR(pdata->panel_bridge)) { + if (PTR_ERR(pdata->panel_bridge) == -ENODEV) return 0; - return ret; - } - if (!panel) - return -ENODEV; - pdata->panel_bridge = devm_drm_panel_bridge_add(dev, panel); - if (IS_ERR(pdata->panel_bridge)) return PTR_ERR(pdata->panel_bridge); + } + DRM_DEV_DEBUG_DRIVER(dev, "get panel node.\n"); return 0; From 73a46da4fa7ca088e7bbf8be817114b9ec40f01b Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 8 Mar 2022 11:06:57 -0800 Subject: [PATCH 00135/11454] drm/bridge: Add MAINTAINERS entry for DRM drivers for bridge chip bindings The bindings for bridge chips should also get the same maintainers entry so the right people get notified about bindings changes. Signed-off-by: Douglas Anderson Reviewed-by: Laurent Pinchart Acked-by: Neil Armstrong Acked-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220308110615.1.I1f1b10daf7361feb6705f789deb680b8d7720de9@changeid --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index 0216d2ffe728..a73179d55d00 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6403,6 +6403,7 @@ R: Jonas Karlman R: Jernej Skrabec S: Maintained T: git git://anongit.freedesktop.org/drm/drm-misc +F: Documentation/devicetree/bindings/display/bridge/ F: drivers/gpu/drm/bridge/ DRM DRIVERS FOR EXYNOS From 59c217b3dde5927ceb37dd403d1058fa9b98cc7a Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 8 Mar 2022 11:06:58 -0800 Subject: [PATCH 00136/11454] drm/bridge: Add myself as a reviewer for the TI SN65DSI86 bridge chip I've spent quite a bit of time poking at this driver and it's used on several Chromebooks I'm involved with. I'd like to get notified about patches. Add myself as a reviewer. It's expected that changes will still be landed through drm-misc as they always have been. Signed-off-by: Douglas Anderson Reviewed-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220308110615.2.I4485769d5b25a8096508e839b8fea12ce7b836d3@changeid --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index a73179d55d00..7d25d0b4dccc 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6284,6 +6284,11 @@ DRM DRIVER FOR TDFX VIDEO CARDS S: Orphan / Obsolete F: drivers/gpu/drm/tdfx/ +DRM DRIVER FOR TI SN65DSI86 BRIDGE CHIP +R: Douglas Anderson +F: Documentation/devicetree/bindings/display/bridge/ti,sn65dsi86.yaml +F: drivers/gpu/drm/bridge/ti-sn65dsi86.c + DRM DRIVER FOR TPO TPG110 PANELS M: Linus Walleij S: Maintained From 46db48f25ed116bf028eca583a0d85a8ae86dd0a Mon Sep 17 00:00:00 2001 From: Douglas Anderson Date: Tue, 8 Mar 2022 11:06:59 -0800 Subject: [PATCH 00137/11454] drm/bridge: Add myself as a reviewer for the Parade PS8640 bridge chip Though the parade bridge chip is a little bit of a black box, I'm at least interested in hearing about changes to the driver since this bridge chip is used on some Chromebooks that I'm involved with. Signed-off-by: Douglas Anderson Reviewed-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220308110615.3.I04f99fbcc14b8c09610b4b18f0696c992a44d2b7@changeid --- MAINTAINERS | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 7d25d0b4dccc..db7fe53643c2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6171,6 +6171,11 @@ S: Maintained F: Documentation/devicetree/bindings/display/panel/olimex,lcd-olinuxino.yaml F: drivers/gpu/drm/panel/panel-olimex-lcd-olinuxino.c +DRM DRIVER FOR PARADE PS8640 BRIDGE CHIP +R: Douglas Anderson +F: Documentation/devicetree/bindings/display/bridge/ps8640.yaml +F: drivers/gpu/drm/bridge/parade-ps8640.c + DRM DRIVER FOR PERVASIVE DISPLAYS REPAPER PANELS M: Noralf Trønnes S: Maintained From 8fb6c44fe8468f92ac7b8bbfcca4404a4e88645f Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 1 Mar 2022 18:11:38 -0800 Subject: [PATCH 00138/11454] drm/bridge: analogix_dp: Grab runtime PM reference for DP-AUX If the display is not enable()d, then we aren't holding a runtime PM reference here. Thus, it's easy to accidentally cause a hang, if user space is poking around at /dev/drm_dp_aux0 at the "wrong" time. Let's get a runtime PM reference, and check that we "see" the panel. Don't force any panel power-up, etc., because that can be intrusive, and that's not what other drivers do (see drivers/gpu/drm/bridge/ti-sn65dsi86.c and drivers/gpu/drm/bridge/parade-ps8640.c.) Fixes: 0d97ad03f422 ("drm/bridge: analogix_dp: Remove duplicated code") Cc: Cc: Tomeu Vizoso Signed-off-by: Brian Norris Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20220301181107.v4.1.I773a08785666ebb236917b0c8e6c05e3de471e75@changeid --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index eb590fb8e8d0..d45931913dfc 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1632,8 +1632,19 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { struct analogix_dp_device *dp = to_dp(aux); + int ret; - return analogix_dp_transfer(dp, msg); + pm_runtime_get_sync(dp->dev); + + ret = analogix_dp_detect_hpd(dp); + if (ret) + goto out; + + ret = analogix_dp_transfer(dp, msg); +out: + pm_runtime_put(dp->dev); + + return ret; } struct analogix_dp_device * From f28dd50756757cde90dbf139c100fb45b13dccb3 Mon Sep 17 00:00:00 2001 From: Brian Norris Date: Tue, 1 Mar 2022 18:11:39 -0800 Subject: [PATCH 00139/11454] drm/bridge: analogix_dp: Enable autosuspend DP AUX transactions can consist of many short operations. There's no need to power things up/down in short intervals. I pick an arbitrary 100ms; for the systems I'm testing (Rockchip RK3399), runtime-PM transitions only take a few microseconds. Signed-off-by: Brian Norris Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20220301181107.v4.2.I48b18ab197c9b649d376cf8cfd934e59d338f86d@changeid --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index d45931913dfc..c5afccd46440 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1119,9 +1119,7 @@ static int analogix_dp_get_modes(struct drm_connector *connector) return 0; } - pm_runtime_get_sync(dp->dev); edid = drm_get_edid(connector, &dp->aux.ddc); - pm_runtime_put(dp->dev); if (edid) { drm_connector_update_edid_property(&dp->connector, edid); @@ -1642,7 +1640,8 @@ static ssize_t analogix_dpaux_transfer(struct drm_dp_aux *aux, ret = analogix_dp_transfer(dp, msg); out: - pm_runtime_put(dp->dev); + pm_runtime_mark_last_busy(dp->dev); + pm_runtime_put_autosuspend(dp->dev); return ret; } @@ -1775,6 +1774,8 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev) if (ret) return ret; + pm_runtime_use_autosuspend(dp->dev); + pm_runtime_set_autosuspend_delay(dp->dev, 100); pm_runtime_enable(dp->dev); ret = analogix_dp_create_bridge(drm_dev, dp); @@ -1786,6 +1787,7 @@ int analogix_dp_bind(struct analogix_dp_device *dp, struct drm_device *drm_dev) return 0; err_disable_pm_runtime: + pm_runtime_dont_use_autosuspend(dp->dev); pm_runtime_disable(dp->dev); drm_dp_aux_unregister(&dp->aux); @@ -1804,6 +1806,7 @@ void analogix_dp_unbind(struct analogix_dp_device *dp) } drm_dp_aux_unregister(&dp->aux); + pm_runtime_dont_use_autosuspend(dp->dev); pm_runtime_disable(dp->dev); } EXPORT_SYMBOL_GPL(analogix_dp_unbind); From 759b30f70597562ebfa60b516c4c5cbfc2f432dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Mar 2022 19:32:25 +0200 Subject: [PATCH 00140/11454] drm/i915: Remove leftover cnl SAGV block time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GLK doesn't support SAGV, so with CNL gone there is no use for having a DISPLAY_VER==10 SAGV block time in the code. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220308173230.4182-2-ville.syrjala@linux.intel.com Reviewed-by: Vinod Govindapillai --- drivers/gpu/drm/i915/intel_pm.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index f70eb10ab24d..8ee31c9590a7 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3689,9 +3689,6 @@ skl_setup_sagv_block_time(struct drm_i915_private *dev_priv) } else if (DISPLAY_VER(dev_priv) == 11) { dev_priv->sagv_block_time_us = 10; return; - } else if (DISPLAY_VER(dev_priv) == 10) { - dev_priv->sagv_block_time_us = 20; - return; } else if (DISPLAY_VER(dev_priv) == 9) { dev_priv->sagv_block_time_us = 30; return; From 353bb6a5f2ac495f289b7c7a528c7d134c9a8ec4 Mon Sep 17 00:00:00 2001 From: Simon Trimmer Date: Wed, 9 Mar 2022 13:00:17 +0000 Subject: [PATCH 00141/11454] ASoC: wm_adsp: Compressed stream DSP memory structs should be __packed The compressed stream code has a bunch of structs that are used to represent DSP memory but have not been marked __packed. This isn't safe, they could get padded on a 64-bit build. Signed-off-by: Simon Trimmer Link: https://lore.kernel.org/r/20220309130017.2816-1-simont@opensource.cirrus.com Acked-by: Charles Keepax Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 0582585236a2..5a57bb04a0ae 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -97,13 +97,13 @@ struct wm_adsp_system_config_xm_hdr { __be32 wdma[8]; __be32 build_job_name[3]; __be32 build_job_number; -}; +} __packed; struct wm_halo_system_config_xm_hdr { __be32 halo_heartbeat; __be32 build_job_name[3]; __be32 build_job_number; -}; +} __packed; struct wm_adsp_alg_xm_struct { __be32 magic; @@ -114,13 +114,13 @@ struct wm_adsp_alg_xm_struct { __be32 high_water_mark; __be32 low_water_mark; __be64 smoothed_power; -}; +} __packed; struct wm_adsp_host_buf_coeff_v1 { __be32 host_buf_ptr; /* Host buffer pointer */ __be32 versions; /* Version numbers */ __be32 name[4]; /* The buffer name */ -}; +} __packed; struct wm_adsp_buffer { __be32 buf1_base; /* Base addr of first buffer area */ @@ -141,7 +141,7 @@ struct wm_adsp_buffer { __be32 min_free; /* min free space since stream start */ __be32 blocks_written[2]; /* total blocks written (64 bit) */ __be32 words_written[2]; /* total words written (64 bit) */ -}; +} __packed; struct wm_adsp_compr; From 8d8b2dd3995f80f26723ad61865e1eb265225561 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Feb 2022 15:13:15 +0200 Subject: [PATCH 00142/11454] drm/i915: Make the PIPESRC rect relative to the entire bigjoiner area MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using bigjoiner it's useful to know the offset of each individual pipe in the whole set of joined pipes. Let's include that information in our PIPESRC rectangle. With this we can make the plane clipping code blissfully unaware of bigjoiner usage, as all we have to do is remove the pipe's offset from the final plane destination coordinates. v2: Use intel_bigjoiner_num_pipes() Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220223131315.18016-14-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- .../gpu/drm/i915/display/intel_atomic_plane.c | 7 +++--- drivers/gpu/drm/i915/display/intel_cursor.c | 8 ++++--- drivers/gpu/drm/i915/display/intel_display.c | 21 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_overlay.c | 22 +++++++++---------- 4 files changed, 40 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 0eae08e389c5..f4d2814867d7 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -823,10 +823,6 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, return -ERANGE; } - /* right side of the image is on the slave crtc, adjust dst to match */ - if (intel_crtc_is_bigjoiner_slave(crtc_state)) - drm_rect_translate(dst, -drm_rect_width(&crtc_state->pipe_src), 0); - /* * FIXME: This might need further adjustment for seamless scaling * with phase information, for the 2p2 and 2p1 scenarios. @@ -843,6 +839,9 @@ int intel_atomic_plane_check_clipping(struct intel_plane_state *plane_state, return -EINVAL; } + /* final plane coordinates will be relative to the plane's pipe */ + drm_rect_translate(dst, -clip->x1, -clip->y1); + return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_cursor.c b/drivers/gpu/drm/i915/display/intel_cursor.c index 24a42be1b1c5..8c80de877605 100644 --- a/drivers/gpu/drm/i915/display/intel_cursor.c +++ b/drivers/gpu/drm/i915/display/intel_cursor.c @@ -152,9 +152,11 @@ static int intel_check_cursor(struct intel_crtc_state *crtc_state, /* Use the unclipped src/dst rectangles, which we program to hw */ plane_state->uapi.src = src; plane_state->uapi.dst = dst; - if (intel_crtc_is_bigjoiner_slave(crtc_state)) - drm_rect_translate(&plane_state->uapi.dst, - -drm_rect_width(&crtc_state->pipe_src), 0); + + /* final plane coordinates will be relative to the plane's pipe */ + drm_rect_translate(&plane_state->uapi.dst, + -crtc_state->pipe_src.x1, + -crtc_state->pipe_src.y1); ret = intel_cursor_check_surface(plane_state); if (ret) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7a11f2224662..1ce31f79625f 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3192,6 +3192,23 @@ static void intel_get_transcoder_timings(struct intel_crtc *crtc, } } +static void intel_bigjoiner_adjust_pipe_src(struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + int num_pipes = intel_bigjoiner_num_pipes(crtc_state); + enum pipe master_pipe, pipe = crtc->pipe; + int width; + + if (num_pipes < 2) + return; + + master_pipe = bigjoiner_master_pipe(crtc_state); + width = drm_rect_width(&crtc_state->pipe_src); + + drm_rect_translate_to(&crtc_state->pipe_src, + (pipe - master_pipe) * width, 0); +} + static void intel_get_pipe_src_size(struct intel_crtc *crtc, struct intel_crtc_state *pipe_config) { @@ -3204,6 +3221,8 @@ static void intel_get_pipe_src_size(struct intel_crtc *crtc, drm_rect_init(&pipe_config->pipe_src, 0, 0, REG_FIELD_GET(PIPESRC_WIDTH_MASK, tmp) + 1, REG_FIELD_GET(PIPESRC_HEIGHT_MASK, tmp) + 1); + + intel_bigjoiner_adjust_pipe_src(pipe_config); } static void i9xx_set_pipeconf(const struct intel_crtc_state *crtc_state) @@ -5838,6 +5857,8 @@ intel_modeset_pipe_config_late(struct intel_crtc_state *crtc_state) struct drm_connector *connector; int i; + intel_bigjoiner_adjust_pipe_src(crtc_state); + for_each_new_connector_in_state(&state->base, connector, conn_state, i) { struct intel_encoder *encoder = diff --git a/drivers/gpu/drm/i915/display/intel_overlay.c b/drivers/gpu/drm/i915/display/intel_overlay.c index 631e1f1dc5e6..ee46561b5ae8 100644 --- a/drivers/gpu/drm/i915/display/intel_overlay.c +++ b/drivers/gpu/drm/i915/display/intel_overlay.c @@ -958,21 +958,21 @@ static void update_pfit_vscale_ratio(struct intel_overlay *overlay) static int check_overlay_dst(struct intel_overlay *overlay, struct drm_intel_overlay_put_image *rec) { - const struct intel_crtc_state *pipe_config = + const struct intel_crtc_state *crtc_state = overlay->crtc->config; - int pipe_src_w = drm_rect_width(&pipe_config->pipe_src); - int pipe_src_h = drm_rect_height(&pipe_config->pipe_src); + struct drm_rect req, clipped; - if (rec->dst_height == 0 || rec->dst_width == 0) + drm_rect_init(&req, rec->dst_x, rec->dst_y, + rec->dst_width, rec->dst_height); + + clipped = req; + drm_rect_intersect(&clipped, &crtc_state->pipe_src); + + if (!drm_rect_visible(&clipped) || + !drm_rect_equals(&clipped, &req)) return -EINVAL; - if (rec->dst_x < pipe_src_w && - rec->dst_x + rec->dst_width <= pipe_src_w && - rec->dst_y < pipe_src_h && - rec->dst_y + rec->dst_height <= pipe_src_h) - return 0; - else - return -EINVAL; + return 0; } static int check_overlay_scaling(struct drm_intel_overlay_put_image *rec) From 9ca48a806cf241e9fe374206b8b0dd9c80ccdde3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2022 23:43:01 +0200 Subject: [PATCH 00143/11454] drm/i915: Store the /5 target clock in struct dpll on vlv/chv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Unify vlv/chv with earlier platforms so that the sturct dpll::dot represents the /5 clock frequency (ie. DP symbol rate or HDMI TMDS rate) rather than the *5 fast clock (/2 of the bitrate). Makes life a little less confusing to get the same number back in .dot which we fed into the DPLL algorithm. v2: Actually just include the 5x in the final P divider Do the same change to the hand rolled gvt code v3: Missed a few *5 in *_find_best_dpll() Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220309214301.22899-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_dpll.c | 23 ++++++++++------------- drivers/gpu/drm/i915/gvt/handlers.c | 4 ++-- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 0ae37fdbf2a5..53184154bc5d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -254,12 +254,12 @@ static const struct intel_limit ilk_limits_dual_lvds_100m = { static const struct intel_limit intel_limits_vlv = { /* - * These are the data rate limits (measured in fast clocks) + * These are based on the data rate limits (measured in fast clocks) * since those are the strictest limits we have. The fast * clock and actual rate limits are more relaxed, so checking * them would make no difference. */ - .dot = { .min = 25000 * 5, .max = 270000 * 5 }, + .dot = { .min = 25000, .max = 270000 }, .vco = { .min = 4000000, .max = 6000000 }, .n = { .min = 1, .max = 7 }, .m1 = { .min = 2, .max = 3 }, @@ -270,12 +270,12 @@ static const struct intel_limit intel_limits_vlv = { static const struct intel_limit intel_limits_chv = { /* - * These are the data rate limits (measured in fast clocks) + * These are based on the data rate limits (measured in fast clocks) * since those are the strictest limits we have. The fast * clock and actual rate limits are more relaxed, so checking * them would make no difference. */ - .dot = { .min = 25000 * 5, .max = 540000 * 5}, + .dot = { .min = 25000, .max = 540000 }, .vco = { .min = 4800000, .max = 6480000 }, .n = { .min = 1, .max = 1 }, .m1 = { .min = 2, .max = 2 }, @@ -337,26 +337,26 @@ int i9xx_calc_dpll_params(int refclk, struct dpll *clock) int vlv_calc_dpll_params(int refclk, struct dpll *clock) { clock->m = clock->m1 * clock->m2; - clock->p = clock->p1 * clock->p2; + clock->p = clock->p1 * clock->p2 * 5; if (WARN_ON(clock->n == 0 || clock->p == 0)) return 0; clock->vco = DIV_ROUND_CLOSEST(refclk * clock->m, clock->n); clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); - return clock->dot / 5; + return clock->dot; } int chv_calc_dpll_params(int refclk, struct dpll *clock) { clock->m = clock->m1 * clock->m2; - clock->p = clock->p1 * clock->p2; + clock->p = clock->p1 * clock->p2 * 5; if (WARN_ON(clock->n == 0 || clock->p == 0)) return 0; clock->vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock->m), clock->n << 22); clock->dot = DIV_ROUND_CLOSEST(clock->vco, clock->p); - return clock->dot / 5; + return clock->dot; } /* @@ -659,8 +659,6 @@ vlv_find_best_dpll(const struct intel_limit *limit, int max_n = min(limit->n.max, refclk / 19200); bool found = false; - target *= 5; /* fast clock */ - memset(best_clock, 0, sizeof(*best_clock)); /* based on hardware requirement, prefer smaller n to precision */ @@ -668,7 +666,7 @@ vlv_find_best_dpll(const struct intel_limit *limit, for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { for (clock.p2 = limit->p2.p2_fast; clock.p2 >= limit->p2.p2_slow; clock.p2 -= clock.p2 > 10 ? 2 : 1) { - clock.p = clock.p1 * clock.p2; + clock.p = clock.p1 * clock.p2 * 5; /* based on hardware requirement, prefer bigger m1,m2 values */ for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; clock.m1++) { unsigned int ppm; @@ -729,7 +727,6 @@ chv_find_best_dpll(const struct intel_limit *limit, */ clock.n = 1; clock.m1 = 2; - target *= 5; /* fast clock */ for (clock.p1 = limit->p1.max; clock.p1 >= limit->p1.min; clock.p1--) { for (clock.p2 = limit->p2.p2_fast; @@ -737,7 +734,7 @@ chv_find_best_dpll(const struct intel_limit *limit, clock.p2 -= clock.p2 > 10 ? 2 : 1) { unsigned int error_ppm; - clock.p = clock.p1 * clock.p2; + clock.p = clock.p1 * clock.p2 * 5; m2 = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(target, clock.p * clock.n) << 22, refclk * clock.m1); diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 520a7e1942f3..efdd2f3f9d73 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -583,7 +583,7 @@ static u32 bxt_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port) clock.p1 = (vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch)) & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT; clock.p2 = (vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch)) & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT; clock.m = clock.m1 * clock.m2; - clock.p = clock.p1 * clock.p2; + clock.p = clock.p1 * clock.p2 * 5; if (clock.n == 0 || clock.p == 0) { gvt_dbg_dpy("vgpu-%d PORT_%c PLL has invalid divider\n", vgpu->id, port_name(port)); @@ -593,7 +593,7 @@ static u32 bxt_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port) clock.vco = DIV_ROUND_CLOSEST_ULL(mul_u32_u32(refclk, clock.m), clock.n << 22); clock.dot = DIV_ROUND_CLOSEST(clock.vco, clock.p); - dp_br = clock.dot / 5; + dp_br = clock.dot; out: return dp_br; From 8e38c6b57e5d1481c43a0b9f77a80e3deeeb7721 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Mar 2022 01:39:34 +0200 Subject: [PATCH 00144/11454] drm/i915: Remove redundant/wrong comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the comment specifying the exact formulat for calculating the DPLL frequency from the *_find_best_dpll() functions. Each platform variant has its own way to calculate these and we have the code already to do that. These comments are entirely redundant and often even wrong so just get rid of them. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220307233940.4161-3-ville.syrjala@linux.intel.com Acked-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index 53184154bc5d..c0c76ff8b590 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -425,8 +425,7 @@ i9xx_select_p2_div(const struct intel_limit *limit, /* * Returns a set of divisors for the desired target clock with the given - * refclk, or FALSE. The returned values represent the clock equation: - * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + * refclk, or FALSE. * * Target and reference clocks are specified in kHz. * @@ -484,8 +483,7 @@ i9xx_find_best_dpll(const struct intel_limit *limit, /* * Returns a set of divisors for the desired target clock with the given - * refclk, or FALSE. The returned values represent the clock equation: - * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + * refclk, or FALSE. * * Target and reference clocks are specified in kHz. * @@ -541,8 +539,7 @@ pnv_find_best_dpll(const struct intel_limit *limit, /* * Returns a set of divisors for the desired target clock with the given - * refclk, or FALSE. The returned values represent the clock equation: - * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + * refclk, or FALSE. * * Target and reference clocks are specified in kHz. * @@ -641,8 +638,7 @@ static bool vlv_PLL_is_optimal(struct drm_device *dev, int target_freq, /* * Returns a set of divisors for the desired target clock with the given - * refclk, or FALSE. The returned values represent the clock equation: - * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + * refclk, or FALSE. */ static bool vlv_find_best_dpll(const struct intel_limit *limit, @@ -700,8 +696,7 @@ vlv_find_best_dpll(const struct intel_limit *limit, /* * Returns a set of divisors for the desired target clock with the given - * refclk, or FALSE. The returned values represent the clock equation: - * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. + * refclk, or FALSE. */ static bool chv_find_best_dpll(const struct intel_limit *limit, From 8b080334e97e1aa2ce78259a11e92895ae073482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Mar 2022 01:39:35 +0200 Subject: [PATCH 00145/11454] drm/i915: Clean up bxt/glk PLL registers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use REG_BIT() & co. for bxt/glk PLL registers. v2: Reorder a few bits for consistency Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220307233940.4161-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 32 +++++----- drivers/gpu/drm/i915/gvt/handlers.c | 15 +++-- drivers/gpu/drm/i915/i915_reg.h | 62 +++++++++---------- 3 files changed, 57 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 4595795d694f..2a88c6fa1f34 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -1898,7 +1898,7 @@ static void bxt_ddi_pll_enable(struct drm_i915_private *dev_priv, /* Write M2 integer */ temp = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 0)); - temp &= ~PORT_PLL_M2_MASK; + temp &= ~PORT_PLL_M2_INT_MASK; temp |= pll->state.hw_state.pll0; intel_de_write(dev_priv, BXT_PORT_PLL(phy, ch, 0), temp); @@ -2034,7 +2034,7 @@ static bool bxt_ddi_pll_get_hw_state(struct drm_i915_private *dev_priv, hw_state->ebb4 &= PORT_PLL_10BIT_CLK_ENABLE; hw_state->pll0 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 0)); - hw_state->pll0 &= PORT_PLL_M2_MASK; + hw_state->pll0 &= PORT_PLL_M2_INT_MASK; hw_state->pll1 = intel_de_read(dev_priv, BXT_PORT_PLL(phy, ch, 1)); hw_state->pll1 &= PORT_PLL_N_MASK; @@ -2200,23 +2200,23 @@ static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, lanestagger = 0x02; dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2); - dpll_hw_state->pll0 = clk_div->m2_int; + dpll_hw_state->pll0 = PORT_PLL_M2_INT(clk_div->m2_int); dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n); - dpll_hw_state->pll2 = clk_div->m2_frac; + dpll_hw_state->pll2 = PORT_PLL_M2_FRAC(clk_div->m2_frac); if (clk_div->m2_frac) dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE; - dpll_hw_state->pll6 = prop_coef | PORT_PLL_INT_COEFF(int_coef); - dpll_hw_state->pll6 |= PORT_PLL_GAIN_CTL(gain_ctl); + dpll_hw_state->pll6 = PORT_PLL_PROP_COEFF(prop_coef) | + PORT_PLL_INT_COEFF(int_coef) | + PORT_PLL_GAIN_CTL(gain_ctl); - dpll_hw_state->pll8 = targ_cnt; + dpll_hw_state->pll8 = PORT_PLL_TARGET_CNT(targ_cnt); - dpll_hw_state->pll9 = 5 << PORT_PLL_LOCK_THRESHOLD_SHIFT; + dpll_hw_state->pll9 = PORT_PLL_LOCK_THRESHOLD(5); - dpll_hw_state->pll10 = - PORT_PLL_DCO_AMP(PORT_PLL_DCO_AMP_DEFAULT) - | PORT_PLL_DCO_AMP_OVR_EN_H; + dpll_hw_state->pll10 = PORT_PLL_DCO_AMP(15) | + PORT_PLL_DCO_AMP_OVR_EN_H; dpll_hw_state->ebb4 = PORT_PLL_10BIT_CLK_ENABLE; @@ -2252,12 +2252,12 @@ static int bxt_ddi_pll_get_freq(struct drm_i915_private *i915, struct dpll clock; clock.m1 = 2; - clock.m2 = (pll_state->pll0 & PORT_PLL_M2_MASK) << 22; + clock.m2 = REG_FIELD_GET(PORT_PLL_M2_INT_MASK, pll_state->pll0) << 22; if (pll_state->pll3 & PORT_PLL_M2_FRAC_ENABLE) - clock.m2 |= pll_state->pll2 & PORT_PLL_M2_FRAC_MASK; - clock.n = (pll_state->pll1 & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT; - clock.p1 = (pll_state->ebb0 & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT; - clock.p2 = (pll_state->ebb0 & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT; + clock.m2 |= REG_FIELD_GET(PORT_PLL_M2_FRAC_MASK, pll_state->pll2); + clock.n = REG_FIELD_GET(PORT_PLL_N_MASK, pll_state->pll1); + clock.p1 = REG_FIELD_GET(PORT_PLL_P1_MASK, pll_state->ebb0); + clock.p2 = REG_FIELD_GET(PORT_PLL_P2_MASK, pll_state->ebb0); return chv_calc_dpll_params(i915->dpll.ref_clks.nssc, &clock); } diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index efdd2f3f9d73..0ee3ecc83234 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -576,12 +576,17 @@ static u32 bxt_vgpu_get_dp_bitrate(struct intel_vgpu *vgpu, enum port port) } clock.m1 = 2; - clock.m2 = (vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 0)) & PORT_PLL_M2_MASK) << 22; + clock.m2 = REG_FIELD_GET(PORT_PLL_M2_INT_MASK, + vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 0))) << 22; if (vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 3)) & PORT_PLL_M2_FRAC_ENABLE) - clock.m2 |= vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 2)) & PORT_PLL_M2_FRAC_MASK; - clock.n = (vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 1)) & PORT_PLL_N_MASK) >> PORT_PLL_N_SHIFT; - clock.p1 = (vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch)) & PORT_PLL_P1_MASK) >> PORT_PLL_P1_SHIFT; - clock.p2 = (vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch)) & PORT_PLL_P2_MASK) >> PORT_PLL_P2_SHIFT; + clock.m2 |= REG_FIELD_GET(PORT_PLL_M2_FRAC_MASK, + vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 2))); + clock.n = REG_FIELD_GET(PORT_PLL_N_MASK, + vgpu_vreg_t(vgpu, BXT_PORT_PLL(phy, ch, 1))); + clock.p1 = REG_FIELD_GET(PORT_PLL_P1_MASK, + vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch))); + clock.p2 = REG_FIELD_GET(PORT_PLL_P2_MASK, + vgpu_vreg_t(vgpu, BXT_PORT_PLL_EBB_0(phy, ch))); clock.m = clock.m1 * clock.m2; clock.p = clock.p1 * clock.p2 * 5; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ad962c9b9d66..601158bef5d7 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -644,22 +644,20 @@ #define _PORT_PLL_A 0x46074 #define _PORT_PLL_B 0x46078 #define _PORT_PLL_C 0x4607c -#define PORT_PLL_ENABLE (1 << 31) -#define PORT_PLL_LOCK (1 << 30) -#define PORT_PLL_REF_SEL (1 << 27) -#define PORT_PLL_POWER_ENABLE (1 << 26) -#define PORT_PLL_POWER_STATE (1 << 25) +#define PORT_PLL_ENABLE REG_BIT(31) +#define PORT_PLL_LOCK REG_BIT(30) +#define PORT_PLL_REF_SEL REG_BIT(27) +#define PORT_PLL_POWER_ENABLE REG_BIT(26) +#define PORT_PLL_POWER_STATE REG_BIT(25) #define BXT_PORT_PLL_ENABLE(port) _MMIO_PORT(port, _PORT_PLL_A, _PORT_PLL_B) #define _PORT_PLL_EBB_0_A 0x162034 #define _PORT_PLL_EBB_0_B 0x6C034 #define _PORT_PLL_EBB_0_C 0x6C340 -#define PORT_PLL_P1_SHIFT 13 -#define PORT_PLL_P1_MASK (0x07 << PORT_PLL_P1_SHIFT) -#define PORT_PLL_P1(x) ((x) << PORT_PLL_P1_SHIFT) -#define PORT_PLL_P2_SHIFT 8 -#define PORT_PLL_P2_MASK (0x1f << PORT_PLL_P2_SHIFT) -#define PORT_PLL_P2(x) ((x) << PORT_PLL_P2_SHIFT) +#define PORT_PLL_P1_MASK REG_GENMASK(15, 13) +#define PORT_PLL_P1(p1) REG_FIELD_PREP(PORT_PLL_P1_MASK, (p1)) +#define PORT_PLL_P2_MASK REG_GENMASK(12, 8) +#define PORT_PLL_P2(p2) REG_FIELD_PREP(PORT_PLL_P2_MASK, (p2)) #define BXT_PORT_PLL_EBB_0(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ _PORT_PLL_EBB_0_B, \ _PORT_PLL_EBB_0_C) @@ -667,8 +665,8 @@ #define _PORT_PLL_EBB_4_A 0x162038 #define _PORT_PLL_EBB_4_B 0x6C038 #define _PORT_PLL_EBB_4_C 0x6C344 -#define PORT_PLL_10BIT_CLK_ENABLE (1 << 13) -#define PORT_PLL_RECALIBRATE (1 << 14) +#define PORT_PLL_RECALIBRATE REG_BIT(14) +#define PORT_PLL_10BIT_CLK_ENABLE REG_BIT(13) #define BXT_PORT_PLL_EBB_4(phy, ch) _MMIO_BXT_PHY_CH(phy, ch, \ _PORT_PLL_EBB_4_B, \ _PORT_PLL_EBB_4_C) @@ -677,31 +675,33 @@ #define _PORT_PLL_0_B 0x6C100 #define _PORT_PLL_0_C 0x6C380 /* PORT_PLL_0_A */ -#define PORT_PLL_M2_MASK 0xFF +#define PORT_PLL_M2_INT_MASK REG_GENMASK(7, 0) +#define PORT_PLL_M2_INT(m2_int) REG_FIELD_PREP(PORT_PLL_M2_INT_MASK, (m2_int)) /* PORT_PLL_1_A */ -#define PORT_PLL_N_SHIFT 8 -#define PORT_PLL_N_MASK (0x0F << PORT_PLL_N_SHIFT) -#define PORT_PLL_N(x) ((x) << PORT_PLL_N_SHIFT) +#define PORT_PLL_N_MASK REG_GENMASK(11, 8) +#define PORT_PLL_N(n) REG_FIELD_PREP(PORT_PLL_N_MASK, (n)) /* PORT_PLL_2_A */ -#define PORT_PLL_M2_FRAC_MASK 0x3FFFFF +#define PORT_PLL_M2_FRAC_MASK REG_GENMASK(21, 0) +#define PORT_PLL_M2_FRAC(m2_frac) REG_FIELD_PREP(PORT_PLL_M2_FRAC_MASK, (m2_frac)) /* PORT_PLL_3_A */ -#define PORT_PLL_M2_FRAC_ENABLE (1 << 16) +#define PORT_PLL_M2_FRAC_ENABLE REG_BIT(16) /* PORT_PLL_6_A */ -#define PORT_PLL_PROP_COEFF_MASK 0xF -#define PORT_PLL_INT_COEFF_MASK (0x1F << 8) -#define PORT_PLL_INT_COEFF(x) ((x) << 8) -#define PORT_PLL_GAIN_CTL_MASK (0x07 << 16) -#define PORT_PLL_GAIN_CTL(x) ((x) << 16) +#define PORT_PLL_GAIN_CTL_MASK REG_GENMASK(18, 16) +#define PORT_PLL_GAIN_CTL(x) REG_FIELD_PREP(PORT_PLL_GAIN_CTL_MASK, (x)) +#define PORT_PLL_INT_COEFF_MASK REG_GENMASK(12, 8) +#define PORT_PLL_INT_COEFF(x) REG_FIELD_PREP(PORT_PLL_INT_COEFF_MASK, (x)) +#define PORT_PLL_PROP_COEFF_MASK REG_GENMASK(3, 0) +#define PORT_PLL_PROP_COEFF(x) REG_FIELD_PREP(PORT_PLL_PROP_COEFF_MASK, (x)) /* PORT_PLL_8_A */ -#define PORT_PLL_TARGET_CNT_MASK 0x3FF +#define PORT_PLL_TARGET_CNT_MASK REG_GENMASK(9, 0) +#define PORT_PLL_TARGET_CNT(x) REG_FIELD_PREP(PORT_PLL_TARGET_CNT_MASK, (x)) /* PORT_PLL_9_A */ -#define PORT_PLL_LOCK_THRESHOLD_SHIFT 1 -#define PORT_PLL_LOCK_THRESHOLD_MASK (0x7 << PORT_PLL_LOCK_THRESHOLD_SHIFT) +#define PORT_PLL_LOCK_THRESHOLD_MASK REG_GENMASK(3, 1) +#define PORT_PLL_LOCK_THRESHOLD(x) REG_FIELD_PREP(PORT_PLL_LOCK_THRESHOLD_MASK, (x)) /* PORT_PLL_10_A */ -#define PORT_PLL_DCO_AMP_OVR_EN_H (1 << 27) -#define PORT_PLL_DCO_AMP_DEFAULT 15 -#define PORT_PLL_DCO_AMP_MASK 0x3c00 -#define PORT_PLL_DCO_AMP(x) ((x) << 10) +#define PORT_PLL_DCO_AMP_OVR_EN_H REG_BIT(27) +#define PORT_PLL_DCO_AMP_MASK REG_GENMASK(13, 10) +#define PORT_PLL_DCO_AMP(x) REG_FIELD_PREP(PORT_PLL_DCO_AMP_MASK, (x)) #define _PORT_PLL_BASE(phy, ch) _BXT_PHY_CH(phy, ch, \ _PORT_PLL_0_B, \ _PORT_PLL_0_C) From 734fe6f17237e6107b6f984e51d2b6b769a594e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Mar 2022 01:39:36 +0200 Subject: [PATCH 00146/11454] drm/i915: Store the m2 divider as a whole in bxt_clk_div MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Get rid of the pointless m2 int vs. frac split in bxt_clk_div and just store the whole divider as one. v2: Document the full divider as a proper decimal number Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220307233940.4161-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 27 +++++++++---------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 2a88c6fa1f34..ae3c07cc2eaa 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2088,8 +2088,7 @@ struct bxt_clk_div { int clock; u32 p1; u32 p2; - u32 m2_int; - u32 m2_frac; + u32 m2; u32 n; int vco; @@ -2097,13 +2096,14 @@ struct bxt_clk_div { /* pre-calculated values for DP linkrates */ static const struct bxt_clk_div bxt_dp_clk_val[] = { - { .clock = 162000, .p1 = 4, .p2 = 2, .m2_int = 32, .m2_frac = 1677722, .n = 1, }, - { .clock = 270000, .p1 = 4, .p2 = 1, .m2_int = 27, .m2_frac = 0, .n = 1, }, - { .clock = 540000, .p1 = 2, .p2 = 1, .m2_int = 27, .m2_frac = 0, .n = 1, }, - { .clock = 216000, .p1 = 3, .p2 = 2, .m2_int = 32, .m2_frac = 1677722, .n = 1, }, - { .clock = 243000, .p1 = 4, .p2 = 1, .m2_int = 24, .m2_frac = 1258291, .n = 1, }, - { .clock = 324000, .p1 = 4, .p2 = 1, .m2_int = 32, .m2_frac = 1677722, .n = 1, }, - { .clock = 432000, .p1 = 3, .p2 = 1, .m2_int = 32, .m2_frac = 1677722, .n = 1, }, + /* m2 is .22 binary fixed point */ + { .clock = 162000, .p1 = 4, .p2 = 2, .n = 1, .m2 = 0x819999a /* 32.4 */ }, + { .clock = 270000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x6c00000 /* 27.0 */ }, + { .clock = 540000, .p1 = 2, .p2 = 1, .n = 1, .m2 = 0x6c00000 /* 27.0 */ }, + { .clock = 216000, .p1 = 3, .p2 = 2, .n = 1, .m2 = 0x819999a /* 32.4 */ }, + { .clock = 243000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x6133333 /* 24.3 */ }, + { .clock = 324000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x819999a /* 32.4 */ }, + { .clock = 432000, .p1 = 3, .p2 = 1, .n = 1, .m2 = 0x819999a /* 32.4 */ }, }; static bool @@ -2130,8 +2130,7 @@ bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state, clk_div->p2 = best_clock.p2; drm_WARN_ON(&i915->drm, best_clock.m1 != 2); clk_div->n = best_clock.n; - clk_div->m2_int = best_clock.m2 >> 22; - clk_div->m2_frac = best_clock.m2 & ((1 << 22) - 1); + clk_div->m2 = best_clock.m2; clk_div->vco = best_clock.vco; @@ -2200,11 +2199,11 @@ static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, lanestagger = 0x02; dpll_hw_state->ebb0 = PORT_PLL_P1(clk_div->p1) | PORT_PLL_P2(clk_div->p2); - dpll_hw_state->pll0 = PORT_PLL_M2_INT(clk_div->m2_int); + dpll_hw_state->pll0 = PORT_PLL_M2_INT(clk_div->m2 >> 22); dpll_hw_state->pll1 = PORT_PLL_N(clk_div->n); - dpll_hw_state->pll2 = PORT_PLL_M2_FRAC(clk_div->m2_frac); + dpll_hw_state->pll2 = PORT_PLL_M2_FRAC(clk_div->m2 & 0x3fffff); - if (clk_div->m2_frac) + if (clk_div->m2 & 0x3fffff) dpll_hw_state->pll3 = PORT_PLL_M2_FRAC_ENABLE; dpll_hw_state->pll6 = PORT_PLL_PROP_COEFF(prop_coef) | From fe649940c2a060cee986633d59381c96205d300e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Mar 2022 01:39:37 +0200 Subject: [PATCH 00147/11454] drm/i915: Replace bxt_clk_div with struct dpll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit bxt_clk_div is basically the same as struct dpll. Just use the latter. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220307233940.4161-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 50 ++++++------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index ae3c07cc2eaa..4b52086aa9e9 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2083,69 +2083,51 @@ out: return ret; } -/* bxt clock parameters */ -struct bxt_clk_div { - int clock; - u32 p1; - u32 p2; - u32 m2; - u32 n; - - int vco; -}; - /* pre-calculated values for DP linkrates */ -static const struct bxt_clk_div bxt_dp_clk_val[] = { +static const struct dpll bxt_dp_clk_val[] = { /* m2 is .22 binary fixed point */ - { .clock = 162000, .p1 = 4, .p2 = 2, .n = 1, .m2 = 0x819999a /* 32.4 */ }, - { .clock = 270000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x6c00000 /* 27.0 */ }, - { .clock = 540000, .p1 = 2, .p2 = 1, .n = 1, .m2 = 0x6c00000 /* 27.0 */ }, - { .clock = 216000, .p1 = 3, .p2 = 2, .n = 1, .m2 = 0x819999a /* 32.4 */ }, - { .clock = 243000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x6133333 /* 24.3 */ }, - { .clock = 324000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x819999a /* 32.4 */ }, - { .clock = 432000, .p1 = 3, .p2 = 1, .n = 1, .m2 = 0x819999a /* 32.4 */ }, + { .dot = 162000, .p1 = 4, .p2 = 2, .n = 1, .m2 = 0x819999a /* 32.4 */ }, + { .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x6c00000 /* 27.0 */ }, + { .dot = 540000, .p1 = 2, .p2 = 1, .n = 1, .m2 = 0x6c00000 /* 27.0 */ }, + { .dot = 216000, .p1 = 3, .p2 = 2, .n = 1, .m2 = 0x819999a /* 32.4 */ }, + { .dot = 243000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x6133333 /* 24.3 */ }, + { .dot = 324000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x819999a /* 32.4 */ }, + { .dot = 432000, .p1 = 3, .p2 = 1, .n = 1, .m2 = 0x819999a /* 32.4 */ }, }; static bool bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state, - struct bxt_clk_div *clk_div) + struct dpll *clk_div) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct dpll best_clock; /* Calculate HDMI div */ /* * FIXME: tie the following calculation into * i9xx_crtc_compute_clock */ - if (!bxt_find_best_dpll(crtc_state, &best_clock)) { + if (!bxt_find_best_dpll(crtc_state, clk_div)) { drm_dbg(&i915->drm, "no PLL dividers found for clock %d pipe %c\n", crtc_state->port_clock, pipe_name(crtc->pipe)); return false; } - clk_div->p1 = best_clock.p1; - clk_div->p2 = best_clock.p2; - drm_WARN_ON(&i915->drm, best_clock.m1 != 2); - clk_div->n = best_clock.n; - clk_div->m2 = best_clock.m2; - - clk_div->vco = best_clock.vco; + drm_WARN_ON(&i915->drm, clk_div->m1 != 2); return true; } static void bxt_ddi_dp_pll_dividers(struct intel_crtc_state *crtc_state, - struct bxt_clk_div *clk_div) + struct dpll *clk_div) { int clock = crtc_state->port_clock; int i; *clk_div = bxt_dp_clk_val[0]; for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) { - if (bxt_dp_clk_val[i].clock == clock) { + if (bxt_dp_clk_val[i].dot == clock) { *clk_div = bxt_dp_clk_val[i]; break; } @@ -2155,7 +2137,7 @@ static void bxt_ddi_dp_pll_dividers(struct intel_crtc_state *crtc_state, } static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, - const struct bxt_clk_div *clk_div) + const struct dpll *clk_div) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); struct intel_dpll_hw_state *dpll_hw_state = &crtc_state->dpll_hw_state; @@ -2227,7 +2209,7 @@ static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, static bool bxt_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) { - struct bxt_clk_div clk_div = {}; + struct dpll clk_div = {}; bxt_ddi_dp_pll_dividers(crtc_state, &clk_div); @@ -2237,7 +2219,7 @@ bxt_ddi_dp_set_dpll_hw_state(struct intel_crtc_state *crtc_state) static bool bxt_ddi_hdmi_set_dpll_hw_state(struct intel_crtc_state *crtc_state) { - struct bxt_clk_div clk_div = {}; + struct dpll clk_div = {}; bxt_ddi_hdmi_pll_dividers(crtc_state, &clk_div); From 3917f4846532266f84a308333713d869b124b05a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Mar 2022 01:39:38 +0200 Subject: [PATCH 00148/11454] drm/i915: Replace hand rolled bxt vco calculation with chv_calc_dpll_params() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use chv_calc_dpll_params() to calculate the BXT DP DPLL VCO frequency. We need to add the m1 divider into bxt_dp_clk_val[] for this to work. v2: Make the WARN_ON() sensible Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220307233940.4161-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll_mgr.c | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c index 4b52086aa9e9..b7071da4b7e5 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll_mgr.c +++ b/drivers/gpu/drm/i915/display/intel_dpll_mgr.c @@ -2086,13 +2086,13 @@ out: /* pre-calculated values for DP linkrates */ static const struct dpll bxt_dp_clk_val[] = { /* m2 is .22 binary fixed point */ - { .dot = 162000, .p1 = 4, .p2 = 2, .n = 1, .m2 = 0x819999a /* 32.4 */ }, - { .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x6c00000 /* 27.0 */ }, - { .dot = 540000, .p1 = 2, .p2 = 1, .n = 1, .m2 = 0x6c00000 /* 27.0 */ }, - { .dot = 216000, .p1 = 3, .p2 = 2, .n = 1, .m2 = 0x819999a /* 32.4 */ }, - { .dot = 243000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x6133333 /* 24.3 */ }, - { .dot = 324000, .p1 = 4, .p2 = 1, .n = 1, .m2 = 0x819999a /* 32.4 */ }, - { .dot = 432000, .p1 = 3, .p2 = 1, .n = 1, .m2 = 0x819999a /* 32.4 */ }, + { .dot = 162000, .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ }, + { .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ }, + { .dot = 540000, .p1 = 2, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ }, + { .dot = 216000, .p1 = 3, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ }, + { .dot = 243000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6133333 /* 24.3 */ }, + { .dot = 324000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ }, + { .dot = 432000, .p1 = 3, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ }, }; static bool @@ -2122,18 +2122,21 @@ bxt_ddi_hdmi_pll_dividers(struct intel_crtc_state *crtc_state, static void bxt_ddi_dp_pll_dividers(struct intel_crtc_state *crtc_state, struct dpll *clk_div) { - int clock = crtc_state->port_clock; + struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); int i; *clk_div = bxt_dp_clk_val[0]; for (i = 0; i < ARRAY_SIZE(bxt_dp_clk_val); ++i) { - if (bxt_dp_clk_val[i].dot == clock) { + if (crtc_state->port_clock == bxt_dp_clk_val[i].dot) { *clk_div = bxt_dp_clk_val[i]; break; } } - clk_div->vco = clock * 10 / 2 * clk_div->p1 * clk_div->p2; + chv_calc_dpll_params(i915->dpll.ref_clks.nssc, clk_div); + + drm_WARN_ON(&i915->drm, clk_div->vco == 0 || + clk_div->dot != crtc_state->port_clock); } static bool bxt_ddi_set_dpll_hw_state(struct intel_crtc_state *crtc_state, From 8b3ed19ccf9fc80d8d750f61c620eaf9836008ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Mar 2022 01:39:39 +0200 Subject: [PATCH 00149/11454] drm/i915: Populate bxt/glk DPLL clock limits a bit more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the bxt/glk DPLL min dotclock to 25MHz (HDMI minimum) and the max to 594 MHz (HDMI max). The supported DP frequencies (162MHz-540MHz) fit within the same range. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220307233940.4161-8-ville.syrjala@linux.intel.com Acked-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dpll.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dpll.c b/drivers/gpu/drm/i915/display/intel_dpll.c index c0c76ff8b590..95b9d327ed4d 100644 --- a/drivers/gpu/drm/i915/display/intel_dpll.c +++ b/drivers/gpu/drm/i915/display/intel_dpll.c @@ -285,8 +285,7 @@ static const struct intel_limit intel_limits_chv = { }; static const struct intel_limit intel_limits_bxt = { - /* FIXME: find real dot limits */ - .dot = { .min = 0, .max = INT_MAX }, + .dot = { .min = 25000, .max = 594000 }, .vco = { .min = 4800000, .max = 6700000 }, .n = { .min = 1, .max = 1 }, .m1 = { .min = 2, .max = 2 }, From 15deead931a11b65474eb58b44eefa19f931716c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 8 Mar 2022 01:39:40 +0200 Subject: [PATCH 00150/11454] drm/i915: Remove struct dp_link_dpll MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct dp_link_dpll is a pointless wrapper around struct dpll. Just store the desired link rate into struct dpll::dot and we're done. v2: Document the full divider as a proper decimal number on chv Nuke bogus eDP 1.4 comments for chv while at it Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220307233940.4161-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/g4x_dp.c | 55 +++++++++------------------ 1 file changed, 17 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 22345051e667..8e1338678d91 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -24,58 +24,37 @@ #include "intel_pps.h" #include "vlv_sideband.h" -struct dp_link_dpll { - int clock; - struct dpll dpll; +static const struct dpll g4x_dpll[] = { + { .dot = 162000, .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8, }, + { .dot = 270000, .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2, }, }; -static const struct dp_link_dpll g4x_dpll[] = { - { 162000, - { .p1 = 2, .p2 = 10, .n = 2, .m1 = 23, .m2 = 8 } }, - { 270000, - { .p1 = 1, .p2 = 10, .n = 1, .m1 = 14, .m2 = 2 } } +static const struct dpll pch_dpll[] = { + { .dot = 162000, .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9, }, + { .dot = 270000, .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8, }, }; -static const struct dp_link_dpll pch_dpll[] = { - { 162000, - { .p1 = 2, .p2 = 10, .n = 1, .m1 = 12, .m2 = 9 } }, - { 270000, - { .p1 = 1, .p2 = 10, .n = 2, .m1 = 14, .m2 = 8 } } +static const struct dpll vlv_dpll[] = { + { .dot = 162000, .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81, }, + { .dot = 270000, .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27, }, }; -static const struct dp_link_dpll vlv_dpll[] = { - { 162000, - { .p1 = 3, .p2 = 2, .n = 5, .m1 = 3, .m2 = 81 } }, - { 270000, - { .p1 = 2, .p2 = 2, .n = 1, .m1 = 2, .m2 = 27 } } -}; - -/* - * CHV supports eDP 1.4 that have more link rates. - * Below only provides the fixed rate but exclude variable rate. - */ -static const struct dp_link_dpll chv_dpll[] = { - /* - * CHV requires to program fractional division for m2. - * m2 is stored in fixed point format using formula below - * (m2_int << 22) | m2_fraction - */ - { 162000, /* m2_int = 32, m2_fraction = 1677722 */ - { .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a } }, - { 270000, /* m2_int = 27, m2_fraction = 0 */ - { .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 } }, +static const struct dpll chv_dpll[] = { + /* m2 is .22 binary fixed point */ + { .dot = 162000, .p1 = 4, .p2 = 2, .n = 1, .m1 = 2, .m2 = 0x819999a /* 32.4 */ }, + { .dot = 270000, .p1 = 4, .p2 = 1, .n = 1, .m1 = 2, .m2 = 0x6c00000 /* 27.0 */ }, }; const struct dpll *vlv_get_dpll(struct drm_i915_private *i915) { - return IS_CHERRYVIEW(i915) ? &chv_dpll[0].dpll : &vlv_dpll[0].dpll; + return IS_CHERRYVIEW(i915) ? &chv_dpll[0] : &vlv_dpll[0]; } void g4x_dp_set_clock(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config) { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); - const struct dp_link_dpll *divisor = NULL; + const struct dpll *divisor = NULL; int i, count = 0; if (IS_G4X(dev_priv)) { @@ -94,8 +73,8 @@ void g4x_dp_set_clock(struct intel_encoder *encoder, if (divisor && count) { for (i = 0; i < count; i++) { - if (pipe_config->port_clock == divisor[i].clock) { - pipe_config->dpll = divisor[i].dpll; + if (pipe_config->port_clock == divisor[i].dot) { + pipe_config->dpll = divisor[i]; pipe_config->clock_set = true; break; } From 2953d732745656982bf8b45ae5bdc89041bb7897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Mar 2022 02:47:50 +0200 Subject: [PATCH 00151/11454] drm/i915: Fix up some DRRS type checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only seamless DRRS needs the frontbuffer tracking, so check for that. Also use != consistently instead of randomly picking < as the comparison operator. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220310004802.16310-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_drrs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index fa715b8ea310..146f2cf7d01a 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -152,7 +152,7 @@ static void intel_drrs_set_state(struct drm_i915_private *dev_priv, return; } - if (dev_priv->drrs.type < SEAMLESS_DRRS_SUPPORT) { + if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) { drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n"); return; } @@ -326,7 +326,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, struct drm_crtc *crtc; enum pipe pipe; - if (dev_priv->drrs.type == DRRS_NOT_SUPPORTED) + if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) return; cancel_delayed_work(&dev_priv->drrs.work); From faf6e8fc73aab9db01964753adf112f1d1ac6524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Mar 2022 02:47:51 +0200 Subject: [PATCH 00152/11454] drm/i915: Constify intel_drrs_init() args MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pass the fixed_mode as const to intel_drrs_init() since it's not supposed to mutate the mode. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220310004802.16310-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_drrs.c | 2 +- drivers/gpu/drm/i915/display/intel_drrs.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 146f2cf7d01a..3b871a51eb55 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -421,7 +421,7 @@ void intel_drrs_page_flip(struct intel_atomic_state *state, */ struct drm_display_mode * intel_drrs_init(struct intel_connector *connector, - struct drm_display_mode *fixed_mode) + const struct drm_display_mode *fixed_mode) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_encoder *encoder = connector->encoder; diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index 9ec9c447211a..6bca7692f59f 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -31,6 +31,6 @@ void intel_drrs_compute_config(struct intel_dp *intel_dp, struct intel_crtc_state *pipe_config, int output_bpp, bool constant_n); struct drm_display_mode *intel_drrs_init(struct intel_connector *connector, - struct drm_display_mode *fixed_mode); + const struct drm_display_mode *fixed_mode); #endif /* __INTEL_DRRS_H__ */ From 5f6a9bea163711dd544d6ba93e18bbb847eb8e12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Mar 2022 02:47:52 +0200 Subject: [PATCH 00153/11454] drm/i915: Pimp DRRS debugs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the standard [CONNECTOR:%d:%s] format in the DRRS debugs. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220310004802.16310-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_drrs.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 3b871a51eb55..17bedecbd7b2 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -432,26 +432,32 @@ intel_drrs_init(struct intel_connector *connector, if (DISPLAY_VER(dev_priv) <= 6) { drm_dbg_kms(&dev_priv->drm, - "DRRS supported for Gen7 and above\n"); + "[CONNECTOR:%d:%s] DRRS not supported on platform\n", + connector->base.base.id, connector->base.name); return NULL; } if ((DISPLAY_VER(dev_priv) < 8 && !HAS_GMCH(dev_priv)) && encoder->port != PORT_A) { drm_dbg_kms(&dev_priv->drm, - "DRRS only supported on eDP port A\n"); + "[CONNECTOR:%d:%s] DRRS not supported on [ENCODER:%d:%s]\n", + connector->base.base.id, connector->base.name, + encoder->base.base.id, encoder->base.name); return NULL; } if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) { - drm_dbg_kms(&dev_priv->drm, "VBT doesn't support DRRS\n"); + drm_dbg_kms(&dev_priv->drm, + "[CONNECTOR:%d:%s] DRRS not supported according to VBT\n", + connector->base.base.id, connector->base.name); return NULL; } downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode); if (!downclock_mode) { drm_dbg_kms(&dev_priv->drm, - "Downclock mode is not found. DRRS not supported\n"); + "[CONNECTOR:%d:%s] DRRS not supported due to lack of downclock mode\n", + connector->base.base.id, connector->base.name); return NULL; } @@ -459,6 +465,8 @@ intel_drrs_init(struct intel_connector *connector, dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR; drm_dbg_kms(&dev_priv->drm, - "seamless DRRS supported for eDP panel.\n"); + "[CONNECTOR:%d:%s] seamless DRRS supported\n", + connector->base.base.id, connector->base.name); + return downclock_mode; } From b395c29add3c8b8966789c4642bac164943fc044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Mar 2022 02:47:53 +0200 Subject: [PATCH 00154/11454] drm/i915: Read DRRS MSA timing delay from VBT MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit VBT hsa a field for the MSA timing delay, which supposedly should be used with DRRS. Extract the data from the VBT. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220310004802.16310-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bios.c | 3 +++ drivers/gpu/drm/i915/i915_drv.h | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index a559a1914588..93dc32fb3e40 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -888,6 +888,9 @@ parse_edp(struct drm_i915_private *i915, const struct bdb_header *bdb) i915->vbt.edp.low_vswing = vswing == 0; } } + + i915->vbt.edp.drrs_msa_timing_delay = + (edp->sdrrs_msa_timing_delay >> (panel_type * 2)) & 3; } static void diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 29cc6f7bebf2..6b22d46ccb27 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -356,10 +356,11 @@ struct intel_vbt_data { int lanes; int preemphasis; int vswing; - bool low_vswing; - bool initialized; int bpp; struct edp_power_seq pps; + u8 drrs_msa_timing_delay; + bool low_vswing; + bool initialized; bool hobl; } edp; From 1fa7bb121401325f91e92a966e84af3075b783ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Mar 2022 02:47:54 +0200 Subject: [PATCH 00155/11454] drm/i915: Program MSA timing delay on ilk/snb/ivb MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Grab the DRRS MSA timing delay value from the VBT and program things accordingly. Only ilk/snb/ivb have this so presumably on hsw+ we don't need it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220310004802.16310-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 8 ++++++-- drivers/gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_drrs.c | 3 +++ drivers/gpu/drm/i915/i915_reg.h | 2 ++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 1ce31f79625f..76fa5024b8b5 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -3596,6 +3596,7 @@ static void ilk_set_pipeconf(const struct intel_crtc_state *crtc_state) val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); val |= PIPECONF_FRAME_START_DELAY(crtc_state->framestart_delay - 1); + val |= PIPECONF_MSA_TIMING_DELAY(crtc_state->msa_timing_delay); intel_de_write(dev_priv, PIPECONF(pipe), val); intel_de_posting_read(dev_priv, PIPECONF(pipe)); @@ -3884,6 +3885,8 @@ static bool ilk_get_pipe_config(struct intel_crtc *crtc, pipe_config->framestart_delay = REG_FIELD_GET(PIPECONF_FRAME_START_DELAY_MASK, tmp) + 1; + pipe_config->msa_timing_delay = REG_FIELD_GET(PIPECONF_MSA_TIMING_DELAY_MASK, tmp); + pipe_config->csc_mode = intel_de_read(dev_priv, PIPE_CSC_MODE(crtc->pipe)); @@ -5364,8 +5367,8 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, &pipe_config->dp_m2_n2); } - drm_dbg_kms(&dev_priv->drm, "framestart delay: %d\n", - pipe_config->framestart_delay); + drm_dbg_kms(&dev_priv->drm, "framestart delay: %d, MSA timing delay: %d\n", + pipe_config->framestart_delay, pipe_config->msa_timing_delay); drm_dbg_kms(&dev_priv->drm, "audio: %i, infoframes: %i, infoframes enabled: 0x%x\n", @@ -6264,6 +6267,7 @@ intel_pipe_config_compare(const struct intel_crtc_state *current_config, PIPE_CONF_CHECK_X(output_types); PIPE_CONF_CHECK_I(framestart_delay); + PIPE_CONF_CHECK_I(msa_timing_delay); PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_hdisplay); PIPE_CONF_CHECK_I(hw.pipe_mode.crtc_htotal); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 5e8d7394a394..86b2fa675124 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1155,6 +1155,7 @@ struct intel_crtc_state { u8 update_planes; u8 framestart_delay; /* 1-4 */ + u8 msa_timing_delay; /* 0-3 */ struct { u32 enable; diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 17bedecbd7b2..5b3711fe0674 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -83,6 +83,9 @@ intel_drrs_compute_config(struct intel_dp *intel_dp, return; } + if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) + pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay; + pipe_config->has_drrs = true; pixel_clock = connector->panel.downclock_mode->clock; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 601158bef5d7..92a90a54c3e4 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3702,6 +3702,8 @@ #define PIPECONF_INTERLACE_IF_ID_DBL_ILK REG_FIELD_PREP(PIPECONF_INTERLACE_MASK_ILK, 4) /* ilk/snb only */ #define PIPECONF_INTERLACE_PF_ID_DBL_ILK REG_FIELD_PREP(PIPECONF_INTERLACE_MASK_ILK, 5) /* ilk/snb only */ #define PIPECONF_EDP_RR_MODE_SWITCH REG_BIT(20) +#define PIPECONF_MSA_TIMING_DELAY_MASK REG_GENMASK(19, 18) /* ilk/snb/ivb */ +#define PIPECONF_MSA_TIMING_DELAY(x) REG_FIELD_PREP(PIPECONF_MSA_TIMING_DELAY_MASK, (x)) #define PIPECONF_CXSR_DOWNCLOCK REG_BIT(16) #define PIPECONF_EDP_RR_MODE_SWITCH_VLV REG_BIT(14) #define PIPECONF_COLOR_RANGE_SELECT REG_BIT(13) From 8e9c9848d846167a6f5bff4a0535a898bc465fe1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Mar 2022 02:47:55 +0200 Subject: [PATCH 00156/11454] drm/i915: Polish drrs type enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the drrs type enum less convoluted. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220310004802.16310-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bios.c | 10 +++++----- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 +- drivers/gpu/drm/i915/display/intel_drrs.c | 10 +++++----- drivers/gpu/drm/i915/i915_drv.h | 12 ++++++------ 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index 93dc32fb3e40..c7afe19dd44a 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -257,16 +257,16 @@ parse_panel_options(struct drm_i915_private *i915, */ switch (drrs_mode) { case 0: - i915->vbt.drrs_type = STATIC_DRRS_SUPPORT; + i915->vbt.drrs_type = DRRS_TYPE_STATIC; drm_dbg_kms(&i915->drm, "DRRS supported mode is static\n"); break; case 2: - i915->vbt.drrs_type = SEAMLESS_DRRS_SUPPORT; + i915->vbt.drrs_type = DRRS_TYPE_SEAMLESS; drm_dbg_kms(&i915->drm, "DRRS supported mode is seamless\n"); break; default: - i915->vbt.drrs_type = DRRS_NOT_SUPPORTED; + i915->vbt.drrs_type = DRRS_TYPE_NONE; drm_dbg_kms(&i915->drm, "DRRS not supported (VBT input)\n"); break; @@ -740,7 +740,7 @@ parse_driver_features(struct drm_i915_private *i915, * driver->drrs_enabled=false */ if (!driver->drrs_enabled) - i915->vbt.drrs_type = DRRS_NOT_SUPPORTED; + i915->vbt.drrs_type = DRRS_TYPE_NONE; i915->vbt.psr.enable = driver->psr_enabled; } @@ -769,7 +769,7 @@ parse_power_conservation_features(struct drm_i915_private *i915, * power->drrs & BIT(panel_type)=false */ if (!(power->drrs & BIT(panel_type))) - i915->vbt.drrs_type = DRRS_NOT_SUPPORTED; + i915->vbt.drrs_type = DRRS_TYPE_NONE; if (bdb->version >= 232) i915->vbt.edp.hobl = power->hobl & BIT(panel_type); diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 41b81d5dd5f4..28414472110e 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1163,7 +1163,7 @@ static void drrs_status_per_crtc(struct seq_file *m, seq_printf(m, "%s:\n", connector->name); if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && - drrs->type == SEAMLESS_DRRS_SUPPORT) + drrs->type == DRRS_TYPE_SEAMLESS) supported = true; seq_printf(m, "\tDRRS Supported: %s\n", str_yes_no(supported)); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 5b3711fe0674..7c4a3ecee93a 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -65,7 +65,7 @@ static bool can_enable_drrs(struct intel_connector *connector, return false; return connector->panel.downclock_mode && - i915->drrs.type == SEAMLESS_DRRS_SUPPORT; + i915->drrs.type == DRRS_TYPE_SEAMLESS; } void @@ -155,7 +155,7 @@ static void intel_drrs_set_state(struct drm_i915_private *dev_priv, return; } - if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) { + if (dev_priv->drrs.type != DRRS_TYPE_SEAMLESS) { drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n"); return; } @@ -274,7 +274,7 @@ intel_drrs_update(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) + if (dev_priv->drrs.type != DRRS_TYPE_SEAMLESS) return; mutex_lock(&dev_priv->drrs.mutex); @@ -329,7 +329,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, struct drm_crtc *crtc; enum pipe pipe; - if (dev_priv->drrs.type != SEAMLESS_DRRS_SUPPORT) + if (dev_priv->drrs.type != DRRS_TYPE_SEAMLESS) return; cancel_delayed_work(&dev_priv->drrs.work); @@ -449,7 +449,7 @@ intel_drrs_init(struct intel_connector *connector, return NULL; } - if (dev_priv->vbt.drrs_type != SEAMLESS_DRRS_SUPPORT) { + if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) { drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] DRRS not supported according to VBT\n", connector->base.base.id, connector->base.name); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6b22d46ccb27..ee6bde0cc93d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -207,10 +207,10 @@ enum drrs_refresh_rate_type { DRRS_MAX_RR, /* RR count */ }; -enum drrs_support_type { - DRRS_NOT_SUPPORTED = 0, - STATIC_DRRS_SUPPORT = 1, - SEAMLESS_DRRS_SUPPORT = 2 +enum drrs_type { + DRRS_TYPE_NONE, + DRRS_TYPE_STATIC, + DRRS_TYPE_SEAMLESS, }; struct i915_drrs { @@ -219,7 +219,7 @@ struct i915_drrs { struct intel_dp *dp; unsigned busy_frontbuffer_bits; enum drrs_refresh_rate_type refresh_rate_type; - enum drrs_support_type type; + enum drrs_type type; }; #define QUIRK_LVDS_SSC_DISABLE (1<<1) @@ -349,7 +349,7 @@ struct intel_vbt_data { bool override_afc_startup; u8 override_afc_startup_val; - enum drrs_support_type drrs_type; + enum drrs_type drrs_type; struct { int rate; From 5a220c536b50b90c4577247ce451a6957fbd1aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Mar 2022 02:47:56 +0200 Subject: [PATCH 00157/11454] drm/i915: Clean up DRRS refresh rate enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the DRRS refresh rate enum less magical. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220310004802.16310-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- .../drm/i915/display/intel_display_debugfs.c | 18 ++------ drivers/gpu/drm/i915/display/intel_drrs.c | 44 +++++++++---------- drivers/gpu/drm/i915/i915_drv.h | 14 ++---- 3 files changed, 28 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 28414472110e..798bf233a60f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1149,7 +1149,6 @@ static void drrs_status_per_crtc(struct seq_file *m, { struct drm_i915_private *dev_priv = to_i915(dev); struct i915_drrs *drrs = &dev_priv->drrs; - int vrefresh = 0; struct drm_connector *connector; struct drm_connector_list_iter conn_iter; @@ -1191,21 +1190,12 @@ static void drrs_status_per_crtc(struct seq_file *m, drrs->busy_frontbuffer_bits); seq_puts(m, "\n\t\t"); - if (drrs->refresh_rate_type == DRRS_HIGH_RR) { - seq_puts(m, "DRRS_State: DRRS_HIGH_RR\n"); - vrefresh = drm_mode_vrefresh(panel->fixed_mode); - } else if (drrs->refresh_rate_type == DRRS_LOW_RR) { - seq_puts(m, "DRRS_State: DRRS_LOW_RR\n"); - vrefresh = drm_mode_vrefresh(panel->downclock_mode); - } else { - seq_printf(m, "DRRS_State: Unknown(%d)\n", - drrs->refresh_rate_type); - mutex_unlock(&drrs->mutex); - return; - } - seq_printf(m, "\t\tVrefresh: %d", vrefresh); + seq_printf(m, "DRRS refresh rate: %s\n", + drrs->refresh_rate == DRRS_REFRESH_RATE_LOW ? + "low" : "high"); seq_puts(m, "\n\t\t"); + mutex_unlock(&drrs->mutex); } else { /* DRRS not supported. Print the VBT parameter*/ diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 7c4a3ecee93a..3979ceaaf651 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -103,7 +103,7 @@ intel_drrs_compute_config(struct intel_dp *intel_dp, static void intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state, - enum drrs_refresh_rate_type refresh_type) + enum drrs_refresh_rate refresh_rate) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -117,7 +117,7 @@ intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state, val = intel_de_read(dev_priv, PIPECONF(cpu_transcoder)); - if (refresh_type == DRRS_LOW_RR) + if (refresh_rate == DRRS_REFRESH_RATE_LOW) val |= bit; else val &= ~bit; @@ -127,22 +127,21 @@ intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state, static void intel_drrs_set_refresh_rate_m_n(const struct intel_crtc_state *crtc_state, - enum drrs_refresh_rate_type refresh_type) + enum drrs_refresh_rate refresh_rate) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); intel_cpu_transcoder_set_m1_n1(crtc, crtc_state->cpu_transcoder, - refresh_type == DRRS_LOW_RR ? + refresh_rate == DRRS_REFRESH_RATE_LOW ? &crtc_state->dp_m2_n2 : &crtc_state->dp_m_n); } static void intel_drrs_set_state(struct drm_i915_private *dev_priv, const struct intel_crtc_state *crtc_state, - enum drrs_refresh_rate_type refresh_type) + enum drrs_refresh_rate refresh_rate) { struct intel_dp *intel_dp = dev_priv->drrs.dp; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_display_mode *mode; if (!intel_dp) { drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n"); @@ -160,7 +159,7 @@ static void intel_drrs_set_state(struct drm_i915_private *dev_priv, return; } - if (refresh_type == dev_priv->drrs.refresh_rate_type) + if (refresh_rate == dev_priv->drrs.refresh_rate) return; if (!crtc_state->hw.active) { @@ -170,18 +169,14 @@ static void intel_drrs_set_state(struct drm_i915_private *dev_priv, } if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) - intel_drrs_set_refresh_rate_m_n(crtc_state, refresh_type); + intel_drrs_set_refresh_rate_m_n(crtc_state, refresh_rate); else if (DISPLAY_VER(dev_priv) > 6) - intel_drrs_set_refresh_rate_pipeconf(crtc_state, refresh_type); + intel_drrs_set_refresh_rate_pipeconf(crtc_state, refresh_rate); - dev_priv->drrs.refresh_rate_type = refresh_type; + dev_priv->drrs.refresh_rate = refresh_rate; - if (refresh_type == DRRS_LOW_RR) - mode = intel_dp->attached_connector->panel.downclock_mode; - else - mode = intel_dp->attached_connector->panel.fixed_mode; - drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %dHz\n", - drm_mode_vrefresh(mode)); + drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %s\n", + refresh_rate == DRRS_REFRESH_RATE_LOW ? "low" : "high"); } static void @@ -229,7 +224,7 @@ intel_drrs_disable_locked(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - intel_drrs_set_state(dev_priv, crtc_state, DRRS_HIGH_RR); + intel_drrs_set_state(dev_priv, crtc_state, DRRS_REFRESH_RATE_HIGH); dev_priv->drrs.dp = NULL; } @@ -297,7 +292,6 @@ static void intel_drrs_downclock_work(struct work_struct *work) struct drm_i915_private *dev_priv = container_of(work, typeof(*dev_priv), drrs.work.work); struct intel_dp *intel_dp; - struct drm_crtc *crtc; mutex_lock(&dev_priv->drrs.mutex); @@ -311,11 +305,13 @@ static void intel_drrs_downclock_work(struct work_struct *work) * recheck. */ - if (dev_priv->drrs.busy_frontbuffer_bits) - goto unlock; + if (!dev_priv->drrs.busy_frontbuffer_bits) { + struct intel_crtc *crtc = + to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); - crtc = dp_to_dig_port(intel_dp)->base.base.crtc; - intel_drrs_set_state(dev_priv, to_intel_crtc(crtc)->config, DRRS_LOW_RR); + intel_drrs_set_state(dev_priv, crtc->config, + DRRS_REFRESH_RATE_LOW); + } unlock: mutex_unlock(&dev_priv->drrs.mutex); @@ -354,7 +350,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, /* flush/invalidate means busy screen hence upclock */ if (frontbuffer_bits) intel_drrs_set_state(dev_priv, to_intel_crtc(crtc)->config, - DRRS_HIGH_RR); + DRRS_REFRESH_RATE_HIGH); /* * flush also means no more activity hence schedule downclock, if all @@ -466,7 +462,7 @@ intel_drrs_init(struct intel_connector *connector, dev_priv->drrs.type = dev_priv->vbt.drrs_type; - dev_priv->drrs.refresh_rate_type = DRRS_HIGH_RR; + dev_priv->drrs.refresh_rate = DRRS_REFRESH_RATE_HIGH; drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] seamless DRRS supported\n", connector->base.base.id, connector->base.name); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ee6bde0cc93d..bd9bff25c54a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -196,15 +196,9 @@ struct drm_i915_display_funcs { #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ -/* - * HIGH_RR is the highest eDP panel refresh rate read from EDID - * LOW_RR is the lowest eDP panel refresh rate found from EDID - * parsing for same resolution. - */ -enum drrs_refresh_rate_type { - DRRS_HIGH_RR, - DRRS_LOW_RR, - DRRS_MAX_RR, /* RR count */ +enum drrs_refresh_rate { + DRRS_REFRESH_RATE_HIGH, + DRRS_REFRESH_RATE_LOW, }; enum drrs_type { @@ -218,7 +212,7 @@ struct i915_drrs { struct delayed_work work; struct intel_dp *dp; unsigned busy_frontbuffer_bits; - enum drrs_refresh_rate_type refresh_rate_type; + enum drrs_refresh_rate refresh_rate; enum drrs_type type; }; From dd7ae6b3e857f230a804ce8706700891e526cc64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 10 Mar 2022 02:47:57 +0200 Subject: [PATCH 00158/11454] drm/i915: Rename PIPECONF refresh select bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the PIPECONF refresh rate select bits to be less cryptic. Also nothing eDP specific about these as they also select between FP0 vs. FP1 for the DPLL and thus can be used to change the refresh rate on other output types as well. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220310004802.16310-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_drrs.c | 4 ++-- drivers/gpu/drm/i915/i915_reg.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 3979ceaaf651..c97b5dee8cae 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -111,9 +111,9 @@ intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state, u32 val, bit; if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - bit = PIPECONF_EDP_RR_MODE_SWITCH_VLV; + bit = PIPECONF_REFRESH_RATE_ALT_VLV; else - bit = PIPECONF_EDP_RR_MODE_SWITCH; + bit = PIPECONF_REFRESH_RATE_ALT_ILK; val = intel_de_read(dev_priv, PIPECONF(cpu_transcoder)); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 92a90a54c3e4..56042d363a15 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3701,11 +3701,11 @@ #define PIPECONF_INTERLACE_IF_ID_ILK REG_FIELD_PREP(PIPECONF_INTERLACE_MASK_ILK, 3) #define PIPECONF_INTERLACE_IF_ID_DBL_ILK REG_FIELD_PREP(PIPECONF_INTERLACE_MASK_ILK, 4) /* ilk/snb only */ #define PIPECONF_INTERLACE_PF_ID_DBL_ILK REG_FIELD_PREP(PIPECONF_INTERLACE_MASK_ILK, 5) /* ilk/snb only */ -#define PIPECONF_EDP_RR_MODE_SWITCH REG_BIT(20) +#define PIPECONF_REFRESH_RATE_ALT_ILK REG_BIT(20) #define PIPECONF_MSA_TIMING_DELAY_MASK REG_GENMASK(19, 18) /* ilk/snb/ivb */ #define PIPECONF_MSA_TIMING_DELAY(x) REG_FIELD_PREP(PIPECONF_MSA_TIMING_DELAY_MASK, (x)) #define PIPECONF_CXSR_DOWNCLOCK REG_BIT(16) -#define PIPECONF_EDP_RR_MODE_SWITCH_VLV REG_BIT(14) +#define PIPECONF_REFRESH_RATE_ALT_VLV REG_BIT(14) #define PIPECONF_COLOR_RANGE_SELECT REG_BIT(13) #define PIPECONF_OUTPUT_COLORSPACE_MASK REG_GENMASK(12, 11) /* ilk-ivb */ #define PIPECONF_OUTPUT_COLORSPACE_RGB REG_FIELD_PREP(PIPECONF_OUTPUT_COLORSPACE_MASK, 0) /* ilk-ivb */ From 661412e301e2ca86799aa4f400d1cf0bd38c57c6 Mon Sep 17 00:00:00 2001 From: Mastan Katragadda Date: Thu, 3 Mar 2022 11:34:28 +0530 Subject: [PATCH 00159/11454] drm/i915/gem: add missing boundary check in vm_access A missing bounds check in vm_access() can lead to an out-of-bounds read or write in the adjacent memory area, since the len attribute is not validated before the memcpy later in the function, potentially hitting: [ 183.637831] BUG: unable to handle page fault for address: ffffc90000c86000 [ 183.637934] #PF: supervisor read access in kernel mode [ 183.637997] #PF: error_code(0x0000) - not-present page [ 183.638059] PGD 100000067 P4D 100000067 PUD 100258067 PMD 106341067 PTE 0 [ 183.638144] Oops: 0000 [#2] PREEMPT SMP NOPTI [ 183.638201] CPU: 3 PID: 1790 Comm: poc Tainted: G D 5.17.0-rc6-ci-drm-11296+ #1 [ 183.638298] Hardware name: Intel Corporation CoffeeLake Client Platform/CoffeeLake H DDR4 RVP, BIOS CNLSFWR1.R00.X208.B00.1905301319 05/30/2019 [ 183.638430] RIP: 0010:memcpy_erms+0x6/0x10 [ 183.640213] RSP: 0018:ffffc90001763d48 EFLAGS: 00010246 [ 183.641117] RAX: ffff888109c14000 RBX: ffff888111bece40 RCX: 0000000000000ffc [ 183.642029] RDX: 0000000000001000 RSI: ffffc90000c86000 RDI: ffff888109c14004 [ 183.642946] RBP: 0000000000000ffc R08: 800000000000016b R09: 0000000000000000 [ 183.643848] R10: ffffc90000c85000 R11: 0000000000000048 R12: 0000000000001000 [ 183.644742] R13: ffff888111bed190 R14: ffff888109c14000 R15: 0000000000001000 [ 183.645653] FS: 00007fe5ef807540(0000) GS:ffff88845b380000(0000) knlGS:0000000000000000 [ 183.646570] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 183.647481] CR2: ffffc90000c86000 CR3: 000000010ff02006 CR4: 00000000003706e0 [ 183.648384] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 [ 183.649271] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 [ 183.650142] Call Trace: [ 183.650988] [ 183.651793] vm_access+0x1f0/0x2a0 [i915] [ 183.652726] __access_remote_vm+0x224/0x380 [ 183.653561] mem_rw.isra.0+0xf9/0x190 [ 183.654402] vfs_read+0x9d/0x1b0 [ 183.655238] ksys_read+0x63/0xe0 [ 183.656065] do_syscall_64+0x38/0xc0 [ 183.656882] entry_SYSCALL_64_after_hwframe+0x44/0xae [ 183.657663] RIP: 0033:0x7fe5ef725142 [ 183.659351] RSP: 002b:00007ffe1e81c7e8 EFLAGS: 00000246 ORIG_RAX: 0000000000000000 [ 183.660227] RAX: ffffffffffffffda RBX: 0000557055dfb780 RCX: 00007fe5ef725142 [ 183.661104] RDX: 0000000000001000 RSI: 00007ffe1e81d880 RDI: 0000000000000005 [ 183.661972] RBP: 00007ffe1e81e890 R08: 0000000000000030 R09: 0000000000000046 [ 183.662832] R10: 0000557055dfc2e0 R11: 0000000000000246 R12: 0000557055dfb1c0 [ 183.663691] R13: 00007ffe1e81e980 R14: 0000000000000000 R15: 0000000000000000 Changes since v1: - Updated if condition with range_overflows_t [Chris Wilson] Fixes: 9f909e215fea ("drm/i915: Implement vm_ops->access for gdb access into mmaps") Signed-off-by: Mastan Katragadda Suggested-by: Adam Zabrocki Reported-by: Jackson Cody Cc: Chris Wilson Cc: Jon Bloomfield Cc: Sudeep Dutt Cc: # v5.8+ Reviewed-by: Matthew Auld [mauld: tidy up the commit message and add Cc: stable] Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220303060428.1668844-1-mastanx.katragadda@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_mman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_mman.c b/drivers/gpu/drm/i915/gem/i915_gem_mman.c index efe69d6b86f4..c3ea243d414d 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_mman.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_mman.c @@ -455,7 +455,7 @@ vm_access(struct vm_area_struct *area, unsigned long addr, return -EACCES; addr -= area->vm_start; - if (addr >= obj->base.size) + if (range_overflows_t(u64, addr, len, obj->base.size)) return -EINVAL; i915_gem_ww_ctx_init(&ww, true); From 239bbb2fe927ed762bfe6307ba6a2e2d94e739da Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Thu, 10 Mar 2022 22:28:35 -0800 Subject: [PATCH 00160/11454] drm/i915/gt: Remove GEN12_SFC_DONE_MAX from register defs header We shouldn't really be keeping track of how many SFC_DONE registers our platforms can have, but rather how many SFC hardware units there can be (each SFC unit will have one corresponding SFC_DONE register). So drop the stray GEN12_SFC_DONE_MAX definition we had in the register definition file and replace it with an I915_MAX_SFC that follows the pattern we use for other hardware units. Note that our hardware has a 2:1:1 ratio of VD:VE:SFC, and as far as we know that pattern should carry forward to future platforms, so we'll define it as #VCS/2. Cc: Jani Nikula Signed-off-by: Matt Roper Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20220311062835.163744-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/intel_engine_types.h | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 4 ++-- drivers/gpu/drm/i915/i915_gpu_error.h | 2 +- drivers/gpu/drm/i915/i915_reg_defs.h | 2 -- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 4fbf45a74ec0..85c00025a2ff 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -96,6 +96,7 @@ struct i915_ctx_workarounds { #define I915_MAX_VCS 8 #define I915_MAX_VECS 4 +#define I915_MAX_SFC (I915_MAX_VCS / 2) #define I915_MAX_CCS 4 #define I915_MAX_RCS 1 diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 1d042551619e..4725d67343a5 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -752,7 +752,7 @@ static void err_print_gt(struct drm_i915_error_state_buf *m, if (GRAPHICS_VER(m->i915) >= 12) { int i; - for (i = 0; i < GEN12_SFC_DONE_MAX; i++) { + for (i = 0; i < I915_MAX_SFC; i++) { /* * SFC_DONE resides in the VD forcewake domain, so it * only exists if the corresponding VCS engine is @@ -1689,7 +1689,7 @@ static void gt_record_regs(struct intel_gt_coredump *gt) gt->aux_err = intel_uncore_read(uncore, GEN12_AUX_ERR_DBG); if (GRAPHICS_VER(i915) >= 12) { - for (i = 0; i < GEN12_SFC_DONE_MAX; i++) { + for (i = 0; i < I915_MAX_SFC; i++) { /* * SFC_DONE resides in the VD forcewake domain, so it * only exists if the corresponding VCS engine is diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index 903d838e2e63..c3ccc8266865 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -137,7 +137,7 @@ struct intel_gt_coredump { u32 gfx_mode; u32 gtt_cache; u32 aux_err; /* gen12 */ - u32 sfc_done[GEN12_SFC_DONE_MAX]; /* gen12 */ + u32 sfc_done[I915_MAX_SFC]; /* gen12 */ u32 gam_done; /* gen12 */ u32 nfence; diff --git a/drivers/gpu/drm/i915/i915_reg_defs.h b/drivers/gpu/drm/i915/i915_reg_defs.h index d78d78fce431..8f486f77609f 100644 --- a/drivers/gpu/drm/i915/i915_reg_defs.h +++ b/drivers/gpu/drm/i915/i915_reg_defs.h @@ -123,6 +123,4 @@ static inline bool i915_mmio_reg_valid(i915_reg_t reg) #define VLV_DISPLAY_BASE 0x180000 -#define GEN12_SFC_DONE_MAX 4 - #endif /* __I915_REG_DEFS__ */ From 485d98d472d53f9617ffdfba5e677ac29ad4fe20 Mon Sep 17 00:00:00 2001 From: Martin Krastev Date: Wed, 2 Mar 2022 10:24:19 -0500 Subject: [PATCH 00161/11454] drm/vmwgfx: Add support for CursorMob and CursorBypass 4 * Add support for CursorMob * Add support for CursorBypass 4 * Refactor vmw_du_cursor_plane_atomic_update to be kms-helper-atomic -- move BO mappings to vmw_du_cursor_plane_prepare_fb -- move BO unmappings to vmw_du_cursor_plane_cleanup_fb Cursor mobs are a new svga feature which enables support for large cursors, e.g. large accessibility cursor on platforms with vmwgfx. It also cleans up the cursor code and makes it more uniform with the rest of modern guest backed objects support. Signed-off-by: Martin Krastev Reviewed-by: Zack Rusin Reviewed-by: Maaz Mombasawala Signed-off-by: Zack Rusin Link: https://patchwork.freedesktop.org/patch/msgid/20220302152426.885214-2-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 6 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 399 ++++++++++++++++++++++----- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 28 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 18 +- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 17 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 16 +- 7 files changed, 382 insertions(+), 104 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 26eb5478394a..621231c66fd4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2009-2016 VMware, Inc., Palo Alto, CA., USA + * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index ea3ecdda561d..780da6147cf9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR MIT */ /************************************************************************** * - * Copyright 2009-2021 VMware, Inc., Palo Alto, CA., USA + * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -101,6 +101,7 @@ struct vmw_fpriv { * struct vmw_buffer_object - TTM buffer object with vmwgfx additions * @base: The TTM buffer object * @res_tree: RB tree of resources using this buffer object as a backing MOB + * @base_mapped_count: ttm BO mapping count; used by KMS atomic helpers. * @cpu_writers: Number of synccpu write grabs. Protected by reservation when * increased. May be decreased without reservation. * @dx_query_ctx: DX context if this buffer object is used as a DX query MOB @@ -111,6 +112,9 @@ struct vmw_fpriv { struct vmw_buffer_object { struct ttm_buffer_object base; struct rb_root res_tree; + /* For KMS atomic helpers: ttm bo mapping count */ + atomic_t base_mapped_count; + atomic_t cpu_writers; /* Not ref-counted. Protected by binding_mutex */ struct vmw_resource *dx_query_ctx; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index bbd2f4ec08ec..9d82a7b49aed 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA + * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -41,7 +41,7 @@ void vmw_du_cleanup(struct vmw_display_unit *du) struct vmw_private *dev_priv = vmw_priv(du->primary.dev); drm_plane_cleanup(&du->primary); if (vmw_cmd_supported(dev_priv)) - drm_plane_cleanup(&du->cursor); + drm_plane_cleanup(&du->cursor.base); drm_connector_unregister(&du->connector); drm_crtc_cleanup(&du->crtc); @@ -53,23 +53,43 @@ void vmw_du_cleanup(struct vmw_display_unit *du) * Display Unit Cursor functions */ -static int vmw_cursor_update_image(struct vmw_private *dev_priv, - u32 *image, u32 width, u32 height, - u32 hotspotX, u32 hotspotY) +static void vmw_cursor_update_mob(struct vmw_private *dev_priv, + struct ttm_buffer_object *bo, + struct ttm_bo_kmap_obj *map, + u32 *image, u32 width, u32 height, + u32 hotspotX, u32 hotspotY); + +struct vmw_svga_fifo_cmd_define_cursor { + u32 cmd; + SVGAFifoCmdDefineAlphaCursor cursor; +}; + +static void vmw_cursor_update_image(struct vmw_private *dev_priv, + struct ttm_buffer_object *cm_bo, + struct ttm_bo_kmap_obj *cm_map, + u32 *image, u32 width, u32 height, + u32 hotspotX, u32 hotspotY) { - struct { - u32 cmd; - SVGAFifoCmdDefineAlphaCursor cursor; - } *cmd; - u32 image_size = width * height * 4; - u32 cmd_size = sizeof(*cmd) + image_size; + struct vmw_svga_fifo_cmd_define_cursor *cmd; + const u32 image_size = width * height * sizeof(*image); + const u32 cmd_size = sizeof(*cmd) + image_size; - if (!image) - return -EINVAL; + if (cm_bo != NULL) { + vmw_cursor_update_mob(dev_priv, cm_bo, cm_map, image, + width, height, + hotspotX, hotspotY); + return; + } + /* Try to reserve fifocmd space and swallow any failures; + such reservations cannot be left unconsumed for long + under the risk of clogging other fifocmd users, so + we treat reservations separtely from the way we treat + other fallible KMS-atomic resources at prepare_fb */ cmd = VMW_CMD_RESERVE(dev_priv, cmd_size); + if (unlikely(cmd == NULL)) - return -ENOMEM; + return; memset(cmd, 0, sizeof(*cmd)); @@ -83,55 +103,158 @@ static int vmw_cursor_update_image(struct vmw_private *dev_priv, cmd->cursor.hotspotY = hotspotY; vmw_cmd_commit_flush(dev_priv, cmd_size); - - return 0; } -static int vmw_cursor_update_bo(struct vmw_private *dev_priv, - struct vmw_buffer_object *bo, - u32 width, u32 height, - u32 hotspotX, u32 hotspotY) +/** + * vmw_cursor_update_mob - Update cursor vis CursorMob mechanism + * + * @dev_priv: device to work with + * @bo: BO for the MOB + * @map: kmap obj for the BO + * @image: cursor source data to fill the MOB with + * @width: source data width + * @height: source data height + * @hotspotX: cursor hotspot x + * @hotspotY: cursor hotspot Y + */ +static void vmw_cursor_update_mob(struct vmw_private *dev_priv, + struct ttm_buffer_object *bo, + struct ttm_bo_kmap_obj *map, + u32 *image, u32 width, u32 height, + u32 hotspotX, u32 hotspotY) { - struct ttm_bo_kmap_obj map; - unsigned long kmap_offset; - unsigned long kmap_num; - void *virtual; + SVGAGBCursorHeader *header; + SVGAGBAlphaCursorHeader *alpha_header; + const u32 image_size = width * height * sizeof(*image); bool dummy; - int ret; - kmap_offset = 0; - kmap_num = PFN_UP(width*height*4); + BUG_ON(!image); - ret = ttm_bo_reserve(&bo->base, true, false, NULL); - if (unlikely(ret != 0)) { - DRM_ERROR("reserve failed\n"); - return -EINVAL; + header = (SVGAGBCursorHeader *)ttm_kmap_obj_virtual(map, &dummy); + alpha_header = &header->header.alphaHeader; + + header->type = SVGA_ALPHA_CURSOR; + header->sizeInBytes = image_size; + + alpha_header->hotspotX = hotspotX; + alpha_header->hotspotY = hotspotY; + alpha_header->width = width; + alpha_header->height = height; + + memcpy(header + 1, image, image_size); + + vmw_write(dev_priv, SVGA_REG_CURSOR_MOBID, bo->resource->start); +} + +void vmw_du_destroy_cursor_mob_array(struct vmw_cursor_plane *vcp) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(vcp->cursor_mob); i++) { + if (vcp->cursor_mob[i] != NULL) { + ttm_bo_unpin(vcp->cursor_mob[i]); + ttm_bo_put(vcp->cursor_mob[i]); + kfree(vcp->cursor_mob[i]); + vcp->cursor_mob[i] = NULL; + } + } +} + +#define CURSOR_MOB_SIZE(dimension) \ + ((dimension) * (dimension) * sizeof(u32) + sizeof(SVGAGBCursorHeader)) + +int vmw_du_create_cursor_mob_array(struct vmw_cursor_plane *cursor) +{ + struct vmw_private *dev_priv = cursor->base.dev->dev_private; + uint32_t cursor_max_dim, mob_max_size; + int ret = 0; + size_t i; + + if (!dev_priv->has_mob || (dev_priv->capabilities2 & SVGA_CAP2_CURSOR_MOB) == 0) + return -ENOSYS; + + mob_max_size = vmw_read(dev_priv, SVGA_REG_MOB_MAX_SIZE); + cursor_max_dim = vmw_read(dev_priv, SVGA_REG_CURSOR_MAX_DIMENSION); + + if (CURSOR_MOB_SIZE(cursor_max_dim) > mob_max_size) + cursor_max_dim = 64; /* Mandatorily-supported cursor dimension */ + + for (i = 0; i < ARRAY_SIZE(cursor->cursor_mob); i++) { + struct ttm_buffer_object **const bo = &cursor->cursor_mob[i]; + + ret = vmw_bo_create_kernel(dev_priv, + CURSOR_MOB_SIZE(cursor_max_dim), + &vmw_mob_placement, bo); + + if (ret != 0) + goto teardown; + + if ((*bo)->resource->mem_type != VMW_PL_MOB) { + DRM_ERROR("Obtained buffer object is not a MOB.\n"); + ret = -ENOSYS; + goto teardown; + } + + /* Fence the mob creation so we are guarateed to have the mob */ + ret = ttm_bo_reserve(*bo, false, false, NULL); + + if (ret != 0) + goto teardown; + + vmw_bo_fence_single(*bo, NULL); + + ttm_bo_unreserve(*bo); + + drm_info(&dev_priv->drm, "Using CursorMob mobid %lu, max dimension %u\n", + (*bo)->resource->start, cursor_max_dim); } - ret = ttm_bo_kmap(&bo->base, kmap_offset, kmap_num, &map); - if (unlikely(ret != 0)) - goto err_unreserve; + return 0; - virtual = ttm_kmap_obj_virtual(&map, &dummy); - ret = vmw_cursor_update_image(dev_priv, virtual, width, height, - hotspotX, hotspotY); - - ttm_bo_kunmap(&map); -err_unreserve: - ttm_bo_unreserve(&bo->base); +teardown: + vmw_du_destroy_cursor_mob_array(cursor); return ret; } +#undef CURSOR_MOB_SIZE + +static void vmw_cursor_update_bo(struct vmw_private *dev_priv, + struct ttm_buffer_object *cm_bo, + struct ttm_bo_kmap_obj *cm_map, + struct vmw_buffer_object *bo, + u32 width, u32 height, + u32 hotspotX, u32 hotspotY) +{ + void *virtual; + bool dummy; + + virtual = ttm_kmap_obj_virtual(&bo->map, &dummy); + if (virtual) { + vmw_cursor_update_image(dev_priv, cm_bo, cm_map, virtual, + width, height, + hotspotX, hotspotY); + atomic_dec(&bo->base_mapped_count); + } +} + static void vmw_cursor_update_position(struct vmw_private *dev_priv, bool show, int x, int y) { + const uint32_t svga_cursor_on = show ? SVGA_CURSOR_ON_SHOW + : SVGA_CURSOR_ON_HIDE; uint32_t count; spin_lock(&dev_priv->cursor_lock); - if (vmw_is_cursor_bypass3_enabled(dev_priv)) { - vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_ON, show ? 1 : 0); + if (dev_priv->capabilities2 & SVGA_CAP2_EXTRA_REGS) { + vmw_write(dev_priv, SVGA_REG_CURSOR4_X, x); + vmw_write(dev_priv, SVGA_REG_CURSOR4_Y, y); + vmw_write(dev_priv, SVGA_REG_CURSOR4_SCREEN_ID, SVGA3D_INVALID_ID); + vmw_write(dev_priv, SVGA_REG_CURSOR4_ON, svga_cursor_on); + vmw_write(dev_priv, SVGA_REG_CURSOR4_SUBMIT, TRUE); + } else if (vmw_is_cursor_bypass3_enabled(dev_priv)) { + vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_ON, svga_cursor_on); vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_X, x); vmw_fifo_mem_write(dev_priv, SVGA_FIFO_CURSOR_Y, y); count = vmw_fifo_mem_read(dev_priv, SVGA_FIFO_CURSOR_COUNT); @@ -139,7 +262,7 @@ static void vmw_cursor_update_position(struct vmw_private *dev_priv, } else { vmw_write(dev_priv, SVGA_REG_CURSOR_X, x); vmw_write(dev_priv, SVGA_REG_CURSOR_Y, y); - vmw_write(dev_priv, SVGA_REG_CURSOR_ON, show ? 1 : 0); + vmw_write(dev_priv, SVGA_REG_CURSOR_ON, svga_cursor_on); } spin_unlock(&dev_priv->cursor_lock); } @@ -269,7 +392,7 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv) continue; du->cursor_age = du->cursor_surface->snooper.age; - vmw_cursor_update_image(dev_priv, + vmw_cursor_update_image(dev_priv, NULL, NULL, du->cursor_surface->snooper.image, 64, 64, du->hotspot_x + du->core_hotspot_x, @@ -283,7 +406,7 @@ void vmw_kms_cursor_post_execbuf(struct vmw_private *dev_priv) void vmw_du_cursor_plane_destroy(struct drm_plane *plane) { vmw_cursor_update_position(plane->dev->dev_private, false, 0, 0); - + vmw_du_destroy_cursor_mob_array(vmw_plane_to_vcp(plane)); drm_plane_cleanup(plane); } @@ -321,7 +444,7 @@ void vmw_du_plane_unpin_surf(struct vmw_plane_state *vps, /** - * vmw_du_plane_cleanup_fb - Unpins the cursor + * vmw_du_plane_cleanup_fb - Unpins the plane surface * * @plane: display plane * @old_state: Contains the FB to clean up @@ -340,6 +463,55 @@ vmw_du_plane_cleanup_fb(struct drm_plane *plane, } +/** + * vmw_du_cursor_plane_cleanup_fb - Unpins the plane surface + * + * @plane: cursor plane + * @old_state: contains the state to clean up + * + * Unmaps all cursor bo mappings and unpins the cursor surface + * + * Returns 0 on success + */ +void +vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state) +{ + struct vmw_plane_state *vps = vmw_plane_state_to_vps(old_state); + bool dummy; + + if (vps->bo != NULL && ttm_kmap_obj_virtual(&vps->bo->map, &dummy) != NULL) { + const int ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL); + + if (likely(ret == 0)) { + if (atomic_read(&vps->bo->base_mapped_count) == 0) + ttm_bo_kunmap(&vps->bo->map); + ttm_bo_unreserve(&vps->bo->base); + } + } + + if (vps->cm_bo != NULL && ttm_kmap_obj_virtual(&vps->cm_map, &dummy) != NULL) { + const int ret = ttm_bo_reserve(vps->cm_bo, true, false, NULL); + + if (likely(ret == 0)) { + ttm_bo_kunmap(&vps->cm_map); + ttm_bo_unreserve(vps->cm_bo); + } + } + + vmw_du_plane_unpin_surf(vps, false); + + if (vps->surf) { + vmw_surface_unreference(&vps->surf); + vps->surf = NULL; + } + + if (vps->bo) { + vmw_bo_unreference(&vps->bo); + vps->bo = NULL; + } +} + /** * vmw_du_cursor_plane_prepare_fb - Readies the cursor by referencing it * @@ -353,14 +525,21 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state) { struct drm_framebuffer *fb = new_state->fb; + struct vmw_cursor_plane *vcp = vmw_plane_to_vcp(plane); struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); + struct ttm_buffer_object *cm_bo = NULL; + bool dummy; + int ret = 0; - - if (vps->surf) + if (vps->surf) { vmw_surface_unreference(&vps->surf); + vps->surf = NULL; + } - if (vps->bo) + if (vps->bo) { vmw_bo_unreference(&vps->bo); + vps->bo = NULL; + } if (fb) { if (vmw_framebuffer_to_vfb(fb)->bo) { @@ -372,7 +551,82 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, } } + vps->cm_bo = NULL; + + if (vps->surf == NULL && vps->bo != NULL) { + const u32 size = new_state->crtc_w * new_state->crtc_h * sizeof(u32); + + /* Not using vmw_bo_map_and_cache() helper here as we need to reserve + the ttm_buffer_object first which wmw_bo_map_and_cache() omits. */ + ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL); + + if (unlikely(ret != 0)) + return -ENOMEM; + + ret = ttm_bo_kmap(&vps->bo->base, 0, PFN_UP(size), &vps->bo->map); + + if (likely(ret == 0)) + atomic_inc(&vps->bo->base_mapped_count); + + ttm_bo_unreserve(&vps->bo->base); + + if (unlikely(ret != 0)) + return -ENOMEM; + } + + if (vps->surf || vps->bo) { + unsigned cursor_mob_idx = vps->cursor_mob_idx; + + /* Lazily set up cursor MOBs just once -- no reattempts. */ + if (cursor_mob_idx == 0 && vcp->cursor_mob[0] == NULL) + if (vmw_du_create_cursor_mob_array(vcp) != 0) + vps->cursor_mob_idx = cursor_mob_idx = -1U; + + if (cursor_mob_idx < ARRAY_SIZE(vcp->cursor_mob)) { + const u32 size = sizeof(SVGAGBCursorHeader) + + new_state->crtc_w * new_state->crtc_h * sizeof(u32); + + cm_bo = vcp->cursor_mob[cursor_mob_idx]; + + if (cm_bo->resource->num_pages * PAGE_SIZE < size) { + ret = -EINVAL; + goto error_bo_unmap; + } + + ret = ttm_bo_reserve(cm_bo, false, false, NULL); + + if (unlikely(ret != 0)) { + ret = -ENOMEM; + goto error_bo_unmap; + } + + ret = ttm_bo_kmap(cm_bo, 0, PFN_UP(size), &vps->cm_map); + + ttm_bo_unreserve(cm_bo); + + if (unlikely(ret != 0)) { + ret = -ENOMEM; + goto error_bo_unmap; + } + + vps->cursor_mob_idx = cursor_mob_idx ^ 1; + vps->cm_bo = cm_bo; + } + } + return 0; + +error_bo_unmap: + if (vps->bo != NULL && ttm_kmap_obj_virtual(&vps->bo->map, &dummy) != NULL) { + const int ret = ttm_bo_reserve(&vps->bo->base, true, false, NULL); + if (likely(ret == 0)) { + atomic_dec(&vps->bo->base_mapped_count); + ttm_bo_kunmap(&vps->bo->map); + ttm_bo_unreserve(&vps->bo->base); + } + } + + return ret; } @@ -389,8 +643,6 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, struct vmw_display_unit *du = vmw_crtc_to_du(crtc); struct vmw_plane_state *vps = vmw_plane_state_to_vps(new_state); s32 hotspot_x, hotspot_y; - int ret = 0; - hotspot_x = du->hotspot_x; hotspot_y = du->hotspot_y; @@ -406,33 +658,31 @@ vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, if (vps->surf) { du->cursor_age = du->cursor_surface->snooper.age; - ret = vmw_cursor_update_image(dev_priv, - vps->surf->snooper.image, - 64, 64, hotspot_x, - hotspot_y); + vmw_cursor_update_image(dev_priv, vps->cm_bo, &vps->cm_map, + vps->surf->snooper.image, + new_state->crtc_w, + new_state->crtc_h, + hotspot_x, hotspot_y); } else if (vps->bo) { - ret = vmw_cursor_update_bo(dev_priv, vps->bo, - new_state->crtc_w, - new_state->crtc_h, - hotspot_x, hotspot_y); + vmw_cursor_update_bo(dev_priv, vps->cm_bo, &vps->cm_map, + vps->bo, + new_state->crtc_w, + new_state->crtc_h, + hotspot_x, hotspot_y); } else { vmw_cursor_update_position(dev_priv, false, 0, 0); return; } - if (!ret) { - du->cursor_x = new_state->crtc_x + du->set_gui_x; - du->cursor_y = new_state->crtc_y + du->set_gui_y; + du->cursor_x = new_state->crtc_x + du->set_gui_x; + du->cursor_y = new_state->crtc_y + du->set_gui_y; - vmw_cursor_update_position(dev_priv, true, - du->cursor_x + hotspot_x, - du->cursor_y + hotspot_y); + vmw_cursor_update_position(dev_priv, true, + du->cursor_x + hotspot_x, + du->cursor_y + hotspot_y); - du->core_hotspot_x = hotspot_x - du->hotspot_x; - du->core_hotspot_y = hotspot_y - du->hotspot_y; - } else { - DRM_ERROR("Failed to update cursor image\n"); - } + du->core_hotspot_x = hotspot_x - du->hotspot_x; + du->core_hotspot_y = hotspot_y - du->hotspot_y; } @@ -518,7 +768,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, if (new_state->crtc_w != 64 || new_state->crtc_h != 64) { DRM_ERROR("Invalid cursor dimensions (%d, %d)\n", new_state->crtc_w, new_state->crtc_h); - ret = -EINVAL; + return -EINVAL; } if (!vmw_framebuffer_to_vfb(fb)->bo) @@ -526,10 +776,10 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, if (surface && !surface->snooper.image) { DRM_ERROR("surface not suitable for cursor\n"); - ret = -EINVAL; + return -EINVAL; } - return ret; + return 0; } @@ -712,7 +962,6 @@ void vmw_du_plane_reset(struct drm_plane *plane) { struct vmw_plane_state *vps; - if (plane->state) vmw_du_plane_destroy_state(plane, plane->state); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 4d36e8507380..c95be95deb8d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0 OR MIT */ /************************************************************************** * - * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA + * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -261,6 +261,7 @@ static const uint32_t __maybe_unused vmw_cursor_plane_formats[] = { #define vmw_plane_state_to_vps(x) container_of(x, struct vmw_plane_state, base) #define vmw_connector_state_to_vcs(x) \ container_of(x, struct vmw_connector_state, base) +#define vmw_plane_to_vcp(x) container_of(x, struct vmw_cursor_plane, base) /** * Derived class for crtc state object @@ -293,6 +294,14 @@ struct vmw_plane_state { /* For CPU Blit */ unsigned int cpp; + + /* CursorMob flipping index; -1 if cursor mobs not used */ + unsigned int cursor_mob_idx; + /* Currently-active CursorMob */ + struct ttm_buffer_object *cm_bo; + /* CursorMob kmap_obj; expected valid at cursor_plane_atomic_update + IFF currently-active CursorMob above is valid */ + struct ttm_bo_kmap_obj cm_map; }; @@ -325,6 +334,17 @@ struct vmw_connector_state { int gui_y; }; +/** + * Derived class for cursor plane object + * + * @base DRM plane object + * @cursor_mob array of two MOBs for CursorMob flipping + */ +struct vmw_cursor_plane { + struct drm_plane base; + struct ttm_buffer_object *cursor_mob[2]; +}; + /** * Base class display unit. * @@ -337,7 +357,7 @@ struct vmw_display_unit { struct drm_encoder encoder; struct drm_connector connector; struct drm_plane primary; - struct drm_plane cursor; + struct vmw_cursor_plane cursor; struct vmw_surface *cursor_surface; struct vmw_buffer_object *cursor_bo; @@ -452,6 +472,8 @@ void vmw_kms_create_implicit_placement_property(struct vmw_private *dev_priv); /* Universal Plane Helpers */ void vmw_du_primary_plane_destroy(struct drm_plane *plane); void vmw_du_cursor_plane_destroy(struct drm_plane *plane); +int vmw_du_create_cursor_mob_array(struct vmw_cursor_plane *vcp); +void vmw_du_destroy_cursor_mob_array(struct vmw_cursor_plane *vcp); /* Atomic Helpers */ int vmw_du_primary_plane_atomic_check(struct drm_plane *plane, @@ -462,6 +484,8 @@ void vmw_du_cursor_plane_atomic_update(struct drm_plane *plane, struct drm_atomic_state *state); int vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, struct drm_plane_state *new_state); +void vmw_du_cursor_plane_cleanup_fb(struct drm_plane *plane, + struct drm_plane_state *old_state); void vmw_du_plane_cleanup_fb(struct drm_plane *plane, struct drm_plane_state *old_state); void vmw_du_plane_reset(struct drm_plane *plane); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index fb58a71c458f..643c1608ddfd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA + * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -338,7 +338,7 @@ drm_plane_helper_funcs vmw_ldu_cursor_plane_helper_funcs = { .atomic_check = vmw_du_cursor_plane_atomic_check, .atomic_update = vmw_du_cursor_plane_atomic_update, .prepare_fb = vmw_du_cursor_plane_prepare_fb, - .cleanup_fb = vmw_du_plane_cleanup_fb, + .cleanup_fb = vmw_du_cursor_plane_cleanup_fb, }; static const struct @@ -363,7 +363,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector; struct drm_encoder *encoder; - struct drm_plane *primary, *cursor; + struct drm_plane *primary; + struct vmw_cursor_plane *cursor; struct drm_crtc *crtc; int ret; @@ -392,7 +393,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) ldu->base.is_implicit = true; /* Initialize primary plane */ - ret = drm_universal_plane_init(dev, &ldu->base.primary, + ret = drm_universal_plane_init(dev, primary, 0, &vmw_ldu_plane_funcs, vmw_primary_plane_formats, ARRAY_SIZE(vmw_primary_plane_formats), @@ -409,7 +410,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) */ if (vmw_cmd_supported(dev_priv)) { /* Initialize cursor plane */ - ret = drm_universal_plane_init(dev, &ldu->base.cursor, + ret = drm_universal_plane_init(dev, &cursor->base, 0, &vmw_ldu_cursor_funcs, vmw_cursor_plane_formats, ARRAY_SIZE(vmw_cursor_plane_formats), @@ -420,7 +421,7 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) goto err_free; } - drm_plane_helper_add(cursor, &vmw_ldu_cursor_plane_helper_funcs); + drm_plane_helper_add(&cursor->base, &vmw_ldu_cursor_plane_helper_funcs); } ret = drm_connector_init(dev, connector, &vmw_legacy_connector_funcs, @@ -450,9 +451,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) goto err_free_encoder; } - ret = drm_crtc_init_with_planes( - dev, crtc, &ldu->base.primary, - vmw_cmd_supported(dev_priv) ? &ldu->base.cursor : NULL, + ret = drm_crtc_init_with_planes(dev, crtc, primary, + vmw_cmd_supported(dev_priv) ? &cursor->base : NULL, &vmw_legacy_crtc_funcs, NULL); if (ret) { DRM_ERROR("Failed to initialize CRTC\n"); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index 3004c7a719e9..c89ad3a2d141 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2011-2015 VMware, Inc., Palo Alto, CA., USA + * Copyright 2011-2022 VMware, Inc., Palo Alto, CA., USA * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -804,7 +804,7 @@ drm_plane_helper_funcs vmw_sou_cursor_plane_helper_funcs = { .atomic_check = vmw_du_cursor_plane_atomic_check, .atomic_update = vmw_du_cursor_plane_atomic_update, .prepare_fb = vmw_du_cursor_plane_prepare_fb, - .cleanup_fb = vmw_du_plane_cleanup_fb, + .cleanup_fb = vmw_du_cursor_plane_cleanup_fb, }; static const struct @@ -832,7 +832,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector; struct drm_encoder *encoder; - struct drm_plane *primary, *cursor; + struct drm_plane *primary; + struct vmw_cursor_plane *cursor; struct drm_crtc *crtc; int ret; @@ -859,7 +860,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) sou->base.is_implicit = false; /* Initialize primary plane */ - ret = drm_universal_plane_init(dev, &sou->base.primary, + ret = drm_universal_plane_init(dev, primary, 0, &vmw_sou_plane_funcs, vmw_primary_plane_formats, ARRAY_SIZE(vmw_primary_plane_formats), @@ -873,7 +874,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) drm_plane_enable_fb_damage_clips(primary); /* Initialize cursor plane */ - ret = drm_universal_plane_init(dev, &sou->base.cursor, + ret = drm_universal_plane_init(dev, &cursor->base, 0, &vmw_sou_cursor_funcs, vmw_cursor_plane_formats, ARRAY_SIZE(vmw_cursor_plane_formats), @@ -884,7 +885,7 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) goto err_free; } - drm_plane_helper_add(cursor, &vmw_sou_cursor_plane_helper_funcs); + drm_plane_helper_add(&cursor->base, &vmw_sou_cursor_plane_helper_funcs); ret = drm_connector_init(dev, connector, &vmw_sou_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); @@ -913,8 +914,8 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) goto err_free_encoder; } - ret = drm_crtc_init_with_planes(dev, crtc, &sou->base.primary, - &sou->base.cursor, + ret = drm_crtc_init_with_planes(dev, crtc, primary, + &cursor->base, &vmw_screen_object_crtc_funcs, NULL); if (ret) { DRM_ERROR("Failed to initialize CRTC\n"); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index ae9a6044d448..42b5ecb0c5e9 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /****************************************************************************** * - * COPYRIGHT (C) 2014-2015 VMware, Inc., Palo Alto, CA., USA + * COPYRIGHT (C) 2014-2022 VMware, Inc., Palo Alto, CA., USA * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -1685,7 +1685,7 @@ drm_plane_helper_funcs vmw_stdu_cursor_plane_helper_funcs = { .atomic_check = vmw_du_cursor_plane_atomic_check, .atomic_update = vmw_du_cursor_plane_atomic_update, .prepare_fb = vmw_du_cursor_plane_prepare_fb, - .cleanup_fb = vmw_du_plane_cleanup_fb, + .cleanup_fb = vmw_du_cursor_plane_cleanup_fb, }; static const struct @@ -1723,11 +1723,11 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit) struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector; struct drm_encoder *encoder; - struct drm_plane *primary, *cursor; + struct drm_plane *primary; + struct vmw_cursor_plane *cursor; struct drm_crtc *crtc; int ret; - stdu = kzalloc(sizeof(*stdu), GFP_KERNEL); if (!stdu) return -ENOMEM; @@ -1759,7 +1759,7 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit) drm_plane_enable_fb_damage_clips(primary); /* Initialize cursor plane */ - ret = drm_universal_plane_init(dev, cursor, + ret = drm_universal_plane_init(dev, &cursor->base, 0, &vmw_stdu_cursor_funcs, vmw_cursor_plane_formats, ARRAY_SIZE(vmw_cursor_plane_formats), @@ -1770,7 +1770,7 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit) goto err_free; } - drm_plane_helper_add(cursor, &vmw_stdu_cursor_plane_helper_funcs); + drm_plane_helper_add(&cursor->base, &vmw_stdu_cursor_plane_helper_funcs); ret = drm_connector_init(dev, connector, &vmw_stdu_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); @@ -1799,8 +1799,8 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit) goto err_free_encoder; } - ret = drm_crtc_init_with_planes(dev, crtc, &stdu->base.primary, - &stdu->base.cursor, + ret = drm_crtc_init_with_planes(dev, crtc, primary, + &cursor->base, &vmw_stdu_crtc_funcs, NULL); if (ret) { DRM_ERROR("Failed to initialize CRTC\n"); From bb30d8d8c1b0002712f112c519c9caf4fdf8c9d1 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Wed, 2 Mar 2022 10:24:20 -0500 Subject: [PATCH 00162/11454] drm/vmwgfx: Cleanup multimon initialization code The results of the legacy display unit initialization were being silently ignored. Unifying the selection of number of display units based on whether the underlying device supports multimon makes it easier to add error checking to all paths. This makes the driver report the errors in ldu initialization paths and try to recover from them. Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Reviewed-by: Maaz Mombasawala Link: https://patchwork.freedesktop.org/patch/msgid/20220302152426.885214-3-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index 643c1608ddfd..e4347faccee0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -492,6 +492,8 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; int i, ret; + int num_display_units = (dev_priv->capabilities & SVGA_CAP_MULTIMON) ? + VMWGFX_NUM_DISPLAY_UNITS : 1; if (unlikely(dev_priv->ldu_priv)) { return -EINVAL; @@ -506,21 +508,17 @@ int vmw_kms_ldu_init_display(struct vmw_private *dev_priv) dev_priv->ldu_priv->last_num_active = 0; dev_priv->ldu_priv->fb = NULL; - /* for old hardware without multimon only enable one display */ - if (dev_priv->capabilities & SVGA_CAP_MULTIMON) - ret = drm_vblank_init(dev, VMWGFX_NUM_DISPLAY_UNITS); - else - ret = drm_vblank_init(dev, 1); + ret = drm_vblank_init(dev, num_display_units); if (ret != 0) goto err_free; vmw_kms_create_implicit_placement_property(dev_priv); - if (dev_priv->capabilities & SVGA_CAP_MULTIMON) - for (i = 0; i < VMWGFX_NUM_DISPLAY_UNITS; ++i) - vmw_ldu_init(dev_priv, i); - else - vmw_ldu_init(dev_priv, 0); + for (i = 0; i < num_display_units; ++i) { + ret = vmw_ldu_init(dev_priv, i); + if (ret != 0) + goto err_free; + } dev_priv->active_display_unit = vmw_du_legacy; From af326e28380ab858cf7e0c67ba04c4f38a7a41ea Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Wed, 2 Mar 2022 10:24:21 -0500 Subject: [PATCH 00163/11454] drm/vmwgfx: Print capabilities early during the initialization Capabilities were logged at the end of initialization so any early errors would make them not appear in the logs. Which is also when they're needed the most. Print the the capabilities right after fetching them, before the init code starts using them to make sure they always show up in the logs. Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Reviewed-by: Maaz Mombasawala Link: https://patchwork.freedesktop.org/patch/msgid/20220302152426.885214-4-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 621231c66fd4..f43afd56915e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -848,12 +848,16 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) dev_priv->capabilities = vmw_read(dev_priv, SVGA_REG_CAPABILITIES); - + vmw_print_bitmap(&dev_priv->drm, "Capabilities", + dev_priv->capabilities, + cap1_names, ARRAY_SIZE(cap1_names)); if (dev_priv->capabilities & SVGA_CAP_CAP2_REGISTER) { dev_priv->capabilities2 = vmw_read(dev_priv, SVGA_REG_CAP2); + vmw_print_bitmap(&dev_priv->drm, "Capabilities2", + dev_priv->capabilities2, + cap2_names, ARRAY_SIZE(cap2_names)); } - ret = vmw_dma_select_mode(dev_priv); if (unlikely(ret != 0)) { drm_info(&dev_priv->drm, @@ -939,14 +943,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) "MOB limits: max mob size = %u kB, max mob pages = %u\n", dev_priv->max_mob_size / 1024, dev_priv->max_mob_pages); - vmw_print_bitmap(&dev_priv->drm, "Capabilities", - dev_priv->capabilities, - cap1_names, ARRAY_SIZE(cap1_names)); - if (dev_priv->capabilities & SVGA_CAP_CAP2_REGISTER) - vmw_print_bitmap(&dev_priv->drm, "Capabilities2", - dev_priv->capabilities2, - cap2_names, ARRAY_SIZE(cap2_names)); - ret = vmw_dma_masks(dev_priv); if (unlikely(ret != 0)) goto out_err0; From c593197b6ece417675256e220b5eac25c0b33290 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Wed, 2 Mar 2022 10:24:22 -0500 Subject: [PATCH 00164/11454] drm/vmwgfx: Fix fencing on SVGAv3 Port of the vmwgfx to SVGAv3 lacked support for fencing. SVGAv3 removed FIFO's and replaced them with command buffers and extra registers. The initial version of SVGAv3 lacked support for most advanced features (e.g. 3D) which made fences unnecessary. That is no longer the case, especially as 3D support is being turned on. Switch from FIFO commands and capabilities to command buffers and extra registers to enable fences on SVGAv3. Fixes: 2cd80dbd3551 ("drm/vmwgfx: Add basic support for SVGA3") Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Reviewed-by: Maaz Mombasawala Link: https://patchwork.freedesktop.org/patch/msgid/20220302152426.885214-5-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 8 ++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 28 ++++++++++++++++++++------- drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | 26 +++++++++++++++++-------- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +++++--- 5 files changed, 53 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c index a3bfbb6c3e14..bf1b394753da 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c @@ -528,7 +528,7 @@ int vmw_cmd_send_fence(struct vmw_private *dev_priv, uint32_t *seqno) *seqno = atomic_add_return(1, &dev_priv->marker_seq); } while (*seqno == 0); - if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE)) { + if (!vmw_has_fences(dev_priv)) { /* * Don't request hardware to send a fence. The diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 780da6147cf9..12eb4de41036 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1683,4 +1683,12 @@ static inline void vmw_irq_status_write(struct vmw_private *vmw, outl(status, vmw->io_start + SVGA_IRQSTATUS_PORT); } +static inline bool vmw_has_fences(struct vmw_private *vmw) +{ + if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS | + SVGA_CAP_CMD_BUFFERS_2)) != 0) + return true; + return (vmw_fifo_caps(vmw) & SVGA_FIFO_CAP_FENCE) != 0; +} + #endif diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 59d6a2dd4c2e..66cc35dc223e 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c @@ -82,6 +82,22 @@ fman_from_fence(struct vmw_fence_obj *fence) return container_of(fence->base.lock, struct vmw_fence_manager, lock); } +static u32 vmw_fence_goal_read(struct vmw_private *vmw) +{ + if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) + return vmw_read(vmw, SVGA_REG_FENCE_GOAL); + else + return vmw_fifo_mem_read(vmw, SVGA_FIFO_FENCE_GOAL); +} + +static void vmw_fence_goal_write(struct vmw_private *vmw, u32 value) +{ + if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) + vmw_write(vmw, SVGA_REG_FENCE_GOAL, value); + else + vmw_fifo_mem_write(vmw, SVGA_FIFO_FENCE_GOAL, value); +} + /* * Note on fencing subsystem usage of irqs: * Typically the vmw_fences_update function is called @@ -392,7 +408,7 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, if (likely(!fman->seqno_valid)) return false; - goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL); + goal_seqno = vmw_fence_goal_read(fman->dev_priv); if (likely(passed_seqno - goal_seqno >= VMW_FENCE_WRAP)) return false; @@ -400,9 +416,8 @@ static bool vmw_fence_goal_new_locked(struct vmw_fence_manager *fman, list_for_each_entry(fence, &fman->fence_list, head) { if (!list_empty(&fence->seq_passed_actions)) { fman->seqno_valid = true; - vmw_fifo_mem_write(fman->dev_priv, - SVGA_FIFO_FENCE_GOAL, - fence->base.seqno); + vmw_fence_goal_write(fman->dev_priv, + fence->base.seqno); break; } } @@ -434,13 +449,12 @@ static bool vmw_fence_goal_check_locked(struct vmw_fence_obj *fence) if (dma_fence_is_signaled_locked(&fence->base)) return false; - goal_seqno = vmw_fifo_mem_read(fman->dev_priv, SVGA_FIFO_FENCE_GOAL); + goal_seqno = vmw_fence_goal_read(fman->dev_priv); if (likely(fman->seqno_valid && goal_seqno - fence->base.seqno < VMW_FENCE_WRAP)) return false; - vmw_fifo_mem_write(fman->dev_priv, SVGA_FIFO_FENCE_GOAL, - fence->base.seqno); + vmw_fence_goal_write(fman->dev_priv, fence->base.seqno); fman->seqno_valid = true; return true; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index c5191de365ca..fe4732bf2c9d 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -32,6 +32,14 @@ #define VMW_FENCE_WRAP (1 << 24) +static u32 vmw_irqflag_fence_goal(struct vmw_private *vmw) +{ + if ((vmw->capabilities2 & SVGA_CAP2_EXTRA_REGS) != 0) + return SVGA_IRQFLAG_REG_FENCE_GOAL; + else + return SVGA_IRQFLAG_FENCE_GOAL; +} + /** * vmw_thread_fn - Deferred (process context) irq handler * @@ -96,7 +104,7 @@ static irqreturn_t vmw_irq_handler(int irq, void *arg) wake_up_all(&dev_priv->fifo_queue); if ((masked_status & (SVGA_IRQFLAG_ANY_FENCE | - SVGA_IRQFLAG_FENCE_GOAL)) && + vmw_irqflag_fence_goal(dev_priv))) && !test_and_set_bit(VMW_IRQTHREAD_FENCE, dev_priv->irqthread_pending)) ret = IRQ_WAKE_THREAD; @@ -137,8 +145,7 @@ bool vmw_seqno_passed(struct vmw_private *dev_priv, if (likely(dev_priv->last_read_seqno - seqno < VMW_FENCE_WRAP)) return true; - if (!(vmw_fifo_caps(dev_priv) & SVGA_FIFO_CAP_FENCE) && - vmw_fifo_idle(dev_priv, seqno)) + if (!vmw_has_fences(dev_priv) && vmw_fifo_idle(dev_priv, seqno)) return true; /** @@ -160,6 +167,7 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, unsigned long timeout) { struct vmw_fifo_state *fifo_state = dev_priv->fifo; + bool fifo_down = false; uint32_t count = 0; uint32_t signal_seq; @@ -176,12 +184,14 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, */ if (fifo_idle) { - down_read(&fifo_state->rwsem); if (dev_priv->cman) { ret = vmw_cmdbuf_idle(dev_priv->cman, interruptible, 10*HZ); if (ret) goto out_err; + } else if (fifo_state) { + down_read(&fifo_state->rwsem); + fifo_down = true; } } @@ -218,12 +228,12 @@ int vmw_fallback_wait(struct vmw_private *dev_priv, } } finish_wait(&dev_priv->fence_queue, &__wait); - if (ret == 0 && fifo_idle) + if (ret == 0 && fifo_idle && fifo_state) vmw_fence_write(dev_priv, signal_seq); wake_up_all(&dev_priv->fence_queue); out_err: - if (fifo_idle) + if (fifo_down) up_read(&fifo_state->rwsem); return ret; @@ -266,13 +276,13 @@ void vmw_seqno_waiter_remove(struct vmw_private *dev_priv) void vmw_goal_waiter_add(struct vmw_private *dev_priv) { - vmw_generic_waiter_add(dev_priv, SVGA_IRQFLAG_FENCE_GOAL, + vmw_generic_waiter_add(dev_priv, vmw_irqflag_fence_goal(dev_priv), &dev_priv->goal_queue_waiters); } void vmw_goal_waiter_remove(struct vmw_private *dev_priv) { - vmw_generic_waiter_remove(dev_priv, SVGA_IRQFLAG_FENCE_GOAL, + vmw_generic_waiter_remove(dev_priv, vmw_irqflag_fence_goal(dev_priv), &dev_priv->goal_queue_waiters); } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 9d82a7b49aed..af252210ef84 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1593,7 +1593,6 @@ vmw_kms_new_framebuffer(struct vmw_private *dev_priv, ret = vmw_kms_new_framebuffer_surface(dev_priv, surface, &vfb, mode_cmd, is_bo_proxy); - /* * vmw_create_bo_proxy() adds a reference that is no longer * needed @@ -1634,13 +1633,16 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev, ret = vmw_user_lookup_handle(dev_priv, file_priv, mode_cmd->handles[0], &surface, &bo); - if (ret) + if (ret) { + DRM_ERROR("Invalid buffer object handle %u (0x%x).\n", + mode_cmd->handles[0], mode_cmd->handles[0]); goto err_out; + } if (!bo && !vmw_kms_srf_ok(dev_priv, mode_cmd->width, mode_cmd->height)) { - DRM_ERROR("Surface size cannot exceed %dx%d", + DRM_ERROR("Surface size cannot exceed %dx%d\n", dev_priv->texture_max_width, dev_priv->texture_max_height); goto err_out; From 23b0e695d4ca92e9ebd97689e2e51e497957cb48 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Wed, 2 Mar 2022 10:24:23 -0500 Subject: [PATCH 00165/11454] drm/vmwgfx: Allow querying of the SVGA PCI id from the userspace Mesa3D loaders require knowledge of the devices PCI id. SVGAv2 and v3 have different PCI id's, but the same driver is used to handle them both. To allow Mesa3D svga driver to be loaded automatically for both SVGAv2 and SVGAv3 make the kernel return the PCI id of the currently running device. Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Reviewed-by: Maaz Mombasawala Link: https://patchwork.freedesktop.org/patch/msgid/20220302152426.885214-6-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c | 27 +++++++++++++++------------ include/uapi/drm/vmwgfx_drm.h | 9 ++++++++- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 471da2b4c177..a1da5678c731 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR MIT /************************************************************************** * - * Copyright 2009-2015 VMware, Inc., Palo Alto, CA., USA + * Copyright 2009-2022 VMware, Inc., Palo Alto, CA., USA * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -27,9 +27,11 @@ #include "vmwgfx_drv.h" #include "vmwgfx_devcaps.h" -#include #include "vmwgfx_kms.h" +#include +#include + int vmw_getparam_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { @@ -62,17 +64,15 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, break; case DRM_VMW_PARAM_FIFO_HW_VERSION: { - if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) { + if ((dev_priv->capabilities & SVGA_CAP_GBOBJECTS)) param->value = SVGA3D_HWVERSION_WS8_B1; - break; - } - - param->value = - vmw_fifo_mem_read(dev_priv, - ((vmw_fifo_caps(dev_priv) & - SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ? - SVGA_FIFO_3D_HWVERSION_REVISED : - SVGA_FIFO_3D_HWVERSION)); + else + param->value = vmw_fifo_mem_read( + dev_priv, + ((vmw_fifo_caps(dev_priv) & + SVGA_FIFO_CAP_3D_HWVERSION_REVISED) ? + SVGA_FIFO_3D_HWVERSION_REVISED : + SVGA_FIFO_3D_HWVERSION)); break; } case DRM_VMW_PARAM_MAX_SURF_MEMORY: @@ -108,6 +108,9 @@ int vmw_getparam_ioctl(struct drm_device *dev, void *data, case DRM_VMW_PARAM_GL43: param->value = has_gl43_context(dev_priv); break; + case DRM_VMW_PARAM_DEVICE_ID: + param->value = to_pci_dev(dev_priv->drm.dev)->device; + break; default: return -EINVAL; } diff --git a/include/uapi/drm/vmwgfx_drm.h b/include/uapi/drm/vmwgfx_drm.h index 8277644c1144..26549c86a91f 100644 --- a/include/uapi/drm/vmwgfx_drm.h +++ b/include/uapi/drm/vmwgfx_drm.h @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright © 2009-2015 VMware, Inc., Palo Alto, CA., USA + * Copyright © 2009-2022 VMware, Inc., Palo Alto, CA., USA * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -92,6 +92,12 @@ extern "C" { * * DRM_VMW_PARAM_SM5 * SM5 support is enabled. + * + * DRM_VMW_PARAM_GL43 + * SM5.1+GL4.3 support is enabled. + * + * DRM_VMW_PARAM_DEVICE_ID + * PCI ID of the underlying SVGA device. */ #define DRM_VMW_PARAM_NUM_STREAMS 0 @@ -111,6 +117,7 @@ extern "C" { #define DRM_VMW_PARAM_SM4_1 14 #define DRM_VMW_PARAM_SM5 15 #define DRM_VMW_PARAM_GL43 16 +#define DRM_VMW_PARAM_DEVICE_ID 17 /** * enum drm_vmw_handle_type - handle type for ref ioctls From 5405d25b9e8e6e0d3bdb04833d528a9bb35fe7ce Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Wed, 2 Mar 2022 10:24:24 -0500 Subject: [PATCH 00166/11454] drm/vmwgfx: Initialize drm_mode_fb_cmd2 Transition to drm_mode_fb_cmd2 from drm_mode_fb_cmd left the structure unitialized. drm_mode_fb_cmd2 adds a few additional members, e.g. flags and modifiers which were never initialized. Garbage in those members can cause random failures during the bringup of the fbcon. Initializing the structure fixes random blank screens after bootup due to flags/modifiers mismatches during the fbcon bring up. Fixes: dabdcdc9822a ("drm/vmwgfx: Switch to mode_cmd2") Signed-off-by: Zack Rusin Cc: Daniel Vetter Cc: # v4.10+ Reviewed-by: Martin Krastev Reviewed-by: Maaz Mombasawala Link: https://patchwork.freedesktop.org/patch/msgid/20220302152426.885214-7-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 8ee34576c7d0..adf17c740656 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c @@ -483,7 +483,7 @@ static int vmw_fb_kms_detach(struct vmw_fb_par *par, static int vmw_fb_kms_framebuffer(struct fb_info *info) { - struct drm_mode_fb_cmd2 mode_cmd; + struct drm_mode_fb_cmd2 mode_cmd = {0}; struct vmw_fb_par *par = info->par; struct fb_var_screeninfo *var = &info->var; struct drm_framebuffer *cur_fb; From 32160e6a98f33cd96fde52cd56b9b758b59d3603 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Mon, 7 Mar 2022 11:24:12 -0500 Subject: [PATCH 00167/11454] drm/vmwgfx: Implement MSI/MSI-X support for IRQs SVGAv3 deprecates legacy interrupts and adds support for MSI/MSI-X. With MSI the driver visible side remains largely unchanged but with MSI-X each interrupt gets delivered on its own vector. Add support for MSI/MSI-X while preserving the old functionality for SVGAv2. Code between the SVGAv2 and SVGAv3 is exactly the same, only the number of available vectors changes, in particular between legacy and MSI-X interrupts. Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Reviewed-by: Maaz Mombasawala Link: https://patchwork.freedesktop.org/patch/msgid/20220307162412.1183049-1-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 9 ++++- drivers/gpu/drm/vmwgfx/vmwgfx_irq.c | 55 +++++++++++++++++++++++++---- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index f43afd56915e..791f9a5f3868 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -980,7 +980,7 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) } if (dev_priv->capabilities & SVGA_CAP_IRQMASK) { - ret = vmw_irq_install(&dev_priv->drm, pdev->irq); + ret = vmw_irq_install(dev_priv); if (ret != 0) { drm_err(&dev_priv->drm, "Failed installing irq: %d\n", ret); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 12eb4de41036..be19aa6e1f13 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -65,6 +65,11 @@ #define VMWGFX_PCI_ID_SVGA2 0x0405 #define VMWGFX_PCI_ID_SVGA3 0x0406 +/* + * This has to match get_count_order(SVGA_IRQFLAG_MAX) + */ +#define VMWGFX_MAX_NUM_IRQS 6 + /* * Perhaps we should have sysfs entries for these. */ @@ -532,6 +537,8 @@ struct vmw_private { bool has_mob; spinlock_t hw_lock; bool assume_16bpp; + u32 irqs[VMWGFX_MAX_NUM_IRQS]; + u32 num_irq_vectors; enum vmw_sm_type sm_type; @@ -1158,7 +1165,7 @@ bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd); * IRQs and wating - vmwgfx_irq.c */ -extern int vmw_irq_install(struct drm_device *dev, int irq); +extern int vmw_irq_install(struct vmw_private *dev_priv); extern void vmw_irq_uninstall(struct drm_device *dev); extern bool vmw_seqno_passed(struct vmw_private *dev_priv, uint32_t seqno); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c index fe4732bf2c9d..086e69a130d4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_irq.c @@ -300,6 +300,7 @@ void vmw_irq_uninstall(struct drm_device *dev) struct vmw_private *dev_priv = vmw_priv(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); uint32_t status; + u32 i; if (!(dev_priv->capabilities & SVGA_CAP_IRQMASK)) return; @@ -309,20 +310,62 @@ void vmw_irq_uninstall(struct drm_device *dev) status = vmw_irq_status_read(dev_priv); vmw_irq_status_write(dev_priv, status); - free_irq(pdev->irq, dev); + for (i = 0; i < dev_priv->num_irq_vectors; ++i) + free_irq(dev_priv->irqs[i], dev); + + pci_free_irq_vectors(pdev); + dev_priv->num_irq_vectors = 0; } /** * vmw_irq_install - Install the irq handlers * - * @dev: Pointer to the drm device. - * @irq: The irq number. + * @dev_priv: Pointer to the vmw_private device. * Return: Zero if successful. Negative number otherwise. */ -int vmw_irq_install(struct drm_device *dev, int irq) +int vmw_irq_install(struct vmw_private *dev_priv) { + struct pci_dev *pdev = to_pci_dev(dev_priv->drm.dev); + struct drm_device *dev = &dev_priv->drm; + int ret; + int nvec; + int i = 0; + + BUILD_BUG_ON((SVGA_IRQFLAG_MAX >> VMWGFX_MAX_NUM_IRQS) != 1); + BUG_ON(VMWGFX_MAX_NUM_IRQS != get_count_order(SVGA_IRQFLAG_MAX)); + + nvec = pci_alloc_irq_vectors(pdev, 1, VMWGFX_MAX_NUM_IRQS, + PCI_IRQ_ALL_TYPES); + + if (nvec <= 0) { + drm_err(&dev_priv->drm, + "IRQ's are unavailable, nvec: %d\n", nvec); + ret = nvec; + goto done; + } + vmw_irq_preinstall(dev); - return request_threaded_irq(irq, vmw_irq_handler, vmw_thread_fn, - IRQF_SHARED, VMWGFX_DRIVER_NAME, dev); + for (i = 0; i < nvec; ++i) { + ret = pci_irq_vector(pdev, i); + if (ret < 0) { + drm_err(&dev_priv->drm, + "failed getting irq vector: %d\n", ret); + goto done; + } + dev_priv->irqs[i] = ret; + + ret = request_threaded_irq(dev_priv->irqs[i], vmw_irq_handler, vmw_thread_fn, + IRQF_SHARED, VMWGFX_DRIVER_NAME, dev); + if (ret != 0) { + drm_err(&dev_priv->drm, + "Failed installing irq(%d): %d\n", + dev_priv->irqs[i], ret); + goto done; + } + } + +done: + dev_priv->num_irq_vectors = i; + return ret; } From b861de246912e10c5bda32cb100bff429a5e1ec4 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Wed, 2 Mar 2022 10:24:26 -0500 Subject: [PATCH 00168/11454] drm/vmwgfx: Stop using surface dma commands on most configurations Initial version of guest backed objects in the host had some performance issues that made using surface-dma's instead of direct copies faster. Surface dma's force a migration to vram which at best is slow and at worst is impossible (e.g. on svga3 where there's not enough vram to migrate fb's to it). Slowly migrate away from surface dma's to direct copies by limiting their usage to systems with more than 32MB of vram. Signed-off-by: Zack Rusin Reviewed-by: Maaz Mombasawala Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20220302152426.885214-9-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 42b5ecb0c5e9..eb014b97d156 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -138,6 +138,11 @@ static void vmw_stdu_destroy(struct vmw_screen_target_display_unit *stdu); * Screen Target Display Unit CRTC Functions *****************************************************************************/ +static bool vmw_stdu_use_cpu_blit(const struct vmw_private *vmw) +{ + return !(vmw->capabilities & SVGA_CAP_3D) || vmw->vram_size < (32 * 1024 * 1024); +} + /** * vmw_stdu_crtc_destroy - cleans up the STDU @@ -689,7 +694,7 @@ int vmw_kms_stdu_dma(struct vmw_private *dev_priv, container_of(vfb, struct vmw_framebuffer_bo, base)->buffer; struct vmw_stdu_dirty ddirty; int ret; - bool cpu_blit = !(dev_priv->capabilities & SVGA_CAP_3D); + bool cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); /* @@ -1164,7 +1169,7 @@ vmw_stdu_primary_plane_prepare_fb(struct drm_plane *plane, * so cache these mappings */ if (vps->content_fb_type == SEPARATE_BO && - !(dev_priv->capabilities & SVGA_CAP_3D)) + vmw_stdu_use_cpu_blit(dev_priv)) vps->cpp = new_fb->pitches[0] / new_fb->width; return 0; @@ -1368,7 +1373,7 @@ static int vmw_stdu_plane_update_bo(struct vmw_private *dev_priv, bo_update.base.vfb = vfb; bo_update.base.out_fence = out_fence; bo_update.base.mutex = NULL; - bo_update.base.cpu_blit = !(dev_priv->capabilities & SVGA_CAP_3D); + bo_update.base.cpu_blit = vmw_stdu_use_cpu_blit(dev_priv); bo_update.base.intr = false; /* From 2d3eec8970335148278a6e350bc4840374f06471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Feb 2022 12:03:42 +0200 Subject: [PATCH 00169/11454] drm: Add drm_mode_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a variant of drm_mode_copy() that explicitly clears out the list head of the destination mode. Helpful to guarantee we don't have stack garbage left in there for on-stack modes. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220218100403.7028-2-ville.syrjala@linux.intel.com Reviewed-by: Andrzej Hajda Reviewed-by: Harry Wentland --- drivers/gpu/drm/drm_modes.c | 17 +++++++++++++++++ include/drm/drm_modes.h | 2 ++ 2 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 3f819c7a021b..6e7e10f16ec0 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -941,6 +941,23 @@ void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode * } EXPORT_SYMBOL(drm_mode_copy); +/** + * drm_mode_init - initialize the mode from another mode + * @dst: mode to overwrite + * @src: mode to copy + * + * Copy an existing mode into another mode, zeroing the + * list head of the destination mode. Typically used + * to guarantee the list head is not left with stack + * garbage in on-stack modes. + */ +void drm_mode_init(struct drm_display_mode *dst, const struct drm_display_mode *src) +{ + memset(dst, 0, sizeof(*dst)); + drm_mode_copy(dst, src); +} +EXPORT_SYMBOL(drm_mode_init); + /** * drm_mode_duplicate - allocate and duplicate an existing mode * @dev: drm_device to allocate the duplicated mode for diff --git a/include/drm/drm_modes.h b/include/drm/drm_modes.h index 2fa6b2c33b3f..a80ae9639e96 100644 --- a/include/drm/drm_modes.h +++ b/include/drm/drm_modes.h @@ -492,6 +492,8 @@ void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags); void drm_mode_copy(struct drm_display_mode *dst, const struct drm_display_mode *src); +void drm_mode_init(struct drm_display_mode *dst, + const struct drm_display_mode *src); struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev, const struct drm_display_mode *mode); bool drm_mode_match(const struct drm_display_mode *mode1, From d008bc331fb135ea1a5cddc3c4e283ba74596ad2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Feb 2022 12:03:47 +0200 Subject: [PATCH 00170/11454] drm/bridge: Use drm_mode_copy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct drm_display_mode embeds a list head, so overwriting the full struct with another one will corrupt the list (if the destination mode is on a list). Use drm_mode_copy() instead which explicitly preserves the list head of the destination mode. Even if we know the destination mode is not on any list using drm_mode_copy() seems decent as it sets a good example. Bad examples of not using it might eventually get copied into code where preserving the list head actually matters. Obviously one case not covered here is when the mode itself is embedded in a larger structure and the whole structure is copied. But if we are careful when copying into modes embedded in structures I think we can be a little more reassured that bogus list heads haven't been propagated in. @is_mode_copy@ @@ drm_mode_copy(...) { ... } @depends on !is_mode_copy@ struct drm_display_mode *mode; expression E, S; @@ ( - *mode = E + drm_mode_copy(mode, &E) | - memcpy(mode, E, S) + drm_mode_copy(mode, E) ) @depends on !is_mode_copy@ struct drm_display_mode mode; expression E; @@ ( - mode = E + drm_mode_copy(&mode, &E) | - memcpy(&mode, E, S) + drm_mode_copy(&mode, E) ) @@ struct drm_display_mode *mode; @@ - &*mode + mode Cc: Andrzej Hajda Cc: Neil Armstrong Cc: Robert Foss Cc: Laurent Pinchart Cc: Jonas Karlman Cc: Jernej Skrabec Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220218100403.7028-7-ville.syrjala@linux.intel.com Reviewed-by: Andrzej Hajda Reviewed-by: Laurent Pinchart --- drivers/gpu/drm/bridge/nwl-dsi.c | 2 +- drivers/gpu/drm/bridge/synopsys/dw-hdmi.c | 2 +- drivers/gpu/drm/bridge/tc358767.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c index 14c763e1fa6f..e34fb09b90b9 100644 --- a/drivers/gpu/drm/bridge/nwl-dsi.c +++ b/drivers/gpu/drm/bridge/nwl-dsi.c @@ -855,7 +855,7 @@ nwl_dsi_bridge_mode_set(struct drm_bridge *bridge, /* Save the new desired phy config */ memcpy(&dsi->phy_cfg, &new_cfg, sizeof(new_cfg)); - memcpy(&dsi->mode, adjusted_mode, sizeof(dsi->mode)); + drm_mode_copy(&dsi->mode, adjusted_mode); drm_mode_debug_printmodeline(adjusted_mode); if (pm_runtime_resume_and_get(dev) < 0) diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index 4befc104d220..a563460f8d20 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -2830,7 +2830,7 @@ static void dw_hdmi_bridge_mode_set(struct drm_bridge *bridge, mutex_lock(&hdmi->mutex); /* Store the display mode for plugin/DKMS poweron events */ - memcpy(&hdmi->previous_mode, mode, sizeof(hdmi->previous_mode)); + drm_mode_copy(&hdmi->previous_mode, mode); mutex_unlock(&hdmi->mutex); } diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index c23e0abc65e8..7f9574b17caa 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1312,7 +1312,7 @@ static void tc_bridge_mode_set(struct drm_bridge *bridge, { struct tc_data *tc = bridge_to_tc(bridge); - tc->mode = *mode; + drm_mode_copy(&tc->mode, mode); } static struct edid *tc_get_edid(struct drm_bridge *bridge, From 193c4df5b0dcbb7ea0efb99ca13bd05cd1adaddb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Feb 2022 12:03:50 +0200 Subject: [PATCH 00171/11454] drm/imx: Use drm_mode_duplicate() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the hand rolled drm_mode_duplicate() with the real thing. @is_dup@ @@ drm_mode_duplicate(...) { ... } @depends on !is_dup@ expression dev, oldmode; identifier newmode; @@ - newmode = drm_mode_create(dev); + newmode = drm_mode_duplicate(dev, oldmode); ... - drm_mode_copy(newmode, oldmode); Cc: Philipp Zabel Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220218100403.7028-10-ville.syrjala@linux.intel.com Reviewed-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-ldb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index e5078d03020d..c8cf819f39ce 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -150,10 +150,9 @@ static int imx_ldb_connector_get_modes(struct drm_connector *connector) if (imx_ldb_ch->mode_valid) { struct drm_display_mode *mode; - mode = drm_mode_create(connector->dev); + mode = drm_mode_duplicate(connector->dev, &imx_ldb_ch->mode); if (!mode) return -EINVAL; - drm_mode_copy(mode, &imx_ldb_ch->mode); mode->type |= DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_probed_add(connector, mode); num_modes++; From ec5d4a723b57721ca0f3c1c86576412e32a50579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Feb 2022 12:04:01 +0200 Subject: [PATCH 00172/11454] drm/panel: Use drm_mode_duplicate() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the hand rolled drm_mode_duplicate() with the real thing. @is_dup@ @@ drm_mode_duplicate(...) { ... } @depends on !is_dup@ expression dev, oldmode; identifier newmode; @@ - newmode = drm_mode_create(dev); + newmode = drm_mode_duplicate(dev, oldmode); ... - drm_mode_copy(newmode, oldmode); Signed-off-by: Ville Syrjälä Cc: Thierry Reding Cc: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220218100403.7028-21-ville.syrjala@linux.intel.com Acked-by: Sam Ravnborg --- drivers/gpu/drm/panel/panel-truly-nt35597.c | 3 +-- drivers/gpu/drm/panel/panel-visionox-rm69299.c | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-truly-nt35597.c b/drivers/gpu/drm/panel/panel-truly-nt35597.c index b24b92d93ea5..9ca5c7ff41d6 100644 --- a/drivers/gpu/drm/panel/panel-truly-nt35597.c +++ b/drivers/gpu/drm/panel/panel-truly-nt35597.c @@ -446,7 +446,7 @@ static int truly_nt35597_get_modes(struct drm_panel *panel, const struct nt35597_config *config; config = ctx->config; - mode = drm_mode_create(connector->dev); + mode = drm_mode_duplicate(connector->dev, config->dm); if (!mode) { dev_err(ctx->dev, "failed to create a new display mode\n"); return 0; @@ -454,7 +454,6 @@ static int truly_nt35597_get_modes(struct drm_panel *panel, connector->display_info.width_mm = config->width_mm; connector->display_info.height_mm = config->height_mm; - drm_mode_copy(mode, config->dm); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_probed_add(connector, mode); diff --git a/drivers/gpu/drm/panel/panel-visionox-rm69299.c b/drivers/gpu/drm/panel/panel-visionox-rm69299.c index eb43503ec97b..db2443ac81d3 100644 --- a/drivers/gpu/drm/panel/panel-visionox-rm69299.c +++ b/drivers/gpu/drm/panel/panel-visionox-rm69299.c @@ -168,7 +168,8 @@ static int visionox_rm69299_get_modes(struct drm_panel *panel, struct visionox_rm69299 *ctx = panel_to_ctx(panel); struct drm_display_mode *mode; - mode = drm_mode_create(connector->dev); + mode = drm_mode_duplicate(connector->dev, + &visionox_rm69299_1080x2248_60hz); if (!mode) { dev_err(ctx->panel.dev, "failed to create a new display mode\n"); return 0; @@ -176,7 +177,6 @@ static int visionox_rm69299_get_modes(struct drm_panel *panel, connector->display_info.width_mm = 74; connector->display_info.height_mm = 131; - drm_mode_copy(mode, &visionox_rm69299_1080x2248_60hz); mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; drm_mode_probed_add(connector, mode); From 5f1b97cb9af6c5471825b16306ad7da419cda563 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 11 Mar 2022 12:06:38 +0200 Subject: [PATCH 00173/11454] x86/gpu: include drm/i915_pciids.h directly in early quirks early-quirks.c is the only user of drm/i915_drm.h that also needs drm/i915_pciids.h. Include the masses of PCI ID macros only where needed. Cc: Bjorn Helgaas Cc: linux-pci@vger.kernel.org Cc: x86@kernel.org Signed-off-by: Jani Nikula Acked-by: Bjorn Helgaas Link: https://patchwork.freedesktop.org/patch/msgid/20220311100639.114685-1-jani.nikula@intel.com --- arch/x86/kernel/early-quirks.c | 1 + include/drm/i915_drm.h | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kernel/early-quirks.c b/arch/x86/kernel/early-quirks.c index bd6dad83c65b..805596736e20 100644 --- a/arch/x86/kernel/early-quirks.c +++ b/arch/x86/kernel/early-quirks.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index 6722005884db..afbf3ef5643e 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -26,7 +26,6 @@ #ifndef _I915_DRM_H_ #define _I915_DRM_H_ -#include #include /* For use by IPS driver */ From 144ce0ac634a38a123f970a62210da70b4ce662a Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 11 Mar 2022 14:54:58 -0800 Subject: [PATCH 00174/11454] drm/i915/sseu: Don't overallocate subslice storage Xe_HP removed "slice" as a first-class unit in the hardware design. Instead we now have a single pool of subslices (which are now referred to as "DSS") that different hardware units have different ways of grouping ("compute slices," "geometry slices," etc.). For the purposes of topology representation, we treat Xe_HP-based platforms as having a single slice that contains all of the platform's DSS. There's no need to allocate storage space for (max legacy slices * max dss); let's update some of our macros to minimize the storage requirement for sseu topology. We'll also document some of the constants to make it a little bit more clear what they represent. v2: - s/LEGACY/HSW/ in macro names. (Lucas) - Rename MAX() to SSEU_MAX() to avoid any potential clashes with other definitions elsewhere. Unfortunately max()/max_t() from linux/minmax.h cannot be used in this context. (Lucas) Signed-off-by: Matt Roper Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220311225459.385515-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/intel_engine_types.h | 2 +- drivers/gpu/drm/i915/gt/intel_sseu.h | 47 +++++++++++++++----- 2 files changed, 36 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h index 85c00025a2ff..eac20112709c 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_types.h +++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h @@ -646,7 +646,7 @@ intel_engine_has_relative_mmio(const struct intel_engine_cs * const engine) #define for_each_instdone_gslice_dss_xehp(dev_priv_, sseu_, iter_, gslice_, dss_) \ for ((iter_) = 0, (gslice_) = 0, (dss_) = 0; \ - (iter_) < GEN_MAX_SUBSLICES; \ + (iter_) < GEN_SS_MASK_SIZE; \ (iter_)++, (gslice_) = (iter_) / GEN_DSS_PER_GSLICE, \ (dss_) = (iter_) % GEN_DSS_PER_GSLICE) \ for_each_if(intel_sseu_has_subslice((sseu_), 0, (iter_))) diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h index 8a79cd8eaab4..b763b4e3dae6 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.h +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h @@ -15,26 +15,49 @@ struct drm_i915_private; struct intel_gt; struct drm_printer; -#define GEN_MAX_SLICES (3) /* SKL upper bound */ -#define GEN_MAX_SUBSLICES (32) /* XEHPSDV upper bound */ -#define GEN_SSEU_STRIDE(max_entries) DIV_ROUND_UP(max_entries, BITS_PER_BYTE) -#define GEN_MAX_SUBSLICE_STRIDE GEN_SSEU_STRIDE(GEN_MAX_SUBSLICES) -#define GEN_MAX_EUS (16) /* TGL upper bound */ -#define GEN_MAX_EU_STRIDE GEN_SSEU_STRIDE(GEN_MAX_EUS) +/* + * Maximum number of slices on older platforms. Slices no longer exist + * starting on Xe_HP ("gslices," "cslices," etc. are a different concept and + * are not expressed through fusing). + */ +#define GEN_MAX_HSW_SLICES 3 + +/* + * Maximum number of subslices that can exist within a HSW-style slice. This + * is only relevant to pre-Xe_HP platforms (Xe_HP and beyond use the + * GEN_MAX_DSS value below). + */ +#define GEN_MAX_SS_PER_HSW_SLICE 6 + +/* Maximum number of DSS on newer platforms (Xe_HP and beyond). */ +#define GEN_MAX_DSS 32 + +/* Maximum number of EUs that can exist within a subslice or DSS. */ +#define GEN_MAX_EUS_PER_SS 16 + +#define SSEU_MAX(a, b) ((a) > (b) ? (a) : (b)) + +/* The maximum number of bits needed to express each subslice/DSS independently */ +#define GEN_SS_MASK_SIZE SSEU_MAX(GEN_MAX_DSS, \ + GEN_MAX_HSW_SLICES * GEN_MAX_SS_PER_HSW_SLICE) + +#define GEN_SSEU_STRIDE(max_entries) DIV_ROUND_UP(max_entries, BITS_PER_BYTE) +#define GEN_MAX_SUBSLICE_STRIDE GEN_SSEU_STRIDE(GEN_SS_MASK_SIZE) +#define GEN_MAX_EU_STRIDE GEN_SSEU_STRIDE(GEN_MAX_EUS_PER_SS) #define GEN_DSS_PER_GSLICE 4 #define GEN_DSS_PER_CSLICE 8 #define GEN_DSS_PER_MSLICE 8 -#define GEN_MAX_GSLICES (GEN_MAX_SUBSLICES / GEN_DSS_PER_GSLICE) -#define GEN_MAX_CSLICES (GEN_MAX_SUBSLICES / GEN_DSS_PER_CSLICE) +#define GEN_MAX_GSLICES (GEN_MAX_DSS / GEN_DSS_PER_GSLICE) +#define GEN_MAX_CSLICES (GEN_MAX_DSS / GEN_DSS_PER_CSLICE) struct sseu_dev_info { u8 slice_mask; - u8 subslice_mask[GEN_MAX_SLICES * GEN_MAX_SUBSLICE_STRIDE]; - u8 geometry_subslice_mask[GEN_MAX_SLICES * GEN_MAX_SUBSLICE_STRIDE]; - u8 compute_subslice_mask[GEN_MAX_SLICES * GEN_MAX_SUBSLICE_STRIDE]; - u8 eu_mask[GEN_MAX_SLICES * GEN_MAX_SUBSLICES * GEN_MAX_EU_STRIDE]; + u8 subslice_mask[GEN_SS_MASK_SIZE]; + u8 geometry_subslice_mask[GEN_SS_MASK_SIZE]; + u8 compute_subslice_mask[GEN_SS_MASK_SIZE]; + u8 eu_mask[GEN_SS_MASK_SIZE * GEN_MAX_EU_STRIDE]; u16 eu_total; u8 eu_per_subslice; u8 min_eu_in_pool; From cc1338f259a21afd09aaaa011b87f3b83388d545 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Fri, 11 Mar 2022 14:54:59 -0800 Subject: [PATCH 00175/11454] drm/i915/xehp: Update topology dumps for Xe_HP When running on Xe_HP or beyond, let's use an updated format for describing topology in our error state dumps and debugfs to give a more accurate view of the hardware: - Just report DSS directly without the legacy "slice0" output that's no longer meaningful. - Indicate whether each DSS is accessible for geometry and/or compute. - Rename "rcs_topology" to "sseu_topology" since the information reported is common to both RCS and CCS engines now. v2: - Name static functions in a more consistent manner. (Lucas) Signed-off-by: Matt Roper Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220311225459.385515-2-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/intel_sseu.c | 54 ++++++++++++++++---- drivers/gpu/drm/i915/gt/intel_sseu.h | 3 +- drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c | 8 +-- drivers/gpu/drm/i915/i915_gpu_error.c | 2 +- 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.c b/drivers/gpu/drm/i915/gt/intel_sseu.c index 4ac0bbaf0c31..726d48b24ae7 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.c +++ b/drivers/gpu/drm/i915/gt/intel_sseu.c @@ -8,6 +8,8 @@ #include "intel_gt_regs.h" #include "intel_sseu.h" +#include "linux/string_helpers.h" + void intel_sseu_set_info(struct sseu_dev_info *sseu, u8 max_slices, u8 max_subslices, u8 max_eus_per_subslice) { @@ -33,8 +35,8 @@ intel_sseu_subslice_total(const struct sseu_dev_info *sseu) } static u32 -_intel_sseu_get_subslices(const struct sseu_dev_info *sseu, - const u8 *subslice_mask, u8 slice) +sseu_get_subslices(const struct sseu_dev_info *sseu, + const u8 *subslice_mask, u8 slice) { int i, offset = slice * sseu->ss_stride; u32 mask = 0; @@ -49,12 +51,17 @@ _intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u32 intel_sseu_get_subslices(const struct sseu_dev_info *sseu, u8 slice) { - return _intel_sseu_get_subslices(sseu, sseu->subslice_mask, slice); + return sseu_get_subslices(sseu, sseu->subslice_mask, slice); +} + +static u32 sseu_get_geometry_subslices(const struct sseu_dev_info *sseu) +{ + return sseu_get_subslices(sseu, sseu->geometry_subslice_mask, 0); } u32 intel_sseu_get_compute_subslices(const struct sseu_dev_info *sseu) { - return _intel_sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0); + return sseu_get_subslices(sseu, sseu->compute_subslice_mask, 0); } void intel_sseu_set_subslices(struct sseu_dev_info *sseu, int slice, @@ -717,16 +724,11 @@ void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p) drm_printf(p, "has EU power gating: %s\n", yesno(sseu->has_eu_pg)); } -void intel_sseu_print_topology(const struct sseu_dev_info *sseu, - struct drm_printer *p) +static void sseu_print_hsw_topology(const struct sseu_dev_info *sseu, + struct drm_printer *p) { int s, ss; - if (sseu->max_slices == 0) { - drm_printf(p, "Unavailable\n"); - return; - } - for (s = 0; s < sseu->max_slices; s++) { drm_printf(p, "slice%d: %u subslice(s) (0x%08x):\n", s, intel_sseu_subslices_per_slice(sseu, s), @@ -741,6 +743,36 @@ void intel_sseu_print_topology(const struct sseu_dev_info *sseu, } } +static void sseu_print_xehp_topology(const struct sseu_dev_info *sseu, + struct drm_printer *p) +{ + u32 g_dss_mask = sseu_get_geometry_subslices(sseu); + u32 c_dss_mask = intel_sseu_get_compute_subslices(sseu); + int dss; + + for (dss = 0; dss < sseu->max_subslices; dss++) { + u16 enabled_eus = sseu_get_eus(sseu, 0, dss); + + drm_printf(p, "DSS_%02d: G:%3s C:%3s, %2u EUs (0x%04hx)\n", dss, + str_yes_no(g_dss_mask & BIT(dss)), + str_yes_no(c_dss_mask & BIT(dss)), + hweight16(enabled_eus), enabled_eus); + } +} + +void intel_sseu_print_topology(struct drm_i915_private *i915, + const struct sseu_dev_info *sseu, + struct drm_printer *p) +{ + if (sseu->max_slices == 0) { + drm_printf(p, "Unavailable\n"); + } else if (GRAPHICS_VER_FULL(i915) >= IP_VER(12, 50)) { + sseu_print_xehp_topology(sseu, p); + } else { + sseu_print_hsw_topology(sseu, p); + } +} + u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice) { u16 slice_mask = 0; diff --git a/drivers/gpu/drm/i915/gt/intel_sseu.h b/drivers/gpu/drm/i915/gt/intel_sseu.h index b763b4e3dae6..5c078df4729c 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu.h +++ b/drivers/gpu/drm/i915/gt/intel_sseu.h @@ -139,7 +139,8 @@ u32 intel_sseu_make_rpcs(struct intel_gt *gt, const struct intel_sseu *req_sseu); void intel_sseu_dump(const struct sseu_dev_info *sseu, struct drm_printer *p); -void intel_sseu_print_topology(const struct sseu_dev_info *sseu, +void intel_sseu_print_topology(struct drm_i915_private *i915, + const struct sseu_dev_info *sseu, struct drm_printer *p); u16 intel_slicemask_from_dssmask(u64 dss_mask, int dss_per_slice); diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c index 903626f106ea..1e199c09fc9c 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c @@ -285,22 +285,22 @@ static int sseu_status_show(struct seq_file *m, void *unused) } DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(sseu_status); -static int rcs_topology_show(struct seq_file *m, void *unused) +static int sseu_topology_show(struct seq_file *m, void *unused) { struct intel_gt *gt = m->private; struct drm_printer p = drm_seq_file_printer(m); - intel_sseu_print_topology(>->info.sseu, &p); + intel_sseu_print_topology(gt->i915, >->info.sseu, &p); return 0; } -DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(rcs_topology); +DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(sseu_topology); void intel_sseu_debugfs_register(struct intel_gt *gt, struct dentry *root) { static const struct intel_gt_debugfs_file files[] = { { "sseu_status", &sseu_status_fops, NULL }, - { "rcs_topology", &rcs_topology_fops, NULL }, + { "sseu_topology", &sseu_topology_fops, NULL }, }; intel_gt_debugfs_register_files(root, files, ARRAY_SIZE(files), gt); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 4725d67343a5..81f70099525a 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -710,7 +710,7 @@ static void err_print_gt_info(struct drm_i915_error_state_buf *m, struct drm_printer p = i915_error_printer(m); intel_gt_info_print(>->info, &p); - intel_sseu_print_topology(>->info.sseu, &p); + intel_sseu_print_topology(gt->_gt->i915, >->info.sseu, &p); } static void err_print_gt(struct drm_i915_error_state_buf *m, From 776c6c8343b94f3760eb7eff69f107e6f5eaca74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Mon, 14 Mar 2022 08:27:53 -0700 Subject: [PATCH 00176/11454] drm/i915/display/adlp: Update eDP voltage swing table MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Up to now alderlake-p was using the same eDP voltage swing table for frequencies up to HBR2 as icelake but now it has its own table. BSpec: 49291 Cc: Clinton A Taylor Signed-off-by: José Roberto de Souza Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220314152753.85081-1-jose.souza@intel.com --- .../gpu/drm/i915/display/intel_ddi_buf_trans.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index 0c32210bf503..2ed52763fcf2 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -931,6 +931,20 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_hbr3[ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */ }; +static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_edp_hbr2[] = { + /* NT mV Trans mV db */ + { .icl = { 0x4, 0x50, 0x38, 0x00, 0x07 } }, /* 200 200 0.0 */ + { .icl = { 0x4, 0x58, 0x35, 0x00, 0x0A } }, /* 200 250 1.9 */ + { .icl = { 0x4, 0x60, 0x34, 0x00, 0x0B } }, /* 200 300 3.5 */ + { .icl = { 0x4, 0x6A, 0x32, 0x00, 0x0D } }, /* 200 350 4.9 */ + { .icl = { 0x4, 0x5E, 0x38, 0x00, 0x07 } }, /* 250 250 0.0 */ + { .icl = { 0x4, 0x61, 0x36, 0x00, 0x09 } }, /* 250 300 1.6 */ + { .icl = { 0x4, 0x6B, 0x34, 0x00, 0x0B } }, /* 250 350 2.9 */ + { .icl = { 0x4, 0x69, 0x39, 0x00, 0x06 } }, /* 300 300 0.0 */ + { .icl = { 0x4, 0x73, 0x37, 0x00, 0x08 } }, /* 300 350 1.3 */ + { .icl = { 0x4, 0x7A, 0x38, 0x00, 0x07 } }, /* 350 350 0.0 */ +}; + static const struct intel_ddi_buf_trans adlp_combo_phy_trans_dp_hbr2_hbr3 = { .entries = _adlp_combo_phy_trans_dp_hbr2_hbr3, .num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_dp_hbr2_hbr3), @@ -942,8 +956,8 @@ static const struct intel_ddi_buf_trans adlp_combo_phy_trans_edp_hbr3 = { }; static const struct intel_ddi_buf_trans adlp_combo_phy_trans_edp_up_to_hbr2 = { - .entries = _icl_combo_phy_trans_edp_hbr2, - .num_entries = ARRAY_SIZE(_icl_combo_phy_trans_edp_hbr2), + .entries = _adlp_combo_phy_trans_edp_hbr2, + .num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_edp_hbr2), }; static const union intel_ddi_buf_trans_entry _adlp_dkl_phy_trans_dp_hbr[] = { From dee5488737dcfde8db61a44dd2b410d9fc4cbc8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:13 +0200 Subject: [PATCH 00177/11454] drm/i915/dsi: Pass fixed_mode to *_dsi_add_properties() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to eventually get rid of the connector->panel.fixed_mode pointer so avoid using it during DSI property setup. Since this all happens during the encoder init we already have the fixed_mode around, just pass that in. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/icl_dsi.c | 11 ++++++----- drivers/gpu/drm/i915/display/vlv_dsi.c | 9 +++++---- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 13b07c6fd6be..00cae5d26637 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1965,7 +1965,8 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi) intel_dsi_log_params(intel_dsi); } -static void icl_dsi_add_properties(struct intel_connector *connector) +static void icl_dsi_add_properties(struct intel_connector *connector, + const struct drm_display_mode *fixed_mode) { u32 allowed_scalers; @@ -1979,9 +1980,9 @@ static void icl_dsi_add_properties(struct intel_connector *connector) connector->base.state->scaling_mode = DRM_MODE_SCALE_ASPECT; drm_connector_set_panel_orientation_with_quirk(&connector->base, - intel_dsi_get_panel_orientation(connector), - connector->panel.fixed_mode->hdisplay, - connector->panel.fixed_mode->vdisplay); + intel_dsi_get_panel_orientation(connector), + fixed_mode->hdisplay, + fixed_mode->vdisplay); } void icl_dsi_init(struct drm_i915_private *dev_priv) @@ -2084,7 +2085,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) icl_dphy_param_init(intel_dsi); - icl_dsi_add_properties(intel_connector); + icl_dsi_add_properties(intel_connector, fixed_mode); return; err: diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 0d936f658b3f..c87a6e729a3c 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1657,7 +1657,8 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = { .atomic_duplicate_state = intel_digital_connector_duplicate_state, }; -static void vlv_dsi_add_properties(struct intel_connector *connector) +static void vlv_dsi_add_properties(struct intel_connector *connector, + const struct drm_display_mode *fixed_mode) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); u32 allowed_scalers; @@ -1673,8 +1674,8 @@ static void vlv_dsi_add_properties(struct intel_connector *connector) drm_connector_set_panel_orientation_with_quirk(&connector->base, intel_dsi_get_panel_orientation(connector), - connector->panel.fixed_mode->hdisplay, - connector->panel.fixed_mode->vdisplay); + fixed_mode->hdisplay, + fixed_mode->vdisplay); } #define NS_KHZ_RATIO 1000000 @@ -1989,7 +1990,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) intel_panel_init(&intel_connector->panel, fixed_mode, NULL); intel_backlight_setup(intel_connector, INVALID_PIPE); - vlv_dsi_add_properties(intel_connector); + vlv_dsi_add_properties(intel_connector, fixed_mode); return; From 54b6af690925f79eb1cbb6f3b7e39b52fc5391eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:14 +0200 Subject: [PATCH 00178/11454] drm/i915/sdvo: Pass the requesed mode to intel_sdvo_create_preferred_input_timing() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to stop using connector->panel.fixed_mode directtly. In order to look it up in the future we'll need to have the requested mode around, so pass that in fully (instead of just passing bits of it). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_sdvo.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 76e1188b01d4..129f6619c3a1 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -783,24 +783,22 @@ static bool intel_sdvo_get_input_timing(struct intel_sdvo *intel_sdvo, static bool intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo, struct intel_sdvo_connector *intel_sdvo_connector, - u16 clock, - u16 width, - u16 height) + const struct drm_display_mode *mode) { struct intel_sdvo_preferred_input_timing_args args; memset(&args, 0, sizeof(args)); - args.clock = clock; - args.width = width; - args.height = height; + args.clock = mode->clock / 10; + args.width = mode->hdisplay; + args.height = mode->vdisplay; args.interlace = 0; if (IS_LVDS(intel_sdvo_connector)) { const struct drm_display_mode *fixed_mode = intel_sdvo_connector->base.panel.fixed_mode; - if (fixed_mode->hdisplay != width || - fixed_mode->vdisplay != height) + if (fixed_mode->hdisplay != args.width || + fixed_mode->vdisplay != args.height) args.scaled = 1; } @@ -1236,9 +1234,7 @@ intel_sdvo_get_preferred_input_mode(struct intel_sdvo *intel_sdvo, if (!intel_sdvo_create_preferred_input_timing(intel_sdvo, intel_sdvo_connector, - mode->clock / 10, - mode->hdisplay, - mode->vdisplay)) + mode)) return false; if (!intel_sdvo_get_preferred_input_timing(intel_sdvo, From 457e992b35089ec6ffb4a95cd2a4a5ce001ad219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:15 +0200 Subject: [PATCH 00179/11454] drm/i915/lvds: Pass fixed_mode to compute_is_dual_link_lvds() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We want to eventually get rid of the connector->panel.fixed_mode pointer so avoid using it during LVDS setup. Since this all happens during the encoder init we already have the fixed_mode around, just pass that in. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_lvds.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 9fced37bed70..dd7292d3c88e 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -784,7 +784,8 @@ bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv) return encoder && to_lvds_encoder(&encoder->base)->is_dual_link; } -static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) +static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder, + const struct drm_display_mode *fixed_mode) { struct drm_device *dev = lvds_encoder->base.base.dev; unsigned int val; @@ -795,7 +796,7 @@ static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) return dev_priv->params.lvds_channel_mode == 2; /* single channel LVDS is limited to 112 MHz */ - if (lvds_encoder->attached_connector->panel.fixed_mode->clock > 112999) + if (fixed_mode->clock > 112999) return true; if (dmi_check_system(intel_dual_link_lvds)) @@ -1004,7 +1005,7 @@ out: intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode); intel_backlight_setup(intel_connector, INVALID_PIPE); - lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder); + lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder, fixed_mode); drm_dbg_kms(&dev_priv->drm, "detected %s-link lvds configuration\n", lvds_encoder->is_dual_link ? "dual" : "single"); From 0032cfd670203a12b96985601ccf0ca1b818ef58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:16 +0200 Subject: [PATCH 00180/11454] drm/i915: Simplify intel_panel_info() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No need for all this connector type special casing. If the connector has a fixed mode just print it, otherwise don't. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- .../drm/i915/display/intel_display_debugfs.c | 24 +++++++------------ 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 798bf233a60f..e511500ee26a 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -544,11 +544,15 @@ static void intel_encoder_info(struct seq_file *m, drm_connector_list_iter_end(&conn_iter); } -static void intel_panel_info(struct seq_file *m, struct intel_panel *panel) +static void intel_panel_info(struct seq_file *m, + struct intel_connector *connector) { - const struct drm_display_mode *mode = panel->fixed_mode; + const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode; - seq_printf(m, "\tfixed mode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode)); + if (!fixed_mode) + return; + + seq_printf(m, "\tfixed mode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(fixed_mode)); } static void intel_hdcp_info(struct seq_file *m, @@ -586,8 +590,6 @@ static void intel_dp_info(struct seq_file *m, seq_printf(m, "\tDPCD rev: %x\n", intel_dp->dpcd[DP_DPCD_REV]); seq_printf(m, "\taudio support: %s\n", str_yes_no(intel_dp->has_audio)); - if (intel_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP) - intel_panel_info(m, &intel_connector->panel); drm_dp_downstream_debug(m, intel_dp->dpcd, intel_dp->downstream_ports, edid ? edid->data : NULL, &intel_dp->aux); @@ -611,12 +613,6 @@ static void intel_hdmi_info(struct seq_file *m, str_yes_no(intel_hdmi->has_audio)); } -static void intel_lvds_info(struct seq_file *m, - struct intel_connector *intel_connector) -{ - intel_panel_info(m, &intel_connector->panel); -} - static void intel_connector_info(struct seq_file *m, struct drm_connector *connector) { @@ -651,10 +647,6 @@ static void intel_connector_info(struct seq_file *m, else intel_dp_info(m, intel_connector); break; - case DRM_MODE_CONNECTOR_LVDS: - if (encoder->type == INTEL_OUTPUT_LVDS) - intel_lvds_info(m, intel_connector); - break; case DRM_MODE_CONNECTOR_HDMIA: if (encoder->type == INTEL_OUTPUT_HDMI || encoder->type == INTEL_OUTPUT_DDI) @@ -667,6 +659,8 @@ static void intel_connector_info(struct seq_file *m, seq_puts(m, "\tHDCP version: "); intel_hdcp_info(m, intel_connector); + intel_panel_info(m, intel_connector); + seq_printf(m, "\tmodes:\n"); list_for_each_entry(mode, &connector->modes, head) intel_seq_print_mode(m, 2, mode); From c25300f0797be30dd63d74fcc38b5238a2844932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:17 +0200 Subject: [PATCH 00181/11454] drm/i915: Nuke dev_priv->drrs.type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When we found a downclock mode dev_priv->drrs.type is just a straight copy of dev_priv->vbt.drrs_type. And in case we couldn't find a downclock mode can_enable_drrs() won't let us enable DRRS anyway so the minor distinction between the two is irrelevant. So let's just nuke dev_priv->drrs.type and consult the VBT version directly. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 +- drivers/gpu/drm/i915/display/intel_drrs.c | 10 ++++------ drivers/gpu/drm/i915/i915_drv.h | 1 - 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index e511500ee26a..2a6fd15b1471 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1156,7 +1156,7 @@ static void drrs_status_per_crtc(struct seq_file *m, seq_printf(m, "%s:\n", connector->name); if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && - drrs->type == DRRS_TYPE_SEAMLESS) + dev_priv->vbt.drrs_type == DRRS_TYPE_SEAMLESS) supported = true; seq_printf(m, "\tDRRS Supported: %s\n", str_yes_no(supported)); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index c97b5dee8cae..4afbc903f169 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -65,7 +65,7 @@ static bool can_enable_drrs(struct intel_connector *connector, return false; return connector->panel.downclock_mode && - i915->drrs.type == DRRS_TYPE_SEAMLESS; + i915->vbt.drrs_type == DRRS_TYPE_SEAMLESS; } void @@ -154,7 +154,7 @@ static void intel_drrs_set_state(struct drm_i915_private *dev_priv, return; } - if (dev_priv->drrs.type != DRRS_TYPE_SEAMLESS) { + if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) { drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n"); return; } @@ -269,7 +269,7 @@ intel_drrs_update(struct intel_dp *intel_dp, { struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); - if (dev_priv->drrs.type != DRRS_TYPE_SEAMLESS) + if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) return; mutex_lock(&dev_priv->drrs.mutex); @@ -325,7 +325,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, struct drm_crtc *crtc; enum pipe pipe; - if (dev_priv->drrs.type != DRRS_TYPE_SEAMLESS) + if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) return; cancel_delayed_work(&dev_priv->drrs.work); @@ -460,8 +460,6 @@ intel_drrs_init(struct intel_connector *connector, return NULL; } - dev_priv->drrs.type = dev_priv->vbt.drrs_type; - dev_priv->drrs.refresh_rate = DRRS_REFRESH_RATE_HIGH; drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] seamless DRRS supported\n", diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index bd9bff25c54a..643e05bf6a80 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -213,7 +213,6 @@ struct i915_drrs { struct intel_dp *dp; unsigned busy_frontbuffer_bits; enum drrs_refresh_rate refresh_rate; - enum drrs_type type; }; #define QUIRK_LVDS_SSC_DISABLE (1<<1) From 092706786e1143fa947f7387600d275113a4043c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:18 +0200 Subject: [PATCH 00182/11454] drm/i915: Introduce intel_panel_{fixed,downclock}_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Abstract away the details on where we store the fixed/downclock modes, and also how we select them. Will be useful for static DRRS (aka. allowing the user to select the refresh rate for the panel). We pass in the user requested mode to intel_panel_fixed_mode() so that in the future it may try to match the refresh rate. And intel_panel_downclock_mode() gets passed the adjusted_mode we actually chose to use so that it may find a suitable lower resresh rate variant. v2: Hook it up for all encoders s/fixed_mode/adjusted_mode/ in intel_panel_downclock_mode() (Jani) Elaborate on the choice or arguments for the functions (Jani) Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 7 +++++-- drivers/gpu/drm/i915/display/intel_drrs.c | 11 +++++++---- drivers/gpu/drm/i915/display/intel_dsi.c | 3 ++- drivers/gpu/drm/i915/display/intel_dvo.c | 6 +++--- drivers/gpu/drm/i915/display/intel_lvds.c | 3 ++- drivers/gpu/drm/i915/display/intel_panel.c | 20 ++++++++++++++++++-- drivers/gpu/drm/i915/display/intel_panel.h | 8 ++++++-- drivers/gpu/drm/i915/display/intel_sdvo.c | 20 ++++++++++++-------- 8 files changed, 55 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 619546441eae..92a2651a71a7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -918,8 +918,8 @@ intel_dp_mode_valid(struct drm_connector *connector, { struct intel_dp *intel_dp = intel_attached_dp(to_intel_connector(connector)); struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; struct drm_i915_private *dev_priv = to_i915(connector->dev); + const struct drm_display_mode *fixed_mode; int target_clock = mode->clock; int max_rate, mode_rate, max_lanes, max_link_clock; int max_dotclk = dev_priv->max_dotclk_freq; @@ -934,6 +934,7 @@ intel_dp_mode_valid(struct drm_connector *connector, if (mode->flags & DRM_MODE_FLAG_DBLCLK) return MODE_H_ILLEGAL; + fixed_mode = intel_panel_fixed_mode(intel_connector, mode); if (intel_dp_is_edp(intel_dp) && fixed_mode) { status = intel_panel_mode_valid(intel_connector, mode); if (status != MODE_OK) @@ -1797,6 +1798,7 @@ intel_dp_compute_config(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); + const struct drm_display_mode *fixed_mode; enum port port = encoder->port; struct intel_connector *intel_connector = intel_dp->attached_connector; struct intel_digital_connector_state *intel_conn_state = @@ -1823,7 +1825,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, else pipe_config->has_audio = intel_conn_state->force_audio == HDMI_AUDIO_ON; - if (intel_dp_is_edp(intel_dp) && intel_connector->panel.fixed_mode) { + fixed_mode = intel_panel_fixed_mode(intel_connector, adjusted_mode); + if (intel_dp_is_edp(intel_dp) && fixed_mode) { ret = intel_panel_compute_config(intel_connector, adjusted_mode); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 4afbc903f169..2a58bf4cb6cd 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -48,7 +48,8 @@ */ static bool can_enable_drrs(struct intel_connector *connector, - const struct intel_crtc_state *pipe_config) + const struct intel_crtc_state *pipe_config, + const struct drm_display_mode *downclock_mode) { const struct drm_i915_private *i915 = to_i915(connector->base.dev); @@ -64,7 +65,7 @@ static bool can_enable_drrs(struct intel_connector *connector, if (pipe_config->has_psr) return false; - return connector->panel.downclock_mode && + return downclock_mode && i915->vbt.drrs_type == DRRS_TYPE_SEAMLESS; } @@ -75,9 +76,11 @@ intel_drrs_compute_config(struct intel_dp *intel_dp, { struct intel_connector *connector = intel_dp->attached_connector; struct drm_i915_private *i915 = to_i915(connector->base.dev); + const struct drm_display_mode *downclock_mode = + intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); int pixel_clock; - if (!can_enable_drrs(connector, pipe_config)) { + if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder)) intel_zero_m_n(&pipe_config->dp_m2_n2); return; @@ -88,7 +91,7 @@ intel_drrs_compute_config(struct intel_dp *intel_dp, pipe_config->has_drrs = true; - pixel_clock = connector->panel.downclock_mode->clock; + pixel_clock = downclock_mode->clock; if (pipe_config->splitter.enable) pixel_clock /= pipe_config->splitter.link_count; diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c index a50422e03a7e..37f280b1f179 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.c +++ b/drivers/gpu/drm/i915/display/intel_dsi.c @@ -61,7 +61,8 @@ enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, { struct drm_i915_private *dev_priv = to_i915(connector->dev); struct intel_connector *intel_connector = to_intel_connector(connector); - const struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; + const struct drm_display_mode *fixed_mode = + intel_panel_fixed_mode(intel_connector, mode); int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; enum drm_mode_status status; diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 2eeb209afc64..0367e6a1bac7 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -226,7 +226,7 @@ intel_dvo_mode_valid(struct drm_connector *connector, struct intel_connector *intel_connector = to_intel_connector(connector); struct intel_dvo *intel_dvo = intel_attached_dvo(intel_connector); const struct drm_display_mode *fixed_mode = - intel_connector->panel.fixed_mode; + intel_panel_fixed_mode(intel_connector, mode); int max_dotclk = to_i915(connector->dev)->max_dotclk_freq; int target_clock = mode->clock; @@ -257,9 +257,9 @@ static int intel_dvo_compute_config(struct intel_encoder *encoder, { struct intel_dvo *intel_dvo = enc_to_dvo(encoder); struct intel_connector *connector = to_intel_connector(conn_state->connector); - const struct drm_display_mode *fixed_mode = - intel_dvo->attached_connector->panel.fixed_mode; struct drm_display_mode *adjusted_mode = &pipe_config->hw.adjusted_mode; + const struct drm_display_mode *fixed_mode = + intel_panel_fixed_mode(intel_dvo->attached_connector, adjusted_mode); /* * If we have timings from the BIOS for the panel, put them in diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index dd7292d3c88e..3842417e06b0 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -389,7 +389,8 @@ intel_lvds_mode_valid(struct drm_connector *connector, struct drm_display_mode *mode) { struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_display_mode *fixed_mode = intel_connector->panel.fixed_mode; + const struct drm_display_mode *fixed_mode = + intel_panel_fixed_mode(intel_connector, mode); int max_pixclk = to_i915(connector->dev)->max_dotclk_freq; enum drm_mode_status status; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 6cd6d4fdd5ad..3ad246791da5 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -45,10 +45,25 @@ bool intel_panel_use_ssc(struct drm_i915_private *i915) && !(i915->quirks & QUIRK_LVDS_SSC_DISABLE); } +const struct drm_display_mode * +intel_panel_fixed_mode(struct intel_connector *connector, + const struct drm_display_mode *mode) +{ + return connector->panel.fixed_mode; +} + +const struct drm_display_mode * +intel_panel_downclock_mode(struct intel_connector *connector, + const struct drm_display_mode *adjusted_mode) +{ + return connector->panel.downclock_mode; +} + int intel_panel_compute_config(struct intel_connector *connector, struct drm_display_mode *adjusted_mode) { - const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode; + const struct drm_display_mode *fixed_mode = + intel_panel_fixed_mode(connector, adjusted_mode); if (!fixed_mode) return 0; @@ -508,7 +523,8 @@ enum drm_mode_status intel_panel_mode_valid(struct intel_connector *connector, const struct drm_display_mode *mode) { - const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode; + const struct drm_display_mode *fixed_mode = + intel_panel_fixed_mode(connector, mode); if (!fixed_mode) return MODE_OK; diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index d50b3f7e9e58..7ce7e995853f 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -24,8 +24,12 @@ void intel_panel_fini(struct intel_panel *panel); enum drm_connector_status intel_panel_detect(struct drm_connector *connector, bool force); bool intel_panel_use_ssc(struct drm_i915_private *i915); -void intel_panel_fixed_mode(const struct drm_display_mode *fixed_mode, - struct drm_display_mode *adjusted_mode); +const struct drm_display_mode * +intel_panel_fixed_mode(struct intel_connector *connector, + const struct drm_display_mode *mode); +const struct drm_display_mode * +intel_panel_downclock_mode(struct intel_connector *connector, + const struct drm_display_mode *adjusted_mode); enum drm_mode_status intel_panel_mode_valid(struct intel_connector *connector, const struct drm_display_mode *mode); diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 129f6619c3a1..04487b03b640 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -795,7 +795,7 @@ intel_sdvo_create_preferred_input_timing(struct intel_sdvo *intel_sdvo, if (IS_LVDS(intel_sdvo_connector)) { const struct drm_display_mode *fixed_mode = - intel_sdvo_connector->base.panel.fixed_mode; + intel_panel_fixed_mode(&intel_sdvo_connector->base, mode); if (fixed_mode->hdisplay != args.width || fixed_mode->vdisplay != args.height) @@ -1331,6 +1331,8 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, adjusted_mode); pipe_config->sdvo_tv_clock = true; } else if (IS_LVDS(intel_sdvo_connector)) { + const struct drm_display_mode *fixed_mode = + intel_panel_fixed_mode(&intel_sdvo_connector->base, mode); int ret; ret = intel_panel_compute_config(&intel_sdvo_connector->base, @@ -1338,8 +1340,7 @@ static int intel_sdvo_compute_config(struct intel_encoder *encoder, if (ret) return ret; - if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, - intel_sdvo_connector->base.panel.fixed_mode)) + if (!intel_sdvo_set_output_timings_from_mode(intel_sdvo, fixed_mode)) return -EINVAL; (void) intel_sdvo_get_preferred_input_mode(intel_sdvo, @@ -1461,7 +1462,7 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state, const struct drm_display_mode *adjusted_mode = &crtc_state->hw.adjusted_mode; const struct intel_sdvo_connector_state *sdvo_state = to_intel_sdvo_connector_state(conn_state); - const struct intel_sdvo_connector *intel_sdvo_connector = + struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(conn_state->connector); const struct drm_display_mode *mode = &crtc_state->hw.mode; struct intel_sdvo *intel_sdvo = to_sdvo(intel_encoder); @@ -1492,11 +1493,14 @@ static void intel_sdvo_pre_enable(struct intel_atomic_state *state, return; /* lvds has a special fixed output timing. */ - if (IS_LVDS(intel_sdvo_connector)) - intel_sdvo_get_dtd_from_mode(&output_dtd, - intel_sdvo_connector->base.panel.fixed_mode); - else + if (IS_LVDS(intel_sdvo_connector)) { + const struct drm_display_mode *fixed_mode = + intel_panel_fixed_mode(&intel_sdvo_connector->base, mode); + + intel_sdvo_get_dtd_from_mode(&output_dtd, fixed_mode); + } else { intel_sdvo_get_dtd_from_mode(&output_dtd, mode); + } if (!intel_sdvo_set_output_timing(intel_sdvo, &output_dtd)) drm_info(&dev_priv->drm, "Setting output timings on %s failed\n", From 53f64f3a24c115bac05a7a343282623005a16c90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:19 +0200 Subject: [PATCH 00183/11454] drm/i915: Introduce intel_panel_get_modes() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Several connectors want to return the fixed_mode from .get_modes(), add a helper to do that (and hide the details inside intel_panel.c). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 13 ++----------- drivers/gpu/drm/i915/display/intel_dsi.c | 21 +-------------------- drivers/gpu/drm/i915/display/intel_dvo.c | 14 +------------- drivers/gpu/drm/i915/display/intel_lvds.c | 9 +-------- drivers/gpu/drm/i915/display/intel_panel.c | 18 ++++++++++++++++++ drivers/gpu/drm/i915/display/intel_panel.h | 1 + 6 files changed, 24 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 92a2651a71a7..3c97cd5853cc 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4588,17 +4588,8 @@ static int intel_dp_get_modes(struct drm_connector *connector) } /* Also add fixed mode, which may or may not be present in EDID */ - if (intel_dp_is_edp(intel_attached_dp(intel_connector)) && - intel_connector->panel.fixed_mode) { - struct drm_display_mode *mode; - - mode = drm_mode_duplicate(connector->dev, - intel_connector->panel.fixed_mode); - if (mode) { - drm_mode_probed_add(connector, mode); - num_modes++; - } - } + if (intel_dp_is_edp(intel_attached_dp(intel_connector))) + num_modes += intel_panel_get_modes(intel_connector); if (num_modes) return num_modes; diff --git a/drivers/gpu/drm/i915/display/intel_dsi.c b/drivers/gpu/drm/i915/display/intel_dsi.c index 37f280b1f179..389a8c24cdc1 100644 --- a/drivers/gpu/drm/i915/display/intel_dsi.c +++ b/drivers/gpu/drm/i915/display/intel_dsi.c @@ -34,26 +34,7 @@ int intel_dsi_tlpx_ns(const struct intel_dsi *intel_dsi) int intel_dsi_get_modes(struct drm_connector *connector) { - struct drm_i915_private *i915 = to_i915(connector->dev); - struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_display_mode *mode; - - drm_dbg_kms(&i915->drm, "\n"); - - if (!intel_connector->panel.fixed_mode) { - drm_dbg_kms(&i915->drm, "no fixed mode\n"); - return 0; - } - - mode = drm_mode_duplicate(connector->dev, - intel_connector->panel.fixed_mode); - if (!mode) { - drm_dbg_kms(&i915->drm, "drm_mode_duplicate failed\n"); - return 0; - } - - drm_mode_probed_add(connector, mode); - return 1; + return intel_panel_get_modes(to_intel_connector(connector)); } enum drm_mode_status intel_dsi_mode_valid(struct drm_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 0367e6a1bac7..d4670889d26c 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -333,8 +333,6 @@ intel_dvo_detect(struct drm_connector *connector, bool force) static int intel_dvo_get_modes(struct drm_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->dev); - const struct drm_display_mode *fixed_mode = - to_intel_connector(connector)->panel.fixed_mode; int num_modes; /* @@ -348,17 +346,7 @@ static int intel_dvo_get_modes(struct drm_connector *connector) if (num_modes) return num_modes; - if (fixed_mode) { - struct drm_display_mode *mode; - - mode = drm_mode_duplicate(connector->dev, fixed_mode); - if (mode) { - drm_mode_probed_add(connector, mode); - num_modes++; - } - } - - return num_modes; + return intel_panel_get_modes(to_intel_connector(connector)); } static const struct drm_connector_funcs intel_dvo_connector_funcs = { diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 3842417e06b0..5449d69fbae5 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -476,19 +476,12 @@ static int intel_lvds_compute_config(struct intel_encoder *intel_encoder, static int intel_lvds_get_modes(struct drm_connector *connector) { struct intel_connector *intel_connector = to_intel_connector(connector); - struct drm_device *dev = connector->dev; - struct drm_display_mode *mode; /* use cached edid if we have one */ if (!IS_ERR_OR_NULL(intel_connector->edid)) return drm_add_edid_modes(connector, intel_connector->edid); - mode = drm_mode_duplicate(dev, intel_connector->panel.fixed_mode); - if (mode == NULL) - return 0; - - drm_mode_probed_add(connector, mode); - return 1; + return intel_panel_get_modes(intel_connector); } static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 3ad246791da5..222328d4e7a1 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -59,6 +59,24 @@ intel_panel_downclock_mode(struct intel_connector *connector, return connector->panel.downclock_mode; } +int intel_panel_get_modes(struct intel_connector *connector) +{ + int num_modes = 0; + + if (connector->panel.fixed_mode) { + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->base.dev, + connector->panel.fixed_mode); + if (mode) { + drm_mode_probed_add(&connector->base, mode); + num_modes++; + } + } + + return num_modes; +} + int intel_panel_compute_config(struct intel_connector *connector, struct drm_display_mode *adjusted_mode) { diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 7ce7e995853f..051b86450156 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -30,6 +30,7 @@ intel_panel_fixed_mode(struct intel_connector *connector, const struct drm_display_mode * intel_panel_downclock_mode(struct intel_connector *connector, const struct drm_display_mode *adjusted_mode); +int intel_panel_get_modes(struct intel_connector *connector); enum drm_mode_status intel_panel_mode_valid(struct intel_connector *connector, const struct drm_display_mode *mode); From 43af674357114db77cfa19be06aa48d8159610f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:20 +0200 Subject: [PATCH 00184/11454] drm/i915: Introduce intel_panel_preferred_fixed_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a couple of cases where we essentially just want to get/check the preferred fixed mode of the panel. Add a small helper for that to abstract away the direct pointer lookup. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 3 ++- drivers/gpu/drm/i915/display/intel_panel.c | 6 ++++++ drivers/gpu/drm/i915/display/intel_panel.h | 2 ++ drivers/gpu/drm/i915/display/intel_sdvo.c | 2 +- 4 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 3c97cd5853cc..2709a8c08cee 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -582,8 +582,9 @@ static bool intel_dp_can_link_train_fallback_for_edp(struct intel_dp *intel_dp, int link_rate, u8 lane_count) { + /* FIXME figure out what we actually want here */ const struct drm_display_mode *fixed_mode = - intel_dp->attached_connector->panel.fixed_mode; + intel_panel_preferred_fixed_mode(intel_dp->attached_connector); int mode_rate, max_rate; mode_rate = intel_dp_link_required(fixed_mode->clock, 18); diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 222328d4e7a1..3ca37766ccb3 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -45,6 +45,12 @@ bool intel_panel_use_ssc(struct drm_i915_private *i915) && !(i915->quirks & QUIRK_LVDS_SSC_DISABLE); } +const struct drm_display_mode * +intel_panel_preferred_fixed_mode(struct intel_connector *connector) +{ + return connector->panel.fixed_mode; +} + const struct drm_display_mode * intel_panel_fixed_mode(struct intel_connector *connector, const struct drm_display_mode *mode) diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 051b86450156..88e6f5c217d8 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -25,6 +25,8 @@ enum drm_connector_status intel_panel_detect(struct drm_connector *connector, bool force); bool intel_panel_use_ssc(struct drm_i915_private *i915); const struct drm_display_mode * +intel_panel_preferred_fixed_mode(struct intel_connector *connector); +const struct drm_display_mode * intel_panel_fixed_mode(struct intel_connector *connector, const struct drm_display_mode *mode); const struct drm_display_mode * diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 04487b03b640..6e0a4f48d84d 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2932,7 +2932,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) } } - if (!intel_connector->panel.fixed_mode) + if (!intel_panel_preferred_fixed_mode(intel_connector)) goto err; return true; From f0a57798fb5c68e7537e75a4acd81f697fd6c089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:21 +0200 Subject: [PATCH 00185/11454] drm/i915: Introduce intel_panel_drrs_type() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a helper to determine which type of DRRS the panel supports. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-10-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_drrs.c | 10 +++------- drivers/gpu/drm/i915/display/intel_panel.c | 10 ++++++++++ drivers/gpu/drm/i915/display/intel_panel.h | 2 ++ 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 2a58bf4cb6cd..c663df51a84a 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -48,11 +48,8 @@ */ static bool can_enable_drrs(struct intel_connector *connector, - const struct intel_crtc_state *pipe_config, - const struct drm_display_mode *downclock_mode) + const struct intel_crtc_state *pipe_config) { - const struct drm_i915_private *i915 = to_i915(connector->base.dev); - if (pipe_config->vrr.enable) return false; @@ -65,8 +62,7 @@ static bool can_enable_drrs(struct intel_connector *connector, if (pipe_config->has_psr) return false; - return downclock_mode && - i915->vbt.drrs_type == DRRS_TYPE_SEAMLESS; + return intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; } void @@ -80,7 +76,7 @@ intel_drrs_compute_config(struct intel_dp *intel_dp, intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); int pixel_clock; - if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { + if (!can_enable_drrs(connector, pipe_config)) { if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder)) intel_zero_m_n(&pipe_config->dp_m2_n2); return; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 3ca37766ccb3..c15f5e3d53d1 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -83,6 +83,16 @@ int intel_panel_get_modes(struct intel_connector *connector) return num_modes; } +enum drrs_type intel_panel_drrs_type(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + + if (!connector->panel.downclock_mode) + return DRRS_TYPE_NONE; + + return i915->vbt.drrs_type; +} + int intel_panel_compute_config(struct intel_connector *connector, struct drm_display_mode *adjusted_mode) { diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 88e6f5c217d8..e86100903f9e 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -9,6 +9,7 @@ #include enum drm_connector_status; +enum drrs_type; struct drm_connector; struct drm_connector_state; struct drm_display_mode; @@ -33,6 +34,7 @@ const struct drm_display_mode * intel_panel_downclock_mode(struct intel_connector *connector, const struct drm_display_mode *adjusted_mode); int intel_panel_get_modes(struct intel_connector *connector); +enum drrs_type intel_panel_drrs_type(struct intel_connector *connector); enum drm_mode_status intel_panel_mode_valid(struct intel_connector *connector, const struct drm_display_mode *mode); From a1b952d4d0a4c2df46f8982d89377e752576c7fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:22 +0200 Subject: [PATCH 00186/11454] drm/i915: Introduce intel_drrs_type_str() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add helper to get the drrs type as a string, and use it in a couple of places. Also pimp the debugfs output a bit while at it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-11-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- .../drm/i915/display/intel_display_debugfs.c | 19 +++++++------------ drivers/gpu/drm/i915/display/intel_drrs.c | 19 +++++++++++++++++-- drivers/gpu/drm/i915/display/intel_drrs.h | 2 ++ 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 2a6fd15b1471..3edf3eb01240 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -22,6 +22,7 @@ #include "intel_fbdev.h" #include "intel_hdcp.h" #include "intel_hdmi.h" +#include "intel_panel.h" #include "intel_pm.h" #include "intel_psr.h" #include "intel_sprite.h" @@ -1143,23 +1144,17 @@ static void drrs_status_per_crtc(struct seq_file *m, { struct drm_i915_private *dev_priv = to_i915(dev); struct i915_drrs *drrs = &dev_priv->drrs; - struct drm_connector *connector; + struct intel_connector *connector; struct drm_connector_list_iter conn_iter; drm_connector_list_iter_begin(dev, &conn_iter); - drm_for_each_connector_iter(connector, &conn_iter) { - bool supported = false; - - if (connector->state->crtc != &crtc->base) + for_each_intel_connector_iter(connector, &conn_iter) { + if (connector->base.state->crtc != &crtc->base) continue; - seq_printf(m, "%s:\n", connector->name); - - if (connector->connector_type == DRM_MODE_CONNECTOR_eDP && - dev_priv->vbt.drrs_type == DRRS_TYPE_SEAMLESS) - supported = true; - - seq_printf(m, "\tDRRS Supported: %s\n", str_yes_no(supported)); + seq_printf(m, "[CONNECTOR:%d:%s] DRRS type: %s\n", + connector->base.base.id, connector->base.name, + intel_drrs_type_str(intel_panel_drrs_type(connector))); } drm_connector_list_iter_end(&conn_iter); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index c663df51a84a..12ae1deea15f 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -47,6 +47,20 @@ * requested by userspace. */ +const char *intel_drrs_type_str(enum drrs_type drrs_type) +{ + static const char * const str[] = { + [DRRS_TYPE_NONE] = "none", + [DRRS_TYPE_STATIC] = "static", + [DRRS_TYPE_SEAMLESS] = "seamless", + }; + + if (drrs_type >= ARRAY_SIZE(str)) + return ""; + + return str[drrs_type]; +} + static bool can_enable_drrs(struct intel_connector *connector, const struct intel_crtc_state *pipe_config) { @@ -461,8 +475,9 @@ intel_drrs_init(struct intel_connector *connector, dev_priv->drrs.refresh_rate = DRRS_REFRESH_RATE_HIGH; drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] seamless DRRS supported\n", - connector->base.base.id, connector->base.name); + "[CONNECTOR:%d:%s] %s DRRS supported\n", + connector->base.base.id, connector->base.name, + intel_drrs_type_str(dev_priv->vbt.drrs_type)); return downclock_mode; } diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index 6bca7692f59f..d3dff44dc3b1 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -8,6 +8,7 @@ #include +enum drrs_type; struct drm_i915_private; struct intel_atomic_state; struct intel_crtc; @@ -15,6 +16,7 @@ struct intel_crtc_state; struct intel_connector; struct intel_dp; +const char *intel_drrs_type_str(enum drrs_type drrs_type); void intel_drrs_enable(struct intel_dp *intel_dp, const struct intel_crtc_state *crtc_state); void intel_drrs_disable(struct intel_dp *intel_dp, From ba770ce36b60c5ca40976579c16f75ac0cf9fb84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:23 +0200 Subject: [PATCH 00187/11454] drm/i915: Eliminate the intel_dp dependency from DRRS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DRRS code has no use for the intel_dp, replace it with just a crtc pointer. This is just an intermediate step towards making DRRS truly per-crtc. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-12-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_ddi.c | 8 +- .../drm/i915/display/intel_display_debugfs.c | 37 ++------- drivers/gpu/drm/i915/display/intel_dp.c | 4 +- drivers/gpu/drm/i915/display/intel_drrs.c | 80 ++++++++----------- drivers/gpu/drm/i915/display/intel_drrs.h | 12 +-- drivers/gpu/drm/i915/i915_drv.h | 2 +- 6 files changed, 50 insertions(+), 93 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 3e6d86a54850..6660fe59e387 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2820,7 +2820,7 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state, if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink) intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); - intel_drrs_enable(intel_dp, crtc_state); + intel_drrs_enable(crtc_state); if (crtc_state->has_audio) intel_audio_codec_enable(encoder, crtc_state, conn_state); @@ -2963,7 +2963,7 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state, intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); - intel_drrs_disable(intel_dp, old_crtc_state); + intel_drrs_disable(old_crtc_state); intel_psr_disable(intel_dp, old_crtc_state); intel_edp_backlight_off(old_conn_state); /* Disable the decompression in DP Sink */ @@ -3013,12 +3013,10 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - intel_ddi_set_dp_msa(crtc_state, conn_state); intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); - intel_drrs_update(intel_dp, crtc_state); + intel_drrs_update(crtc_state); intel_backlight_update(state, encoder, crtc_state, conn_state); drm_connector_update_privacy_screen(conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 3edf3eb01240..219bac411cda 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1161,20 +1161,17 @@ static void drrs_status_per_crtc(struct seq_file *m, seq_puts(m, "\n"); if (to_intel_crtc_state(crtc->base.state)->has_drrs) { - struct intel_panel *panel; - mutex_lock(&drrs->mutex); /* DRRS Supported */ seq_puts(m, "\tDRRS Enabled: Yes\n"); /* disable_drrs() will make drrs->dp NULL */ - if (!drrs->dp) { + if (!drrs->crtc) { seq_puts(m, "Idleness DRRS: Disabled\n"); mutex_unlock(&drrs->mutex); return; } - panel = &drrs->dp->attached_connector->panel; seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X", drrs->busy_frontbuffer_bits); @@ -1881,9 +1878,7 @@ static int i915_drrs_ctl_set(void *data, u64 val) return -ENODEV; for_each_intel_crtc(dev, crtc) { - struct drm_connector_list_iter conn_iter; struct intel_crtc_state *crtc_state; - struct drm_connector *connector; struct drm_crtc_commit *commit; int ret; @@ -1904,30 +1899,14 @@ static int i915_drrs_ctl_set(void *data, u64 val) goto out; } - drm_connector_list_iter_begin(dev, &conn_iter); - drm_for_each_connector_iter(connector, &conn_iter) { - struct intel_encoder *encoder; - struct intel_dp *intel_dp; + drm_dbg(&dev_priv->drm, + "Manually %sabling DRRS. %llu\n", + val ? "en" : "dis", val); - if (!(crtc_state->uapi.connector_mask & - drm_connector_mask(connector))) - continue; - - encoder = intel_attached_encoder(to_intel_connector(connector)); - if (encoder->type != INTEL_OUTPUT_EDP) - continue; - - drm_dbg(&dev_priv->drm, - "Manually %sabling DRRS. %llu\n", - val ? "en" : "dis", val); - - intel_dp = enc_to_intel_dp(encoder); - if (val) - intel_drrs_enable(intel_dp, crtc_state); - else - intel_drrs_disable(intel_dp, crtc_state); - } - drm_connector_list_iter_end(&conn_iter); + if (val) + intel_drrs_enable(crtc_state); + else + intel_drrs_disable(crtc_state); out: drm_modeset_unlock(&crtc->base.mutex); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 2709a8c08cee..a4e4a286230f 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1899,8 +1899,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, intel_vrr_compute_config(pipe_config, conn_state); intel_psr_compute_config(intel_dp, pipe_config, conn_state); - intel_drrs_compute_config(intel_dp, pipe_config, output_bpp, - constant_n); + intel_drrs_compute_config(intel_connector, pipe_config, + output_bpp, constant_n); intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state); intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 12ae1deea15f..12d09560bc80 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -80,11 +80,10 @@ static bool can_enable_drrs(struct intel_connector *connector, } void -intel_drrs_compute_config(struct intel_dp *intel_dp, +intel_drrs_compute_config(struct intel_connector *connector, struct intel_crtc_state *pipe_config, int output_bpp, bool constant_n) { - struct intel_connector *connector = intel_dp->attached_connector; struct drm_i915_private *i915 = to_i915(connector->base.dev); const struct drm_display_mode *downclock_mode = intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); @@ -153,10 +152,9 @@ static void intel_drrs_set_state(struct drm_i915_private *dev_priv, const struct intel_crtc_state *crtc_state, enum drrs_refresh_rate refresh_rate) { - struct intel_dp *intel_dp = dev_priv->drrs.dp; struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - if (!intel_dp) { + if (!dev_priv->drrs.crtc) { drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n"); return; } @@ -193,25 +191,24 @@ static void intel_drrs_set_state(struct drm_i915_private *dev_priv, } static void -intel_drrs_enable_locked(struct intel_dp *intel_dp) +intel_drrs_enable_locked(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); dev_priv->drrs.busy_frontbuffer_bits = 0; - dev_priv->drrs.dp = intel_dp; + dev_priv->drrs.crtc = crtc; } /** * intel_drrs_enable - init drrs struct if supported - * @intel_dp: DP struct * @crtc_state: A pointer to the active crtc state. * * Initializes frontbuffer_bits and drrs.dp */ -void intel_drrs_enable(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) +void intel_drrs_enable(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (!crtc_state->has_drrs) return; @@ -220,48 +217,45 @@ void intel_drrs_enable(struct intel_dp *intel_dp, mutex_lock(&dev_priv->drrs.mutex); - if (dev_priv->drrs.dp) { + if (dev_priv->drrs.crtc) { drm_warn(&dev_priv->drm, "DRRS already enabled\n"); goto unlock; } - intel_drrs_enable_locked(intel_dp); + intel_drrs_enable_locked(crtc); unlock: mutex_unlock(&dev_priv->drrs.mutex); } static void -intel_drrs_disable_locked(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) +intel_drrs_disable_locked(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); intel_drrs_set_state(dev_priv, crtc_state, DRRS_REFRESH_RATE_HIGH); - dev_priv->drrs.dp = NULL; + dev_priv->drrs.crtc = NULL; } /** * intel_drrs_disable - Disable DRRS - * @intel_dp: DP struct * @old_crtc_state: Pointer to old crtc_state. - * */ -void intel_drrs_disable(struct intel_dp *intel_dp, - const struct intel_crtc_state *old_crtc_state) +void intel_drrs_disable(const struct intel_crtc_state *old_crtc_state) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (!old_crtc_state->has_drrs) return; mutex_lock(&dev_priv->drrs.mutex); - if (!dev_priv->drrs.dp) { + if (dev_priv->drrs.crtc != crtc) { mutex_unlock(&dev_priv->drrs.mutex); return; } - intel_drrs_disable_locked(intel_dp, old_crtc_state); + intel_drrs_disable_locked(old_crtc_state); mutex_unlock(&dev_priv->drrs.mutex); cancel_delayed_work_sync(&dev_priv->drrs.work); @@ -269,7 +263,6 @@ void intel_drrs_disable(struct intel_dp *intel_dp, /** * intel_drrs_update - Update DRRS state - * @intel_dp: Intel DP * @crtc_state: new CRTC state * * This function will update DRRS states, disabling or enabling DRRS when @@ -277,10 +270,10 @@ void intel_drrs_disable(struct intel_dp *intel_dp, * intel_drrs_enable() should be called instead. */ void -intel_drrs_update(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state) +intel_drrs_update(const struct intel_crtc_state *crtc_state) { - struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) return; @@ -288,13 +281,13 @@ intel_drrs_update(struct intel_dp *intel_dp, mutex_lock(&dev_priv->drrs.mutex); /* New state matches current one? */ - if (crtc_state->has_drrs == !!dev_priv->drrs.dp) + if (crtc_state->has_drrs == !!dev_priv->drrs.crtc) goto unlock; if (crtc_state->has_drrs) - intel_drrs_enable_locked(intel_dp); + intel_drrs_enable_locked(crtc); else - intel_drrs_disable_locked(intel_dp, crtc_state); + intel_drrs_disable_locked(crtc_state); unlock: mutex_unlock(&dev_priv->drrs.mutex); @@ -304,13 +297,12 @@ static void intel_drrs_downclock_work(struct work_struct *work) { struct drm_i915_private *dev_priv = container_of(work, typeof(*dev_priv), drrs.work.work); - struct intel_dp *intel_dp; + struct intel_crtc *crtc; mutex_lock(&dev_priv->drrs.mutex); - intel_dp = dev_priv->drrs.dp; - - if (!intel_dp) + crtc = dev_priv->drrs.crtc; + if (!crtc) goto unlock; /* @@ -319,9 +311,6 @@ static void intel_drrs_downclock_work(struct work_struct *work) */ if (!dev_priv->drrs.busy_frontbuffer_bits) { - struct intel_crtc *crtc = - to_intel_crtc(dp_to_dig_port(intel_dp)->base.base.crtc); - intel_drrs_set_state(dev_priv, crtc->config, DRRS_REFRESH_RATE_LOW); } @@ -334,9 +323,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits, bool invalidate) { - struct intel_dp *intel_dp; - struct drm_crtc *crtc; - enum pipe pipe; + struct intel_crtc *crtc; if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) return; @@ -345,16 +332,13 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, mutex_lock(&dev_priv->drrs.mutex); - intel_dp = dev_priv->drrs.dp; - if (!intel_dp) { + crtc = dev_priv->drrs.crtc; + if (!crtc) { mutex_unlock(&dev_priv->drrs.mutex); return; } - crtc = dp_to_dig_port(intel_dp)->base.base.crtc; - pipe = to_intel_crtc(crtc)->pipe; - - frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(pipe); + frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); if (invalidate) dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits; else @@ -362,7 +346,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, /* flush/invalidate means busy screen hence upclock */ if (frontbuffer_bits) - intel_drrs_set_state(dev_priv, to_intel_crtc(crtc)->config, + intel_drrs_set_state(dev_priv, crtc->config, DRRS_REFRESH_RATE_HIGH); /* diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index d3dff44dc3b1..e202e8810c12 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -14,22 +14,18 @@ struct intel_atomic_state; struct intel_crtc; struct intel_crtc_state; struct intel_connector; -struct intel_dp; const char *intel_drrs_type_str(enum drrs_type drrs_type); -void intel_drrs_enable(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state); -void intel_drrs_disable(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state); -void intel_drrs_update(struct intel_dp *intel_dp, - const struct intel_crtc_state *crtc_state); +void intel_drrs_enable(const struct intel_crtc_state *crtc_state); +void intel_drrs_disable(const struct intel_crtc_state *crtc_state); +void intel_drrs_update(const struct intel_crtc_state *crtc_state); void intel_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_drrs_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_drrs_page_flip(struct intel_atomic_state *state, struct intel_crtc *crtc); -void intel_drrs_compute_config(struct intel_dp *intel_dp, +void intel_drrs_compute_config(struct intel_connector *connector, struct intel_crtc_state *pipe_config, int output_bpp, bool constant_n); struct drm_display_mode *intel_drrs_init(struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 643e05bf6a80..02ca2434c26f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -210,7 +210,7 @@ enum drrs_type { struct i915_drrs { struct mutex mutex; struct delayed_work work; - struct intel_dp *dp; + struct intel_crtc *crtc; unsigned busy_frontbuffer_bits; enum drrs_refresh_rate refresh_rate; }; From 851f15fe4c1a2541ac80fa5158c786bf83a2b8e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:24 +0200 Subject: [PATCH 00188/11454] drm/i915: Stash DRRS state under intel_crtc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ger rid of one more ugly crtc->config usage by storing the DRRS state under intel_crtc. intel_drrs_enable() copies what it needs from the crtc state, after which DRRS can be blissfully ignorant of anything going on around it. This also lets multiple pipes do DRRS simultanously and entirely independently. v2: Split out some stuff (Jani) Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-13-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_crtc.c | 2 + drivers/gpu/drm/i915/display/intel_ddi.c | 4 +- drivers/gpu/drm/i915/display/intel_display.c | 2 +- .../drm/i915/display/intel_display_debugfs.c | 70 ++--- .../drm/i915/display/intel_display_types.h | 14 + drivers/gpu/drm/i915/display/intel_drrs.c | 261 +++++++----------- drivers/gpu/drm/i915/display/intel_drrs.h | 8 +- drivers/gpu/drm/i915/i915_drv.h | 14 - 8 files changed, 146 insertions(+), 229 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_crtc.c b/drivers/gpu/drm/i915/display/intel_crtc.c index 65827481c1b1..f655c1622877 100644 --- a/drivers/gpu/drm/i915/display/intel_crtc.c +++ b/drivers/gpu/drm/i915/display/intel_crtc.c @@ -24,6 +24,7 @@ #include "intel_display_debugfs.h" #include "intel_display_trace.h" #include "intel_display_types.h" +#include "intel_drrs.h" #include "intel_dsi.h" #include "intel_pipe_crc.h" #include "intel_psr.h" @@ -367,6 +368,7 @@ int intel_crtc_init(struct drm_i915_private *dev_priv, enum pipe pipe) intel_color_init(crtc); + intel_crtc_drrs_init(crtc); intel_crtc_crc_init(crtc); cpu_latency_qos_add_request(&crtc->vblank_pm_qos, PM_QOS_DEFAULT_VALUE); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index 6660fe59e387..a3bf4e876fb4 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3013,10 +3013,12 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + intel_ddi_set_dp_msa(crtc_state, conn_state); intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); - intel_drrs_update(crtc_state); + intel_drrs_update(state, crtc); intel_backlight_update(state, encoder, crtc_state, conn_state); drm_connector_update_privacy_screen(conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 76fa5024b8b5..2c63cd33ede9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1229,7 +1229,7 @@ static void intel_post_plane_update(struct intel_atomic_state *state, hsw_ips_post_update(state, crtc); intel_fbc_post_update(state, crtc); - intel_drrs_page_flip(state, crtc); + intel_drrs_page_flip(crtc); if (needs_async_flip_vtd_wa(old_crtc_state) && !needs_async_flip_vtd_wa(new_crtc_state)) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 219bac411cda..24f773583dd3 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1138,20 +1138,15 @@ static int i915_ddb_info(struct seq_file *m, void *unused) return 0; } -static void drrs_status_per_crtc(struct seq_file *m, - struct drm_device *dev, - struct intel_crtc *crtc) +static int i915_drrs_status(struct seq_file *m, void *unused) { - struct drm_i915_private *dev_priv = to_i915(dev); - struct i915_drrs *drrs = &dev_priv->drrs; - struct intel_connector *connector; + struct drm_i915_private *dev_priv = node_to_i915(m->private); struct drm_connector_list_iter conn_iter; + struct intel_connector *connector; + struct intel_crtc *crtc; - drm_connector_list_iter_begin(dev, &conn_iter); + drm_connector_list_iter_begin(&dev_priv->drm, &conn_iter); for_each_intel_connector_iter(connector, &conn_iter) { - if (connector->base.state->crtc != &crtc->base) - continue; - seq_printf(m, "[CONNECTOR:%d:%s] DRRS type: %s\n", connector->base.base.id, connector->base.name, intel_drrs_type_str(intel_panel_drrs_type(connector))); @@ -1160,56 +1155,25 @@ static void drrs_status_per_crtc(struct seq_file *m, seq_puts(m, "\n"); - if (to_intel_crtc_state(crtc->base.state)->has_drrs) { - mutex_lock(&drrs->mutex); + for_each_intel_crtc(&dev_priv->drm, crtc) { + seq_printf(m, "[CRTC:%d:%s]:\n", + crtc->base.base.id, crtc->base.name); + + mutex_lock(&crtc->drrs.mutex); + /* DRRS Supported */ - seq_puts(m, "\tDRRS Enabled: Yes\n"); + seq_printf(m, "\tDRRS Enabled: %s\n", + str_yes_no(intel_drrs_is_enabled(crtc))); - /* disable_drrs() will make drrs->dp NULL */ - if (!drrs->crtc) { - seq_puts(m, "Idleness DRRS: Disabled\n"); - mutex_unlock(&drrs->mutex); - return; - } - - seq_printf(m, "\t\tBusy_frontbuffer_bits: 0x%X", - drrs->busy_frontbuffer_bits); - - seq_puts(m, "\n\t\t"); + seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X\n", + crtc->drrs.busy_frontbuffer_bits); seq_printf(m, "DRRS refresh rate: %s\n", - drrs->refresh_rate == DRRS_REFRESH_RATE_LOW ? + crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ? "low" : "high"); - seq_puts(m, "\n\t\t"); - mutex_unlock(&drrs->mutex); - } else { - /* DRRS not supported. Print the VBT parameter*/ - seq_puts(m, "\tDRRS Enabled : No"); + mutex_unlock(&crtc->drrs.mutex); } - seq_puts(m, "\n"); -} - -static int i915_drrs_status(struct seq_file *m, void *unused) -{ - struct drm_i915_private *dev_priv = node_to_i915(m->private); - struct drm_device *dev = &dev_priv->drm; - struct intel_crtc *crtc; - int active_crtc_cnt = 0; - - drm_modeset_lock_all(dev); - for_each_intel_crtc(dev, crtc) { - if (crtc->base.state->active) { - active_crtc_cnt++; - seq_printf(m, "\nCRTC %d: ", active_crtc_cnt); - - drrs_status_per_crtc(m, dev, crtc); - } - } - drm_modeset_unlock_all(dev); - - if (!active_crtc_cnt) - seq_puts(m, "No active crtc found\n"); return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 86b2fa675124..e34800ab6924 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1252,6 +1252,11 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_MAX, }; +enum drrs_refresh_rate { + DRRS_REFRESH_RATE_HIGH, + DRRS_REFRESH_RATE_LOW, +}; + #define INTEL_PIPE_CRC_ENTRIES_NR 128 struct intel_pipe_crc { spinlock_t lock; @@ -1294,6 +1299,15 @@ struct intel_crtc { } active; } wm; + struct { + struct mutex mutex; + struct delayed_work work; + enum drrs_refresh_rate refresh_rate; + unsigned int busy_frontbuffer_bits; + enum transcoder cpu_transcoder; + struct intel_link_m_n m_n, m2_n2; + } drrs; + int scanline_offset; struct { diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 12d09560bc80..fd956775698e 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -114,12 +114,11 @@ intel_drrs_compute_config(struct intel_connector *connector, } static void -intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state, +intel_drrs_set_refresh_rate_pipeconf(struct intel_crtc *crtc, enum drrs_refresh_rate refresh_rate) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum transcoder cpu_transcoder = crtc_state->cpu_transcoder; + enum transcoder cpu_transcoder = crtc->drrs.cpu_transcoder; u32 val, bit; if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) @@ -138,65 +137,33 @@ intel_drrs_set_refresh_rate_pipeconf(const struct intel_crtc_state *crtc_state, } static void -intel_drrs_set_refresh_rate_m_n(const struct intel_crtc_state *crtc_state, +intel_drrs_set_refresh_rate_m_n(struct intel_crtc *crtc, enum drrs_refresh_rate refresh_rate) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - - intel_cpu_transcoder_set_m1_n1(crtc, crtc_state->cpu_transcoder, + intel_cpu_transcoder_set_m1_n1(crtc, crtc->drrs.cpu_transcoder, refresh_rate == DRRS_REFRESH_RATE_LOW ? - &crtc_state->dp_m2_n2 : &crtc_state->dp_m_n); + &crtc->drrs.m2_n2 : &crtc->drrs.m_n); } -static void intel_drrs_set_state(struct drm_i915_private *dev_priv, - const struct intel_crtc_state *crtc_state, - enum drrs_refresh_rate refresh_rate) +bool intel_drrs_is_enabled(struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - - if (!dev_priv->drrs.crtc) { - drm_dbg_kms(&dev_priv->drm, "DRRS not supported.\n"); - return; - } - - if (!crtc) { - drm_dbg_kms(&dev_priv->drm, - "DRRS: intel_crtc not initialized\n"); - return; - } - - if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) { - drm_dbg_kms(&dev_priv->drm, "Only Seamless DRRS supported.\n"); - return; - } - - if (refresh_rate == dev_priv->drrs.refresh_rate) - return; - - if (!crtc_state->hw.active) { - drm_dbg_kms(&dev_priv->drm, - "eDP encoder disabled. CRTC not Active\n"); - return; - } - - if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) - intel_drrs_set_refresh_rate_m_n(crtc_state, refresh_rate); - else if (DISPLAY_VER(dev_priv) > 6) - intel_drrs_set_refresh_rate_pipeconf(crtc_state, refresh_rate); - - dev_priv->drrs.refresh_rate = refresh_rate; - - drm_dbg_kms(&dev_priv->drm, "eDP Refresh Rate set to : %s\n", - refresh_rate == DRRS_REFRESH_RATE_LOW ? "low" : "high"); + return crtc->drrs.cpu_transcoder != INVALID_TRANSCODER; } -static void -intel_drrs_enable_locked(struct intel_crtc *crtc) +static void intel_drrs_set_state(struct intel_crtc *crtc, + enum drrs_refresh_rate refresh_rate) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - dev_priv->drrs.busy_frontbuffer_bits = 0; - dev_priv->drrs.crtc = crtc; + if (refresh_rate == crtc->drrs.refresh_rate) + return; + + if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) + intel_drrs_set_refresh_rate_m_n(crtc, refresh_rate); + else if (DISPLAY_VER(dev_priv) > 6) + intel_drrs_set_refresh_rate_pipeconf(crtc, refresh_rate); + + crtc->drrs.refresh_rate = refresh_rate; } /** @@ -213,28 +180,17 @@ void intel_drrs_enable(const struct intel_crtc_state *crtc_state) if (!crtc_state->has_drrs) return; - drm_dbg_kms(&dev_priv->drm, "Enabling DRRS\n"); + drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Enabling DRRS\n", + crtc->base.base.id, crtc->base.name); - mutex_lock(&dev_priv->drrs.mutex); + mutex_lock(&crtc->drrs.mutex); - if (dev_priv->drrs.crtc) { - drm_warn(&dev_priv->drm, "DRRS already enabled\n"); - goto unlock; - } + crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder; + crtc->drrs.m_n = crtc_state->dp_m_n; + crtc->drrs.m2_n2 = crtc_state->dp_m2_n2; + crtc->drrs.busy_frontbuffer_bits = 0; - intel_drrs_enable_locked(crtc); - -unlock: - mutex_unlock(&dev_priv->drrs.mutex); -} - -static void -intel_drrs_disable_locked(const struct intel_crtc_state *crtc_state) -{ - struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - - intel_drrs_set_state(dev_priv, crtc_state, DRRS_REFRESH_RATE_HIGH); - dev_priv->drrs.crtc = NULL; + mutex_unlock(&crtc->drrs.mutex); } /** @@ -249,74 +205,54 @@ void intel_drrs_disable(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->has_drrs) return; - mutex_lock(&dev_priv->drrs.mutex); - if (dev_priv->drrs.crtc != crtc) { - mutex_unlock(&dev_priv->drrs.mutex); - return; - } + drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Disabling DRRS\n", + crtc->base.base.id, crtc->base.name); - intel_drrs_disable_locked(old_crtc_state); - mutex_unlock(&dev_priv->drrs.mutex); + mutex_lock(&crtc->drrs.mutex); - cancel_delayed_work_sync(&dev_priv->drrs.work); + if (intel_drrs_is_enabled(crtc)) + intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); + + crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; + crtc->drrs.busy_frontbuffer_bits = 0; + + mutex_unlock(&crtc->drrs.mutex); + + cancel_delayed_work_sync(&crtc->drrs.work); } /** - * intel_drrs_update - Update DRRS state - * @crtc_state: new CRTC state - * - * This function will update DRRS states, disabling or enabling DRRS when - * executing fastsets. For full modeset, intel_drrs_disable() and - * intel_drrs_enable() should be called instead. + * intel_drrs_update - Update DRRS during fastset + * @state: atomic state + * @crtc: crtc */ -void -intel_drrs_update(const struct intel_crtc_state *crtc_state) +void intel_drrs_update(struct intel_atomic_state *state, + struct intel_crtc *crtc) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); + const struct intel_crtc_state *old_crtc_state = + intel_atomic_get_old_crtc_state(state, crtc); + const struct intel_crtc_state *new_crtc_state = + intel_atomic_get_new_crtc_state(state, crtc); - if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) + if (old_crtc_state->has_drrs == new_crtc_state->has_drrs) return; - mutex_lock(&dev_priv->drrs.mutex); - - /* New state matches current one? */ - if (crtc_state->has_drrs == !!dev_priv->drrs.crtc) - goto unlock; - - if (crtc_state->has_drrs) - intel_drrs_enable_locked(crtc); + if (new_crtc_state->has_drrs) + intel_drrs_enable(new_crtc_state); else - intel_drrs_disable_locked(crtc_state); - -unlock: - mutex_unlock(&dev_priv->drrs.mutex); + intel_drrs_disable(old_crtc_state); } static void intel_drrs_downclock_work(struct work_struct *work) { - struct drm_i915_private *dev_priv = - container_of(work, typeof(*dev_priv), drrs.work.work); - struct intel_crtc *crtc; + struct intel_crtc *crtc = container_of(work, typeof(*crtc), drrs.work.work); - mutex_lock(&dev_priv->drrs.mutex); + mutex_lock(&crtc->drrs.mutex); - crtc = dev_priv->drrs.crtc; - if (!crtc) - goto unlock; + if (intel_drrs_is_enabled(crtc) && !crtc->drrs.busy_frontbuffer_bits) + intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_LOW); - /* - * The delayed work can race with an invalidate hence we need to - * recheck. - */ - - if (!dev_priv->drrs.busy_frontbuffer_bits) { - intel_drrs_set_state(dev_priv, crtc->config, - DRRS_REFRESH_RATE_LOW); - } - -unlock: - mutex_unlock(&dev_priv->drrs.mutex); + mutex_unlock(&crtc->drrs.mutex); } static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, @@ -328,35 +264,36 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) return; - cancel_delayed_work(&dev_priv->drrs.work); + for_each_intel_crtc(&dev_priv->drm, crtc) { + cancel_delayed_work(&crtc->drrs.work); - mutex_lock(&dev_priv->drrs.mutex); + mutex_lock(&crtc->drrs.mutex); - crtc = dev_priv->drrs.crtc; - if (!crtc) { - mutex_unlock(&dev_priv->drrs.mutex); - return; + if (!intel_drrs_is_enabled(crtc)) { + mutex_unlock(&crtc->drrs.mutex); + continue; + } + + frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); + if (invalidate) + crtc->drrs.busy_frontbuffer_bits |= frontbuffer_bits; + else + crtc->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits; + + /* flush/invalidate means busy screen hence upclock */ + if (frontbuffer_bits) + intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); + + /* + * flush also means no more activity hence schedule downclock, if all + * other fbs are quiescent too + */ + if (!invalidate && !crtc->drrs.busy_frontbuffer_bits) + schedule_delayed_work(&crtc->drrs.work, + msecs_to_jiffies(1000)); + + mutex_unlock(&crtc->drrs.mutex); } - - frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); - if (invalidate) - dev_priv->drrs.busy_frontbuffer_bits |= frontbuffer_bits; - else - dev_priv->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits; - - /* flush/invalidate means busy screen hence upclock */ - if (frontbuffer_bits) - intel_drrs_set_state(dev_priv, crtc->config, - DRRS_REFRESH_RATE_HIGH); - - /* - * flush also means no more activity hence schedule downclock, if all - * other fbs are quiescent too - */ - if (!invalidate && !dev_priv->drrs.busy_frontbuffer_bits) - schedule_delayed_work(&dev_priv->drrs.work, - msecs_to_jiffies(1000)); - mutex_unlock(&dev_priv->drrs.mutex); } /** @@ -393,22 +330,36 @@ void intel_drrs_flush(struct drm_i915_private *dev_priv, intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false); } -void intel_drrs_page_flip(struct intel_atomic_state *state, - struct intel_crtc *crtc) +void intel_drrs_page_flip(struct intel_crtc *crtc) { - struct drm_i915_private *dev_priv = to_i915(state->base.dev); + struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); unsigned int frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false); } /** - * intel_drrs_init - Init basic DRRS work and mutex. + * intel_crtc_drrs_init - Init DRRS for CRTC + * @crtc: crtc + * + * This function is called only once at driver load to initialize basic + * DRRS stuff. + * + */ +void intel_crtc_drrs_init(struct intel_crtc *crtc) +{ + INIT_DELAYED_WORK(&crtc->drrs.work, intel_drrs_downclock_work); + mutex_init(&crtc->drrs.mutex); + crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; +} + +/** + * intel_drrs_init - Init DRRS for eDP connector * @connector: eDP connector * @fixed_mode: preferred mode of panel * - * This function is called only once at driver load to initialize basic - * DRRS stuff. + * This function is called only once at driver load to initialize + * DRRS support for the connector. * * Returns: * Downclock mode if panel supports it, else return NULL. @@ -421,10 +372,7 @@ intel_drrs_init(struct intel_connector *connector, { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct intel_encoder *encoder = connector->encoder; - struct drm_display_mode *downclock_mode = NULL; - - INIT_DELAYED_WORK(&dev_priv->drrs.work, intel_drrs_downclock_work); - mutex_init(&dev_priv->drrs.mutex); + struct drm_display_mode *downclock_mode; if (DISPLAY_VER(dev_priv) <= 6) { drm_dbg_kms(&dev_priv->drm, @@ -457,7 +405,6 @@ intel_drrs_init(struct intel_connector *connector, return NULL; } - dev_priv->drrs.refresh_rate = DRRS_REFRESH_RATE_HIGH; drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] %s DRRS supported\n", connector->base.base.id, connector->base.name, diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index e202e8810c12..c6e325a91552 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -16,18 +16,20 @@ struct intel_crtc_state; struct intel_connector; const char *intel_drrs_type_str(enum drrs_type drrs_type); +bool intel_drrs_is_enabled(struct intel_crtc *crtc); void intel_drrs_enable(const struct intel_crtc_state *crtc_state); void intel_drrs_disable(const struct intel_crtc_state *crtc_state); -void intel_drrs_update(const struct intel_crtc_state *crtc_state); +void intel_drrs_update(struct intel_atomic_state *state, + struct intel_crtc *crtc); void intel_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_drrs_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); -void intel_drrs_page_flip(struct intel_atomic_state *state, - struct intel_crtc *crtc); +void intel_drrs_page_flip(struct intel_crtc *crtc); void intel_drrs_compute_config(struct intel_connector *connector, struct intel_crtc_state *pipe_config, int output_bpp, bool constant_n); +void intel_crtc_drrs_init(struct intel_crtc *crtc); struct drm_display_mode *intel_drrs_init(struct intel_connector *connector, const struct drm_display_mode *fixed_mode); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 02ca2434c26f..1c9a7189e0a5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -196,25 +196,12 @@ struct drm_i915_display_funcs { #define I915_COLOR_UNEVICTABLE (-1) /* a non-vma sharing the address space */ -enum drrs_refresh_rate { - DRRS_REFRESH_RATE_HIGH, - DRRS_REFRESH_RATE_LOW, -}; - enum drrs_type { DRRS_TYPE_NONE, DRRS_TYPE_STATIC, DRRS_TYPE_SEAMLESS, }; -struct i915_drrs { - struct mutex mutex; - struct delayed_work work; - struct intel_crtc *crtc; - unsigned busy_frontbuffer_bits; - enum drrs_refresh_rate refresh_rate; -}; - #define QUIRK_LVDS_SSC_DISABLE (1<<1) #define QUIRK_INVERT_BRIGHTNESS (1<<2) #define QUIRK_BACKLIGHT_PRESENT (1<<3) @@ -536,7 +523,6 @@ struct drm_i915_private { struct i915_hotplug hotplug; struct intel_fbc *fbc[I915_MAX_FBCS]; - struct i915_drrs drrs; struct intel_opregion opregion; struct intel_vbt_data vbt; From e8ae25df50803b93fa9530ed7048bc67531eb7da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:25 +0200 Subject: [PATCH 00189/11454] drm/i915: Move DRRS enable/disable higher up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No reason to keep the DRRS enable/disable hidden insider the encoder hooks. Let's just move them all the way up into platform independent code so that all platforms get to use them. These are nops when the state computation doesn't think DRRS is possible. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-14-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 3 --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index a3bf4e876fb4..e2b297d2c295 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2820,8 +2820,6 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state, if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink) intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); - intel_drrs_enable(crtc_state); - if (crtc_state->has_audio) intel_audio_codec_enable(encoder, crtc_state, conn_state); @@ -2963,7 +2961,6 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state, intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); - intel_drrs_disable(old_crtc_state); intel_psr_disable(intel_dp, old_crtc_state); intel_edp_backlight_off(old_conn_state); /* Disable the decompression in DP Sink */ diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 2c63cd33ede9..6817a3dcf72b 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -8114,6 +8114,8 @@ static void intel_enable_crtc(struct intel_atomic_state *state, if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) return; + intel_drrs_enable(new_crtc_state); + /* vblanks work again, re-enable pipe CRC. */ intel_crtc_enable_pipe_crc(crtc); } @@ -8183,6 +8185,8 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, */ intel_crtc_disable_pipe_crc(crtc); + intel_drrs_disable(old_crtc_state); + dev_priv->display->crtc_disable(state, crtc); crtc->active = false; intel_fbc_disable(crtc); From c2f12155536a28ee99fbf9960c1d83ceff81d9ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:26 +0200 Subject: [PATCH 00190/11454] drm/i915: Enable eDP DRRS on ilk/snb port A MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing special about ivb+ here, if DRRS works on ivb+ port A it should work just as well on ilk/snb. So let's enable that. Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-15-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 3 --- drivers/gpu/drm/i915/display/intel_drrs.c | 8 ++++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 24f773583dd3..35c27d67d584 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1838,9 +1838,6 @@ static int i915_drrs_ctl_set(void *data, u64 val) struct drm_device *dev = &dev_priv->drm; struct intel_crtc *crtc; - if (DISPLAY_VER(dev_priv) < 7) - return -ENODEV; - for_each_intel_crtc(dev, crtc) { struct intel_crtc_state *crtc_state; struct drm_crtc_commit *commit; diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index fd956775698e..981eb37d613e 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -158,10 +158,10 @@ static void intel_drrs_set_state(struct intel_crtc *crtc, if (refresh_rate == crtc->drrs.refresh_rate) return; - if (DISPLAY_VER(dev_priv) >= 8 && !IS_CHERRYVIEW(dev_priv)) - intel_drrs_set_refresh_rate_m_n(crtc, refresh_rate); - else if (DISPLAY_VER(dev_priv) > 6) + if (intel_cpu_transcoder_has_m2_n2(dev_priv, crtc->drrs.cpu_transcoder)) intel_drrs_set_refresh_rate_pipeconf(crtc, refresh_rate); + else + intel_drrs_set_refresh_rate_m_n(crtc, refresh_rate); crtc->drrs.refresh_rate = refresh_rate; } @@ -374,7 +374,7 @@ intel_drrs_init(struct intel_connector *connector, struct intel_encoder *encoder = connector->encoder; struct drm_display_mode *downclock_mode; - if (DISPLAY_VER(dev_priv) <= 6) { + if (DISPLAY_VER(dev_priv) < 5) { drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] DRRS not supported on platform\n", connector->base.base.id, connector->base.name); From c5ee23437cae2cffadc1a96ebd444ae2504e0408 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 19:24:27 +0200 Subject: [PATCH 00191/11454] drm/i915: Implement static DRRS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's start supporting static DRRS by trying to match the refresh rate the user has requested, assuming the panel supports suitable timings. For now we stick to just our current two timings: - fixed_mode: the panel's preferred mode - downclock_mode: the lowest refresh rate mode we found Some panels may support more timings than that, but we'll have to convert our fixed_mode/downclock_mode pointers into a full list before we can handle that. v2: Rebase due to intel_panel_get_modes() Reviewed-by: Jani Nikula #v1 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311172428.14685-16-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_drrs.c | 2 +- drivers/gpu/drm/i915/display/intel_panel.c | 31 ++++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 981eb37d613e..2bbc0388263a 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -390,7 +390,7 @@ intel_drrs_init(struct intel_connector *connector, return NULL; } - if (dev_priv->vbt.drrs_type != DRRS_TYPE_SEAMLESS) { + if (dev_priv->vbt.drrs_type == DRRS_TYPE_NONE) { drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] DRRS not supported according to VBT\n", connector->base.base.id, connector->base.name); diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index c15f5e3d53d1..08a0612edd60 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -55,14 +55,30 @@ const struct drm_display_mode * intel_panel_fixed_mode(struct intel_connector *connector, const struct drm_display_mode *mode) { - return connector->panel.fixed_mode; + const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode; + const struct drm_display_mode *downclock_mode = connector->panel.downclock_mode; + + /* pick the one that is closer in terms of vrefresh */ + /* FIXME make this a a list of modes so we can have more than two */ + if (fixed_mode && downclock_mode && + abs(drm_mode_vrefresh(downclock_mode) - drm_mode_vrefresh(mode)) < + abs(drm_mode_vrefresh(fixed_mode) - drm_mode_vrefresh(mode))) + return downclock_mode; + else + return fixed_mode; } const struct drm_display_mode * intel_panel_downclock_mode(struct intel_connector *connector, const struct drm_display_mode *adjusted_mode) { - return connector->panel.downclock_mode; + const struct drm_display_mode *downclock_mode = connector->panel.downclock_mode; + + if (downclock_mode && + drm_mode_vrefresh(downclock_mode) < drm_mode_vrefresh(adjusted_mode)) + return downclock_mode; + else + return NULL; } int intel_panel_get_modes(struct intel_connector *connector) @@ -80,6 +96,17 @@ int intel_panel_get_modes(struct intel_connector *connector) } } + if (connector->panel.downclock_mode) { + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->base.dev, + connector->panel.downclock_mode); + if (mode) { + drm_mode_probed_add(&connector->base, mode); + num_modes++; + } + } + return num_modes; } From 345b7c4b86884cf413735be3edc8e28d0d494916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Mon, 14 Mar 2022 17:27:37 +0200 Subject: [PATCH 00192/11454] drm/i915: Convert fixed_mode/downclock_mode into a list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store the fixed_mode and downclock_mode as a real list, in preparation for exposing other supported modes as well. v2: Init the list in intel_sdvo_connector_alloc() too v3: Use list_first_entry_or_null() (Jani) Reviewed-by: Jani Nikula Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220314152737.9125-1-ville.syrjala@linux.intel.com --- .../gpu/drm/i915/display/intel_connector.c | 2 + .../drm/i915/display/intel_display_debugfs.c | 9 ++- .../drm/i915/display/intel_display_types.h | 3 +- drivers/gpu/drm/i915/display/intel_panel.c | 78 +++++++++---------- drivers/gpu/drm/i915/display/intel_sdvo.c | 2 + 5 files changed, 49 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c index c65f95a9a1ec..a5f5dd55b0cb 100644 --- a/drivers/gpu/drm/i915/display/intel_connector.c +++ b/drivers/gpu/drm/i915/display/intel_connector.c @@ -54,6 +54,8 @@ int intel_connector_init(struct intel_connector *connector) __drm_atomic_helper_connector_reset(&connector->base, &conn_state->base); + INIT_LIST_HEAD(&connector->panel.fixed_modes); + return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 35c27d67d584..b3d426cc3266 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -548,12 +548,15 @@ static void intel_encoder_info(struct seq_file *m, static void intel_panel_info(struct seq_file *m, struct intel_connector *connector) { - const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode; + const struct drm_display_mode *fixed_mode; - if (!fixed_mode) + if (list_empty(&connector->panel.fixed_modes)) return; - seq_printf(m, "\tfixed mode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(fixed_mode)); + seq_puts(m, "\tfixed modes:\n"); + + list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) + intel_seq_print_mode(m, 2, fixed_mode); } static void intel_hdcp_info(struct seq_file *m, diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index e34800ab6924..d84e82f3eab9 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -280,8 +280,7 @@ struct intel_panel_bl_funcs { }; struct intel_panel { - struct drm_display_mode *fixed_mode; - struct drm_display_mode *downclock_mode; + struct list_head fixed_modes; /* backlight */ struct { diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 08a0612edd60..f428d0457c17 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -48,59 +48,55 @@ bool intel_panel_use_ssc(struct drm_i915_private *i915) const struct drm_display_mode * intel_panel_preferred_fixed_mode(struct intel_connector *connector) { - return connector->panel.fixed_mode; + return list_first_entry_or_null(&connector->panel.fixed_modes, + struct drm_display_mode, head); } const struct drm_display_mode * intel_panel_fixed_mode(struct intel_connector *connector, const struct drm_display_mode *mode) { - const struct drm_display_mode *fixed_mode = connector->panel.fixed_mode; - const struct drm_display_mode *downclock_mode = connector->panel.downclock_mode; + const struct drm_display_mode *fixed_mode, *best_mode = NULL; + int vrefresh = drm_mode_vrefresh(mode); - /* pick the one that is closer in terms of vrefresh */ - /* FIXME make this a a list of modes so we can have more than two */ - if (fixed_mode && downclock_mode && - abs(drm_mode_vrefresh(downclock_mode) - drm_mode_vrefresh(mode)) < - abs(drm_mode_vrefresh(fixed_mode) - drm_mode_vrefresh(mode))) - return downclock_mode; - else - return fixed_mode; + /* pick the fixed_mode that is closest in terms of vrefresh */ + list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) { + if (!best_mode || + abs(drm_mode_vrefresh(fixed_mode) - vrefresh) < + abs(drm_mode_vrefresh(best_mode) - vrefresh)) + best_mode = fixed_mode; + } + + return best_mode; } const struct drm_display_mode * intel_panel_downclock_mode(struct intel_connector *connector, const struct drm_display_mode *adjusted_mode) { - const struct drm_display_mode *downclock_mode = connector->panel.downclock_mode; + const struct drm_display_mode *fixed_mode, *best_mode = NULL; + int vrefresh = drm_mode_vrefresh(adjusted_mode); - if (downclock_mode && - drm_mode_vrefresh(downclock_mode) < drm_mode_vrefresh(adjusted_mode)) - return downclock_mode; - else - return NULL; + /* pick the fixed_mode with the lowest refresh rate */ + list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) { + if (drm_mode_vrefresh(fixed_mode) < vrefresh) { + vrefresh = drm_mode_vrefresh(fixed_mode); + best_mode = fixed_mode; + } + } + + return best_mode; } int intel_panel_get_modes(struct intel_connector *connector) { + const struct drm_display_mode *fixed_mode; int num_modes = 0; - if (connector->panel.fixed_mode) { + list_for_each_entry(fixed_mode, &connector->panel.fixed_modes, head) { struct drm_display_mode *mode; - mode = drm_mode_duplicate(connector->base.dev, - connector->panel.fixed_mode); - if (mode) { - drm_mode_probed_add(&connector->base, mode); - num_modes++; - } - } - - if (connector->panel.downclock_mode) { - struct drm_display_mode *mode; - - mode = drm_mode_duplicate(connector->base.dev, - connector->panel.downclock_mode); + mode = drm_mode_duplicate(connector->base.dev, fixed_mode); if (mode) { drm_mode_probed_add(&connector->base, mode); num_modes++; @@ -114,7 +110,8 @@ enum drrs_type intel_panel_drrs_type(struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); - if (!connector->panel.downclock_mode) + if (list_empty(&connector->panel.fixed_modes) || + list_is_singular(&connector->panel.fixed_modes)) return DRRS_TYPE_NONE; return i915->vbt.drrs_type; @@ -608,8 +605,10 @@ int intel_panel_init(struct intel_panel *panel, { intel_backlight_init_funcs(panel); - panel->fixed_mode = fixed_mode; - panel->downclock_mode = downclock_mode; + if (fixed_mode) + list_add_tail(&fixed_mode->head, &panel->fixed_modes); + if (downclock_mode) + list_add_tail(&downclock_mode->head, &panel->fixed_modes); return 0; } @@ -618,13 +617,12 @@ void intel_panel_fini(struct intel_panel *panel) { struct intel_connector *intel_connector = container_of(panel, struct intel_connector, panel); + struct drm_display_mode *fixed_mode, *next; intel_backlight_destroy(panel); - if (panel->fixed_mode) - drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); - - if (panel->downclock_mode) - drm_mode_destroy(intel_connector->base.dev, - panel->downclock_mode); + list_for_each_entry_safe(fixed_mode, next, &panel->fixed_modes, head) { + list_del(&fixed_mode->head); + drm_mode_destroy(intel_connector->base.dev, fixed_mode); + } } diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 6e0a4f48d84d..158e750e5b4d 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2747,6 +2747,8 @@ static struct intel_sdvo_connector *intel_sdvo_connector_alloc(void) __drm_atomic_helper_connector_reset(&sdvo_connector->base.base, &conn_state->base.base); + INIT_LIST_HEAD(&sdvo_connector->base.panel.fixed_modes); + return sdvo_connector; } From 8f0c1c0949b609acfad62b8d5f742a3b5e7b05ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Fri, 11 Mar 2022 10:51:48 -0800 Subject: [PATCH 00193/11454] drm/i915/display: Fix HPD short pulse handling for eDP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 13ea6db2cf24 ("drm/i915/edp: Ignore short pulse when panel powered off") completely broke short pulse handling for eDP as it is usually generated by sink when it is displaying image and there is some error or status that source needs to handle. When power panel is enabled, this state is enough to power aux transactions and VDD override is disabled, so intel_pps_have_power() is always returning false causing short pulses to be ignored. So here better naming this function that intends to check if aux lines are powered to avoid the endless cycle mentioned in the commit being fixed and fixing the check for what it is intended. v2: - renamed to intel_pps_have_panel_power_or_vdd() - fixed indentation Fixes: 13ea6db2cf24 ("drm/i915/edp: Ignore short pulse when panel powered off") Cc: Anshuman Gupta Cc: Jani Nikula Cc: Uma Shankar Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220311185149.110527-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_pps.c | 6 +++--- drivers/gpu/drm/i915/display/intel_pps.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index a4e4a286230f..9e19165fd175 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4862,7 +4862,7 @@ intel_dp_hpd_pulse(struct intel_digital_port *dig_port, bool long_hpd) struct intel_dp *intel_dp = &dig_port->dp; if (dig_port->base.type == INTEL_OUTPUT_EDP && - (long_hpd || !intel_pps_have_power(intel_dp))) { + (long_hpd || !intel_pps_have_panel_power_or_vdd(intel_dp))) { /* * vdd off can generate a long/short pulse on eDP which * would require vdd on to handle it, and thus we diff --git a/drivers/gpu/drm/i915/display/intel_pps.c b/drivers/gpu/drm/i915/display/intel_pps.c index 9c986e8932f8..64bd4ca0edd4 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.c +++ b/drivers/gpu/drm/i915/display/intel_pps.c @@ -1075,14 +1075,14 @@ static void intel_pps_vdd_sanitize(struct intel_dp *intel_dp) edp_panel_vdd_schedule_off(intel_dp); } -bool intel_pps_have_power(struct intel_dp *intel_dp) +bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp) { intel_wakeref_t wakeref; bool have_power = false; with_intel_pps_lock(intel_dp, wakeref) { - have_power = edp_have_panel_power(intel_dp) && - edp_have_panel_vdd(intel_dp); + have_power = edp_have_panel_power(intel_dp) || + edp_have_panel_vdd(intel_dp); } return have_power; diff --git a/drivers/gpu/drm/i915/display/intel_pps.h b/drivers/gpu/drm/i915/display/intel_pps.h index fbb47f6f453e..e64144659d31 100644 --- a/drivers/gpu/drm/i915/display/intel_pps.h +++ b/drivers/gpu/drm/i915/display/intel_pps.h @@ -37,7 +37,7 @@ void intel_pps_vdd_on(struct intel_dp *intel_dp); void intel_pps_on(struct intel_dp *intel_dp); void intel_pps_off(struct intel_dp *intel_dp); void intel_pps_vdd_off_sync(struct intel_dp *intel_dp); -bool intel_pps_have_power(struct intel_dp *intel_dp); +bool intel_pps_have_panel_power_or_vdd(struct intel_dp *intel_dp); void intel_pps_wait_power_cycle(struct intel_dp *intel_dp); void intel_pps_init(struct intel_dp *intel_dp); From 15f26bdc81f7f03561aaea5a10d87bd6638e1459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Fri, 11 Mar 2022 10:51:49 -0800 Subject: [PATCH 00194/11454] drm/i915/display: Do not re-enable PSR after it was marked as not reliable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If a error happens and sink_not_reliable is set, PSR should be disabled for good but that is not happening. It would be disabled by the function handling the PSR error but then on the next fastset it would be enabled again in _intel_psr_post_plane_update(). It would only be disabled for good in the next modeset where has_psr will be set false. v2: - release psr lock before continue Fixes: 9ce5884e5139 ("drm/i915/display: Only keep PSR enabled if there is active planes") Reported-by: Khaled Almahallawy Reported-by: Charlton Lin Cc: Jouni Högander Signed-off-by: José Roberto de Souza Reviewed-by: Jouni Högander Link: https://patchwork.freedesktop.org/patch/msgid/20220311185149.110527-2-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_psr.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_psr.c b/drivers/gpu/drm/i915/display/intel_psr.c index bbd581ed0815..80002ca6a6eb 100644 --- a/drivers/gpu/drm/i915/display/intel_psr.c +++ b/drivers/gpu/drm/i915/display/intel_psr.c @@ -1853,6 +1853,9 @@ static void _intel_psr_post_plane_update(const struct intel_atomic_state *state, mutex_lock(&psr->lock); + if (psr->sink_not_reliable) + goto exit; + drm_WARN_ON(&dev_priv->drm, psr->enabled && !crtc_state->active_planes); /* Only enable if there is active planes */ @@ -1863,6 +1866,7 @@ static void _intel_psr_post_plane_update(const struct intel_atomic_state *state, if (crtc_state->crc_enabled && psr->enabled) psr_force_hw_tracking_exit(intel_dp); +exit: mutex_unlock(&psr->lock); } } From 4dc3a1e52fece14c8bf05d5b46c9834d31c8dbf4 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Mon, 14 Mar 2022 19:08:05 -0700 Subject: [PATCH 00195/11454] drm/i915: Reduce stack usage in debugfs due to SSEU MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sseu_dev_info is already a pretty large structure which will likely continue to grow when future platforms increase potential DSS and EU counts. Let's switch the stack placement of this structure in debugfs with a dynamic allocation. Signed-off-by: John Harrison Signed-off-by: Matt Roper Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220315020805.844962-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c | 22 +++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c index 1e199c09fc9c..074d293f287e 100644 --- a/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_sseu_debugfs.c @@ -246,7 +246,7 @@ int intel_sseu_status(struct seq_file *m, struct intel_gt *gt) { struct drm_i915_private *i915 = gt->i915; const struct intel_gt_info *info = >->info; - struct sseu_dev_info sseu; + struct sseu_dev_info *sseu; intel_wakeref_t wakeref; if (GRAPHICS_VER(i915) < 8) @@ -256,23 +256,29 @@ int intel_sseu_status(struct seq_file *m, struct intel_gt *gt) i915_print_sseu_info(m, true, HAS_POOLED_EU(i915), &info->sseu); seq_puts(m, "SSEU Device Status\n"); - memset(&sseu, 0, sizeof(sseu)); - intel_sseu_set_info(&sseu, info->sseu.max_slices, + + sseu = kzalloc(sizeof(*sseu), GFP_KERNEL); + if (!sseu) + return -ENOMEM; + + intel_sseu_set_info(sseu, info->sseu.max_slices, info->sseu.max_subslices, info->sseu.max_eus_per_subslice); with_intel_runtime_pm(&i915->runtime_pm, wakeref) { if (IS_CHERRYVIEW(i915)) - cherryview_sseu_device_status(gt, &sseu); + cherryview_sseu_device_status(gt, sseu); else if (IS_BROADWELL(i915)) - bdw_sseu_device_status(gt, &sseu); + bdw_sseu_device_status(gt, sseu); else if (GRAPHICS_VER(i915) == 9) - gen9_sseu_device_status(gt, &sseu); + gen9_sseu_device_status(gt, sseu); else if (GRAPHICS_VER(i915) >= 11) - gen11_sseu_device_status(gt, &sseu); + gen11_sseu_device_status(gt, sseu); } - i915_print_sseu_info(m, false, HAS_POOLED_EU(i915), &sseu); + i915_print_sseu_info(m, false, HAS_POOLED_EU(i915), sseu); + + kfree(sseu); return 0; } From b7563ec7d906ef87dcd15f39c66e0f35f58c2003 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Tue, 15 Mar 2022 10:02:50 -0700 Subject: [PATCH 00196/11454] drm/i915: Report steering details in debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new 'steering' node in each gt's debugfs directory that tells whether we're using explicit steering for various types of MCR ranges and, if so, what MMIO ranges it applies to. We're going to be transitioning away from implicit steering, even for slice/dss steering soon, so the information reported here will become increasingly valuable once that happens. v2: - Adding missing 'static' on intel_steering_types[] (Jose, sparse) v3: - "static const char *" -> "static const char * const" (sparse) Cc: Daniele Ceraolo Spurio Signed-off-by: Matt Roper Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220315170250.954380-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/intel_gt.c | 46 +++++++++++++++++++++ drivers/gpu/drm/i915/gt/intel_gt.h | 2 + drivers/gpu/drm/i915/gt/intel_gt_debugfs.c | 13 ++++++ drivers/gpu/drm/i915/gt/intel_gt_types.h | 5 +++ drivers/gpu/drm/i915/gt/intel_workarounds.c | 8 +++- 5 files changed, 73 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 8a2483ccbfb9..ef6fef1bab20 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -96,6 +96,12 @@ int intel_gt_assign_ggtt(struct intel_gt *gt) return gt->ggtt ? 0 : -ENOMEM; } +static const char * const intel_steering_types[] = { + "L3BANK", + "MSLICE", + "LNCF", +}; + static const struct intel_mmio_range icl_l3bank_steering_table[] = { { 0x00B100, 0x00B3FF }, {}, @@ -932,6 +938,46 @@ u32 intel_gt_read_register(struct intel_gt *gt, i915_reg_t reg) return intel_uncore_read(gt->uncore, reg); } +static void report_steering_type(struct drm_printer *p, + struct intel_gt *gt, + enum intel_steering_type type, + bool dump_table) +{ + const struct intel_mmio_range *entry; + u8 slice, subslice; + + BUILD_BUG_ON(ARRAY_SIZE(intel_steering_types) != NUM_STEERING_TYPES); + + if (!gt->steering_table[type]) { + drm_printf(p, "%s steering: uses default steering\n", + intel_steering_types[type]); + return; + } + + intel_gt_get_valid_steering(gt, type, &slice, &subslice); + drm_printf(p, "%s steering: sliceid=0x%x, subsliceid=0x%x\n", + intel_steering_types[type], slice, subslice); + + if (!dump_table) + return; + + for (entry = gt->steering_table[type]; entry->end; entry++) + drm_printf(p, "\t0x%06x - 0x%06x\n", entry->start, entry->end); +} + +void intel_gt_report_steering(struct drm_printer *p, struct intel_gt *gt, + bool dump_table) +{ + drm_printf(p, "Default steering: sliceid=0x%x, subsliceid=0x%x\n", + gt->default_steering.groupid, + gt->default_steering.instanceid); + + if (HAS_MSLICES(gt->i915)) { + report_steering_type(p, gt, MSLICE, dump_table); + report_steering_type(p, gt, LNCF, dump_table); + } +} + void intel_gt_info_print(const struct intel_gt_info *info, struct drm_printer *p) { diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index 0f571c8ee22b..3edece1865e4 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -87,6 +87,8 @@ static inline bool intel_gt_needs_read_steering(struct intel_gt *gt, u32 intel_gt_read_register_fw(struct intel_gt *gt, i915_reg_t reg); u32 intel_gt_read_register(struct intel_gt *gt, i915_reg_t reg); +void intel_gt_report_steering(struct drm_printer *p, struct intel_gt *gt, + bool dump_table); void intel_gt_info_print(const struct intel_gt_info *info, struct drm_printer *p); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_debugfs.c index f103664b71d4..6f45b131a001 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_debugfs.c @@ -6,6 +6,7 @@ #include #include "i915_drv.h" +#include "intel_gt.h" #include "intel_gt_debugfs.h" #include "intel_gt_engines_debugfs.h" #include "intel_gt_pm_debugfs.h" @@ -57,10 +58,22 @@ static int __intel_gt_debugfs_reset_store(void *data, u64 val) DEFINE_SIMPLE_ATTRIBUTE(reset_fops, __intel_gt_debugfs_reset_show, __intel_gt_debugfs_reset_store, "%llu\n"); +static int steering_show(struct seq_file *m, void *data) +{ + struct drm_printer p = drm_seq_file_printer(m); + struct intel_gt *gt = m->private; + + intel_gt_report_steering(&p, gt, true); + + return 0; +} +DEFINE_INTEL_GT_DEBUGFS_ATTRIBUTE(steering); + static void gt_debugfs_register(struct intel_gt *gt, struct dentry *root) { static const struct intel_gt_debugfs_file files[] = { { "reset", &reset_fops, NULL }, + { "steering", &steering_fops }, }; intel_gt_debugfs_register_files(root, files, ARRAY_SIZE(files), gt); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h index f20687796490..7781ab84e7a3 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_types.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h @@ -182,6 +182,11 @@ struct intel_gt { const struct intel_mmio_range *steering_table[NUM_STEERING_TYPES]; + struct { + u8 groupid; + u8 instanceid; + } default_steering; + struct intel_gt_info { intel_engine_mask_t engine_mask; diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index beca8735bae5..c328d46f8095 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -1072,9 +1072,15 @@ static void __set_mcr_steering(struct i915_wa_list *wal, static void __add_mcr_wa(struct intel_gt *gt, struct i915_wa_list *wal, unsigned int slice, unsigned int subslice) { - drm_dbg(>->i915->drm, "MCR slice=0x%x, subslice=0x%x\n", slice, subslice); + struct drm_printer p = drm_debug_printer("MCR Steering:"); __set_mcr_steering(wal, GEN8_MCR_SELECTOR, slice, subslice); + + gt->default_steering.groupid = slice; + gt->default_steering.instanceid = subslice; + + if (drm_debug_enabled(DRM_UT_DRIVER)) + intel_gt_report_steering(&p, gt, false); } static void From 10343606ad287d2b8d8ebce0a5cebe5e877f341c Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Mon, 14 Mar 2022 16:42:02 -0700 Subject: [PATCH 00197/11454] drm/i915/guc: add steering info to GuC register save/restore list GuC has its own steering mechanism and can't use the default set by i915, so we need to provide the steering information that the FW will need to save/restore registers while processing an engine reset. The GUC interface allows us to do so as part of the register save/restore list and it requires us to specify the steering for all multicast register, even those that would be covered by the default setting for cpu access. Given that we do not distinguish between registers that do not need steering and registers that are guaranteed to work the default steering, we set the steering for all entries in the guc list that do not require a special steering (e.g. mslice) to the default settings; this will cost us a few extra writes during engine reset but allows us to keep the steering logic simple. Cc: John Harrison Cc: Matt Roper Signed-off-by: Daniele Ceraolo Spurio Signed-off-by: Matt Roper Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220314234203.799268-3-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/intel_gt.c | 29 +++++++++++ drivers/gpu/drm/i915/gt/intel_gt.h | 3 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 54 +++++++++++++++------ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 3 ++ 4 files changed, 73 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index ef6fef1bab20..8ee532abdd7a 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -919,6 +919,35 @@ u32 intel_gt_read_register_fw(struct intel_gt *gt, i915_reg_t reg) return intel_uncore_read_fw(gt->uncore, reg); } +/** + * intel_gt_get_valid_steering_for_reg - get a valid steering for a register + * @gt: GT structure + * @reg: register for which the steering is required + * @sliceid: return variable for slice steering + * @subsliceid: return variable for subslice steering + * + * This function returns a slice/subslice pair that is guaranteed to work for + * read steering of the given register. Note that a value will be returned even + * if the register is not replicated and therefore does not actually require + * steering. + */ +void intel_gt_get_valid_steering_for_reg(struct intel_gt *gt, i915_reg_t reg, + u8 *sliceid, u8 *subsliceid) +{ + int type; + + for (type = 0; type < NUM_STEERING_TYPES; type++) { + if (intel_gt_reg_needs_read_steering(gt, reg, type)) { + intel_gt_get_valid_steering(gt, type, sliceid, + subsliceid); + return; + } + } + + *sliceid = gt->default_steering.groupid; + *subsliceid = gt->default_steering.instanceid; +} + u32 intel_gt_read_register(struct intel_gt *gt, i915_reg_t reg) { int type; diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index 3edece1865e4..996f8f3c17b9 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -84,6 +84,9 @@ static inline bool intel_gt_needs_read_steering(struct intel_gt *gt, return gt->steering_table[type]; } +void intel_gt_get_valid_steering_for_reg(struct intel_gt *gt, i915_reg_t reg, + u8 *sliceid, u8 *subsliceid); + u32 intel_gt_read_register_fw(struct intel_gt *gt, i915_reg_t reg); u32 intel_gt_read_register(struct intel_gt *gt, i915_reg_t reg); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index acc4a3766dc1..feb372fc0b48 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -276,15 +276,24 @@ __mmio_reg_add(struct temp_regset *regset, struct guc_mmio_reg *reg) return slot; } -static long __must_check guc_mmio_reg_add(struct temp_regset *regset, - u32 offset, u32 flags) +#define GUC_REGSET_STEERING(group, instance) ( \ + FIELD_PREP(GUC_REGSET_STEERING_GROUP, (group)) | \ + FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, (instance)) | \ + GUC_REGSET_NEEDS_STEERING \ +) + +static long __must_check guc_mmio_reg_add(struct intel_gt *gt, + struct temp_regset *regset, + i915_reg_t reg, u32 flags) { u32 count = regset->storage_used - (regset->registers - regset->storage); - struct guc_mmio_reg reg = { + u32 offset = i915_mmio_reg_offset(reg); + struct guc_mmio_reg entry = { .offset = offset, .flags = flags, }; struct guc_mmio_reg *slot; + u8 group, inst; /* * The mmio list is built using separate lists within the driver. @@ -292,11 +301,22 @@ static long __must_check guc_mmio_reg_add(struct temp_regset *regset, * register more than once. Do not consider this an error; silently * move on if the register is already in the list. */ - if (bsearch(®, regset->registers, count, - sizeof(reg), guc_mmio_reg_cmp)) + if (bsearch(&entry, regset->registers, count, + sizeof(entry), guc_mmio_reg_cmp)) return 0; - slot = __mmio_reg_add(regset, ®); + /* + * The GuC doesn't have a default steering, so we need to explicitly + * steer all registers that need steering. However, we do not keep track + * of all the steering ranges, only of those that have a chance of using + * a non-default steering from the i915 pov. Instead of adding such + * tracking, it is easier to just program the default steering for all + * regs that don't need a non-default one. + */ + intel_gt_get_valid_steering_for_reg(gt, reg, &group, &inst); + entry.flags |= GUC_REGSET_STEERING(group, inst); + + slot = __mmio_reg_add(regset, &entry); if (IS_ERR(slot)) return PTR_ERR(slot); @@ -311,14 +331,16 @@ static long __must_check guc_mmio_reg_add(struct temp_regset *regset, return 0; } -#define GUC_MMIO_REG_ADD(regset, reg, masked) \ - guc_mmio_reg_add(regset, \ - i915_mmio_reg_offset((reg)), \ +#define GUC_MMIO_REG_ADD(gt, regset, reg, masked) \ + guc_mmio_reg_add(gt, \ + regset, \ + (reg), \ (masked) ? GUC_REGSET_MASKED : 0) static int guc_mmio_regset_init(struct temp_regset *regset, struct intel_engine_cs *engine) { + struct intel_gt *gt = engine->gt; const u32 base = engine->mmio_base; struct i915_wa_list *wal = &engine->wa_list; struct i915_wa *wa; @@ -331,26 +353,26 @@ static int guc_mmio_regset_init(struct temp_regset *regset, */ regset->registers = regset->storage + regset->storage_used; - ret |= GUC_MMIO_REG_ADD(regset, RING_MODE_GEN7(base), true); - ret |= GUC_MMIO_REG_ADD(regset, RING_HWS_PGA(base), false); - ret |= GUC_MMIO_REG_ADD(regset, RING_IMR(base), false); + ret |= GUC_MMIO_REG_ADD(gt, regset, RING_MODE_GEN7(base), true); + ret |= GUC_MMIO_REG_ADD(gt, regset, RING_HWS_PGA(base), false); + ret |= GUC_MMIO_REG_ADD(gt, regset, RING_IMR(base), false); if ((engine->flags & I915_ENGINE_FIRST_RENDER_COMPUTE) && CCS_MASK(engine->gt)) - ret |= GUC_MMIO_REG_ADD(regset, GEN12_RCU_MODE, true); + ret |= GUC_MMIO_REG_ADD(gt, regset, GEN12_RCU_MODE, true); for (i = 0, wa = wal->list; i < wal->count; i++, wa++) - ret |= GUC_MMIO_REG_ADD(regset, wa->reg, wa->masked_reg); + ret |= GUC_MMIO_REG_ADD(gt, regset, wa->reg, wa->masked_reg); /* Be extra paranoid and include all whitelist registers. */ for (i = 0; i < RING_MAX_NONPRIV_SLOTS; i++) - ret |= GUC_MMIO_REG_ADD(regset, + ret |= GUC_MMIO_REG_ADD(gt, regset, RING_FORCE_TO_NONPRIV(base, i), false); /* add in local MOCS registers */ for (i = 0; i < GEN9_LNCFCMOCS_REG_COUNT; i++) - ret |= GUC_MMIO_REG_ADD(regset, GEN9_LNCFCMOCS(i), false); + ret |= GUC_MMIO_REG_ADD(gt, regset, GEN9_LNCFCMOCS(i), false); return ret ? -1 : 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index a4a6136b3616..78590372b85f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -287,8 +287,11 @@ struct guc_mmio_reg { u32 flags; u32 mask; #define GUC_REGSET_MASKED BIT(0) +#define GUC_REGSET_NEEDS_STEERING BIT(1) #define GUC_REGSET_MASKED_WITH_VALUE BIT(2) #define GUC_REGSET_RESTORE_ONLY BIT(3) +#define GUC_REGSET_STEERING_GROUP GENMASK(15, 12) +#define GUC_REGSET_STEERING_INSTANCE GENMASK(23, 20) } __packed; /* GuC register sets */ From 31a86f0019b12f22546ca434f375194415834278 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 14 Mar 2022 16:42:03 -0700 Subject: [PATCH 00198/11454] drm/i915: Add support for steered register writes Upcoming patches will need to steer writes to multicast registers as well as reading them. Although the setting of the 'multicast' bit should only really matter for write operations (reads always operate in a unicast manner and give us the result from one specific instance), Wa_22013088509 suggests that we leave the multicast bit enabled when performing read operations, so we follow suit here. Cc: Harish Chegondi Signed-off-by: Matt Roper Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220314234203.799268-4-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/intel_gt_regs.h | 1 + drivers/gpu/drm/i915/intel_uncore.c | 75 ++++++++++++++++++++++--- drivers/gpu/drm/i915/intel_uncore.h | 4 +- 3 files changed, 70 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 19cd34f24263..62e0f075b1de 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -46,6 +46,7 @@ #define GEN8_MCR_SLICE_MASK GEN8_MCR_SLICE(3) #define GEN8_MCR_SUBSLICE(subslice) (((subslice) & 3) << 24) #define GEN8_MCR_SUBSLICE_MASK GEN8_MCR_SUBSLICE(3) +#define GEN11_MCR_MULTICAST REG_BIT(31) #define GEN11_MCR_SLICE(slice) (((slice) & 0xf) << 27) #define GEN11_MCR_SLICE_MASK GEN11_MCR_SLICE(0xf) #define GEN11_MCR_SUBSLICE(subslice) (((subslice) & 0x7) << 24) diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index dd8fdd5863de..ef8ffc01ad19 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -2464,17 +2464,46 @@ intel_uncore_forcewake_for_reg(struct intel_uncore *uncore, return fw_domains; } -u32 intel_uncore_read_with_mcr_steering_fw(struct intel_uncore *uncore, - i915_reg_t reg, - int slice, int subslice) +/** + * uncore_rw_with_mcr_steering_fw - Access a register after programming + * the MCR selector register. + * @uncore: pointer to struct intel_uncore + * @reg: register being accessed + * @rw_flag: FW_REG_READ for read access or FW_REG_WRITE for write access + * @slice: slice number (ignored for multi-cast write) + * @subslice: sub-slice number (ignored for multi-cast write) + * @value: register value to be written (ignored for read) + * + * Return: 0 for write access. register value for read access. + * + * Caller needs to make sure the relevant forcewake wells are up. + */ +static u32 uncore_rw_with_mcr_steering_fw(struct intel_uncore *uncore, + i915_reg_t reg, u8 rw_flag, + int slice, int subslice, u32 value) { - u32 mcr_mask, mcr_ss, mcr, old_mcr, val; + u32 mcr_mask, mcr_ss, mcr, old_mcr, val = 0; lockdep_assert_held(&uncore->lock); if (GRAPHICS_VER(uncore->i915) >= 11) { mcr_mask = GEN11_MCR_SLICE_MASK | GEN11_MCR_SUBSLICE_MASK; mcr_ss = GEN11_MCR_SLICE(slice) | GEN11_MCR_SUBSLICE(subslice); + + /* + * Wa_22013088509 + * + * The setting of the multicast/unicast bit usually wouldn't + * matter for read operations (which always return the value + * from a single register instance regardless of how that bit + * is set), but some platforms have a workaround requiring us + * to remain in multicast mode for reads. There's no real + * downside to this, so we'll just go ahead and do so on all + * platforms; we'll only clear the multicast bit from the mask + * when exlicitly doing a write operation. + */ + if (rw_flag == FW_REG_WRITE) + mcr_mask |= GEN11_MCR_MULTICAST; } else { mcr_mask = GEN8_MCR_SLICE_MASK | GEN8_MCR_SUBSLICE_MASK; mcr_ss = GEN8_MCR_SLICE(slice) | GEN8_MCR_SUBSLICE(subslice); @@ -2486,7 +2515,10 @@ u32 intel_uncore_read_with_mcr_steering_fw(struct intel_uncore *uncore, mcr |= mcr_ss; intel_uncore_write_fw(uncore, GEN8_MCR_SELECTOR, mcr); - val = intel_uncore_read_fw(uncore, reg); + if (rw_flag == FW_REG_READ) + val = intel_uncore_read_fw(uncore, reg); + else + intel_uncore_write_fw(uncore, reg, value); mcr &= ~mcr_mask; mcr |= old_mcr & mcr_mask; @@ -2496,14 +2528,16 @@ u32 intel_uncore_read_with_mcr_steering_fw(struct intel_uncore *uncore, return val; } -u32 intel_uncore_read_with_mcr_steering(struct intel_uncore *uncore, - i915_reg_t reg, int slice, int subslice) +static u32 uncore_rw_with_mcr_steering(struct intel_uncore *uncore, + i915_reg_t reg, u8 rw_flag, + int slice, int subslice, + u32 value) { enum forcewake_domains fw_domains; u32 val; fw_domains = intel_uncore_forcewake_for_reg(uncore, reg, - FW_REG_READ); + rw_flag); fw_domains |= intel_uncore_forcewake_for_reg(uncore, GEN8_MCR_SELECTOR, FW_REG_READ | FW_REG_WRITE); @@ -2511,7 +2545,8 @@ u32 intel_uncore_read_with_mcr_steering(struct intel_uncore *uncore, spin_lock_irq(&uncore->lock); intel_uncore_forcewake_get__locked(uncore, fw_domains); - val = intel_uncore_read_with_mcr_steering_fw(uncore, reg, slice, subslice); + val = uncore_rw_with_mcr_steering_fw(uncore, reg, rw_flag, + slice, subslice, value); intel_uncore_forcewake_put__locked(uncore, fw_domains); spin_unlock_irq(&uncore->lock); @@ -2519,6 +2554,28 @@ u32 intel_uncore_read_with_mcr_steering(struct intel_uncore *uncore, return val; } +u32 intel_uncore_read_with_mcr_steering_fw(struct intel_uncore *uncore, + i915_reg_t reg, int slice, int subslice) +{ + return uncore_rw_with_mcr_steering_fw(uncore, reg, FW_REG_READ, + slice, subslice, 0); +} + +u32 intel_uncore_read_with_mcr_steering(struct intel_uncore *uncore, + i915_reg_t reg, int slice, int subslice) +{ + return uncore_rw_with_mcr_steering(uncore, reg, FW_REG_READ, + slice, subslice, 0); +} + +void intel_uncore_write_with_mcr_steering(struct intel_uncore *uncore, + i915_reg_t reg, u32 value, + int slice, int subslice) +{ + uncore_rw_with_mcr_steering(uncore, reg, FW_REG_WRITE, + slice, subslice, value); +} + #if IS_ENABLED(CONFIG_DRM_I915_SELFTEST) #include "selftests/mock_uncore.c" #include "selftests/intel_uncore.c" diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index 6ff56d673e2b..9a760952d46a 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -214,7 +214,9 @@ u32 intel_uncore_read_with_mcr_steering_fw(struct intel_uncore *uncore, int slice, int subslice); u32 intel_uncore_read_with_mcr_steering(struct intel_uncore *uncore, i915_reg_t reg, int slice, int subslice); - +void intel_uncore_write_with_mcr_steering(struct intel_uncore *uncore, + i915_reg_t reg, u32 value, + int slice, int subslice); void intel_uncore_mmio_debug_init_early(struct intel_uncore_mmio_debug *mmio_debug); void intel_uncore_init_early(struct intel_uncore *uncore, From a4f24ada636dc0262621213988f0d15beb5596bb Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 16 Mar 2022 10:46:48 +0300 Subject: [PATCH 00199/11454] drm/blend: fix typo in the comment The documentation for drm_rotation_simplify() uses DRM_MODE_ROTATE_X, while it's clear the comment should mention DRM_MODE_REFLECT_X instead. The example passes all flags except the DRM_MODE_REFLECT_X as supported and expects to eliminate this flag. Fixes: c2c446ad2943 ("drm: Add DRM_MODE_ROTATE_ and DRM_MODE_REFLECT_ to UAPI") Signed-off-by: Dmitry Baryshkov Reviewed-by: Simon Ser Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220316074648.7009-1-dmitry.baryshkov@linaro.org --- drivers/gpu/drm/drm_blend.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_blend.c b/drivers/gpu/drm/drm_blend.c index ec37cbfabb50..46ee5d5df6b4 100644 --- a/drivers/gpu/drm/drm_blend.c +++ b/drivers/gpu/drm/drm_blend.c @@ -317,7 +317,7 @@ EXPORT_SYMBOL(drm_plane_create_rotation_property); * DRM_MODE_ROTATE_90 | DRM_MODE_ROTATE_180 | * DRM_MODE_ROTATE_270 | DRM_MODE_REFLECT_Y); * - * to eliminate the DRM_MODE_ROTATE_X flag. Depending on what kind of + * to eliminate the DRM_MODE_REFLECT_X flag. Depending on what kind of * transforms the hardware supports, this function may not * be able to produce a supported transform, so the caller should * check the result afterwards. From 1c7cea157912ec8229b116c9274a18653689e193 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Feb 2022 12:04:00 +0200 Subject: [PATCH 00200/11454] drm/i915: Use drm_mode_copy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct drm_display_mode embeds a list head, so overwriting the full struct with another one will corrupt the list (if the destination mode is on a list). Use drm_mode_copy() instead which explicitly preserves the list head of the destination mode. Even if we know the destination mode is not on any list using drm_mode_copy() seems decent as it sets a good example. Bad examples of not using it might eventually get copied into code where preserving the list head actually matters. Obviously one case not covered here is when the mode itself is embedded in a larger structure and the whole structure is copied. But if we are careful when copying into modes embedded in structures I think we can be a little more reassured that bogus list heads haven't been propagated in. @is_mode_copy@ @@ drm_mode_copy(...) { ... } @depends on !is_mode_copy@ struct drm_display_mode *mode; expression E, S; @@ ( - *mode = E + drm_mode_copy(mode, &E) | - memcpy(mode, E, S) + drm_mode_copy(mode, E) ) @depends on !is_mode_copy@ struct drm_display_mode mode; expression E; @@ ( - mode = E + drm_mode_copy(&mode, &E) | - memcpy(&mode, E, S) + drm_mode_copy(&mode, E) ) @@ struct drm_display_mode *mode; @@ - &*mode + mode Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220218100403.7028-20-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_display.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6817a3dcf72b..7aee15ee49bf 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5571,8 +5571,10 @@ intel_crtc_copy_uapi_to_hw_state_modeset(struct intel_atomic_state *state, crtc_state->hw.enable = crtc_state->uapi.enable; crtc_state->hw.active = crtc_state->uapi.active; - crtc_state->hw.mode = crtc_state->uapi.mode; - crtc_state->hw.adjusted_mode = crtc_state->uapi.adjusted_mode; + drm_mode_copy(&crtc_state->hw.mode, + &crtc_state->uapi.mode); + drm_mode_copy(&crtc_state->hw.adjusted_mode, + &crtc_state->uapi.adjusted_mode); crtc_state->hw.scaling_filter = crtc_state->uapi.scaling_filter; intel_crtc_copy_uapi_to_hw_state_nomodeset(state, crtc); @@ -5652,9 +5654,12 @@ copy_bigjoiner_crtc_state_modeset(struct intel_atomic_state *state, memset(&slave_crtc_state->hw, 0, sizeof(slave_crtc_state->hw)); slave_crtc_state->hw.enable = master_crtc_state->hw.enable; slave_crtc_state->hw.active = master_crtc_state->hw.active; - slave_crtc_state->hw.mode = master_crtc_state->hw.mode; - slave_crtc_state->hw.pipe_mode = master_crtc_state->hw.pipe_mode; - slave_crtc_state->hw.adjusted_mode = master_crtc_state->hw.adjusted_mode; + drm_mode_copy(&slave_crtc_state->hw.mode, + &master_crtc_state->hw.mode); + drm_mode_copy(&slave_crtc_state->hw.pipe_mode, + &master_crtc_state->hw.pipe_mode); + drm_mode_copy(&slave_crtc_state->hw.adjusted_mode, + &master_crtc_state->hw.adjusted_mode); slave_crtc_state->hw.scaling_filter = master_crtc_state->hw.scaling_filter; copy_bigjoiner_crtc_state_nomodeset(state, slave_crtc); From 2260e4d8f51c014575eef595873351c83bc9ce4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2022 15:27:44 +0200 Subject: [PATCH 00201/11454] drm/i915: Put the downclock_mode check back into can_enable_drrs() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With static DRRS the user might ask for the lowest possible refresh rate of the panel, in which case we're not going to find a suitable downclock mode for it and we should not try to enable seamless DRRS. This will in fact oops. We used to check for the presence of the downclock mode here, but that got removed in commit f0a57798fb5c ("drm/i915: Introduce intel_panel_drrs_type()") as redundant (which it was at the time). But we do need the check again now that static DRRS is a thing. I must have not re-tested static DRRS fully after introducing intel_panel_drrs_type() :/ Fixes: c5ee23437cae ("drm/i915: Implement static DRRS") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315132752.11849-2-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_drrs.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 2bbc0388263a..e1b41b772521 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -62,7 +62,8 @@ const char *intel_drrs_type_str(enum drrs_type drrs_type) } static bool can_enable_drrs(struct intel_connector *connector, - const struct intel_crtc_state *pipe_config) + const struct intel_crtc_state *pipe_config, + const struct drm_display_mode *downclock_mode) { if (pipe_config->vrr.enable) return false; @@ -76,7 +77,8 @@ static bool can_enable_drrs(struct intel_connector *connector, if (pipe_config->has_psr) return false; - return intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; + return downclock_mode && + intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; } void @@ -89,7 +91,7 @@ intel_drrs_compute_config(struct intel_connector *connector, intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); int pixel_clock; - if (!can_enable_drrs(connector, pipe_config)) { + if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder)) intel_zero_m_n(&pipe_config->dp_m2_n2); return; From ead8fb9c78483bec601c5a8ac885dcb1f8ecf783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2022 15:27:45 +0200 Subject: [PATCH 00202/11454] drm/i915: Add missing tab to DRRS debugfs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The DRRS refresh rate should be indented by one tab like the other per-crtc DRRS stuff. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315132752.11849-3-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index b3d426cc3266..e0a126e7ebb8 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1171,7 +1171,7 @@ static int i915_drrs_status(struct seq_file *m, void *unused) seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X\n", crtc->drrs.busy_frontbuffer_bits); - seq_printf(m, "DRRS refresh rate: %s\n", + seq_printf(m, "\tDRRS refresh rate: %s\n", crtc->drrs.refresh_rate == DRRS_REFRESH_RATE_LOW ? "low" : "high"); From 18f23b92187ff75f8381aecd8b89c8feeddcab09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2022 15:27:46 +0200 Subject: [PATCH 00203/11454] drm/i915: Fix DRRS frontbuffer_bits handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that DRRS can operate on multiple pipes we need to make sure one pipe doesn't throw away the other pipe's frontbuffer_bits before said pipe can handle them. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315132752.11849-4-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_drrs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index e1b41b772521..e9d622fe66b3 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -258,7 +258,7 @@ static void intel_drrs_downclock_work(struct work_struct *work) } static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, - unsigned int frontbuffer_bits, + unsigned int all_frontbuffer_bits, bool invalidate) { struct intel_crtc *crtc; @@ -267,6 +267,8 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, return; for_each_intel_crtc(&dev_priv->drm, crtc) { + unsigned int frontbuffer_bits; + cancel_delayed_work(&crtc->drrs.work); mutex_lock(&crtc->drrs.mutex); @@ -276,7 +278,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, continue; } - frontbuffer_bits &= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); + frontbuffer_bits = all_frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); if (invalidate) crtc->drrs.busy_frontbuffer_bits |= frontbuffer_bits; else From 70e10a2b7e989d1e1069f701c4159c20f52a1dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2022 15:27:47 +0200 Subject: [PATCH 00204/11454] drm/i915: Determine DRRS frontbuffer_bits ahead of time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pre-determine the frontbuffer_bits for the each pipe during intel_drrs_enable(). Will become useful for bigjoiner use cases soon. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315132752.11849-5-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display_types.h | 1 + drivers/gpu/drm/i915/display/intel_drrs.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index d84e82f3eab9..c94eb7d5191d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1302,6 +1302,7 @@ struct intel_crtc { struct mutex mutex; struct delayed_work work; enum drrs_refresh_rate refresh_rate; + unsigned int frontbuffer_bits; unsigned int busy_frontbuffer_bits; enum transcoder cpu_transcoder; struct intel_link_m_n m_n, m2_n2; diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index e9d622fe66b3..91aab77c495c 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -168,6 +168,13 @@ static void intel_drrs_set_state(struct intel_crtc *crtc, crtc->drrs.refresh_rate = refresh_rate; } +static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + + return INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); +} + /** * intel_drrs_enable - init drrs struct if supported * @crtc_state: A pointer to the active crtc state. @@ -190,6 +197,7 @@ void intel_drrs_enable(const struct intel_crtc_state *crtc_state) crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder; crtc->drrs.m_n = crtc_state->dp_m_n; crtc->drrs.m2_n2 = crtc_state->dp_m2_n2; + crtc->drrs.frontbuffer_bits = intel_drrs_frontbuffer_bits(crtc_state); crtc->drrs.busy_frontbuffer_bits = 0; mutex_unlock(&crtc->drrs.mutex); @@ -216,6 +224,7 @@ void intel_drrs_disable(const struct intel_crtc_state *old_crtc_state) intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; + crtc->drrs.frontbuffer_bits = 0; crtc->drrs.busy_frontbuffer_bits = 0; mutex_unlock(&crtc->drrs.mutex); @@ -278,7 +287,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, continue; } - frontbuffer_bits = all_frontbuffer_bits & INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); + frontbuffer_bits = all_frontbuffer_bits & crtc->drrs.frontbuffer_bits; if (invalidate) crtc->drrs.busy_frontbuffer_bits |= frontbuffer_bits; else From fb4ae6e6500a7ca70b41a765eb4189740b7725f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2022 15:27:48 +0200 Subject: [PATCH 00205/11454] drm/i915: Don't cancel/schedule drrs work if the pipe wasn't affected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skip all the DRRS work cancel/schedule stuff if the pipe's frontbuffer bits were not among those affected by the frontbuffer rendering. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315132752.11849-6-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_drrs.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 91aab77c495c..f36394fd85be 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -278,32 +278,31 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, for_each_intel_crtc(&dev_priv->drm, crtc) { unsigned int frontbuffer_bits; - cancel_delayed_work(&crtc->drrs.work); - mutex_lock(&crtc->drrs.mutex); - if (!intel_drrs_is_enabled(crtc)) { + frontbuffer_bits = all_frontbuffer_bits & crtc->drrs.frontbuffer_bits; + if (!frontbuffer_bits) { mutex_unlock(&crtc->drrs.mutex); continue; } - frontbuffer_bits = all_frontbuffer_bits & crtc->drrs.frontbuffer_bits; if (invalidate) crtc->drrs.busy_frontbuffer_bits |= frontbuffer_bits; else crtc->drrs.busy_frontbuffer_bits &= ~frontbuffer_bits; /* flush/invalidate means busy screen hence upclock */ - if (frontbuffer_bits) - intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); + intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); /* * flush also means no more activity hence schedule downclock, if all * other fbs are quiescent too */ - if (!invalidate && !crtc->drrs.busy_frontbuffer_bits) - schedule_delayed_work(&crtc->drrs.work, - msecs_to_jiffies(1000)); + if (!crtc->drrs.busy_frontbuffer_bits) + mod_delayed_work(system_wq, &crtc->drrs.work, + msecs_to_jiffies(1000)); + else + cancel_delayed_work(&crtc->drrs.work); mutex_unlock(&crtc->drrs.mutex); } From 1c00404769dcd4b51c691aeba9eb98d72632720e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2022 15:27:49 +0200 Subject: [PATCH 00206/11454] drm/i915: Schedule DRRS work from intel_drrs_enable() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Schedule the DRRS downclock work already from intel_drrs_enable() instead of waiting around for a frontbuffer flush that may or may not ever come. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315132752.11849-7-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_drrs.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index f36394fd85be..8f9e0fde0c5a 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -168,6 +168,11 @@ static void intel_drrs_set_state(struct intel_crtc *crtc, crtc->drrs.refresh_rate = refresh_rate; } +static void intel_drrs_schedule_work(struct intel_crtc *crtc) +{ + mod_delayed_work(system_wq, &crtc->drrs.work, msecs_to_jiffies(1000)); +} + static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -200,6 +205,8 @@ void intel_drrs_enable(const struct intel_crtc_state *crtc_state) crtc->drrs.frontbuffer_bits = intel_drrs_frontbuffer_bits(crtc_state); crtc->drrs.busy_frontbuffer_bits = 0; + intel_drrs_schedule_work(crtc); + mutex_unlock(&crtc->drrs.mutex); } @@ -299,8 +306,7 @@ static void intel_drrs_frontbuffer_update(struct drm_i915_private *dev_priv, * other fbs are quiescent too */ if (!crtc->drrs.busy_frontbuffer_bits) - mod_delayed_work(system_wq, &crtc->drrs.work, - msecs_to_jiffies(1000)); + intel_drrs_schedule_work(crtc); else cancel_delayed_work(&crtc->drrs.work); From 1b333c679a0fdfd899269b7e10a002aad334a15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2022 23:39:44 +0200 Subject: [PATCH 00207/11454] drm/i915: Do DRRS disable/enable during pre/post_plane_update() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's just do a full DRRS disable/enable across all pipe updates. This guarantees that the DRRS work doesn't interfere with anything while the atomic commit is busy reprogramming the pipe. Needed so that we can start reprogramming M/N seamlessly during fastsets whenever possible. Also avoids the pre-bdw DRRS PIPECONF rmw racing with the potential PIPECONF write from the atomic commit (eg. due to GAMMA_MODE changes). v2: Include has_drrs in state dump (José) Reviewed-by: José Roberto de Souza Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315213944.17132-1-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_ddi.c | 4 -- drivers/gpu/drm/i915/display/intel_display.c | 13 +++---- drivers/gpu/drm/i915/display/intel_drrs.c | 40 ++------------------ drivers/gpu/drm/i915/display/intel_drrs.h | 3 -- 4 files changed, 10 insertions(+), 50 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index e2b297d2c295..dc208df829f1 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -45,7 +45,6 @@ #include "intel_dp_link_training.h" #include "intel_dp_mst.h" #include "intel_dpio_phy.h" -#include "intel_drrs.h" #include "intel_dsi.h" #include "intel_fdi.h" #include "intel_fifo_underrun.h" @@ -3010,12 +3009,9 @@ static void intel_ddi_update_pipe_dp(struct intel_atomic_state *state, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { - struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - intel_ddi_set_dp_msa(crtc_state, conn_state); intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); - intel_drrs_update(state, crtc); intel_backlight_update(state, encoder, crtc_state, conn_state); drm_connector_update_privacy_screen(conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7aee15ee49bf..6ed976b77b1c 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1229,7 +1229,6 @@ static void intel_post_plane_update(struct intel_atomic_state *state, hsw_ips_post_update(state, crtc); intel_fbc_post_update(state, crtc); - intel_drrs_page_flip(crtc); if (needs_async_flip_vtd_wa(old_crtc_state) && !needs_async_flip_vtd_wa(new_crtc_state)) @@ -1247,6 +1246,7 @@ static void intel_post_plane_update(struct intel_atomic_state *state, !needs_cursorclk_wa(new_crtc_state)) icl_wa_cursorclkgating(dev_priv, pipe, false); + intel_drrs_enable(new_crtc_state); } static void intel_crtc_enable_flip_done(struct intel_atomic_state *state, @@ -1324,6 +1324,8 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); enum pipe pipe = crtc->pipe; + intel_drrs_disable(old_crtc_state); + intel_psr_pre_plane_update(state, crtc); if (hsw_ips_pre_update(state, crtc)) @@ -5442,8 +5444,9 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, str_enabled_disabled(pipe_config->pch_pfit.enabled), str_yes_no(pipe_config->pch_pfit.force_thru)); - drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i\n", - pipe_config->ips_enabled, pipe_config->double_wide); + drm_dbg_kms(&dev_priv->drm, "ips: %i, double wide: %i, drrs: %i\n", + pipe_config->ips_enabled, pipe_config->double_wide, + pipe_config->has_drrs); intel_dpll_dump_hw_state(dev_priv, &pipe_config->dpll_hw_state); @@ -8119,8 +8122,6 @@ static void intel_enable_crtc(struct intel_atomic_state *state, if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) return; - intel_drrs_enable(new_crtc_state); - /* vblanks work again, re-enable pipe CRC. */ intel_crtc_enable_pipe_crc(crtc); } @@ -8190,8 +8191,6 @@ static void intel_old_crtc_state_disables(struct intel_atomic_state *state, */ intel_crtc_disable_pipe_crc(crtc); - intel_drrs_disable(old_crtc_state); - dev_priv->display->crtc_disable(state, crtc); crtc->active = false; intel_fbc_disable(crtc); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 8f9e0fde0c5a..44c9af8f8b9b 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -189,13 +189,12 @@ static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *c void intel_drrs_enable(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (!crtc_state->has_drrs) return; - drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Enabling DRRS\n", - crtc->base.base.id, crtc->base.name); + if (!crtc_state->hw.active) + return; mutex_lock(&crtc->drrs.mutex); @@ -217,13 +216,12 @@ void intel_drrs_enable(const struct intel_crtc_state *crtc_state) void intel_drrs_disable(const struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (!old_crtc_state->has_drrs) return; - drm_dbg_kms(&dev_priv->drm, "[CRTC:%d:%s] Disabling DRRS\n", - crtc->base.base.id, crtc->base.name); + if (!old_crtc_state->hw.active) + return; mutex_lock(&crtc->drrs.mutex); @@ -239,28 +237,6 @@ void intel_drrs_disable(const struct intel_crtc_state *old_crtc_state) cancel_delayed_work_sync(&crtc->drrs.work); } -/** - * intel_drrs_update - Update DRRS during fastset - * @state: atomic state - * @crtc: crtc - */ -void intel_drrs_update(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - const struct intel_crtc_state *old_crtc_state = - intel_atomic_get_old_crtc_state(state, crtc); - const struct intel_crtc_state *new_crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - - if (old_crtc_state->has_drrs == new_crtc_state->has_drrs) - return; - - if (new_crtc_state->has_drrs) - intel_drrs_enable(new_crtc_state); - else - intel_drrs_disable(old_crtc_state); -} - static void intel_drrs_downclock_work(struct work_struct *work) { struct intel_crtc *crtc = container_of(work, typeof(*crtc), drrs.work.work); @@ -348,14 +324,6 @@ void intel_drrs_flush(struct drm_i915_private *dev_priv, intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false); } -void intel_drrs_page_flip(struct intel_crtc *crtc) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - unsigned int frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); - - intel_drrs_frontbuffer_update(dev_priv, frontbuffer_bits, false); -} - /** * intel_crtc_drrs_init - Init DRRS for CRTC * @crtc: crtc diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index c6e325a91552..6e84b8e800a6 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -19,13 +19,10 @@ const char *intel_drrs_type_str(enum drrs_type drrs_type); bool intel_drrs_is_enabled(struct intel_crtc *crtc); void intel_drrs_enable(const struct intel_crtc_state *crtc_state); void intel_drrs_disable(const struct intel_crtc_state *crtc_state); -void intel_drrs_update(struct intel_atomic_state *state, - struct intel_crtc *crtc); void intel_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_drrs_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); -void intel_drrs_page_flip(struct intel_crtc *crtc); void intel_drrs_compute_config(struct intel_connector *connector, struct intel_crtc_state *pipe_config, int output_bpp, bool constant_n); From 579899c7da714fac736b13fdb202e0a2cb9d3d27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2022 15:27:51 +0200 Subject: [PATCH 00208/11454] drm/i915: Deal with bigjoiner vs. DRRS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DRRS operates on transcoder level, so we should only poke at it from the master crtc rather than letting every joined pipe give it potentially conflicting input. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315132752.11849-9-ville.syrjala@linux.intel.com Reviewed-by: Manasi Navare --- drivers/gpu/drm/i915/display/intel_drrs.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 44c9af8f8b9b..9a341ab1a848 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -176,8 +176,16 @@ static void intel_drrs_schedule_work(struct intel_crtc *crtc) static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + unsigned int frontbuffer_bits; - return INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); + frontbuffer_bits = INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); + + for_each_intel_crtc_in_pipe_mask(&i915->drm, crtc, + crtc_state->bigjoiner_pipes) + frontbuffer_bits |= INTEL_FRONTBUFFER_ALL_MASK(crtc->pipe); + + return frontbuffer_bits; } /** @@ -196,6 +204,9 @@ void intel_drrs_enable(const struct intel_crtc_state *crtc_state) if (!crtc_state->hw.active) return; + if (intel_crtc_is_bigjoiner_slave(crtc_state)) + return; + mutex_lock(&crtc->drrs.mutex); crtc->drrs.cpu_transcoder = crtc_state->cpu_transcoder; @@ -223,6 +234,9 @@ void intel_drrs_disable(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->hw.active) return; + if (intel_crtc_is_bigjoiner_slave(old_crtc_state)) + return; + mutex_lock(&crtc->drrs.mutex); if (intel_drrs_is_enabled(crtc)) From 47042e0ddd218f100292cebc5208cb1eff7473b6 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Sat, 12 Mar 2022 14:34:37 +0800 Subject: [PATCH 00209/11454] drm/solomon: Make DRM_SSD130X depends on MMU WARNING: unmet direct dependencies detected for DRM_GEM_SHMEM_HELPER Depends on [n]: HAS_IOMEM [=y] && DRM [=m] && MMU [=n] Selected by [m]: - DRM_SSD130X [=m] && HAS_IOMEM [=y] && DRM [=m] DRM_GEM_SHMEM_HELPER depends on MMU, DRM_SSD130X should also depends on MMU. Fixes: a61732e80867 ("drm: Add driver for Solomon SSD130x OLED displays") Signed-off-by: YueHaibing Acked-by: Javier Martinez Canillas Signed-off-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20220312063437.19160-1-yuehaibing@huawei.com --- drivers/gpu/drm/solomon/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/solomon/Kconfig b/drivers/gpu/drm/solomon/Kconfig index 5861c3ab7c45..6230369505c9 100644 --- a/drivers/gpu/drm/solomon/Kconfig +++ b/drivers/gpu/drm/solomon/Kconfig @@ -1,6 +1,6 @@ config DRM_SSD130X tristate "DRM support for Solomon SSD130x OLED displays" - depends on DRM + depends on DRM && MMU select BACKLIGHT_CLASS_DEVICE select DRM_GEM_SHMEM_HELPER select DRM_KMS_HELPER From e5086cb3f3d3f94091be29eec38cf13f8a75a778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 11 Mar 2022 23:28:45 +0200 Subject: [PATCH 00210/11454] drm/i915: Reject unsupported TMDS rates on ICL+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ICL+ PLLs can't genenerate certain frequencies. Running the PLL algorithms through for all frequencies 25-594MHz we see a gap just above 500 MHz. Specifically 500-522.8MHZ for TC PLLs, and 500-533.2 MHz for combo PHY PLLs. Reject those frequencies hdmi_port_clock_valid() so that we properly filter out unsupported modes and/or color depths for HDMI. Cc: stable@vger.kernel.org Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5247 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311212845.32358-1-ville.syrjala@linux.intel.com Reviewed-by: Mika Kahola --- drivers/gpu/drm/i915/display/intel_hdmi.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/i915/display/intel_hdmi.c b/drivers/gpu/drm/i915/display/intel_hdmi.c index f3e688f739f3..a4a6f8bd2841 100644 --- a/drivers/gpu/drm/i915/display/intel_hdmi.c +++ b/drivers/gpu/drm/i915/display/intel_hdmi.c @@ -1837,6 +1837,7 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, bool has_hdmi_sink) { struct drm_i915_private *dev_priv = intel_hdmi_to_i915(hdmi); + enum phy phy = intel_port_to_phy(dev_priv, hdmi_to_dig_port(hdmi)->base.port); if (clock < 25000) return MODE_CLOCK_LOW; @@ -1857,6 +1858,14 @@ hdmi_port_clock_valid(struct intel_hdmi *hdmi, if (IS_CHERRYVIEW(dev_priv) && clock > 216000 && clock < 240000) return MODE_CLOCK_RANGE; + /* ICL+ combo PHY PLL can't generate 500-533.2 MHz */ + if (intel_phy_is_combo(dev_priv, phy) && clock > 500000 && clock < 533200) + return MODE_CLOCK_RANGE; + + /* ICL+ TC PHY PLL can't generate 500-532.8 MHz */ + if (intel_phy_is_tc(dev_priv, phy) && clock > 500000 && clock < 532800) + return MODE_CLOCK_RANGE; + /* * SNPS PHYs' MPLLB table-based programming can only handle a fixed * set of link rates. From de2d1822f9489268e0707b2d188dd789d5effd08 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:11 +0100 Subject: [PATCH 00211/11454] drm/gma500: Remove struct psb_gem_object.npage Calculate the number of pages in the BO's backing storage from the size. Remove the npage field. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-2-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gem.c | 9 +++++---- drivers/gpu/drm/gma500/gem.h | 1 - drivers/gpu/drm/gma500/gma_display.c | 8 +++----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index 8d65af80bb08..fe7d242567c0 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -51,7 +51,6 @@ int psb_gem_pin(struct psb_gem_object *pobj) (gpu_base + pobj->offset), npages, 0, 0, PSB_MMU_CACHED_MEMORY); - pobj->npage = npages; pobj->pages = pages; out: @@ -71,6 +70,7 @@ void psb_gem_unpin(struct psb_gem_object *pobj) struct drm_device *dev = obj->dev; struct drm_psb_private *dev_priv = to_drm_psb_private(dev); u32 gpu_base = dev_priv->gtt.gatt_start; + unsigned long npages; mutex_lock(&dev_priv->gtt_mutex); @@ -81,16 +81,17 @@ void psb_gem_unpin(struct psb_gem_object *pobj) if (pobj->in_gart || pobj->stolen) goto out; + npages = obj->size / PAGE_SIZE; + psb_mmu_remove_pages(psb_mmu_get_default_pd(dev_priv->mmu), - (gpu_base + pobj->offset), pobj->npage, 0, 0); + (gpu_base + pobj->offset), npages, 0, 0); psb_gtt_remove_pages(dev_priv, &pobj->resource); /* Reset caching flags */ - set_pages_array_wb(pobj->pages, pobj->npage); + set_pages_array_wb(pobj->pages, npages); drm_gem_put_pages(obj, pobj->pages, true, false); pobj->pages = NULL; - pobj->npage = 0; out: mutex_unlock(&dev_priv->gtt_mutex); diff --git a/drivers/gpu/drm/gma500/gem.h b/drivers/gpu/drm/gma500/gem.h index 79cced40c87f..96ef864b4bf1 100644 --- a/drivers/gpu/drm/gma500/gem.h +++ b/drivers/gpu/drm/gma500/gem.h @@ -23,7 +23,6 @@ struct psb_gem_object { bool stolen; /* Backed from stolen RAM */ bool mmapping; /* Is mmappable */ struct page **pages; /* Backing pages if present */ - int npage; /* Number of backing pages */ }; static inline struct psb_gem_object *to_psb_gem_object(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 60ba7de59139..dd801404cf99 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -391,11 +391,9 @@ int gma_crtc_cursor_set(struct drm_crtc *crtc, goto unref_cursor; } - /* Prevent overflow */ - if (pobj->npage > 4) - cursor_pages = 4; - else - cursor_pages = pobj->npage; + cursor_pages = obj->size / PAGE_SIZE; + if (cursor_pages > 4) + cursor_pages = 4; /* Prevent overflow */ /* Copy the cursor to cursor mem */ tmp_dst = dev_priv->vram_addr + cursor_pobj->offset; From 16dad99de8f2abfcec9836e2031613a713e339d2 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:12 +0100 Subject: [PATCH 00212/11454] drm/gma500: Acquire reservation lock for GEM objects Protect concurrent access to struct psb_gem_object by acquiring the GEM object's reservation lock; as it's supposed to be. The use of the GTT mutex can now be moved into GTT code. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-3-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gem.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index fe7d242567c0..026ce11f7460 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -31,6 +31,10 @@ int psb_gem_pin(struct psb_gem_object *pobj) unsigned int npages; int ret; + ret = dma_resv_lock(obj->resv, NULL); + if (drm_WARN_ONCE(dev, ret, "dma_resv_lock() failed, ret=%d\n", ret)) + return ret; + mutex_lock(&dev_priv->gtt_mutex); if (pobj->in_gart || pobj->stolen) @@ -56,11 +60,13 @@ int psb_gem_pin(struct psb_gem_object *pobj) out: ++pobj->in_gart; mutex_unlock(&dev_priv->gtt_mutex); + dma_resv_unlock(obj->resv); return 0; err_mutex_unlock: mutex_unlock(&dev_priv->gtt_mutex); + dma_resv_unlock(obj->resv); return ret; } @@ -71,6 +77,11 @@ void psb_gem_unpin(struct psb_gem_object *pobj) struct drm_psb_private *dev_priv = to_drm_psb_private(dev); u32 gpu_base = dev_priv->gtt.gatt_start; unsigned long npages; + int ret; + + ret = dma_resv_lock(obj->resv, NULL); + if (drm_WARN_ONCE(dev, ret, "dma_resv_lock() failed, ret=%d\n", ret)) + return; mutex_lock(&dev_priv->gtt_mutex); @@ -95,6 +106,7 @@ void psb_gem_unpin(struct psb_gem_object *pobj) out: mutex_unlock(&dev_priv->gtt_mutex); + dma_resv_unlock(obj->resv); } static vm_fault_t psb_gem_fault(struct vm_fault *vmf); From 14e92dd104cde77db5612b111baf2f41f1eba127 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:13 +0100 Subject: [PATCH 00213/11454] drm/gma500: Move GTT locking into GTT helpers Acquire the GTT mutex in psb_gtt_{insert,remove}_pages(). Remove locking from callers. Also remove the GTT locking around the resume code. Resume does not run concurrently with other GTT operations. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-4-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gem.c | 11 ++--------- drivers/gpu/drm/gma500/gtt.c | 24 +++++++++++------------- 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index 026ce11f7460..2f44535f58e7 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -35,15 +35,13 @@ int psb_gem_pin(struct psb_gem_object *pobj) if (drm_WARN_ONCE(dev, ret, "dma_resv_lock() failed, ret=%d\n", ret)) return ret; - mutex_lock(&dev_priv->gtt_mutex); - if (pobj->in_gart || pobj->stolen) goto out; /* already mapped */ pages = drm_gem_get_pages(obj); if (IS_ERR(pages)) { ret = PTR_ERR(pages); - goto err_mutex_unlock; + goto err_dma_resv_unlock; } npages = obj->size / PAGE_SIZE; @@ -59,13 +57,11 @@ int psb_gem_pin(struct psb_gem_object *pobj) out: ++pobj->in_gart; - mutex_unlock(&dev_priv->gtt_mutex); dma_resv_unlock(obj->resv); return 0; -err_mutex_unlock: - mutex_unlock(&dev_priv->gtt_mutex); +err_dma_resv_unlock: dma_resv_unlock(obj->resv); return ret; } @@ -83,8 +79,6 @@ void psb_gem_unpin(struct psb_gem_object *pobj) if (drm_WARN_ONCE(dev, ret, "dma_resv_lock() failed, ret=%d\n", ret)) return; - mutex_lock(&dev_priv->gtt_mutex); - WARN_ON(!pobj->in_gart); --pobj->in_gart; @@ -105,7 +99,6 @@ void psb_gem_unpin(struct psb_gem_object *pobj) pobj->pages = NULL; out: - mutex_unlock(&dev_priv->gtt_mutex); dma_resv_unlock(obj->resv); } diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 309ffe921bfd..4202e88e5f84 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -74,11 +74,7 @@ static u32 __iomem *psb_gtt_entry(struct drm_psb_private *pdev, const struct res return pdev->gtt_map + (offset >> PAGE_SHIFT); } -/* - * Take our preallocated GTT range and insert the GEM object into - * the GTT. This is protected via the gtt mutex which the caller - * must hold. - */ +/* Acquires GTT mutex internally. */ void psb_gtt_insert_pages(struct drm_psb_private *pdev, const struct resource *res, struct page **pages) { @@ -86,6 +82,8 @@ void psb_gtt_insert_pages(struct drm_psb_private *pdev, const struct resource *r u32 __iomem *gtt_slot; u32 pte; + mutex_lock(&pdev->gtt_mutex); + /* Write our page entries into the GTT itself */ npages = resource_size(res) >> PAGE_SHIFT; @@ -98,19 +96,19 @@ void psb_gtt_insert_pages(struct drm_psb_private *pdev, const struct resource *r /* Make sure all the entries are set before we return */ ioread32(gtt_slot - 1); + + mutex_unlock(&pdev->gtt_mutex); } -/* - * Remove a preallocated GTT range from the GTT. Overwrite all the - * page table entries with the dummy page. This is protected via the gtt - * mutex which the caller must hold. - */ +/* Acquires GTT mutex internally. */ void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *res) { resource_size_t npages, i; u32 __iomem *gtt_slot; u32 pte; + mutex_lock(&pdev->gtt_mutex); + /* Install scratch page for the resource */ pte = psb_gtt_mask_pte(page_to_pfn(pdev->scratch_page), PSB_MMU_CACHED_MEMORY); @@ -123,6 +121,8 @@ void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *r /* Make sure all the entries are set before we return */ ioread32(gtt_slot - 1); + + mutex_unlock(&pdev->gtt_mutex); } static void psb_gtt_alloc(struct drm_device *dev) @@ -306,8 +306,6 @@ int psb_gtt_restore(struct drm_device *dev) struct psb_gem_object *pobj; unsigned int restored = 0, total = 0, size = 0; - /* On resume, the gtt_mutex is already initialized */ - mutex_lock(&dev_priv->gtt_mutex); psb_gtt_init(dev, 1); while (r != NULL) { @@ -325,7 +323,7 @@ int psb_gtt_restore(struct drm_device *dev) r = r->sibling; total++; } - mutex_unlock(&dev_priv->gtt_mutex); + DRM_DEBUG_DRIVER("Restored %u of %u gtt ranges (%u KB)", restored, total, (size / 1024)); From e160b70ba1604b0c88f97f7f8756d126515ed039 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:14 +0100 Subject: [PATCH 00214/11454] drm/gma500: Remove struct psb_gtt.sem sempahore The semaphore at struct psb_mmu_driver.sem protects access to the MMU fields. Additional locking with struct psb_gtt.sem is unnecessary. Remove the field and related code. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-5-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gtt.c | 7 ------- drivers/gpu/drm/gma500/gtt.h | 1 - drivers/gpu/drm/gma500/psb_drv.c | 4 ---- 3 files changed, 12 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 4202e88e5f84..c7b7cb1f2d13 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -125,12 +125,6 @@ void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *r mutex_unlock(&pdev->gtt_mutex); } -static void psb_gtt_alloc(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - init_rwsem(&dev_priv->gtt.sem); -} - void psb_gtt_takedown(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); @@ -166,7 +160,6 @@ int psb_gtt_init(struct drm_device *dev, int resume) if (!resume) { mutex_init(&dev_priv->gtt_mutex); mutex_init(&dev_priv->mmap_mutex); - psb_gtt_alloc(dev); } pg = &dev_priv->gtt; diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h index ff1dcdd1ff52..31500533ac45 100644 --- a/drivers/gpu/drm/gma500/gtt.h +++ b/drivers/gpu/drm/gma500/gtt.h @@ -22,7 +22,6 @@ struct psb_gtt { unsigned gatt_pages; unsigned long stolen_size; unsigned long vram_stolen_size; - struct rw_semaphore sem; }; /* Exported functions */ diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index eeb681be9c95..7227a8e44d23 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -184,13 +184,11 @@ static void psb_driver_unload(struct drm_device *dev) if (dev_priv->mmu) { struct psb_gtt *pg = &dev_priv->gtt; - down_read(&pg->sem); psb_mmu_remove_pfn_sequence( psb_mmu_get_default_pd (dev_priv->mmu), pg->mmu_gatt_start, dev_priv->vram_stolen_size >> PAGE_SHIFT); - up_read(&pg->sem); psb_mmu_driver_takedown(dev_priv->mmu); dev_priv->mmu = NULL; } @@ -345,12 +343,10 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) return ret; /* Add stolen memory to SGX MMU */ - down_read(&pg->sem); ret = psb_mmu_insert_pfn_sequence(psb_mmu_get_default_pd(dev_priv->mmu), dev_priv->stolen_base >> PAGE_SHIFT, pg->gatt_start, pg->stolen_size >> PAGE_SHIFT, 0); - up_read(&pg->sem); psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0); psb_mmu_set_pd_context(dev_priv->pf_pd, 1); From 60a78f9ea0e6940cf14422eadfd537292e4562cf Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:15 +0100 Subject: [PATCH 00215/11454] drm/gma500: Move GTT setup and restoration into helper funtions The GTT init and restore functions contain logic to populate the GTT entries. Move the code into helper functions. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-6-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gtt.c | 115 +++++++++++++++++++++-------------- 1 file changed, 68 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index c7b7cb1f2d13..acd50ee26b03 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -144,18 +144,79 @@ void psb_gtt_takedown(struct drm_device *dev) iounmap(dev_priv->gtt_map); } +/* Clear GTT. Use a scratch page to avoid accidents or scribbles. */ +static void psb_gtt_clear(struct drm_psb_private *pdev) +{ + resource_size_t pfn_base; + unsigned long i; + uint32_t pte; + + pfn_base = page_to_pfn(pdev->scratch_page); + pte = psb_gtt_mask_pte(pfn_base, PSB_MMU_CACHED_MEMORY); + + for (i = 0; i < pdev->gtt.gtt_pages; ++i) + iowrite32(pte, pdev->gtt_map + i); + + (void)ioread32(pdev->gtt_map + i - 1); +} + +/* Insert vram stolen pages into the GTT. */ +static void psb_gtt_populate_stolen(struct drm_psb_private *pdev) +{ + struct drm_device *dev = &pdev->dev; + unsigned int pfn_base; + unsigned int i, num_pages; + uint32_t pte; + + pfn_base = pdev->stolen_base >> PAGE_SHIFT; + num_pages = pdev->vram_stolen_size >> PAGE_SHIFT; + + drm_dbg(dev, "Set up %u stolen pages starting at 0x%08x, GTT offset %dK\n", + num_pages, pfn_base << PAGE_SHIFT, 0); + + for (i = 0; i < num_pages; ++i) { + pte = psb_gtt_mask_pte(pfn_base + i, PSB_MMU_CACHED_MEMORY); + iowrite32(pte, pdev->gtt_map + i); + } + + (void)ioread32(pdev->gtt_map + i - 1); +} + +/* Re-insert all pinned GEM objects into GTT. */ +static void psb_gtt_populate_resources(struct drm_psb_private *pdev) +{ + unsigned int restored = 0, total = 0, size = 0; + struct resource *r = pdev->gtt_mem->child; + struct drm_device *dev = &pdev->dev; + struct psb_gem_object *pobj; + + while (r) { + /* + * TODO: GTT restoration needs a refactoring, so that we don't have to touch + * struct psb_gem_object here. The type represents a GEM object and is + * not related to the GTT itself. + */ + pobj = container_of(r, struct psb_gem_object, resource); + if (pobj->pages) { + psb_gtt_insert_pages(pdev, &pobj->resource, pobj->pages); + size += resource_size(&pobj->resource); + ++restored; + } + r = r->sibling; + ++total; + } + + drm_dbg(dev, "Restored %u of %u gtt ranges (%u KB)", restored, total, (size / 1024)); +} + int psb_gtt_init(struct drm_device *dev, int resume) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); unsigned gtt_pages; unsigned long stolen_size, vram_stolen_size; - unsigned i, num_pages; - unsigned pfn_base; struct psb_gtt *pg; - int ret = 0; - uint32_t pte; if (!resume) { mutex_init(&dev_priv->gtt_mutex); @@ -262,29 +323,9 @@ int psb_gtt_init(struct drm_device *dev, int resume) goto out_err; } - /* - * Insert vram stolen pages into the GTT - */ + psb_gtt_clear(dev_priv); + psb_gtt_populate_stolen(dev_priv); - pfn_base = dev_priv->stolen_base >> PAGE_SHIFT; - num_pages = vram_stolen_size >> PAGE_SHIFT; - dev_dbg(dev->dev, "Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n", - num_pages, pfn_base << PAGE_SHIFT, 0); - for (i = 0; i < num_pages; ++i) { - pte = psb_gtt_mask_pte(pfn_base + i, PSB_MMU_CACHED_MEMORY); - iowrite32(pte, dev_priv->gtt_map + i); - } - - /* - * Init rest of GTT to the scratch page to avoid accidents or scribbles - */ - - pfn_base = page_to_pfn(dev_priv->scratch_page); - pte = psb_gtt_mask_pte(pfn_base, PSB_MMU_CACHED_MEMORY); - for (; i < gtt_pages; ++i) - iowrite32(pte, dev_priv->gtt_map + i); - - (void) ioread32(dev_priv->gtt_map + i - 1); return 0; out_err: @@ -295,30 +336,10 @@ out_err: int psb_gtt_restore(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - struct resource *r = dev_priv->gtt_mem->child; - struct psb_gem_object *pobj; - unsigned int restored = 0, total = 0, size = 0; psb_gtt_init(dev, 1); - while (r != NULL) { - /* - * TODO: GTT restoration needs a refactoring, so that we don't have to touch - * struct psb_gem_object here. The type represents a GEM object and is - * not related to the GTT itself. - */ - pobj = container_of(r, struct psb_gem_object, resource); - if (pobj->pages) { - psb_gtt_insert_pages(dev_priv, &pobj->resource, pobj->pages); - size += pobj->resource.end - pobj->resource.start; - restored++; - } - r = r->sibling; - total++; - } - - DRM_DEBUG_DRIVER("Restored %u of %u gtt ranges (%u KB)", restored, - total, (size / 1024)); + psb_gtt_populate_resources(dev_priv); return 0; } From 97bd66c46d8bfbc02406d848ebb53c6a2992e03f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:16 +0100 Subject: [PATCH 00216/11454] drm/gma500: Move GTT resume logic out of psb_gtt_init() The current implementation of psb_gtt_init() also does resume handling. Move the resume code into its own helper. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-7-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gtt.c | 122 ++++++++++++++++++++++++++----- drivers/gpu/drm/gma500/gtt.h | 2 +- drivers/gpu/drm/gma500/psb_drv.c | 2 +- 3 files changed, 104 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index acd50ee26b03..43ad3ec38c80 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -209,7 +209,7 @@ static void psb_gtt_populate_resources(struct drm_psb_private *pdev) drm_dbg(dev, "Restored %u of %u gtt ranges (%u KB)", restored, total, (size / 1024)); } -int psb_gtt_init(struct drm_device *dev, int resume) +int psb_gtt_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); @@ -218,10 +218,8 @@ int psb_gtt_init(struct drm_device *dev, int resume) struct psb_gtt *pg; int ret = 0; - if (!resume) { - mutex_init(&dev_priv->gtt_mutex); - mutex_init(&dev_priv->mmap_mutex); - } + mutex_init(&dev_priv->gtt_mutex); + mutex_init(&dev_priv->mmap_mutex); pg = &dev_priv->gtt; @@ -290,13 +288,6 @@ int psb_gtt_init(struct drm_device *dev, int resume) dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", dev_priv->stolen_base, vram_stolen_size / 1024); - if (resume && (gtt_pages != pg->gtt_pages) && - (stolen_size != pg->stolen_size)) { - dev_err(dev->dev, "GTT resume error.\n"); - ret = -EINVAL; - goto out_err; - } - pg->gtt_pages = gtt_pages; pg->stolen_size = stolen_size; dev_priv->vram_stolen_size = vram_stolen_size; @@ -304,19 +295,14 @@ int psb_gtt_init(struct drm_device *dev, int resume) /* * Map the GTT and the stolen memory area */ - if (!resume) - dev_priv->gtt_map = ioremap(pg->gtt_phys_start, - gtt_pages << PAGE_SHIFT); + dev_priv->gtt_map = ioremap(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT); if (!dev_priv->gtt_map) { dev_err(dev->dev, "Failure to map gtt.\n"); ret = -ENOMEM; goto out_err; } - if (!resume) - dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, - stolen_size); - + dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); if (!dev_priv->vram_addr) { dev_err(dev->dev, "Failure to map stolen base.\n"); ret = -ENOMEM; @@ -333,11 +319,107 @@ out_err: return ret; } +static int psb_gtt_resume(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); + unsigned int gtt_pages; + unsigned long stolen_size, vram_stolen_size; + struct psb_gtt *pg; + int ret = 0; + + pg = &dev_priv->gtt; + + /* Enable the GTT */ + pci_read_config_word(pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); + pci_write_config_word(pdev, PSB_GMCH_CTRL, + dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); + + dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); + PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); + (void) PSB_RVDC32(PSB_PGETBL_CTL); + + /* The root resource we allocate address space from */ + dev_priv->gtt_initialized = 1; + + pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; + + /* + * The video mmu has a hw bug when accessing 0x0D0000000. + * Make gatt start at 0x0e000,0000. This doesn't actually + * matter for us but may do if the video acceleration ever + * gets opened up. + */ + pg->mmu_gatt_start = 0xE0000000; + + pg->gtt_start = pci_resource_start(pdev, PSB_GTT_RESOURCE); + gtt_pages = pci_resource_len(pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT; + /* CDV doesn't report this. In which case the system has 64 gtt pages */ + if (pg->gtt_start == 0 || gtt_pages == 0) { + dev_dbg(dev->dev, "GTT PCI BAR not initialized.\n"); + gtt_pages = 64; + pg->gtt_start = dev_priv->pge_ctl; + } + + pg->gatt_start = pci_resource_start(pdev, PSB_GATT_RESOURCE); + pg->gatt_pages = pci_resource_len(pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT; + dev_priv->gtt_mem = &pdev->resource[PSB_GATT_RESOURCE]; + + if (pg->gatt_pages == 0 || pg->gatt_start == 0) { + static struct resource fudge; /* Preferably peppermint */ + /* + * This can occur on CDV systems. Fudge it in this case. We + * really don't care what imaginary space is being allocated + * at this point. + */ + dev_dbg(dev->dev, "GATT PCI BAR not initialized.\n"); + pg->gatt_start = 0x40000000; + pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT; + /* + * This is a little confusing but in fact the GTT is providing + * a view from the GPU into memory and not vice versa. As such + * this is really allocating space that is not the same as the + * CPU address space on CDV. + */ + fudge.start = 0x40000000; + fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1; + fudge.name = "fudge"; + fudge.flags = IORESOURCE_MEM; + dev_priv->gtt_mem = &fudge; + } + + pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base); + vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE; + stolen_size = vram_stolen_size; + + dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", + dev_priv->stolen_base, vram_stolen_size / 1024); + + if ((gtt_pages != pg->gtt_pages) && (stolen_size != pg->stolen_size)) { + dev_err(dev->dev, "GTT resume error.\n"); + ret = -EINVAL; + goto out_err; + } + + pg->gtt_pages = gtt_pages; + pg->stolen_size = stolen_size; + dev_priv->vram_stolen_size = vram_stolen_size; + + psb_gtt_clear(dev_priv); + psb_gtt_populate_stolen(dev_priv); + + return 0; + +out_err: + psb_gtt_takedown(dev); + return ret; +} + int psb_gtt_restore(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - psb_gtt_init(dev, 1); + psb_gtt_resume(dev); psb_gtt_populate_resources(dev_priv); diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h index 31500533ac45..cb270ea40794 100644 --- a/drivers/gpu/drm/gma500/gtt.h +++ b/drivers/gpu/drm/gma500/gtt.h @@ -25,7 +25,7 @@ struct psb_gtt { }; /* Exported functions */ -extern int psb_gtt_init(struct drm_device *dev, int resume); +int psb_gtt_init(struct drm_device *dev); extern void psb_gtt_takedown(struct drm_device *dev); extern int psb_gtt_restore(struct drm_device *dev); diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 7227a8e44d23..2891a3dc8d2e 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -324,7 +324,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) set_pages_uc(dev_priv->scratch_page, 1); - ret = psb_gtt_init(dev, 0); + ret = psb_gtt_init(dev); if (ret) goto out_err; From 6069fd815d287e786a5ac1b0f875fa92aac798ff Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:17 +0100 Subject: [PATCH 00217/11454] drm/gma500: Cleanup GTT uninit and error handling Replace psb_gtt_takedown() with finalizer function that is only called for unloading the driver. Use roll-back pattern for error handling in psb_gtt_init() and _resume(). Also fixes a bug where vmap_addr was never unmapped. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-8-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gtt.c | 49 ++++++++++++++++---------------- drivers/gpu/drm/gma500/gtt.h | 2 +- drivers/gpu/drm/gma500/psb_drv.c | 2 +- drivers/gpu/drm/gma500/psb_drv.h | 1 - 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 43ad3ec38c80..99c644a5c5cb 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -125,23 +125,20 @@ void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *r mutex_unlock(&pdev->gtt_mutex); } -void psb_gtt_takedown(struct drm_device *dev) +void psb_gtt_fini(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); - if (dev_priv->gtt_map) { - iounmap(dev_priv->gtt_map); - dev_priv->gtt_map = NULL; - } - if (dev_priv->gtt_initialized) { - pci_write_config_word(pdev, PSB_GMCH_CTRL, - dev_priv->gmch_ctrl); - PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); - (void) PSB_RVDC32(PSB_PGETBL_CTL); - } - if (dev_priv->vram_addr) - iounmap(dev_priv->gtt_map); + iounmap(dev_priv->vram_addr); + iounmap(dev_priv->gtt_map); + + pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl); + PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); + (void)PSB_RVDC32(PSB_PGETBL_CTL); + + mutex_destroy(&dev_priv->mmap_mutex); + mutex_destroy(&dev_priv->gtt_mutex); } /* Clear GTT. Use a scratch page to avoid accidents or scribbles. */ @@ -233,8 +230,6 @@ int psb_gtt_init(struct drm_device *dev) (void) PSB_RVDC32(PSB_PGETBL_CTL); /* The root resource we allocate address space from */ - dev_priv->gtt_initialized = 1; - pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; /* @@ -299,14 +294,14 @@ int psb_gtt_init(struct drm_device *dev) if (!dev_priv->gtt_map) { dev_err(dev->dev, "Failure to map gtt.\n"); ret = -ENOMEM; - goto out_err; + goto err_gtt_disable; } dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); if (!dev_priv->vram_addr) { dev_err(dev->dev, "Failure to map stolen base.\n"); ret = -ENOMEM; - goto out_err; + goto err_iounmap; } psb_gtt_clear(dev_priv); @@ -314,8 +309,14 @@ int psb_gtt_init(struct drm_device *dev) return 0; -out_err: - psb_gtt_takedown(dev); +err_iounmap: + iounmap(dev_priv->gtt_map); +err_gtt_disable: + pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl); + PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); + (void)PSB_RVDC32(PSB_PGETBL_CTL); + mutex_destroy(&dev_priv->mmap_mutex); + mutex_destroy(&dev_priv->gtt_mutex); return ret; } @@ -340,8 +341,6 @@ static int psb_gtt_resume(struct drm_device *dev) (void) PSB_RVDC32(PSB_PGETBL_CTL); /* The root resource we allocate address space from */ - dev_priv->gtt_initialized = 1; - pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; /* @@ -398,7 +397,7 @@ static int psb_gtt_resume(struct drm_device *dev) if ((gtt_pages != pg->gtt_pages) && (stolen_size != pg->stolen_size)) { dev_err(dev->dev, "GTT resume error.\n"); ret = -EINVAL; - goto out_err; + goto err_gtt_disable; } pg->gtt_pages = gtt_pages; @@ -410,8 +409,10 @@ static int psb_gtt_resume(struct drm_device *dev) return 0; -out_err: - psb_gtt_takedown(dev); +err_gtt_disable: + pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl); + PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); + (void)PSB_RVDC32(PSB_PGETBL_CTL); return ret; } diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h index cb270ea40794..5839d5d06adc 100644 --- a/drivers/gpu/drm/gma500/gtt.h +++ b/drivers/gpu/drm/gma500/gtt.h @@ -26,7 +26,7 @@ struct psb_gtt { /* Exported functions */ int psb_gtt_init(struct drm_device *dev); -extern void psb_gtt_takedown(struct drm_device *dev); +void psb_gtt_fini(struct drm_device *dev); extern int psb_gtt_restore(struct drm_device *dev); int psb_gtt_allocate_resource(struct drm_psb_private *pdev, struct resource *res, diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 2891a3dc8d2e..41be6e1ac7f9 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -192,7 +192,7 @@ static void psb_driver_unload(struct drm_device *dev) psb_mmu_driver_takedown(dev_priv->mmu); dev_priv->mmu = NULL; } - psb_gtt_takedown(dev); + psb_gtt_fini(dev); if (dev_priv->scratch_page) { set_pages_wb(dev_priv->scratch_page, 1); __free_page(dev_priv->scratch_page); diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 0439b10d3db5..553d03190ce1 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -408,7 +408,6 @@ struct drm_psb_private { uint32_t stolen_base; u8 __iomem *vram_addr; unsigned long vram_stolen_size; - int gtt_initialized; u16 gmch_ctrl; /* Saved GTT setup */ u32 pge_ctl; From d00f44ddfbb18d73fab98492e5fcb43281564f4f Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:18 +0100 Subject: [PATCH 00218/11454] drm/gma500: Split GTT init/resume/fini into GTT and GEM functions The GTT init, fini and resume functions contain both, GTT and GEM, code. Split each into a separate GTT and a GEM function. The GEM code is responsible for mmap_mutex and the stolen memory area. The rest of the functionality is left in GTT functions. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-9-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gtt.c | 122 ++++++++++++++++++++----------- drivers/gpu/drm/gma500/gtt.h | 3 + drivers/gpu/drm/gma500/psb_drv.c | 4 + 3 files changed, 85 insertions(+), 44 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 99c644a5c5cb..0e99774c7e59 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -125,19 +125,26 @@ void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *r mutex_unlock(&pdev->gtt_mutex); } +void psb_gem_mm_fini(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + + iounmap(dev_priv->vram_addr); + + mutex_destroy(&dev_priv->mmap_mutex); +} + void psb_gtt_fini(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); - iounmap(dev_priv->vram_addr); iounmap(dev_priv->gtt_map); pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl); PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); (void)PSB_RVDC32(PSB_PGETBL_CTL); - mutex_destroy(&dev_priv->mmap_mutex); mutex_destroy(&dev_priv->gtt_mutex); } @@ -211,12 +218,10 @@ int psb_gtt_init(struct drm_device *dev) struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); unsigned gtt_pages; - unsigned long stolen_size, vram_stolen_size; struct psb_gtt *pg; int ret = 0; mutex_init(&dev_priv->gtt_mutex); - mutex_init(&dev_priv->mmap_mutex); pg = &dev_priv->gtt; @@ -274,22 +279,8 @@ int psb_gtt_init(struct drm_device *dev) dev_priv->gtt_mem = &fudge; } - pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base); - vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - - PAGE_SIZE; - - stolen_size = vram_stolen_size; - - dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", - dev_priv->stolen_base, vram_stolen_size / 1024); - pg->gtt_pages = gtt_pages; - pg->stolen_size = stolen_size; - dev_priv->vram_stolen_size = vram_stolen_size; - /* - * Map the GTT and the stolen memory area - */ dev_priv->gtt_map = ioremap(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT); if (!dev_priv->gtt_map) { dev_err(dev->dev, "Failure to map gtt.\n"); @@ -297,37 +288,64 @@ int psb_gtt_init(struct drm_device *dev) goto err_gtt_disable; } - dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); - if (!dev_priv->vram_addr) { - dev_err(dev->dev, "Failure to map stolen base.\n"); - ret = -ENOMEM; - goto err_iounmap; - } - psb_gtt_clear(dev_priv); - psb_gtt_populate_stolen(dev_priv); return 0; -err_iounmap: - iounmap(dev_priv->gtt_map); err_gtt_disable: pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl); PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); (void)PSB_RVDC32(PSB_PGETBL_CTL); - mutex_destroy(&dev_priv->mmap_mutex); mutex_destroy(&dev_priv->gtt_mutex); return ret; } +int psb_gem_mm_init(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); + unsigned long stolen_size, vram_stolen_size; + struct psb_gtt *pg; + int ret; + + mutex_init(&dev_priv->mmap_mutex); + + pg = &dev_priv->gtt; + + pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base); + vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE; + + stolen_size = vram_stolen_size; + + dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", + dev_priv->stolen_base, vram_stolen_size / 1024); + + pg->stolen_size = stolen_size; + dev_priv->vram_stolen_size = vram_stolen_size; + + dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); + if (!dev_priv->vram_addr) { + dev_err(dev->dev, "Failure to map stolen base.\n"); + ret = -ENOMEM; + goto err_mutex_destroy; + } + + psb_gtt_populate_stolen(dev_priv); + + return 0; + +err_mutex_destroy: + mutex_destroy(&dev_priv->mmap_mutex); + return ret; +} + static int psb_gtt_resume(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); unsigned int gtt_pages; - unsigned long stolen_size, vram_stolen_size; struct psb_gtt *pg; - int ret = 0; + int ret; pg = &dev_priv->gtt; @@ -387,27 +405,15 @@ static int psb_gtt_resume(struct drm_device *dev) dev_priv->gtt_mem = &fudge; } - pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base); - vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE; - stolen_size = vram_stolen_size; - - dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", - dev_priv->stolen_base, vram_stolen_size / 1024); - - if ((gtt_pages != pg->gtt_pages) && (stolen_size != pg->stolen_size)) { + if (gtt_pages != pg->gtt_pages) { dev_err(dev->dev, "GTT resume error.\n"); ret = -EINVAL; goto err_gtt_disable; } pg->gtt_pages = gtt_pages; - pg->stolen_size = stolen_size; - dev_priv->vram_stolen_size = vram_stolen_size; psb_gtt_clear(dev_priv); - psb_gtt_populate_stolen(dev_priv); - - return 0; err_gtt_disable: pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl); @@ -416,11 +422,39 @@ err_gtt_disable: return ret; } +static int psb_gem_mm_resume(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); + unsigned long stolen_size, vram_stolen_size; + struct psb_gtt *pg; + + pg = &dev_priv->gtt; + + pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base); + vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE; + + stolen_size = vram_stolen_size; + + dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", dev_priv->stolen_base, + vram_stolen_size / 1024); + + if (stolen_size != pg->stolen_size) { + dev_err(dev->dev, "GTT resume error.\n"); + return -EINVAL; + } + + psb_gtt_populate_stolen(dev_priv); + + return 0; +} + int psb_gtt_restore(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); psb_gtt_resume(dev); + psb_gem_mm_resume(dev); psb_gtt_populate_resources(dev_priv); diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h index 5839d5d06adc..45e1926dfce1 100644 --- a/drivers/gpu/drm/gma500/gtt.h +++ b/drivers/gpu/drm/gma500/gtt.h @@ -37,4 +37,7 @@ void psb_gtt_insert_pages(struct drm_psb_private *pdev, const struct resource *r struct page **pages); void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *res); +int psb_gem_mm_init(struct drm_device *dev); +void psb_gem_mm_fini(struct drm_device *dev); + #endif diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 41be6e1ac7f9..6547967b51e1 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -192,6 +192,7 @@ static void psb_driver_unload(struct drm_device *dev) psb_mmu_driver_takedown(dev_priv->mmu); dev_priv->mmu = NULL; } + psb_gem_mm_fini(dev); psb_gtt_fini(dev); if (dev_priv->scratch_page) { set_pages_wb(dev_priv->scratch_page, 1); @@ -325,6 +326,9 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) set_pages_uc(dev_priv->scratch_page, 1); ret = psb_gtt_init(dev); + if (ret) + goto out_err; + ret = psb_gem_mm_init(dev); if (ret) goto out_err; From 42ceddb696a01e6e31e90c456b882392f1572d69 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:19 +0100 Subject: [PATCH 00219/11454] drm/gma500: Inline psb_gtt_restore() Inline psb_gtt_restore() into its only caller in power.c. Perform the GTT restoration in psb_gem_mm_resume(). The restoration step is part of GEM anyway and will be moved over at some point. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-10-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gtt.c | 15 ++------------- drivers/gpu/drm/gma500/gtt.h | 3 ++- drivers/gpu/drm/gma500/power.c | 4 +++- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 0e99774c7e59..9e1b19fcea28 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -339,7 +339,7 @@ err_mutex_destroy: return ret; } -static int psb_gtt_resume(struct drm_device *dev) +int psb_gtt_resume(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); @@ -422,7 +422,7 @@ err_gtt_disable: return ret; } -static int psb_gem_mm_resume(struct drm_device *dev) +int psb_gem_mm_resume(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); @@ -445,17 +445,6 @@ static int psb_gem_mm_resume(struct drm_device *dev) } psb_gtt_populate_stolen(dev_priv); - - return 0; -} - -int psb_gtt_restore(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - - psb_gtt_resume(dev); - psb_gem_mm_resume(dev); - psb_gtt_populate_resources(dev_priv); return 0; diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h index 45e1926dfce1..9a6d79200dce 100644 --- a/drivers/gpu/drm/gma500/gtt.h +++ b/drivers/gpu/drm/gma500/gtt.h @@ -27,7 +27,7 @@ struct psb_gtt { /* Exported functions */ int psb_gtt_init(struct drm_device *dev); void psb_gtt_fini(struct drm_device *dev); -extern int psb_gtt_restore(struct drm_device *dev); +int psb_gtt_resume(struct drm_device *dev); int psb_gtt_allocate_resource(struct drm_psb_private *pdev, struct resource *res, const char *name, resource_size_t size, resource_size_t align, @@ -39,5 +39,6 @@ void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *r int psb_gem_mm_init(struct drm_device *dev); void psb_gem_mm_fini(struct drm_device *dev); +int psb_gem_mm_resume(struct drm_device *dev); #endif diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c index d2a46d96e746..28e472b31698 100644 --- a/drivers/gpu/drm/gma500/power.c +++ b/drivers/gpu/drm/gma500/power.c @@ -112,7 +112,9 @@ static void gma_resume_display(struct pci_dev *pdev) pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); - psb_gtt_restore(dev); /* Rebuild our GTT mappings */ + /* Rebuild our GTT mappings */ + psb_gtt_resume(dev); + psb_gem_mm_resume(dev); dev_priv->ops->restore_regs(dev); } From d339386c9ffa69d20fcc34f3636dea80ea71818c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:20 +0100 Subject: [PATCH 00220/11454] drm/gma500: Move GEM memory management functions to gem.c Move GEM functions from gtt.c to gem.c. Adapt some names. No functional changes. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-11-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gem.c | 133 +++++++++++++++++++++++++++++++ drivers/gpu/drm/gma500/gem.h | 12 +++ drivers/gpu/drm/gma500/gtt.c | 127 +---------------------------- drivers/gpu/drm/gma500/gtt.h | 5 +- drivers/gpu/drm/gma500/power.c | 1 + drivers/gpu/drm/gma500/psb_drv.c | 1 + 6 files changed, 149 insertions(+), 130 deletions(-) diff --git a/drivers/gpu/drm/gma500/gem.c b/drivers/gpu/drm/gma500/gem.c index 2f44535f58e7..dffe37490206 100644 --- a/drivers/gpu/drm/gma500/gem.c +++ b/drivers/gpu/drm/gma500/gem.c @@ -21,6 +21,10 @@ #include "gem.h" #include "psb_drv.h" +/* + * PSB GEM object + */ + int psb_gem_pin(struct psb_gem_object *pobj) { struct drm_gem_object *obj = &pobj->base; @@ -296,3 +300,132 @@ fail: return ret; } + +/* + * Memory management + */ + +/* Insert vram stolen pages into the GTT. */ +static void psb_gem_mm_populate_stolen(struct drm_psb_private *pdev) +{ + struct drm_device *dev = &pdev->dev; + unsigned int pfn_base; + unsigned int i, num_pages; + uint32_t pte; + + pfn_base = pdev->stolen_base >> PAGE_SHIFT; + num_pages = pdev->vram_stolen_size >> PAGE_SHIFT; + + drm_dbg(dev, "Set up %u stolen pages starting at 0x%08x, GTT offset %dK\n", + num_pages, pfn_base << PAGE_SHIFT, 0); + + for (i = 0; i < num_pages; ++i) { + pte = psb_gtt_mask_pte(pfn_base + i, PSB_MMU_CACHED_MEMORY); + iowrite32(pte, pdev->gtt_map + i); + } + + (void)ioread32(pdev->gtt_map + i - 1); +} + +int psb_gem_mm_init(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); + unsigned long stolen_size, vram_stolen_size; + struct psb_gtt *pg; + int ret; + + mutex_init(&dev_priv->mmap_mutex); + + pg = &dev_priv->gtt; + + pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base); + vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE; + + stolen_size = vram_stolen_size; + + dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", + dev_priv->stolen_base, vram_stolen_size / 1024); + + pg->stolen_size = stolen_size; + dev_priv->vram_stolen_size = vram_stolen_size; + + dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); + if (!dev_priv->vram_addr) { + dev_err(dev->dev, "Failure to map stolen base.\n"); + ret = -ENOMEM; + goto err_mutex_destroy; + } + + psb_gem_mm_populate_stolen(dev_priv); + + return 0; + +err_mutex_destroy: + mutex_destroy(&dev_priv->mmap_mutex); + return ret; +} + +void psb_gem_mm_fini(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + + iounmap(dev_priv->vram_addr); + + mutex_destroy(&dev_priv->mmap_mutex); +} + +/* Re-insert all pinned GEM objects into GTT. */ +static void psb_gem_mm_populate_resources(struct drm_psb_private *pdev) +{ + unsigned int restored = 0, total = 0, size = 0; + struct resource *r = pdev->gtt_mem->child; + struct drm_device *dev = &pdev->dev; + struct psb_gem_object *pobj; + + while (r) { + /* + * TODO: GTT restoration needs a refactoring, so that we don't have to touch + * struct psb_gem_object here. The type represents a GEM object and is + * not related to the GTT itself. + */ + pobj = container_of(r, struct psb_gem_object, resource); + if (pobj->pages) { + psb_gtt_insert_pages(pdev, &pobj->resource, pobj->pages); + size += resource_size(&pobj->resource); + ++restored; + } + r = r->sibling; + ++total; + } + + drm_dbg(dev, "Restored %u of %u gtt ranges (%u KB)", restored, total, (size / 1024)); +} + +int psb_gem_mm_resume(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct pci_dev *pdev = to_pci_dev(dev->dev); + unsigned long stolen_size, vram_stolen_size; + struct psb_gtt *pg; + + pg = &dev_priv->gtt; + + pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base); + vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE; + + stolen_size = vram_stolen_size; + + dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", dev_priv->stolen_base, + vram_stolen_size / 1024); + + if (stolen_size != pg->stolen_size) { + dev_err(dev->dev, "GTT resume error.\n"); + return -EINVAL; + } + + psb_gem_mm_populate_stolen(dev_priv); + psb_gem_mm_populate_resources(dev_priv); + + return 0; +} diff --git a/drivers/gpu/drm/gma500/gem.h b/drivers/gpu/drm/gma500/gem.h index 96ef864b4bf1..27df6ff4ed37 100644 --- a/drivers/gpu/drm/gma500/gem.h +++ b/drivers/gpu/drm/gma500/gem.h @@ -14,6 +14,10 @@ struct drm_device; +/* + * PSB GEM object + */ + struct psb_gem_object { struct drm_gem_object base; @@ -36,4 +40,12 @@ psb_gem_create(struct drm_device *dev, u64 size, const char *name, bool stolen, int psb_gem_pin(struct psb_gem_object *pobj); void psb_gem_unpin(struct psb_gem_object *pobj); +/* + * Memory management + */ + +int psb_gem_mm_init(struct drm_device *dev); +void psb_gem_mm_fini(struct drm_device *dev); +int psb_gem_mm_resume(struct drm_device *dev); + #endif diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 9e1b19fcea28..b03feec64f01 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -49,7 +49,7 @@ int psb_gtt_allocate_resource(struct drm_psb_private *pdev, struct resource *res * * Set the GTT entry for the appropriate memory type. */ -static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) +uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) { uint32_t mask = PSB_PTE_VALID; @@ -125,15 +125,6 @@ void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *r mutex_unlock(&pdev->gtt_mutex); } -void psb_gem_mm_fini(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - - iounmap(dev_priv->vram_addr); - - mutex_destroy(&dev_priv->mmap_mutex); -} - void psb_gtt_fini(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); @@ -164,55 +155,6 @@ static void psb_gtt_clear(struct drm_psb_private *pdev) (void)ioread32(pdev->gtt_map + i - 1); } -/* Insert vram stolen pages into the GTT. */ -static void psb_gtt_populate_stolen(struct drm_psb_private *pdev) -{ - struct drm_device *dev = &pdev->dev; - unsigned int pfn_base; - unsigned int i, num_pages; - uint32_t pte; - - pfn_base = pdev->stolen_base >> PAGE_SHIFT; - num_pages = pdev->vram_stolen_size >> PAGE_SHIFT; - - drm_dbg(dev, "Set up %u stolen pages starting at 0x%08x, GTT offset %dK\n", - num_pages, pfn_base << PAGE_SHIFT, 0); - - for (i = 0; i < num_pages; ++i) { - pte = psb_gtt_mask_pte(pfn_base + i, PSB_MMU_CACHED_MEMORY); - iowrite32(pte, pdev->gtt_map + i); - } - - (void)ioread32(pdev->gtt_map + i - 1); -} - -/* Re-insert all pinned GEM objects into GTT. */ -static void psb_gtt_populate_resources(struct drm_psb_private *pdev) -{ - unsigned int restored = 0, total = 0, size = 0; - struct resource *r = pdev->gtt_mem->child; - struct drm_device *dev = &pdev->dev; - struct psb_gem_object *pobj; - - while (r) { - /* - * TODO: GTT restoration needs a refactoring, so that we don't have to touch - * struct psb_gem_object here. The type represents a GEM object and is - * not related to the GTT itself. - */ - pobj = container_of(r, struct psb_gem_object, resource); - if (pobj->pages) { - psb_gtt_insert_pages(pdev, &pobj->resource, pobj->pages); - size += resource_size(&pobj->resource); - ++restored; - } - r = r->sibling; - ++total; - } - - drm_dbg(dev, "Restored %u of %u gtt ranges (%u KB)", restored, total, (size / 1024)); -} - int psb_gtt_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); @@ -300,45 +242,6 @@ err_gtt_disable: return ret; } -int psb_gem_mm_init(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - struct pci_dev *pdev = to_pci_dev(dev->dev); - unsigned long stolen_size, vram_stolen_size; - struct psb_gtt *pg; - int ret; - - mutex_init(&dev_priv->mmap_mutex); - - pg = &dev_priv->gtt; - - pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base); - vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE; - - stolen_size = vram_stolen_size; - - dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", - dev_priv->stolen_base, vram_stolen_size / 1024); - - pg->stolen_size = stolen_size; - dev_priv->vram_stolen_size = vram_stolen_size; - - dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); - if (!dev_priv->vram_addr) { - dev_err(dev->dev, "Failure to map stolen base.\n"); - ret = -ENOMEM; - goto err_mutex_destroy; - } - - psb_gtt_populate_stolen(dev_priv); - - return 0; - -err_mutex_destroy: - mutex_destroy(&dev_priv->mmap_mutex); - return ret; -} - int psb_gtt_resume(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); @@ -421,31 +324,3 @@ err_gtt_disable: (void)PSB_RVDC32(PSB_PGETBL_CTL); return ret; } - -int psb_gem_mm_resume(struct drm_device *dev) -{ - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - struct pci_dev *pdev = to_pci_dev(dev->dev); - unsigned long stolen_size, vram_stolen_size; - struct psb_gtt *pg; - - pg = &dev_priv->gtt; - - pci_read_config_dword(pdev, PSB_BSM, &dev_priv->stolen_base); - vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base - PAGE_SIZE; - - stolen_size = vram_stolen_size; - - dev_dbg(dev->dev, "Stolen memory base 0x%x, size %luK\n", dev_priv->stolen_base, - vram_stolen_size / 1024); - - if (stolen_size != pg->stolen_size) { - dev_err(dev->dev, "GTT resume error.\n"); - return -EINVAL; - } - - psb_gtt_populate_stolen(dev_priv); - psb_gtt_populate_resources(dev_priv); - - return 0; -} diff --git a/drivers/gpu/drm/gma500/gtt.h b/drivers/gpu/drm/gma500/gtt.h index 9a6d79200dce..d5a5fd4466c1 100644 --- a/drivers/gpu/drm/gma500/gtt.h +++ b/drivers/gpu/drm/gma500/gtt.h @@ -33,12 +33,9 @@ int psb_gtt_allocate_resource(struct drm_psb_private *pdev, struct resource *res const char *name, resource_size_t size, resource_size_t align, bool stolen, u32 *offset); +uint32_t psb_gtt_mask_pte(uint32_t pfn, int type); void psb_gtt_insert_pages(struct drm_psb_private *pdev, const struct resource *res, struct page **pages); void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *res); -int psb_gem_mm_init(struct drm_device *dev); -void psb_gem_mm_fini(struct drm_device *dev); -int psb_gem_mm_resume(struct drm_device *dev); - #endif diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c index 28e472b31698..6f917cfef65b 100644 --- a/drivers/gpu/drm/gma500/power.c +++ b/drivers/gpu/drm/gma500/power.c @@ -28,6 +28,7 @@ * Alan Cox */ +#include "gem.h" #include "power.h" #include "psb_drv.h" #include "psb_reg.h" diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 6547967b51e1..e30b58184156 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -28,6 +28,7 @@ #include #include "framebuffer.h" +#include "gem.h" #include "intel_bios.h" #include "mid_bios.h" #include "power.h" From 5169f3592d48be8fd84b2a9e23c07a1c2977d19c Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:21 +0100 Subject: [PATCH 00221/11454] drm/gma500: Move GTT enable and disable code into helpers Move the code for enabling and disabling the GTT into helpers and call the functions in psb_gtt_init(), psb_gtt_fini() and psb_gtt_resume(). Removes code duplication. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-12-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gtt.c | 83 ++++++++++++++++++++---------------- 1 file changed, 47 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index b03feec64f01..83d9a9f7c73c 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -125,17 +125,44 @@ void psb_gtt_remove_pages(struct drm_psb_private *pdev, const struct resource *r mutex_unlock(&pdev->gtt_mutex); } -void psb_gtt_fini(struct drm_device *dev) +static int psb_gtt_enable(struct drm_psb_private *dev_priv) { - struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct drm_device *dev = &dev_priv->dev; struct pci_dev *pdev = to_pci_dev(dev->dev); + int ret; - iounmap(dev_priv->gtt_map); + ret = pci_read_config_word(pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); + if (ret) + return pcibios_err_to_errno(ret); + ret = pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); + if (ret) + return pcibios_err_to_errno(ret); + + dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); + PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); + + (void)PSB_RVDC32(PSB_PGETBL_CTL); + + return 0; +} + +static void psb_gtt_disable(struct drm_psb_private *dev_priv) +{ + struct drm_device *dev = &dev_priv->dev; + struct pci_dev *pdev = to_pci_dev(dev->dev); pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl); PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); - (void)PSB_RVDC32(PSB_PGETBL_CTL); + (void)PSB_RVDC32(PSB_PGETBL_CTL); +} + +void psb_gtt_fini(struct drm_device *dev) +{ + struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + + iounmap(dev_priv->gtt_map); + psb_gtt_disable(dev_priv); mutex_destroy(&dev_priv->gtt_mutex); } @@ -159,22 +186,15 @@ int psb_gtt_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); + struct psb_gtt *pg = &dev_priv->gtt; unsigned gtt_pages; - struct psb_gtt *pg; - int ret = 0; + int ret; mutex_init(&dev_priv->gtt_mutex); - pg = &dev_priv->gtt; - - /* Enable the GTT */ - pci_read_config_word(pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); - pci_write_config_word(pdev, PSB_GMCH_CTRL, - dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); - - dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); - PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); - (void) PSB_RVDC32(PSB_PGETBL_CTL); + ret = psb_gtt_enable(dev_priv); + if (ret) + goto err_mutex_destroy; /* The root resource we allocate address space from */ pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; @@ -227,17 +247,16 @@ int psb_gtt_init(struct drm_device *dev) if (!dev_priv->gtt_map) { dev_err(dev->dev, "Failure to map gtt.\n"); ret = -ENOMEM; - goto err_gtt_disable; + goto err_psb_gtt_disable; } psb_gtt_clear(dev_priv); return 0; -err_gtt_disable: - pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl); - PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); - (void)PSB_RVDC32(PSB_PGETBL_CTL); +err_psb_gtt_disable: + psb_gtt_disable(dev_priv); +err_mutex_destroy: mutex_destroy(&dev_priv->gtt_mutex); return ret; } @@ -246,20 +265,14 @@ int psb_gtt_resume(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); + struct psb_gtt *pg = &dev_priv->gtt; unsigned int gtt_pages; - struct psb_gtt *pg; int ret; - pg = &dev_priv->gtt; - /* Enable the GTT */ - pci_read_config_word(pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); - pci_write_config_word(pdev, PSB_GMCH_CTRL, - dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); - - dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); - PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); - (void) PSB_RVDC32(PSB_PGETBL_CTL); + ret = psb_gtt_enable(dev_priv); + if (ret) + return ret; /* The root resource we allocate address space from */ pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; @@ -311,16 +324,14 @@ int psb_gtt_resume(struct drm_device *dev) if (gtt_pages != pg->gtt_pages) { dev_err(dev->dev, "GTT resume error.\n"); ret = -EINVAL; - goto err_gtt_disable; + goto err_psb_gtt_disable; } pg->gtt_pages = gtt_pages; psb_gtt_clear(dev_priv); -err_gtt_disable: - pci_write_config_word(pdev, PSB_GMCH_CTRL, dev_priv->gmch_ctrl); - PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); - (void)PSB_RVDC32(PSB_PGETBL_CTL); +err_psb_gtt_disable: + psb_gtt_disable(dev_priv); return ret; } From 07739597b4d0eae539c9020ea321f636afd878ee Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Tue, 8 Mar 2022 20:52:22 +0100 Subject: [PATCH 00222/11454] drm/gma500: Move GTT memory-range setup into helper Move the setup code for GTT/GATT memory ranges into a new helper and call the function from psb_gtt_init() and psb_gtt_resume(). Removes code duplication. Signed-off-by: Thomas Zimmermann Acked-by: Patrik Jakobsson Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220308195222.13471-13-tzimmermann@suse.de --- drivers/gpu/drm/gma500/gtt.c | 177 +++++++++++++++-------------------- 1 file changed, 76 insertions(+), 101 deletions(-) diff --git a/drivers/gpu/drm/gma500/gtt.c b/drivers/gpu/drm/gma500/gtt.c index 83d9a9f7c73c..379bc218aa6b 100644 --- a/drivers/gpu/drm/gma500/gtt.c +++ b/drivers/gpu/drm/gma500/gtt.c @@ -182,12 +182,80 @@ static void psb_gtt_clear(struct drm_psb_private *pdev) (void)ioread32(pdev->gtt_map + i - 1); } +static void psb_gtt_init_ranges(struct drm_psb_private *dev_priv) +{ + struct drm_device *dev = &dev_priv->dev; + struct pci_dev *pdev = to_pci_dev(dev->dev); + struct psb_gtt *pg = &dev_priv->gtt; + resource_size_t gtt_phys_start, mmu_gatt_start, gtt_start, gtt_pages, + gatt_start, gatt_pages; + struct resource *gtt_mem; + + /* The root resource we allocate address space from */ + gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; + + /* + * The video MMU has a HW bug when accessing 0x0d0000000. Make + * GATT start at 0x0e0000000. This doesn't actually matter for + * us now, but maybe will if the video acceleration ever gets + * opened up. + */ + mmu_gatt_start = 0xe0000000; + + gtt_start = pci_resource_start(pdev, PSB_GTT_RESOURCE); + gtt_pages = pci_resource_len(pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT; + + /* CDV doesn't report this. In which case the system has 64 gtt pages */ + if (!gtt_start || !gtt_pages) { + dev_dbg(dev->dev, "GTT PCI BAR not initialized.\n"); + gtt_pages = 64; + gtt_start = dev_priv->pge_ctl; + } + + gatt_start = pci_resource_start(pdev, PSB_GATT_RESOURCE); + gatt_pages = pci_resource_len(pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT; + + if (!gatt_pages || !gatt_start) { + static struct resource fudge; /* Preferably peppermint */ + + /* + * This can occur on CDV systems. Fudge it in this case. We + * really don't care what imaginary space is being allocated + * at this point. + */ + dev_dbg(dev->dev, "GATT PCI BAR not initialized.\n"); + gatt_start = 0x40000000; + gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT; + + /* + * This is a little confusing but in fact the GTT is providing + * a view from the GPU into memory and not vice versa. As such + * this is really allocating space that is not the same as the + * CPU address space on CDV. + */ + fudge.start = 0x40000000; + fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1; + fudge.name = "fudge"; + fudge.flags = IORESOURCE_MEM; + + gtt_mem = &fudge; + } else { + gtt_mem = &pdev->resource[PSB_GATT_RESOURCE]; + } + + pg->gtt_phys_start = gtt_phys_start; + pg->mmu_gatt_start = mmu_gatt_start; + pg->gtt_start = gtt_start; + pg->gtt_pages = gtt_pages; + pg->gatt_start = gatt_start; + pg->gatt_pages = gatt_pages; + dev_priv->gtt_mem = gtt_mem; +} + int psb_gtt_init(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - struct pci_dev *pdev = to_pci_dev(dev->dev); struct psb_gtt *pg = &dev_priv->gtt; - unsigned gtt_pages; int ret; mutex_init(&dev_priv->gtt_mutex); @@ -196,54 +264,9 @@ int psb_gtt_init(struct drm_device *dev) if (ret) goto err_mutex_destroy; - /* The root resource we allocate address space from */ - pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; + psb_gtt_init_ranges(dev_priv); - /* - * The video mmu has a hw bug when accessing 0x0D0000000. - * Make gatt start at 0x0e000,0000. This doesn't actually - * matter for us but may do if the video acceleration ever - * gets opened up. - */ - pg->mmu_gatt_start = 0xE0000000; - - pg->gtt_start = pci_resource_start(pdev, PSB_GTT_RESOURCE); - gtt_pages = pci_resource_len(pdev, PSB_GTT_RESOURCE) - >> PAGE_SHIFT; - /* CDV doesn't report this. In which case the system has 64 gtt pages */ - if (pg->gtt_start == 0 || gtt_pages == 0) { - dev_dbg(dev->dev, "GTT PCI BAR not initialized.\n"); - gtt_pages = 64; - pg->gtt_start = dev_priv->pge_ctl; - } - - pg->gatt_start = pci_resource_start(pdev, PSB_GATT_RESOURCE); - pg->gatt_pages = pci_resource_len(pdev, PSB_GATT_RESOURCE) - >> PAGE_SHIFT; - dev_priv->gtt_mem = &pdev->resource[PSB_GATT_RESOURCE]; - - if (pg->gatt_pages == 0 || pg->gatt_start == 0) { - static struct resource fudge; /* Preferably peppermint */ - /* This can occur on CDV systems. Fudge it in this case. - We really don't care what imaginary space is being allocated - at this point */ - dev_dbg(dev->dev, "GATT PCI BAR not initialized.\n"); - pg->gatt_start = 0x40000000; - pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT; - /* This is a little confusing but in fact the GTT is providing - a view from the GPU into memory and not vice versa. As such - this is really allocating space that is not the same as the - CPU address space on CDV */ - fudge.start = 0x40000000; - fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1; - fudge.name = "fudge"; - fudge.flags = IORESOURCE_MEM; - dev_priv->gtt_mem = &fudge; - } - - pg->gtt_pages = gtt_pages; - - dev_priv->gtt_map = ioremap(pg->gtt_phys_start, gtt_pages << PAGE_SHIFT); + dev_priv->gtt_map = ioremap(pg->gtt_phys_start, pg->gtt_pages << PAGE_SHIFT); if (!dev_priv->gtt_map) { dev_err(dev->dev, "Failure to map gtt.\n"); ret = -ENOMEM; @@ -264,9 +287,8 @@ err_mutex_destroy: int psb_gtt_resume(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); - struct pci_dev *pdev = to_pci_dev(dev->dev); struct psb_gtt *pg = &dev_priv->gtt; - unsigned int gtt_pages; + unsigned int old_gtt_pages = pg->gtt_pages; int ret; /* Enable the GTT */ @@ -274,61 +296,14 @@ int psb_gtt_resume(struct drm_device *dev) if (ret) return ret; - /* The root resource we allocate address space from */ - pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; + psb_gtt_init_ranges(dev_priv); - /* - * The video mmu has a hw bug when accessing 0x0D0000000. - * Make gatt start at 0x0e000,0000. This doesn't actually - * matter for us but may do if the video acceleration ever - * gets opened up. - */ - pg->mmu_gatt_start = 0xE0000000; - - pg->gtt_start = pci_resource_start(pdev, PSB_GTT_RESOURCE); - gtt_pages = pci_resource_len(pdev, PSB_GTT_RESOURCE) >> PAGE_SHIFT; - /* CDV doesn't report this. In which case the system has 64 gtt pages */ - if (pg->gtt_start == 0 || gtt_pages == 0) { - dev_dbg(dev->dev, "GTT PCI BAR not initialized.\n"); - gtt_pages = 64; - pg->gtt_start = dev_priv->pge_ctl; - } - - pg->gatt_start = pci_resource_start(pdev, PSB_GATT_RESOURCE); - pg->gatt_pages = pci_resource_len(pdev, PSB_GATT_RESOURCE) >> PAGE_SHIFT; - dev_priv->gtt_mem = &pdev->resource[PSB_GATT_RESOURCE]; - - if (pg->gatt_pages == 0 || pg->gatt_start == 0) { - static struct resource fudge; /* Preferably peppermint */ - /* - * This can occur on CDV systems. Fudge it in this case. We - * really don't care what imaginary space is being allocated - * at this point. - */ - dev_dbg(dev->dev, "GATT PCI BAR not initialized.\n"); - pg->gatt_start = 0x40000000; - pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT; - /* - * This is a little confusing but in fact the GTT is providing - * a view from the GPU into memory and not vice versa. As such - * this is really allocating space that is not the same as the - * CPU address space on CDV. - */ - fudge.start = 0x40000000; - fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1; - fudge.name = "fudge"; - fudge.flags = IORESOURCE_MEM; - dev_priv->gtt_mem = &fudge; - } - - if (gtt_pages != pg->gtt_pages) { + if (old_gtt_pages != pg->gtt_pages) { dev_err(dev->dev, "GTT resume error.\n"); - ret = -EINVAL; + ret = -ENODEV; goto err_psb_gtt_disable; } - pg->gtt_pages = gtt_pages; - psb_gtt_clear(dev_priv); err_psb_gtt_disable: From 56eda725c929da5d0a0141a923151d418856b364 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 15 Mar 2022 18:14:19 +0000 Subject: [PATCH 00223/11454] drm/i915/lmem: don't treat small BAR as an error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Just pass along the probed io_size. The backend should be able to utilize the entire range here, even if some of it is non-mappable. It does leave open with what to do with stolen local-memory. Signed-off-by: Matthew Auld Cc: Thomas Hellström Reviewed-by: Thomas Hellström Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220315181425.576828-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/gt/intel_region_lmem.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c index 6cecfdae07ad..783d81072c3b 100644 --- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c +++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c @@ -93,6 +93,7 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) struct intel_memory_region *mem; resource_size_t min_page_size; resource_size_t io_start; + resource_size_t io_size; resource_size_t lmem_size; int err; @@ -124,7 +125,8 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) io_start = pci_resource_start(pdev, 2); - if (GEM_WARN_ON(lmem_size > pci_resource_len(pdev, 2))) + io_size = min(pci_resource_len(pdev, 2), lmem_size); + if (!io_size) return ERR_PTR(-ENODEV); min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K : @@ -134,7 +136,7 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) lmem_size, min_page_size, io_start, - lmem_size, + io_size, INTEL_MEMORY_LOCAL, 0, &intel_region_lmem_ops); From b8ca8fef58d4656859a46a9d0e84821d3b6551b1 Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Tue, 15 Mar 2022 18:14:20 +0000 Subject: [PATCH 00224/11454] drm/i915/stolen: don't treat small BAR as an error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On client platforms with reduced LMEM BAR, we should be able to continue with driver load with reduced io_size. Instead of using the BAR size to determine the how large stolen should be, we should instead use the ADDR_RANGE register to figure this out(at least on platforms like DG2). For simplicity we don't attempt to support partially mappable stolen. v2: rearrange the io_mapping_init_wc slightly, since the stolen setup might result in reduced io_size. Signed-off-by: Akeem G Abodunrin Co-developed-by: Matthew Auld Signed-off-by: Matthew Auld Cc: Thomas Hellström Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220315181425.576828-2-matthew.auld@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 62 +++++++++++++++------- drivers/gpu/drm/i915/i915_reg.h | 3 ++ 2 files changed, 46 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index 0bf8f61134af..b860ec954104 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -12,6 +12,8 @@ #include "gem/i915_gem_lmem.h" #include "gem/i915_gem_region.h" +#include "gt/intel_gt.h" +#include "gt/intel_region_lmem.h" #include "i915_drv.h" #include "i915_gem_stolen.h" #include "i915_reg.h" @@ -492,7 +494,7 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem) /* Exclude the reserved region from driver use */ mem->region.end = reserved_base - 1; - mem->io_size = resource_size(&mem->region); + mem->io_size = min(mem->io_size, resource_size(&mem->region)); /* It is possible for the reserved area to end before the end of stolen * memory, so just consider the start. */ @@ -750,11 +752,6 @@ static int init_stolen_lmem(struct intel_memory_region *mem) if (GEM_WARN_ON(resource_size(&mem->region) == 0)) return -ENODEV; - if (!io_mapping_init_wc(&mem->iomap, - mem->io_start, - mem->io_size)) - return -EIO; - /* * TODO: For stolen lmem we mostly just care about populating the dsm * related bits and setting up the drm_mm allocator for the range. @@ -762,18 +759,26 @@ static int init_stolen_lmem(struct intel_memory_region *mem) */ err = i915_gem_init_stolen(mem); if (err) - goto err_fini; + return err; + + if (mem->io_size && !io_mapping_init_wc(&mem->iomap, + mem->io_start, + mem->io_size)) { + err = -EIO; + goto err_cleanup; + } return 0; -err_fini: - io_mapping_fini(&mem->iomap); +err_cleanup: + i915_gem_cleanup_stolen(mem->i915); return err; } static int release_stolen_lmem(struct intel_memory_region *mem) { - io_mapping_fini(&mem->iomap); + if (mem->io_size) + io_mapping_fini(&mem->iomap); i915_gem_cleanup_stolen(mem->i915); return 0; } @@ -790,25 +795,43 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, { struct intel_uncore *uncore = &i915->uncore; struct pci_dev *pdev = to_pci_dev(i915->drm.dev); + resource_size_t dsm_size, dsm_base, lmem_size; struct intel_memory_region *mem; + resource_size_t io_start, io_size; resource_size_t min_page_size; - resource_size_t io_start; - resource_size_t lmem_size; - u64 lmem_base; - lmem_base = intel_uncore_read64(uncore, GEN12_DSMBASE); - if (GEM_WARN_ON(lmem_base >= pci_resource_len(pdev, 2))) + if (WARN_ON_ONCE(instance)) return ERR_PTR(-ENODEV); - lmem_size = pci_resource_len(pdev, 2) - lmem_base; - io_start = pci_resource_start(pdev, 2) + lmem_base; + /* Use DSM base address instead for stolen memory */ + dsm_base = intel_uncore_read64(uncore, GEN12_DSMBASE); + if (IS_DG1(uncore->i915)) { + lmem_size = pci_resource_len(pdev, 2); + if (WARN_ON(lmem_size < dsm_base)) + return ERR_PTR(-ENODEV); + } else { + resource_size_t lmem_range; + + lmem_range = intel_gt_read_register(&i915->gt0, XEHPSDV_TILE0_ADDR_RANGE) & 0xFFFF; + lmem_size = lmem_range >> XEHPSDV_TILE_LMEM_RANGE_SHIFT; + lmem_size *= SZ_1G; + } + + dsm_size = lmem_size - dsm_base; + if (pci_resource_len(pdev, 2) < lmem_size) { + io_start = 0; + io_size = 0; + } else { + io_start = pci_resource_start(pdev, 2) + dsm_base; + io_size = dsm_size; + } min_page_size = HAS_64K_PAGES(i915) ? I915_GTT_PAGE_SIZE_64K : I915_GTT_PAGE_SIZE_4K; - mem = intel_memory_region_create(i915, lmem_base, lmem_size, + mem = intel_memory_region_create(i915, dsm_base, dsm_size, min_page_size, - io_start, lmem_size, + io_start, io_size, type, instance, &i915_region_stolen_lmem_ops); if (IS_ERR(mem)) @@ -822,6 +845,7 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, drm_dbg(&i915->drm, "Stolen Local memory IO start: %pa\n", &mem->io_start); + drm_dbg(&i915->drm, "Stolen Local DSM base: %pa\n", &dsm_base); intel_memory_region_set_name(mem, "stolen-local"); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 4da10e131216..3cdcd25ff401 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -8464,6 +8464,9 @@ enum skl_power_gate { #define SGGI_DIS REG_BIT(15) #define SGR_DIS REG_BIT(13) +#define XEHPSDV_TILE0_ADDR_RANGE _MMIO(0x4900) +#define XEHPSDV_TILE_LMEM_RANGE_SHIFT 8 + #define XEHPSDV_FLAT_CCS_BASE_ADDR _MMIO(0x4910) #define XEHPSDV_CCS_BASE_SHIFT 8 From d511d013e2869bed51191b6f70f8073e64c600a1 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 15 Mar 2022 18:14:21 +0000 Subject: [PATCH 00225/11454] drm/i915/stolen: consider I915_BO_ALLOC_GPU_ONLY MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep the behaviour consistent with normal lmem, where we assume CPU access if by default required. Signed-off-by: Matthew Auld Cc: Thomas Hellström Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220315181425.576828-3-matthew.auld@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index b860ec954104..17f35892ab7e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -695,6 +695,14 @@ static int _i915_gem_object_stolen_init(struct intel_memory_region *mem, if (size == 0) return -EINVAL; + /* + * With discrete devices, where we lack a mappable aperture there is no + * possible way to ever access this memory on the CPU side. + */ + if (mem->type == INTEL_MEMORY_STOLEN_LOCAL && !mem->io_size && + !(flags & I915_BO_ALLOC_GPU_ONLY)) + return -ENOSPC; + stolen = kzalloc(sizeof(*stolen), GFP_KERNEL); if (!stolen) return -ENOMEM; From 9b78b5dade2d26e2b77f1ac27044946e4e8e7247 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 15 Mar 2022 18:14:22 +0000 Subject: [PATCH 00226/11454] drm/i915: add i915_gem_object_create_region_at() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a generic interface for allocating an object at some specific offset, and convert stolen over. Later we will want to hook this up to different backends. Signed-off-by: Matthew Auld Cc: Thomas Hellström Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220315181425.576828-4-matthew.auld@intel.com --- .../drm/i915/display/intel_plane_initial.c | 4 +- drivers/gpu/drm/i915/gem/i915_gem_create.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_region.c | 47 ++++++++++-- drivers/gpu/drm/i915/gem/i915_gem_region.h | 7 ++ drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 1 + drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 74 ++++--------------- drivers/gpu/drm/i915/gem/i915_gem_stolen.h | 4 - drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 1 + drivers/gpu/drm/i915/gem/i915_gem_ttm.h | 1 + drivers/gpu/drm/i915/gt/intel_rc6.c | 8 +- drivers/gpu/drm/i915/intel_memory_region.h | 1 + drivers/gpu/drm/i915/selftests/mock_region.c | 1 + 12 files changed, 77 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index d7b1de4cc205..17373fd5536d 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -3,6 +3,7 @@ * Copyright © 2021 Intel Corporation */ +#include "gem/i915_gem_region.h" #include "i915_drv.h" #include "intel_atomic_plane.h" #include "intel_display.h" @@ -69,7 +70,8 @@ initial_plane_vma(struct drm_i915_private *i915, size * 2 > i915->stolen_usable_size) return NULL; - obj = i915_gem_object_create_stolen_for_preallocated(i915, base, size); + obj = i915_gem_object_create_region_at(i915->mm.stolen_region, + base, size, 0); if (IS_ERR(obj)) return NULL; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_create.c b/drivers/gpu/drm/i915/gem/i915_gem_create.c index c6eb023d3d86..5802692ea604 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_create.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_create.c @@ -123,7 +123,7 @@ __i915_gem_object_create_user_ext(struct drm_i915_private *i915, u64 size, */ flags = I915_BO_ALLOC_USER; - ret = mr->ops->init_object(mr, obj, size, 0, flags); + ret = mr->ops->init_object(mr, obj, I915_BO_INVALID_OFFSET, size, 0, flags); if (ret) goto object_free; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c index c9b2e8b91053..3428ddfb2fdb 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_region.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c @@ -27,11 +27,12 @@ void i915_gem_object_release_memory_region(struct drm_i915_gem_object *obj) mutex_unlock(&mem->objects.lock); } -struct drm_i915_gem_object * -i915_gem_object_create_region(struct intel_memory_region *mem, - resource_size_t size, - resource_size_t page_size, - unsigned int flags) +static struct drm_i915_gem_object * +__i915_gem_object_create_region(struct intel_memory_region *mem, + resource_size_t offset, + resource_size_t size, + resource_size_t page_size, + unsigned int flags) { struct drm_i915_gem_object *obj; resource_size_t default_page_size; @@ -86,7 +87,7 @@ i915_gem_object_create_region(struct intel_memory_region *mem, if (default_page_size < mem->min_page_size) flags |= I915_BO_ALLOC_PM_EARLY; - err = mem->ops->init_object(mem, obj, size, page_size, flags); + err = mem->ops->init_object(mem, obj, offset, size, page_size, flags); if (err) goto err_object_free; @@ -98,6 +99,40 @@ err_object_free: return ERR_PTR(err); } +struct drm_i915_gem_object * +i915_gem_object_create_region(struct intel_memory_region *mem, + resource_size_t size, + resource_size_t page_size, + unsigned int flags) +{ + return __i915_gem_object_create_region(mem, I915_BO_INVALID_OFFSET, + size, page_size, flags); +} + +struct drm_i915_gem_object * +i915_gem_object_create_region_at(struct intel_memory_region *mem, + resource_size_t offset, + resource_size_t size, + unsigned int flags) +{ + GEM_BUG_ON(offset == I915_BO_INVALID_OFFSET); + + if (GEM_WARN_ON(!IS_ALIGNED(size, mem->min_page_size)) || + GEM_WARN_ON(!IS_ALIGNED(offset, mem->min_page_size))) + return ERR_PTR(-EINVAL); + + if (range_overflows(offset, size, resource_size(&mem->region))) + return ERR_PTR(-EINVAL); + + if (!(flags & I915_BO_ALLOC_GPU_ONLY) && + offset + size > mem->io_size && + !i915_ggtt_has_aperture(to_gt(mem->i915)->ggtt)) + return ERR_PTR(-ENOSPC); + + return __i915_gem_object_create_region(mem, offset, size, 0, + flags | I915_BO_ALLOC_CONTIGUOUS); +} + /** * i915_gem_process_region - Iterate over all objects of a region using ops * to process and optionally skip objects diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.h b/drivers/gpu/drm/i915/gem/i915_gem_region.h index fcaa12d657d4..2dfcc41c0170 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_region.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_region.h @@ -14,6 +14,8 @@ struct sg_table; struct i915_gem_apply_to_region; +#define I915_BO_INVALID_OFFSET ((resource_size_t)-1) + /** * struct i915_gem_apply_to_region_ops - ops to use when iterating over all * region objects. @@ -56,6 +58,11 @@ i915_gem_object_create_region(struct intel_memory_region *mem, resource_size_t size, resource_size_t page_size, unsigned int flags); +struct drm_i915_gem_object * +i915_gem_object_create_region_at(struct intel_memory_region *mem, + resource_size_t offset, + resource_size_t size, + unsigned int flags); int i915_gem_process_region(struct intel_memory_region *mr, struct i915_gem_apply_to_region *apply); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 3a1c782ed791..9e5faf0bdd4e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -552,6 +552,7 @@ static int __create_shmem(struct drm_i915_private *i915, static int shmem_object_init(struct intel_memory_region *mem, struct drm_i915_gem_object *obj, + resource_size_t offset, resource_size_t size, resource_size_t page_size, unsigned int flags) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index 17f35892ab7e..143f61aaa867 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -681,6 +681,7 @@ static int __i915_gem_object_create_stolen(struct intel_memory_region *mem, static int _i915_gem_object_stolen_init(struct intel_memory_region *mem, struct drm_i915_gem_object *obj, + resource_size_t offset, resource_size_t size, resource_size_t page_size, unsigned int flags) @@ -707,8 +708,20 @@ static int _i915_gem_object_stolen_init(struct intel_memory_region *mem, if (!stolen) return -ENOMEM; - ret = i915_gem_stolen_insert_node(i915, stolen, size, - mem->min_page_size); + if (offset != I915_BO_INVALID_OFFSET) { + drm_dbg(&i915->drm, + "creating preallocated stolen object: stolen_offset=%pa, size=%pa\n", + &offset, &size); + + stolen->start = offset; + stolen->size = size; + mutex_lock(&i915->mm.stolen_lock); + ret = drm_mm_reserve_node(&i915->mm.stolen, stolen); + mutex_unlock(&i915->mm.stolen_lock); + } else { + ret = i915_gem_stolen_insert_node(i915, stolen, size, + mem->min_page_size); + } if (ret) goto err_free; @@ -882,63 +895,6 @@ i915_gem_stolen_smem_setup(struct drm_i915_private *i915, u16 type, return mem; } -struct drm_i915_gem_object * -i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *i915, - resource_size_t stolen_offset, - resource_size_t size) -{ - struct intel_memory_region *mem = i915->mm.stolen_region; - struct drm_i915_gem_object *obj; - struct drm_mm_node *stolen; - int ret; - - if (!drm_mm_initialized(&i915->mm.stolen)) - return ERR_PTR(-ENODEV); - - drm_dbg(&i915->drm, - "creating preallocated stolen object: stolen_offset=%pa, size=%pa\n", - &stolen_offset, &size); - - /* KISS and expect everything to be page-aligned */ - if (GEM_WARN_ON(size == 0) || - GEM_WARN_ON(!IS_ALIGNED(size, mem->min_page_size)) || - GEM_WARN_ON(!IS_ALIGNED(stolen_offset, mem->min_page_size))) - return ERR_PTR(-EINVAL); - - stolen = kzalloc(sizeof(*stolen), GFP_KERNEL); - if (!stolen) - return ERR_PTR(-ENOMEM); - - stolen->start = stolen_offset; - stolen->size = size; - mutex_lock(&i915->mm.stolen_lock); - ret = drm_mm_reserve_node(&i915->mm.stolen, stolen); - mutex_unlock(&i915->mm.stolen_lock); - if (ret) - goto err_free; - - obj = i915_gem_object_alloc(); - if (!obj) { - ret = -ENOMEM; - goto err_stolen; - } - - ret = __i915_gem_object_create_stolen(mem, obj, stolen); - if (ret) - goto err_object_free; - - i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE); - return obj; - -err_object_free: - i915_gem_object_free(obj); -err_stolen: - i915_gem_stolen_remove_node(i915, stolen); -err_free: - kfree(stolen); - return ERR_PTR(ret); -} - bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj) { return obj->ops == &i915_gem_object_stolen_ops; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h index ccdf7befc571..d5005a39d130 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.h @@ -31,10 +31,6 @@ i915_gem_stolen_lmem_setup(struct drm_i915_private *i915, u16 type, struct drm_i915_gem_object * i915_gem_object_create_stolen(struct drm_i915_private *dev_priv, resource_size_t size); -struct drm_i915_gem_object * -i915_gem_object_create_stolen_for_preallocated(struct drm_i915_private *dev_priv, - resource_size_t stolen_offset, - resource_size_t size); bool i915_gem_object_is_stolen(const struct drm_i915_gem_object *obj); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 45cc5837ce00..5e543ed867a2 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -1142,6 +1142,7 @@ void i915_ttm_bo_destroy(struct ttm_buffer_object *bo) */ int __i915_gem_ttm_object_init(struct intel_memory_region *mem, struct drm_i915_gem_object *obj, + resource_size_t offset, resource_size_t size, resource_size_t page_size, unsigned int flags) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h index 9d698ad00853..73e371aa3850 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.h @@ -45,6 +45,7 @@ i915_ttm_to_gem(struct ttm_buffer_object *bo) int __i915_gem_ttm_object_init(struct intel_memory_region *mem, struct drm_i915_gem_object *obj, + resource_size_t offset, resource_size_t size, resource_size_t page_size, unsigned int flags); diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c index 6df359c534fe..4f11f28816f1 100644 --- a/drivers/gpu/drm/i915/gt/intel_rc6.c +++ b/drivers/gpu/drm/i915/gt/intel_rc6.c @@ -5,6 +5,7 @@ #include +#include "gem/i915_gem_region.h" #include "i915_drv.h" #include "i915_reg.h" #include "i915_vgpu.h" @@ -324,9 +325,10 @@ static int vlv_rc6_init(struct intel_rc6 *rc6) resource_size_t pcbr_offset; pcbr_offset = (pcbr & ~4095) - i915->dsm.start; - pctx = i915_gem_object_create_stolen_for_preallocated(i915, - pcbr_offset, - pctx_size); + pctx = i915_gem_object_create_region_at(i915->mm.stolen_region, + pcbr_offset, + pctx_size, + 0); if (IS_ERR(pctx)) return PTR_ERR(pctx); diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h index 21dcbd620758..56f266020285 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.h +++ b/drivers/gpu/drm/i915/intel_memory_region.h @@ -54,6 +54,7 @@ struct intel_memory_region_ops { int (*init_object)(struct intel_memory_region *mem, struct drm_i915_gem_object *obj, + resource_size_t offset, resource_size_t size, resource_size_t page_size, unsigned int flags); diff --git a/drivers/gpu/drm/i915/selftests/mock_region.c b/drivers/gpu/drm/i915/selftests/mock_region.c index f64325491f35..f16c0b7198c7 100644 --- a/drivers/gpu/drm/i915/selftests/mock_region.c +++ b/drivers/gpu/drm/i915/selftests/mock_region.c @@ -57,6 +57,7 @@ static const struct drm_i915_gem_object_ops mock_region_obj_ops = { static int mock_object_init(struct intel_memory_region *mem, struct drm_i915_gem_object *obj, + resource_size_t offset, resource_size_t size, resource_size_t page_size, unsigned int flags) From ecbf20604848eccc007030766efaed2bb5533191 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 15 Mar 2022 18:14:23 +0000 Subject: [PATCH 00227/11454] drm/i915/ttm: wire up the object offset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the ttm backend we can use existing placements fpfn and lpfn to force the allocator to place the object at the requested offset, potentially evicting stuff if the spot is currently occupied. Signed-off-by: Matthew Auld Cc: Thomas Hellström Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220315181425.576828-5-matthew.auld@intel.com --- .../gpu/drm/i915/gem/i915_gem_object_types.h | 2 ++ drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 18 ++++++++++++++---- drivers/gpu/drm/i915/i915_ttm_buddy_manager.c | 3 ++- drivers/gpu/drm/i915/intel_region_ttm.c | 7 ++++++- drivers/gpu/drm/i915/intel_region_ttm.h | 1 + drivers/gpu/drm/i915/selftests/mock_region.c | 3 +++ 6 files changed, 28 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h index fd54eb8f4826..2c88bdb8ff7c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_object_types.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_object_types.h @@ -631,6 +631,8 @@ struct drm_i915_gem_object { struct drm_mm_node *stolen; + resource_size_t bo_offset; + unsigned long scratch; u64 encode; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 5e543ed867a2..e4a06fcf741a 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -126,6 +126,8 @@ i915_ttm_select_tt_caching(const struct drm_i915_gem_object *obj) static void i915_ttm_place_from_region(const struct intel_memory_region *mr, struct ttm_place *place, + resource_size_t offset, + resource_size_t size, unsigned int flags) { memset(place, 0, sizeof(*place)); @@ -133,7 +135,10 @@ i915_ttm_place_from_region(const struct intel_memory_region *mr, if (flags & I915_BO_ALLOC_CONTIGUOUS) place->flags |= TTM_PL_FLAG_CONTIGUOUS; - if (mr->io_size && mr->io_size < mr->total) { + if (offset != I915_BO_INVALID_OFFSET) { + place->fpfn = offset >> PAGE_SHIFT; + place->lpfn = place->fpfn + (size >> PAGE_SHIFT); + } else if (mr->io_size && mr->io_size < mr->total) { if (flags & I915_BO_ALLOC_GPU_ONLY) { place->flags |= TTM_PL_FLAG_TOPDOWN; } else { @@ -155,12 +160,14 @@ i915_ttm_placement_from_obj(const struct drm_i915_gem_object *obj, placement->num_placement = 1; i915_ttm_place_from_region(num_allowed ? obj->mm.placements[0] : - obj->mm.region, requested, flags); + obj->mm.region, requested, obj->bo_offset, + obj->base.size, flags); /* Cache this on object? */ placement->num_busy_placement = num_allowed; for (i = 0; i < placement->num_busy_placement; ++i) - i915_ttm_place_from_region(obj->mm.placements[i], busy + i, flags); + i915_ttm_place_from_region(obj->mm.placements[i], busy + i, + obj->bo_offset, obj->base.size, flags); if (num_allowed == 0) { *busy = *requested; @@ -802,7 +809,8 @@ static int __i915_ttm_migrate(struct drm_i915_gem_object *obj, struct ttm_placement placement; int ret; - i915_ttm_place_from_region(mr, &requested, flags); + i915_ttm_place_from_region(mr, &requested, obj->bo_offset, + obj->base.size, flags); placement.num_placement = 1; placement.num_busy_placement = 1; placement.placement = &requested; @@ -1159,6 +1167,8 @@ int __i915_gem_ttm_object_init(struct intel_memory_region *mem, drm_gem_private_object_init(&i915->drm, &obj->base, size); i915_gem_object_init(obj, &i915_gem_ttm_obj_ops, &lock_class, flags); + obj->bo_offset = offset; + /* Don't put on a region list until we're either locked or fully initialized. */ obj->mm.region = mem; INIT_LIST_HEAD(&obj->mm.region_link); diff --git a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c index 129f668f21ff..8e4e3f72c1ef 100644 --- a/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c +++ b/drivers/gpu/drm/i915/i915_ttm_buddy_manager.c @@ -71,7 +71,8 @@ static int i915_ttm_buddy_man_alloc(struct ttm_resource_manager *man, GEM_BUG_ON(min_page_size < mm->chunk_size); - if (place->flags & TTM_PL_FLAG_CONTIGUOUS) { + if (place->fpfn + bman_res->base.num_pages != place->lpfn && + place->flags & TTM_PL_FLAG_CONTIGUOUS) { unsigned long pages; size = roundup_pow_of_two(size); diff --git a/drivers/gpu/drm/i915/intel_region_ttm.c b/drivers/gpu/drm/i915/intel_region_ttm.c index 737ef3f4ab54..62ff77445b01 100644 --- a/drivers/gpu/drm/i915/intel_region_ttm.c +++ b/drivers/gpu/drm/i915/intel_region_ttm.c @@ -12,6 +12,7 @@ #include "intel_region_ttm.h" +#include "gem/i915_gem_region.h" #include "gem/i915_gem_ttm.h" /* For the funcs/ops export only */ /** * DOC: TTM support structure @@ -191,6 +192,7 @@ intel_region_ttm_resource_to_rsgt(struct intel_memory_region *mem, */ struct ttm_resource * intel_region_ttm_resource_alloc(struct intel_memory_region *mem, + resource_size_t offset, resource_size_t size, unsigned int flags) { @@ -202,7 +204,10 @@ intel_region_ttm_resource_alloc(struct intel_memory_region *mem, if (flags & I915_BO_ALLOC_CONTIGUOUS) place.flags |= TTM_PL_FLAG_CONTIGUOUS; - if (mem->io_size && mem->io_size < mem->total) { + if (offset != I915_BO_INVALID_OFFSET) { + place.fpfn = offset >> PAGE_SHIFT; + place.lpfn = place.fpfn + (size >> PAGE_SHIFT); + } else if (mem->io_size && mem->io_size < mem->total) { if (flags & I915_BO_ALLOC_GPU_ONLY) { place.flags |= TTM_PL_FLAG_TOPDOWN; } else { diff --git a/drivers/gpu/drm/i915/intel_region_ttm.h b/drivers/gpu/drm/i915/intel_region_ttm.h index fdee5e7bd46c..cf9d86dcf409 100644 --- a/drivers/gpu/drm/i915/intel_region_ttm.h +++ b/drivers/gpu/drm/i915/intel_region_ttm.h @@ -36,6 +36,7 @@ struct ttm_device_funcs *i915_ttm_driver(void); #ifdef CONFIG_DRM_I915_SELFTEST struct ttm_resource * intel_region_ttm_resource_alloc(struct intel_memory_region *mem, + resource_size_t offset, resource_size_t size, unsigned int flags); #endif diff --git a/drivers/gpu/drm/i915/selftests/mock_region.c b/drivers/gpu/drm/i915/selftests/mock_region.c index f16c0b7198c7..670557ce1024 100644 --- a/drivers/gpu/drm/i915/selftests/mock_region.c +++ b/drivers/gpu/drm/i915/selftests/mock_region.c @@ -26,6 +26,7 @@ static int mock_region_get_pages(struct drm_i915_gem_object *obj) int err; obj->mm.res = intel_region_ttm_resource_alloc(obj->mm.region, + obj->bo_offset, obj->base.size, obj->flags); if (IS_ERR(obj->mm.res)) @@ -71,6 +72,8 @@ static int mock_object_init(struct intel_memory_region *mem, drm_gem_private_object_init(&i915->drm, &obj->base, size); i915_gem_object_init(obj, &mock_region_obj_ops, &lock_class, flags); + obj->bo_offset = offset; + obj->read_domains = I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT; i915_gem_object_set_cache_coherency(obj, I915_CACHE_NONE); From 51dc0e1a58798417e794d67b7193fe8f01cc2c86 Mon Sep 17 00:00:00 2001 From: CQ Tang Date: Tue, 15 Mar 2022 18:14:24 +0000 Subject: [PATCH 00228/11454] drm/i915/display: Check mappable aperture when pinning preallocated vma MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When system does not have mappable aperture, ggtt->mappable_end=0. In this case if we pass PIN_MAPPABLE when pinning vma, the pinning code will return -ENOSPC. So conditionally set PIN_MAPPABLE if HAS_GMCH(). Suggested-by: Chris P Wilson Signed-off-by: CQ Tang Cc: Radhakrishna Sripada Cc: Ap Kamal Reviewed-by: Matthew Auld Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Ville Syrjälä Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220315181425.576828-6-matthew.auld@intel.com --- drivers/gpu/drm/i915/display/intel_plane_initial.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 17373fd5536d..a934fcca59d2 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -51,6 +51,7 @@ initial_plane_vma(struct drm_i915_private *i915, struct drm_i915_gem_object *obj; struct i915_vma *vma; u32 base, size; + u64 pinctl; if (!mem || plane_config->size == 0) return NULL; @@ -101,7 +102,10 @@ initial_plane_vma(struct drm_i915_private *i915, if (IS_ERR(vma)) goto err_obj; - if (i915_ggtt_pin(vma, NULL, 0, PIN_MAPPABLE | PIN_OFFSET_FIXED | base)) + pinctl = PIN_GLOBAL | PIN_OFFSET_FIXED | base; + if (HAS_GMCH(i915)) + pinctl |= PIN_MAPPABLE; + if (i915_vma_pin(vma, 0, 0, pinctl)) goto err_obj; if (i915_gem_object_is_tiled(obj) && From 7fe7c2a679dcec878d3f5ed4ee0dc064bfb91719 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Tue, 15 Mar 2022 18:14:25 +0000 Subject: [PATCH 00229/11454] drm/i915: fixup the initial fb base on DGFX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On integrated it looks like the GGTT base should always 1:1 maps to somewhere within DSM. On discrete the base seems to be pre-programmed with a normal lmem address, and is not 1:1 mapped with the base address. On such devices probe the lmem address directly from the PTE. v2(Ville): - The base is actually the pre-programmed GGTT address, which is then meant to 1:1 map to somewhere inside dsm. In the case of dgpu the base looks to just be some offset within lmem, but this also happens to be the exact dsm start, on dg1. Therefore we should only need to fudge the physical address, before allocating from stolen. - Bail if it's not located in dsm. v3: - Scratch that. There doesn't seem to be any relationship with the base and PTE address, on at least DG1. Let's instead just grab the lmem address from the PTE itself. Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Ville Syrjälä Cc: Nirmoy Das Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220315181425.576828-7-matthew.auld@intel.com --- .../drm/i915/display/intel_plane_initial.c | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index a934fcca59d2..5c0cd0775a14 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -47,17 +47,55 @@ static struct i915_vma * initial_plane_vma(struct drm_i915_private *i915, struct intel_initial_plane_config *plane_config) { - struct intel_memory_region *mem = i915->mm.stolen_region; + struct intel_memory_region *mem; struct drm_i915_gem_object *obj; struct i915_vma *vma; + resource_size_t phys_base; u32 base, size; u64 pinctl; - if (!mem || plane_config->size == 0) + if (plane_config->size == 0) + return NULL; + + base = round_down(plane_config->base, I915_GTT_MIN_ALIGNMENT); + if (IS_DGFX(i915)) { + gen8_pte_t __iomem *gte = to_gt(i915)->ggtt->gsm; + gen8_pte_t pte; + + gte += base / I915_GTT_PAGE_SIZE; + + pte = ioread64(gte); + if (!(pte & GEN12_GGTT_PTE_LM)) { + drm_err(&i915->drm, + "Initial plane programming missing PTE_LM bit\n"); + return NULL; + } + + phys_base = pte & I915_GTT_PAGE_MASK; + mem = i915->mm.regions[INTEL_REGION_LMEM]; + + /* + * We don't currently expect this to ever be placed in the + * stolen portion. + */ + if (phys_base >= resource_size(&mem->region)) { + drm_err(&i915->drm, + "Initial plane programming using invalid range, phys_base=%pa\n", + &phys_base); + return NULL; + } + + drm_dbg(&i915->drm, + "Using phys_base=%pa, based on initial plane programming\n", + &phys_base); + } else { + phys_base = base; + mem = i915->mm.stolen_region; + } + + if (!mem) return NULL; - base = round_down(plane_config->base, - I915_GTT_MIN_ALIGNMENT); size = round_up(plane_config->base + plane_config->size, mem->min_page_size); size -= base; @@ -68,11 +106,11 @@ initial_plane_vma(struct drm_i915_private *i915, * features. */ if (IS_ENABLED(CONFIG_FRAMEBUFFER_CONSOLE) && + mem == i915->mm.stolen_region && size * 2 > i915->stolen_usable_size) return NULL; - obj = i915_gem_object_create_region_at(i915->mm.stolen_region, - base, size, 0); + obj = i915_gem_object_create_region_at(mem, phys_base, size, 0); if (IS_ERR(obj)) return NULL; From f33b21f1397ee0f22f1d514cf6c3344c6c731a8b Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 15 Mar 2022 22:19:29 +0000 Subject: [PATCH 00230/11454] drm/nouveau: Fix spelling mistake "endianess" -> "endianness" There is a spelling mistake in a nvdev_error error message. Fix it. Signed-off-by: Colin Ian King Reviewed-by: Lyude Paul Signed-off-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20220315221929.2959700-1-colin.i.king@gmail.com --- drivers/gpu/drm/nouveau/nvkm/engine/device/base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 88d262ba648c..62efbd0f3846 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2935,7 +2935,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func, /* switch mmio to cpu's native endianness */ if (!nvkm_device_endianness(device)) { nvdev_error(device, - "Couldn't switch GPU to CPUs endianess\n"); + "Couldn't switch GPU to CPUs endianness\n"); ret = -ENOSYS; goto done; } From 0438fd1aa69cb97dffa4c4285b1a330e46ef8832 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 16 Mar 2022 11:50:18 +0200 Subject: [PATCH 00231/11454] drm/i915: move i915_gem_object_needs_bit17_swizzle() to i915_gem_tiling.[ch] Move i915_gem_object_needs_bit17_swizzle() to i915_gem_tiling.[ch] as a i915_gem_object function related to tiling. Also un-inline while at it; does not seem like this is a function needed in hot paths. v2: i915_gem_tiling.[ch] instead of intel_ggtt_fencing.[ch] (Chris) Cc: Tvrtko Ursulin Signed-off-by: Jani Nikula Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20220316095018.137998-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_phys.c | 1 + drivers/gpu/drm/i915/gem/i915_gem_shmem.c | 3 ++- drivers/gpu/drm/i915/gem/i915_gem_tiling.c | 8 ++++++++ drivers/gpu/drm/i915/gem/i915_gem_tiling.h | 2 ++ drivers/gpu/drm/i915/i915_drv.h | 9 --------- 5 files changed, 13 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_phys.c b/drivers/gpu/drm/i915/gem/i915_gem_phys.c index ca6faffcc496..0d0e46dae559 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_phys.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_phys.c @@ -14,6 +14,7 @@ #include "i915_drv.h" #include "i915_gem_object.h" #include "i915_gem_region.h" +#include "i915_gem_tiling.h" #include "i915_scatterlist.h" static int i915_gem_object_get_pages_phys(struct drm_i915_gem_object *obj) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c index 4efa821f3cb1..c42e1e1c90be 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_shmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_shmem.c @@ -12,8 +12,9 @@ #include "gem/i915_gem_region.h" #include "i915_drv.h" -#include "i915_gemfs.h" #include "i915_gem_object.h" +#include "i915_gem_tiling.h" +#include "i915_gemfs.h" #include "i915_scatterlist.h" #include "i915_trace.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c index d6adda5bf96b..80ac0db1ae8c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_tiling.c @@ -219,6 +219,14 @@ i915_gem_object_fence_prepare(struct drm_i915_gem_object *obj, return ret; } +bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) +{ + struct drm_i915_private *i915 = to_i915(obj->base.dev); + + return to_gt(i915)->ggtt->bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 && + i915_gem_object_is_tiled(obj); +} + int i915_gem_object_set_tiling(struct drm_i915_gem_object *obj, unsigned int tiling, unsigned int stride) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_tiling.h b/drivers/gpu/drm/i915/gem/i915_gem_tiling.h index 9924196a8139..6bd5751abf28 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_tiling.h +++ b/drivers/gpu/drm/i915/gem/i915_gem_tiling.h @@ -8,8 +8,10 @@ #include +struct drm_i915_gem_object; struct drm_i915_private; +bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj); u32 i915_gem_fence_size(struct drm_i915_private *i915, u32 size, unsigned int tiling, unsigned int stride); u32 i915_gem_fence_alignment(struct drm_i915_private *i915, u32 size, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1c9a7189e0a5..3c85dc8c1f04 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1474,15 +1474,6 @@ void i915_gem_driver_release(struct drm_i915_private *dev_priv); int i915_gem_open(struct drm_i915_private *i915, struct drm_file *file); -/* i915_gem_tiling.c */ -static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj) -{ - struct drm_i915_private *i915 = to_i915(obj->base.dev); - - return to_gt(i915)->ggtt->bit_6_swizzle_x == I915_BIT_6_SWIZZLE_9_10_17 && - i915_gem_object_is_tiled(obj); -} - /* intel_device_info.c */ static inline struct intel_device_info * mkwrite_device_info(struct drm_i915_private *dev_priv) From aa457ff1b2be72c0d89ee2118769859e513e6fc8 Mon Sep 17 00:00:00 2001 From: Jeffrey Hugo Date: Mon, 7 Mar 2022 08:32:36 -0700 Subject: [PATCH 00232/11454] drm/doc: Clarify what ioctls can be used on render nodes The documentation for render nodes indicates that only "PRIME-related" ioctls are valid on render nodes, but the documentation does not clarify what that means. If the reader is not familiar with PRIME, they may beleive this to be only the ioctls with "PRIME" in the name and not other ioctls such as set of syncobj ioctls. Clarify the situation for the reader by referencing where the reader will find a current list of valid ioctls. Signed-off-by: Jeffrey Hugo Acked-by: Pekka Paalanen Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/1646667156-16366-1-git-send-email-quic_jhugo@quicinc.com --- Documentation/gpu/drm-uapi.rst | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/gpu/drm-uapi.rst b/Documentation/gpu/drm-uapi.rst index 199afb503ab1..ce47b4292481 100644 --- a/Documentation/gpu/drm-uapi.rst +++ b/Documentation/gpu/drm-uapi.rst @@ -148,7 +148,9 @@ clients together with the legacy drmAuth authentication procedure. If a driver advertises render node support, DRM core will create a separate render node called renderD. There will be one render node per device. No ioctls except PRIME-related ioctls will be allowed on -this node. Especially GEM_OPEN will be explicitly prohibited. Render +this node. Especially GEM_OPEN will be explicitly prohibited. For a +complete list of driver-independent ioctls that can be used on render +nodes, see the ioctls marked DRM_RENDER_ALLOW in drm_ioctl.c Render nodes are designed to avoid the buffer-leaks, which occur if clients guess the flink names or mmap offsets on the legacy interface. Additionally to this basic interface, drivers must mark their From 9b13a3fcd35fc24045d2fd0f0e13ddd8d7985b4b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 17 Mar 2022 09:18:26 +0100 Subject: [PATCH 00233/11454] drm/format-helper: Rename drm_fb_xrgb8888_to_mono_reversed() There is no "reversed" handling in drm_fb_xrgb8888_to_mono_reversed(): the function just converts from color to grayscale, and reduces the number of grayscale levels from 256 to 2 (i.e. brightness 0-127 is mapped to 0, 128-255 to 1). All "reversed" handling is done in the repaper driver, where this function originated. Hence make this clear by renaming drm_fb_xrgb8888_to_mono_reversed() to drm_fb_xrgb8888_to_mono(), and documenting the black/white pixel mapping. Fixes: bcf8b616deb87941 ("drm/format-helper: Add drm_fb_xrgb8888_to_mono_reversed()") Signed-off-by: Geert Uytterhoeven Acked-by: Javier Martinez Canillas Reviewed-by: Andy Shevchenko Signed-off-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20220317081830.1211400-2-geert@linux-m68k.org --- drivers/gpu/drm/drm_format_helper.c | 31 ++++++++++++++--------------- drivers/gpu/drm/solomon/ssd130x.c | 2 +- drivers/gpu/drm/tiny/repaper.c | 2 +- include/drm/drm_format_helper.h | 5 ++--- 4 files changed, 19 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index bc0f49773868..5d9d0c695845 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -594,8 +594,8 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for } EXPORT_SYMBOL(drm_fb_blit_toio); -static void drm_fb_gray8_to_mono_reversed_line(u8 *dst, const u8 *src, unsigned int pixels, - unsigned int start_offset, unsigned int end_len) +static void drm_fb_gray8_to_mono_line(u8 *dst, const u8 *src, unsigned int pixels, + unsigned int start_offset, unsigned int end_len) { unsigned int xb, i; @@ -621,8 +621,8 @@ static void drm_fb_gray8_to_mono_reversed_line(u8 *dst, const u8 *src, unsigned } /** - * drm_fb_xrgb8888_to_mono_reversed - Convert XRGB8888 to reversed monochrome - * @dst: reversed monochrome destination buffer + * drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome + * @dst: monochrome destination buffer (0=black, 1=white) * @dst_pitch: Number of bytes between two consecutive scanlines within dst * @src: XRGB8888 source buffer * @fb: DRM framebuffer @@ -633,10 +633,10 @@ static void drm_fb_gray8_to_mono_reversed_line(u8 *dst, const u8 *src, unsigned * and use this function to convert to the native format. * * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and - * then the result is converted from grayscale to reversed monohrome. + * then the result is converted from grayscale to monochrome. */ -void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *vaddr, - const struct drm_framebuffer *fb, const struct drm_rect *clip) +void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vaddr, + const struct drm_framebuffer *fb, const struct drm_rect *clip) { unsigned int linepixels = drm_rect_width(clip); unsigned int lines = clip->y2 - clip->y1; @@ -652,8 +652,8 @@ void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const v return; /* - * The reversed mono destination buffer contains 1 bit per pixel - * and destination scanlines have to be in multiple of 8 pixels. + * The mono destination buffer contains 1 bit per pixel and + * destination scanlines have to be in multiple of 8 pixels. */ if (!dst_pitch) dst_pitch = DIV_ROUND_UP(linepixels, 8); @@ -664,9 +664,9 @@ void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const v * The cma memory is write-combined so reads are uncached. * Speed up by fetching one line at a time. * - * Also, format conversion from XR24 to reversed monochrome - * are done line-by-line but are converted to 8-bit grayscale - * as an intermediate step. + * Also, format conversion from XR24 to monochrome are done + * line-by-line but are converted to 8-bit grayscale as an + * intermediate step. * * Allocate a buffer to be used for both copying from the cma * memory and to store the intermediate grayscale line pixels. @@ -683,7 +683,7 @@ void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const v * are not aligned to multiple of 8. * * Calculate if the start and end pixels are not aligned and set the - * offsets for the reversed mono line conversion function to adjust. + * offsets for the mono line conversion function to adjust. */ start_offset = clip->x1 % 8; end_len = clip->x2 % 8; @@ -692,12 +692,11 @@ void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const v for (y = 0; y < lines; y++) { src32 = memcpy(src32, vaddr, len_src32); drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels); - drm_fb_gray8_to_mono_reversed_line(mono, gray8, dst_pitch, - start_offset, end_len); + drm_fb_gray8_to_mono_line(mono, gray8, dst_pitch, start_offset, end_len); vaddr += fb->pitches[0]; mono += dst_pitch; } kfree(src32); } -EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono_reversed); +EXPORT_SYMBOL(drm_fb_xrgb8888_to_mono); diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index a95ab7e5bbf0..33e5bacbdf76 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -458,7 +458,7 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf if (!buf) return -ENOMEM; - drm_fb_xrgb8888_to_mono_reversed(buf, 0, vmap, fb, rect); + drm_fb_xrgb8888_to_mono(buf, 0, vmap, fb, rect); ssd130x_update_rect(ssd130x, buf, rect); diff --git a/drivers/gpu/drm/tiny/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 5c74e236b16d..c7018dd1b831 100644 --- a/drivers/gpu/drm/tiny/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -540,7 +540,7 @@ static int repaper_fb_dirty(struct drm_framebuffer *fb) if (ret) goto out_free; - drm_fb_xrgb8888_to_mono_reversed(buf, 0, cma_obj->vaddr, fb, &clip); + drm_fb_xrgb8888_to_mono(buf, 0, cma_obj->vaddr, fb, &clip); drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE); diff --git a/include/drm/drm_format_helper.h b/include/drm/drm_format_helper.h index 0b0937c0b2f6..55145eca0782 100644 --- a/include/drm/drm_format_helper.h +++ b/include/drm/drm_format_helper.h @@ -43,8 +43,7 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for const void *vmap, const struct drm_framebuffer *fb, const struct drm_rect *rect); -void drm_fb_xrgb8888_to_mono_reversed(void *dst, unsigned int dst_pitch, const void *src, - const struct drm_framebuffer *fb, - const struct drm_rect *clip); +void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *src, + const struct drm_framebuffer *fb, const struct drm_rect *clip); #endif /* __LINUX_DRM_FORMAT_HELPER_H */ From 7392f2459eefcdab1d998af002d2b8b16fe4a2fd Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 17 Mar 2022 09:18:27 +0100 Subject: [PATCH 00234/11454] drm/format-helper: Fix XRGB888 to monochrome conversion The conversion functions drm_fb_xrgb8888_to_mono() and drm_fb_gray8_to_mono_line() do not behave correctly when the horizontal boundaries of the clip rectangle are not multiples of 8: a. When x1 % 8 != 0, the calculated pitch is not correct, b. When x2 % 8 != 0, the pixel data for the last byte is wrong. Simplify the code and fix (a) by: 1. Removing start_offset, and always storing the first pixel in the first bit of the monochrome destination buffer. Drivers that require the first pixel in a byte to be located at an x-coordinate that is a multiple of 8 can always align the clip rectangle before calling drm_fb_xrgb8888_to_mono(). Note that: - The ssd130x driver does not need the alignment, as the monochrome buffer is a temporary format, - The repaper driver always updates the full screen, so the clip rectangle is always aligned. 2. Passing the number of pixels to drm_fb_gray8_to_mono_line(), instead of the number of bytes, and the number of pixels in the last byte. Fix (b) by explicitly setting the target bit, instead of always setting bit 7 and shifting the value in each loop iteration. Remove the bogus pitch check, which operates on bytes instead of pixels, and triggers when e.g. flashing the cursor on a text console with a font that is 8 pixels wide. Drop the confusing comment about scanlines, as a pitch in bytes always contains a multiple of 8 pixels. While at it, use the drm_rect_height() helper instead of open-coding the same operation. Update the comments accordingly. Fixes: bcf8b616deb87941 ("drm/format-helper: Add drm_fb_xrgb8888_to_mono_reversed()") Signed-off-by: Geert Uytterhoeven Acked-by: Javier Martinez Canillas Reviewed-by: Andy Shevchenko Signed-off-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20220317081830.1211400-3-geert@linux-m68k.org --- drivers/gpu/drm/drm_format_helper.c | 55 ++++++++++------------------- 1 file changed, 18 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/drm_format_helper.c b/drivers/gpu/drm/drm_format_helper.c index 5d9d0c695845..e085f855a199 100644 --- a/drivers/gpu/drm/drm_format_helper.c +++ b/drivers/gpu/drm/drm_format_helper.c @@ -594,27 +594,16 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for } EXPORT_SYMBOL(drm_fb_blit_toio); -static void drm_fb_gray8_to_mono_line(u8 *dst, const u8 *src, unsigned int pixels, - unsigned int start_offset, unsigned int end_len) + +static void drm_fb_gray8_to_mono_line(u8 *dst, const u8 *src, unsigned int pixels) { - unsigned int xb, i; + while (pixels) { + unsigned int i, bits = min(pixels, 8U); + u8 byte = 0; - for (xb = 0; xb < pixels; xb++) { - unsigned int start = 0, end = 8; - u8 byte = 0x00; - - if (xb == 0 && start_offset) - start = start_offset; - - if (xb == pixels - 1 && end_len) - end = end_len; - - for (i = start; i < end; i++) { - unsigned int x = xb * 8 + i; - - byte >>= 1; - if (src[x] >> 7) - byte |= BIT(7); + for (i = 0; i < bits; i++, pixels--) { + if (*src++ >= 128) + byte |= BIT(i); } *dst++ = byte; } @@ -634,16 +623,22 @@ static void drm_fb_gray8_to_mono_line(u8 *dst, const u8 *src, unsigned int pixel * * This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and * then the result is converted from grayscale to monochrome. + * + * The first pixel (upper left corner of the clip rectangle) will be converted + * and copied to the first bit (LSB) in the first byte of the monochrome + * destination buffer. + * If the caller requires that the first pixel in a byte must be located at an + * x-coordinate that is a multiple of 8, then the caller must take care itself + * of supplying a suitable clip rectangle. */ void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vaddr, const struct drm_framebuffer *fb, const struct drm_rect *clip) { unsigned int linepixels = drm_rect_width(clip); - unsigned int lines = clip->y2 - clip->y1; + unsigned int lines = drm_rect_height(clip); unsigned int cpp = fb->format->cpp[0]; unsigned int len_src32 = linepixels * cpp; struct drm_device *dev = fb->dev; - unsigned int start_offset, end_len; unsigned int y; u8 *mono = dst, *gray8; u32 *src32; @@ -652,14 +647,11 @@ void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vadd return; /* - * The mono destination buffer contains 1 bit per pixel and - * destination scanlines have to be in multiple of 8 pixels. + * The mono destination buffer contains 1 bit per pixel */ if (!dst_pitch) dst_pitch = DIV_ROUND_UP(linepixels, 8); - drm_WARN_ONCE(dev, dst_pitch % 8 != 0, "dst_pitch is not a multiple of 8\n"); - /* * The cma memory is write-combined so reads are uncached. * Speed up by fetching one line at a time. @@ -677,22 +669,11 @@ void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vadd gray8 = (u8 *)src32 + len_src32; - /* - * For damage handling, it is possible that only parts of the source - * buffer is copied and this could lead to start and end pixels that - * are not aligned to multiple of 8. - * - * Calculate if the start and end pixels are not aligned and set the - * offsets for the mono line conversion function to adjust. - */ - start_offset = clip->x1 % 8; - end_len = clip->x2 % 8; - vaddr += clip_offset(clip, fb->pitches[0], cpp); for (y = 0; y < lines; y++) { src32 = memcpy(src32, vaddr, len_src32); drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels); - drm_fb_gray8_to_mono_line(mono, gray8, dst_pitch, start_offset, end_len); + drm_fb_gray8_to_mono_line(mono, gray8, linepixels); vaddr += fb->pitches[0]; mono += dst_pitch; } From a97e753fd358e23155ae42c61292dfd57eb54c4a Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 17 Mar 2022 09:18:28 +0100 Subject: [PATCH 00235/11454] drm/ssd130x: Fix rectangle updates The rectangle update functions ssd130x_fb_blit_rect() and ssd130x_update_rect() do not behave correctly when x1 != 0 or y1 != 0, or when y1 or y2 are not aligned to display page boundaries. E.g. when used as a text console, only the first line of text is shown on the display. 1. The buffer passed by ssd130x_fb_blit_rect() points to the first byte of monochrome bitmap data, and thus has its origin at (x1, y1), while ssd130x_update_rect() assumes it is at (0, 0). Fix ssd130x_update_rect() by changing the vertical and horizontal loop ranges, and adding the offsets only when needed. 2. In ssd130x_fb_blit_rect(), align y1 and y2 to the display page boundaries before doing the color conversion, so the full page is converted and updated. Remove the correction for an unaligned y1 from ssd130x_update_rect(), and add a check to make sure y1 is aligned. Fixes: a61732e808672cfa ("drm: Add driver for Solomon SSD130x OLED displays") Signed-off-by: Geert Uytterhoeven Acked-by: Javier Martinez Canillas Signed-off-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20220317081830.1211400-4-geert@linux-m68k.org --- drivers/gpu/drm/solomon/ssd130x.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 33e5bacbdf76..5156c4c2c076 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -355,11 +355,14 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf, unsigned int width = drm_rect_width(rect); unsigned int height = drm_rect_height(rect); unsigned int line_length = DIV_ROUND_UP(width, 8); - unsigned int pages = DIV_ROUND_UP(y % 8 + height, 8); + unsigned int pages = DIV_ROUND_UP(height, 8); + struct drm_device *drm = &ssd130x->drm; u32 array_idx = 0; int ret, i, j, k; u8 *data_array = NULL; + drm_WARN_ONCE(drm, y % 8 != 0, "y must be aligned to screen page\n"); + data_array = kcalloc(width, pages, GFP_KERNEL); if (!data_array) return -ENOMEM; @@ -401,13 +404,13 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf, if (ret < 0) goto out_free; - for (i = y / 8; i < y / 8 + pages; i++) { + for (i = 0; i < pages; i++) { int m = 8; /* Last page may be partial */ - if (8 * (i + 1) > ssd130x->height) + if (8 * (y / 8 + i + 1) > ssd130x->height) m = ssd130x->height % 8; - for (j = x; j < x + width; j++) { + for (j = 0; j < width; j++) { u8 data = 0; for (k = 0; k < m; k++) { @@ -454,6 +457,10 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf int ret = 0; u8 *buf = NULL; + /* Align y to display page boundaries */ + rect->y1 = round_down(rect->y1, 8); + rect->y2 = min_t(unsigned int, round_up(rect->y2, 8), ssd130x->height); + buf = kcalloc(fb->width, fb->height, GFP_KERNEL); if (!buf) return -ENOMEM; From 4442ac1af10442d6e7e824fdc226f89ed94d5b53 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Thu, 17 Mar 2022 09:18:29 +0100 Subject: [PATCH 00236/11454] drm/ssd130x: Reduce temporary buffer sizes ssd130x_clear_screen() allocates a temporary buffer sized to hold one byte per pixel, while it only needs to hold one bit per pixel. ssd130x_fb_blit_rect() allocates a temporary buffer sized to hold one byte per pixel for the whole frame buffer, while it only needs to hold one bit per pixel for the part that is to be updated. Pass dst_pitch to drm_fb_xrgb8888_to_mono(), as we have already calculated it anyway. Fixes: a61732e808672cfa ("drm: Add driver for Solomon SSD130x OLED displays") Signed-off-by: Geert Uytterhoeven Acked-by: Javier Martinez Canillas Signed-off-by: Javier Martinez Canillas Link: https://patchwork.freedesktop.org/patch/msgid/20220317081830.1211400-5-geert@linux-m68k.org --- drivers/gpu/drm/solomon/ssd130x.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c index 5156c4c2c076..ddff4561120e 100644 --- a/drivers/gpu/drm/solomon/ssd130x.c +++ b/drivers/gpu/drm/solomon/ssd130x.c @@ -440,7 +440,8 @@ static void ssd130x_clear_screen(struct ssd130x_device *ssd130x) .y2 = ssd130x->height, }; - buf = kcalloc(ssd130x->width, ssd130x->height, GFP_KERNEL); + buf = kcalloc(DIV_ROUND_UP(ssd130x->width, 8), ssd130x->height, + GFP_KERNEL); if (!buf) return; @@ -454,6 +455,7 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf { struct ssd130x_device *ssd130x = drm_to_ssd130x(fb->dev); void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */ + unsigned int dst_pitch; int ret = 0; u8 *buf = NULL; @@ -461,11 +463,12 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct dma_buf rect->y1 = round_down(rect->y1, 8); rect->y2 = min_t(unsigned int, round_up(rect->y2, 8), ssd130x->height); - buf = kcalloc(fb->width, fb->height, GFP_KERNEL); + dst_pitch = DIV_ROUND_UP(drm_rect_width(rect), 8); + buf = kcalloc(dst_pitch, drm_rect_height(rect), GFP_KERNEL); if (!buf) return -ENOMEM; - drm_fb_xrgb8888_to_mono(buf, 0, vmap, fb, rect); + drm_fb_xrgb8888_to_mono(buf, dst_pitch, vmap, fb, rect); ssd130x_update_rect(ssd130x, buf, rect); From 044feb974801140d923ecae66bc1685592b19865 Mon Sep 17 00:00:00 2001 From: Melissa Wen Date: Tue, 1 Feb 2022 20:26:51 -0100 Subject: [PATCH 00237/11454] drm/vc4: add tracepoints for CL submissions Trace submit_cl_ioctl and related IRQs for CL submission and bin/render jobs execution. It might be helpful to get a rendering timeline and track job throttling. Signed-off-by: Melissa Wen Reviewed-by: Jose Maria Casanova Crespo Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20220201212651.zhltjmaokisffq3x@mail.igalia.com --- drivers/gpu/drm/vc4/vc4_gem.c | 7 +++ drivers/gpu/drm/vc4/vc4_irq.c | 5 ++ drivers/gpu/drm/vc4/vc4_trace.h | 95 +++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 445d3bab89e0..4abf10b66fe8 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -485,6 +485,8 @@ again: * immediately move it to the to-be-rendered queue. */ if (exec->ct0ca != exec->ct0ea) { + trace_vc4_submit_cl(dev, false, exec->seqno, exec->ct0ca, + exec->ct0ea); submit_cl(dev, 0, exec->ct0ca, exec->ct0ea); } else { struct vc4_exec_info *next; @@ -519,6 +521,7 @@ vc4_submit_next_render_job(struct drm_device *dev) */ vc4_flush_texture_caches(dev); + trace_vc4_submit_cl(dev, true, exec->seqno, exec->ct1ca, exec->ct1ea); submit_cl(dev, 1, exec->ct1ca, exec->ct1ea); } @@ -1135,6 +1138,10 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data, struct dma_fence *in_fence; int ret = 0; + trace_vc4_submit_cl_ioctl(dev, args->bin_cl_size, + args->shader_rec_size, + args->bo_handle_count); + if (!vc4->v3d) { DRM_DEBUG("VC4_SUBMIT_CL with no VC4 V3D probed\n"); return -ENODEV; diff --git a/drivers/gpu/drm/vc4/vc4_irq.c b/drivers/gpu/drm/vc4/vc4_irq.c index 20fa8e34c20b..4342fb43e8c1 100644 --- a/drivers/gpu/drm/vc4/vc4_irq.c +++ b/drivers/gpu/drm/vc4/vc4_irq.c @@ -51,6 +51,7 @@ #include "vc4_drv.h" #include "vc4_regs.h" +#include "vc4_trace.h" #define V3D_DRIVER_IRQS (V3D_INT_OUTOMEM | \ V3D_INT_FLDONE | \ @@ -123,6 +124,8 @@ vc4_irq_finish_bin_job(struct drm_device *dev) if (!exec) return; + trace_vc4_bcl_end_irq(dev, exec->seqno); + vc4_move_job_to_render(dev, exec); next = vc4_first_bin_job(vc4); @@ -161,6 +164,8 @@ vc4_irq_finish_render_job(struct drm_device *dev) if (!exec) return; + trace_vc4_rcl_end_irq(dev, exec->seqno); + vc4->finished_seqno++; list_move_tail(&exec->head, &vc4->job_done_list); diff --git a/drivers/gpu/drm/vc4/vc4_trace.h b/drivers/gpu/drm/vc4/vc4_trace.h index 1cccde0b09a7..7f4c49e7e011 100644 --- a/drivers/gpu/drm/vc4/vc4_trace.h +++ b/drivers/gpu/drm/vc4/vc4_trace.h @@ -52,6 +52,101 @@ TRACE_EVENT(vc4_wait_for_seqno_end, __entry->dev, __entry->seqno) ); +TRACE_EVENT(vc4_submit_cl_ioctl, + TP_PROTO(struct drm_device *dev, u32 bin_cl_size, u32 shader_rec_size, u32 bo_count), + TP_ARGS(dev, bin_cl_size, shader_rec_size, bo_count), + + TP_STRUCT__entry( + __field(u32, dev) + __field(u32, bin_cl_size) + __field(u32, shader_rec_size) + __field(u32, bo_count) + ), + + TP_fast_assign( + __entry->dev = dev->primary->index; + __entry->bin_cl_size = bin_cl_size; + __entry->shader_rec_size = shader_rec_size; + __entry->bo_count = bo_count; + ), + + TP_printk("dev=%u, bin_cl_size=%u, shader_rec_size=%u, bo_count=%u", + __entry->dev, + __entry->bin_cl_size, + __entry->shader_rec_size, + __entry->bo_count) +); + +TRACE_EVENT(vc4_submit_cl, + TP_PROTO(struct drm_device *dev, bool is_render, + uint64_t seqno, + u32 ctnqba, u32 ctnqea), + TP_ARGS(dev, is_render, seqno, ctnqba, ctnqea), + + TP_STRUCT__entry( + __field(u32, dev) + __field(bool, is_render) + __field(u64, seqno) + __field(u32, ctnqba) + __field(u32, ctnqea) + ), + + TP_fast_assign( + __entry->dev = dev->primary->index; + __entry->is_render = is_render; + __entry->seqno = seqno; + __entry->ctnqba = ctnqba; + __entry->ctnqea = ctnqea; + ), + + TP_printk("dev=%u, %s, seqno=%llu, 0x%08x..0x%08x", + __entry->dev, + __entry->is_render ? "RCL" : "BCL", + __entry->seqno, + __entry->ctnqba, + __entry->ctnqea) +); + +TRACE_EVENT(vc4_bcl_end_irq, + TP_PROTO(struct drm_device *dev, + uint64_t seqno), + TP_ARGS(dev, seqno), + + TP_STRUCT__entry( + __field(u32, dev) + __field(u64, seqno) + ), + + TP_fast_assign( + __entry->dev = dev->primary->index; + __entry->seqno = seqno; + ), + + TP_printk("dev=%u, seqno=%llu", + __entry->dev, + __entry->seqno) +); + +TRACE_EVENT(vc4_rcl_end_irq, + TP_PROTO(struct drm_device *dev, + uint64_t seqno), + TP_ARGS(dev, seqno), + + TP_STRUCT__entry( + __field(u32, dev) + __field(u64, seqno) + ), + + TP_fast_assign( + __entry->dev = dev->primary->index; + __entry->seqno = seqno; + ), + + TP_printk("dev=%u, seqno=%llu", + __entry->dev, + __entry->seqno) +); + #endif /* _VC4_TRACE_H_ */ /* This part must be outside protection */ From 3138ba6e0653f62828d02e4d99e7e033e628076e Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Thu, 17 Mar 2022 10:25:52 +0100 Subject: [PATCH 00238/11454] drm/gma500: Remove unused declarations and other cruft Most of these are old leftovers from one of the driver merges. This is all dead code. Signed-off-by: Patrik Jakobsson Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220317092555.17882-1-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/psb_drv.h | 75 +------------------------------- 1 file changed, 1 insertion(+), 74 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 553d03190ce1..66f61909a8c8 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -36,12 +36,6 @@ /* Append new drm mode definition here, align with libdrm definition */ #define DRM_MODE_SCALE_NO_SCALE 2 -enum { - CHIP_PSB_8108 = 0, /* Poulsbo */ - CHIP_PSB_8109 = 1, /* Poulsbo */ - CHIP_MRST_4100 = 2, /* Moorestown/Oaktrail */ -}; - #define IS_PSB(drm) ((to_pci_dev((drm)->dev)->device & 0xfffe) == 0x8108) #define IS_MRST(drm) ((to_pci_dev((drm)->dev)->device & 0xfff0) == 0x4100) #define IS_CDV(drm) ((to_pci_dev((drm)->dev)->device & 0xfff0) == 0x0be0) @@ -617,15 +611,7 @@ struct psb_ops { int i2c_bus; /* I2C bus identifier for Moorestown */ }; - - -extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int); -extern int drm_pick_crtcs(struct drm_device *dev); - /* psb_irq.c */ -extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands); -extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence); -extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence); extern int psb_enable_vblank(struct drm_crtc *crtc); extern void psb_disable_vblank(struct drm_crtc *crtc); void @@ -636,17 +622,9 @@ psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); extern u32 psb_get_vblank_counter(struct drm_crtc *crtc); -/* framebuffer.c */ -extern int psbfb_probed(struct drm_device *dev); -extern int psbfb_remove(struct drm_device *dev, - struct drm_framebuffer *fb); -/* psb_drv.c */ -extern void psb_spank(struct drm_psb_private *dev_priv); - -/* psb_reset.c */ +/* psb_lid.c */ extern void psb_lid_timer_init(struct drm_psb_private *dev_priv); extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); -extern void psb_print_pagefault(struct drm_psb_private *dev_priv); /* modesetting */ extern void psb_modeset_init(struct drm_device *dev); @@ -689,43 +667,7 @@ extern const struct psb_ops oaktrail_chip_ops; /* cdv_device.c */ extern const struct psb_ops cdv_chip_ops; -/* Debug print bits setting */ -#define PSB_D_GENERAL (1 << 0) -#define PSB_D_INIT (1 << 1) -#define PSB_D_IRQ (1 << 2) -#define PSB_D_ENTRY (1 << 3) -/* debug the get H/V BP/FP count */ -#define PSB_D_HV (1 << 4) -#define PSB_D_DBI_BF (1 << 5) -#define PSB_D_PM (1 << 6) -#define PSB_D_RENDER (1 << 7) -#define PSB_D_REG (1 << 8) -#define PSB_D_MSVDX (1 << 9) -#define PSB_D_TOPAZ (1 << 10) - -extern int drm_idle_check_interval; - /* Utilities */ -static inline u32 MRST_MSG_READ32(int domain, uint port, uint offset) -{ - int mcr = (0xD0<<24) | (port << 16) | (offset << 8); - uint32_t ret_val = 0; - struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_read_config_dword(pci_root, 0xD4, &ret_val); - pci_dev_put(pci_root); - return ret_val; -} -static inline void MRST_MSG_WRITE32(int domain, uint port, uint offset, - u32 value) -{ - int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0; - struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0); - pci_write_config_dword(pci_root, 0xD4, value); - pci_write_config_dword(pci_root, 0xD0, mcr); - pci_dev_put(pci_root); -} - static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); @@ -806,24 +748,9 @@ static inline void REGISTER_WRITE8(struct drm_device *dev, #define PSB_WVDC32(_val, _offs) iowrite32(_val, dev_priv->vdc_reg + (_offs)) #define PSB_RVDC32(_offs) ioread32(dev_priv->vdc_reg + (_offs)) -/* #define TRAP_SGX_PM_FAULT 1 */ -#ifdef TRAP_SGX_PM_FAULT -#define PSB_RSGX32(_offs) \ -({ \ - if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) { \ - pr_err("access sgx when it's off!! (READ) %s, %d\n", \ - __FILE__, __LINE__); \ - melay(1000); \ - } \ - ioread32(dev_priv->sgx_reg + (_offs)); \ -}) -#else #define PSB_RSGX32(_offs) ioread32(dev_priv->sgx_reg + (_offs)) -#endif #define PSB_WSGX32(_val, _offs) iowrite32(_val, dev_priv->sgx_reg + (_offs)) -#define MSVDX_REG_DUMP 0 - #define PSB_WMSVDX32(_val, _offs) iowrite32(_val, dev_priv->msvdx_reg + (_offs)) #define PSB_RMSVDX32(_offs) ioread32(dev_priv->msvdx_reg + (_offs)) From a29c6f882418ecc7a2046d8cf9b5a8aa92b68693 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Thu, 17 Mar 2022 10:25:53 +0100 Subject: [PATCH 00239/11454] drm/gma500: Move gma_intel_crtc_funcs into gma_display.c All functions live in gma_display.c already so move the vtable. Also shorten the name to gma_crtc_funcs. Signed-off-by: Patrik Jakobsson Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220317092555.17882-2-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/cdv_device.c | 2 +- drivers/gpu/drm/gma500/gma_display.c | 12 ++++++++++++ drivers/gpu/drm/gma500/gma_display.h | 10 ++-------- drivers/gpu/drm/gma500/oaktrail_device.c | 2 +- drivers/gpu/drm/gma500/psb_device.c | 2 +- drivers/gpu/drm/gma500/psb_drv.h | 2 -- drivers/gpu/drm/gma500/psb_intel_display.c | 12 ------------ 7 files changed, 17 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index d7c6cca23e94..887c157d75f4 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -603,7 +603,7 @@ const struct psb_ops cdv_chip_ops = { .errata = cdv_errata, .crtc_helper = &cdv_intel_helper_funcs, - .crtc_funcs = &gma_intel_crtc_funcs, + .crtc_funcs = &gma_crtc_funcs, .clock_funcs = &cdv_clock_funcs, .output_init = cdv_output_init, diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index dd801404cf99..931ffb192fc4 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -565,6 +565,18 @@ int gma_crtc_set_config(struct drm_mode_set *set, return ret; } +const struct drm_crtc_funcs gma_crtc_funcs = { + .cursor_set = gma_crtc_cursor_set, + .cursor_move = gma_crtc_cursor_move, + .gamma_set = gma_crtc_gamma_set, + .set_config = gma_crtc_set_config, + .destroy = gma_crtc_destroy, + .page_flip = gma_crtc_page_flip, + .enable_vblank = psb_enable_vblank, + .disable_vblank = psb_disable_vblank, + .get_vblank_counter = psb_get_vblank_counter, +}; + /* * Save HW states of given crtc */ diff --git a/drivers/gpu/drm/gma500/gma_display.h b/drivers/gpu/drm/gma500/gma_display.h index 7bd6c1ee8b21..113cf048105e 100644 --- a/drivers/gpu/drm/gma500/gma_display.h +++ b/drivers/gpu/drm/gma500/gma_display.h @@ -58,15 +58,7 @@ extern bool gma_pipe_has_type(struct drm_crtc *crtc, int type); extern void gma_wait_for_vblank(struct drm_device *dev); extern int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb); -extern int gma_crtc_cursor_set(struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - uint32_t width, uint32_t height); -extern int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y); extern void gma_crtc_load_lut(struct drm_crtc *crtc); -extern int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, - u16 *blue, u32 size, - struct drm_modeset_acquire_ctx *ctx); extern void gma_crtc_dpms(struct drm_crtc *crtc, int mode); extern void gma_crtc_prepare(struct drm_crtc *crtc); extern void gma_crtc_commit(struct drm_crtc *crtc); @@ -83,6 +75,8 @@ extern int gma_crtc_set_config(struct drm_mode_set *set, extern void gma_crtc_save(struct drm_crtc *crtc); extern void gma_crtc_restore(struct drm_crtc *crtc); +extern const struct drm_crtc_funcs gma_crtc_funcs; + extern void gma_encoder_prepare(struct drm_encoder *encoder); extern void gma_encoder_commit(struct drm_encoder *encoder); extern void gma_encoder_destroy(struct drm_encoder *encoder); diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 5c75eae630b5..40f1bc736125 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -545,7 +545,7 @@ const struct psb_ops oaktrail_chip_ops = { .chip_setup = oaktrail_chip_setup, .chip_teardown = oaktrail_teardown, .crtc_helper = &oaktrail_helper_funcs, - .crtc_funcs = &gma_intel_crtc_funcs, + .crtc_funcs = &gma_crtc_funcs, .output_init = oaktrail_output_init, diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index 3030f18ba022..e93e4191c0ca 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -329,7 +329,7 @@ const struct psb_ops psb_chip_ops = { .chip_teardown = psb_chip_teardown, .crtc_helper = &psb_intel_helper_funcs, - .crtc_funcs = &gma_intel_crtc_funcs, + .crtc_funcs = &gma_crtc_funcs, .clock_funcs = &psb_clock_funcs, .output_init = psb_output_init, diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 66f61909a8c8..88f44dbbc4eb 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -13,7 +13,6 @@ #include -#include "gma_display.h" #include "gtt.h" #include "intel_bios.h" #include "mmu.h" @@ -647,7 +646,6 @@ extern void oaktrail_lvds_init(struct drm_device *dev, /* psb_intel_display.c */ extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs; -extern const struct drm_crtc_funcs gma_intel_crtc_funcs; /* psb_intel_lvds.c */ extern const struct drm_connector_helper_funcs diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index d5f95212934e..6df62fe7c1e0 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -427,18 +427,6 @@ const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { .disable = gma_crtc_disable, }; -const struct drm_crtc_funcs gma_intel_crtc_funcs = { - .cursor_set = gma_crtc_cursor_set, - .cursor_move = gma_crtc_cursor_move, - .gamma_set = gma_crtc_gamma_set, - .set_config = gma_crtc_set_config, - .destroy = gma_crtc_destroy, - .page_flip = gma_crtc_page_flip, - .enable_vblank = psb_enable_vblank, - .disable_vblank = psb_disable_vblank, - .get_vblank_counter = psb_get_vblank_counter, -}; - const struct gma_clock_funcs psb_clock_funcs = { .clock = psb_intel_clock, .limit = psb_intel_limit, From 76feffd16cc9728a4d6adf2080fe7f79242822c7 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Thu, 17 Mar 2022 10:25:54 +0100 Subject: [PATCH 00240/11454] drm/gma500: Don't store crtc_funcs in psb_ops The drm_crtc_funcs are all generic and no chip specific functions are necessary. We can therefore directly put gma_crtc_funcs into the drm_crtc. Signed-off-by: Patrik Jakobsson Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220317092555.17882-3-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/cdv_device.c | 1 - drivers/gpu/drm/gma500/oaktrail_device.c | 1 - drivers/gpu/drm/gma500/psb_device.c | 1 - drivers/gpu/drm/gma500/psb_drv.h | 1 - drivers/gpu/drm/gma500/psb_intel_display.c | 3 +-- 5 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index 887c157d75f4..f854f58bcbb3 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -603,7 +603,6 @@ const struct psb_ops cdv_chip_ops = { .errata = cdv_errata, .crtc_helper = &cdv_intel_helper_funcs, - .crtc_funcs = &gma_crtc_funcs, .clock_funcs = &cdv_clock_funcs, .output_init = cdv_output_init, diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c index 40f1bc736125..5923a9c89312 100644 --- a/drivers/gpu/drm/gma500/oaktrail_device.c +++ b/drivers/gpu/drm/gma500/oaktrail_device.c @@ -545,7 +545,6 @@ const struct psb_ops oaktrail_chip_ops = { .chip_setup = oaktrail_chip_setup, .chip_teardown = oaktrail_teardown, .crtc_helper = &oaktrail_helper_funcs, - .crtc_funcs = &gma_crtc_funcs, .output_init = oaktrail_output_init, diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index e93e4191c0ca..59f325165667 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -329,7 +329,6 @@ const struct psb_ops psb_chip_ops = { .chip_teardown = psb_chip_teardown, .crtc_helper = &psb_intel_helper_funcs, - .crtc_funcs = &gma_crtc_funcs, .clock_funcs = &psb_clock_funcs, .output_init = psb_output_init, diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index 88f44dbbc4eb..aed167af13c5 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -578,7 +578,6 @@ struct psb_ops { /* Sub functions */ struct drm_crtc_helper_funcs const *crtc_helper; - struct drm_crtc_funcs const *crtc_funcs; const struct gma_clock_funcs *clock_funcs; /* Setup hooks */ diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index 6df62fe7c1e0..a99859b5b13a 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -488,8 +488,7 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, return; } - /* Set the CRTC operations from the chip specific data */ - drm_crtc_init(dev, &gma_crtc->base, dev_priv->ops->crtc_funcs); + drm_crtc_init(dev, &gma_crtc->base, &gma_crtc_funcs); /* Set the CRTC clock functions from chip specific data */ gma_crtc->clock_funcs = dev_priv->ops->clock_funcs; From 5d5fb74630c1896aa80f01a551d0a0e82e4d5765 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Thu, 17 Mar 2022 10:25:55 +0100 Subject: [PATCH 00241/11454] drm/gma500: Cosmetic cleanup of irq code Use the gma_ prefix instead of psb_ since the code is common for all chips. Various coding style fixes. Removal of unused code. Removal of duplicate function declarations. Signed-off-by: Patrik Jakobsson Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220317092555.17882-4-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/gma_display.c | 8 +-- drivers/gpu/drm/gma500/opregion.c | 5 +- drivers/gpu/drm/gma500/power.c | 10 +-- drivers/gpu/drm/gma500/psb_drv.c | 2 +- drivers/gpu/drm/gma500/psb_drv.h | 11 ---- drivers/gpu/drm/gma500/psb_irq.c | 94 +++++++++++----------------- drivers/gpu/drm/gma500/psb_irq.h | 19 +++--- 7 files changed, 57 insertions(+), 92 deletions(-) diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 931ffb192fc4..1d7964c339f4 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -17,7 +17,7 @@ #include "framebuffer.h" #include "gem.h" #include "gma_display.h" -#include "psb_drv.h" +#include "psb_irq.h" #include "psb_intel_drv.h" #include "psb_intel_reg.h" @@ -572,9 +572,9 @@ const struct drm_crtc_funcs gma_crtc_funcs = { .set_config = gma_crtc_set_config, .destroy = gma_crtc_destroy, .page_flip = gma_crtc_page_flip, - .enable_vblank = psb_enable_vblank, - .disable_vblank = psb_disable_vblank, - .get_vblank_counter = psb_get_vblank_counter, + .enable_vblank = gma_enable_vblank, + .disable_vblank = gma_disable_vblank, + .get_vblank_counter = gma_get_vblank_counter, }; /* diff --git a/drivers/gpu/drm/gma500/opregion.c b/drivers/gpu/drm/gma500/opregion.c index fef04ff8c3a9..dc494df71a48 100644 --- a/drivers/gpu/drm/gma500/opregion.c +++ b/drivers/gpu/drm/gma500/opregion.c @@ -23,6 +23,7 @@ */ #include #include "psb_drv.h" +#include "psb_irq.h" #include "psb_intel_reg.h" #define PCI_ASLE 0xe4 @@ -217,8 +218,8 @@ void psb_intel_opregion_enable_asle(struct drm_device *dev) if (asle && system_opregion ) { /* Don't do this on Medfield or other non PC like devices, they use the bit for something different altogether */ - psb_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE); - psb_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE); + gma_enable_pipestat(dev_priv, 0, PIPE_LEGACY_BLC_EVENT_ENABLE); + gma_enable_pipestat(dev_priv, 1, PIPE_LEGACY_BLC_EVENT_ENABLE); asle->tche = ASLE_ALS_EN | ASLE_BLC_EN | ASLE_PFIT_EN | ASLE_PFMB_EN; diff --git a/drivers/gpu/drm/gma500/power.c b/drivers/gpu/drm/gma500/power.c index 6f917cfef65b..b91de6d36e41 100644 --- a/drivers/gpu/drm/gma500/power.c +++ b/drivers/gpu/drm/gma500/power.c @@ -201,7 +201,7 @@ int gma_power_suspend(struct device *_dev) dev_err(dev->dev, "GPU hardware busy, cannot suspend\n"); return -EBUSY; } - psb_irq_uninstall(dev); + gma_irq_uninstall(dev); gma_suspend_display(dev); gma_suspend_pci(pdev); } @@ -223,8 +223,8 @@ int gma_power_resume(struct device *_dev) mutex_lock(&power_mutex); gma_resume_pci(pdev); gma_resume_display(pdev); - psb_irq_preinstall(dev); - psb_irq_postinstall(dev); + gma_irq_preinstall(dev); + gma_irq_postinstall(dev); mutex_unlock(&power_mutex); return 0; } @@ -270,8 +270,8 @@ bool gma_power_begin(struct drm_device *dev, bool force_on) /* Ok power up needed */ ret = gma_resume_pci(pdev); if (ret == 0) { - psb_irq_preinstall(dev); - psb_irq_postinstall(dev); + gma_irq_preinstall(dev); + gma_irq_postinstall(dev); pm_runtime_get(dev->dev); dev_priv->display_count++; spin_unlock_irqrestore(&power_ctrl_lock, flags); diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index e30b58184156..82d51e9821ad 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -380,7 +380,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); - psb_irq_install(dev, pdev->irq); + gma_irq_install(dev, pdev->irq); dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h index aed167af13c5..0ddfec1a0851 100644 --- a/drivers/gpu/drm/gma500/psb_drv.h +++ b/drivers/gpu/drm/gma500/psb_drv.h @@ -609,17 +609,6 @@ struct psb_ops { int i2c_bus; /* I2C bus identifier for Moorestown */ }; -/* psb_irq.c */ -extern int psb_enable_vblank(struct drm_crtc *crtc); -extern void psb_disable_vblank(struct drm_crtc *crtc); -void -psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); - -void -psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); - -extern u32 psb_get_vblank_counter(struct drm_crtc *crtc); - /* psb_lid.c */ extern void psb_lid_timer_init(struct drm_psb_private *dev_priv); extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index ccf402007beb..2e8ded532930 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -21,8 +21,7 @@ * inline functions */ -static inline u32 -psb_pipestat(int pipe) +static inline u32 gma_pipestat(int pipe) { if (pipe == 0) return PIPEASTAT; @@ -33,8 +32,7 @@ psb_pipestat(int pipe) BUG(); } -static inline u32 -mid_pipe_event(int pipe) +static inline u32 gma_pipe_event(int pipe) { if (pipe == 0) return _PSB_PIPEA_EVENT_FLAG; @@ -45,20 +43,7 @@ mid_pipe_event(int pipe) BUG(); } -static inline u32 -mid_pipe_vsync(int pipe) -{ - if (pipe == 0) - return _PSB_VSYNC_PIPEA_FLAG; - if (pipe == 1) - return _PSB_VSYNC_PIPEB_FLAG; - if (pipe == 2) - return _MDFLD_PIPEC_VBLANK_FLAG; - BUG(); -} - -static inline u32 -mid_pipeconf(int pipe) +static inline u32 gma_pipeconf(int pipe) { if (pipe == 0) return PIPEACONF; @@ -69,11 +54,10 @@ mid_pipeconf(int pipe) BUG(); } -void -psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) +void gma_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) { if ((dev_priv->pipestat[pipe] & mask) != mask) { - u32 reg = psb_pipestat(pipe); + u32 reg = gma_pipestat(pipe); dev_priv->pipestat[pipe] |= mask; /* Enable the interrupt, clear any pending status */ if (gma_power_begin(&dev_priv->dev, false)) { @@ -86,11 +70,10 @@ psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) } } -void -psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) +void gma_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) { if ((dev_priv->pipestat[pipe] & mask) != 0) { - u32 reg = psb_pipestat(pipe); + u32 reg = gma_pipestat(pipe); dev_priv->pipestat[pipe] &= ~mask; if (gma_power_begin(&dev_priv->dev, false)) { u32 writeVal = PSB_RVDC32(reg); @@ -105,12 +88,12 @@ psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) /* * Display controller interrupt handler for pipe event. */ -static void mid_pipe_event_handler(struct drm_device *dev, int pipe) +static void gma_pipe_event_handler(struct drm_device *dev, int pipe) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); uint32_t pipe_stat_val = 0; - uint32_t pipe_stat_reg = psb_pipestat(pipe); + uint32_t pipe_stat_reg = gma_pipestat(pipe); uint32_t pipe_enable = dev_priv->pipestat[pipe]; uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16; uint32_t pipe_clear; @@ -160,22 +143,22 @@ static void mid_pipe_event_handler(struct drm_device *dev, int pipe) /* * Display controller interrupt handler. */ -static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) +static void gma_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) { if (vdc_stat & _PSB_IRQ_ASLE) psb_intel_opregion_asle_intr(dev); if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) - mid_pipe_event_handler(dev, 0); + gma_pipe_event_handler(dev, 0); if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG) - mid_pipe_event_handler(dev, 1); + gma_pipe_event_handler(dev, 1); } /* * SGX interrupt handler */ -static void psb_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2) +static void gma_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); u32 val, addr; @@ -222,7 +205,7 @@ static void psb_sgx_interrupt(struct drm_device *dev, u32 stat_1, u32 stat_2) PSB_RSGX32(PSB_CR_EVENT_HOST_CLEAR2); } -static irqreturn_t psb_irq_handler(int irq, void *arg) +static irqreturn_t gma_irq_handler(int irq, void *arg) { struct drm_device *dev = arg; struct drm_psb_private *dev_priv = to_drm_psb_private(dev); @@ -246,14 +229,14 @@ static irqreturn_t psb_irq_handler(int irq, void *arg) spin_unlock(&dev_priv->irqmask_lock); if (dsp_int && gma_power_is_on(dev)) { - psb_vdc_interrupt(dev, vdc_stat); + gma_vdc_interrupt(dev, vdc_stat); handled = 1; } if (sgx_int) { sgx_stat_1 = PSB_RSGX32(PSB_CR_EVENT_STATUS); sgx_stat_2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); - psb_sgx_interrupt(dev, sgx_stat_1, sgx_stat_2); + gma_sgx_interrupt(dev, sgx_stat_1, sgx_stat_2); handled = 1; } @@ -274,7 +257,7 @@ static irqreturn_t psb_irq_handler(int irq, void *arg) return IRQ_HANDLED; } -void psb_irq_preinstall(struct drm_device *dev) +void gma_irq_preinstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); unsigned long irqflags; @@ -303,7 +286,7 @@ void psb_irq_preinstall(struct drm_device *dev) spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); } -void psb_irq_postinstall(struct drm_device *dev) +void gma_irq_postinstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); unsigned long irqflags; @@ -322,9 +305,9 @@ void psb_irq_postinstall(struct drm_device *dev) for (i = 0; i < dev->num_crtcs; ++i) { if (dev->vblank[i].enabled) - psb_enable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE); + gma_enable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE); else - psb_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE); + gma_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE); } if (dev_priv->ops->hotplug_enable) @@ -333,26 +316,26 @@ void psb_irq_postinstall(struct drm_device *dev) spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); } -int psb_irq_install(struct drm_device *dev, unsigned int irq) +int gma_irq_install(struct drm_device *dev, unsigned int irq) { int ret; if (irq == IRQ_NOTCONNECTED) return -ENOTCONN; - psb_irq_preinstall(dev); + gma_irq_preinstall(dev); /* PCI devices require shared interrupts. */ - ret = request_irq(irq, psb_irq_handler, IRQF_SHARED, dev->driver->name, dev); + ret = request_irq(irq, gma_irq_handler, IRQF_SHARED, dev->driver->name, dev); if (ret) return ret; - psb_irq_postinstall(dev); + gma_irq_postinstall(dev); return 0; } -void psb_irq_uninstall(struct drm_device *dev) +void gma_irq_uninstall(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); @@ -368,7 +351,7 @@ void psb_irq_uninstall(struct drm_device *dev) for (i = 0; i < dev->num_crtcs; ++i) { if (dev->vblank[i].enabled) - psb_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE); + gma_disable_pipestat(dev_priv, i, PIPE_VBLANK_INTERRUPT_ENABLE); } dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | @@ -388,17 +371,14 @@ void psb_irq_uninstall(struct drm_device *dev) free_irq(pdev->irq, dev); } -/* - * It is used to enable VBLANK interrupt - */ -int psb_enable_vblank(struct drm_crtc *crtc) +int gma_enable_vblank(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; struct drm_psb_private *dev_priv = to_drm_psb_private(dev); unsigned long irqflags; uint32_t reg_val = 0; - uint32_t pipeconf_reg = mid_pipeconf(pipe); + uint32_t pipeconf_reg = gma_pipeconf(pipe); if (gma_power_begin(dev, false)) { reg_val = REG_READ(pipeconf_reg); @@ -417,17 +397,14 @@ int psb_enable_vblank(struct drm_crtc *crtc) PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); + gma_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); return 0; } -/* - * It is used to disable VBLANK interrupt - */ -void psb_disable_vblank(struct drm_crtc *crtc) +void gma_disable_vblank(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; @@ -443,7 +420,7 @@ void psb_disable_vblank(struct drm_crtc *crtc) PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); - psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); + gma_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); } @@ -451,7 +428,7 @@ void psb_disable_vblank(struct drm_crtc *crtc) /* Called from drm generic code, passed a 'crtc', which * we use as a pipe index */ -u32 psb_get_vblank_counter(struct drm_crtc *crtc) +u32 gma_get_vblank_counter(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; @@ -486,8 +463,8 @@ u32 psb_get_vblank_counter(struct drm_crtc *crtc) if (!(reg_val & PIPEACONF_ENABLE)) { dev_err(dev->dev, "trying to get vblank count for disabled pipe %u\n", - pipe); - goto psb_get_vblank_counter_exit; + pipe); + goto err_gma_power_end; } /* @@ -506,8 +483,7 @@ u32 psb_get_vblank_counter(struct drm_crtc *crtc) count = (high1 << 8) | low; -psb_get_vblank_counter_exit: - +err_gma_power_end: gma_power_end(dev); return count; diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h index a97cb49393d8..c22878914f5b 100644 --- a/drivers/gpu/drm/gma500/psb_irq.h +++ b/drivers/gpu/drm/gma500/psb_irq.h @@ -15,16 +15,15 @@ struct drm_crtc; struct drm_device; -bool sysirq_init(struct drm_device *dev); -void sysirq_uninit(struct drm_device *dev); +void gma_irq_preinstall(struct drm_device *dev); +void gma_irq_postinstall(struct drm_device *dev); +int gma_irq_install(struct drm_device *dev, unsigned int irq); +void gma_irq_uninstall(struct drm_device *dev); -void psb_irq_preinstall(struct drm_device *dev); -void psb_irq_postinstall(struct drm_device *dev); -int psb_irq_install(struct drm_device *dev, unsigned int irq); -void psb_irq_uninstall(struct drm_device *dev); - -int psb_enable_vblank(struct drm_crtc *crtc); -void psb_disable_vblank(struct drm_crtc *crtc); -u32 psb_get_vblank_counter(struct drm_crtc *crtc); +int gma_enable_vblank(struct drm_crtc *crtc); +void gma_disable_vblank(struct drm_crtc *crtc); +u32 gma_get_vblank_counter(struct drm_crtc *crtc); +void gma_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); +void gma_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); #endif /* _PSB_IRQ_H_ */ From 109d101e273d81ba079306308e9512a8b1673ca9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Fri, 11 Mar 2022 12:06:39 +0200 Subject: [PATCH 00242/11454] drm/i915: include uapi/drm/i915_drm.h directly where needed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the uapi/drm/i915_drm.h include from drm/i915_drm.h, and stop being a proxy for uapi/drm/i915_drm.h. Include uapi/drm/i915_drm.h and drm/i915_drm.h only where needed. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220311100639.114685-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_lmem.c | 2 ++ drivers/gpu/drm/i915/gem/i915_gem_region.c | 2 ++ drivers/gpu/drm/i915/intel_memory_region.c | 2 ++ drivers/gpu/drm/i915/intel_memory_region.h | 2 +- drivers/gpu/drm/i915/pxp/intel_pxp_session.c | 2 -- include/drm/i915_drm.h | 2 +- 6 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c index 444f8268b9c5..ede084f36ca9 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c @@ -3,6 +3,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include "intel_memory_region.h" #include "gem/i915_gem_region.h" #include "gem/i915_gem_lmem.h" diff --git a/drivers/gpu/drm/i915/gem/i915_gem_region.c b/drivers/gpu/drm/i915/gem/i915_gem_region.c index a4350227e9ae..60e63182bfa3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_region.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_region.c @@ -3,6 +3,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include "intel_memory_region.h" #include "i915_gem_region.h" #include "i915_drv.h" diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index c70d7e286a51..49ccafc224b7 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -5,6 +5,8 @@ #include +#include + #include "intel_memory_region.h" #include "i915_drv.h" #include "i915_ttm_buddy_manager.h" diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h index 5625c9c38993..385c32b0709d 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.h +++ b/drivers/gpu/drm/i915/intel_memory_region.h @@ -10,7 +10,7 @@ #include #include #include -#include +#include struct drm_i915_private; struct drm_i915_gem_object; diff --git a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c index 598840b73dfa..92b00b4de240 100644 --- a/drivers/gpu/drm/i915/pxp/intel_pxp_session.c +++ b/drivers/gpu/drm/i915/pxp/intel_pxp_session.c @@ -3,8 +3,6 @@ * Copyright(c) 2020, Intel Corporation. All rights reserved. */ -#include - #include "i915_drv.h" #include "intel_pxp.h" diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h index afbf3ef5643e..7adce327c1c2 100644 --- a/include/drm/i915_drm.h +++ b/include/drm/i915_drm.h @@ -26,7 +26,7 @@ #ifndef _I915_DRM_H_ #define _I915_DRM_H_ -#include +#include /* For use by IPS driver */ unsigned long i915_read_mch_val(void); From 61bfcb6a3b981e8f19e044ac8c3de6edbe6caf70 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Sun, 13 Mar 2022 20:29:51 +0100 Subject: [PATCH 00243/11454] fbdev: Fix sys_imageblit() for arbitrary image widths Commit 6f29e04938bf ("fbdev: Improve performance of sys_imageblit()") broke sys_imageblit() for image width that are not aligned to 8-bit boundaries. Fix this by handling the trailing pixels on each line separately. The performance improvements in the original commit do not regress by this change. Signed-off-by: Thomas Zimmermann Fixes: 6f29e04938bf ("fbdev: Improve performance of sys_imageblit()") Reviewed-by: Javier Martinez Canillas Acked-by: Daniel Vetter Tested-by: Geert Uytterhoeven Cc: Thomas Zimmermann Cc: Javier Martinez Canillas Cc: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220313192952.12058-2-tzimmermann@suse.de --- drivers/video/fbdev/core/sysimgblt.c | 29 ++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/core/sysimgblt.c b/drivers/video/fbdev/core/sysimgblt.c index 722c327a381b..335e92b813fc 100644 --- a/drivers/video/fbdev/core/sysimgblt.c +++ b/drivers/video/fbdev/core/sysimgblt.c @@ -188,7 +188,7 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, { u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; u32 ppw = 32/bpp, spitch = (image->width + 7)/8; - u32 bit_mask, eorx; + u32 bit_mask, eorx, shift; const char *s = image->data, *src; u32 *dst; const u32 *tab; @@ -229,17 +229,23 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, for (i = image->height; i--; ) { dst = dst1; + shift = 8; src = s; + /* + * Manually unroll the per-line copying loop for better + * performance. This works until we processed the last + * completely filled source byte (inclusive). + */ switch (ppw) { case 4: /* 8 bpp */ - for (j = k; j; j -= 2, ++src) { + for (j = k; j >= 2; j -= 2, ++src) { *dst++ = colortab[(*src >> 4) & bit_mask]; *dst++ = colortab[(*src >> 0) & bit_mask]; } break; case 2: /* 16 bpp */ - for (j = k; j; j -= 4, ++src) { + for (j = k; j >= 4; j -= 4, ++src) { *dst++ = colortab[(*src >> 6) & bit_mask]; *dst++ = colortab[(*src >> 4) & bit_mask]; *dst++ = colortab[(*src >> 2) & bit_mask]; @@ -247,7 +253,7 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, } break; case 1: /* 32 bpp */ - for (j = k; j; j -= 8, ++src) { + for (j = k; j >= 8; j -= 8, ++src) { *dst++ = colortab[(*src >> 7) & bit_mask]; *dst++ = colortab[(*src >> 6) & bit_mask]; *dst++ = colortab[(*src >> 5) & bit_mask]; @@ -259,6 +265,21 @@ static void fast_imageblit(const struct fb_image *image, struct fb_info *p, } break; } + + /* + * For image widths that are not a multiple of 8, there + * are trailing pixels left on the current line. Print + * them as well. + */ + for (; j--; ) { + shift -= ppw; + *dst++ = colortab[(*src >> shift) & bit_mask]; + if (!shift) { + shift = 8; + ++src; + } + } + dst1 += p->fix.line_length; s += spitch; } From 7438f52b578afbac3807396531361aac85d43a06 Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Sun, 13 Mar 2022 20:29:52 +0100 Subject: [PATCH 00244/11454] fbdev: Fix cfb_imageblit() for arbitrary image widths Commit 0d03011894d2 ("fbdev: Improve performance of cfb_imageblit()") broke cfb_imageblit() for image widths that are not aligned to 8-bit boundaries. Fix this by handling the trailing pixels on each line separately. The performance improvements in the original commit do not regress by this change. Signed-off-by: Thomas Zimmermann Fixes: 0d03011894d2 ("fbdev: Improve performance of cfb_imageblit()") Reviewed-by: Javier Martinez Canillas Acked-by: Daniel Vetter Tested-by: Marek Szyprowski Reported-by: Marek Szyprowski Cc: Thomas Zimmermann Cc: Javier Martinez Canillas Cc: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20220313192952.12058-3-tzimmermann@suse.de --- drivers/video/fbdev/core/cfbimgblt.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/drivers/video/fbdev/core/cfbimgblt.c b/drivers/video/fbdev/core/cfbimgblt.c index 7361cfabdd85..9ebda4e0dc7a 100644 --- a/drivers/video/fbdev/core/cfbimgblt.c +++ b/drivers/video/fbdev/core/cfbimgblt.c @@ -218,7 +218,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * { u32 fgx = fgcolor, bgx = bgcolor, bpp = p->var.bits_per_pixel; u32 ppw = 32/bpp, spitch = (image->width + 7)/8; - u32 bit_mask, eorx; + u32 bit_mask, eorx, shift; const char *s = image->data, *src; u32 __iomem *dst; const u32 *tab = NULL; @@ -259,17 +259,23 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * for (i = image->height; i--; ) { dst = (u32 __iomem *)dst1; + shift = 8; src = s; + /* + * Manually unroll the per-line copying loop for better + * performance. This works until we processed the last + * completely filled source byte (inclusive). + */ switch (ppw) { case 4: /* 8 bpp */ - for (j = k; j; j -= 2, ++src) { + for (j = k; j >= 2; j -= 2, ++src) { FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 0) & bit_mask], dst++); } break; case 2: /* 16 bpp */ - for (j = k; j; j -= 4, ++src) { + for (j = k; j >= 4; j -= 4, ++src) { FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 4) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 2) & bit_mask], dst++); @@ -277,7 +283,7 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * } break; case 1: /* 32 bpp */ - for (j = k; j; j -= 8, ++src) { + for (j = k; j >= 8; j -= 8, ++src) { FB_WRITEL(colortab[(*src >> 7) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 6) & bit_mask], dst++); FB_WRITEL(colortab[(*src >> 5) & bit_mask], dst++); @@ -290,6 +296,20 @@ static inline void fast_imageblit(const struct fb_image *image, struct fb_info * break; } + /* + * For image widths that are not a multiple of 8, there + * are trailing pixels left on the current line. Print + * them as well. + */ + for (; j--; ) { + shift -= ppw; + FB_WRITEL(colortab[(*src >> shift) & bit_mask], dst++); + if (!shift) { + shift = 8; + ++src; + } + } + dst1 += p->fix.line_length; s += spitch; } From daa83f744a31ca1c4f6cde7c4fcae0c89aa2dadc Mon Sep 17 00:00:00 2001 From: Christophe Branchereau Date: Fri, 11 Mar 2022 18:02:40 +0100 Subject: [PATCH 00245/11454] dt-bindings: display/panel: Add Leadtek ltk035c5444t Add binding for the leadtek ltk035c5444t, which is a 640x480 mipi-dbi over spi / 24-bit RGB panel based on the newvision NV03052C chipset. It is found in the Anbernic RG350M mips handheld. Signed-off-by: Christophe Branchereau Signed-off-by: Paul Cercueil Reviewed-by: Rob Herring Link: https://patchwork.freedesktop.org/patch/msgid/20220311170240.173846-5-cbranchereau@gmail.com --- .../display/panel/leadtek,ltk035c5444t.yaml | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/leadtek,ltk035c5444t.yaml diff --git a/Documentation/devicetree/bindings/display/panel/leadtek,ltk035c5444t.yaml b/Documentation/devicetree/bindings/display/panel/leadtek,ltk035c5444t.yaml new file mode 100644 index 000000000000..817a9bed7d5a --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/leadtek,ltk035c5444t.yaml @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/leadtek,ltk035c5444t.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Leadtek ltk035c5444t 3.5" (640x480 pixels) 24-bit IPS LCD panel + +maintainers: + - Paul Cercueil + - Christophe Branchereau + +allOf: + - $ref: panel-common.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + const: leadtek,ltk035c5444t + + backlight: true + port: true + power-supply: true + reg: true + reset-gpios: true + +required: + - compatible + - power-supply + - reset-gpios + +unevaluatedProperties: false + +examples: + - | + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + panel@0 { + compatible = "leadtek,ltk035c5444t"; + reg = <0>; + + spi-3wire; + spi-max-frequency = <3125000>; + + reset-gpios = <&gpe 2 GPIO_ACTIVE_LOW>; + + backlight = <&backlight>; + power-supply = <&vcc>; + + port { + panel_input: endpoint { + remote-endpoint = <&panel_output>; + }; + }; + }; + }; From 9f493fd71d4b132ed87e88b39cd46acf6b963062 Mon Sep 17 00:00:00 2001 From: Sankeerth Billakanti Date: Wed, 16 Mar 2022 23:05:49 +0530 Subject: [PATCH 00246/11454] drm/panel-edp: add LQ140M1JW46 edp panel entry Add panel identification entry for the sharp LQ140M1JW46 eDP panel with power sequencing delay information. Signed-off-by: Sankeerth Billakanti Reviewed-by: Stephen Boyd Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/1647452154-16361-5-git-send-email-quic_sbillaka@quicinc.com --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index f7bfcf63d48e..e15e62f235d8 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1859,6 +1859,7 @@ static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('K', 'D', 'B', 0x0624, &kingdisplay_kd116n21_30nv_a010.delay, "116N21-30NV-A010"), EDP_PANEL_ENTRY('K', 'D', 'B', 0x1120, &delay_200_500_e80_d50, "116N29-30NK-C007"), + EDP_PANEL_ENTRY('S', 'H', 'P', 0x1523, &sharp_lq140m1jw46.delay, "LQ140M1JW46"), EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"), EDP_PANEL_ENTRY('S', 'T', 'A', 0x0100, &delay_100_500_e200, "2081116HHD028001-51D"), From 8781f0515247f441623a01f6e036a1d7898170e2 Mon Sep 17 00:00:00 2001 From: John Harrison Date: Sun, 6 Mar 2022 15:21:56 -0800 Subject: [PATCH 00247/11454] drm/i915/guc: Add fetch of hwconfig blob Implement support for fetching the hardware description table from the GuC. The call is made twice - once without a destination buffer to query the size and then a second time to fill in the buffer. The table is stored in the GT structure so that it can be fetched once at driver load time. Keeping inside a GuC structure would mean it would be release and reloaded on a GuC reset (part of a full GT reset). However, the table does not change just because the GT has been reset and the GuC reloaded. Also, dynamic memory allocations inside the reset path are a problem. Note that the table is only available on ADL-P and later platforms. v2 (John's v2 patch): * Move to GT level to avoid memory allocation during reset path (and unnecessary re-read of the table on a reset). v5 (of Jordan's posting): * Various changes made by Jordan and recommended by Michal - Makefile ordering - Adjust "struct intel_guc_hwconfig hwconfig" comment - Set Copyright year to 2022 in intel_guc_hwconfig.c/.h - Drop inline from hwconfig_to_guc() - Replace hwconfig param with guc in __guc_action_get_hwconfig() - Move zero size check into guc_hwconfig_discover_size() - Change comment to say zero size offset/size is needed to get size - Add has_guc_hwconfig to devinfo and drop has_table() - Change drm_err to notice in __uc_init_hw() and use %pe v6 (of Jordan's posting): * Added a couple more small changes recommended by Michal * Merge in John's v2 patch, but note: - Using drm_notice as recommended by Michal - Reverted Michal's suggestion of using devinfo v7 (of Jordan's posting): * Change back to drm_err as preferred by John Cc: Michal Wajdeczko Signed-off-by: Rodrigo Vivi Signed-off-by: John Harrison Reviewed-by: Matthew Brost Acked-by: Jon Bloomfield Signed-off-by: Jordan Justen Reviewed-by: Michal Wajdeczko Signed-off-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20220306232157.1174335-2-jordan.l.justen@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gt/intel_gt.c | 6 + drivers/gpu/drm/i915/gt/intel_gt_types.h | 4 + drivers/gpu/drm/i915/gt/intel_hwconfig.h | 21 +++ .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 1 + .../gpu/drm/i915/gt/uc/abi/guc_errors_abi.h | 4 + .../gpu/drm/i915/gt/uc/intel_guc_hwconfig.c | 162 ++++++++++++++++++ 7 files changed, 199 insertions(+) create mode 100644 drivers/gpu/drm/i915/gt/intel_hwconfig.h create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 9d588d936e3d..61b078bd1b32 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -187,6 +187,7 @@ i915-y += gt/uc/intel_uc.o \ gt/uc/intel_guc_ct.o \ gt/uc/intel_guc_debugfs.o \ gt/uc/intel_guc_fw.o \ + gt/uc/intel_guc_hwconfig.o \ gt/uc/intel_guc_log.o \ gt/uc/intel_guc_log_debugfs.o \ gt/uc/intel_guc_rc.o \ diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 8ee532abdd7a..57ca1e6b6203 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -718,6 +718,11 @@ int intel_gt_init(struct intel_gt *gt) if (err) goto err_uc_init; + err = intel_gt_init_hwconfig(gt); + if (err) + drm_err(>->i915->drm, "Failed to retrieve hwconfig table: %pe\n", + ERR_PTR(err)); + err = __engines_record_defaults(gt); if (err) goto err_gt; @@ -799,6 +804,7 @@ void intel_gt_driver_release(struct intel_gt *gt) intel_gt_pm_fini(gt); intel_gt_fini_scratch(gt); intel_gt_fini_buffer_pool(gt); + intel_gt_fini_hwconfig(gt); } void intel_gt_driver_late_release(struct intel_gt *gt) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h index 7781ab84e7a3..bbba885d45bd 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_types.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h @@ -20,6 +20,7 @@ #include "i915_vma.h" #include "intel_engine_types.h" #include "intel_gt_buffer_pool_types.h" +#include "intel_hwconfig.h" #include "intel_llc_types.h" #include "intel_reset_types.h" #include "intel_rc6_types.h" @@ -204,6 +205,9 @@ struct intel_gt { struct sseu_dev_info sseu; unsigned long mslice_mask; + + /** @hwconfig: hardware configuration data */ + struct intel_hwconfig hwconfig; } info; struct { diff --git a/drivers/gpu/drm/i915/gt/intel_hwconfig.h b/drivers/gpu/drm/i915/gt/intel_hwconfig.h new file mode 100644 index 000000000000..322290780b67 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_hwconfig.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef _INTEL_HWCONFIG_H_ +#define _INTEL_HWCONFIG_H_ + +#include + +struct intel_gt; + +struct intel_hwconfig { + u32 size; + void *ptr; +}; + +int intel_gt_init_hwconfig(struct intel_gt *gt); +void intel_gt_fini_hwconfig(struct intel_gt *gt); + +#endif /* _INTEL_HWCONFIG_H_ */ diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h index e77f955435ce..f9b3dd146a7e 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h @@ -129,6 +129,7 @@ enum intel_guc_action { INTEL_GUC_ACTION_ENGINE_FAILURE_NOTIFICATION = 0x1009, INTEL_GUC_ACTION_SETUP_PC_GUCRC = 0x3004, INTEL_GUC_ACTION_AUTHENTICATE_HUC = 0x4000, + INTEL_GUC_ACTION_GET_HWCONFIG = 0x4100, INTEL_GUC_ACTION_REGISTER_CONTEXT = 0x4502, INTEL_GUC_ACTION_DEREGISTER_CONTEXT = 0x4503, INTEL_GUC_ACTION_DEREGISTER_CONTEXT_DONE = 0x4600, diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h index c20658ee85a5..8085fb181274 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_errors_abi.h @@ -8,6 +8,10 @@ enum intel_guc_response_status { INTEL_GUC_RESPONSE_STATUS_SUCCESS = 0x0, + INTEL_GUC_RESPONSE_NOT_SUPPORTED = 0x20, + INTEL_GUC_RESPONSE_NO_ATTRIBUTE_TABLE = 0x201, + INTEL_GUC_RESPONSE_NO_DECRYPTION_KEY = 0x202, + INTEL_GUC_RESPONSE_DECRYPTION_FAILED = 0x204, INTEL_GUC_RESPONSE_STATUS_GENERIC_FAIL = 0xF000, }; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c new file mode 100644 index 000000000000..e0f65bdd1c84 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_hwconfig.c @@ -0,0 +1,162 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + */ + +#include "gt/intel_gt.h" +#include "gt/intel_hwconfig.h" +#include "i915_drv.h" +#include "i915_memcpy.h" + +/* + * GuC has a blob containing hardware configuration information (HWConfig). + * This is formatted as a simple and flexible KLV (Key/Length/Value) table. + * + * For example, a minimal version could be: + * enum device_attr { + * ATTR_SOME_VALUE = 0, + * ATTR_SOME_MASK = 1, + * }; + * + * static const u32 hwconfig[] = { + * ATTR_SOME_VALUE, + * 1, // Value Length in DWords + * 8, // Value + * + * ATTR_SOME_MASK, + * 3, + * 0x00FFFFFFFF, 0xFFFFFFFF, 0xFF000000, + * }; + * + * The attribute ids are defined in a hardware spec. + */ + +static int __guc_action_get_hwconfig(struct intel_guc *guc, + u32 ggtt_offset, u32 ggtt_size) +{ + u32 action[] = { + INTEL_GUC_ACTION_GET_HWCONFIG, + lower_32_bits(ggtt_offset), + upper_32_bits(ggtt_offset), + ggtt_size, + }; + int ret; + + ret = intel_guc_send_mmio(guc, action, ARRAY_SIZE(action), NULL, 0); + if (ret == -ENXIO) + return -ENOENT; + + return ret; +} + +static int guc_hwconfig_discover_size(struct intel_guc *guc, struct intel_hwconfig *hwconfig) +{ + int ret; + + /* + * Sending a query with zero offset and size will return the + * size of the blob. + */ + ret = __guc_action_get_hwconfig(guc, 0, 0); + if (ret < 0) + return ret; + + if (ret == 0) + return -EINVAL; + + hwconfig->size = ret; + return 0; +} + +static int guc_hwconfig_fill_buffer(struct intel_guc *guc, struct intel_hwconfig *hwconfig) +{ + struct i915_vma *vma; + u32 ggtt_offset; + void *vaddr; + int ret; + + GEM_BUG_ON(!hwconfig->size); + + ret = intel_guc_allocate_and_map_vma(guc, hwconfig->size, &vma, &vaddr); + if (ret) + return ret; + + ggtt_offset = intel_guc_ggtt_offset(guc, vma); + + ret = __guc_action_get_hwconfig(guc, ggtt_offset, hwconfig->size); + if (ret >= 0) + memcpy(hwconfig->ptr, vaddr, hwconfig->size); + + i915_vma_unpin_and_release(&vma, I915_VMA_RELEASE_MAP); + + return ret; +} + +static bool has_table(struct drm_i915_private *i915) +{ + if (IS_ALDERLAKE_P(i915)) + return true; + + return false; +} + +/** + * intel_guc_hwconfig_init - Initialize the HWConfig + * + * Retrieve the HWConfig table from the GuC and save it locally. + * It can then be queried on demand by other users later on. + */ +static int guc_hwconfig_init(struct intel_gt *gt) +{ + struct intel_hwconfig *hwconfig = >->info.hwconfig; + struct intel_guc *guc = >->uc.guc; + int ret; + + if (!has_table(gt->i915)) + return 0; + + ret = guc_hwconfig_discover_size(guc, hwconfig); + if (ret) + return ret; + + hwconfig->ptr = kmalloc(hwconfig->size, GFP_KERNEL); + if (!hwconfig->ptr) { + hwconfig->size = 0; + return -ENOMEM; + } + + ret = guc_hwconfig_fill_buffer(guc, hwconfig); + if (ret < 0) { + intel_gt_fini_hwconfig(gt); + return ret; + } + + return 0; +} + +/** + * intel_gt_init_hwconfig - Initialize the HWConfig if available + * + * Retrieve the HWConfig table if available on the current platform. + */ +int intel_gt_init_hwconfig(struct intel_gt *gt) +{ + if (!intel_uc_uses_guc(>->uc)) + return 0; + + return guc_hwconfig_init(gt); +} + +/** + * intel_gt_fini_hwconfig - Finalize the HWConfig + * + * Free up the memory allocation holding the table. + */ +void intel_gt_fini_hwconfig(struct intel_gt *gt) +{ + struct intel_hwconfig *hwconfig = >->info.hwconfig; + + kfree(hwconfig->ptr); + hwconfig->size = 0; + hwconfig->ptr = NULL; +} From 78e1fb3112c0ac440bf9dce080a4aefbaa547d52 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Sun, 6 Mar 2022 15:21:57 -0800 Subject: [PATCH 00248/11454] drm/i915/uapi: Add query for hwconfig blob In this interface i915 is returning a blob of data which it receives from the guc software. This blob provides some useful data about the hardware for drivers. The format of this blob will be documented in the Programmer Reference Manuals when released. Cc: Tvrtko Ursulin Cc: Kenneth Graunke Cc: Michal Wajdeczko Cc: Slawomir Milczarek Cc: Joonas Lahtinen Signed-off-by: Rodrigo Vivi Signed-off-by: John Harrison Reviewed-by: Matthew Brost Acked-by: Jordan Justen Tested-by: Jordan Justen Acked-by: Jon Bloomfield Signed-off-by: John Harrison Link: https://patchwork.freedesktop.org/patch/msgid/20220306232157.1174335-3-jordan.l.justen@intel.com --- drivers/gpu/drm/i915/i915_query.c | 23 +++++++++++++++++++++++ include/uapi/drm/i915_drm.h | 1 + 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_query.c b/drivers/gpu/drm/i915/i915_query.c index 2dfbc22857a3..b5ca00cb6cf6 100644 --- a/drivers/gpu/drm/i915/i915_query.c +++ b/drivers/gpu/drm/i915/i915_query.c @@ -479,12 +479,35 @@ static int query_memregion_info(struct drm_i915_private *i915, return total_length; } +static int query_hwconfig_blob(struct drm_i915_private *i915, + struct drm_i915_query_item *query_item) +{ + struct intel_gt *gt = to_gt(i915); + struct intel_hwconfig *hwconfig = >->info.hwconfig; + + if (!hwconfig->size || !hwconfig->ptr) + return -ENODEV; + + if (query_item->length == 0) + return hwconfig->size; + + if (query_item->length < hwconfig->size) + return -EINVAL; + + if (copy_to_user(u64_to_user_ptr(query_item->data_ptr), + hwconfig->ptr, hwconfig->size)) + return -EFAULT; + + return hwconfig->size; +} + static int (* const i915_query_funcs[])(struct drm_i915_private *dev_priv, struct drm_i915_query_item *query_item) = { query_topology_info, query_engine_info, query_perf_config, query_memregion_info, + query_hwconfig_blob, }; int i915_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file) diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 05c3642aaece..071ffd9d51f1 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -2691,6 +2691,7 @@ struct drm_i915_query_item { #define DRM_I915_QUERY_ENGINE_INFO 2 #define DRM_I915_QUERY_PERF_CONFIG 3 #define DRM_I915_QUERY_MEMORY_REGIONS 4 +#define DRM_I915_QUERY_HWCONFIG_BLOB 5 /* Must be kept compact -- no holes and well documented */ /** From ba9177fcef21fa98406e73c472b5ac2eb4ec5f31 Mon Sep 17 00:00:00 2001 From: Carl Huang Date: Mon, 14 Mar 2022 07:18:15 +0200 Subject: [PATCH 00249/11454] ath11k: Add basic WoW functionalities Implement basic WoW functionalities such as magic-packet, disconnect and pattern. The logic is very similar to ath10k. When WoW is configured, ath11k_core_suspend and ath11k_core_resume are skipped as WoW configuration and hif suspend/resume are done in ath11k_wow_op_suspend() and ath11k_wow_op_resume(). Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Carl Huang Signed-off-by: Baochen Qiang Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1644308006-22784-2-git-send-email-quic_cjhuang@quicinc.com --- drivers/net/wireless/ath/ath11k/Makefile | 4 +- drivers/net/wireless/ath/ath11k/core.c | 33 ++ drivers/net/wireless/ath/ath11k/core.h | 4 + drivers/net/wireless/ath/ath11k/htc.c | 6 + drivers/net/wireless/ath/ath11k/mac.c | 59 +++- drivers/net/wireless/ath/ath11k/mac.h | 1 + drivers/net/wireless/ath/ath11k/wmi.c | 158 +++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 76 ++++- drivers/net/wireless/ath/ath11k/wow.c | 414 +++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wow.h | 45 +++ 10 files changed, 781 insertions(+), 19 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/Makefile b/drivers/net/wireless/ath/ath11k/Makefile index c1fce4159f1f..444c00c2bce2 100644 --- a/drivers/net/wireless/ath/ath11k/Makefile +++ b/drivers/net/wireless/ath/ath11k/Makefile @@ -16,14 +16,14 @@ ath11k-y += core.o \ ce.o \ peer.o \ dbring.o \ - hw.o \ - wow.o + hw.o ath11k-$(CONFIG_ATH11K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o ath11k-$(CONFIG_NL80211_TESTMODE) += testmode.o ath11k-$(CONFIG_ATH11K_TRACING) += trace.o ath11k-$(CONFIG_THERMAL) += thermal.o ath11k-$(CONFIG_ATH11K_SPECTRAL) += spectral.o +ath11k-$(CONFIG_PM) += wow.o obj-$(CONFIG_ATH11K_AHB) += ath11k_ahb.o ath11k_ahb-y += ahb.o diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 71eb7d04c3bf..104149050205 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -428,13 +428,30 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { }, }; +static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab) +{ + WARN_ON(!ab->hw_params.single_pdev_only); + + return &ab->pdevs[0]; +} + int ath11k_core_suspend(struct ath11k_base *ab) { int ret; + struct ath11k_pdev *pdev; + struct ath11k *ar; if (!ab->hw_params.supports_suspend) return -EOPNOTSUPP; + /* so far single_pdev_only chips have supports_suspend as true + * and only the first pdev is valid. + */ + pdev = ath11k_core_get_single_pdev(ab); + ar = pdev->ar; + if (!ar || ar->state != ATH11K_STATE_OFF) + return 0; + /* TODO: there can frames in queues so for now add delay as a hack. * Need to implement to handle and remove this delay. */ @@ -447,6 +464,12 @@ int ath11k_core_suspend(struct ath11k_base *ab) return ret; } + ret = ath11k_mac_wait_tx_complete(ar); + if (ret) { + ath11k_warn(ab, "failed to wait tx complete: %d\n", ret); + return ret; + } + ret = ath11k_wow_enable(ab); if (ret) { ath11k_warn(ab, "failed to enable wow during suspend: %d\n", ret); @@ -479,10 +502,20 @@ EXPORT_SYMBOL(ath11k_core_suspend); int ath11k_core_resume(struct ath11k_base *ab) { int ret; + struct ath11k_pdev *pdev; + struct ath11k *ar; if (!ab->hw_params.supports_suspend) return -EOPNOTSUPP; + /* so far signle_pdev_only chips have supports_suspend as true + * and only the first pdev is valid. + */ + pdev = ath11k_core_get_single_pdev(ab); + ar = pdev->ar; + if (!ar || ar->state != ATH11K_STATE_OFF) + return 0; + ret = ath11k_hif_resume(ab); if (ret) { ath11k_warn(ab, "failed to resume hif during resume: %d\n", ret); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index c0228e91a596..7b658d4c7d19 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -23,6 +23,7 @@ #include "thermal.h" #include "dbring.h" #include "spectral.h" +#include "wow.h" #define SM(_v, _f) (((_v) << _f##_LSB) & _f##_MASK) @@ -590,6 +591,9 @@ struct ath11k { struct work_struct wmi_mgmt_tx_work; struct sk_buff_head wmi_mgmt_tx_queue; + struct ath11k_wow wow; + struct completion target_suspend; + bool target_suspend_ack; struct ath11k_per_peer_tx_stats peer_tx_stats; struct list_head ppdu_stats_info; u32 ppdu_stat_list_depth; diff --git a/drivers/net/wireless/ath/ath11k/htc.c b/drivers/net/wireless/ath/ath11k/htc.c index 6913b7494b9b..069c29a4fac7 100644 --- a/drivers/net/wireless/ath/ath11k/htc.c +++ b/drivers/net/wireless/ath/ath11k/htc.c @@ -272,6 +272,11 @@ void ath11k_htc_tx_completion_handler(struct ath11k_base *ab, ep_tx_complete(htc->ab, skb); } +static void ath11k_htc_wakeup_from_suspend(struct ath11k_base *ab) +{ + ath11k_dbg(ab, ATH11K_DBG_BOOT, "boot wakeup from suspend is received\n"); +} + void ath11k_htc_rx_completion_handler(struct ath11k_base *ab, struct sk_buff *skb) { @@ -376,6 +381,7 @@ void ath11k_htc_rx_completion_handler(struct ath11k_base *ab, ath11k_htc_suspend_complete(ab, false); break; case ATH11K_HTC_MSG_WAKEUP_FROM_SUSPEND_ID: + ath11k_htc_wakeup_from_suspend(ab); break; default: ath11k_warn(ab, "ignoring unsolicited htc ep0 event %ld\n", diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index d5b83f90d27a..a58e56ca9a99 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -16,6 +16,8 @@ #include "testmode.h" #include "peer.h" #include "debugfs_sta.h" +#include "hif.h" +#include "wow.h" #define CHAN2G(_channel, _freq, _flags) { \ .band = NL80211_BAND_2GHZ, \ @@ -7258,31 +7260,47 @@ static int ath11k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) return -EOPNOTSUPP; } -static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, - u32 queues, bool drop) +static int ath11k_mac_flush_tx_complete(struct ath11k *ar) { - struct ath11k *ar = hw->priv; long time_left; - - if (drop) - return; + int ret = 0; time_left = wait_event_timeout(ar->dp.tx_empty_waitq, (atomic_read(&ar->dp.num_tx_pending) == 0), ATH11K_FLUSH_TIMEOUT); - if (time_left == 0) - ath11k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left); + if (time_left == 0) { + ath11k_warn(ar->ab, "failed to flush transmit queue, data pkts pending %d\n", + atomic_read(&ar->dp.num_tx_pending)); + ret = -ETIMEDOUT; + } time_left = wait_event_timeout(ar->txmgmt_empty_waitq, (atomic_read(&ar->num_pending_mgmt_tx) == 0), ATH11K_FLUSH_TIMEOUT); - if (time_left == 0) - ath11k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n", - time_left); + if (time_left == 0) { + ath11k_warn(ar->ab, "failed to flush mgmt transmit queue, mgmt pkts pending %d\n", + atomic_read(&ar->num_pending_mgmt_tx)); + ret = -ETIMEDOUT; + } - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac mgmt tx flush mgmt pending %d\n", - atomic_read(&ar->num_pending_mgmt_tx)); + return ret; +} + +int ath11k_mac_wait_tx_complete(struct ath11k *ar) +{ + ath11k_mac_drain_tx(ar); + return ath11k_mac_flush_tx_complete(ar); +} + +static void ath11k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + u32 queues, bool drop) +{ + struct ath11k *ar = hw->priv; + + if (drop) + return; + + ath11k_mac_flush_tx_complete(ar); } static int @@ -8104,6 +8122,13 @@ static const struct ieee80211_ops ath11k_ops = { .flush = ath11k_mac_op_flush, .sta_statistics = ath11k_mac_op_sta_statistics, CFG80211_TESTMODE_CMD(ath11k_tm_cmd) + +#ifdef CONFIG_PM + .suspend = ath11k_wow_op_suspend, + .resume = ath11k_wow_op_resume, + .set_wakeup = ath11k_wow_op_set_wakeup, +#endif + #ifdef CONFIG_ATH11K_DEBUGFS .sta_add_debugfs = ath11k_debugfs_sta_op_add, #endif @@ -8473,6 +8498,12 @@ static int __ath11k_mac_register(struct ath11k *ar) NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; } + ret = ath11k_wow_init(ar); + if (ret) { + ath11k_warn(ar->ab, "failed to init wow: %d\n", ret); + goto err_free_if_combs; + } + ar->hw->queues = ATH11K_HW_MAX_QUEUES; ar->hw->wiphy->tx_queue_len = ATH11K_QUEUE_LEN; ar->hw->offchannel_tx_hw_queue = ATH11K_HW_MAX_QUEUES - 1; diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index 0e6c870b09c8..045bf4fe1706 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -172,4 +172,5 @@ enum hal_encrypt_type ath11k_dp_tx_get_encrypt_type(u32 cipher); void ath11k_mac_handle_beacon(struct ath11k *ar, struct sk_buff *skb); void ath11k_mac_handle_beacon_miss(struct ath11k *ar, u32 vdev_id); void ath11k_mac_bcn_tx_event(struct ath11k_vif *arvif); +int ath11k_mac_wait_tx_complete(struct ath11k *ar); #endif diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index b4f86c45d81f..25222293f162 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -8235,3 +8235,161 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar, return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SCAN_PROB_REQ_OUI_CMDID); } + +int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id, + enum wmi_wow_wakeup_event event, + u32 enable) +{ + struct wmi_wow_add_del_event_cmd *cmd; + struct sk_buff *skb; + size_t len; + + len = sizeof(*cmd); + skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_wow_add_del_event_cmd *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_WOW_ADD_DEL_EVT_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + + cmd->vdev_id = vdev_id; + cmd->is_add = enable; + cmd->event_bitmap = (1 << event); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow add wakeup event %s enable %d vdev_id %d\n", + wow_wakeup_event(event), enable, vdev_id); + + return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ENABLE_DISABLE_WAKE_EVENT_CMDID); +} + +int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id, + const u8 *pattern, const u8 *mask, + int pattern_len, int pattern_offset) +{ + struct wmi_wow_add_pattern_cmd *cmd; + struct wmi_wow_bitmap_pattern *bitmap; + struct wmi_tlv *tlv; + struct sk_buff *skb; + u8 *ptr; + size_t len; + + len = sizeof(*cmd) + + sizeof(*tlv) + /* array struct */ + sizeof(*bitmap) + /* bitmap */ + sizeof(*tlv) + /* empty ipv4 sync */ + sizeof(*tlv) + /* empty ipv6 sync */ + sizeof(*tlv) + /* empty magic */ + sizeof(*tlv) + /* empty info timeout */ + sizeof(*tlv) + sizeof(u32); /* ratelimit interval */ + + skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + /* cmd */ + ptr = (u8 *)skb->data; + cmd = (struct wmi_wow_add_pattern_cmd *)ptr; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_WOW_ADD_PATTERN_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + + cmd->vdev_id = vdev_id; + cmd->pattern_id = pattern_id; + cmd->pattern_type = WOW_BITMAP_PATTERN; + + ptr += sizeof(*cmd); + + /* bitmap */ + tlv = (struct wmi_tlv *)ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_ARRAY_STRUCT) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*bitmap)); + + ptr += sizeof(*tlv); + + bitmap = (struct wmi_wow_bitmap_pattern *)ptr; + bitmap->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_WOW_BITMAP_PATTERN_T) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*bitmap) - TLV_HDR_SIZE); + + memcpy(bitmap->patternbuf, pattern, pattern_len); + ath11k_ce_byte_swap(bitmap->patternbuf, roundup(pattern_len, 4)); + memcpy(bitmap->bitmaskbuf, mask, pattern_len); + ath11k_ce_byte_swap(bitmap->bitmaskbuf, roundup(pattern_len, 4)); + bitmap->pattern_offset = pattern_offset; + bitmap->pattern_len = pattern_len; + bitmap->bitmask_len = pattern_len; + bitmap->pattern_id = pattern_id; + + ptr += sizeof(*bitmap); + + /* ipv4 sync */ + tlv = (struct wmi_tlv *)ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_ARRAY_STRUCT) | + FIELD_PREP(WMI_TLV_LEN, 0); + + ptr += sizeof(*tlv); + + /* ipv6 sync */ + tlv = (struct wmi_tlv *)ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_ARRAY_STRUCT) | + FIELD_PREP(WMI_TLV_LEN, 0); + + ptr += sizeof(*tlv); + + /* magic */ + tlv = (struct wmi_tlv *)ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_ARRAY_STRUCT) | + FIELD_PREP(WMI_TLV_LEN, 0); + + ptr += sizeof(*tlv); + + /* pattern info timeout */ + tlv = (struct wmi_tlv *)ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_ARRAY_UINT32) | + FIELD_PREP(WMI_TLV_LEN, 0); + + ptr += sizeof(*tlv); + + /* ratelimit interval */ + tlv = (struct wmi_tlv *)ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_ARRAY_UINT32) | + FIELD_PREP(WMI_TLV_LEN, sizeof(u32)); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow add pattern vdev_id %d pattern_id %d pattern_offset %d\n", + vdev_id, pattern_id, pattern_offset); + + return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_ADD_WAKE_PATTERN_CMDID); +} + +int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id) +{ + struct wmi_wow_del_pattern_cmd *cmd; + struct sk_buff *skb; + size_t len; + + len = sizeof(*cmd); + skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_wow_del_pattern_cmd *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_WOW_DEL_PATTERN_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + + cmd->vdev_id = vdev_id; + cmd->pattern_id = pattern_id; + cmd->pattern_type = WOW_BITMAP_PATTERN; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv wow del pattern vdev_id %d pattern_id %d\n", + vdev_id, pattern_id); + + return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID); +} diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 587f42307250..b82f432a3d95 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -5534,6 +5534,45 @@ static inline const char *wow_reason(enum wmi_wow_wake_reason reason) #undef C2S +struct wmi_wow_ev_arg { + u32 vdev_id; + u32 flag; + enum wmi_wow_wake_reason wake_reason; + u32 data_len; +}; + +enum wmi_tlv_pattern_type { + WOW_PATTERN_MIN = 0, + WOW_BITMAP_PATTERN = WOW_PATTERN_MIN, + WOW_IPV4_SYNC_PATTERN, + WOW_IPV6_SYNC_PATTERN, + WOW_WILD_CARD_PATTERN, + WOW_TIMER_PATTERN, + WOW_MAGIC_PATTERN, + WOW_IPV6_RA_PATTERN, + WOW_IOAC_PKT_PATTERN, + WOW_IOAC_TMR_PATTERN, + WOW_PATTERN_MAX +}; + +#define WOW_DEFAULT_BITMAP_PATTERN_SIZE 148 +#define WOW_DEFAULT_BITMASK_SIZE 148 + +#define WOW_MIN_PATTERN_SIZE 1 +#define WOW_MAX_PATTERN_SIZE 148 +#define WOW_MAX_PKT_OFFSET 128 +#define WOW_HDR_LEN (sizeof(struct ieee80211_hdr_3addr) + \ + sizeof(struct rfc1042_hdr)) +#define WOW_MAX_REDUCE (WOW_HDR_LEN - sizeof(struct ethhdr) - \ + offsetof(struct ieee80211_hdr_3addr, addr1)) + +struct wmi_wow_add_del_event_cmd { + u32 tlv_header; + u32 vdev_id; + u32 is_add; + u32 event_bitmap; +} __packed; + struct wmi_wow_enable_cmd { u32 tlv_header; u32 enable; @@ -5546,12 +5585,36 @@ struct wmi_wow_host_wakeup_ind { u32 reserved; } __packed; -struct wmi_wow_ev_arg { +struct wmi_tlv_wow_event_info { u32 vdev_id; u32 flag; - enum wmi_wow_wake_reason wake_reason; + u32 wake_reason; u32 data_len; -}; +} __packed; + +struct wmi_wow_bitmap_pattern { + u32 tlv_header; + u8 patternbuf[WOW_DEFAULT_BITMAP_PATTERN_SIZE]; + u8 bitmaskbuf[WOW_DEFAULT_BITMASK_SIZE]; + u32 pattern_offset; + u32 pattern_len; + u32 bitmask_len; + u32 pattern_id; +} __packed; + +struct wmi_wow_add_pattern_cmd { + u32 tlv_header; + u32 vdev_id; + u32 pattern_id; + u32 pattern_type; +} __packed; + +struct wmi_wow_del_pattern_cmd { + u32 tlv_header; + u32 vdev_id; + u32 pattern_id; + u32 pattern_type; +} __packed; int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, u32 cmd_id); @@ -5714,4 +5777,11 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar, const u8 mac_addr[ETH_ALEN]); int ath11k_wmi_fw_dbglog_cfg(struct ath11k *ar, u32 *module_id_bitmap, struct ath11k_fw_dbglog *dbglog); +int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id); +int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id, + const u8 *pattern, const u8 *mask, + int pattern_len, int pattern_offset); +int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id, + enum wmi_wow_wakeup_event event, + u32 enable); #endif diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c index 43c62e99dd0e..837dab469ab2 100644 --- a/drivers/net/wireless/ath/ath11k/wow.c +++ b/drivers/net/wireless/ath/ath11k/wow.c @@ -6,12 +6,22 @@ #include #include "mac.h" + +#include #include "core.h" #include "hif.h" #include "debug.h" #include "wmi.h" #include "wow.h" +static const struct wiphy_wowlan_support ath11k_wowlan_support = { + .flags = WIPHY_WOWLAN_DISCONNECT | + WIPHY_WOWLAN_MAGIC_PKT, + .pattern_min_len = WOW_MIN_PATTERN_SIZE, + .pattern_max_len = WOW_MAX_PATTERN_SIZE, + .max_pkt_offset = WOW_MAX_PKT_OFFSET, +}; + int ath11k_wow_enable(struct ath11k_base *ab) { struct ath11k *ar = ath11k_ab_to_ar(ab, 0); @@ -71,3 +81,407 @@ int ath11k_wow_wakeup(struct ath11k_base *ab) return 0; } + +static int ath11k_wow_vif_cleanup(struct ath11k_vif *arvif) +{ + struct ath11k *ar = arvif->ar; + int i, ret; + + for (i = 0; i < WOW_EVENT_MAX; i++) { + ret = ath11k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0); + if (ret) { + ath11k_warn(ar->ab, "failed to issue wow wakeup for event %s on vdev %i: %d\n", + wow_wakeup_event(i), arvif->vdev_id, ret); + return ret; + } + } + + for (i = 0; i < ar->wow.max_num_patterns; i++) { + ret = ath11k_wmi_wow_del_pattern(ar, arvif->vdev_id, i); + if (ret) { + ath11k_warn(ar->ab, "failed to delete wow pattern %d for vdev %i: %d\n", + i, arvif->vdev_id, ret); + return ret; + } + } + + return 0; +} + +static int ath11k_wow_cleanup(struct ath11k *ar) +{ + struct ath11k_vif *arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + ret = ath11k_wow_vif_cleanup(arvif); + if (ret) { + ath11k_warn(ar->ab, "failed to clean wow wakeups on vdev %i: %d\n", + arvif->vdev_id, ret); + return ret; + } + } + + return 0; +} + +/* Convert a 802.3 format to a 802.11 format. + * +------------+-----------+--------+----------------+ + * 802.3: |dest mac(6B)|src mac(6B)|type(2B)| body... | + * +------------+-----------+--------+----------------+ + * |__ |_______ |____________ |________ + * | | | | + * +--+------------+----+-----------+---------------+-----------+ + * 802.11: |4B|dest mac(6B)| 6B |src mac(6B)| 8B |type(2B)| body... | + * +--+------------+----+-----------+---------------+-----------+ + */ +static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new, + const struct cfg80211_pkt_pattern *old) +{ + u8 hdr_8023_pattern[ETH_HLEN] = {}; + u8 hdr_8023_bit_mask[ETH_HLEN] = {}; + u8 hdr_80211_pattern[WOW_HDR_LEN] = {}; + u8 hdr_80211_bit_mask[WOW_HDR_LEN] = {}; + + int total_len = old->pkt_offset + old->pattern_len; + int hdr_80211_end_offset; + + struct ieee80211_hdr_3addr *new_hdr_pattern = + (struct ieee80211_hdr_3addr *)hdr_80211_pattern; + struct ieee80211_hdr_3addr *new_hdr_mask = + (struct ieee80211_hdr_3addr *)hdr_80211_bit_mask; + struct ethhdr *old_hdr_pattern = (struct ethhdr *)hdr_8023_pattern; + struct ethhdr *old_hdr_mask = (struct ethhdr *)hdr_8023_bit_mask; + int hdr_len = sizeof(*new_hdr_pattern); + + struct rfc1042_hdr *new_rfc_pattern = + (struct rfc1042_hdr *)(hdr_80211_pattern + hdr_len); + struct rfc1042_hdr *new_rfc_mask = + (struct rfc1042_hdr *)(hdr_80211_bit_mask + hdr_len); + int rfc_len = sizeof(*new_rfc_pattern); + + memcpy(hdr_8023_pattern + old->pkt_offset, + old->pattern, ETH_HLEN - old->pkt_offset); + memcpy(hdr_8023_bit_mask + old->pkt_offset, + old->mask, ETH_HLEN - old->pkt_offset); + + /* Copy destination address */ + memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN); + memcpy(new_hdr_mask->addr1, old_hdr_mask->h_dest, ETH_ALEN); + + /* Copy source address */ + memcpy(new_hdr_pattern->addr3, old_hdr_pattern->h_source, ETH_ALEN); + memcpy(new_hdr_mask->addr3, old_hdr_mask->h_source, ETH_ALEN); + + /* Copy logic link type */ + memcpy(&new_rfc_pattern->snap_type, + &old_hdr_pattern->h_proto, + sizeof(old_hdr_pattern->h_proto)); + memcpy(&new_rfc_mask->snap_type, + &old_hdr_mask->h_proto, + sizeof(old_hdr_mask->h_proto)); + + /* Compute new pkt_offset */ + if (old->pkt_offset < ETH_ALEN) + new->pkt_offset = old->pkt_offset + + offsetof(struct ieee80211_hdr_3addr, addr1); + else if (old->pkt_offset < offsetof(struct ethhdr, h_proto)) + new->pkt_offset = old->pkt_offset + + offsetof(struct ieee80211_hdr_3addr, addr3) - + offsetof(struct ethhdr, h_source); + else + new->pkt_offset = old->pkt_offset + hdr_len + rfc_len - ETH_HLEN; + + /* Compute new hdr end offset */ + if (total_len > ETH_HLEN) + hdr_80211_end_offset = hdr_len + rfc_len; + else if (total_len > offsetof(struct ethhdr, h_proto)) + hdr_80211_end_offset = hdr_len + rfc_len + total_len - ETH_HLEN; + else if (total_len > ETH_ALEN) + hdr_80211_end_offset = total_len - ETH_ALEN + + offsetof(struct ieee80211_hdr_3addr, addr3); + else + hdr_80211_end_offset = total_len + + offsetof(struct ieee80211_hdr_3addr, addr1); + + new->pattern_len = hdr_80211_end_offset - new->pkt_offset; + + memcpy((u8 *)new->pattern, + hdr_80211_pattern + new->pkt_offset, + new->pattern_len); + memcpy((u8 *)new->mask, + hdr_80211_bit_mask + new->pkt_offset, + new->pattern_len); + + if (total_len > ETH_HLEN) { + /* Copy frame body */ + memcpy((u8 *)new->pattern + new->pattern_len, + (void *)old->pattern + ETH_HLEN - old->pkt_offset, + total_len - ETH_HLEN); + memcpy((u8 *)new->mask + new->pattern_len, + (void *)old->mask + ETH_HLEN - old->pkt_offset, + total_len - ETH_HLEN); + + new->pattern_len += total_len - ETH_HLEN; + } +} + +static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif, + struct cfg80211_wowlan *wowlan) +{ + int ret, i; + unsigned long wow_mask = 0; + struct ath11k *ar = arvif->ar; + const struct cfg80211_pkt_pattern *patterns = wowlan->patterns; + int pattern_id = 0; + + /* Setup requested WOW features */ + switch (arvif->vdev_type) { + case WMI_VDEV_TYPE_IBSS: + __set_bit(WOW_BEACON_EVENT, &wow_mask); + fallthrough; + case WMI_VDEV_TYPE_AP: + __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask); + __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask); + __set_bit(WOW_PROBE_REQ_WPS_IE_EVENT, &wow_mask); + __set_bit(WOW_AUTH_REQ_EVENT, &wow_mask); + __set_bit(WOW_ASSOC_REQ_EVENT, &wow_mask); + __set_bit(WOW_HTT_EVENT, &wow_mask); + __set_bit(WOW_RA_MATCH_EVENT, &wow_mask); + break; + case WMI_VDEV_TYPE_STA: + if (wowlan->disconnect) { + __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask); + __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask); + __set_bit(WOW_BMISS_EVENT, &wow_mask); + __set_bit(WOW_CSA_IE_EVENT, &wow_mask); + } + + if (wowlan->magic_pkt) + __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask); + break; + default: + break; + } + + for (i = 0; i < wowlan->n_patterns; i++) { + u8 bitmask[WOW_MAX_PATTERN_SIZE] = {}; + u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {}; + u8 ath_bitmask[WOW_MAX_PATTERN_SIZE] = {}; + struct cfg80211_pkt_pattern new_pattern = {}; + struct cfg80211_pkt_pattern old_pattern = patterns[i]; + int j; + + new_pattern.pattern = ath_pattern; + new_pattern.mask = ath_bitmask; + if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE) + continue; + /* convert bytemask to bitmask */ + for (j = 0; j < patterns[i].pattern_len; j++) + if (patterns[i].mask[j / 8] & BIT(j % 8)) + bitmask[j] = 0xff; + old_pattern.mask = bitmask; + + if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode == + ATH11K_HW_TXRX_NATIVE_WIFI) { + if (patterns[i].pkt_offset < ETH_HLEN) { + u8 pattern_ext[WOW_MAX_PATTERN_SIZE] = {}; + + memcpy(pattern_ext, old_pattern.pattern, + old_pattern.pattern_len); + old_pattern.pattern = pattern_ext; + ath11k_wow_convert_8023_to_80211(&new_pattern, + &old_pattern); + } else { + new_pattern = old_pattern; + new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN; + } + } + + if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE)) + return -EINVAL; + + ret = ath11k_wmi_wow_add_pattern(ar, arvif->vdev_id, + pattern_id, + new_pattern.pattern, + new_pattern.mask, + new_pattern.pattern_len, + new_pattern.pkt_offset); + if (ret) { + ath11k_warn(ar->ab, "failed to add pattern %i to vdev %i: %d\n", + pattern_id, + arvif->vdev_id, ret); + return ret; + } + + pattern_id++; + __set_bit(WOW_PATTERN_MATCH_EVENT, &wow_mask); + } + + for (i = 0; i < WOW_EVENT_MAX; i++) { + if (!test_bit(i, &wow_mask)) + continue; + ret = ath11k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1); + if (ret) { + ath11k_warn(ar->ab, "failed to enable wakeup event %s on vdev %i: %d\n", + wow_wakeup_event(i), arvif->vdev_id, ret); + return ret; + } + } + + return 0; +} + +static int ath11k_wow_set_wakeups(struct ath11k *ar, + struct cfg80211_wowlan *wowlan) +{ + struct ath11k_vif *arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + ret = ath11k_vif_wow_set_wakeups(arvif, wowlan); + if (ret) { + ath11k_warn(ar->ab, "failed to set wow wakeups on vdev %i: %d\n", + arvif->vdev_id, ret); + return ret; + } + } + + return 0; +} + +int ath11k_wow_op_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan) +{ + struct ath11k *ar = hw->priv; + int ret; + + mutex_lock(&ar->conf_mutex); + + ret = ath11k_wow_cleanup(ar); + if (ret) { + ath11k_warn(ar->ab, "failed to clear wow wakeup events: %d\n", + ret); + goto exit; + } + + ret = ath11k_wow_set_wakeups(ar, wowlan); + if (ret) { + ath11k_warn(ar->ab, "failed to set wow wakeup events: %d\n", + ret); + goto cleanup; + } + + ret = ath11k_mac_wait_tx_complete(ar); + if (ret) { + ath11k_warn(ar->ab, "failed to wait tx complete: %d\n", ret); + goto cleanup; + } + + ret = ath11k_wow_enable(ar->ab); + if (ret) { + ath11k_warn(ar->ab, "failed to start wow: %d\n", ret); + goto cleanup; + } + + ath11k_ce_stop_shadow_timers(ar->ab); + ath11k_dp_stop_shadow_timers(ar->ab); + + ath11k_hif_irq_disable(ar->ab); + ath11k_hif_ce_irq_disable(ar->ab); + + ret = ath11k_hif_suspend(ar->ab); + if (ret) { + ath11k_warn(ar->ab, "failed to suspend hif: %d\n", ret); + goto wakeup; + } + + goto exit; + +wakeup: + ath11k_wow_wakeup(ar->ab); + +cleanup: + ath11k_wow_cleanup(ar); + +exit: + mutex_unlock(&ar->conf_mutex); + return ret ? 1 : 0; +} + +void ath11k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled) +{ + struct ath11k *ar = hw->priv; + + mutex_lock(&ar->conf_mutex); + device_set_wakeup_enable(ar->ab->dev, enabled); + mutex_unlock(&ar->conf_mutex); +} + +int ath11k_wow_op_resume(struct ieee80211_hw *hw) +{ + struct ath11k *ar = hw->priv; + int ret; + + mutex_lock(&ar->conf_mutex); + + ret = ath11k_hif_resume(ar->ab); + if (ret) { + ath11k_warn(ar->ab, "failed to resume hif: %d\n", ret); + goto exit; + } + + ath11k_hif_ce_irq_enable(ar->ab); + ath11k_hif_irq_enable(ar->ab); + + ret = ath11k_wow_wakeup(ar->ab); + if (ret) + ath11k_warn(ar->ab, "failed to wakeup from wow: %d\n", ret); + +exit: + if (ret) { + switch (ar->state) { + case ATH11K_STATE_ON: + ar->state = ATH11K_STATE_RESTARTING; + ret = 1; + break; + case ATH11K_STATE_OFF: + case ATH11K_STATE_RESTARTING: + case ATH11K_STATE_RESTARTED: + case ATH11K_STATE_WEDGED: + ath11k_warn(ar->ab, "encountered unexpected device state %d on resume, cannot recover\n", + ar->state); + ret = -EIO; + break; + } + } + + mutex_unlock(&ar->conf_mutex); + return ret; +} + +int ath11k_wow_init(struct ath11k *ar) +{ + if (WARN_ON(!test_bit(WMI_TLV_SERVICE_WOW, ar->wmi->wmi_ab->svc_map))) + return -EINVAL; + + ar->wow.wowlan_support = ath11k_wowlan_support; + + if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode == + ATH11K_HW_TXRX_NATIVE_WIFI) { + ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE; + ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; + } + + ar->wow.max_num_patterns = ATH11K_WOW_PATTERNS; + ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; + ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; + + device_set_wakeup_capable(ar->ab->dev, true); + + return 0; +} diff --git a/drivers/net/wireless/ath/ath11k/wow.h b/drivers/net/wireless/ath/ath11k/wow.h index dabc4ee63cf6..553ba850d910 100644 --- a/drivers/net/wireless/ath/ath11k/wow.h +++ b/drivers/net/wireless/ath/ath11k/wow.h @@ -3,8 +3,53 @@ * Copyright (c) 2020 The Linux Foundation. All rights reserved. */ +#ifndef _WOW_H_ +#define _WOW_H_ + +struct ath11k_wow { + u32 max_num_patterns; + struct completion wakeup_completed; + struct wiphy_wowlan_support wowlan_support; +}; + +struct rfc1042_hdr { + u8 llc_dsap; + u8 llc_ssap; + u8 llc_ctrl; + u8 snap_oui[3]; + __be16 snap_type; +} __packed; + #define ATH11K_WOW_RETRY_NUM 3 #define ATH11K_WOW_RETRY_WAIT_MS 200 +#define ATH11K_WOW_PATTERNS 22 +#ifdef CONFIG_PM + +int ath11k_wow_init(struct ath11k *ar); +int ath11k_wow_op_suspend(struct ieee80211_hw *hw, + struct cfg80211_wowlan *wowlan); +int ath11k_wow_op_resume(struct ieee80211_hw *hw); +void ath11k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled); int ath11k_wow_enable(struct ath11k_base *ab); int ath11k_wow_wakeup(struct ath11k_base *ab); + +#else + +static inline int ath11k_wow_init(struct ath11k *ar) +{ + return 0; +} + +static inline int ath11k_wow_enable(struct ath11k_base *ab) +{ + return 0; +} + +static inline int ath11k_wow_wakeup(struct ath11k_base *ab) +{ + return 0; +} + +#endif /* CONFIG_PM */ +#endif /* _WOW_H_ */ From fec4b898f369a9b9d516f7bfc459eb4a8c5ceb2c Mon Sep 17 00:00:00 2001 From: Carl Huang Date: Mon, 14 Mar 2022 07:18:16 +0200 Subject: [PATCH 00250/11454] ath11k: Add WoW net-detect functionality Implement net-detect feature by setting flag WIPHY_WOWLAN_NET_DETECT if firmware supports this feature. Driver sets the related PNO configuration to firmware before entering WoW and firmware then scans periodically and wakes up host if a specific SSID is found. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Carl Huang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1644308006-22784-3-git-send-email-quic_cjhuang@quicinc.com --- drivers/net/wireless/ath/ath11k/core.h | 1 + drivers/net/wireless/ath/ath11k/mac.c | 12 ++ drivers/net/wireless/ath/ath11k/wmi.c | 154 ++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 169 ++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wow.c | 175 ++++++++++++++++++++++++- 5 files changed, 510 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 7b658d4c7d19..1f5e977aa976 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -617,6 +617,7 @@ struct ath11k { bool regdom_set_by_user; int hw_rate_code; u8 twt_enabled; + bool nlo_enabled; }; struct ath11k_band_cap { diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index a58e56ca9a99..7a6c758b8e45 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -8498,6 +8498,18 @@ static int __ath11k_mac_register(struct ath11k *ar) NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; } + if (test_bit(WMI_TLV_SERVICE_NLO, ar->wmi->wmi_ab->svc_map)) { + ar->hw->wiphy->max_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS; + ar->hw->wiphy->max_match_sets = WMI_PNO_MAX_SUPP_NETWORKS; + ar->hw->wiphy->max_sched_scan_ie_len = WMI_PNO_MAX_IE_LENGTH; + ar->hw->wiphy->max_sched_scan_plans = WMI_PNO_MAX_SCHED_SCAN_PLANS; + ar->hw->wiphy->max_sched_scan_plan_interval = + WMI_PNO_MAX_SCHED_SCAN_PLAN_INT; + ar->hw->wiphy->max_sched_scan_plan_iterations = + WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS; + ar->hw->wiphy->features |= NL80211_FEATURE_ND_RANDOM_MAC_ADDR; + } + ret = ath11k_wow_init(ar); if (ret) { ath11k_warn(ar->ab, "failed to init wow: %d\n", ret); diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 25222293f162..d4d34b932e0b 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -8393,3 +8393,157 @@ int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id) return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_WOW_DEL_WAKE_PATTERN_CMDID); } + +static struct sk_buff * +ath11k_wmi_op_gen_config_pno_start(struct ath11k *ar, + u32 vdev_id, + struct wmi_pno_scan_req *pno) +{ + struct nlo_configured_parameters *nlo_list; + struct wmi_wow_nlo_config_cmd *cmd; + struct wmi_tlv *tlv; + struct sk_buff *skb; + u32 *channel_list; + size_t len, nlo_list_len, channel_list_len; + u8 *ptr; + u32 i; + + len = sizeof(*cmd) + + sizeof(*tlv) + + /* TLV place holder for array of structures + * nlo_configured_parameters(nlo_list) + */ + sizeof(*tlv); + /* TLV place holder for array of uint32 channel_list */ + + channel_list_len = sizeof(u32) * pno->a_networks[0].channel_count; + len += channel_list_len; + + nlo_list_len = sizeof(*nlo_list) * pno->uc_networks_count; + len += nlo_list_len; + + skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); + if (!skb) + return ERR_PTR(-ENOMEM); + + ptr = (u8 *)skb->data; + cmd = (struct wmi_wow_nlo_config_cmd *)ptr; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_NLO_CONFIG_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + + cmd->vdev_id = pno->vdev_id; + cmd->flags = WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN; + + /* current FW does not support min-max range for dwell time */ + cmd->active_dwell_time = pno->active_max_time; + cmd->passive_dwell_time = pno->passive_max_time; + + if (pno->do_passive_scan) + cmd->flags |= WMI_NLO_CONFIG_SCAN_PASSIVE; + + cmd->fast_scan_period = pno->fast_scan_period; + cmd->slow_scan_period = pno->slow_scan_period; + cmd->fast_scan_max_cycles = pno->fast_scan_max_cycles; + cmd->delay_start_time = pno->delay_start_time; + + if (pno->enable_pno_scan_randomization) { + cmd->flags |= WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ | + WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ; + ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr); + ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask); + ath11k_ce_byte_swap(cmd->mac_addr.addr, 8); + ath11k_ce_byte_swap(cmd->mac_mask.addr, 8); + } + + ptr += sizeof(*cmd); + + /* nlo_configured_parameters(nlo_list) */ + cmd->no_of_ssids = pno->uc_networks_count; + tlv = (struct wmi_tlv *)ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_ARRAY_STRUCT) | + FIELD_PREP(WMI_TLV_LEN, nlo_list_len); + + ptr += sizeof(*tlv); + nlo_list = (struct nlo_configured_parameters *)ptr; + for (i = 0; i < cmd->no_of_ssids; i++) { + tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header); + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_BYTE) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*nlo_list) - sizeof(*tlv)); + + nlo_list[i].ssid.valid = true; + nlo_list[i].ssid.ssid.ssid_len = pno->a_networks[i].ssid.ssid_len; + memcpy(nlo_list[i].ssid.ssid.ssid, + pno->a_networks[i].ssid.ssid, + nlo_list[i].ssid.ssid.ssid_len); + ath11k_ce_byte_swap(nlo_list[i].ssid.ssid.ssid, + roundup(nlo_list[i].ssid.ssid.ssid_len, 4)); + + if (pno->a_networks[i].rssi_threshold && + pno->a_networks[i].rssi_threshold > -300) { + nlo_list[i].rssi_cond.valid = true; + nlo_list[i].rssi_cond.rssi = + pno->a_networks[i].rssi_threshold; + } + + nlo_list[i].bcast_nw_type.valid = true; + nlo_list[i].bcast_nw_type.bcast_nw_type = + pno->a_networks[i].bcast_nw_type; + } + + ptr += nlo_list_len; + cmd->num_of_channels = pno->a_networks[0].channel_count; + tlv = (struct wmi_tlv *)ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_UINT32) | + FIELD_PREP(WMI_TLV_LEN, channel_list_len); + ptr += sizeof(*tlv); + channel_list = (u32 *)ptr; + for (i = 0; i < cmd->num_of_channels; i++) + channel_list[i] = pno->a_networks[0].channels[i]; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n", + vdev_id); + + return skb; +} + +static struct sk_buff *ath11k_wmi_op_gen_config_pno_stop(struct ath11k *ar, + u32 vdev_id) +{ + struct wmi_wow_nlo_config_cmd *cmd; + struct sk_buff *skb; + size_t len; + + len = sizeof(*cmd); + skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); + if (!skb) + return ERR_PTR(-ENOMEM); + + cmd = (struct wmi_wow_nlo_config_cmd *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_NLO_CONFIG_CMD) | + FIELD_PREP(WMI_TLV_LEN, len - TLV_HDR_SIZE); + + cmd->vdev_id = vdev_id; + cmd->flags = WMI_NLO_CONFIG_STOP; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "wmi tlv stop pno config vdev_id %d\n", vdev_id); + return skb; +} + +int ath11k_wmi_wow_config_pno(struct ath11k *ar, u32 vdev_id, + struct wmi_pno_scan_req *pno_scan) +{ + struct sk_buff *skb; + + if (pno_scan->enable) + skb = ath11k_wmi_op_gen_config_pno_start(ar, vdev_id, pno_scan); + else + skb = ath11k_wmi_op_gen_config_pno_stop(ar, vdev_id); + + if (IS_ERR_OR_NULL(skb)) + return -ENOMEM; + + return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID); +} + diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index b82f432a3d95..9150e0555c6d 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -5616,6 +5616,173 @@ struct wmi_wow_del_pattern_cmd { u32 pattern_type; } __packed; +#define WMI_PNO_MAX_SCHED_SCAN_PLANS 2 +#define WMI_PNO_MAX_SCHED_SCAN_PLAN_INT 7200 +#define WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS 100 +#define WMI_PNO_MAX_NETW_CHANNELS 26 +#define WMI_PNO_MAX_NETW_CHANNELS_EX 60 +#define WMI_PNO_MAX_SUPP_NETWORKS WLAN_SCAN_PARAMS_MAX_SSID +#define WMI_PNO_MAX_IE_LENGTH WLAN_SCAN_PARAMS_MAX_IE_LEN + +/* size based of dot11 declaration without extra IEs as we will not carry those for PNO */ +#define WMI_PNO_MAX_PB_REQ_SIZE 450 + +#define WMI_PNO_24G_DEFAULT_CH 1 +#define WMI_PNO_5G_DEFAULT_CH 36 + +#define WMI_ACTIVE_MAX_CHANNEL_TIME 40 +#define WMI_PASSIVE_MAX_CHANNEL_TIME 110 + +/* SSID broadcast type */ +enum wmi_ssid_bcast_type { + BCAST_UNKNOWN = 0, + BCAST_NORMAL = 1, + BCAST_HIDDEN = 2, +}; + +#define WMI_NLO_MAX_SSIDS 16 +#define WMI_NLO_MAX_CHAN 48 + +#define WMI_NLO_CONFIG_STOP BIT(0) +#define WMI_NLO_CONFIG_START BIT(1) +#define WMI_NLO_CONFIG_RESET BIT(2) +#define WMI_NLO_CONFIG_SLOW_SCAN BIT(4) +#define WMI_NLO_CONFIG_FAST_SCAN BIT(5) +#define WMI_NLO_CONFIG_SSID_HIDE_EN BIT(6) + +/* This bit is used to indicate if EPNO or supplicant PNO is enabled. + * Only one of them can be enabled at a given time + */ +#define WMI_NLO_CONFIG_ENLO BIT(7) +#define WMI_NLO_CONFIG_SCAN_PASSIVE BIT(8) +#define WMI_NLO_CONFIG_ENLO_RESET BIT(9) +#define WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ BIT(10) +#define WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ BIT(11) +#define WMI_NLO_CONFIG_ENABLE_IE_WHITELIST_IN_PROBE_REQ BIT(12) +#define WMI_NLO_CONFIG_ENABLE_CNLO_RSSI_CONFIG BIT(13) + +struct wmi_nlo_ssid_param { + u32 valid; + struct wmi_ssid ssid; +} __packed; + +struct wmi_nlo_enc_param { + u32 valid; + u32 enc_type; +} __packed; + +struct wmi_nlo_auth_param { + u32 valid; + u32 auth_type; +} __packed; + +struct wmi_nlo_bcast_nw_param { + u32 valid; + u32 bcast_nw_type; +} __packed; + +struct wmi_nlo_rssi_param { + u32 valid; + s32 rssi; +} __packed; + +struct nlo_configured_parameters { + /* TLV tag and len;*/ + u32 tlv_header; + struct wmi_nlo_ssid_param ssid; + struct wmi_nlo_enc_param enc_type; + struct wmi_nlo_auth_param auth_type; + struct wmi_nlo_rssi_param rssi_cond; + + /* indicates if the SSID is hidden or not */ + struct wmi_nlo_bcast_nw_param bcast_nw_type; +} __packed; + +struct wmi_network_type { + struct wmi_ssid ssid; + u32 authentication; + u32 encryption; + u32 bcast_nw_type; + u8 channel_count; + u16 channels[WMI_PNO_MAX_NETW_CHANNELS_EX]; + s32 rssi_threshold; +}; + +struct wmi_pno_scan_req { + u8 enable; + u8 vdev_id; + u8 uc_networks_count; + struct wmi_network_type a_networks[WMI_PNO_MAX_SUPP_NETWORKS]; + u32 fast_scan_period; + u32 slow_scan_period; + u8 fast_scan_max_cycles; + + bool do_passive_scan; + + u32 delay_start_time; + u32 active_min_time; + u32 active_max_time; + u32 passive_min_time; + u32 passive_max_time; + + /* mac address randomization attributes */ + u32 enable_pno_scan_randomization; + u8 mac_addr[ETH_ALEN]; + u8 mac_addr_mask[ETH_ALEN]; +}; + +struct wmi_wow_nlo_config_cmd { + u32 tlv_header; + u32 flags; + u32 vdev_id; + u32 fast_scan_max_cycles; + u32 active_dwell_time; + u32 passive_dwell_time; + u32 probe_bundle_size; + + /* ART = IRT */ + u32 rest_time; + + /* Max value that can be reached after SBM */ + u32 max_rest_time; + + /* SBM */ + u32 scan_backoff_multiplier; + + /* SCBM */ + u32 fast_scan_period; + + /* specific to windows */ + u32 slow_scan_period; + + u32 no_of_ssids; + + u32 num_of_channels; + + /* NLO scan start delay time in milliseconds */ + u32 delay_start_time; + + /* MAC Address to use in Probe Req as SA */ + struct wmi_mac_addr mac_addr; + + /* Mask on which MAC has to be randomized */ + struct wmi_mac_addr mac_mask; + + /* IE bitmap to use in Probe Req */ + u32 ie_bitmap[8]; + + /* Number of vendor OUIs. In the TLV vendor_oui[] */ + u32 num_vendor_oui; + + /* Number of connected NLO band preferences */ + u32 num_cnlo_band_pref; + + /* The TLVs will follow. + * nlo_configured_parameters nlo_list[]; + * u32 channel_list[num_of_channels]; + */ +} __packed; + int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, u32 cmd_id); struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); @@ -5777,6 +5944,8 @@ int ath11k_wmi_scan_prob_req_oui(struct ath11k *ar, const u8 mac_addr[ETH_ALEN]); int ath11k_wmi_fw_dbglog_cfg(struct ath11k *ar, u32 *module_id_bitmap, struct ath11k_fw_dbglog *dbglog); +int ath11k_wmi_wow_config_pno(struct ath11k *ar, u32 vdev_id, + struct wmi_pno_scan_req *pno_scan); int ath11k_wmi_wow_del_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id); int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id, const u8 *pattern, const u8 *mask, diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c index 837dab469ab2..5f3aa0b7eb9b 100644 --- a/drivers/net/wireless/ath/ath11k/wow.c +++ b/drivers/net/wireless/ath/ath11k/wow.c @@ -228,6 +228,101 @@ static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new, } } +static int ath11k_wmi_pno_check_and_convert(struct ath11k *ar, u32 vdev_id, + struct cfg80211_sched_scan_request *nd_config, + struct wmi_pno_scan_req *pno) +{ + int i, j; + u8 ssid_len; + + pno->enable = 1; + pno->vdev_id = vdev_id; + pno->uc_networks_count = nd_config->n_match_sets; + + if (!pno->uc_networks_count || + pno->uc_networks_count > WMI_PNO_MAX_SUPP_NETWORKS) + return -EINVAL; + + if (nd_config->n_channels > WMI_PNO_MAX_NETW_CHANNELS_EX) + return -EINVAL; + + /* Filling per profile params */ + for (i = 0; i < pno->uc_networks_count; i++) { + ssid_len = nd_config->match_sets[i].ssid.ssid_len; + + if (ssid_len == 0 || ssid_len > 32) + return -EINVAL; + + pno->a_networks[i].ssid.ssid_len = ssid_len; + + memcpy(pno->a_networks[i].ssid.ssid, + nd_config->match_sets[i].ssid.ssid, + nd_config->match_sets[i].ssid.ssid_len); + pno->a_networks[i].authentication = 0; + pno->a_networks[i].encryption = 0; + pno->a_networks[i].bcast_nw_type = 0; + + /* Copying list of valid channel into request */ + pno->a_networks[i].channel_count = nd_config->n_channels; + pno->a_networks[i].rssi_threshold = nd_config->match_sets[i].rssi_thold; + + for (j = 0; j < nd_config->n_channels; j++) { + pno->a_networks[i].channels[j] = + nd_config->channels[j]->center_freq; + } + } + + /* set scan to passive if no SSIDs are specified in the request */ + if (nd_config->n_ssids == 0) + pno->do_passive_scan = true; + else + pno->do_passive_scan = false; + + for (i = 0; i < nd_config->n_ssids; i++) { + j = 0; + while (j < pno->uc_networks_count) { + if (pno->a_networks[j].ssid.ssid_len == + nd_config->ssids[i].ssid_len && + (memcmp(pno->a_networks[j].ssid.ssid, + nd_config->ssids[i].ssid, + pno->a_networks[j].ssid.ssid_len) == 0)) { + pno->a_networks[j].bcast_nw_type = BCAST_HIDDEN; + break; + } + j++; + } + } + + if (nd_config->n_scan_plans == 2) { + pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; + pno->fast_scan_max_cycles = nd_config->scan_plans[0].iterations; + pno->slow_scan_period = + nd_config->scan_plans[1].interval * MSEC_PER_SEC; + } else if (nd_config->n_scan_plans == 1) { + pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; + pno->fast_scan_max_cycles = 1; + pno->slow_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; + } else { + ath11k_warn(ar->ab, "Invalid number of scan plans %d !!", + nd_config->n_scan_plans); + } + + if (nd_config->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { + /* enable mac randomization */ + pno->enable_pno_scan_randomization = 1; + memcpy(pno->mac_addr, nd_config->mac_addr, ETH_ALEN); + memcpy(pno->mac_addr_mask, nd_config->mac_addr_mask, ETH_ALEN); + } + + pno->delay_start_time = nd_config->delay; + + /* Current FW does not support min-max range for dwell time */ + pno->active_max_time = WMI_ACTIVE_MAX_CHANNEL_TIME; + pno->passive_max_time = WMI_PASSIVE_MAX_CHANNEL_TIME; + + return 0; +} + static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif, struct cfg80211_wowlan *wowlan) { @@ -261,6 +356,26 @@ static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif, if (wowlan->magic_pkt) __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask); + + if (wowlan->nd_config) { + struct wmi_pno_scan_req *pno; + int ret; + + pno = kzalloc(sizeof(*pno), GFP_KERNEL); + if (!pno) + return -ENOMEM; + + ar->nlo_enabled = true; + + ret = ath11k_wmi_pno_check_and_convert(ar, arvif->vdev_id, + wowlan->nd_config, pno); + if (!ret) { + ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); + __set_bit(WOW_NLO_DETECTED_EVENT, &wow_mask); + } + + kfree(pno); + } break; default: break; @@ -354,6 +469,51 @@ static int ath11k_wow_set_wakeups(struct ath11k *ar, return 0; } +static int ath11k_vif_wow_clean_nlo(struct ath11k_vif *arvif) +{ + int ret = 0; + struct ath11k *ar = arvif->ar; + + switch (arvif->vdev_type) { + case WMI_VDEV_TYPE_STA: + if (ar->nlo_enabled) { + struct wmi_pno_scan_req *pno; + + pno = kzalloc(sizeof(*pno), GFP_KERNEL); + if (!pno) + return -ENOMEM; + + pno->enable = 0; + ar->nlo_enabled = false; + ret = ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); + kfree(pno); + } + break; + default: + break; + } + return ret; +} + +static int ath11k_wow_nlo_cleanup(struct ath11k *ar) +{ + struct ath11k_vif *arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + ret = ath11k_vif_wow_clean_nlo(arvif); + if (ret) { + ath11k_warn(ar->ab, "failed to clean nlo settings on vdev %i: %d\n", + arvif->vdev_id, ret); + return ret; + } + } + + return 0; +} + int ath11k_wow_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { @@ -439,8 +599,16 @@ int ath11k_wow_op_resume(struct ieee80211_hw *hw) ath11k_hif_irq_enable(ar->ab); ret = ath11k_wow_wakeup(ar->ab); - if (ret) + if (ret) { ath11k_warn(ar->ab, "failed to wakeup from wow: %d\n", ret); + goto exit; + } + + ret = ath11k_wow_nlo_cleanup(ar); + if (ret) { + ath11k_warn(ar->ab, "failed to cleanup nlo: %d\n", ret); + goto exit; + } exit: if (ret) { @@ -477,6 +645,11 @@ int ath11k_wow_init(struct ath11k *ar) ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; } + if (test_bit(WMI_TLV_SERVICE_NLO, ar->wmi->wmi_ab->svc_map)) { + ar->wow.wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT; + ar->wow.wowlan_support.max_nd_match_sets = WMI_PNO_MAX_SUPP_NETWORKS; + } + ar->wow.max_num_patterns = ATH11K_WOW_PATTERNS; ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; From c417b247ba042161ddfb34f26a42ec67edc5c378 Mon Sep 17 00:00:00 2001 From: Carl Huang Date: Mon, 14 Mar 2022 07:18:16 +0200 Subject: [PATCH 00251/11454] ath11k: implement hardware data filter Host needs to set hardware data filter before entering WoW to let firmware drop needless broadcast/mulitcast frames to avoid frequent wakeup. Host clears hardware data filter when leaving WoW. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Carl Huang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1644308006-22784-4-git-send-email-quic_cjhuang@quicinc.com --- drivers/net/wireless/ath/ath11k/wmi.c | 33 ++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 15 +++++++ drivers/net/wireless/ath/ath11k/wow.c | 57 +++++++++++++++++++++++++++ 3 files changed, 105 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index d4d34b932e0b..62b13f5cb8b4 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -8165,6 +8165,39 @@ void ath11k_wmi_detach(struct ath11k_base *ab) ath11k_wmi_free_dbring_caps(ab); } +int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id, + u32 filter_bitmap, bool enable) +{ + struct wmi_hw_data_filter_cmd *cmd; + struct sk_buff *skb; + int len; + + len = sizeof(*cmd); + skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); + + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_hw_data_filter_cmd *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_HW_DATA_FILTER_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + + cmd->vdev_id = vdev_id; + cmd->enable = enable; + + /* Set all modes in case of disable */ + if (cmd->enable) + cmd->hw_filter_bitmap = filter_bitmap; + else + cmd->hw_filter_bitmap = ((u32)~0U); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "wmi hw data filter enable %d filter_bitmap 0x%x\n", + enable, filter_bitmap); + + return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_HW_DATA_FILTER_CMDID); +} + int ath11k_wmi_wow_host_wakeup_ind(struct ath11k *ar) { struct wmi_wow_host_wakeup_ind *cmd; diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 9150e0555c6d..17e50987e115 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -5390,6 +5390,19 @@ struct ath11k_wmi_base { struct ath11k_targ_cap *targ_cap; }; +/* Definition of HW data filtering */ +enum hw_data_filter_type { + WMI_HW_DATA_FILTER_DROP_NON_ARP_BC = BIT(0), + WMI_HW_DATA_FILTER_DROP_NON_ICMPV6_MC = BIT(1), +}; + +struct wmi_hw_data_filter_cmd { + u32 tlv_header; + u32 vdev_id; + u32 enable; + u32 hw_filter_bitmap; +} __packed; + /* WOW structures */ enum wmi_wow_wakeup_event { WOW_BMISS_EVENT = 0, @@ -5953,4 +5966,6 @@ int ath11k_wmi_wow_add_pattern(struct ath11k *ar, u32 vdev_id, u32 pattern_id, int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id, enum wmi_wow_wakeup_event event, u32 enable); +int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id, + u32 filter_bitmap, bool enable); #endif diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c index 5f3aa0b7eb9b..50dd50944edd 100644 --- a/drivers/net/wireless/ath/ath11k/wow.c +++ b/drivers/net/wireless/ath/ath11k/wow.c @@ -514,6 +514,50 @@ static int ath11k_wow_nlo_cleanup(struct ath11k *ar) return 0; } +static int ath11k_wow_set_hw_filter(struct ath11k *ar) +{ + struct ath11k_vif *arvif; + u32 bitmap; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + bitmap = WMI_HW_DATA_FILTER_DROP_NON_ICMPV6_MC | + WMI_HW_DATA_FILTER_DROP_NON_ARP_BC; + ret = ath11k_wmi_hw_data_filter_cmd(ar, arvif->vdev_id, + bitmap, + true); + if (ret) { + ath11k_warn(ar->ab, "failed to set hw data filter on vdev %i: %d\n", + arvif->vdev_id, ret); + return ret; + } + } + + return 0; +} + +static int ath11k_wow_clear_hw_filter(struct ath11k *ar) +{ + struct ath11k_vif *arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + ret = ath11k_wmi_hw_data_filter_cmd(ar, arvif->vdev_id, 0, false); + + if (ret) { + ath11k_warn(ar->ab, "failed to clear hw data filter on vdev %i: %d\n", + arvif->vdev_id, ret); + return ret; + } + } + + return 0; +} + int ath11k_wow_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { @@ -542,6 +586,13 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw, goto cleanup; } + ret = ath11k_wow_set_hw_filter(ar); + if (ret) { + ath11k_warn(ar->ab, "failed to set hw filter: %d\n", + ret); + goto cleanup; + } + ret = ath11k_wow_enable(ar->ab); if (ret) { ath11k_warn(ar->ab, "failed to start wow: %d\n", ret); @@ -610,6 +661,12 @@ int ath11k_wow_op_resume(struct ieee80211_hw *hw) goto exit; } + ret = ath11k_wow_clear_hw_filter(ar); + if (ret) { + ath11k_warn(ar->ab, "failed to clear hw filter: %d\n", ret); + goto exit; + } + exit: if (ret) { switch (ar->state) { From 90bf5c8d0f7ecddf96fc1cd9434af4e157b51970 Mon Sep 17 00:00:00 2001 From: Carl Huang Date: Mon, 14 Mar 2022 07:18:16 +0200 Subject: [PATCH 00252/11454] ath11k: purge rx pktlog when entering WoW This change is to purge rx pktlog when entering WoW and reap the mon_status buffer to keep it empty. When leaving WoW, host restarts the reap timer. In WoW state, it's not allowed to feed into mon_status rings per firmware team's recommendation. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Carl Huang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1644308006-22784-5-git-send-email-quic_cjhuang@quicinc.com --- drivers/net/wireless/ath/ath11k/wow.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c index 50dd50944edd..602b8f4c5985 100644 --- a/drivers/net/wireless/ath/ath11k/wow.c +++ b/drivers/net/wireless/ath/ath11k/wow.c @@ -13,6 +13,7 @@ #include "debug.h" #include "wmi.h" #include "wow.h" +#include "dp_rx.h" static const struct wiphy_wowlan_support ath11k_wowlan_support = { .flags = WIPHY_WOWLAN_DISCONNECT | @@ -566,6 +567,14 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); + ret = ath11k_dp_rx_pktlog_stop(ar->ab, true); + if (ret) { + ath11k_warn(ar->ab, + "failed to stop dp rx (and timer) pktlog during wow suspend: %d\n", + ret); + goto exit; + } + ret = ath11k_wow_cleanup(ar); if (ret) { ath11k_warn(ar->ab, "failed to clear wow wakeup events: %d\n", @@ -599,6 +608,14 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw, goto cleanup; } + ret = ath11k_dp_rx_pktlog_stop(ar->ab, false); + if (ret) { + ath11k_warn(ar->ab, + "failed to stop dp rx pktlog during wow suspend: %d\n", + ret); + goto cleanup; + } + ath11k_ce_stop_shadow_timers(ar->ab); ath11k_dp_stop_shadow_timers(ar->ab); @@ -649,6 +666,12 @@ int ath11k_wow_op_resume(struct ieee80211_hw *hw) ath11k_hif_ce_irq_enable(ar->ab); ath11k_hif_irq_enable(ar->ab); + ret = ath11k_dp_rx_pktlog_start(ar->ab); + if (ret) { + ath11k_warn(ar->ab, "failed to start rx pktlog from wow: %d\n", ret); + return ret; + } + ret = ath11k_wow_wakeup(ar->ab); if (ret) { ath11k_warn(ar->ab, "failed to wakeup from wow: %d\n", ret); From c3c36bfe998b3ad14aa87a57037a05d861889ac8 Mon Sep 17 00:00:00 2001 From: Carl Huang Date: Mon, 14 Mar 2022 07:18:16 +0200 Subject: [PATCH 00253/11454] ath11k: support ARP and NS offload Support ARP and NS offload in WoW state. Tested this way: put machine A with QCA6390 to WoW state, ping/ping6 machine A from another machine B, check sniffer to see any ARP response and Neighbour advertisement from machine A. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Carl Huang Signed-off-by: Baochen Qiang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1644308006-22784-6-git-send-email-quic_cjhuang@quicinc.com --- drivers/net/wireless/ath/ath11k/core.h | 19 +++ drivers/net/wireless/ath/ath11k/mac.c | 118 +++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.c | 155 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 47 ++++++++ drivers/net/wireless/ath/ath11k/wow.c | 52 +++++++++ 5 files changed, 391 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 1f5e977aa976..4ba12de44415 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -213,6 +213,23 @@ enum ath11k_monitor_flags { ATH11K_FLAG_MONITOR_VDEV_CREATED, }; +#define ATH11K_IPV6_UC_TYPE 0 +#define ATH11K_IPV6_AC_TYPE 1 + +#define ATH11K_IPV6_MAX_COUNT 16 +#define ATH11K_IPV4_MAX_COUNT 2 + +struct ath11k_arp_ns_offload { + u8 ipv4_addr[ATH11K_IPV4_MAX_COUNT][4]; + u32 ipv4_count; + u32 ipv6_count; + u8 ipv6_addr[ATH11K_IPV6_MAX_COUNT][16]; + u8 self_ipv6_addr[ATH11K_IPV6_MAX_COUNT][16]; + u8 ipv6_type[ATH11K_IPV6_MAX_COUNT]; + bool ipv6_valid[ATH11K_IPV6_MAX_COUNT]; + u8 mac_addr[ETH_ALEN]; +}; + struct ath11k_vif { u32 vdev_id; enum wmi_vdev_type vdev_type; @@ -264,6 +281,8 @@ struct ath11k_vif { bool bcca_zero_sent; bool do_not_send_tmpl; struct ieee80211_chanctx_conf chanctx; + struct ath11k_arp_ns_offload arp_ns_offload; + #ifdef CONFIG_ATH11K_DEBUGFS struct dentry *debugfs_twt; #endif /* CONFIG_ATH11K_DEBUGFS */ diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 7a6c758b8e45..dee1cb4121f8 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -6,6 +6,11 @@ #include #include +#include +#include +#include +#include + #include "mac.h" #include "core.h" #include "debug.h" @@ -3095,6 +3100,7 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, int ret = 0; u8 rateidx; u32 rate; + u32 ipv4_cnt; mutex_lock(&ar->conf_mutex); @@ -3387,6 +3393,18 @@ static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw, changed & BSS_CHANGED_UNSOL_BCAST_PROBE_RESP) ath11k_mac_fils_discovery(arvif, info); + if (changed & BSS_CHANGED_ARP_FILTER) { + ipv4_cnt = min(info->arp_addr_cnt, ATH11K_IPV4_MAX_COUNT); + memcpy(arvif->arp_ns_offload.ipv4_addr, info->arp_addr_list, + ipv4_cnt * sizeof(u32)); + memcpy(arvif->arp_ns_offload.mac_addr, vif->addr, ETH_ALEN); + arvif->arp_ns_offload.ipv4_count = ipv4_cnt; + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac arp_addr_cnt %d vif->addr %pM, offload_addr %pI4\n", + info->arp_addr_cnt, + vif->addr, arvif->arp_ns_offload.ipv4_addr); + } + mutex_unlock(&ar->conf_mutex); } @@ -8087,6 +8105,101 @@ static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw, } } +static void ath11k_generate_ns_mc_addr(struct ath11k *ar, + struct ath11k_arp_ns_offload *offload) +{ + int i; + + for (i = 0; i < offload->ipv6_count; i++) { + offload->self_ipv6_addr[i][0] = 0xff; + offload->self_ipv6_addr[i][1] = 0x02; + offload->self_ipv6_addr[i][11] = 0x01; + offload->self_ipv6_addr[i][12] = 0xff; + offload->self_ipv6_addr[i][13] = + offload->ipv6_addr[i][13]; + offload->self_ipv6_addr[i][14] = + offload->ipv6_addr[i][14]; + offload->self_ipv6_addr[i][15] = + offload->ipv6_addr[i][15]; + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "NS solicited addr %pI6\n", + offload->self_ipv6_addr[i]); + } +} + +static void ath11k_mac_op_ipv6_changed(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct inet6_dev *idev) +{ + struct ath11k *ar = hw->priv; + struct ath11k_arp_ns_offload *offload; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct inet6_ifaddr *ifa6; + struct ifacaddr6 *ifaca6; + struct list_head *p; + u32 count, scope; + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac op ipv6 changed\n"); + + offload = &arvif->arp_ns_offload; + count = 0; + + read_lock_bh(&idev->lock); + + memset(offload->ipv6_addr, 0, sizeof(offload->ipv6_addr)); + memset(offload->self_ipv6_addr, 0, sizeof(offload->self_ipv6_addr)); + memcpy(offload->mac_addr, vif->addr, ETH_ALEN); + + /* get unicast address */ + list_for_each(p, &idev->addr_list) { + if (count >= ATH11K_IPV6_MAX_COUNT) + goto generate; + + ifa6 = list_entry(p, struct inet6_ifaddr, if_list); + if (ifa6->flags & IFA_F_DADFAILED) + continue; + scope = ipv6_addr_src_scope(&ifa6->addr); + if (scope == IPV6_ADDR_SCOPE_LINKLOCAL || + scope == IPV6_ADDR_SCOPE_GLOBAL) { + memcpy(offload->ipv6_addr[count], &ifa6->addr.s6_addr, + sizeof(ifa6->addr.s6_addr)); + offload->ipv6_type[count] = ATH11K_IPV6_UC_TYPE; + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac count %d ipv6 uc %pI6 scope %d\n", + count, offload->ipv6_addr[count], + scope); + count++; + } else { + ath11k_warn(ar->ab, "Unsupported ipv6 scope: %d\n", scope); + } + } + + /* get anycast address */ + for (ifaca6 = idev->ac_list; ifaca6; ifaca6 = ifaca6->aca_next) { + if (count >= ATH11K_IPV6_MAX_COUNT) + goto generate; + + scope = ipv6_addr_src_scope(&ifaca6->aca_addr); + if (scope == IPV6_ADDR_SCOPE_LINKLOCAL || + scope == IPV6_ADDR_SCOPE_GLOBAL) { + memcpy(offload->ipv6_addr[count], &ifaca6->aca_addr, + sizeof(ifaca6->aca_addr)); + offload->ipv6_type[count] = ATH11K_IPV6_AC_TYPE; + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac count %d ipv6 ac %pI6 scope %d\n", + count, offload->ipv6_addr[count], + scope); + count++; + } else { + ath11k_warn(ar->ab, "Unsupported ipv scope: %d\n", scope); + } + } + +generate: + offload->ipv6_count = count; + read_unlock_bh(&idev->lock); + + /* generate ns multicast address */ + ath11k_generate_ns_mc_addr(ar, offload); +} + static const struct ieee80211_ops ath11k_ops = { .tx = ath11k_mac_op_tx, .start = ath11k_mac_op_start, @@ -8132,6 +8245,11 @@ static const struct ieee80211_ops ath11k_ops = { #ifdef CONFIG_ATH11K_DEBUGFS .sta_add_debugfs = ath11k_debugfs_sta_op_add, #endif + +#if IS_ENABLED(CONFIG_IPV6) + .ipv6_addr_change = ath11k_mac_op_ipv6_changed, +#endif + }; static void ath11k_mac_update_ch_list(struct ath11k *ar, diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 62b13f5cb8b4..828f9cacbe57 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -8580,3 +8580,158 @@ int ath11k_wmi_wow_config_pno(struct ath11k *ar, u32 vdev_id, return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID); } +static void ath11k_wmi_fill_ns_offload(struct ath11k *ar, + struct ath11k_arp_ns_offload *offload, + u8 **ptr, + bool enable, + bool ext) +{ + struct wmi_ns_offload_tuple *ns; + struct wmi_tlv *tlv; + u8 *buf_ptr = *ptr; + u32 ns_cnt, ns_ext_tuples; + int i, max_offloads; + + ns_cnt = offload->ipv6_count; + + tlv = (struct wmi_tlv *)buf_ptr; + + if (ext) { + ns_ext_tuples = offload->ipv6_count - WMI_MAX_NS_OFFLOADS; + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | + FIELD_PREP(WMI_TLV_LEN, ns_ext_tuples * sizeof(*ns)); + i = WMI_MAX_NS_OFFLOADS; + max_offloads = offload->ipv6_count; + } else { + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | + FIELD_PREP(WMI_TLV_LEN, WMI_MAX_NS_OFFLOADS * sizeof(*ns)); + i = 0; + max_offloads = WMI_MAX_NS_OFFLOADS; + } + + buf_ptr += sizeof(*tlv); + + for (; i < max_offloads; i++) { + ns = (struct wmi_ns_offload_tuple *)buf_ptr; + ns->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_NS_OFFLOAD_TUPLE) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*ns) - TLV_HDR_SIZE); + + if (enable) { + if (i < ns_cnt) + ns->flags |= WMI_NSOL_FLAGS_VALID; + + memcpy(ns->target_ipaddr[0], offload->ipv6_addr[i], 16); + memcpy(ns->solicitation_ipaddr, offload->self_ipv6_addr[i], 16); + ath11k_ce_byte_swap(ns->target_ipaddr[0], 16); + ath11k_ce_byte_swap(ns->solicitation_ipaddr, 16); + + if (offload->ipv6_type[i]) + ns->flags |= WMI_NSOL_FLAGS_IS_IPV6_ANYCAST; + + memcpy(ns->target_mac.addr, offload->mac_addr, ETH_ALEN); + ath11k_ce_byte_swap(ns->target_mac.addr, 8); + + if (ns->target_mac.word0 != 0 || + ns->target_mac.word1 != 0) { + ns->flags |= WMI_NSOL_FLAGS_MAC_VALID; + } + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, + "wmi index %d ns_solicited %pI6 target %pI6", + i, ns->solicitation_ipaddr, + ns->target_ipaddr[0]); + } + + buf_ptr += sizeof(*ns); + } + + *ptr = buf_ptr; +} + +static void ath11k_wmi_fill_arp_offload(struct ath11k *ar, + struct ath11k_arp_ns_offload *offload, + u8 **ptr, + bool enable) +{ + struct wmi_arp_offload_tuple *arp; + struct wmi_tlv *tlv; + u8 *buf_ptr = *ptr; + int i; + + /* fill arp tuple */ + tlv = (struct wmi_tlv *)buf_ptr; + tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) | + FIELD_PREP(WMI_TLV_LEN, WMI_MAX_ARP_OFFLOADS * sizeof(*arp)); + buf_ptr += sizeof(*tlv); + + for (i = 0; i < WMI_MAX_ARP_OFFLOADS; i++) { + arp = (struct wmi_arp_offload_tuple *)buf_ptr; + arp->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARP_OFFLOAD_TUPLE) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*arp) - TLV_HDR_SIZE); + + if (enable && i < offload->ipv4_count) { + /* Copy the target ip addr and flags */ + arp->flags = WMI_ARPOL_FLAGS_VALID; + memcpy(arp->target_ipaddr, offload->ipv4_addr[i], 4); + ath11k_ce_byte_swap(arp->target_ipaddr, 4); + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "wmi arp offload address %pI4", + arp->target_ipaddr); + } + + buf_ptr += sizeof(*arp); + } + + *ptr = buf_ptr; +} + +int ath11k_wmi_arp_ns_offload(struct ath11k *ar, + struct ath11k_vif *arvif, bool enable) +{ + struct ath11k_arp_ns_offload *offload; + struct wmi_set_arp_ns_offload_cmd *cmd; + struct wmi_tlv *tlv; + struct sk_buff *skb; + u8 *buf_ptr; + size_t len; + u8 ns_cnt, ns_ext_tuples = 0; + + offload = &arvif->arp_ns_offload; + ns_cnt = offload->ipv6_count; + + len = sizeof(*cmd) + + sizeof(*tlv) + + WMI_MAX_NS_OFFLOADS * sizeof(struct wmi_ns_offload_tuple) + + sizeof(*tlv) + + WMI_MAX_ARP_OFFLOADS * sizeof(struct wmi_arp_offload_tuple); + + if (ns_cnt > WMI_MAX_NS_OFFLOADS) { + ns_ext_tuples = ns_cnt - WMI_MAX_NS_OFFLOADS; + len += sizeof(*tlv) + + ns_ext_tuples * sizeof(struct wmi_ns_offload_tuple); + } + + skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + buf_ptr = skb->data; + cmd = (struct wmi_set_arp_ns_offload_cmd *)buf_ptr; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, + WMI_TAG_SET_ARP_NS_OFFLOAD_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + + cmd->flags = 0; + cmd->vdev_id = arvif->vdev_id; + cmd->num_ns_ext_tuples = ns_ext_tuples; + + buf_ptr += sizeof(*cmd); + + ath11k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 0); + ath11k_wmi_fill_arp_offload(ar, offload, &buf_ptr, enable); + + if (ns_ext_tuples) + ath11k_wmi_fill_ns_offload(ar, offload, &buf_ptr, enable, 1); + + return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID); +} diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index 17e50987e115..e2d03c3b422c 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -13,6 +13,7 @@ struct ath11k_base; struct ath11k; struct ath11k_fw_stats; struct ath11k_fw_dbglog; +struct ath11k_vif; #define PSOC_HOST_MAX_NUM_SS (8) @@ -5796,6 +5797,49 @@ struct wmi_wow_nlo_config_cmd { */ } __packed; +#define WMI_MAX_NS_OFFLOADS 2 +#define WMI_MAX_ARP_OFFLOADS 2 + +#define WMI_ARPOL_FLAGS_VALID BIT(0) +#define WMI_ARPOL_FLAGS_MAC_VALID BIT(1) +#define WMI_ARPOL_FLAGS_REMOTE_IP_VALID BIT(2) + +struct wmi_arp_offload_tuple { + u32 tlv_header; + u32 flags; + u8 target_ipaddr[4]; + u8 remote_ipaddr[4]; + struct wmi_mac_addr target_mac; +} __packed; + +#define WMI_NSOL_FLAGS_VALID BIT(0) +#define WMI_NSOL_FLAGS_MAC_VALID BIT(1) +#define WMI_NSOL_FLAGS_REMOTE_IP_VALID BIT(2) +#define WMI_NSOL_FLAGS_IS_IPV6_ANYCAST BIT(3) + +#define WMI_NSOL_MAX_TARGET_IPS 2 + +struct wmi_ns_offload_tuple { + u32 tlv_header; + u32 flags; + u8 target_ipaddr[WMI_NSOL_MAX_TARGET_IPS][16]; + u8 solicitation_ipaddr[16]; + u8 remote_ipaddr[16]; + struct wmi_mac_addr target_mac; +} __packed; + +struct wmi_set_arp_ns_offload_cmd { + u32 tlv_header; + u32 flags; + u32 vdev_id; + u32 num_ns_ext_tuples; + /* The TLVs follow: + * wmi_ns_offload_tuple ns_tuples[WMI_MAX_NS_OFFLOADS]; + * wmi_arp_offload_tuple arp_tuples[WMI_MAX_ARP_OFFLOADS]; + * wmi_ns_offload_tuple ns_ext_tuples[num_ns_ext_tuples]; + */ +} __packed; + int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, u32 cmd_id); struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); @@ -5968,4 +6012,7 @@ int ath11k_wmi_wow_add_wakeup_event(struct ath11k *ar, u32 vdev_id, u32 enable); int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id, u32 filter_bitmap, bool enable); +int ath11k_wmi_arp_ns_offload(struct ath11k *ar, + struct ath11k_vif *arvif, bool enable); + #endif diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c index 602b8f4c5985..bc6a4d3d6d7c 100644 --- a/drivers/net/wireless/ath/ath11k/wow.c +++ b/drivers/net/wireless/ath/ath11k/wow.c @@ -559,6 +559,43 @@ static int ath11k_wow_clear_hw_filter(struct ath11k *ar) return 0; } +static int ath11k_wow_arp_ns_offload(struct ath11k *ar, bool enable) +{ + struct ath11k_vif *arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + if (arvif->vdev_type != WMI_VDEV_TYPE_STA) + continue; + + ret = ath11k_wmi_arp_ns_offload(ar, arvif, enable); + + if (ret) { + ath11k_warn(ar->ab, "failed to set arp ns offload vdev %i: enable %d, ret %d\n", + arvif->vdev_id, enable, ret); + return ret; + } + } + + return 0; +} + +static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable) +{ + int ret; + + ret = ath11k_wow_arp_ns_offload(ar, enable); + if (ret) { + ath11k_warn(ar->ab, "failed to offload ARP and NS %d %d\n", + enable, ret); + return ret; + } + + return 0; +} + int ath11k_wow_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { @@ -589,6 +626,14 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw, goto cleanup; } + ret = ath11k_wow_protocol_offload(ar, true); + if (ret) { + ath11k_warn(ar->ab, "failed to set wow protocol offload events: %d\n", + ret); + goto cleanup; + } + + ath11k_mac_drain_tx(ar); ret = ath11k_mac_wait_tx_complete(ar); if (ret) { ath11k_warn(ar->ab, "failed to wait tx complete: %d\n", ret); @@ -690,6 +735,13 @@ int ath11k_wow_op_resume(struct ieee80211_hw *hw) goto exit; } + ret = ath11k_wow_protocol_offload(ar, false); + if (ret) { + ath11k_warn(ar->ab, "failed to clear wow protocol offload events: %d\n", + ret); + goto exit; + } + exit: if (ret) { switch (ar->state) { From a16d9b50cfbaf112401b8e5ccfa852709f498cd4 Mon Sep 17 00:00:00 2001 From: Carl Huang Date: Mon, 14 Mar 2022 07:18:16 +0200 Subject: [PATCH 00254/11454] ath11k: support GTK rekey offload Host sets GTK related info to firmware before WoW is enabled, and gets rekey replay_count and then disables GTK rekey when WoW quits. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Carl Huang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1644308006-22784-7-git-send-email-quic_cjhuang@quicinc.com --- drivers/net/wireless/ath/ath11k/core.h | 8 ++ drivers/net/wireless/ath/ath11k/mac.c | 37 ++++++++ drivers/net/wireless/ath/ath11k/wmi.c | 119 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/wmi.h | 49 ++++++++++ drivers/net/wireless/ath/ath11k/wow.c | 46 +++++++++- 5 files changed, 258 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 4ba12de44415..e556beb945ac 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -230,6 +230,13 @@ struct ath11k_arp_ns_offload { u8 mac_addr[ETH_ALEN]; }; +struct ath11k_rekey_data { + u8 kck[NL80211_KCK_LEN]; + u8 kek[NL80211_KCK_LEN]; + u64 replay_ctr; + bool enable_offload; +}; + struct ath11k_vif { u32 vdev_id; enum wmi_vdev_type vdev_type; @@ -282,6 +289,7 @@ struct ath11k_vif { bool do_not_send_tmpl; struct ieee80211_chanctx_conf chanctx; struct ath11k_arp_ns_offload arp_ns_offload; + struct ath11k_rekey_data rekey_data; #ifdef CONFIG_ATH11K_DEBUGFS struct dentry *debugfs_twt; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index dee1cb4121f8..e0e31605e0b0 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -2757,6 +2757,7 @@ static void ath11k_bss_assoc(struct ieee80211_hw *hw, } arvif->is_up = true; + arvif->rekey_data.enable_offload = false; ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac vdev %d up (associated) bssid %pM aid %d\n", @@ -2814,6 +2815,8 @@ static void ath11k_bss_disassoc(struct ieee80211_hw *hw, arvif->is_up = false; + memset(&arvif->rekey_data, 0, sizeof(arvif->rekey_data)); + cancel_delayed_work_sync(&arvif->connection_loss_work); } @@ -8200,6 +8203,39 @@ generate: ath11k_generate_ns_mc_addr(ar, offload); } +static void ath11k_mac_op_set_rekey_data(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct cfg80211_gtk_rekey_data *data) +{ + struct ath11k *ar = hw->priv; + struct ath11k_vif *arvif = ath11k_vif_to_arvif(vif); + struct ath11k_rekey_data *rekey_data = &arvif->rekey_data; + + ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac set rekey data vdev %d\n", + arvif->vdev_id); + + mutex_lock(&ar->conf_mutex); + + memcpy(rekey_data->kck, data->kck, NL80211_KCK_LEN); + memcpy(rekey_data->kek, data->kek, NL80211_KEK_LEN); + + /* The supplicant works on big-endian, the firmware expects it on + * little endian. + */ + rekey_data->replay_ctr = get_unaligned_be64(data->replay_ctr); + + arvif->rekey_data.enable_offload = true; + + ath11k_dbg_dump(ar->ab, ATH11K_DBG_MAC, "kck", NULL, + rekey_data->kck, NL80211_KCK_LEN); + ath11k_dbg_dump(ar->ab, ATH11K_DBG_MAC, "kek", NULL, + rekey_data->kck, NL80211_KEK_LEN); + ath11k_dbg_dump(ar->ab, ATH11K_DBG_MAC, "replay ctr", NULL, + &rekey_data->replay_ctr, sizeof(rekey_data->replay_ctr)); + + mutex_unlock(&ar->conf_mutex); +} + static const struct ieee80211_ops ath11k_ops = { .tx = ath11k_mac_op_tx, .start = ath11k_mac_op_start, @@ -8214,6 +8250,7 @@ static const struct ieee80211_ops ath11k_ops = { .hw_scan = ath11k_mac_op_hw_scan, .cancel_hw_scan = ath11k_mac_op_cancel_hw_scan, .set_key = ath11k_mac_op_set_key, + .set_rekey_data = ath11k_mac_op_set_rekey_data, .sta_state = ath11k_mac_op_sta_state, .sta_set_4addr = ath11k_mac_op_sta_set_4addr, .sta_set_txpwr = ath11k_mac_op_sta_set_txpwr, diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 828f9cacbe57..7f97c26bffd9 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -7765,6 +7765,56 @@ exit: kfree(tb); } +static void ath11k_wmi_gtk_offload_status_event(struct ath11k_base *ab, + struct sk_buff *skb) +{ + const void **tb; + const struct wmi_gtk_offload_status_event *ev; + struct ath11k_vif *arvif; + __be64 replay_ctr_be; + u64 replay_ctr; + int ret; + + tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); + if (IS_ERR(tb)) { + ret = PTR_ERR(tb); + ath11k_warn(ab, "failed to parse tlv: %d\n", ret); + return; + } + + ev = tb[WMI_TAG_GTK_OFFLOAD_STATUS_EVENT]; + if (!ev) { + ath11k_warn(ab, "failed to fetch gtk offload status ev"); + kfree(tb); + return; + } + + arvif = ath11k_mac_get_arvif_by_vdev_id(ab, ev->vdev_id); + if (!arvif) { + ath11k_warn(ab, "failed to get arvif for vdev_id:%d\n", + ev->vdev_id); + kfree(tb); + return; + } + + ath11k_dbg(ab, ATH11K_DBG_WMI, "wmi gtk offload event refresh_cnt %d\n", + ev->refresh_cnt); + ath11k_dbg_dump(ab, ATH11K_DBG_WMI, "replay_cnt", + NULL, ev->replay_ctr.counter, GTK_REPLAY_COUNTER_BYTES); + + replay_ctr = ev->replay_ctr.word1; + replay_ctr = (replay_ctr << 32) | ev->replay_ctr.word0; + arvif->rekey_data.replay_ctr = replay_ctr; + + /* supplicant expects big-endian replay counter */ + replay_ctr_be = cpu_to_be64(replay_ctr); + + ieee80211_gtk_rekey_notify(arvif->vif, arvif->bssid, + (void *)&replay_ctr_be, GFP_KERNEL); + + kfree(tb); +} + static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) { struct wmi_cmd_hdr *cmd_hdr; @@ -7896,6 +7946,9 @@ static void ath11k_wmi_tlv_op_rx(struct ath11k_base *ab, struct sk_buff *skb) case WMI_DIAG_EVENTID: ath11k_wmi_diag_event(ab, skb); break; + case WMI_GTK_OFFLOAD_STATUS_EVENTID: + ath11k_wmi_gtk_offload_status_event(ab, skb); + break; /* TODO: Add remaining events */ default: ath11k_dbg(ab, ATH11K_DBG_WMI, "Unknown eventid: 0x%x\n", id); @@ -8735,3 +8788,69 @@ int ath11k_wmi_arp_ns_offload(struct ath11k *ar, return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_SET_ARP_NS_OFFLOAD_CMDID); } + +int ath11k_wmi_gtk_rekey_offload(struct ath11k *ar, + struct ath11k_vif *arvif, bool enable) +{ + struct wmi_gtk_rekey_offload_cmd *cmd; + struct ath11k_rekey_data *rekey_data = &arvif->rekey_data; + int len; + struct sk_buff *skb; + __le64 replay_ctr; + + len = sizeof(*cmd); + skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_gtk_rekey_offload_cmd *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_GTK_OFFLOAD_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + + cmd->vdev_id = arvif->vdev_id; + + if (enable) { + cmd->flags = GTK_OFFLOAD_ENABLE_OPCODE; + + /* the length in rekey_data and cmd is equal */ + memcpy(cmd->kck, rekey_data->kck, sizeof(cmd->kck)); + ath11k_ce_byte_swap(cmd->kck, GTK_OFFLOAD_KEK_BYTES); + memcpy(cmd->kek, rekey_data->kek, sizeof(cmd->kek)); + ath11k_ce_byte_swap(cmd->kek, GTK_OFFLOAD_KEK_BYTES); + + replay_ctr = cpu_to_le64(rekey_data->replay_ctr); + memcpy(cmd->replay_ctr, &replay_ctr, + sizeof(replay_ctr)); + ath11k_ce_byte_swap(cmd->replay_ctr, GTK_REPLAY_COUNTER_BYTES); + } else { + cmd->flags = GTK_OFFLOAD_DISABLE_OPCODE; + } + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "offload gtk rekey vdev: %d %d\n", + arvif->vdev_id, enable); + return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID); +} + +int ath11k_wmi_gtk_rekey_getinfo(struct ath11k *ar, + struct ath11k_vif *arvif) +{ + struct wmi_gtk_rekey_offload_cmd *cmd; + int len; + struct sk_buff *skb; + + len = sizeof(*cmd); + skb = ath11k_wmi_alloc_skb(ar->wmi->wmi_ab, len); + if (!skb) + return -ENOMEM; + + cmd = (struct wmi_gtk_rekey_offload_cmd *)skb->data; + cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_GTK_OFFLOAD_CMD) | + FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE); + + cmd->vdev_id = arvif->vdev_id; + cmd->flags = GTK_OFFLOAD_REQUEST_STATUS_OPCODE; + + ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "get gtk rekey vdev_id: %d\n", + arvif->vdev_id); + return ath11k_wmi_cmd_send(ar->wmi, skb, WMI_GTK_OFFLOAD_CMDID); +} diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h index e2d03c3b422c..925b8003feae 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.h +++ b/drivers/net/wireless/ath/ath11k/wmi.h @@ -5840,6 +5840,51 @@ struct wmi_set_arp_ns_offload_cmd { */ } __packed; +#define GTK_OFFLOAD_OPCODE_MASK 0xFF000000 +#define GTK_OFFLOAD_ENABLE_OPCODE 0x01000000 +#define GTK_OFFLOAD_DISABLE_OPCODE 0x02000000 +#define GTK_OFFLOAD_REQUEST_STATUS_OPCODE 0x04000000 + +#define GTK_OFFLOAD_KEK_BYTES 16 +#define GTK_OFFLOAD_KCK_BYTES 16 +#define GTK_REPLAY_COUNTER_BYTES 8 +#define WMI_MAX_KEY_LEN 32 +#define IGTK_PN_SIZE 6 + +struct wmi_replayc_cnt { + union { + u8 counter[GTK_REPLAY_COUNTER_BYTES]; + struct { + u32 word0; + u32 word1; + } __packed; + } __packed; +} __packed; + +struct wmi_gtk_offload_status_event { + u32 vdev_id; + u32 flags; + u32 refresh_cnt; + struct wmi_replayc_cnt replay_ctr; + u8 igtk_key_index; + u8 igtk_key_length; + u8 igtk_key_rsc[IGTK_PN_SIZE]; + u8 igtk_key[WMI_MAX_KEY_LEN]; + u8 gtk_key_index; + u8 gtk_key_length; + u8 gtk_key_rsc[GTK_REPLAY_COUNTER_BYTES]; + u8 gtk_key[WMI_MAX_KEY_LEN]; +} __packed; + +struct wmi_gtk_rekey_offload_cmd { + u32 tlv_header; + u32 vdev_id; + u32 flags; + u8 kek[GTK_OFFLOAD_KEK_BYTES]; + u8 kck[GTK_OFFLOAD_KCK_BYTES]; + u8 replay_ctr[GTK_REPLAY_COUNTER_BYTES]; +} __packed; + int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb, u32 cmd_id); struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_sc, u32 len); @@ -6014,5 +6059,9 @@ int ath11k_wmi_hw_data_filter_cmd(struct ath11k *ar, u32 vdev_id, u32 filter_bitmap, bool enable); int ath11k_wmi_arp_ns_offload(struct ath11k *ar, struct ath11k_vif *arvif, bool enable); +int ath11k_wmi_gtk_rekey_offload(struct ath11k *ar, + struct ath11k_vif *arvif, bool enable); +int ath11k_wmi_gtk_rekey_getinfo(struct ath11k *ar, + struct ath11k_vif *arvif); #endif diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c index bc6a4d3d6d7c..93714df834b2 100644 --- a/drivers/net/wireless/ath/ath11k/wow.c +++ b/drivers/net/wireless/ath/ath11k/wow.c @@ -17,7 +17,9 @@ static const struct wiphy_wowlan_support ath11k_wowlan_support = { .flags = WIPHY_WOWLAN_DISCONNECT | - WIPHY_WOWLAN_MAGIC_PKT, + WIPHY_WOWLAN_MAGIC_PKT | + WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_GTK_REKEY_FAILURE, .pattern_min_len = WOW_MIN_PATTERN_SIZE, .pattern_max_len = WOW_MAX_PATTERN_SIZE, .max_pkt_offset = WOW_MAX_PKT_OFFSET, @@ -582,6 +584,41 @@ static int ath11k_wow_arp_ns_offload(struct ath11k *ar, bool enable) return 0; } +static int ath11k_gtk_rekey_offload(struct ath11k *ar, bool enable) +{ + struct ath11k_vif *arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + if (arvif->vdev_type != WMI_VDEV_TYPE_STA || + !arvif->is_up || + !arvif->rekey_data.enable_offload) + continue; + + /* get rekey info before disable rekey offload */ + if (!enable) { + ret = ath11k_wmi_gtk_rekey_getinfo(ar, arvif); + if (ret) { + ath11k_warn(ar->ab, "failed to request rekey info vdev %i, ret %d\n", + arvif->vdev_id, ret); + return ret; + } + } + + ret = ath11k_wmi_gtk_rekey_offload(ar, arvif, enable); + + if (ret) { + ath11k_warn(ar->ab, "failed to offload gtk reky vdev %i: enable %d, ret %d\n", + arvif->vdev_id, enable, ret); + return ret; + } + } + + return 0; +} + static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable) { int ret; @@ -593,6 +630,13 @@ static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable) return ret; } + ret = ath11k_gtk_rekey_offload(ar, enable); + if (ret) { + ath11k_warn(ar->ab, "failed to offload gtk rekey %d %d\n", + enable, ret); + return ret; + } + return 0; } From 9503a1fc123d9c9c502a7e518634296874a7b8cc Mon Sep 17 00:00:00 2001 From: Minghao Chi Date: Mon, 14 Mar 2022 06:45:01 +0000 Subject: [PATCH 00255/11454] ath9k: Use platform_get_irq() to get the interrupt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is not recommened to use platform_get_resource(pdev, IORESOURCE_IRQ) for requesting IRQ's resources any more, as they can be not ready yet in case of DT-booting. platform_get_irq() instead is a recommended way for getting IRQ even if it was not retrieved earlier. It also makes code simpler because we're getting "int" value right away and no conversion from resource to int is required. Reported-by: Zeal Robot Signed-off-by: Minghao Chi Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220314064501.2114002-1-chi.minghao@zte.com.cn --- drivers/net/wireless/ath/ath9k/ahb.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c index cdefb8e2daf1..c9b853af41d1 100644 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ b/drivers/net/wireless/ath/ath9k/ahb.c @@ -98,14 +98,12 @@ static int ath_ahb_probe(struct platform_device *pdev) return -ENOMEM; } - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) { + irq = platform_get_irq(pdev, 0); + if (irq < 0) { dev_err(&pdev->dev, "no IRQ resource found\n"); - return -ENXIO; + return irq; } - irq = res->start; - ath9k_fill_chanctx_ops(); hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops); if (hw == NULL) { From b7d174479c8ac365828d474b385da2da858f2089 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 14 Mar 2022 12:53:27 +0100 Subject: [PATCH 00256/11454] ath6kl: fix typos in comments Various spelling mistakes in comments. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220314115354.144023-4-Julia.Lawall@inria.fr --- drivers/net/wireless/ath/ath6kl/htc_mbox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index e3874421c4c0..1963d3145481 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c @@ -1538,7 +1538,7 @@ static int ath6kl_htc_rx_alloc(struct htc_target *target, queue, n_msg); /* - * This is due to unavailabilty of buffers to rx entire data. + * This is due to unavailability of buffers to rx entire data. * Return no error so that free buffers from queue can be used * to receive partial data. */ From ca6920811aa5428270dd78af0a7a36b10119065a Mon Sep 17 00:00:00 2001 From: Akeem G Abodunrin Date: Thu, 17 Mar 2022 19:10:51 -0700 Subject: [PATCH 00257/11454] drm/i915/dg2: Add preemption changes for Wa_14015141709 Starting with DG2, preemption can no longer be controlled using userspace on a per-context basis. Instead, the hardware only allows us to enable or disable preemption in a global, system-wide basis. Also, we lose the ability to specify the preemption granularity (such as batch-level vs command-level vs object-level). v2 (MattR): - Move debugfs interface to a separate patch. (Jani) v3 (MattR): - Drop the debugfs support completely for now. Cc: Matt Roper Cc: Prathap Kumar Valsan Cc: John Harrison Cc: Joonas Lahtinen Cc: Jani Nikula Cc: Tvrtko Ursulin Signed-off-by: Akeem G Abodunrin Signed-off-by: Matt Roper Reviewed-by: Anusha Srivatsa Link: https://patchwork.freedesktop.org/patch/msgid/20220318021051.2073847-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/gt/intel_workarounds.c | 2 +- drivers/gpu/drm/i915/i915_drv.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index c328d46f8095..dc0ffff6f655 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -2316,7 +2316,7 @@ rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal) FF_DOP_CLOCK_GATE_DISABLE); } - if (IS_GRAPHICS_VER(i915, 9, 12)) { + if (HAS_PERCTX_PREEMPT_CTRL(i915)) { /* FtrPerCtxtPreemptionGranularityControl:skl,bxt,kbl,cfl,cnl,icl,tgl */ wa_masked_en(wal, GEN7_FF_SLICE_CS_CHICKEN1, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 57643639b092..86f95f40576b 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1400,6 +1400,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_GUC_DEPRIVILEGE(dev_priv) \ (INTEL_INFO(dev_priv)->has_guc_deprivilege) +#define HAS_PERCTX_PREEMPT_CTRL(i915) \ + ((GRAPHICS_VER(i915) >= 9) && GRAPHICS_VER_FULL(i915) < IP_VER(12, 55)) + static inline bool run_as_guest(void) { return !hypervisor_is_type(X86_HYPER_NATIVE); From 856082f021a28221db2c32bd0531614a8382be67 Mon Sep 17 00:00:00 2001 From: Chuansheng Liu Date: Fri, 18 Mar 2022 08:50:03 +0800 Subject: [PATCH 00258/11454] fbdev: defio: fix the pagelist corruption Easily hit the below list corruption: == list_add corruption. prev->next should be next (ffffffffc0ceb090), but was ffffec604507edc8. (prev=ffffec604507edc8). WARNING: CPU: 65 PID: 3959 at lib/list_debug.c:26 __list_add_valid+0x53/0x80 CPU: 65 PID: 3959 Comm: fbdev Tainted: G U RIP: 0010:__list_add_valid+0x53/0x80 Call Trace: fb_deferred_io_mkwrite+0xea/0x150 do_page_mkwrite+0x57/0xc0 do_wp_page+0x278/0x2f0 __handle_mm_fault+0xdc2/0x1590 handle_mm_fault+0xdd/0x2c0 do_user_addr_fault+0x1d3/0x650 exc_page_fault+0x77/0x180 ? asm_exc_page_fault+0x8/0x30 asm_exc_page_fault+0x1e/0x30 RIP: 0033:0x7fd98fc8fad1 == Figure out the race happens when one process is adding &page->lru into the pagelist tail in fb_deferred_io_mkwrite(), another process is re-initializing the same &page->lru in fb_deferred_io_fault(), which is not protected by the lock. This fix is to init all the page lists one time during initialization, it not only fixes the list corruption, but also avoids INIT_LIST_HEAD() redundantly. V2: change "int i" to "unsigned int i" (Geert Uytterhoeven) Signed-off-by: Chuansheng Liu Fixes: 105a940416fc ("fbdev/defio: Early-out if page is already enlisted") Cc: Thomas Zimmermann Cc: Geert Uytterhoeven Reviewed-by: Javier Martinez Canillas Reviewed-by: Thomas Zimmermann Signed-off-by: Thomas Zimmermann Link: https://patchwork.freedesktop.org/patch/msgid/20220318005003.51810-1-chuansheng.liu@intel.com --- drivers/video/fbdev/core/fb_defio.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/video/fbdev/core/fb_defio.c b/drivers/video/fbdev/core/fb_defio.c index 98b0f23bf5e2..a1da54016c88 100644 --- a/drivers/video/fbdev/core/fb_defio.c +++ b/drivers/video/fbdev/core/fb_defio.c @@ -59,7 +59,6 @@ static vm_fault_t fb_deferred_io_fault(struct vm_fault *vmf) printk(KERN_ERR "no mapping available\n"); BUG_ON(!page->mapping); - INIT_LIST_HEAD(&page->lru); page->index = vmf->pgoff; vmf->page = page; @@ -220,6 +219,8 @@ static void fb_deferred_io_work(struct work_struct *work) void fb_deferred_io_init(struct fb_info *info) { struct fb_deferred_io *fbdefio = info->fbdefio; + struct page *page; + unsigned int i; BUG_ON(!fbdefio); mutex_init(&fbdefio->lock); @@ -227,6 +228,12 @@ void fb_deferred_io_init(struct fb_info *info) INIT_LIST_HEAD(&fbdefio->pagelist); if (fbdefio->delay == 0) /* set a default of 1 s */ fbdefio->delay = HZ; + + /* initialize all the page lists one time */ + for (i = 0; i < info->fix.smem_len; i += PAGE_SIZE) { + page = fb_deferred_io_page(info, i); + INIT_LIST_HEAD(&page->lru); + } } EXPORT_SYMBOL_GPL(fb_deferred_io_init); From d8f5855b31c0523ea3b171db8dfb998830e8735d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2022 18:49:41 +0200 Subject: [PATCH 00259/11454] drm/i915: Treat SAGV block time 0 as SAGV disabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For modern platforms the spec explicitly states that a SAGV block time of zero means that SAGV is not supported. Let's extend that to all platforms. Supposedly there should be no systems where this isn't true, and it'll allow us to: - use the same code regardless of older vs. newer platform - wm latencies already treat 0 as disabled, so this fits well with other related code - make it a bit more clear when SAGV is used vs. not - avoid overflows from adding U32_MAX with a u16 wm0 latency value which could cause us to miscalculate the SAGV watermarks on tgl+ Cc: stable@vger.kernel.org Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220309164948.10671-2-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/intel_pm.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8ee31c9590a7..40a3094e55ca 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3696,8 +3696,7 @@ skl_setup_sagv_block_time(struct drm_i915_private *dev_priv) MISSING_CASE(DISPLAY_VER(dev_priv)); } - /* Default to an unusable block time */ - dev_priv->sagv_block_time_us = -1; + dev_priv->sagv_block_time_us = 0; } /* @@ -5644,7 +5643,7 @@ static void skl_compute_plane_wm(const struct intel_crtc_state *crtc_state, result->min_ddb_alloc = max(min_ddb_alloc, blocks) + 1; result->enable = true; - if (DISPLAY_VER(dev_priv) < 12) + if (DISPLAY_VER(dev_priv) < 12 && dev_priv->sagv_block_time_us) result->can_sagv = latency >= dev_priv->sagv_block_time_us; } @@ -5677,7 +5676,10 @@ static void tgl_compute_sagv_wm(const struct intel_crtc_state *crtc_state, struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); struct skl_wm_level *sagv_wm = &plane_wm->sagv.wm0; struct skl_wm_level *levels = plane_wm->wm; - unsigned int latency = dev_priv->wm.skl_latency[0] + dev_priv->sagv_block_time_us; + unsigned int latency = 0; + + if (dev_priv->sagv_block_time_us) + latency = dev_priv->sagv_block_time_us + dev_priv->wm.skl_latency[0]; skl_compute_plane_wm(crtc_state, plane, 0, latency, wm_params, &levels[0], From c0074e71bf8d0d16459ecb0de682fcb4192326c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2022 18:49:42 +0200 Subject: [PATCH 00260/11454] drm/i915: Rework SAGV block time probing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I'd like to see the SAGV block time we got from the mailbox in the logs regardless of whether other factors prevent the use of SAGV. So let's adjust the code to always query the SAGV block time, log it, and then reset it if SAGV is not actually supported. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220309164948.10671-3-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/intel_pm.c | 36 +++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 40a3094e55ca..906501d6b298 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3670,8 +3670,8 @@ intel_has_sagv(struct drm_i915_private *dev_priv) dev_priv->sagv_status != I915_SAGV_NOT_CONTROLLED; } -static void -skl_setup_sagv_block_time(struct drm_i915_private *dev_priv) +static u32 +intel_sagv_block_time(struct drm_i915_private *dev_priv) { if (DISPLAY_VER(dev_priv) >= 12) { u32 val = 0; @@ -3680,23 +3680,30 @@ skl_setup_sagv_block_time(struct drm_i915_private *dev_priv) ret = snb_pcode_read(dev_priv, GEN12_PCODE_READ_SAGV_BLOCK_TIME_US, &val, NULL); - if (!ret) { - dev_priv->sagv_block_time_us = val; - return; + if (ret) { + drm_dbg_kms(&dev_priv->drm, "Couldn't read SAGV block time!\n"); + return 0; } - drm_dbg(&dev_priv->drm, "Couldn't read SAGV block time!\n"); + return val; } else if (DISPLAY_VER(dev_priv) == 11) { - dev_priv->sagv_block_time_us = 10; - return; - } else if (DISPLAY_VER(dev_priv) == 9) { - dev_priv->sagv_block_time_us = 30; - return; + return 10; + } else if (DISPLAY_VER(dev_priv) == 9 && !IS_LP(dev_priv)) { + return 30; } else { - MISSING_CASE(DISPLAY_VER(dev_priv)); + return 0; } +} - dev_priv->sagv_block_time_us = 0; +static void intel_sagv_init(struct drm_i915_private *i915) +{ + i915->sagv_block_time_us = intel_sagv_block_time(i915); + + drm_dbg_kms(&i915->drm, "SAGV supported: %s, original SAGV block time: %u us\n", + str_yes_no(intel_has_sagv(i915)), i915->sagv_block_time_us); + + if (!intel_has_sagv(i915)) + i915->sagv_block_time_us = 0; } /* @@ -8175,8 +8182,7 @@ void intel_init_pm(struct drm_i915_private *dev_priv) else if (GRAPHICS_VER(dev_priv) == 5) ilk_get_mem_freq(dev_priv); - if (intel_has_sagv(dev_priv)) - skl_setup_sagv_block_time(dev_priv); + intel_sagv_init(dev_priv); /* For FIFO watermark updates */ if (DISPLAY_VER(dev_priv) >= 9) { From 15fc156f22db140ea2d25ecd4aff15e3d800ec35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2022 18:49:43 +0200 Subject: [PATCH 00261/11454] drm/i915: Probe whether SAGV works on pre-icl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of leaving the SAGV enable/disable to the first commit let's try to disable it first thing to see if we can do it or not (disabling SAGV is a safe thing to at any time). This avoids running the code in this funny intermediate state where we don't know if SAGV is available or not. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220309164948.10671-4-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/intel_pm.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 906501d6b298..36f5bccabf64 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -57,6 +57,8 @@ #include "vlv_sideband.h" #include "../../../platform/x86/intel_ips.h" +static int intel_disable_sagv(struct drm_i915_private *dev_priv); + struct drm_i915_clock_gating_funcs { void (*init_clock_gating)(struct drm_i915_private *i915); }; @@ -3697,6 +3699,18 @@ intel_sagv_block_time(struct drm_i915_private *dev_priv) static void intel_sagv_init(struct drm_i915_private *i915) { + if (!intel_has_sagv(i915)) + i915->sagv_status = I915_SAGV_NOT_CONTROLLED; + + /* + * Probe to see if we have working SAGV control. + * For icl+ this was already determined by intel_bw_init_hw(). + */ + if (DISPLAY_VER(i915) < 11) + intel_disable_sagv(i915); + + drm_WARN_ON(&i915->drm, i915->sagv_status == I915_SAGV_UNKNOWN); + i915->sagv_block_time_us = intel_sagv_block_time(i915); drm_dbg_kms(&i915->drm, "SAGV supported: %s, original SAGV block time: %u us\n", From de2cac863da9427f4476edfc9af35343d0b19a56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2022 18:49:44 +0200 Subject: [PATCH 00262/11454] drm/i915: Reject excessive SAGV block time MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the mailbox returns an exceesively large SAGV block time let's just reject it. This avoids having to worry about overflows when we add the SAGV block time to the wm0 latency. We shall put the limit arbitrarily at U16_MAX. >65msec latency doesn't really make sense to me in any case. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220309164948.10671-5-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/intel_pm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 36f5bccabf64..166246fa27e4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -3716,6 +3716,12 @@ static void intel_sagv_init(struct drm_i915_private *i915) drm_dbg_kms(&i915->drm, "SAGV supported: %s, original SAGV block time: %u us\n", str_yes_no(intel_has_sagv(i915)), i915->sagv_block_time_us); + /* avoid overflow when adding with wm0 latency/etc. */ + if (drm_WARN(&i915->drm, i915->sagv_block_time_us > U16_MAX, + "Excessive SAGV block time %u, ignoring\n", + i915->sagv_block_time_us)) + i915->sagv_block_time_us = 0; + if (!intel_has_sagv(i915)) i915->sagv_block_time_us = 0; } From 4593e8e064353c4db3c1ad0f774d389af33d31c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2022 18:49:45 +0200 Subject: [PATCH 00263/11454] drm/i915: Rename pre-icl SAGV enable/disable functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Give the pre-icl SAGV control functions a skl_ prefix instead of the intel_ prefix to make it a bit more clear that they are not some kind of universal things that can be called on any platform. Also make the functions void since we never use the return value anyway. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220309164948.10671-6-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/intel_pm.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 166246fa27e4..bd936d4c5b0f 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -57,7 +57,7 @@ #include "vlv_sideband.h" #include "../../../platform/x86/intel_ips.h" -static int intel_disable_sagv(struct drm_i915_private *dev_priv); +static void skl_sagv_disable(struct drm_i915_private *dev_priv); struct drm_i915_clock_gating_funcs { void (*init_clock_gating)(struct drm_i915_private *i915); @@ -3707,7 +3707,7 @@ static void intel_sagv_init(struct drm_i915_private *i915) * For icl+ this was already determined by intel_bw_init_hw(). */ if (DISPLAY_VER(i915) < 11) - intel_disable_sagv(i915); + skl_sagv_disable(i915); drm_WARN_ON(&i915->drm, i915->sagv_status == I915_SAGV_UNKNOWN); @@ -3737,16 +3737,15 @@ static void intel_sagv_init(struct drm_i915_private *i915) * - All planes can enable watermarks for latencies >= SAGV engine block time * - We're not using an interlaced display configuration */ -static int -intel_enable_sagv(struct drm_i915_private *dev_priv) +static void skl_sagv_enable(struct drm_i915_private *dev_priv) { int ret; if (!intel_has_sagv(dev_priv)) - return 0; + return; if (dev_priv->sagv_status == I915_SAGV_ENABLED) - return 0; + return; drm_dbg_kms(&dev_priv->drm, "Enabling SAGV\n"); ret = snb_pcode_write(dev_priv, GEN9_PCODE_SAGV_CONTROL, @@ -3761,26 +3760,24 @@ intel_enable_sagv(struct drm_i915_private *dev_priv) if (IS_SKYLAKE(dev_priv) && ret == -ENXIO) { drm_dbg(&dev_priv->drm, "No SAGV found on system, ignoring\n"); dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; - return 0; + return; } else if (ret < 0) { drm_err(&dev_priv->drm, "Failed to enable SAGV\n"); - return ret; + return; } dev_priv->sagv_status = I915_SAGV_ENABLED; - return 0; } -static int -intel_disable_sagv(struct drm_i915_private *dev_priv) +static void skl_sagv_disable(struct drm_i915_private *dev_priv) { int ret; if (!intel_has_sagv(dev_priv)) - return 0; + return; if (dev_priv->sagv_status == I915_SAGV_DISABLED) - return 0; + return; drm_dbg_kms(&dev_priv->drm, "Disabling SAGV\n"); /* bspec says to keep retrying for at least 1 ms */ @@ -3795,14 +3792,13 @@ intel_disable_sagv(struct drm_i915_private *dev_priv) if (IS_SKYLAKE(dev_priv) && ret == -ENXIO) { drm_dbg(&dev_priv->drm, "No SAGV found on system, ignoring\n"); dev_priv->sagv_status = I915_SAGV_NOT_CONTROLLED; - return 0; + return; } else if (ret < 0) { drm_err(&dev_priv->drm, "Failed to disable SAGV (%d)\n", ret); - return ret; + return; } dev_priv->sagv_status = I915_SAGV_DISABLED; - return 0; } static void skl_sagv_pre_plane_update(struct intel_atomic_state *state) @@ -3815,7 +3811,7 @@ static void skl_sagv_pre_plane_update(struct intel_atomic_state *state) return; if (!intel_can_enable_sagv(i915, new_bw_state)) - intel_disable_sagv(i915); + skl_sagv_disable(i915); } static void skl_sagv_post_plane_update(struct intel_atomic_state *state) @@ -3828,7 +3824,7 @@ static void skl_sagv_post_plane_update(struct intel_atomic_state *state) return; if (intel_can_enable_sagv(i915, new_bw_state)) - intel_enable_sagv(i915); + skl_sagv_enable(i915); } static void icl_sagv_pre_plane_update(struct intel_atomic_state *state) From 0fed4ddd18f064d2359b430c6e83ee60dd1f49b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2022 18:49:46 +0200 Subject: [PATCH 00264/11454] drm/i915: Fix PSF GV point mask when SAGV is not possible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't just mask off all the PSF GV points when SAGV gets disabled. This should in fact cause the Pcode to reject the request since at least one PSF point must remain enabled at all times. Cc: stable@vger.kernel.org Cc: Stanislav Lisovskiy Fixes: 192fbfb76744 ("drm/i915: Implement PSF GV point support") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220309164948.10671-7-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_bw.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index ad1564ca7269..adf58c58513b 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -992,7 +992,8 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) * cause. */ if (!intel_can_enable_sagv(dev_priv, new_bw_state)) { - allowed_points = BIT(max_bw_point); + allowed_points &= ADLS_PSF_PT_MASK; + allowed_points |= BIT(max_bw_point); drm_dbg_kms(&dev_priv->drm, "No SAGV, using single QGV point %d\n", max_bw_point); } From f8a1cb3ff4397c2a295712953452946b3dff70c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2022 18:49:47 +0200 Subject: [PATCH 00265/11454] drm/i915: Unconfuses QGV vs. PSF point masks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use separate bitmasks for QGV vs. PSF GV points during the computation. Makes the whole thing a lot less confusing. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220309164948.10671-8-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_bw.c | 35 ++++++++++++------------- drivers/gpu/drm/i915/i915_reg.h | 3 ++- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index adf58c58513b..b794545ff81d 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -820,7 +820,7 @@ static u16 icl_qgv_points_mask(struct drm_i915_private *i915) { unsigned int num_psf_gv_points = i915->max_bw[0].num_psf_gv_points; unsigned int num_qgv_points = i915->max_bw[0].num_qgv_points; - u16 mask = 0; + u16 qgv_points = 0, psf_points = 0; /* * We can _not_ use the whole ADLS_QGV_PT_MASK here, as PCode rejects @@ -828,12 +828,12 @@ static u16 icl_qgv_points_mask(struct drm_i915_private *i915) * So need to operate only with those returned from PCode. */ if (num_qgv_points > 0) - mask |= REG_GENMASK(num_qgv_points - 1, 0); + qgv_points = GENMASK(num_qgv_points - 1, 0); if (num_psf_gv_points > 0) - mask |= REG_GENMASK(num_psf_gv_points - 1, 0) << ADLS_PSF_PT_SHIFT; + psf_points = GENMASK(num_psf_gv_points - 1, 0); - return mask; + return ADLS_QGV_PT(qgv_points) | ADLS_PSF_PT(psf_points); } static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *changed) @@ -890,7 +890,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) unsigned int data_rate; unsigned int num_active_planes; int i, ret; - u32 allowed_points = 0; + u16 qgv_points = 0, psf_points = 0; unsigned int max_bw_point = 0, max_bw = 0; unsigned int num_qgv_points = dev_priv->max_bw[0].num_qgv_points; unsigned int num_psf_gv_points = dev_priv->max_bw[0].num_psf_gv_points; @@ -948,7 +948,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) max_bw = max_data_rate; } if (max_data_rate >= data_rate) - allowed_points |= REG_FIELD_PREP(ADLS_QGV_PT_MASK, BIT(i)); + qgv_points |= BIT(i); drm_dbg_kms(&dev_priv->drm, "QGV point %d: max bw %d required %d\n", i, max_data_rate, data_rate); @@ -958,7 +958,7 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) unsigned int max_data_rate = adl_psf_bw(dev_priv, i); if (max_data_rate >= data_rate) - allowed_points |= REG_FIELD_PREP(ADLS_PSF_PT_MASK, BIT(i)); + psf_points |= BIT(i); drm_dbg_kms(&dev_priv->drm, "PSF GV point %d: max bw %d" " required %d\n", @@ -970,20 +970,18 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) * left, so if we couldn't - simply reject the configuration for obvious * reasons. */ - if ((allowed_points & ADLS_QGV_PT_MASK) == 0) { + if (qgv_points == 0) { drm_dbg_kms(&dev_priv->drm, "No QGV points provide sufficient memory" " bandwidth %d for display configuration(%d active planes).\n", data_rate, num_active_planes); return -EINVAL; } - if (num_psf_gv_points > 0) { - if ((allowed_points & ADLS_PSF_PT_MASK) == 0) { - drm_dbg_kms(&dev_priv->drm, "No PSF GV points provide sufficient memory" - " bandwidth %d for display configuration(%d active planes).\n", - data_rate, num_active_planes); - return -EINVAL; - } + if (num_psf_gv_points > 0 && psf_points == 0) { + drm_dbg_kms(&dev_priv->drm, "No PSF GV points provide sufficient memory" + " bandwidth %d for display configuration(%d active planes).\n", + data_rate, num_active_planes); + return -EINVAL; } /* @@ -992,16 +990,17 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) * cause. */ if (!intel_can_enable_sagv(dev_priv, new_bw_state)) { - allowed_points &= ADLS_PSF_PT_MASK; - allowed_points |= BIT(max_bw_point); + qgv_points = BIT(max_bw_point); drm_dbg_kms(&dev_priv->drm, "No SAGV, using single QGV point %d\n", max_bw_point); } + /* * We store the ones which need to be masked as that is what PCode * actually accepts as a parameter. */ - new_bw_state->qgv_points_mask = ~allowed_points & + new_bw_state->qgv_points_mask = + ~(ADLS_QGV_PT(qgv_points) | ADLS_PSF_PT(psf_points)) & icl_qgv_points_mask(dev_priv); /* diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 56042d363a15..ac6b5c741289 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6720,9 +6720,10 @@ #define ICL_PCODE_SAGV_DE_MEM_SS_CONFIG 0xe #define ICL_PCODE_POINTS_RESTRICTED 0x0 #define ICL_PCODE_POINTS_RESTRICTED_MASK 0xf -#define ADLS_PSF_PT_SHIFT 8 #define ADLS_QGV_PT_MASK REG_GENMASK(7, 0) +#define ADLS_QGV_PT(x) REG_FIELD_PREP(ADLS_QGV_PT_MASK, (x)) #define ADLS_PSF_PT_MASK REG_GENMASK(10, 8) +#define ADLS_PSF_PT(x) REG_FIELD_PREP(ADLS_PSF_PT_MASK, (x)) #define GEN6_PCODE_READ_D_COMP 0x10 #define GEN6_PCODE_WRITE_D_COMP 0x11 #define ICL_PCODE_EXIT_TCCOLD 0x12 From 4bdba4f4db4cdb34c6d11e8e4030c9044046cb6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 9 Mar 2022 18:49:48 +0200 Subject: [PATCH 00266/11454] drm/i915: Rename QGV request/response bits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Name all the ICL_PCODE_SAGV_DE_MEM_SS_CONFIG request/response bits in a manner that we can actually understand what they're doing. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220309164948.10671-9-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_bw.c | 9 +++++---- drivers/gpu/drm/i915/i915_reg.h | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index b794545ff81d..395e48930b08 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -124,8 +124,8 @@ int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv, /* bspec says to keep retrying for at least 1 ms */ ret = skl_pcode_request(dev_priv, ICL_PCODE_SAGV_DE_MEM_SS_CONFIG, points_mask, - ICL_PCODE_POINTS_RESTRICTED_MASK, - ICL_PCODE_POINTS_RESTRICTED, + ICL_PCODE_REP_QGV_MASK | ADLS_PCODE_REP_PSF_MASK, + ICL_PCODE_REP_QGV_SAFE | ADLS_PCODE_REP_PSF_SAFE, 1); if (ret < 0) { @@ -833,7 +833,7 @@ static u16 icl_qgv_points_mask(struct drm_i915_private *i915) if (num_psf_gv_points > 0) psf_points = GENMASK(num_psf_gv_points - 1, 0); - return ADLS_QGV_PT(qgv_points) | ADLS_PSF_PT(psf_points); + return ICL_PCODE_REQ_QGV_PT(qgv_points) | ADLS_PCODE_REQ_PSF_PT(psf_points); } static int intel_bw_check_data_rate(struct intel_atomic_state *state, bool *changed) @@ -1000,7 +1000,8 @@ int intel_bw_atomic_check(struct intel_atomic_state *state) * actually accepts as a parameter. */ new_bw_state->qgv_points_mask = - ~(ADLS_QGV_PT(qgv_points) | ADLS_PSF_PT(psf_points)) & + ~(ICL_PCODE_REQ_QGV_PT(qgv_points) | + ADLS_PCODE_REQ_PSF_PT(psf_points)) & icl_qgv_points_mask(dev_priv); /* diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index ac6b5c741289..77c6f259eda1 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -6718,12 +6718,18 @@ #define ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point) (((point) << 16) | (0x1 << 8)) #define ADL_PCODE_MEM_SS_READ_PSF_GV_INFO ((0) | (0x2 << 8)) #define ICL_PCODE_SAGV_DE_MEM_SS_CONFIG 0xe -#define ICL_PCODE_POINTS_RESTRICTED 0x0 -#define ICL_PCODE_POINTS_RESTRICTED_MASK 0xf -#define ADLS_QGV_PT_MASK REG_GENMASK(7, 0) -#define ADLS_QGV_PT(x) REG_FIELD_PREP(ADLS_QGV_PT_MASK, (x)) -#define ADLS_PSF_PT_MASK REG_GENMASK(10, 8) -#define ADLS_PSF_PT(x) REG_FIELD_PREP(ADLS_PSF_PT_MASK, (x)) +#define ICL_PCODE_REP_QGV_MASK REG_GENMASK(1, 0) +#define ICL_PCODE_REP_QGV_SAFE REG_FIELD_PREP(ICL_PCODE_REP_QGV_MASK, 0) +#define ICL_PCODE_REP_QGV_POLL REG_FIELD_PREP(ICL_PCODE_REP_QGV_MASK, 1) +#define ICL_PCODE_REP_QGV_REJECTED REG_FIELD_PREP(ICL_PCODE_REP_QGV_MASK, 2) +#define ADLS_PCODE_REP_PSF_MASK REG_GENMASK(3, 2) +#define ADLS_PCODE_REP_PSF_SAFE REG_FIELD_PREP(ADLS_PCODE_REP_PSF_MASK, 0) +#define ADLS_PCODE_REP_PSF_POLL REG_FIELD_PREP(ADLS_PCODE_REP_PSF_MASK, 1) +#define ADLS_PCODE_REP_PSF_REJECTED REG_FIELD_PREP(ADLS_PCODE_REP_PSF_MASK, 2) +#define ICL_PCODE_REQ_QGV_PT_MASK REG_GENMASK(7, 0) +#define ICL_PCODE_REQ_QGV_PT(x) REG_FIELD_PREP(ICL_PCODE_REQ_QGV_PT_MASK, (x)) +#define ADLS_PCODE_REQ_PSF_PT_MASK REG_GENMASK(10, 8) +#define ADLS_PCODE_REQ_PSF_PT(x) REG_FIELD_PREP(ADLS_PCODE_REQ_PSF_PT_MASK, (x)) #define GEN6_PCODE_READ_D_COMP 0x10 #define GEN6_PCODE_WRITE_D_COMP 0x11 #define ICL_PCODE_EXIT_TCCOLD 0x12 From b4ac33b973233dc08a56c8ef9d3c2edeab7a4370 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Wed, 16 Mar 2022 16:45:37 -0700 Subject: [PATCH 00267/11454] drm/i915: Fix renamed struct field MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Earlier versions of commit a5b7ef27da60 ("drm/i915: Add struct to hold IP version") named "ver" as "arch" and then when it was renamed it missed the rename on MEDIA_VER_FULL() since it it's currently not used. Fixes: a5b7ef27da60 ("drm/i915: Add struct to hold IP version") Cc: José Roberto de Souza Cc: Matt Roper Signed-off-by: Lucas De Marchi Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220316234538.434357-1-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 86f95f40576b..1487e3eca77a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -947,7 +947,7 @@ static inline struct intel_gt *to_gt(struct drm_i915_private *i915) (GRAPHICS_VER(i915) >= (from) && GRAPHICS_VER(i915) <= (until)) #define MEDIA_VER(i915) (INTEL_INFO(i915)->media.ver) -#define MEDIA_VER_FULL(i915) IP_VER(INTEL_INFO(i915)->media.arch, \ +#define MEDIA_VER_FULL(i915) IP_VER(INTEL_INFO(i915)->media.ver, \ INTEL_INFO(i915)->media.rel) #define IS_MEDIA_VER(i915, from, until) \ (MEDIA_VER(i915) >= (from) && MEDIA_VER(i915) <= (until)) From 6f270e1488d7a85e0c93e6536d0073796adf8b4f Mon Sep 17 00:00:00 2001 From: Matthew Brost Date: Wed, 16 Mar 2022 16:45:38 -0700 Subject: [PATCH 00268/11454] drm/i915: Add logical mapping for video decode engines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add logical mapping for VDBOXs. This mapping is required for split-frame workloads, which otherwise fail with 00000000-F8C53528: [GUC] 0441-INVALID_ENGINE_SUBMIT_MASK ... if the application is using the logical id to reorder the engines and then using it for the batch buffer submission. It's not a big problem on media version 11 and 12 as they have only 2 instances of VCS and the logical to physical mapping is monotonically increasing - if the application is not using the logical id. Changing it for the previous platforms allows the media driver implementation for the next ones (12.50 and above) to be the same, checking the logical id. It should also not introduce any bug for the old versions of userspace not checking the id. The mapping added here is the complete map needed by XEHPSDV. Previous platforms with only 2 instances will just use a partial map and should still work. v2: Remove static from map variable (José) Cc: Matt Roper Signed-off-by: Matthew Brost [ Extend the mapping to media versions 11 and 12 and give proper justification in the commit message why ] Signed-off-by: Lucas De Marchi Acked-by: Matthew Brost Reviewed-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220316234538.434357-2-lucas.demarchi@intel.com --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index d26cef970f40..624117c55d1b 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -729,12 +729,24 @@ static void populate_logical_ids(struct intel_gt *gt, u8 *logical_ids, static void setup_logical_ids(struct intel_gt *gt, u8 *logical_ids, u8 class) { - int i; - u8 map[MAX_ENGINE_INSTANCE + 1]; + /* + * Logical to physical mapping is needed for proper support + * to split-frame feature. + */ + if (MEDIA_VER(gt->i915) >= 11 && class == VIDEO_DECODE_CLASS) { + const u8 map[] = { 0, 2, 4, 6, 1, 3, 5, 7 }; - for (i = 0; i < MAX_ENGINE_INSTANCE + 1; ++i) - map[i] = i; - populate_logical_ids(gt, logical_ids, class, map, ARRAY_SIZE(map)); + populate_logical_ids(gt, logical_ids, class, + map, ARRAY_SIZE(map)); + } else { + int i; + u8 map[MAX_ENGINE_INSTANCE + 1]; + + for (i = 0; i < MAX_ENGINE_INSTANCE + 1; ++i) + map[i] = i; + populate_logical_ids(gt, logical_ids, class, + map, ARRAY_SIZE(map)); + } } /** From fa732088378fa0492bd85f32a89f1f39b305d363 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Sat, 19 Mar 2022 01:39:31 +0200 Subject: [PATCH 00269/11454] drm/i915: Rename INTEL_REGION_LMEM with INTEL_REGION_LMEM_0 With the upcoming multitile support each tile will have its own local memory. Mark the current LMEM with the suffix '0' to emphasise that it belongs to the root tile. Suggested-by: Michal Wajdeczko Signed-off-by: Andi Shyti Reviewed-by: Michal Wajdeczko Reviewed-by: Andrzej Hajda Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220318233938.149744-2-andi.shyti@linux.intel.com --- drivers/gpu/drm/i915/display/intel_fb.c | 2 +- drivers/gpu/drm/i915/display/intel_fb_pin.c | 2 +- drivers/gpu/drm/i915/display/intel_plane_initial.c | 2 +- drivers/gpu/drm/i915/gem/i915_gem_lmem.c | 4 ++-- drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c | 6 +++--- drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c | 8 ++++---- drivers/gpu/drm/i915/gt/intel_gt.c | 2 +- drivers/gpu/drm/i915/intel_memory_region.c | 2 +- drivers/gpu/drm/i915/intel_memory_region.h | 4 ++-- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_fb.c b/drivers/gpu/drm/i915/display/intel_fb.c index 23cfe2e5ce2a..421f7238da05 100644 --- a/drivers/gpu/drm/i915/display/intel_fb.c +++ b/drivers/gpu/drm/i915/display/intel_fb.c @@ -1981,7 +1981,7 @@ intel_user_framebuffer_create(struct drm_device *dev, /* object is backed with LMEM for discrete */ i915 = to_i915(obj->base.dev); - if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM)) { + if (HAS_LMEM(i915) && !i915_gem_object_can_migrate(obj, INTEL_REGION_LMEM_0)) { /* object is "remote", not in local memory */ i915_gem_object_put(obj); return ERR_PTR(-EREMOTE); diff --git a/drivers/gpu/drm/i915/display/intel_fb_pin.c b/drivers/gpu/drm/i915/display/intel_fb_pin.c index a307b4993bcf..bd6e7c98e751 100644 --- a/drivers/gpu/drm/i915/display/intel_fb_pin.c +++ b/drivers/gpu/drm/i915/display/intel_fb_pin.c @@ -140,7 +140,7 @@ retry: if (!ret && phys_cursor) ret = i915_gem_object_attach_phys(obj, alignment); else if (!ret && HAS_LMEM(dev_priv)) - ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM); + ret = i915_gem_object_migrate(obj, &ww, INTEL_REGION_LMEM_0); /* TODO: Do we need to sync when migration becomes async? */ if (!ret) ret = i915_gem_object_pin_pages(obj); diff --git a/drivers/gpu/drm/i915/display/intel_plane_initial.c b/drivers/gpu/drm/i915/display/intel_plane_initial.c index 5c0cd0775a14..41ff7bf23e3b 100644 --- a/drivers/gpu/drm/i915/display/intel_plane_initial.c +++ b/drivers/gpu/drm/i915/display/intel_plane_initial.c @@ -72,7 +72,7 @@ initial_plane_vma(struct drm_i915_private *i915, } phys_base = pte & I915_GTT_PAGE_MASK; - mem = i915->mm.regions[INTEL_REGION_LMEM]; + mem = i915->mm.regions[INTEL_REGION_LMEM_0]; /* * We don't currently expect this to ever be placed in the diff --git a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c index 444f8268b9c5..47e43dc3a174 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_lmem.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_lmem.c @@ -100,7 +100,7 @@ __i915_gem_object_create_lmem_with_ps(struct drm_i915_private *i915, resource_size_t page_size, unsigned int flags) { - return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM], + return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM_0], size, page_size, flags); } @@ -135,6 +135,6 @@ i915_gem_object_create_lmem(struct drm_i915_private *i915, resource_size_t size, unsigned int flags) { - return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM], + return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_LMEM_0], size, 0, flags); } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c index b071a58dd6da..a342fd387d4e 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c @@ -88,7 +88,7 @@ out: static int igt_dmabuf_import_same_driver_lmem(void *arg) { struct drm_i915_private *i915 = arg; - struct intel_memory_region *lmem = i915->mm.regions[INTEL_REGION_LMEM]; + struct intel_memory_region *lmem = i915->mm.regions[INTEL_REGION_LMEM_0]; struct drm_i915_gem_object *obj; struct drm_gem_object *import; struct dma_buf *dmabuf; @@ -252,10 +252,10 @@ static int igt_dmabuf_import_same_driver_lmem_smem(void *arg) struct drm_i915_private *i915 = arg; struct intel_memory_region *regions[2]; - if (!i915->mm.regions[INTEL_REGION_LMEM]) + if (!i915->mm.regions[INTEL_REGION_LMEM_0]) return 0; - regions[0] = i915->mm.regions[INTEL_REGION_LMEM]; + regions[0] = i915->mm.regions[INTEL_REGION_LMEM_0]; regions[1] = i915->mm.regions[INTEL_REGION_SMEM]; return igt_dmabuf_import_same_driver(i915, regions, 2); } diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c index d534141b2cf7..2c63daf932de 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_migrate.c @@ -92,17 +92,17 @@ static int igt_create_migrate(struct intel_gt *gt, enum intel_region_id src, static int igt_smem_create_migrate(void *arg) { - return igt_create_migrate(arg, INTEL_REGION_LMEM, INTEL_REGION_SMEM); + return igt_create_migrate(arg, INTEL_REGION_LMEM_0, INTEL_REGION_SMEM); } static int igt_lmem_create_migrate(void *arg) { - return igt_create_migrate(arg, INTEL_REGION_SMEM, INTEL_REGION_LMEM); + return igt_create_migrate(arg, INTEL_REGION_SMEM, INTEL_REGION_LMEM_0); } static int igt_same_create_migrate(void *arg) { - return igt_create_migrate(arg, INTEL_REGION_LMEM, INTEL_REGION_LMEM); + return igt_create_migrate(arg, INTEL_REGION_LMEM_0, INTEL_REGION_LMEM_0); } static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww, @@ -152,7 +152,7 @@ static int lmem_pages_migrate_one(struct i915_gem_ww_ctx *ww, } } else { - err = i915_gem_object_migrate(obj, ww, INTEL_REGION_LMEM); + err = i915_gem_object_migrate(obj, ww, INTEL_REGION_LMEM_0); if (err) { pr_err("Object failed migration to lmem\n"); if (err) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index 57ca1e6b6203..ca875ba3e2a9 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -76,7 +76,7 @@ int intel_gt_probe_lmem(struct intel_gt *gt) return err; } - id = INTEL_REGION_LMEM; + id = INTEL_REGION_LMEM_0; mem->id = id; diff --git a/drivers/gpu/drm/i915/intel_memory_region.c b/drivers/gpu/drm/i915/intel_memory_region.c index 1c841f68169a..6a6ee2f200f8 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.c +++ b/drivers/gpu/drm/i915/intel_memory_region.c @@ -17,7 +17,7 @@ static const struct { .class = INTEL_MEMORY_SYSTEM, .instance = 0, }, - [INTEL_REGION_LMEM] = { + [INTEL_REGION_LMEM_0] = { .class = INTEL_MEMORY_LOCAL, .instance = 0, }, diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h index 56f266020285..92a821c25941 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.h +++ b/drivers/gpu/drm/i915/intel_memory_region.h @@ -29,14 +29,14 @@ enum intel_memory_type { enum intel_region_id { INTEL_REGION_SMEM = 0, - INTEL_REGION_LMEM, + INTEL_REGION_LMEM_0, INTEL_REGION_STOLEN_SMEM, INTEL_REGION_STOLEN_LMEM, INTEL_REGION_UNKNOWN, /* Should be last */ }; #define REGION_SMEM BIT(INTEL_REGION_SMEM) -#define REGION_LMEM BIT(INTEL_REGION_LMEM) +#define REGION_LMEM BIT(INTEL_REGION_LMEM_0) #define REGION_STOLEN_SMEM BIT(INTEL_REGION_STOLEN_SMEM) #define REGION_STOLEN_LMEM BIT(INTEL_REGION_STOLEN_LMEM) From b9741faadbd64db562a85dc79b31b85fa354eeb5 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Sat, 19 Mar 2022 01:39:32 +0200 Subject: [PATCH 00270/11454] drm/i915/gt: add gt_is_root() helper The "gt_is_root(struct intel_gt *gt)" helper return true if the gt is the root gt, which means that its id is 0. Return false otherwise. Suggested-by: Michal Wajdeczko Signed-off-by: Andi Shyti Reviewed-by: Michal Wajdeczko Reviewed-by: Andrzej Hajda Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220318233938.149744-3-andi.shyti@linux.intel.com --- drivers/gpu/drm/i915/gt/intel_gt.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index 996f8f3c17b9..ce471aa5c83d 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -19,6 +19,11 @@ struct drm_printer; ##__VA_ARGS__); \ } while (0) +static inline bool gt_is_root(struct intel_gt *gt) +{ + return !gt->info.id; +} + static inline struct intel_gt *uc_to_gt(struct intel_uc *uc) { return container_of(uc, struct intel_gt, uc); From bec68cc9ea42d853f00da347793cefe49575a574 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Sat, 19 Mar 2022 01:39:33 +0200 Subject: [PATCH 00271/11454] drm/i915: Prepare for multiple GTs On a multi-tile platform, each tile has its own registers + GGTT space, and BAR 0 is extended to cover all of them. Up to four GTs are supported in i915->gt[], with slot zero shadowing the existing i915->gt0 to enable source compatibility with legacy driver paths. A for_each_gt macro is added to iterate over the GTs and will be used by upcoming patches that convert various parts of the driver to be multi-gt aware. Only the primary/root tile is initialized for now; the other tiles will be detected and plugged in by future patches once the necessary infrastructure is in place to handle them. Signed-off-by: Abdiel Janulgue Signed-off-by: Daniele Ceraolo Spurio Signed-off-by: Tvrtko Ursulin Signed-off-by: Matt Roper Signed-off-by: Andi Shyti Cc: Daniele Ceraolo Spurio Cc: Joonas Lahtinen Cc: Matthew Auld Reviewed-by: Matt Roper Reviewed-by: Andrzej Hajda Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220318233938.149744-4-andi.shyti@linux.intel.com --- drivers/gpu/drm/i915/gt/intel_gt.c | 133 ++++++++++++++++-- drivers/gpu/drm/i915/gt/intel_gt.h | 17 ++- drivers/gpu/drm/i915/gt/intel_gt_pm.c | 9 +- drivers/gpu/drm/i915/gt/intel_gt_types.h | 7 + drivers/gpu/drm/i915/i915_driver.c | 28 ++-- drivers/gpu/drm/i915/i915_drv.h | 6 + drivers/gpu/drm/i915/intel_memory_region.h | 3 + drivers/gpu/drm/i915/intel_uncore.c | 11 +- drivers/gpu/drm/i915/intel_uncore.h | 3 +- .../gpu/drm/i915/selftests/mock_gem_device.c | 13 +- 10 files changed, 184 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index ca875ba3e2a9..cfac4a913642 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -29,7 +29,7 @@ #include "intel_uncore.h" #include "shmem_utils.h" -void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) +static void __intel_gt_init_early(struct intel_gt *gt) { spin_lock_init(>->irq_lock); @@ -51,17 +51,23 @@ void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) intel_rps_init_early(>->rps); } -void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915) +/* Preliminary initialization of Tile 0 */ +void intel_root_gt_init_early(struct drm_i915_private *i915) { + struct intel_gt *gt = to_gt(i915); + gt->i915 = i915; gt->uncore = &i915->uncore; + + __intel_gt_init_early(gt); } -int intel_gt_probe_lmem(struct intel_gt *gt) +static int intel_gt_probe_lmem(struct intel_gt *gt) { struct drm_i915_private *i915 = gt->i915; + unsigned int instance = gt->info.id; + int id = INTEL_REGION_LMEM_0 + instance; struct intel_memory_region *mem; - int id; int err; mem = intel_gt_setup_lmem(gt); @@ -76,9 +82,8 @@ int intel_gt_probe_lmem(struct intel_gt *gt) return err; } - id = INTEL_REGION_LMEM_0; - mem->id = id; + mem->instance = instance; intel_memory_region_set_name(mem, "local%u", mem->instance); @@ -807,16 +812,21 @@ void intel_gt_driver_release(struct intel_gt *gt) intel_gt_fini_hwconfig(gt); } -void intel_gt_driver_late_release(struct intel_gt *gt) +void intel_gt_driver_late_release_all(struct drm_i915_private *i915) { + struct intel_gt *gt; + unsigned int id; + /* We need to wait for inflight RCU frees to release their grip */ rcu_barrier(); - intel_uc_driver_late_release(>->uc); - intel_gt_fini_requests(gt); - intel_gt_fini_reset(gt); - intel_gt_fini_timelines(gt); - intel_engines_free(gt); + for_each_gt(gt, i915, id) { + intel_uc_driver_late_release(>->uc); + intel_gt_fini_requests(gt); + intel_gt_fini_reset(gt); + intel_gt_fini_timelines(gt); + intel_engines_free(gt); + } } /** @@ -1013,6 +1023,105 @@ void intel_gt_report_steering(struct drm_printer *p, struct intel_gt *gt, } } +static int intel_gt_tile_setup(struct intel_gt *gt, phys_addr_t phys_addr) +{ + int ret; + + if (!gt_is_root(gt)) { + struct intel_uncore_mmio_debug *mmio_debug; + struct intel_uncore *uncore; + + uncore = kzalloc(sizeof(*uncore), GFP_KERNEL); + if (!uncore) + return -ENOMEM; + + mmio_debug = kzalloc(sizeof(*mmio_debug), GFP_KERNEL); + if (!mmio_debug) { + kfree(uncore); + return -ENOMEM; + } + + gt->uncore = uncore; + gt->uncore->debug = mmio_debug; + + __intel_gt_init_early(gt); + } + + intel_uncore_init_early(gt->uncore, gt); + + ret = intel_uncore_setup_mmio(gt->uncore, phys_addr); + if (ret) + return ret; + + gt->phys_addr = phys_addr; + + return 0; +} + +static void +intel_gt_tile_cleanup(struct intel_gt *gt) +{ + intel_uncore_cleanup_mmio(gt->uncore); + + if (!gt_is_root(gt)) { + kfree(gt->uncore->debug); + kfree(gt->uncore); + kfree(gt); + } +} + +int intel_gt_probe_all(struct drm_i915_private *i915) +{ + struct pci_dev *pdev = to_pci_dev(i915->drm.dev); + struct intel_gt *gt = &i915->gt0; + phys_addr_t phys_addr; + unsigned int mmio_bar; + int ret; + + mmio_bar = GRAPHICS_VER(i915) == 2 ? 1 : 0; + phys_addr = pci_resource_start(pdev, mmio_bar); + + /* + * We always have at least one primary GT on any device + * and it has been already initialized early during probe + * in i915_driver_probe() + */ + ret = intel_gt_tile_setup(gt, phys_addr); + if (ret) + return ret; + + i915->gt[0] = gt; + + /* TODO: add more tiles */ + return 0; +} + +int intel_gt_tiles_init(struct drm_i915_private *i915) +{ + struct intel_gt *gt; + unsigned int id; + int ret; + + for_each_gt(gt, i915, id) { + ret = intel_gt_probe_lmem(gt); + if (ret) + return ret; + } + + return 0; +} + +void intel_gt_release_all(struct drm_i915_private *i915) +{ + struct intel_gt *gt; + unsigned int id; + + for_each_gt(gt, i915, id) { + intel_gt_tile_cleanup(gt); + i915->gt[id] = NULL; + } +} + void intel_gt_info_print(const struct intel_gt_info *info, struct drm_printer *p) { diff --git a/drivers/gpu/drm/i915/gt/intel_gt.h b/drivers/gpu/drm/i915/gt/intel_gt.h index ce471aa5c83d..e76168e10a21 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.h +++ b/drivers/gpu/drm/i915/gt/intel_gt.h @@ -39,10 +39,8 @@ static inline struct intel_gt *huc_to_gt(struct intel_huc *huc) return container_of(huc, struct intel_gt, uc.huc); } -void intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915); -void __intel_gt_init_early(struct intel_gt *gt, struct drm_i915_private *i915); +void intel_root_gt_init_early(struct drm_i915_private *i915); int intel_gt_assign_ggtt(struct intel_gt *gt); -int intel_gt_probe_lmem(struct intel_gt *gt); int intel_gt_init_mmio(struct intel_gt *gt); int __must_check intel_gt_init_hw(struct intel_gt *gt); int intel_gt_init(struct intel_gt *gt); @@ -52,7 +50,7 @@ void intel_gt_driver_unregister(struct intel_gt *gt); void intel_gt_driver_remove(struct intel_gt *gt); void intel_gt_driver_release(struct intel_gt *gt); -void intel_gt_driver_late_release(struct intel_gt *gt); +void intel_gt_driver_late_release_all(struct drm_i915_private *i915); int intel_gt_wait_for_idle(struct intel_gt *gt, long timeout); @@ -97,6 +95,17 @@ u32 intel_gt_read_register(struct intel_gt *gt, i915_reg_t reg); void intel_gt_report_steering(struct drm_printer *p, struct intel_gt *gt, bool dump_table); + +int intel_gt_probe_all(struct drm_i915_private *i915); +int intel_gt_tiles_init(struct drm_i915_private *i915); +void intel_gt_release_all(struct drm_i915_private *i915); + +#define for_each_gt(gt__, i915__, id__) \ + for ((id__) = 0; \ + (id__) < I915_MAX_GT; \ + (id__)++) \ + for_each_if(((gt__) = (i915__)->gt[(id__)])) + void intel_gt_info_print(const struct intel_gt_info *info, struct drm_printer *p); diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_pm.c index c0fa41e4c803..e66479d33bc3 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm.c @@ -128,7 +128,14 @@ static const struct intel_wakeref_ops wf_ops = { void intel_gt_pm_init_early(struct intel_gt *gt) { - intel_wakeref_init(>->wakeref, gt->uncore->rpm, &wf_ops); + /* + * We access the runtime_pm structure via gt->i915 here rather than + * gt->uncore as we do elsewhere in the file because gt->uncore is not + * yet initialized for all tiles at this point in the driver startup. + * runtime_pm is per-device rather than per-tile, so this is still the + * correct structure. + */ + intel_wakeref_init(>->wakeref, >->i915->runtime_pm, &wf_ops); seqcount_mutex_init(>->stats.lock, >->wakeref.mutex); } diff --git a/drivers/gpu/drm/i915/gt/intel_gt_types.h b/drivers/gpu/drm/i915/gt/intel_gt_types.h index bbba885d45bd..937b2e1a305e 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_types.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_types.h @@ -188,7 +188,14 @@ struct intel_gt { u8 instanceid; } default_steering; + /* + * Base of per-tile GTTMMADR where we can derive the MMIO and the GGTT. + */ + phys_addr_t phys_addr; + struct intel_gt_info { + unsigned int id; + intel_engine_mask_t engine_mask; u32 l3bank_mask; diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 62b3f332bbf5..6f8762b26b1c 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -320,9 +320,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) intel_device_info_subplatform_init(dev_priv); intel_step_init(dev_priv); - intel_gt_init_early(to_gt(dev_priv), dev_priv); intel_uncore_mmio_debug_init_early(&dev_priv->mmio_debug); - intel_uncore_init_early(&dev_priv->uncore, to_gt(dev_priv)); spin_lock_init(&dev_priv->irq_lock); spin_lock_init(&dev_priv->gpu_error.lock); @@ -353,7 +351,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) intel_wopcm_init_early(&dev_priv->wopcm); - __intel_gt_init_early(to_gt(dev_priv), dev_priv); + intel_root_gt_init_early(dev_priv); i915_gem_init_early(dev_priv); @@ -374,7 +372,7 @@ static int i915_driver_early_probe(struct drm_i915_private *dev_priv) err_gem: i915_gem_cleanup_early(dev_priv); - intel_gt_driver_late_release(to_gt(dev_priv)); + intel_gt_driver_late_release_all(dev_priv); intel_region_ttm_device_fini(dev_priv); err_ttm: vlv_suspend_cleanup(dev_priv); @@ -393,7 +391,7 @@ static void i915_driver_late_release(struct drm_i915_private *dev_priv) intel_irq_fini(dev_priv); intel_power_domains_cleanup(dev_priv); i915_gem_cleanup_early(dev_priv); - intel_gt_driver_late_release(to_gt(dev_priv)); + intel_gt_driver_late_release_all(dev_priv); intel_region_ttm_device_fini(dev_priv); vlv_suspend_cleanup(dev_priv); i915_workqueues_cleanup(dev_priv); @@ -424,13 +422,9 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) if (ret < 0) return ret; - ret = intel_uncore_setup_mmio(&dev_priv->uncore); - if (ret < 0) - goto err_bridge; - ret = intel_uncore_init_mmio(&dev_priv->uncore); if (ret) - goto err_mmio; + return ret; /* Try to make sure MCHBAR is enabled before poking at it */ intel_setup_mchbar(dev_priv); @@ -448,9 +442,6 @@ static int i915_driver_mmio_probe(struct drm_i915_private *dev_priv) err_uncore: intel_teardown_mchbar(dev_priv); intel_uncore_fini_mmio(&dev_priv->uncore); -err_mmio: - intel_uncore_cleanup_mmio(&dev_priv->uncore); -err_bridge: pci_dev_put(dev_priv->bridge_dev); return ret; @@ -464,7 +455,6 @@ static void i915_driver_mmio_release(struct drm_i915_private *dev_priv) { intel_teardown_mchbar(dev_priv); intel_uncore_fini_mmio(&dev_priv->uncore); - intel_uncore_cleanup_mmio(&dev_priv->uncore); pci_dev_put(dev_priv->bridge_dev); } @@ -597,7 +587,7 @@ static int i915_driver_hw_probe(struct drm_i915_private *dev_priv) if (ret) goto err_ggtt; - ret = intel_gt_probe_lmem(to_gt(dev_priv)); + ret = intel_gt_tiles_init(dev_priv); if (ret) goto err_mem_regions; @@ -847,10 +837,14 @@ int i915_driver_probe(struct pci_dev *pdev, const struct pci_device_id *ent) intel_vgpu_detect(i915); - ret = i915_driver_mmio_probe(i915); + ret = intel_gt_probe_all(i915); if (ret < 0) goto out_runtime_pm_put; + ret = i915_driver_mmio_probe(i915); + if (ret < 0) + goto out_tiles_cleanup; + ret = i915_driver_hw_probe(i915); if (ret < 0) goto out_cleanup_mmio; @@ -907,6 +901,8 @@ out_cleanup_hw: i915_ggtt_driver_late_release(i915); out_cleanup_mmio: i915_driver_mmio_release(i915); +out_tiles_cleanup: + intel_gt_release_all(i915); out_runtime_pm_put: enable_rpm_wakeref_asserts(&i915->runtime_pm); i915_driver_late_release(i915); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1487e3eca77a..64977f0833b0 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -808,6 +808,12 @@ struct drm_i915_private { /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ struct intel_gt gt0; + /* + * i915->gt[0] == &i915->gt0 + */ +#define I915_MAX_GT 4 + struct intel_gt *gt[I915_MAX_GT]; + struct { struct i915_gem_contexts { spinlock_t lock; /* locks list */ diff --git a/drivers/gpu/drm/i915/intel_memory_region.h b/drivers/gpu/drm/i915/intel_memory_region.h index 92a821c25941..2d84aff53efd 100644 --- a/drivers/gpu/drm/i915/intel_memory_region.h +++ b/drivers/gpu/drm/i915/intel_memory_region.h @@ -30,6 +30,9 @@ enum intel_memory_type { enum intel_region_id { INTEL_REGION_SMEM = 0, INTEL_REGION_LMEM_0, + INTEL_REGION_LMEM_1, + INTEL_REGION_LMEM_2, + INTEL_REGION_LMEM_3, INTEL_REGION_STOLEN_SMEM, INTEL_REGION_STOLEN_LMEM, INTEL_REGION_UNKNOWN, /* Should be last */ diff --git a/drivers/gpu/drm/i915/intel_uncore.c b/drivers/gpu/drm/i915/intel_uncore.c index ef8ffc01ad19..8b9caaaacc21 100644 --- a/drivers/gpu/drm/i915/intel_uncore.c +++ b/drivers/gpu/drm/i915/intel_uncore.c @@ -2039,14 +2039,11 @@ static int i915_pmic_bus_access_notifier(struct notifier_block *nb, return NOTIFY_OK; } -int intel_uncore_setup_mmio(struct intel_uncore *uncore) +int intel_uncore_setup_mmio(struct intel_uncore *uncore, phys_addr_t phys_addr) { struct drm_i915_private *i915 = uncore->i915; - struct pci_dev *pdev = to_pci_dev(i915->drm.dev); - int mmio_bar; int mmio_size; - mmio_bar = GRAPHICS_VER(i915) == 2 ? 1 : 0; /* * Before gen4, the registers and the GTT are behind different BARs. * However, from gen4 onwards, the registers and the GTT are shared @@ -2063,7 +2060,7 @@ int intel_uncore_setup_mmio(struct intel_uncore *uncore) else mmio_size = 2 * 1024 * 1024; - uncore->regs = pci_iomap(pdev, mmio_bar, mmio_size); + uncore->regs = ioremap(phys_addr, mmio_size); if (uncore->regs == NULL) { drm_err(&i915->drm, "failed to map registers\n"); return -EIO; @@ -2074,9 +2071,7 @@ int intel_uncore_setup_mmio(struct intel_uncore *uncore) void intel_uncore_cleanup_mmio(struct intel_uncore *uncore) { - struct pci_dev *pdev = to_pci_dev(uncore->i915->drm.dev); - - pci_iounmap(pdev, uncore->regs); + iounmap(uncore->regs); } void intel_uncore_init_early(struct intel_uncore *uncore, diff --git a/drivers/gpu/drm/i915/intel_uncore.h b/drivers/gpu/drm/i915/intel_uncore.h index 9a760952d46a..52fe3d89dd2b 100644 --- a/drivers/gpu/drm/i915/intel_uncore.h +++ b/drivers/gpu/drm/i915/intel_uncore.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "i915_reg_defs.h" @@ -221,7 +222,7 @@ void intel_uncore_mmio_debug_init_early(struct intel_uncore_mmio_debug *mmio_debug); void intel_uncore_init_early(struct intel_uncore *uncore, struct intel_gt *gt); -int intel_uncore_setup_mmio(struct intel_uncore *uncore); +int intel_uncore_setup_mmio(struct intel_uncore *uncore, phys_addr_t phys_addr); int intel_uncore_init_mmio(struct intel_uncore *uncore); void intel_uncore_prune_engine_fw_domains(struct intel_uncore *uncore, struct intel_gt *gt); diff --git a/drivers/gpu/drm/i915/selftests/mock_gem_device.c b/drivers/gpu/drm/i915/selftests/mock_gem_device.c index 573d9b2e1a4a..9c31a16f8380 100644 --- a/drivers/gpu/drm/i915/selftests/mock_gem_device.c +++ b/drivers/gpu/drm/i915/selftests/mock_gem_device.c @@ -73,7 +73,7 @@ static void mock_device_release(struct drm_device *dev) destroy_workqueue(i915->wq); intel_region_ttm_device_fini(i915); - intel_gt_driver_late_release(to_gt(i915)); + intel_gt_driver_late_release_all(i915); intel_memory_regions_driver_release(i915); drm_mode_config_cleanup(&i915->drm); @@ -112,6 +112,11 @@ static struct dev_pm_domain pm_domain = { }, }; +static void mock_gt_probe(struct drm_i915_private *i915) +{ + i915->gt[0] = &i915->gt0; +} + struct drm_i915_private *mock_gem_device(void) { #if IS_ENABLED(CONFIG_IOMMU_API) && defined(CONFIG_INTEL_IOMMU) @@ -180,11 +185,11 @@ struct drm_i915_private *mock_gem_device(void) spin_lock_init(&i915->gpu_error.lock); i915_gem_init__mm(i915); - intel_gt_init_early(to_gt(i915), i915); - __intel_gt_init_early(to_gt(i915), i915); + intel_root_gt_init_early(i915); mock_uncore_init(&i915->uncore, i915); atomic_inc(&to_gt(i915)->wakeref.count); /* disable; no hw support */ to_gt(i915)->awake = -ENODEV; + mock_gt_probe(i915); ret = intel_region_ttm_device_init(i915); if (ret) @@ -229,7 +234,7 @@ err_unlock: err_drv: intel_region_ttm_device_fini(i915); err_ttm: - intel_gt_driver_late_release(to_gt(i915)); + intel_gt_driver_late_release_all(i915); intel_memory_regions_driver_release(i915); drm_mode_config_cleanup(&i915->drm); mock_destroy_device(i915); From b770bcfae9ad816cd9efce6b0fff4dab47084578 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Sat, 19 Mar 2022 01:39:34 +0200 Subject: [PATCH 00272/11454] drm/i915/gt: create per-tile sysfs interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that we have tiles we want each of them to have its own interface. A directory "gt/" is created under "cardN/" that will contain as many diroctories as the tiles. In the coming patches tile related interfaces will be added. For now the sysfs gt structure simply has an id interface related to the current tile count. The directory structure will follow this scheme: /sys/.../card0 └── gt    ├── gt0    │   └── id : : └─- gtN       └── id This new set of interfaces will be a basic tool for system managers and administrators when using i915. Signed-off-by: Andi Shyti Cc: Chris Wilson Cc: Matt Roper Cc: Sujaritha Sundaresan Cc: Tvrtko Ursulin Reviewed-by: Sujaritha Sundaresan Reviewed-by: Andrzej Hajda Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220318233938.149744-5-andi.shyti@linux.intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gt/intel_gt.c | 2 + drivers/gpu/drm/i915/gt/intel_gt_sysfs.c | 103 +++++++++++++++++++++++ drivers/gpu/drm/i915/gt/intel_gt_sysfs.h | 34 ++++++++ drivers/gpu/drm/i915/i915_drv.h | 2 + drivers/gpu/drm/i915/i915_sysfs.c | 7 +- drivers/gpu/drm/i915/i915_sysfs.h | 3 + 7 files changed, 151 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_sysfs.c create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_sysfs.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 61b078bd1b32..f68d62d2bbea 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -105,6 +105,7 @@ gt-y += \ gt/intel_gt_pm_debugfs.o \ gt/intel_gt_pm_irq.o \ gt/intel_gt_requests.o \ + gt/intel_gt_sysfs.o \ gt/intel_gtt.o \ gt/intel_llc.o \ gt/intel_lrc.o \ diff --git a/drivers/gpu/drm/i915/gt/intel_gt.c b/drivers/gpu/drm/i915/gt/intel_gt.c index cfac4a913642..5001a6168d56 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt.c +++ b/drivers/gpu/drm/i915/gt/intel_gt.c @@ -26,6 +26,7 @@ #include "intel_rc6.h" #include "intel_renderstate.h" #include "intel_rps.h" +#include "intel_gt_sysfs.h" #include "intel_uncore.h" #include "shmem_utils.h" @@ -458,6 +459,7 @@ void intel_gt_driver_register(struct intel_gt *gt) intel_rps_driver_register(>->rps); intel_gt_debugfs_register(gt); + intel_gt_sysfs_register(gt); } static int intel_gt_init_scratch(struct intel_gt *gt, unsigned int size) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c new file mode 100644 index 000000000000..d50831961294 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c @@ -0,0 +1,103 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + */ + +#include +#include +#include +#include +#include + +#include "i915_drv.h" +#include "i915_sysfs.h" +#include "intel_gt.h" +#include "intel_gt_sysfs.h" +#include "intel_gt_types.h" +#include "intel_rc6.h" + +bool is_object_gt(struct kobject *kobj) +{ + return !strncmp(kobj->name, "gt", 2); +} + +static struct intel_gt *kobj_to_gt(struct kobject *kobj) +{ + return container_of(kobj, struct kobj_gt, base)->gt; +} + +struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, + const char *name) +{ + struct kobject *kobj = &dev->kobj; + + /* + * We are interested at knowing from where the interface + * has been called, whether it's called from gt/ or from + * the parent directory. + * From the interface position it depends also the value of + * the private data. + * If the interface is called from gt/ then private data is + * of the "struct intel_gt *" type, otherwise it's * a + * "struct drm_i915_private *" type. + */ + if (!is_object_gt(kobj)) { + struct drm_i915_private *i915 = kdev_minor_to_i915(dev); + + return to_gt(i915); + } + + return kobj_to_gt(kobj); +} + +static ssize_t id_show(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); + + return sysfs_emit(buf, "%u\n", gt->info.id); +} +static DEVICE_ATTR_RO(id); + +static struct attribute *id_attrs[] = { + &dev_attr_id.attr, + NULL, +}; +ATTRIBUTE_GROUPS(id); + +static void kobj_gt_release(struct kobject *kobj) +{ + kfree(kobj); +} + +static struct kobj_type kobj_gt_type = { + .release = kobj_gt_release, + .sysfs_ops = &kobj_sysfs_ops, + .default_groups = id_groups, +}; + +void intel_gt_sysfs_register(struct intel_gt *gt) +{ + struct kobj_gt *kg; + + kg = kzalloc(sizeof(*kg), GFP_KERNEL); + if (!kg) + goto exit_fail; + + kobject_init(&kg->base, &kobj_gt_type); + kg->gt = gt; + + /* xfer ownership to sysfs tree */ + if (kobject_add(&kg->base, gt->i915->sysfs_gt, "gt%d", gt->info.id)) + goto exit_kobj_put; + + return; + +exit_kobj_put: + kobject_put(&kg->base); + +exit_fail: + drm_warn(>->i915->drm, + "failed to initialize gt%d sysfs root\n", gt->info.id); +} diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs.h b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.h new file mode 100644 index 000000000000..9471b26752cf --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.h @@ -0,0 +1,34 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __SYSFS_GT_H__ +#define __SYSFS_GT_H__ + +#include +#include + +#include "i915_gem.h" /* GEM_BUG_ON() */ + +struct intel_gt; + +struct kobj_gt { + struct kobject base; + struct intel_gt *gt; +}; + +bool is_object_gt(struct kobject *kobj); + +struct drm_i915_private *kobj_to_i915(struct kobject *kobj); + +struct kobject * +intel_gt_create_kobj(struct intel_gt *gt, + struct kobject *dir, + const char *name); + +void intel_gt_sysfs_register(struct intel_gt *gt); +struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, + const char *name); + +#endif /* SYSFS_GT_H */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 64977f0833b0..8c99a3c58a5a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -814,6 +814,8 @@ struct drm_i915_private { #define I915_MAX_GT 4 struct intel_gt *gt[I915_MAX_GT]; + struct kobject *sysfs_gt; + struct { struct i915_gem_contexts { spinlock_t lock; /* locks list */ diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index a4d1759375b9..5ff915b93c21 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -39,7 +39,7 @@ #include "i915_sysfs.h" #include "intel_pm.h" -static inline struct drm_i915_private *kdev_minor_to_i915(struct device *kdev) +struct drm_i915_private *kdev_minor_to_i915(struct device *kdev) { struct drm_minor *minor = dev_get_drvdata(kdev); return to_i915(minor->dev); @@ -538,6 +538,11 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) if (ret) drm_err(&dev_priv->drm, "RPS sysfs setup failed\n"); + dev_priv->sysfs_gt = kobject_create_and_add("gt", &kdev->kobj); + if (!dev_priv->sysfs_gt) + drm_warn(&dev_priv->drm, + "failed to register GT sysfs directory\n"); + i915_setup_error_capture(kdev); intel_engines_add_sysfs(dev_priv); diff --git a/drivers/gpu/drm/i915/i915_sysfs.h b/drivers/gpu/drm/i915/i915_sysfs.h index 41afd4366416..243a17741e3f 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.h +++ b/drivers/gpu/drm/i915/i915_sysfs.h @@ -6,8 +6,11 @@ #ifndef __I915_SYSFS_H__ #define __I915_SYSFS_H__ +struct device; struct drm_i915_private; +struct drm_i915_private *kdev_minor_to_i915(struct device *kdev); + void i915_setup_sysfs(struct drm_i915_private *i915); void i915_teardown_sysfs(struct drm_i915_private *i915); From 80cf8af17af042cd4b287716aca917422053f873 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Sat, 19 Mar 2022 01:39:35 +0200 Subject: [PATCH 00273/11454] drm/i915/gt: Create per-tile RC6 sysfs interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now tiles have their own sysfs interfaces under the gt/ directory. Because RC6 is a property that can be configured on a tile basis, then each tile should have its own interface The new sysfs structure will have a similar layout for the 4 tile case: /sys/.../card0 ├── gt │   ├── gt0 │   │   ├── id │   │   ├── rc6_enable │   │   ├── rc6_residency_ms . . . . . . . . │   └── gtN │   ├── id │   ├── rc6_enable │   ├── rc6_residency_ms │ . │ . │ └── power/ -+ ├── rc6_enable | Original interface ├── rc6_residency_ms +-> kept as existing ABI; . | it multiplexes over . | the GTs -+ The existing interfaces have been kept in their original location to preserve the existing ABI. They act on all the GTs: when reading they provide the average value from all the GTs. This patch is not really adding exposing new interfaces (new ABI) other than adapting the existing one to more tiles. In any case this new set of interfaces will be a basic tool for system managers and administrators when using i915. Signed-off-by: Andi Shyti Signed-off-by: Lucas De Marchi Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Matt Roper Cc: Sujaritha Sundaresan Cc: Tvrtko Ursulin Reviewed-by: Andrzej Hajda Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220318233938.149744-6-andi.shyti@linux.intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gt/intel_gt_sysfs.c | 19 ++ drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 244 ++++++++++++++++++++ drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.h | 15 ++ drivers/gpu/drm/i915/i915_sysfs.c | 128 ---------- 5 files changed, 279 insertions(+), 128 deletions(-) create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c create mode 100644 drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index f68d62d2bbea..9801aaa9885d 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -106,6 +106,7 @@ gt-y += \ gt/intel_gt_pm_irq.o \ gt/intel_gt_requests.o \ gt/intel_gt_sysfs.o \ + gt/intel_gt_sysfs_pm.o \ gt/intel_gtt.o \ gt/intel_llc.o \ gt/intel_lrc.o \ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c index d50831961294..8ec8bc660c8c 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs.c @@ -13,6 +13,7 @@ #include "i915_sysfs.h" #include "intel_gt.h" #include "intel_gt_sysfs.h" +#include "intel_gt_sysfs_pm.h" #include "intel_gt_types.h" #include "intel_rc6.h" @@ -50,6 +51,11 @@ struct intel_gt *intel_gt_sysfs_get_drvdata(struct device *dev, return kobj_to_gt(kobj); } +static struct kobject *gt_get_parent_obj(struct intel_gt *gt) +{ + return >->i915->drm.primary->kdev->kobj; +} + static ssize_t id_show(struct device *dev, struct device_attribute *attr, char *buf) @@ -81,6 +87,17 @@ void intel_gt_sysfs_register(struct intel_gt *gt) { struct kobj_gt *kg; + /* + * We need to make things right with the + * ABI compatibility. The files were originally + * generated under the parent directory. + * + * We generate the files only for gt 0 + * to avoid duplicates. + */ + if (gt_is_root(gt)) + intel_gt_sysfs_pm_init(gt, gt_get_parent_obj(gt)); + kg = kzalloc(sizeof(*kg), GFP_KERNEL); if (!kg) goto exit_fail; @@ -92,6 +109,8 @@ void intel_gt_sysfs_register(struct intel_gt *gt) if (kobject_add(&kg->base, gt->i915->sysfs_gt, "gt%d", gt->info.id)) goto exit_kobj_put; + intel_gt_sysfs_pm_init(gt, &kg->base); + return; exit_kobj_put: diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c new file mode 100644 index 000000000000..144b004e4de8 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c @@ -0,0 +1,244 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2022 Intel Corporation + */ + +#include +#include +#include + +#include "i915_drv.h" +#include "i915_sysfs.h" +#include "intel_gt.h" +#include "intel_gt_regs.h" +#include "intel_gt_sysfs.h" +#include "intel_gt_sysfs_pm.h" +#include "intel_rc6.h" + +#ifdef CONFIG_PM +enum intel_gt_sysfs_op { + INTEL_GT_SYSFS_MIN = 0, + INTEL_GT_SYSFS_MAX, +}; + +static u32 +sysfs_gt_attribute_r_func(struct device *dev, struct device_attribute *attr, + u32 (func)(struct intel_gt *gt), + enum intel_gt_sysfs_op op) +{ + struct intel_gt *gt; + u32 ret; + + ret = (op == INTEL_GT_SYSFS_MAX) ? 0 : (u32) -1; + + if (!is_object_gt(&dev->kobj)) { + int i; + struct drm_i915_private *i915 = kdev_minor_to_i915(dev); + + for_each_gt(gt, i915, i) { + u32 val = func(gt); + + switch (op) { + case INTEL_GT_SYSFS_MIN: + if (val < ret) + ret = val; + break; + + case INTEL_GT_SYSFS_MAX: + if (val > ret) + ret = val; + break; + } + } + } else { + gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); + ret = func(gt); + } + + return ret; +} + +/* RC6 interfaces will show the minimum RC6 residency value */ +#define sysfs_gt_attribute_r_min_func(d, a, f) \ + sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MIN) + +#define sysfs_gt_attribute_r_max_func(d, a, f) \ + sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MAX) + +static u32 get_residency(struct intel_gt *gt, i915_reg_t reg) +{ + intel_wakeref_t wakeref; + u64 res = 0; + + with_intel_runtime_pm(gt->uncore->rpm, wakeref) + res = intel_rc6_residency_us(>->rc6, reg); + + return DIV_ROUND_CLOSEST_ULL(res, 1000); +} + +static ssize_t rc6_enable_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); + u8 mask = 0; + + if (HAS_RC6(gt->i915)) + mask |= BIT(0); + if (HAS_RC6p(gt->i915)) + mask |= BIT(1); + if (HAS_RC6pp(gt->i915)) + mask |= BIT(2); + + return sysfs_emit(buff, "%x\n", mask); +} + +static u32 __rc6_residency_ms_show(struct intel_gt *gt) +{ + return get_residency(gt, GEN6_GT_GFX_RC6); +} + +static ssize_t rc6_residency_ms_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + u32 rc6_residency = sysfs_gt_attribute_r_min_func(dev, attr, + __rc6_residency_ms_show); + + return sysfs_emit(buff, "%u\n", rc6_residency); +} + +static u32 __rc6p_residency_ms_show(struct intel_gt *gt) +{ + return get_residency(gt, GEN6_GT_GFX_RC6p); +} + +static ssize_t rc6p_residency_ms_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + u32 rc6p_residency = sysfs_gt_attribute_r_min_func(dev, attr, + __rc6p_residency_ms_show); + + return sysfs_emit(buff, "%u\n", rc6p_residency); +} + +static u32 __rc6pp_residency_ms_show(struct intel_gt *gt) +{ + return get_residency(gt, GEN6_GT_GFX_RC6pp); +} + +static ssize_t rc6pp_residency_ms_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + u32 rc6pp_residency = sysfs_gt_attribute_r_min_func(dev, attr, + __rc6pp_residency_ms_show); + + return sysfs_emit(buff, "%u\n", rc6pp_residency); +} + +static u32 __media_rc6_residency_ms_show(struct intel_gt *gt) +{ + return get_residency(gt, VLV_GT_MEDIA_RC6); +} + +static ssize_t media_rc6_residency_ms_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + u32 rc6_residency = sysfs_gt_attribute_r_min_func(dev, attr, + __media_rc6_residency_ms_show); + + return sysfs_emit(buff, "%u\n", rc6_residency); +} + +static DEVICE_ATTR_RO(rc6_enable); +static DEVICE_ATTR_RO(rc6_residency_ms); +static DEVICE_ATTR_RO(rc6p_residency_ms); +static DEVICE_ATTR_RO(rc6pp_residency_ms); +static DEVICE_ATTR_RO(media_rc6_residency_ms); + +static struct attribute *rc6_attrs[] = { + &dev_attr_rc6_enable.attr, + &dev_attr_rc6_residency_ms.attr, + NULL +}; + +static struct attribute *rc6p_attrs[] = { + &dev_attr_rc6p_residency_ms.attr, + &dev_attr_rc6pp_residency_ms.attr, + NULL +}; + +static struct attribute *media_rc6_attrs[] = { + &dev_attr_media_rc6_residency_ms.attr, + NULL +}; + +static const struct attribute_group rc6_attr_group[] = { + { .attrs = rc6_attrs, }, + { .name = power_group_name, .attrs = rc6_attrs, }, +}; + +static const struct attribute_group rc6p_attr_group[] = { + { .attrs = rc6p_attrs, }, + { .name = power_group_name, .attrs = rc6p_attrs, }, +}; + +static const struct attribute_group media_rc6_attr_group[] = { + { .attrs = media_rc6_attrs, }, + { .name = power_group_name, .attrs = media_rc6_attrs, }, +}; + +static int __intel_gt_sysfs_create_group(struct kobject *kobj, + const struct attribute_group *grp) +{ + return is_object_gt(kobj) ? + sysfs_create_group(kobj, &grp[0]) : + sysfs_merge_group(kobj, &grp[1]); +} + +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj) +{ + int ret; + + if (!HAS_RC6(gt->i915)) + return; + + ret = __intel_gt_sysfs_create_group(kobj, rc6_attr_group); + if (ret) + drm_warn(>->i915->drm, + "failed to create gt%u RC6 sysfs files (%pe)\n", + gt->info.id, ERR_PTR(ret)); + + /* + * cannot use the is_visible() attribute because + * the upper object inherits from the parent group. + */ + if (HAS_RC6p(gt->i915)) { + ret = __intel_gt_sysfs_create_group(kobj, rc6p_attr_group); + if (ret) + drm_warn(>->i915->drm, + "failed to create gt%u RC6p sysfs files (%pe)\n", + gt->info.id, ERR_PTR(ret)); + } + + if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) { + ret = __intel_gt_sysfs_create_group(kobj, media_rc6_attr_group); + if (ret) + drm_warn(>->i915->drm, + "failed to create media %u RC6 sysfs files (%pe)\n", + gt->info.id, ERR_PTR(ret)); + } +} +#else +static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj) +{ +} +#endif /* CONFIG_PM */ + +void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj) +{ + intel_sysfs_rc6_init(gt, kobj); +} diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.h b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.h new file mode 100644 index 000000000000..f567105a4a89 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __SYSFS_GT_PM_H__ +#define __SYSFS_GT_PM_H__ + +#include + +#include "intel_gt_types.h" + +void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj); + +#endif /* SYSFS_RC6_H */ diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 5ff915b93c21..2c5d62a521f6 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -45,107 +45,6 @@ struct drm_i915_private *kdev_minor_to_i915(struct device *kdev) return to_i915(minor->dev); } -#ifdef CONFIG_PM -static u32 calc_residency(struct drm_i915_private *dev_priv, - i915_reg_t reg) -{ - intel_wakeref_t wakeref; - u64 res = 0; - - with_intel_runtime_pm(&dev_priv->runtime_pm, wakeref) - res = intel_rc6_residency_us(&to_gt(dev_priv)->rc6, reg); - - return DIV_ROUND_CLOSEST_ULL(res, 1000); -} - -static ssize_t rc6_enable_show(struct device *kdev, - struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - unsigned int mask; - - mask = 0; - if (HAS_RC6(dev_priv)) - mask |= BIT(0); - if (HAS_RC6p(dev_priv)) - mask |= BIT(1); - if (HAS_RC6pp(dev_priv)) - mask |= BIT(2); - - return sysfs_emit(buf, "%x\n", mask); -} - -static ssize_t rc6_residency_ms_show(struct device *kdev, - struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - u32 rc6_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6); - return sysfs_emit(buf, "%u\n", rc6_residency); -} - -static ssize_t rc6p_residency_ms_show(struct device *kdev, - struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - u32 rc6p_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6p); - return sysfs_emit(buf, "%u\n", rc6p_residency); -} - -static ssize_t rc6pp_residency_ms_show(struct device *kdev, - struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - u32 rc6pp_residency = calc_residency(dev_priv, GEN6_GT_GFX_RC6pp); - return sysfs_emit(buf, "%u\n", rc6pp_residency); -} - -static ssize_t media_rc6_residency_ms_show(struct device *kdev, - struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - u32 rc6_residency = calc_residency(dev_priv, VLV_GT_MEDIA_RC6); - return sysfs_emit(buf, "%u\n", rc6_residency); -} - -static DEVICE_ATTR_RO(rc6_enable); -static DEVICE_ATTR_RO(rc6_residency_ms); -static DEVICE_ATTR_RO(rc6p_residency_ms); -static DEVICE_ATTR_RO(rc6pp_residency_ms); -static DEVICE_ATTR_RO(media_rc6_residency_ms); - -static struct attribute *rc6_attrs[] = { - &dev_attr_rc6_enable.attr, - &dev_attr_rc6_residency_ms.attr, - NULL -}; - -static const struct attribute_group rc6_attr_group = { - .name = power_group_name, - .attrs = rc6_attrs -}; - -static struct attribute *rc6p_attrs[] = { - &dev_attr_rc6p_residency_ms.attr, - &dev_attr_rc6pp_residency_ms.attr, - NULL -}; - -static const struct attribute_group rc6p_attr_group = { - .name = power_group_name, - .attrs = rc6p_attrs -}; - -static struct attribute *media_rc6_attrs[] = { - &dev_attr_media_rc6_residency_ms.attr, - NULL -}; - -static const struct attribute_group media_rc6_attr_group = { - .name = power_group_name, - .attrs = media_rc6_attrs -}; -#endif - static int l3_access_valid(struct drm_i915_private *i915, loff_t offset) { if (!HAS_L3_DPF(i915)) @@ -492,29 +391,6 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) struct device *kdev = dev_priv->drm.primary->kdev; int ret; -#ifdef CONFIG_PM - if (HAS_RC6(dev_priv)) { - ret = sysfs_merge_group(&kdev->kobj, - &rc6_attr_group); - if (ret) - drm_err(&dev_priv->drm, - "RC6 residency sysfs setup failed\n"); - } - if (HAS_RC6p(dev_priv)) { - ret = sysfs_merge_group(&kdev->kobj, - &rc6p_attr_group); - if (ret) - drm_err(&dev_priv->drm, - "RC6p residency sysfs setup failed\n"); - } - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { - ret = sysfs_merge_group(&kdev->kobj, - &media_rc6_attr_group); - if (ret) - drm_err(&dev_priv->drm, - "Media RC6 residency sysfs setup failed\n"); - } -#endif if (HAS_L3_DPF(dev_priv)) { ret = device_create_bin_file(kdev, &dpf_attrs); if (ret) @@ -560,8 +436,4 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv) sysfs_remove_files(&kdev->kobj, gen6_attrs); device_remove_bin_file(kdev, &dpf_attrs_1); device_remove_bin_file(kdev, &dpf_attrs); -#ifdef CONFIG_PM - sysfs_unmerge_group(&kdev->kobj, &rc6_attr_group); - sysfs_unmerge_group(&kdev->kobj, &rc6p_attr_group); -#endif } From 56a709cf77468e3a422b0ce3d58f8c2257bac2f1 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Sat, 19 Mar 2022 01:39:36 +0200 Subject: [PATCH 00274/11454] drm/i915/gt: Create per-tile RPS sysfs interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now tiles have their own sysfs interfaces under the gt/ directory. Because RPS is a property that can be configured on a tile basis, then each tile should have its own interface The new sysfs structure will have a similar layout for the 4 tile case: /sys/.../card0 ├── gt │   ├── gt0 │   │   ├── id │   │   ├── rc6_enable │   │   ├── rc6_residency_ms │   │   ├── rps_act_freq_mhz │   │   ├── rps_boost_freq_mhz │   │   ├── rps_cur_freq_mhz │   │   ├── rps_max_freq_mhz │   │   ├── rps_min_freq_mhz │   │   ├── rps_RP0_freq_mhz │   │   ├── rps_RP1_freq_mhz │   │  └── rps_RPn_freq_mhz . . . . . . │   └── gtN │   ├── id │   ├── rc6_enable │   ├── rc6_residency_ms │   ├── rps_act_freq_mhz │   ├── rps_boost_freq_mhz │   ├── rps_cur_freq_mhz │   ├── rps_max_freq_mhz │   ├── rps_min_freq_mhz │   ├── rps_RP0_freq_mhz │   ├── rps_RP1_freq_mhz │   └── rps_RPn_freq_mhz ├── gt_act_freq_mhz -+ ├── gt_boost_freq_mhz | ├── gt_cur_freq_mhz | Original interface ├── gt_max_freq_mhz +─-> kept as existing ABI; ├── gt_min_freq_mhz | it points to gt0/ ├── gt_RP0_freq_mhz | ├── gt_RP1_freq_mhz | └── gt_RPn_freq_mhz -+ The existing interfaces have been kept in their original location to preserve the existing ABI. They act on all the GTs: when writing they loop through all the GTs and write the information on each interface. When reading they provide the average value from all the GTs. This patch is not really adding exposing new interfaces (new ABI) other than adapting the existing one to more tiles. In any case this new set of interfaces will be a basic tool for system managers and administrators when using i915. Signed-off-by: Andi Shyti Signed-off-by: Lucas De Marchi Cc: Chris Wilson Cc: Joonas Lahtinen Cc: Matt Roper Cc: Sujaritha Sundaresan Cc: Tvrtko Ursulin Reviewed-by: Andrzej Hajda Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220318233938.149744-7-andi.shyti@linux.intel.com --- drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 283 ++++++++++++++++++++ drivers/gpu/drm/i915/i915_sysfs.c | 177 ------------ 2 files changed, 283 insertions(+), 177 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c index 144b004e4de8..b0a1ea95d028 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c @@ -14,6 +14,7 @@ #include "intel_gt_sysfs.h" #include "intel_gt_sysfs_pm.h" #include "intel_rc6.h" +#include "intel_rps.h" #ifdef CONFIG_PM enum intel_gt_sysfs_op { @@ -21,6 +22,30 @@ enum intel_gt_sysfs_op { INTEL_GT_SYSFS_MAX, }; +static int +sysfs_gt_attribute_w_func(struct device *dev, struct device_attribute *attr, + int (func)(struct intel_gt *gt, u32 val), u32 val) +{ + struct intel_gt *gt; + int ret; + + if (!is_object_gt(&dev->kobj)) { + int i; + struct drm_i915_private *i915 = kdev_minor_to_i915(dev); + + for_each_gt(gt, i915, i) { + ret = func(gt, val); + if (ret) + break; + } + } else { + gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); + ret = func(gt, val); + } + + return ret; +} + static u32 sysfs_gt_attribute_r_func(struct device *dev, struct device_attribute *attr, u32 (func)(struct intel_gt *gt), @@ -62,6 +87,7 @@ sysfs_gt_attribute_r_func(struct device *dev, struct device_attribute *attr, #define sysfs_gt_attribute_r_min_func(d, a, f) \ sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MIN) +/* Frequency interfaces will show the maximum frequency value */ #define sysfs_gt_attribute_r_max_func(d, a, f) \ sysfs_gt_attribute_r_func(d, a, f, INTEL_GT_SYSFS_MAX) @@ -238,7 +264,264 @@ static void intel_sysfs_rc6_init(struct intel_gt *gt, struct kobject *kobj) } #endif /* CONFIG_PM */ +static u32 __act_freq_mhz_show(struct intel_gt *gt) +{ + return intel_rps_read_actual_frequency(>->rps); +} + +static ssize_t act_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + u32 actual_freq = sysfs_gt_attribute_r_max_func(dev, attr, + __act_freq_mhz_show); + + return sysfs_emit(buff, "%u\n", actual_freq); +} + +static u32 __cur_freq_mhz_show(struct intel_gt *gt) +{ + return intel_rps_get_requested_frequency(>->rps); +} + +static ssize_t cur_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + u32 cur_freq = sysfs_gt_attribute_r_max_func(dev, attr, + __cur_freq_mhz_show); + + return sysfs_emit(buff, "%u\n", cur_freq); +} + +static u32 __boost_freq_mhz_show(struct intel_gt *gt) +{ + return intel_rps_get_boost_frequency(>->rps); +} + +static ssize_t boost_freq_mhz_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + u32 boost_freq = sysfs_gt_attribute_r_max_func(dev, attr, + __boost_freq_mhz_show); + + return sysfs_emit(buff, "%u\n", boost_freq); +} + +static int __boost_freq_mhz_store(struct intel_gt *gt, u32 val) +{ + return intel_rps_set_boost_frequency(>->rps, val); +} + +static ssize_t boost_freq_mhz_store(struct device *dev, + struct device_attribute *attr, + const char *buff, size_t count) +{ + ssize_t ret; + u32 val; + + ret = kstrtou32(buff, 0, &val); + if (ret) + return ret; + + return sysfs_gt_attribute_w_func(dev, attr, + __boost_freq_mhz_store, val) ?: count; +} + +static u32 __rp0_freq_mhz_show(struct intel_gt *gt) +{ + return intel_rps_get_rp0_frequency(>->rps); +} + +static ssize_t RP0_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + u32 rp0_freq = sysfs_gt_attribute_r_max_func(dev, attr, + __rp0_freq_mhz_show); + + return sysfs_emit(buff, "%u\n", rp0_freq); +} + +static u32 __rp1_freq_mhz_show(struct intel_gt *gt) +{ + return intel_rps_get_rp1_frequency(>->rps); +} + +static ssize_t RP1_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + u32 rp1_freq = sysfs_gt_attribute_r_max_func(dev, attr, + __rp1_freq_mhz_show); + + return sysfs_emit(buff, "%u\n", rp1_freq); +} + +static u32 __rpn_freq_mhz_show(struct intel_gt *gt) +{ + return intel_rps_get_rpn_frequency(>->rps); +} + +static ssize_t RPn_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + u32 rpn_freq = sysfs_gt_attribute_r_max_func(dev, attr, + __rpn_freq_mhz_show); + + return sysfs_emit(buff, "%u\n", rpn_freq); +} + +static u32 __max_freq_mhz_show(struct intel_gt *gt) +{ + return intel_rps_get_max_frequency(>->rps); +} + +static ssize_t max_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + u32 max_freq = sysfs_gt_attribute_r_max_func(dev, attr, + __max_freq_mhz_show); + + return sysfs_emit(buff, "%u\n", max_freq); +} + +static int __set_max_freq(struct intel_gt *gt, u32 val) +{ + return intel_rps_set_max_frequency(>->rps, val); +} + +static ssize_t max_freq_mhz_store(struct device *dev, + struct device_attribute *attr, + const char *buff, size_t count) +{ + int ret; + u32 val; + + ret = kstrtou32(buff, 0, &val); + if (ret) + return ret; + + ret = sysfs_gt_attribute_w_func(dev, attr, __set_max_freq, val); + + return ret ?: count; +} + +static u32 __min_freq_mhz_show(struct intel_gt *gt) +{ + return intel_rps_get_min_frequency(>->rps); +} + +static ssize_t min_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + u32 min_freq = sysfs_gt_attribute_r_min_func(dev, attr, + __min_freq_mhz_show); + + return sysfs_emit(buff, "%u\n", min_freq); +} + +static int __set_min_freq(struct intel_gt *gt, u32 val) +{ + return intel_rps_set_min_frequency(>->rps, val); +} + +static ssize_t min_freq_mhz_store(struct device *dev, + struct device_attribute *attr, + const char *buff, size_t count) +{ + int ret; + u32 val; + + ret = kstrtou32(buff, 0, &val); + if (ret) + return ret; + + ret = sysfs_gt_attribute_w_func(dev, attr, __set_min_freq, val); + + return ret ?: count; +} + +static u32 __vlv_rpe_freq_mhz_show(struct intel_gt *gt) +{ + struct intel_rps *rps = >->rps; + + return intel_gpu_freq(rps, rps->efficient_freq); +} + +static ssize_t vlv_rpe_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buff) +{ + u32 rpe_freq = sysfs_gt_attribute_r_max_func(dev, attr, + __vlv_rpe_freq_mhz_show); + + return sysfs_emit(buff, "%u\n", rpe_freq); +} + +#define INTEL_GT_RPS_SYSFS_ATTR(_name, _mode, _show, _store) \ + struct device_attribute dev_attr_gt_##_name = __ATTR(gt_##_name, _mode, _show, _store); \ + struct device_attribute dev_attr_rps_##_name = __ATTR(rps_##_name, _mode, _show, _store) + +#define INTEL_GT_RPS_SYSFS_ATTR_RO(_name) \ + INTEL_GT_RPS_SYSFS_ATTR(_name, 0444, _name##_show, NULL) +#define INTEL_GT_RPS_SYSFS_ATTR_RW(_name) \ + INTEL_GT_RPS_SYSFS_ATTR(_name, 0644, _name##_show, _name##_store) + +static INTEL_GT_RPS_SYSFS_ATTR_RO(act_freq_mhz); +static INTEL_GT_RPS_SYSFS_ATTR_RO(cur_freq_mhz); +static INTEL_GT_RPS_SYSFS_ATTR_RW(boost_freq_mhz); +static INTEL_GT_RPS_SYSFS_ATTR_RO(RP0_freq_mhz); +static INTEL_GT_RPS_SYSFS_ATTR_RO(RP1_freq_mhz); +static INTEL_GT_RPS_SYSFS_ATTR_RO(RPn_freq_mhz); +static INTEL_GT_RPS_SYSFS_ATTR_RW(max_freq_mhz); +static INTEL_GT_RPS_SYSFS_ATTR_RW(min_freq_mhz); + +static DEVICE_ATTR_RO(vlv_rpe_freq_mhz); + +#define GEN6_ATTR(s) { \ + &dev_attr_##s##_act_freq_mhz.attr, \ + &dev_attr_##s##_cur_freq_mhz.attr, \ + &dev_attr_##s##_boost_freq_mhz.attr, \ + &dev_attr_##s##_max_freq_mhz.attr, \ + &dev_attr_##s##_min_freq_mhz.attr, \ + &dev_attr_##s##_RP0_freq_mhz.attr, \ + &dev_attr_##s##_RP1_freq_mhz.attr, \ + &dev_attr_##s##_RPn_freq_mhz.attr, \ + NULL, \ + } + +#define GEN6_RPS_ATTR GEN6_ATTR(rps) +#define GEN6_GT_ATTR GEN6_ATTR(gt) + +static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR; +static const struct attribute * const gen6_gt_attrs[] = GEN6_GT_ATTR; + +static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj, + const struct attribute * const *attrs) +{ + int ret; + + if (GRAPHICS_VER(gt->i915) < 6) + return 0; + + ret = sysfs_create_files(kobj, attrs); + if (ret) + return ret; + + if (IS_VALLEYVIEW(gt->i915) || IS_CHERRYVIEW(gt->i915)) + ret = sysfs_create_file(kobj, &dev_attr_vlv_rpe_freq_mhz.attr); + + return ret; +} + void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj) { + int ret; + intel_sysfs_rc6_init(gt, kobj); + + ret = is_object_gt(kobj) ? + intel_sysfs_rps_init(gt, kobj, gen6_rps_attrs) : + intel_sysfs_rps_init(gt, kobj, gen6_gt_attrs); + if (ret) + drm_warn(>->i915->drm, + "failed to create gt%u RPS sysfs files (%pe)", + gt->info.id, ERR_PTR(ret)); } diff --git a/drivers/gpu/drm/i915/i915_sysfs.c b/drivers/gpu/drm/i915/i915_sysfs.c index 2c5d62a521f6..8521daba212a 100644 --- a/drivers/gpu/drm/i915/i915_sysfs.c +++ b/drivers/gpu/drm/i915/i915_sysfs.c @@ -156,171 +156,6 @@ static const struct bin_attribute dpf_attrs_1 = { .private = (void *)1 }; -static ssize_t gt_act_freq_mhz_show(struct device *kdev, - struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &to_gt(i915)->rps; - - return sysfs_emit(buf, "%d\n", intel_rps_read_actual_frequency(rps)); -} - -static ssize_t gt_cur_freq_mhz_show(struct device *kdev, - struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &to_gt(i915)->rps; - - return sysfs_emit(buf, "%d\n", intel_rps_get_requested_frequency(rps)); -} - -static ssize_t gt_boost_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &to_gt(i915)->rps; - - return sysfs_emit(buf, "%d\n", intel_rps_get_boost_frequency(rps)); -} - -static ssize_t gt_boost_freq_mhz_store(struct device *kdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &to_gt(dev_priv)->rps; - ssize_t ret; - u32 val; - - ret = kstrtou32(buf, 0, &val); - if (ret) - return ret; - - ret = intel_rps_set_boost_frequency(rps, val); - - return ret ?: count; -} - -static ssize_t vlv_rpe_freq_mhz_show(struct device *kdev, - struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &to_gt(dev_priv)->rps; - - return sysfs_emit(buf, "%d\n", intel_gpu_freq(rps, rps->efficient_freq)); -} - -static ssize_t gt_max_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - struct intel_gt *gt = to_gt(dev_priv); - struct intel_rps *rps = >->rps; - - return sysfs_emit(buf, "%d\n", intel_rps_get_max_frequency(rps)); -} - -static ssize_t gt_max_freq_mhz_store(struct device *kdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - struct intel_gt *gt = to_gt(dev_priv); - struct intel_rps *rps = >->rps; - ssize_t ret; - u32 val; - - ret = kstrtou32(buf, 0, &val); - if (ret) - return ret; - - ret = intel_rps_set_max_frequency(rps, val); - - return ret ?: count; -} - -static ssize_t gt_min_freq_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); - struct intel_gt *gt = to_gt(i915); - struct intel_rps *rps = >->rps; - - return sysfs_emit(buf, "%d\n", intel_rps_get_min_frequency(rps)); -} - -static ssize_t gt_min_freq_mhz_store(struct device *kdev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct drm_i915_private *i915 = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &to_gt(i915)->rps; - ssize_t ret; - u32 val; - - ret = kstrtou32(buf, 0, &val); - if (ret) - return ret; - - ret = intel_rps_set_min_frequency(rps, val); - - return ret ?: count; -} - -static DEVICE_ATTR_RO(gt_act_freq_mhz); -static DEVICE_ATTR_RO(gt_cur_freq_mhz); -static DEVICE_ATTR_RW(gt_boost_freq_mhz); -static DEVICE_ATTR_RW(gt_max_freq_mhz); -static DEVICE_ATTR_RW(gt_min_freq_mhz); - -static DEVICE_ATTR_RO(vlv_rpe_freq_mhz); - -static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf); -static DEVICE_ATTR(gt_RP0_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); -static DEVICE_ATTR(gt_RP1_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); -static DEVICE_ATTR(gt_RPn_freq_mhz, S_IRUGO, gt_rp_mhz_show, NULL); - -/* For now we have a static number of RP states */ -static ssize_t gt_rp_mhz_show(struct device *kdev, struct device_attribute *attr, char *buf) -{ - struct drm_i915_private *dev_priv = kdev_minor_to_i915(kdev); - struct intel_rps *rps = &to_gt(dev_priv)->rps; - u32 val; - - if (attr == &dev_attr_gt_RP0_freq_mhz) - val = intel_rps_get_rp0_frequency(rps); - else if (attr == &dev_attr_gt_RP1_freq_mhz) - val = intel_rps_get_rp1_frequency(rps); - else if (attr == &dev_attr_gt_RPn_freq_mhz) - val = intel_rps_get_rpn_frequency(rps); - else - BUG(); - - return sysfs_emit(buf, "%d\n", val); -} - -static const struct attribute * const gen6_attrs[] = { - &dev_attr_gt_act_freq_mhz.attr, - &dev_attr_gt_cur_freq_mhz.attr, - &dev_attr_gt_boost_freq_mhz.attr, - &dev_attr_gt_max_freq_mhz.attr, - &dev_attr_gt_min_freq_mhz.attr, - &dev_attr_gt_RP0_freq_mhz.attr, - &dev_attr_gt_RP1_freq_mhz.attr, - &dev_attr_gt_RPn_freq_mhz.attr, - NULL, -}; - -static const struct attribute * const vlv_attrs[] = { - &dev_attr_gt_act_freq_mhz.attr, - &dev_attr_gt_cur_freq_mhz.attr, - &dev_attr_gt_boost_freq_mhz.attr, - &dev_attr_gt_max_freq_mhz.attr, - &dev_attr_gt_min_freq_mhz.attr, - &dev_attr_gt_RP0_freq_mhz.attr, - &dev_attr_gt_RP1_freq_mhz.attr, - &dev_attr_gt_RPn_freq_mhz.attr, - &dev_attr_vlv_rpe_freq_mhz.attr, - NULL, -}; - #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) static ssize_t error_state_read(struct file *filp, struct kobject *kobj, @@ -406,14 +241,6 @@ void i915_setup_sysfs(struct drm_i915_private *dev_priv) } } - ret = 0; - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - ret = sysfs_create_files(&kdev->kobj, vlv_attrs); - else if (GRAPHICS_VER(dev_priv) >= 6) - ret = sysfs_create_files(&kdev->kobj, gen6_attrs); - if (ret) - drm_err(&dev_priv->drm, "RPS sysfs setup failed\n"); - dev_priv->sysfs_gt = kobject_create_and_add("gt", &kdev->kobj); if (!dev_priv->sysfs_gt) drm_warn(&dev_priv->drm, @@ -430,10 +257,6 @@ void i915_teardown_sysfs(struct drm_i915_private *dev_priv) i915_teardown_error_capture(kdev); - if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) - sysfs_remove_files(&kdev->kobj, vlv_attrs); - else - sysfs_remove_files(&kdev->kobj, gen6_attrs); device_remove_bin_file(kdev, &dpf_attrs_1); device_remove_bin_file(kdev, &dpf_attrs); } From fa68bff7cf27d83e0ca83c6388d6bc2ddc599905 Mon Sep 17 00:00:00 2001 From: Sujaritha Sundaresan Date: Sat, 19 Mar 2022 01:39:37 +0200 Subject: [PATCH 00275/11454] drm/i915/gt: Add sysfs throttle frequency interfaces Throttling here refers to the GT frequency being clipped. Each of the throttle reason attributes will have a 0 or 1 value depending upon whether there is throttling and also the specific reason for it. The following is a brief description of the sysfs throttle frequency attributes added: - throttle_reason_status: when set indicates that there is GT frequency clipping. - throttle_reason_pl1: when set indicates that PBM PL1 (platform or package PL1) has caused GT frequency clipping. - throttle_reason_pl2: when set indicates that PBM PL2 or PL3 (platform or package PL2 or PL3) has caused GT frequency clipping. - throttle_reason_pl4: when set indicates that PL4 or IccMax has caused GT frequency clipping. - throttle_reason_thermal: when set indicates that Thermal event has caused GT frequency clipping. - throttle_reason_prochot: when set indicates that PROCHOT# has caused GT frequency clipping. - throttle_reason_ratl: when set indicates that Running Average Thermal Limit has caused GT frequency clipping. - throttle_reason_vr_thermalert: when set indicates that Hot VR (any processor VR) has caused GT frequency clipping. - throttle_reason_vr_tdc: when set indicates that VR TDC (Thermal Design Current) has caused GT frequency clipping. Signed-off-by: Sujaritha Sundaresan Signed-off-by: Andi Shyti Cc: Dale B Stimson Reviewed-by: Andrzej Hajda Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220318233938.149744-8-andi.shyti@linux.intel.com --- drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c | 74 +++++++++++++++++++++ drivers/gpu/drm/i915/gt/intel_rps.c | 18 +++++ drivers/gpu/drm/i915/gt/intel_rps.h | 4 ++ drivers/gpu/drm/i915/i915_reg.h | 11 +++ 4 files changed, 107 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c index b0a1ea95d028..26cbfa6477d1 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_sysfs_pm.c @@ -8,6 +8,7 @@ #include #include "i915_drv.h" +#include "i915_reg.h" #include "i915_sysfs.h" #include "intel_gt.h" #include "intel_gt_regs.h" @@ -493,6 +494,69 @@ static DEVICE_ATTR_RO(vlv_rpe_freq_mhz); static const struct attribute * const gen6_rps_attrs[] = GEN6_RPS_ATTR; static const struct attribute * const gen6_gt_attrs[] = GEN6_GT_ATTR; +static ssize_t punit_req_freq_mhz_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); + u32 preq = intel_rps_read_punit_req_frequency(>->rps); + + return sysfs_emit(buff, "%u\n", preq); +} + +struct intel_gt_bool_throttle_attr { + struct attribute attr; + ssize_t (*show)(struct device *dev, struct device_attribute *attr, + char *buf); + i915_reg_t reg32; + u32 mask; +}; + +static ssize_t throttle_reason_bool_show(struct device *dev, + struct device_attribute *attr, + char *buff) +{ + struct intel_gt *gt = intel_gt_sysfs_get_drvdata(dev, attr->attr.name); + struct intel_gt_bool_throttle_attr *t_attr = + (struct intel_gt_bool_throttle_attr *) attr; + bool val = rps_read_mask_mmio(>->rps, t_attr->reg32, t_attr->mask); + + return sysfs_emit(buff, "%u\n", val); +} + +#define INTEL_GT_RPS_BOOL_ATTR_RO(sysfs_func__, mask__) \ +struct intel_gt_bool_throttle_attr attr_##sysfs_func__ = { \ + .attr = { .name = __stringify(sysfs_func__), .mode = 0444 }, \ + .show = throttle_reason_bool_show, \ + .reg32 = GT0_PERF_LIMIT_REASONS, \ + .mask = mask__, \ +} + +static DEVICE_ATTR_RO(punit_req_freq_mhz); +static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_status, GT0_PERF_LIMIT_REASONS_MASK); +static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl1, POWER_LIMIT_1_MASK); +static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl2, POWER_LIMIT_2_MASK); +static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_pl4, POWER_LIMIT_4_MASK); +static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_thermal, THERMAL_LIMIT_MASK); +static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_prochot, PROCHOT_MASK); +static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_ratl, RATL_MASK); +static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_thermalert, VR_THERMALERT_MASK); +static INTEL_GT_RPS_BOOL_ATTR_RO(throttle_reason_vr_tdc, VR_TDC_MASK); + +static const struct attribute *freq_attrs[] = { + &dev_attr_punit_req_freq_mhz.attr, + &attr_throttle_reason_status.attr, + &attr_throttle_reason_pl1.attr, + &attr_throttle_reason_pl2.attr, + &attr_throttle_reason_pl4.attr, + &attr_throttle_reason_thermal.attr, + &attr_throttle_reason_prochot.attr, + &attr_throttle_reason_ratl.attr, + &attr_throttle_reason_vr_thermalert.attr, + &attr_throttle_reason_vr_tdc.attr, + NULL +}; + static int intel_sysfs_rps_init(struct intel_gt *gt, struct kobject *kobj, const struct attribute * const *attrs) { @@ -524,4 +588,14 @@ void intel_gt_sysfs_pm_init(struct intel_gt *gt, struct kobject *kobj) drm_warn(>->i915->drm, "failed to create gt%u RPS sysfs files (%pe)", gt->info.id, ERR_PTR(ret)); + + /* end of the legacy interfaces */ + if (!is_object_gt(kobj)) + return; + + ret = sysfs_create_files(kobj, freq_attrs); + if (ret) + drm_warn(>->i915->drm, + "failed to create gt%u throttle sysfs files (%pe)", + gt->info.id, ERR_PTR(ret)); } diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index c8124101aada..746bd07a2abd 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -2286,6 +2286,24 @@ void intel_rps_lower_unslice(struct intel_rps *rps) mutex_unlock(&rps->lock); } +static u32 rps_read_mmio(struct intel_rps *rps, i915_reg_t reg32) +{ + struct intel_gt *gt = rps_to_gt(rps); + intel_wakeref_t wakeref; + u32 val; + + with_intel_runtime_pm(gt->uncore->rpm, wakeref) + val = intel_uncore_read(gt->uncore, reg32); + + return val; +} + +bool rps_read_mask_mmio(struct intel_rps *rps, + i915_reg_t reg32, u32 mask) +{ + return rps_read_mmio(rps, reg32) & mask; +} + /* External interface for intel_ips.ko */ static struct drm_i915_private __rcu *ips_mchdev; diff --git a/drivers/gpu/drm/i915/gt/intel_rps.h b/drivers/gpu/drm/i915/gt/intel_rps.h index c6d76a3d1331..ba1ed9f7ecda 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.h +++ b/drivers/gpu/drm/i915/gt/intel_rps.h @@ -7,6 +7,7 @@ #define INTEL_RPS_H #include "intel_rps_types.h" +#include "i915_reg_defs.h" struct i915_request; @@ -48,6 +49,9 @@ u32 intel_rps_read_state_cap(struct intel_rps *rps); void intel_rps_raise_unslice(struct intel_rps *rps); void intel_rps_lower_unslice(struct intel_rps *rps); +u32 intel_rps_read_throttle_reason(struct intel_rps *rps); +bool rps_read_mask_mmio(struct intel_rps *rps, i915_reg_t reg32, u32 mask); + void gen5_rps_irq_handler(struct intel_rps *rps); void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir); void gen11_rps_irq_handler(struct intel_rps *rps, u32 pm_iir); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3cdcd25ff401..8d6ffd2ca446 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1837,6 +1837,17 @@ #define GEN9_RP_STATE_LIMITS _MMIO(0x138148) #define XEHPSDV_RP_STATE_CAP _MMIO(0x250014) +#define GT0_PERF_LIMIT_REASONS _MMIO(0x1381a8) +#define GT0_PERF_LIMIT_REASONS_MASK 0xde3 +#define PROCHOT_MASK REG_BIT(1) +#define THERMAL_LIMIT_MASK REG_BIT(2) +#define RATL_MASK REG_BIT(6) +#define VR_THERMALERT_MASK REG_BIT(7) +#define VR_TDC_MASK REG_BIT(8) +#define POWER_LIMIT_4_MASK REG_BIT(9) +#define POWER_LIMIT_1_MASK REG_BIT(11) +#define POWER_LIMIT_2_MASK REG_BIT(12) + #define CHV_CLK_CTL1 _MMIO(0x101100) #define VLV_CLK_CTL2 _MMIO(0x101104) #define CLK_CTL2_CZCOUNT_30NS_SHIFT 28 From 2c3fc50591ff3b7c90afb39c6f4ac67a0ffeeb76 Mon Sep 17 00:00:00 2001 From: Youghandhar Chintala Date: Tue, 15 Mar 2022 13:59:44 +0530 Subject: [PATCH 00276/11454] ath10k: Trigger sta disconnect on hardware restart Currently after the hardware restart triggered from the driver, the station interface connection remains intact, since a disconnect trigger is not sent to userspace. This can lead to a problem in targets where the wifi mac sequence is added by the firmware. After the target restart, its wifi mac sequence number gets reset to zero. Hence AP to which our device is connected will receive frames with a wifi mac sequence number jump to the past, thereby resulting in the AP dropping all these frames, until the frame arrives with a wifi mac sequence number which AP was expecting. To avoid such frame drops, its better to trigger a station disconnect upon target hardware restart which can be done with API ieee80211_reconfig_disconnect exposed to mac80211. The other targets are not affected by this change, since the hardware params flag is not set. Tested-on: WCN3990 hw1.0 SNOC WLAN.HL.3.1-01040-QCAHLSWMTPLZ-1 Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00048 Signed-off-by: Youghandhar Chintala Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220315082944.12406-3-youghand@codeaurora.org --- drivers/net/wireless/ath/ath10k/core.c | 25 +++++++++++++++++++++++++ drivers/net/wireless/ath/ath10k/hw.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 9e1f483e1362..2092bfd02cd1 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -94,6 +94,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = true, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA988X_HW_2_0_VERSION, @@ -131,6 +132,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = true, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA9887_HW_1_0_VERSION, @@ -169,6 +171,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA6174_HW_3_2_VERSION, @@ -202,6 +205,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .bmi_large_size_download = true, .supports_peer_stats_info = true, .dynamic_sar_support = true, + .hw_restart_disconnect = false, }, { .id = QCA6174_HW_2_1_VERSION, @@ -239,6 +243,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA6174_HW_2_1_VERSION, @@ -276,6 +281,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA6174_HW_3_0_VERSION, @@ -313,6 +319,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA6174_HW_3_2_VERSION, @@ -354,6 +361,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .tx_stats_over_pktlog = false, .supports_peer_stats_info = true, .dynamic_sar_support = true, + .hw_restart_disconnect = false, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, @@ -397,6 +405,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA9984_HW_1_0_DEV_VERSION, @@ -447,6 +456,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA9888_HW_2_0_DEV_VERSION, @@ -494,6 +504,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA9377_HW_1_0_DEV_VERSION, @@ -531,6 +542,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -570,6 +582,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -600,6 +613,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .uart_pin_workaround = true, .credit_size_workaround = true, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = QCA4019_HW_1_0_DEV_VERSION, @@ -644,6 +658,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = false, + .hw_restart_disconnect = false, }, { .id = WCN3990_HW_1_0_DEV_VERSION, @@ -674,6 +689,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .credit_size_workaround = false, .tx_stats_over_pktlog = false, .dynamic_sar_support = true, + .hw_restart_disconnect = true, }, }; @@ -2442,6 +2458,7 @@ EXPORT_SYMBOL(ath10k_core_napi_sync_disable); static void ath10k_core_restart(struct work_struct *work) { struct ath10k *ar = container_of(work, struct ath10k, restart_work); + struct ath10k_vif *arvif; int ret; set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); @@ -2480,6 +2497,14 @@ static void ath10k_core_restart(struct work_struct *work) ar->state = ATH10K_STATE_RESTARTING; ath10k_halt(ar); ath10k_scan_finish(ar); + if (ar->hw_params.hw_restart_disconnect) { + list_for_each_entry(arvif, &ar->arvifs, list) { + if (arvif->is_up && + arvif->vdev_type == WMI_VDEV_TYPE_STA) + ieee80211_hw_restart_disconnect(arvif->vif); + } + } + ieee80211_restart_hw(ar->hw); break; case ATH10K_STATE_OFF: diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 5215a6816d71..93acf0dd580a 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -633,6 +633,8 @@ struct ath10k_hw_params { bool supports_peer_stats_info; bool dynamic_sar_support; + + bool hw_restart_disconnect; }; struct htt_resp; From c4e9705c50121771e7582830359894431f24db73 Mon Sep 17 00:00:00 2001 From: Meng Tang Date: Fri, 18 Mar 2022 10:53:31 +0800 Subject: [PATCH 00277/11454] ath10k: Use of_device_get_match_data() helper Only the device data is needed, not the entire struct of_device_id. Use of_device_get_match_data() instead of of_match_device(). Signed-off-by: Meng Tang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220318025331.23030-1-tangmeng@uniontech.com --- drivers/net/wireless/ath/ath10k/ahb.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index ab8f77ae5e66..f0c615fa5614 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -728,20 +728,17 @@ static int ath10k_ahb_probe(struct platform_device *pdev) struct ath10k *ar; struct ath10k_ahb *ar_ahb; struct ath10k_pci *ar_pci; - const struct of_device_id *of_id; enum ath10k_hw_rev hw_rev; size_t size; int ret; struct ath10k_bus_params bus_params = {}; - of_id = of_match_device(ath10k_ahb_of_match, &pdev->dev); - if (!of_id) { - dev_err(&pdev->dev, "failed to find matching device tree id\n"); + hw_rev = (enum ath10k_hw_rev)of_device_get_match_data(&pdev->dev); + if (!hw_rev) { + dev_err(&pdev->dev, "OF data missing\n"); return -EINVAL; } - hw_rev = (enum ath10k_hw_rev)of_id->data; - size = sizeof(*ar_pci) + sizeof(*ar_ahb); ar = ath10k_core_create(size, &pdev->dev, ATH10K_BUS_AHB, hw_rev, &ath10k_ahb_hif_ops); From 997dc60f0855b39aec0400511b37d65781da9255 Mon Sep 17 00:00:00 2001 From: Karthikeyan Periyasamy Date: Mon, 28 Feb 2022 10:24:39 +0530 Subject: [PATCH 00278/11454] ath11k: Refactor the peer delete Introduce new helper function for peer delete to reuse this logic in all peer cleanup procedures. Found this in code review. Also this change is applicable for all the platform. Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01067-QCAHKSWPL_SILICONZ-1 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1646024079-26391-1-git-send-email-quic_periyasa@quicinc.com --- drivers/net/wireless/ath/ath11k/mac.c | 16 +++---------- drivers/net/wireless/ath/ath11k/peer.c | 31 +++++++++++++------------- 2 files changed, 19 insertions(+), 28 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index e0e31605e0b0..7cf1ea276e24 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -6387,22 +6387,12 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, err_peer_del: if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { - reinit_completion(&ar->peer_delete_done); - - fbret = ath11k_wmi_send_peer_delete_cmd(ar, vif->addr, - arvif->vdev_id); + fbret = ath11k_peer_delete(ar, arvif->vdev_id, vif->addr); if (fbret) { - ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", - arvif->vdev_id, vif->addr); + ath11k_warn(ar->ab, "fallback fail to delete peer addr %pM vdev_id %d ret %d\n", + vif->addr, arvif->vdev_id, fbret); goto err; } - - fbret = ath11k_wait_for_peer_delete_done(ar, arvif->vdev_id, - vif->addr); - if (fbret) - goto err; - - ar->num_peers--; } err_vdev_del: diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c index 332886bc6b33..392985b873bf 100644 --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c @@ -217,7 +217,7 @@ int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, return 0; } -int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) +static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr) { int ret; @@ -237,6 +237,19 @@ int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) if (ret) return ret; + return 0; +} + +int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr) +{ + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + ret = __ath11k_peer_delete(ar, vdev_id, addr); + if (ret) + return ret; + ar->num_peers--; return 0; @@ -323,22 +336,10 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, return 0; cleanup: - reinit_completion(&ar->peer_delete_done); - - fbret = ath11k_wmi_send_peer_delete_cmd(ar, param->peer_addr, - param->vdev_id); - if (fbret) { - ath11k_warn(ar->ab, "failed to delete peer vdev_id %d addr %pM\n", - param->vdev_id, param->peer_addr); - goto exit; - } - - fbret = ath11k_wait_for_peer_delete_done(ar, param->vdev_id, - param->peer_addr); + fbret = __ath11k_peer_delete(ar, param->vdev_id, param->peer_addr); if (fbret) - ath11k_warn(ar->ab, "failed wait for peer %pM delete done id %d fallback ret %d\n", + ath11k_warn(ar->ab, "failed peer %pM delete vdev_id %d fallback ret %d\n", param->peer_addr, param->vdev_id, fbret); -exit: return ret; } From 72a9bff386545d3f8e9c432cb8e036272ad4e1fa Mon Sep 17 00:00:00 2001 From: Hari Chandrakanthan Date: Wed, 9 Mar 2022 16:54:25 +0530 Subject: [PATCH 00279/11454] ath11k: change fw build id format in driver init log Currently fw build id is printed during init as follows. fw_version 0x250684a5 fw_build_timestamp 2021-07-13 10:57 fw_build_id QC_IMAGE_VERSION_STRING=WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 The string "QC_IMAGE_VERSION_STRING=" is removed from the log to improve readability. With this patch the fw build id is printed during init as follows. fw_version 0x250684a5 fw_build_timestamp 2021-07-13 10:57 fw_build_id WLAN.HK.2.5.0.1-01100-QCAHKSWPL_SILICONZ-1 Signed-off-by: Hari Chandrakanthan Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1646825065-7736-1-git-send-email-quic_haric@quicinc.com --- drivers/net/wireless/ath/ath11k/qmi.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index 04e966830c18..ec110fe81378 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -16,6 +16,8 @@ #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 #define HOST_CSTATE_BIT 0x04 +#define FW_BUILD_ID_MASK "QC_IMAGE_VERSION_STRING=" + bool ath11k_cold_boot_cal = 1; EXPORT_SYMBOL(ath11k_cold_boot_cal); module_param_named(cold_boot_cal, ath11k_cold_boot_cal, bool, 0644); @@ -2008,6 +2010,8 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) struct qmi_txn txn; int ret = 0; int r; + char *fw_build_id; + int fw_build_id_mask_len; memset(&req, 0, sizeof(req)); memset(&resp, 0, sizeof(resp)); @@ -2073,6 +2077,11 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi cal data supported from eeprom\n"); } + fw_build_id = ab->qmi.target.fw_build_id; + fw_build_id_mask_len = strlen(FW_BUILD_ID_MASK); + if (!strncmp(fw_build_id, FW_BUILD_ID_MASK, fw_build_id_mask_len)) + fw_build_id = fw_build_id + fw_build_id_mask_len; + ath11k_info(ab, "chip_id 0x%x chip_family 0x%x board_id 0x%x soc_id 0x%x\n", ab->qmi.target.chip_id, ab->qmi.target.chip_family, ab->qmi.target.board_id, ab->qmi.target.soc_id); @@ -2080,7 +2089,7 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) ath11k_info(ab, "fw_version 0x%x fw_build_timestamp %s fw_build_id %s", ab->qmi.target.fw_version, ab->qmi.target.fw_build_timestamp, - ab->qmi.target.fw_build_id); + fw_build_id); r = ath11k_core_check_dt(ab); if (r) From 230523ba24bda5387637188ad56530bf6abd3f6c Mon Sep 17 00:00:00 2001 From: Vivek Kasireddy Date: Sun, 20 Mar 2022 17:54:31 -0700 Subject: [PATCH 00280/11454] drm/i915/gem: Don't evict unmappable VMAs when pinning with PIN_MAPPABLE (v2) On platforms capable of allowing 8K (7680 x 4320) modes, pinning 2 or more framebuffers/scanout buffers results in only one that is mappable/ fenceable. Therefore, pageflipping between these 2 FBs where only one is mappable/fenceable creates latencies large enough to miss alternate vblanks thereby producing less optimal framerate. This mainly happens because when i915_gem_object_pin_to_display_plane() is called to pin one of the FB objs, the associated vma is identified as misplaced -- because there is no space for it in the aperture -- and therefore i915_vma_unbind() is called which unbinds and evicts it. This misplaced vma gets subseqently pinned only when i915_gem_object_ggtt_pin_ww() is called without PIN_MAPPABLE. This whole thing results in a latency of ~10ms and happens every other repaint cycle. Therefore, to fix this issue, we just ensure that the misplaced VMA does not get evicted when we try to pin it with PIN_MAPPABLE -- by returning early if the mappable/fenceable flag is not set. Testcase: Running Weston and weston-simple-egl on an Alderlake_S (ADLS) platform with a 8K@60 mode results in only ~40 FPS (compared to ~59 FPS with this patch). Since upstream Weston submits a frame ~7ms before the next vblank, the latencies seen between atomic commit and flip event are 7, 24 (7 + 16.66), 7, 24..... suggesting that it misses the vblank every other frame. Here is the ftrace snippet that shows the source of the ~10ms latency: i915_gem_object_pin_to_display_plane() { 0.102 us | i915_gem_object_set_cache_level(); i915_gem_object_ggtt_pin_ww() { 0.390 us | i915_vma_instance(); 0.178 us | i915_vma_misplaced(); i915_vma_unbind() { __i915_active_wait() { 0.082 us | i915_active_acquire_if_busy(); 0.475 us | } intel_runtime_pm_get() { 0.087 us | intel_runtime_pm_acquire(); 0.259 us | } __i915_active_wait() { 0.085 us | i915_active_acquire_if_busy(); 0.240 us | } __i915_vma_evict() { ggtt_unbind_vma() { gen8_ggtt_clear_range() { 10507.255 us | } 10507.689 us | } 10508.516 us | } v2: - Expand the code comments to describe the ping-pong issue. Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Signed-off-by: Vivek Kasireddy Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20220321005431.1113890-1-vivek.kasireddy@intel.com --- drivers/gpu/drm/i915/i915_gem.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 9747924cc57b..44741f842852 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -939,8 +939,19 @@ new_vma: if (i915_vma_is_pinned(vma) || i915_vma_is_active(vma)) return ERR_PTR(-ENOSPC); + /* + * If this misplaced vma is too big (i.e, at-least + * half the size of aperture) or hasn't been pinned + * mappable before, we ignore the misplacement when + * PIN_NONBLOCK is set in order to avoid the ping-pong + * issue described above. In other words, we try to + * avoid the costly operation of unbinding this vma + * from the GGTT and rebinding it back because there + * may not be enough space for this vma in the aperture. + */ if (flags & PIN_MAPPABLE && - vma->fence_size > ggtt->mappable_end / 2) + (vma->fence_size > ggtt->mappable_end / 2 || + !i915_vma_is_map_and_fenceable(vma))) return ERR_PTR(-ENOSPC); } From 008bd15c4f17432f44cc48d38e97bb86110fd305 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 17 Mar 2022 19:33:55 +0200 Subject: [PATCH 00281/11454] drm/i915/sdvo: prefer __packed over __attribute__((packed)) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kernel preference is to use the __packed macro instead of the direct __attribute__. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220317173355.336835-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_sdvo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 158e750e5b4d..328a8f20c63b 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -283,7 +283,7 @@ static bool intel_sdvo_read_byte(struct intel_sdvo *intel_sdvo, u8 addr, u8 *ch) static const struct { u8 cmd; const char *name; -} __attribute__ ((packed)) sdvo_cmd_names[] = { +} __packed sdvo_cmd_names[] = { SDVO_CMD_NAME_ENTRY(RESET), SDVO_CMD_NAME_ENTRY(GET_DEVICE_CAPS), SDVO_CMD_NAME_ENTRY(GET_FIRMWARE_REV), From 10a26e0d5fc3574f63ce8a6cf28381b126317f40 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 18 Mar 2022 13:43:28 -0400 Subject: [PATCH 00282/11454] drm/vmwgfx: Fix an invalid read vmw_move assumed that buffers to be moved would always be vmw_buffer_object's but after introduction of new placement for mob pages that's no longer the case. The resulting invalid read didn't have any practical consequences because the memory isn't used unless the object actually is a vmw_buffer_object. Fix it by moving the cast to the spot where the results are used. Signed-off-by: Zack Rusin Fixes: f6be23264bba ("drm/vmwgfx: Introduce a new placement for MOB page tables") Reported-by: Chuck Lever III Reviewed-by: Martin Krastev Tested-by: Chuck Lever Link: https://patchwork.freedesktop.org/patch/msgid/20220318174332.440068-2-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 708899ba2102..6542f1498651 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -859,22 +859,21 @@ void vmw_query_move_notify(struct ttm_buffer_object *bo, struct ttm_device *bdev = bo->bdev; struct vmw_private *dev_priv; - dev_priv = container_of(bdev, struct vmw_private, bdev); mutex_lock(&dev_priv->binding_mutex); - dx_query_mob = container_of(bo, struct vmw_buffer_object, base); - if (!dx_query_mob || !dx_query_mob->dx_query_ctx) { - mutex_unlock(&dev_priv->binding_mutex); - return; - } - /* If BO is being moved from MOB to system memory */ if (new_mem->mem_type == TTM_PL_SYSTEM && old_mem->mem_type == VMW_PL_MOB) { struct vmw_fence_obj *fence; + dx_query_mob = container_of(bo, struct vmw_buffer_object, base); + if (!dx_query_mob || !dx_query_mob->dx_query_ctx) { + mutex_unlock(&dev_priv->binding_mutex); + return; + } + (void) vmw_query_readback_all(dx_query_mob); mutex_unlock(&dev_priv->binding_mutex); @@ -888,7 +887,6 @@ void vmw_query_move_notify(struct ttm_buffer_object *bo, (void) ttm_bo_wait(bo, false, false); } else mutex_unlock(&dev_priv->binding_mutex); - } /** From ab709795e38637320fea9fdc8e06b64f670b58ee Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 18 Mar 2022 13:43:29 -0400 Subject: [PATCH 00283/11454] drm/vmwgfx: Fix mob cursor allocation race Writes to SVGA_REG_CURSOR_MOBID did not wait for the buffers to be fully populated. This sometimes results in the device not being aware of the buffer when the cursor mob register was written. Properly wait for the buffer to be fully populated before setting it as a cursor mob. Signed-off-by: Zack Rusin Fixes: 485d98d472d5 ("drm/vmwgfx: Add support for CursorMob and CursorBypass 4") Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20220318174332.440068-3-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index af252210ef84..7a23f252d212 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -602,6 +602,14 @@ vmw_du_cursor_plane_prepare_fb(struct drm_plane *plane, ret = ttm_bo_kmap(cm_bo, 0, PFN_UP(size), &vps->cm_map); + /* + * We just want to try to get mob bind to finish + * so that the first write to SVGA_REG_CURSOR_MOBID + * is done with a buffer that the device has already + * seen + */ + (void) ttm_bo_wait(cm_bo, false, false); + ttm_bo_unreserve(cm_bo); if (unlikely(ret != 0)) { From 8bb75aeb58bd688d70827ae179bd3da57b6d975b Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 18 Mar 2022 13:43:30 -0400 Subject: [PATCH 00284/11454] drm/vmwgfx: validate the screen formats The kms code wasn't validating the modifiers and was letting through unsupported formats. rgb8 was never properly supported and has no matching svga screen target format so remove it. This fixes format/modifier failures in kms_addfb_basic from IGT. Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20220318174332.440068-4-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 30 +++++++++++++++-------------- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 1 - 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 7a23f252d212..693028c31b6b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1171,6 +1171,15 @@ static int vmw_kms_new_framebuffer_surface(struct vmw_private *dev_priv, * Sanity checks. */ + if (!drm_any_plane_has_format(&dev_priv->drm, + mode_cmd->pixel_format, + mode_cmd->modifier[0])) { + drm_dbg(&dev_priv->drm, + "unsupported pixel format %p4cc / modifier 0x%llx\n", + &mode_cmd->pixel_format, mode_cmd->modifier[0]); + return -EINVAL; + } + /* Surface must be marked as a scanout. */ if (unlikely(!surface->metadata.scanout)) return -EINVAL; @@ -1493,20 +1502,13 @@ static int vmw_kms_new_framebuffer_bo(struct vmw_private *dev_priv, return -EINVAL; } - /* Limited framebuffer color depth support for screen objects */ - if (dev_priv->active_display_unit == vmw_du_screen_object) { - switch (mode_cmd->pixel_format) { - case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: - break; - case DRM_FORMAT_XRGB1555: - case DRM_FORMAT_RGB565: - break; - default: - DRM_ERROR("Invalid pixel format: %p4cc\n", - &mode_cmd->pixel_format); - return -EINVAL; - } + if (!drm_any_plane_has_format(&dev_priv->drm, + mode_cmd->pixel_format, + mode_cmd->modifier[0])) { + drm_dbg(&dev_priv->drm, + "unsupported pixel format %p4cc / modifier 0x%llx\n", + &mode_cmd->pixel_format, mode_cmd->modifier[0]); + return -EINVAL; } vfbd = kzalloc(sizeof(*vfbd), GFP_KERNEL); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index c95be95deb8d..1d1c8b82c898 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -247,7 +247,6 @@ struct vmw_framebuffer_bo { static const uint32_t __maybe_unused vmw_primary_plane_formats[] = { DRM_FORMAT_XRGB1555, DRM_FORMAT_RGB565, - DRM_FORMAT_RGB888, DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, }; From 6f6f9788d821ee39c8a28e389a35027d6a5f143b Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 18 Mar 2022 13:43:31 -0400 Subject: [PATCH 00285/11454] drm/vmwgfx: Disable command buffers on svga3 without gbobjects With very limited vram on svga3 it's difficult to handle all the surface migrations. Without gbobjects, i.e. the ability to store surfaces in guest mobs, there's no reason to support intermediate svga2 features, especially because we can fall back to fb traces and svga3 will never support those in-between features. On svga3 we wither want to use fb traces or screen targets (i.e. gbobjects), nothing in between. This fixes presentation on a lot of fusion/esxi tech previews where the exposed svga3 caps haven't been finalized yet. Signed-off-by: Zack Rusin Fixes: 2cd80dbd3551 ("drm/vmwgfx: Add basic support for SVGA3") Cc: # v5.14+ Reviewed-by: Martin Krastev Link: https://patchwork.freedesktop.org/patch/msgid/20220318174332.440068-5-zack@kde.org --- drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c index bf1b394753da..162dfeb1cc5a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cmd.c @@ -675,11 +675,14 @@ int vmw_cmd_emit_dummy_query(struct vmw_private *dev_priv, */ bool vmw_cmd_supported(struct vmw_private *vmw) { - if ((vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS | - SVGA_CAP_CMD_BUFFERS_2)) != 0) - return true; + bool has_cmdbufs = + (vmw->capabilities & (SVGA_CAP_COMMAND_BUFFERS | + SVGA_CAP_CMD_BUFFERS_2)) != 0; + if (vmw_is_svga_v3(vmw)) + return (has_cmdbufs && + (vmw->capabilities & SVGA_CAP_GBOBJECTS) != 0); /* * We have FIFO cmd's */ - return vmw->fifo_mem != NULL; + return has_cmdbufs || vmw->fifo_mem != NULL; } From f99f55690798b7fb9ce8877c74d1c126998a14b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Tue, 15 Mar 2022 13:51:22 -0700 Subject: [PATCH 00286/11454] drm/i915/display/adlp: More voltage swing table updates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A few more updates in the alderlake-P voltage swing tables. eDP HBR3 table was the same as icelake one but now it has changes for voltage 0 and pre-emphasis 2 line. And DP tables also had one line change in each. Bspec: 49291 Signed-off-by: José Roberto de Souza Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315205122.202701-1-jose.souza@intel.com --- .../drm/i915/display/intel_ddi_buf_trans.c | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c index 2ed52763fcf2..fca8f5b3cffe 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c +++ b/drivers/gpu/drm/i915/display/intel_ddi_buf_trans.c @@ -907,7 +907,7 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr[] = { { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */ { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */ { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */ - { .icl = { 0xC, 0x73, 0x3E, 0x00, 0x01 } }, /* 650 700 0.6 */ + { .icl = { 0xC, 0x7C, 0x3C, 0x00, 0x03 } }, /* 650 700 0.6 */ { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */ { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */ }; @@ -921,7 +921,7 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_hbr3[ /* NT mV Trans mV db */ { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */ { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */ - { .icl = { 0xC, 0x71, 0x2F, 0x00, 0x10 } }, /* 350 700 6.0 */ + { .icl = { 0xC, 0x71, 0x30, 0x00, 0x0F } }, /* 350 700 6.0 */ { .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } }, /* 350 900 8.2 */ { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */ { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */ @@ -945,14 +945,28 @@ static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_edp_hbr2[] = { .icl = { 0x4, 0x7A, 0x38, 0x00, 0x07 } }, /* 350 350 0.0 */ }; +static const union intel_ddi_buf_trans_entry _adlp_combo_phy_trans_dp_hbr2_edp_hbr3[] = { + /* NT mV Trans mV db */ + { .icl = { 0xA, 0x35, 0x3F, 0x00, 0x00 } }, /* 350 350 0.0 */ + { .icl = { 0xA, 0x4F, 0x37, 0x00, 0x08 } }, /* 350 500 3.1 */ + { .icl = { 0xC, 0x71, 0x30, 0x00, 0x0f } }, /* 350 700 6.0 */ + { .icl = { 0x6, 0x7F, 0x2B, 0x00, 0x14 } }, /* 350 900 8.2 */ + { .icl = { 0xA, 0x4C, 0x3F, 0x00, 0x00 } }, /* 500 500 0.0 */ + { .icl = { 0xC, 0x73, 0x34, 0x00, 0x0B } }, /* 500 700 2.9 */ + { .icl = { 0x6, 0x7F, 0x2F, 0x00, 0x10 } }, /* 500 900 5.1 */ + { .icl = { 0xC, 0x6C, 0x3C, 0x00, 0x03 } }, /* 650 700 0.6 */ + { .icl = { 0x6, 0x7F, 0x35, 0x00, 0x0A } }, /* 600 900 3.5 */ + { .icl = { 0x6, 0x7F, 0x3F, 0x00, 0x00 } }, /* 900 900 0.0 */ +}; + static const struct intel_ddi_buf_trans adlp_combo_phy_trans_dp_hbr2_hbr3 = { .entries = _adlp_combo_phy_trans_dp_hbr2_hbr3, .num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_dp_hbr2_hbr3), }; static const struct intel_ddi_buf_trans adlp_combo_phy_trans_edp_hbr3 = { - .entries = _icl_combo_phy_trans_dp_hbr2_edp_hbr3, - .num_entries = ARRAY_SIZE(_icl_combo_phy_trans_dp_hbr2_edp_hbr3), + .entries = _adlp_combo_phy_trans_dp_hbr2_edp_hbr3, + .num_entries = ARRAY_SIZE(_adlp_combo_phy_trans_dp_hbr2_edp_hbr3), }; static const struct intel_ddi_buf_trans adlp_combo_phy_trans_edp_up_to_hbr2 = { From 7d4561722c3b9233865e327e0497e269eee76d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Mar 2022 21:11:59 +0200 Subject: [PATCH 00287/11454] drm/i915: Tweak plane ddb allocation tracking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Let's store the plane allocation in a manner which more closely matches how the hw operates. That is, we store the packed/CbCr ddb in one struct, and the Y ddb in another. Currently we're storing packed/Y in one struct, CbCr in the other. This also works pretty well for icl+ where the UV plane is the main plane and the Y plane is subservient to it. Although in this case we do not even use ddb_y as we do the ddb allocation in terms of hw planes. v2: Rebase Reviewed-by: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-2-ville.syrjala@linux.intel.com --- .../gpu/drm/i915/display/intel_atomic_plane.c | 32 +++--- drivers/gpu/drm/i915/display/intel_bw.c | 6 +- drivers/gpu/drm/i915/display/intel_display.c | 8 +- .../drm/i915/display/intel_display_debugfs.c | 4 +- .../drm/i915/display/intel_display_types.h | 7 +- drivers/gpu/drm/i915/intel_pm.c | 108 ++++++++---------- 6 files changed, 74 insertions(+), 91 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index f4d2814867d7..2dca3122cce0 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -616,8 +616,8 @@ int intel_plane_atomic_check(struct intel_atomic_state *state, static struct intel_plane * skl_next_plane_to_commit(struct intel_atomic_state *state, struct intel_crtc *crtc, - struct skl_ddb_entry entries_y[I915_MAX_PLANES], - struct skl_ddb_entry entries_uv[I915_MAX_PLANES], + struct skl_ddb_entry ddb[I915_MAX_PLANES], + struct skl_ddb_entry ddb_y[I915_MAX_PLANES], unsigned int *update_mask) { struct intel_crtc_state *crtc_state = @@ -636,17 +636,15 @@ skl_next_plane_to_commit(struct intel_atomic_state *state, !(*update_mask & BIT(plane_id))) continue; - if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id], - entries_y, - I915_MAX_PLANES, plane_id) || - skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_uv[plane_id], - entries_uv, - I915_MAX_PLANES, plane_id)) + if (skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb[plane_id], + ddb, I915_MAX_PLANES, plane_id) || + skl_ddb_allocation_overlaps(&crtc_state->wm.skl.plane_ddb_y[plane_id], + ddb_y, I915_MAX_PLANES, plane_id)) continue; *update_mask &= ~BIT(plane_id); - entries_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id]; - entries_uv[plane_id] = crtc_state->wm.skl.plane_ddb_uv[plane_id]; + ddb[plane_id] = crtc_state->wm.skl.plane_ddb[plane_id]; + ddb_y[plane_id] = crtc_state->wm.skl.plane_ddb_y[plane_id]; return plane; } @@ -728,19 +726,17 @@ static void skl_crtc_planes_update_arm(struct intel_atomic_state *state, intel_atomic_get_old_crtc_state(state, crtc); struct intel_crtc_state *new_crtc_state = intel_atomic_get_new_crtc_state(state, crtc); - struct skl_ddb_entry entries_y[I915_MAX_PLANES]; - struct skl_ddb_entry entries_uv[I915_MAX_PLANES]; + struct skl_ddb_entry ddb[I915_MAX_PLANES]; + struct skl_ddb_entry ddb_y[I915_MAX_PLANES]; u32 update_mask = new_crtc_state->update_planes; struct intel_plane *plane; - memcpy(entries_y, old_crtc_state->wm.skl.plane_ddb_y, + memcpy(ddb, old_crtc_state->wm.skl.plane_ddb, + sizeof(old_crtc_state->wm.skl.plane_ddb)); + memcpy(ddb_y, old_crtc_state->wm.skl.plane_ddb_y, sizeof(old_crtc_state->wm.skl.plane_ddb_y)); - memcpy(entries_uv, old_crtc_state->wm.skl.plane_ddb_uv, - sizeof(old_crtc_state->wm.skl.plane_ddb_uv)); - while ((plane = skl_next_plane_to_commit(state, crtc, - entries_y, entries_uv, - &update_mask))) { + while ((plane = skl_next_plane_to_commit(state, crtc, ddb, ddb_y, &update_mask))) { struct intel_plane_state *new_plane_state = intel_atomic_get_new_plane_state(state, plane); diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 395e48930b08..baa9b1d7ab6c 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -688,16 +688,16 @@ static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state, return; for_each_plane_id_on_crtc(crtc, plane_id) { + const struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; const struct skl_ddb_entry *ddb_y = &crtc_state->wm.skl.plane_ddb_y[plane_id]; - const struct skl_ddb_entry *ddb_uv = - &crtc_state->wm.skl.plane_ddb_uv[plane_id]; unsigned int data_rate = crtc_state->data_rate[plane_id]; unsigned int dbuf_mask = 0; enum dbuf_slice slice; + dbuf_mask |= skl_ddb_dbuf_slice_mask(i915, ddb); dbuf_mask |= skl_ddb_dbuf_slice_mask(i915, ddb_y); - dbuf_mask |= skl_ddb_dbuf_slice_mask(i915, ddb_uv); /* * FIXME: To calculate that more properly we probably diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6ed976b77b1c..c138972a2bef 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -6508,8 +6508,8 @@ static void verify_wm_state(struct intel_crtc *crtc, { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); struct skl_hw_state { + struct skl_ddb_entry ddb[I915_MAX_PLANES]; struct skl_ddb_entry ddb_y[I915_MAX_PLANES]; - struct skl_ddb_entry ddb_uv[I915_MAX_PLANES]; struct skl_pipe_wm wm; } *hw; const struct skl_pipe_wm *sw_wm = &new_crtc_state->wm.skl.optimal; @@ -6526,7 +6526,7 @@ static void verify_wm_state(struct intel_crtc *crtc, skl_pipe_wm_get_hw_state(crtc, &hw->wm); - skl_pipe_ddb_get_hw_state(crtc, hw->ddb_y, hw->ddb_uv); + skl_pipe_ddb_get_hw_state(crtc, hw->ddb, hw->ddb_y); hw_enabled_slices = intel_enabled_dbuf_slices_mask(dev_priv); @@ -6608,8 +6608,8 @@ static void verify_wm_state(struct intel_crtc *crtc, } /* DDB */ - hw_ddb_entry = &hw->ddb_y[plane->id]; - sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb_y[plane->id]; + hw_ddb_entry = &hw->ddb[PLANE_CURSOR]; + sw_ddb_entry = &new_crtc_state->wm.skl.plane_ddb[PLANE_CURSOR]; if (!skl_ddb_entry_equal(hw_ddb_entry, sw_ddb_entry)) { drm_err(&dev_priv->drm, diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index e0a126e7ebb8..101e57384832 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1125,13 +1125,13 @@ static int i915_ddb_info(struct seq_file *m, void *unused) seq_printf(m, "Pipe %c\n", pipe_name(pipe)); for_each_plane_id_on_crtc(crtc, plane_id) { - entry = &crtc_state->wm.skl.plane_ddb_y[plane_id]; + entry = &crtc_state->wm.skl.plane_ddb[plane_id]; seq_printf(m, " Plane%-8d%8u%8u%8u\n", plane_id + 1, entry->start, entry->end, skl_ddb_entry_size(entry)); } - entry = &crtc_state->wm.skl.plane_ddb_y[PLANE_CURSOR]; + entry = &crtc_state->wm.skl.plane_ddb[PLANE_CURSOR]; seq_printf(m, " %-13s%8u%8u%8u\n", "Cursor", entry->start, entry->end, skl_ddb_entry_size(entry)); } diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index c94eb7d5191d..71d5a9eb8706 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -846,8 +846,13 @@ struct intel_crtc_wm_state { /* gen9+ only needs 1-step wm programming */ struct skl_pipe_wm optimal; struct skl_ddb_entry ddb; + /* + * pre-icl: for packed/planar CbCr + * icl+: for everything + */ + struct skl_ddb_entry plane_ddb[I915_MAX_PLANES]; + /* pre-icl: for planar Y */ struct skl_ddb_entry plane_ddb_y[I915_MAX_PLANES]; - struct skl_ddb_entry plane_ddb_uv[I915_MAX_PLANES]; } skl; struct { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index bd936d4c5b0f..073a52e28a4d 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4346,46 +4346,31 @@ static void skl_ddb_get_hw_plane_state(struct drm_i915_private *dev_priv, const enum pipe pipe, const enum plane_id plane_id, - struct skl_ddb_entry *ddb_y, - struct skl_ddb_entry *ddb_uv) + struct skl_ddb_entry *ddb, + struct skl_ddb_entry *ddb_y) { - u32 val, val2; - u32 fourcc = 0; + u32 val; /* Cursor doesn't support NV12/planar, so no extra calculation needed */ if (plane_id == PLANE_CURSOR) { val = intel_uncore_read(&dev_priv->uncore, CUR_BUF_CFG(pipe)); - skl_ddb_entry_init_from_hw(ddb_y, val); + skl_ddb_entry_init_from_hw(ddb, val); return; } - val = intel_uncore_read(&dev_priv->uncore, PLANE_CTL(pipe, plane_id)); + val = intel_uncore_read(&dev_priv->uncore, PLANE_BUF_CFG(pipe, plane_id)); + skl_ddb_entry_init_from_hw(ddb, val); - /* No DDB allocated for disabled planes */ - if (val & PLANE_CTL_ENABLE) - fourcc = skl_format_to_fourcc(val & PLANE_CTL_FORMAT_MASK_SKL, - val & PLANE_CTL_ORDER_RGBX, - val & PLANE_CTL_ALPHA_MASK); + if (DISPLAY_VER(dev_priv) >= 11) + return; - if (DISPLAY_VER(dev_priv) >= 11) { - val = intel_uncore_read(&dev_priv->uncore, PLANE_BUF_CFG(pipe, plane_id)); - skl_ddb_entry_init_from_hw(ddb_y, val); - } else { - val = intel_uncore_read(&dev_priv->uncore, PLANE_BUF_CFG(pipe, plane_id)); - val2 = intel_uncore_read(&dev_priv->uncore, PLANE_NV12_BUF_CFG(pipe, plane_id)); - - if (fourcc && - drm_format_info_is_yuv_semiplanar(drm_format_info(fourcc))) - swap(val, val2); - - skl_ddb_entry_init_from_hw(ddb_y, val); - skl_ddb_entry_init_from_hw(ddb_uv, val2); - } + val = intel_uncore_read(&dev_priv->uncore, PLANE_NV12_BUF_CFG(pipe, plane_id)); + skl_ddb_entry_init_from_hw(ddb_y, val); } void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, - struct skl_ddb_entry *ddb_y, - struct skl_ddb_entry *ddb_uv) + struct skl_ddb_entry *ddb, + struct skl_ddb_entry *ddb_y) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum intel_display_power_domain power_domain; @@ -4401,8 +4386,8 @@ void skl_pipe_ddb_get_hw_state(struct intel_crtc *crtc, for_each_plane_id_on_crtc(crtc, plane_id) skl_ddb_get_hw_plane_state(dev_priv, pipe, plane_id, - &ddb_y[plane_id], - &ddb_uv[plane_id]); + &ddb[plane_id], + &ddb_y[plane_id]); intel_display_power_put(dev_priv, power_domain, wakeref); } @@ -5195,8 +5180,8 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, int level; /* Clear the partitioning for disabled planes. */ + memset(crtc_state->wm.skl.plane_ddb, 0, sizeof(crtc_state->wm.skl.plane_ddb)); memset(crtc_state->wm.skl.plane_ddb_y, 0, sizeof(crtc_state->wm.skl.plane_ddb_y)); - memset(crtc_state->wm.skl.plane_ddb_uv, 0, sizeof(crtc_state->wm.skl.plane_ddb_uv)); if (!crtc_state->hw.active) return 0; @@ -5213,7 +5198,7 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, /* Allocate fixed number of blocks for cursor. */ iter.total[PLANE_CURSOR] = skl_cursor_allocation(crtc_state, num_active); iter.size -= iter.total[PLANE_CURSOR]; - skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb_y[PLANE_CURSOR], + skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR], alloc->end - iter.total[PLANE_CURSOR], alloc->end); /* @@ -5283,10 +5268,10 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, /* Set the actual DDB start/end points for each plane */ iter.start = alloc->start; for_each_plane_id_on_crtc(crtc, plane_id) { - struct skl_ddb_entry *plane_alloc = + struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; + struct skl_ddb_entry *ddb_y = &crtc_state->wm.skl.plane_ddb_y[plane_id]; - struct skl_ddb_entry *uv_plane_alloc = - &crtc_state->wm.skl.plane_ddb_uv[plane_id]; if (plane_id == PLANE_CURSOR) continue; @@ -5297,12 +5282,15 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, /* Leave disabled planes at (0,0) */ if (iter.total[plane_id]) - iter.start = skl_ddb_entry_init(plane_alloc, iter.start, + iter.start = skl_ddb_entry_init(ddb, iter.start, iter.start + iter.total[plane_id]); - if (iter.uv_total[plane_id]) - iter.start = skl_ddb_entry_init(uv_plane_alloc, iter.start, + if (iter.uv_total[plane_id]) { + /* hardware wants these swapped */ + *ddb_y = *ddb; + iter.start = skl_ddb_entry_init(ddb, iter.start, iter.start + iter.uv_total[plane_id]); + } } /* @@ -5962,11 +5950,10 @@ void skl_write_plane_wm(struct intel_plane *plane, enum plane_id plane_id = plane->id; enum pipe pipe = plane->pipe; const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; - const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; + const struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; const struct skl_ddb_entry *ddb_y = &crtc_state->wm.skl.plane_ddb_y[plane_id]; - const struct skl_ddb_entry *ddb_uv = - &crtc_state->wm.skl.plane_ddb_uv[plane_id]; for (level = 0; level <= max_level; level++) skl_write_wm_level(dev_priv, PLANE_WM(pipe, plane_id, level), @@ -5976,25 +5963,20 @@ void skl_write_plane_wm(struct intel_plane *plane, skl_plane_trans_wm(pipe_wm, plane_id)); if (HAS_HW_SAGV_WM(dev_priv)) { + const struct skl_plane_wm *wm = &pipe_wm->planes[plane_id]; + skl_write_wm_level(dev_priv, PLANE_WM_SAGV(pipe, plane_id), &wm->sagv.wm0); skl_write_wm_level(dev_priv, PLANE_WM_SAGV_TRANS(pipe, plane_id), &wm->sagv.trans_wm); } - if (DISPLAY_VER(dev_priv) >= 11) { + skl_ddb_entry_write(dev_priv, + PLANE_BUF_CFG(pipe, plane_id), ddb); + + if (DISPLAY_VER(dev_priv) < 11) skl_ddb_entry_write(dev_priv, - PLANE_BUF_CFG(pipe, plane_id), ddb_y); - return; - } - - if (wm->is_planar) - swap(ddb_y, ddb_uv); - - skl_ddb_entry_write(dev_priv, - PLANE_BUF_CFG(pipe, plane_id), ddb_y); - skl_ddb_entry_write(dev_priv, - PLANE_NV12_BUF_CFG(pipe, plane_id), ddb_uv); + PLANE_NV12_BUF_CFG(pipe, plane_id), ddb_y); } void skl_write_cursor_wm(struct intel_plane *plane, @@ -6006,7 +5988,7 @@ void skl_write_cursor_wm(struct intel_plane *plane, enum pipe pipe = plane->pipe; const struct skl_pipe_wm *pipe_wm = &crtc_state->wm.skl.optimal; const struct skl_ddb_entry *ddb = - &crtc_state->wm.skl.plane_ddb_y[plane_id]; + &crtc_state->wm.skl.plane_ddb[plane_id]; for (level = 0; level <= max_level; level++) skl_write_wm_level(dev_priv, CUR_WM(pipe, level), @@ -6103,10 +6085,10 @@ skl_ddb_add_affected_planes(const struct intel_crtc_state *old_crtc_state, struct intel_plane_state *plane_state; enum plane_id plane_id = plane->id; - if (skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_y[plane_id], - &new_crtc_state->wm.skl.plane_ddb_y[plane_id]) && - skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_uv[plane_id], - &new_crtc_state->wm.skl.plane_ddb_uv[plane_id])) + if (skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb[plane_id], + &new_crtc_state->wm.skl.plane_ddb[plane_id]) && + skl_ddb_entry_equal(&old_crtc_state->wm.skl.plane_ddb_y[plane_id], + &new_crtc_state->wm.skl.plane_ddb_y[plane_id])) continue; plane_state = intel_atomic_get_plane_state(state, plane); @@ -6275,8 +6257,8 @@ skl_print_wm_changes(struct intel_atomic_state *state) enum plane_id plane_id = plane->id; const struct skl_ddb_entry *old, *new; - old = &old_crtc_state->wm.skl.plane_ddb_y[plane_id]; - new = &new_crtc_state->wm.skl.plane_ddb_y[plane_id]; + old = &old_crtc_state->wm.skl.plane_ddb[plane_id]; + new = &new_crtc_state->wm.skl.plane_ddb[plane_id]; if (skl_ddb_entry_equal(old, new)) continue; @@ -6678,16 +6660,16 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) memset(&dbuf_state->ddb[pipe], 0, sizeof(dbuf_state->ddb[pipe])); for_each_plane_id_on_crtc(crtc, plane_id) { + struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; struct skl_ddb_entry *ddb_y = &crtc_state->wm.skl.plane_ddb_y[plane_id]; - struct skl_ddb_entry *ddb_uv = - &crtc_state->wm.skl.plane_ddb_uv[plane_id]; skl_ddb_get_hw_plane_state(dev_priv, crtc->pipe, - plane_id, ddb_y, ddb_uv); + plane_id, ddb, ddb_y); + skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb); skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_y); - skl_ddb_entry_union(&dbuf_state->ddb[pipe], ddb_uv); } dbuf_state->weight[pipe] = intel_crtc_ddb_weight(crtc_state); From 943ed3cc02191b220eb430dc855509ccc2c1a28e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Mar 2022 21:12:00 +0200 Subject: [PATCH 00288/11454] drm/i915: Split plane data_rate into data_rate+data_rate_y MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the currently combined plane data_rate into the proper Y vs. CbCr components. This matches how we now track the plane dbuf allocations, and thus will make the dbuf bandwidth calculations actually produce the correct numbers for each dbuf slice. Reviewed-by: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-3-ville.syrjala@linux.intel.com --- .../gpu/drm/i915/display/intel_atomic_plane.c | 34 ++++++++---------- .../gpu/drm/i915/display/intel_atomic_plane.h | 3 +- drivers/gpu/drm/i915/display/intel_bw.c | 36 +++++++++---------- drivers/gpu/drm/i915/display/intel_display.c | 4 +++ .../drm/i915/display/intel_display_types.h | 3 ++ 5 files changed, 42 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index 2dca3122cce0..b6c80824aea1 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -181,29 +181,16 @@ unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state, } unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state) + const struct intel_plane_state *plane_state, + int color_plane) { const struct drm_framebuffer *fb = plane_state->hw.fb; - unsigned int cpp; - unsigned int pixel_rate; if (!plane_state->uapi.visible) return 0; - pixel_rate = intel_plane_pixel_rate(crtc_state, plane_state); - - cpp = fb->format->cpp[0]; - - /* - * Based on HSD#:1408715493 - * NV12 cpp == 4, P010 cpp == 8 - * - * FIXME what is the logic behind this? - */ - if (fb->format->is_yuv && fb->format->num_planes > 1) - cpp *= 4; - - return pixel_rate * cpp; + return intel_plane_pixel_rate(crtc_state, plane_state) * + fb->format->cpp[color_plane]; } int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, @@ -326,6 +313,7 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, crtc_state->nv12_planes &= ~BIT(plane->id); crtc_state->c8_planes &= ~BIT(plane->id); crtc_state->data_rate[plane->id] = 0; + crtc_state->data_rate_y[plane->id] = 0; crtc_state->min_cdclk[plane->id] = 0; plane_state->uapi.visible = false; @@ -551,8 +539,16 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ if (new_plane_state->uapi.visible || old_plane_state->uapi.visible) new_crtc_state->update_planes |= BIT(plane->id); - new_crtc_state->data_rate[plane->id] = - intel_plane_data_rate(new_crtc_state, new_plane_state); + if (new_plane_state->uapi.visible && + intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) { + new_crtc_state->data_rate_y[plane->id] = + intel_plane_data_rate(new_crtc_state, new_plane_state, 0); + new_crtc_state->data_rate[plane->id] = + intel_plane_data_rate(new_crtc_state, new_plane_state, 1); + } else if (new_plane_state->uapi.visible) { + new_crtc_state->data_rate[plane->id] = + intel_plane_data_rate(new_crtc_state, new_plane_state, 0); + } return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state, old_plane_state, new_plane_state); diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.h b/drivers/gpu/drm/i915/display/intel_atomic_plane.h index f4763a53541e..74b6d3b169a7 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.h +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.h @@ -25,7 +25,8 @@ unsigned int intel_plane_pixel_rate(const struct intel_crtc_state *crtc_state, const struct intel_plane_state *plane_state); unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state); + const struct intel_plane_state *plane_state, + int color_plane); void intel_plane_copy_uapi_to_hw_state(struct intel_plane_state *plane_state, const struct intel_plane_state *from_plane_state, struct intel_crtc *crtc); diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index baa9b1d7ab6c..5517d1ac78d6 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -578,6 +578,7 @@ static unsigned int intel_bw_crtc_num_active_planes(const struct intel_crtc_stat static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); unsigned int data_rate = 0; enum plane_id plane_id; @@ -590,6 +591,9 @@ static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_ continue; data_rate += crtc_state->data_rate[plane_id]; + + if (DISPLAY_VER(i915) < 11) + data_rate += crtc_state->data_rate_y[plane_id]; } return data_rate; @@ -690,28 +694,24 @@ static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state, for_each_plane_id_on_crtc(crtc, plane_id) { const struct skl_ddb_entry *ddb = &crtc_state->wm.skl.plane_ddb[plane_id]; - const struct skl_ddb_entry *ddb_y = - &crtc_state->wm.skl.plane_ddb_y[plane_id]; unsigned int data_rate = crtc_state->data_rate[plane_id]; - unsigned int dbuf_mask = 0; + unsigned int dbuf_mask = skl_ddb_dbuf_slice_mask(i915, ddb); enum dbuf_slice slice; - dbuf_mask |= skl_ddb_dbuf_slice_mask(i915, ddb); - dbuf_mask |= skl_ddb_dbuf_slice_mask(i915, ddb_y); + for_each_dbuf_slice_in_mask(i915, slice, dbuf_mask) + crtc_bw->used_bw[slice] += data_rate; + } + + if (DISPLAY_VER(i915) >= 11) + return; + + for_each_plane_id_on_crtc(crtc, plane_id) { + const struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb_y[plane_id]; + unsigned int data_rate = crtc_state->data_rate_y[plane_id]; + unsigned int dbuf_mask = skl_ddb_dbuf_slice_mask(i915, ddb); + enum dbuf_slice slice; - /* - * FIXME: To calculate that more properly we probably - * need to split per plane data_rate into data_rate_y - * and data_rate_uv for multiplanar formats in order not - * to get accounted those twice if they happen to reside - * on different slices. - * However for pre-icl this would work anyway because - * we have only single slice and for icl+ uv plane has - * non-zero data rate. - * So in worst case those calculation are a bit - * pessimistic, which shouldn't pose any significant - * problem anyway. - */ for_each_dbuf_slice_in_mask(i915, slice, dbuf_mask) crtc_bw->used_bw[slice] += data_rate; } diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index c138972a2bef..853f943d5138 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -780,6 +780,7 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, intel_set_plane_visible(crtc_state, plane_state, false); fixup_plane_bitmasks(crtc_state); crtc_state->data_rate[plane->id] = 0; + crtc_state->data_rate_y[plane->id] = 0; crtc_state->min_cdclk[plane->id] = 0; if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 && @@ -4813,6 +4814,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) crtc_state->enabled_planes &= ~BIT(plane->id); crtc_state->active_planes &= ~BIT(plane->id); crtc_state->update_planes |= BIT(plane->id); + crtc_state->data_rate[plane->id] = 0; } plane_state->planar_slave = false; @@ -4857,6 +4859,8 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) crtc_state->enabled_planes |= BIT(linked->id); crtc_state->active_planes |= BIT(linked->id); crtc_state->update_planes |= BIT(linked->id); + crtc_state->data_rate[linked->id] = + crtc_state->data_rate_y[plane->id]; drm_dbg_kms(&dev_priv->drm, "Using %s as Y plane for %s\n", linked->base.name, plane->base.name); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 71d5a9eb8706..55ce91e4bb71 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1129,7 +1129,10 @@ struct intel_crtc_state { int min_cdclk[I915_MAX_PLANES]; + /* for packed/planar CbCr */ u32 data_rate[I915_MAX_PLANES]; + /* for planar Y */ + u32 data_rate_y[I915_MAX_PLANES]; /* FIXME unify with data_rate[] */ u64 plane_data_rate[I915_MAX_PLANES]; From c034363ca898ea0f809efb113e232dfd0b3e59f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Mar 2022 21:12:01 +0200 Subject: [PATCH 00289/11454] drm/i915: Pre-calculate plane relative data rate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Handle the plane relative data rate in exactly the same way as we already handle the real data rate. Ie. pre-calculate it during intel_plane_atomic_check_with_state(), and assign/clear it for the Y plane as needed. This should guarantee that the tracking is 100% consistent, and makes me have to think less when the same apporach is used by both types of data rate. We might even want to consider replacing the relative data rate with the real data rate entirely, but it's not clear if that will produce less optimal plane ddb allocations. So for now lets keep using the current approach. v2: Rebase due to async flip wm optimization Reviewed-by: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-4-ville.syrjala@linux.intel.com --- .../gpu/drm/i915/display/intel_atomic_plane.c | 64 ++++++ drivers/gpu/drm/i915/display/intel_display.c | 5 + .../drm/i915/display/intel_display_types.h | 6 +- drivers/gpu/drm/i915/intel_pm.c | 187 ++++-------------- 4 files changed, 108 insertions(+), 154 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_atomic_plane.c b/drivers/gpu/drm/i915/display/intel_atomic_plane.c index b6c80824aea1..3d87da283cfa 100644 --- a/drivers/gpu/drm/i915/display/intel_atomic_plane.c +++ b/drivers/gpu/drm/i915/display/intel_atomic_plane.c @@ -193,6 +193,57 @@ unsigned int intel_plane_data_rate(const struct intel_crtc_state *crtc_state, fb->format->cpp[color_plane]; } +static bool +use_min_ddb(const struct intel_crtc_state *crtc_state, + struct intel_plane *plane) +{ + struct drm_i915_private *i915 = to_i915(plane->base.dev); + + return DISPLAY_VER(i915) >= 13 && + crtc_state->uapi.async_flip && + plane->async_flip; +} + +static unsigned int +intel_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, + const struct intel_plane_state *plane_state, + int color_plane) +{ + struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); + const struct drm_framebuffer *fb = plane_state->hw.fb; + int width, height; + + if (plane->id == PLANE_CURSOR) + return 0; + + if (!plane_state->uapi.visible) + return 0; + + /* + * We calculate extra ddb based on ratio plane rate/total data rate + * in case, in some cases we should not allocate extra ddb for the plane, + * so do not count its data rate, if this is the case. + */ + if (use_min_ddb(crtc_state, plane)) + return 0; + + /* + * Src coordinates are already rotated by 270 degrees for + * the 90/270 degree plane rotation cases (to match the + * GTT mapping), hence no need to account for rotation here. + */ + width = drm_rect_width(&plane_state->uapi.src) >> 16; + height = drm_rect_height(&plane_state->uapi.src) >> 16; + + /* UV plane does 1/2 pixel sub-sampling */ + if (color_plane == 1) { + width /= 2; + height /= 2; + } + + return width * height * fb->format->cpp[color_plane]; +} + int intel_plane_calc_min_cdclk(struct intel_atomic_state *state, struct intel_plane *plane, bool *need_cdclk_calc) @@ -314,6 +365,8 @@ void intel_plane_set_invisible(struct intel_crtc_state *crtc_state, crtc_state->c8_planes &= ~BIT(plane->id); crtc_state->data_rate[plane->id] = 0; crtc_state->data_rate_y[plane->id] = 0; + crtc_state->rel_data_rate[plane->id] = 0; + crtc_state->rel_data_rate_y[plane->id] = 0; crtc_state->min_cdclk[plane->id] = 0; plane_state->uapi.visible = false; @@ -545,9 +598,20 @@ int intel_plane_atomic_check_with_state(const struct intel_crtc_state *old_crtc_ intel_plane_data_rate(new_crtc_state, new_plane_state, 0); new_crtc_state->data_rate[plane->id] = intel_plane_data_rate(new_crtc_state, new_plane_state, 1); + + new_crtc_state->rel_data_rate_y[plane->id] = + intel_plane_relative_data_rate(new_crtc_state, + new_plane_state, 0); + new_crtc_state->rel_data_rate[plane->id] = + intel_plane_relative_data_rate(new_crtc_state, + new_plane_state, 1); } else if (new_plane_state->uapi.visible) { new_crtc_state->data_rate[plane->id] = intel_plane_data_rate(new_crtc_state, new_plane_state, 0); + + new_crtc_state->rel_data_rate[plane->id] = + intel_plane_relative_data_rate(new_crtc_state, + new_plane_state, 0); } return intel_plane_atomic_calc_changes(old_crtc_state, new_crtc_state, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 853f943d5138..39dbc7f69d4d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -781,6 +781,8 @@ void intel_plane_disable_noatomic(struct intel_crtc *crtc, fixup_plane_bitmasks(crtc_state); crtc_state->data_rate[plane->id] = 0; crtc_state->data_rate_y[plane->id] = 0; + crtc_state->rel_data_rate[plane->id] = 0; + crtc_state->rel_data_rate_y[plane->id] = 0; crtc_state->min_cdclk[plane->id] = 0; if ((crtc_state->active_planes & ~BIT(PLANE_CURSOR)) == 0 && @@ -4815,6 +4817,7 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) crtc_state->active_planes &= ~BIT(plane->id); crtc_state->update_planes |= BIT(plane->id); crtc_state->data_rate[plane->id] = 0; + crtc_state->rel_data_rate[plane->id] = 0; } plane_state->planar_slave = false; @@ -4861,6 +4864,8 @@ static int icl_check_nv12_planes(struct intel_crtc_state *crtc_state) crtc_state->update_planes |= BIT(linked->id); crtc_state->data_rate[linked->id] = crtc_state->data_rate_y[plane->id]; + crtc_state->rel_data_rate[linked->id] = + crtc_state->rel_data_rate_y[plane->id]; drm_dbg_kms(&dev_priv->drm, "Using %s as Y plane for %s\n", linked->base.name, plane->base.name); diff --git a/drivers/gpu/drm/i915/display/intel_display_types.h b/drivers/gpu/drm/i915/display/intel_display_types.h index 55ce91e4bb71..96024f7d839d 100644 --- a/drivers/gpu/drm/i915/display/intel_display_types.h +++ b/drivers/gpu/drm/i915/display/intel_display_types.h @@ -1134,9 +1134,9 @@ struct intel_crtc_state { /* for planar Y */ u32 data_rate_y[I915_MAX_PLANES]; - /* FIXME unify with data_rate[] */ - u64 plane_data_rate[I915_MAX_PLANES]; - u64 uv_plane_data_rate[I915_MAX_PLANES]; + /* FIXME unify with data_rate[]? */ + u64 rel_data_rate[I915_MAX_PLANES]; + u64 rel_data_rate_y[I915_MAX_PLANES]; /* Gamma mode programmed on the pipe */ u32 gamma_mode; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 073a52e28a4d..34c381803632 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4918,17 +4918,6 @@ static u8 skl_compute_dbuf_slices(struct intel_crtc *crtc, u8 active_pipes, bool return active_pipes & BIT(pipe) ? BIT(DBUF_S1) : 0; } -static bool -use_min_ddb(const struct intel_crtc_state *crtc_state, - struct intel_plane *plane) -{ - struct drm_i915_private *i915 = to_i915(plane->base.dev); - - return DISPLAY_VER(i915) >= 13 && - crtc_state->uapi.async_flip && - plane->async_flip; -} - static bool use_minimal_wm0_only(const struct intel_crtc_state *crtc_state, struct intel_plane *plane) @@ -4941,134 +4930,24 @@ use_minimal_wm0_only(const struct intel_crtc_state *crtc_state, } static u64 -skl_plane_relative_data_rate(const struct intel_crtc_state *crtc_state, - const struct intel_plane_state *plane_state, - int color_plane) +skl_total_relative_data_rate(const struct intel_crtc_state *crtc_state) { - struct intel_plane *plane = to_intel_plane(plane_state->uapi.plane); - const struct drm_framebuffer *fb = plane_state->hw.fb; - int width, height; - - if (!plane_state->uapi.visible) - return 0; - - if (plane->id == PLANE_CURSOR) - return 0; - - /* - * We calculate extra ddb based on ratio plane rate/total data rate - * in case, in some cases we should not allocate extra ddb for the plane, - * so do not count its data rate, if this is the case. - */ - if (use_min_ddb(crtc_state, plane)) - return 0; - - if (color_plane == 1 && - !intel_format_info_is_yuv_semiplanar(fb->format, fb->modifier)) - return 0; - - /* - * Src coordinates are already rotated by 270 degrees for - * the 90/270 degree plane rotation cases (to match the - * GTT mapping), hence no need to account for rotation here. - */ - width = drm_rect_width(&plane_state->uapi.src) >> 16; - height = drm_rect_height(&plane_state->uapi.src) >> 16; - - /* UV plane does 1/2 pixel sub-sampling */ - if (color_plane == 1) { - width /= 2; - height /= 2; - } - - return width * height * fb->format->cpp[color_plane]; -} - -static u64 -skl_get_total_relative_data_rate(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - const struct intel_plane_state *plane_state; - struct intel_plane *plane; - u64 total_data_rate = 0; + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); enum plane_id plane_id; - int i; - - /* Calculate and cache data rate for each plane */ - for_each_new_intel_plane_in_state(state, plane, plane_state, i) { - if (plane->pipe != crtc->pipe) - continue; - - plane_id = plane->id; - - /* packed/y */ - crtc_state->plane_data_rate[plane_id] = - skl_plane_relative_data_rate(crtc_state, plane_state, 0); - - /* uv-plane */ - crtc_state->uv_plane_data_rate[plane_id] = - skl_plane_relative_data_rate(crtc_state, plane_state, 1); - } + u64 data_rate = 0; for_each_plane_id_on_crtc(crtc, plane_id) { - total_data_rate += crtc_state->plane_data_rate[plane_id]; - total_data_rate += crtc_state->uv_plane_data_rate[plane_id]; - } - - return total_data_rate; -} - -static u64 -icl_get_total_relative_data_rate(struct intel_atomic_state *state, - struct intel_crtc *crtc) -{ - struct intel_crtc_state *crtc_state = - intel_atomic_get_new_crtc_state(state, crtc); - const struct intel_plane_state *plane_state; - struct intel_plane *plane; - u64 total_data_rate = 0; - enum plane_id plane_id; - int i; - - /* Calculate and cache data rate for each plane */ - for_each_new_intel_plane_in_state(state, plane, plane_state, i) { - if (plane->pipe != crtc->pipe) + if (plane_id == PLANE_CURSOR) continue; - plane_id = plane->id; + data_rate += crtc_state->rel_data_rate[plane_id]; - if (!plane_state->planar_linked_plane) { - crtc_state->plane_data_rate[plane_id] = - skl_plane_relative_data_rate(crtc_state, plane_state, 0); - } else { - enum plane_id y_plane_id; - - /* - * The slave plane might not iterate in - * intel_atomic_crtc_state_for_each_plane_state(), - * and needs the master plane state which may be - * NULL if we try get_new_plane_state(), so we - * always calculate from the master. - */ - if (plane_state->planar_slave) - continue; - - /* Y plane rate is calculated on the slave */ - y_plane_id = plane_state->planar_linked_plane->id; - crtc_state->plane_data_rate[y_plane_id] = - skl_plane_relative_data_rate(crtc_state, plane_state, 0); - - crtc_state->plane_data_rate[plane_id] = - skl_plane_relative_data_rate(crtc_state, plane_state, 1); - } + if (DISPLAY_VER(i915) < 11) + data_rate += crtc_state->rel_data_rate_y[plane_id]; } - for_each_plane_id_on_crtc(crtc, plane_id) - total_data_rate += crtc_state->plane_data_rate[plane_id]; - - return total_data_rate; + return data_rate; } const struct skl_wm_level * @@ -5186,11 +5065,6 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, if (!crtc_state->hw.active) return 0; - if (DISPLAY_VER(dev_priv) >= 11) - iter.data_rate = icl_get_total_relative_data_rate(state, crtc); - else - iter.data_rate = skl_get_total_relative_data_rate(state, crtc); - iter.size = skl_ddb_entry_size(alloc); if (iter.size == 0) return 0; @@ -5201,6 +5075,8 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR], alloc->end - iter.total[PLANE_CURSOR], alloc->end); + iter.data_rate = skl_total_relative_data_rate(crtc_state); + /* * Find the highest watermark level for which we can satisfy the block * requirement of active planes. @@ -5255,13 +5131,19 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, if (plane_id == PLANE_CURSOR) continue; - iter.total[plane_id] = - skl_allocate_plane_ddb(&iter, &wm->wm[level], - crtc_state->plane_data_rate[plane_id]); - - iter.uv_total[plane_id] = - skl_allocate_plane_ddb(&iter, &wm->uv_wm[level], - crtc_state->uv_plane_data_rate[plane_id]); + if (DISPLAY_VER(dev_priv) < 11 && + crtc_state->nv12_planes & BIT(plane_id)) { + iter.total[plane_id] = + skl_allocate_plane_ddb(&iter, &wm->wm[level], + crtc_state->rel_data_rate_y[plane_id]); + iter.uv_total[plane_id] = + skl_allocate_plane_ddb(&iter, &wm->uv_wm[level], + crtc_state->rel_data_rate[plane_id]); + } else { + iter.total[plane_id] = + skl_allocate_plane_ddb(&iter, &wm->wm[level], + crtc_state->rel_data_rate[plane_id]); + } } drm_WARN_ON(&dev_priv->drm, iter.size != 0 || iter.data_rate != 0); @@ -5281,15 +5163,18 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, DISPLAY_VER(dev_priv) >= 11 && iter.uv_total[plane_id]); /* Leave disabled planes at (0,0) */ - if (iter.total[plane_id]) - iter.start = skl_ddb_entry_init(ddb, iter.start, - iter.start + iter.total[plane_id]); - - if (iter.uv_total[plane_id]) { - /* hardware wants these swapped */ - *ddb_y = *ddb; - iter.start = skl_ddb_entry_init(ddb, iter.start, - iter.start + iter.uv_total[plane_id]); + if (DISPLAY_VER(dev_priv) < 11 && + crtc_state->nv12_planes & BIT(plane_id)) { + if (iter.total[plane_id]) + iter.start = skl_ddb_entry_init(ddb_y, iter.start, + iter.start + iter.total[plane_id]); + if (iter.uv_total[plane_id]) + iter.start = skl_ddb_entry_init(ddb, iter.start, + iter.start + iter.uv_total[plane_id]); + } else { + if (iter.total[plane_id]) + iter.start = skl_ddb_entry_init(ddb, iter.start, + iter.start + iter.total[plane_id]); } } From 0d21fd10fb3c7485e4701d9f89bf463965e28339 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Mar 2022 21:12:02 +0200 Subject: [PATCH 00290/11454] drm/i915: Remove total[] and uv_total[] from ddb allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There's really no need to maintain these total[] arrays to track the size of each plane's ddb allocation. We just stick the results straight into the crtc_state ddb tracking structures. The main annoyance with all this is the mismatch between wm_uv vs. ddb_y on pre-icl. If only the hw was consistent in what it considers the primary source of information we could avoid some of the uglyness. But since that is not the case we need a bit of special casing for planar formats. v2: Keep the ddb entry zeroed when the plane is disabled Reviewed-by: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-5-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/intel_pm.c | 124 ++++++++++++++++---------------- 1 file changed, 63 insertions(+), 61 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 34c381803632..2c3cd4d775da 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -4988,18 +4988,18 @@ skl_plane_trans_wm(const struct skl_pipe_wm *pipe_wm, * So this is actually safe to do. */ static void -skl_check_wm_level(struct skl_wm_level *wm, u64 total) +skl_check_wm_level(struct skl_wm_level *wm, const struct skl_ddb_entry *ddb) { - if (wm->min_ddb_alloc > total) + if (wm->min_ddb_alloc > skl_ddb_entry_size(ddb)) memset(wm, 0, sizeof(*wm)); } static void skl_check_nv12_wm_level(struct skl_wm_level *wm, struct skl_wm_level *uv_wm, - u64 total, u64 uv_total) + const struct skl_ddb_entry *ddb_y, const struct skl_ddb_entry *ddb) { - if (wm->min_ddb_alloc > total || - uv_wm->min_ddb_alloc > uv_total) { + if (wm->min_ddb_alloc > skl_ddb_entry_size(ddb_y) || + uv_wm->min_ddb_alloc > skl_ddb_entry_size(ddb)) { memset(wm, 0, sizeof(*wm)); memset(uv_wm, 0, sizeof(*uv_wm)); } @@ -5019,17 +5019,16 @@ static bool icl_need_wm1_wa(struct drm_i915_private *i915, struct skl_plane_ddb_iter { u64 data_rate; - u16 total[I915_MAX_PLANES]; - u16 uv_total[I915_MAX_PLANES]; u16 start, size; }; -static u16 +static void skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter, + struct skl_ddb_entry *ddb, const struct skl_wm_level *wm, u64 data_rate) { - u16 extra = 0; + u16 size, extra = 0; if (data_rate) { extra = min_t(u16, iter->size, @@ -5039,7 +5038,15 @@ skl_allocate_plane_ddb(struct skl_plane_ddb_iter *iter, iter->data_rate -= data_rate; } - return wm->min_ddb_alloc + extra; + /* + * Keep ddb entry of all disabled planes explicitly zeroed + * to avoid skl_ddb_add_affected_planes() adding them to + * the state when other planes change their allocations. + */ + size = wm->min_ddb_alloc + extra; + if (size) + iter->start = skl_ddb_entry_init(ddb, iter->start, + iter->start + size); } static int @@ -5053,8 +5060,9 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, intel_atomic_get_new_dbuf_state(state); const struct skl_ddb_entry *alloc = &dbuf_state->ddb[crtc->pipe]; int num_active = hweight8(dbuf_state->active_pipes); - struct skl_plane_ddb_iter iter = {}; + struct skl_plane_ddb_iter iter; enum plane_id plane_id; + u16 cursor_size; u32 blocks; int level; @@ -5065,15 +5073,16 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, if (!crtc_state->hw.active) return 0; + iter.start = alloc->start; iter.size = skl_ddb_entry_size(alloc); if (iter.size == 0) return 0; /* Allocate fixed number of blocks for cursor. */ - iter.total[PLANE_CURSOR] = skl_cursor_allocation(crtc_state, num_active); - iter.size -= iter.total[PLANE_CURSOR]; + cursor_size = skl_cursor_allocation(crtc_state, num_active); + iter.size -= cursor_size; skl_ddb_entry_init(&crtc_state->wm.skl.plane_ddb[PLANE_CURSOR], - alloc->end - iter.total[PLANE_CURSOR], alloc->end); + alloc->end - cursor_size, alloc->end); iter.data_rate = skl_total_relative_data_rate(crtc_state); @@ -5088,7 +5097,10 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, &crtc_state->wm.skl.optimal.planes[plane_id]; if (plane_id == PLANE_CURSOR) { - if (wm->wm[level].min_ddb_alloc > iter.total[PLANE_CURSOR]) { + const struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; + + if (wm->wm[level].min_ddb_alloc > skl_ddb_entry_size(ddb)) { drm_WARN_ON(&dev_priv->drm, wm->wm[level].min_ddb_alloc != U16_MAX); blocks = U32_MAX; @@ -5125,6 +5137,10 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, * proportional to its relative data rate. */ for_each_plane_id_on_crtc(crtc, plane_id) { + struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; + struct skl_ddb_entry *ddb_y = + &crtc_state->wm.skl.plane_ddb_y[plane_id]; const struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id]; @@ -5133,51 +5149,17 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, if (DISPLAY_VER(dev_priv) < 11 && crtc_state->nv12_planes & BIT(plane_id)) { - iter.total[plane_id] = - skl_allocate_plane_ddb(&iter, &wm->wm[level], - crtc_state->rel_data_rate_y[plane_id]); - iter.uv_total[plane_id] = - skl_allocate_plane_ddb(&iter, &wm->uv_wm[level], - crtc_state->rel_data_rate[plane_id]); + skl_allocate_plane_ddb(&iter, ddb_y, &wm->wm[level], + crtc_state->rel_data_rate_y[plane_id]); + skl_allocate_plane_ddb(&iter, ddb, &wm->uv_wm[level], + crtc_state->rel_data_rate[plane_id]); } else { - iter.total[plane_id] = - skl_allocate_plane_ddb(&iter, &wm->wm[level], - crtc_state->rel_data_rate[plane_id]); + skl_allocate_plane_ddb(&iter, ddb, &wm->wm[level], + crtc_state->rel_data_rate[plane_id]); } } drm_WARN_ON(&dev_priv->drm, iter.size != 0 || iter.data_rate != 0); - /* Set the actual DDB start/end points for each plane */ - iter.start = alloc->start; - for_each_plane_id_on_crtc(crtc, plane_id) { - struct skl_ddb_entry *ddb = - &crtc_state->wm.skl.plane_ddb[plane_id]; - struct skl_ddb_entry *ddb_y = - &crtc_state->wm.skl.plane_ddb_y[plane_id]; - - if (plane_id == PLANE_CURSOR) - continue; - - /* Gen11+ uses a separate plane for UV watermarks */ - drm_WARN_ON(&dev_priv->drm, - DISPLAY_VER(dev_priv) >= 11 && iter.uv_total[plane_id]); - - /* Leave disabled planes at (0,0) */ - if (DISPLAY_VER(dev_priv) < 11 && - crtc_state->nv12_planes & BIT(plane_id)) { - if (iter.total[plane_id]) - iter.start = skl_ddb_entry_init(ddb_y, iter.start, - iter.start + iter.total[plane_id]); - if (iter.uv_total[plane_id]) - iter.start = skl_ddb_entry_init(ddb, iter.start, - iter.start + iter.uv_total[plane_id]); - } else { - if (iter.total[plane_id]) - iter.start = skl_ddb_entry_init(ddb, iter.start, - iter.start + iter.total[plane_id]); - } - } - /* * When we calculated watermark values we didn't know how high * of a level we'd actually be able to hit, so we just marked @@ -5186,12 +5168,20 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, */ for (level++; level <= ilk_wm_max_level(dev_priv); level++) { for_each_plane_id_on_crtc(crtc, plane_id) { + const struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; + const struct skl_ddb_entry *ddb_y = + &crtc_state->wm.skl.plane_ddb_y[plane_id]; struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id]; - skl_check_nv12_wm_level(&wm->wm[level], &wm->uv_wm[level], - iter.total[plane_id], - iter.uv_total[plane_id]); + if (DISPLAY_VER(dev_priv) < 11 && + crtc_state->nv12_planes & BIT(plane_id)) + skl_check_nv12_wm_level(&wm->wm[level], + &wm->uv_wm[level], + ddb_y, ddb); + else + skl_check_wm_level(&wm->wm[level], ddb); if (icl_need_wm1_wa(dev_priv, plane_id) && level == 1 && wm->wm[0].enable) { @@ -5207,12 +5197,24 @@ skl_crtc_allocate_plane_ddb(struct intel_atomic_state *state, * if it turns out we don't have enough DDB blocks for them. */ for_each_plane_id_on_crtc(crtc, plane_id) { + const struct skl_ddb_entry *ddb = + &crtc_state->wm.skl.plane_ddb[plane_id]; + const struct skl_ddb_entry *ddb_y = + &crtc_state->wm.skl.plane_ddb_y[plane_id]; struct skl_plane_wm *wm = &crtc_state->wm.skl.optimal.planes[plane_id]; - skl_check_wm_level(&wm->trans_wm, iter.total[plane_id]); - skl_check_wm_level(&wm->sagv.wm0, iter.total[plane_id]); - skl_check_wm_level(&wm->sagv.trans_wm, iter.total[plane_id]); + if (DISPLAY_VER(dev_priv) < 11 && + crtc_state->nv12_planes & BIT(plane_id)) { + skl_check_wm_level(&wm->trans_wm, ddb_y); + } else { + WARN_ON(skl_ddb_entry_size(ddb_y)); + + skl_check_wm_level(&wm->trans_wm, ddb); + } + + skl_check_wm_level(&wm->sagv.wm0, ddb); + skl_check_wm_level(&wm->sagv.trans_wm, ddb); } return 0; From 7243867c6f9617c451c763a7751fa743c3f04f4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Mar 2022 21:12:03 +0200 Subject: [PATCH 00291/11454] drm/i915: Nuke intel_bw_calc_min_cdclk() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_bw_calc_min_cdclk() is entirely pointless. All it manages to do is somehow conflate the per-pipe min cdclk with dbuf min cdclk. There is no (at least documented) dbuf min cdclk limit on pre-skl so let's just get rid of all this confusion. Reviewed-by: Stanislav Lisovskiy Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-6-ville.syrjala@linux.intel.com --- drivers/gpu/drm/i915/display/intel_bw.c | 49 ++-------------------- drivers/gpu/drm/i915/display/intel_bw.h | 1 - drivers/gpu/drm/i915/display/intel_cdclk.c | 31 +------------- 3 files changed, 5 insertions(+), 76 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 5517d1ac78d6..e991949c6e5d 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -717,7 +717,7 @@ static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state, } } -int skl_bw_calc_min_cdclk(struct intel_atomic_state *state) +int intel_bw_calc_min_cdclk(struct intel_atomic_state *state) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_bw_state *new_bw_state = NULL; @@ -728,6 +728,9 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state) enum pipe pipe; int i; + if (DISPLAY_VER(dev_priv) < 9) + return 0; + for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { new_bw_state = intel_atomic_get_bw_state(state); if (IS_ERR(new_bw_state)) @@ -772,50 +775,6 @@ int skl_bw_calc_min_cdclk(struct intel_atomic_state *state) return 0; } -int intel_bw_calc_min_cdclk(struct intel_atomic_state *state) -{ - struct drm_i915_private *dev_priv = to_i915(state->base.dev); - struct intel_bw_state *new_bw_state = NULL; - struct intel_bw_state *old_bw_state = NULL; - const struct intel_crtc_state *crtc_state; - struct intel_crtc *crtc; - int min_cdclk = 0; - enum pipe pipe; - int i; - - for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) { - new_bw_state = intel_atomic_get_bw_state(state); - if (IS_ERR(new_bw_state)) - return PTR_ERR(new_bw_state); - - old_bw_state = intel_atomic_get_old_bw_state(state); - } - - if (!old_bw_state) - return 0; - - for_each_pipe(dev_priv, pipe) { - struct intel_cdclk_state *cdclk_state; - - cdclk_state = intel_atomic_get_new_cdclk_state(state); - if (!cdclk_state) - return 0; - - min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk); - } - - new_bw_state->min_cdclk = min_cdclk; - - if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) { - int ret = intel_atomic_lock_global_state(&new_bw_state->base); - - if (ret) - return ret; - } - - return 0; -} - static u16 icl_qgv_points_mask(struct drm_i915_private *i915) { unsigned int num_psf_gv_points = i915->max_bw[0].num_psf_gv_points; diff --git a/drivers/gpu/drm/i915/display/intel_bw.h b/drivers/gpu/drm/i915/display/intel_bw.h index 0ceaed1c9656..6acdf1245b3a 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.h +++ b/drivers/gpu/drm/i915/display/intel_bw.h @@ -65,6 +65,5 @@ void intel_bw_crtc_update(struct intel_bw_state *bw_state, int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv, u32 points_mask); int intel_bw_calc_min_cdclk(struct intel_atomic_state *state); -int skl_bw_calc_min_cdclk(struct intel_atomic_state *state); #endif /* __INTEL_BW_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 8888fda8b701..5d0c2f8b0533 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -72,7 +72,6 @@ struct intel_cdclk_funcs { void (*set_cdclk)(struct drm_i915_private *i915, const struct intel_cdclk_config *cdclk_config, enum pipe pipe); - int (*bw_calc_min_cdclk)(struct intel_atomic_state *state); int (*modeset_calc_cdclk)(struct intel_cdclk_state *state); u8 (*calc_voltage_level)(int cdclk); }; @@ -83,12 +82,6 @@ void intel_cdclk_get_cdclk(struct drm_i915_private *dev_priv, dev_priv->cdclk_funcs->get_cdclk(dev_priv, cdclk_config); } -static int intel_cdclk_bw_calc_min_cdclk(struct intel_atomic_state *state) -{ - struct drm_i915_private *dev_priv = to_i915(state->base.dev); - return dev_priv->cdclk_funcs->bw_calc_min_cdclk(state); -} - static void intel_cdclk_set_cdclk(struct drm_i915_private *dev_priv, const struct intel_cdclk_config *cdclk_config, enum pipe pipe) @@ -2683,7 +2676,7 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state, old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk) *need_cdclk_calc = true; - ret = intel_cdclk_bw_calc_min_cdclk(state); + ret = intel_bw_calc_min_cdclk(state); if (ret) return ret; @@ -3072,7 +3065,6 @@ u32 intel_read_rawclk(struct drm_i915_private *dev_priv) static const struct intel_cdclk_funcs tgl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, - .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, .modeset_calc_cdclk = bxt_modeset_calc_cdclk, .calc_voltage_level = tgl_calc_voltage_level, }; @@ -3080,7 +3072,6 @@ static const struct intel_cdclk_funcs tgl_cdclk_funcs = { static const struct intel_cdclk_funcs ehl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, - .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, .modeset_calc_cdclk = bxt_modeset_calc_cdclk, .calc_voltage_level = ehl_calc_voltage_level, }; @@ -3088,7 +3079,6 @@ static const struct intel_cdclk_funcs ehl_cdclk_funcs = { static const struct intel_cdclk_funcs icl_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, - .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, .modeset_calc_cdclk = bxt_modeset_calc_cdclk, .calc_voltage_level = icl_calc_voltage_level, }; @@ -3096,7 +3086,6 @@ static const struct intel_cdclk_funcs icl_cdclk_funcs = { static const struct intel_cdclk_funcs bxt_cdclk_funcs = { .get_cdclk = bxt_get_cdclk, .set_cdclk = bxt_set_cdclk, - .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, .modeset_calc_cdclk = bxt_modeset_calc_cdclk, .calc_voltage_level = bxt_calc_voltage_level, }; @@ -3104,53 +3093,45 @@ static const struct intel_cdclk_funcs bxt_cdclk_funcs = { static const struct intel_cdclk_funcs skl_cdclk_funcs = { .get_cdclk = skl_get_cdclk, .set_cdclk = skl_set_cdclk, - .bw_calc_min_cdclk = skl_bw_calc_min_cdclk, .modeset_calc_cdclk = skl_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs bdw_cdclk_funcs = { .get_cdclk = bdw_get_cdclk, .set_cdclk = bdw_set_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = bdw_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs chv_cdclk_funcs = { .get_cdclk = vlv_get_cdclk, .set_cdclk = chv_set_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = vlv_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs vlv_cdclk_funcs = { .get_cdclk = vlv_get_cdclk, .set_cdclk = vlv_set_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = vlv_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs hsw_cdclk_funcs = { .get_cdclk = hsw_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; /* SNB, IVB, 965G, 945G */ static const struct intel_cdclk_funcs fixed_400mhz_cdclk_funcs = { .get_cdclk = fixed_400mhz_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs ilk_cdclk_funcs = { .get_cdclk = fixed_450mhz_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs gm45_cdclk_funcs = { .get_cdclk = gm45_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; @@ -3158,7 +3139,6 @@ static const struct intel_cdclk_funcs gm45_cdclk_funcs = { static const struct intel_cdclk_funcs i965gm_cdclk_funcs = { .get_cdclk = i965gm_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; @@ -3166,19 +3146,16 @@ static const struct intel_cdclk_funcs i965gm_cdclk_funcs = { static const struct intel_cdclk_funcs pnv_cdclk_funcs = { .get_cdclk = pnv_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs g33_cdclk_funcs = { .get_cdclk = g33_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs i945gm_cdclk_funcs = { .get_cdclk = i945gm_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; @@ -3186,37 +3163,31 @@ static const struct intel_cdclk_funcs i945gm_cdclk_funcs = { static const struct intel_cdclk_funcs i915gm_cdclk_funcs = { .get_cdclk = i915gm_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs i915g_cdclk_funcs = { .get_cdclk = fixed_333mhz_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs i865g_cdclk_funcs = { .get_cdclk = fixed_266mhz_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs i85x_cdclk_funcs = { .get_cdclk = i85x_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs i845g_cdclk_funcs = { .get_cdclk = fixed_200mhz_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; static const struct intel_cdclk_funcs i830_cdclk_funcs = { .get_cdclk = fixed_133mhz_get_cdclk, - .bw_calc_min_cdclk = intel_bw_calc_min_cdclk, .modeset_calc_cdclk = fixed_modeset_calc_cdclk, }; From 6c69d0bb9f15cdbc8fd6134e2c66438b69bb9581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Mar 2022 21:12:04 +0200 Subject: [PATCH 00292/11454] drm/i915: Round up when calculating display bandwidth requirements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We should round up when doing bandwidth calculations to make sure our estimates don't fall short of the actual number. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-7-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_bw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index e991949c6e5d..8155f2309f80 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -638,7 +638,7 @@ static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv, data_rate += bw_state->data_rate[pipe]; if (DISPLAY_VER(dev_priv) >= 13 && intel_vtd_active(dev_priv)) - data_rate = data_rate * 105 / 100; + data_rate = DIV_ROUND_UP(data_rate * 105, 100); return data_rate; } @@ -763,7 +763,7 @@ int intel_bw_calc_min_cdclk(struct intel_atomic_state *state) } } - new_bw_state->min_cdclk = max_bw / 64; + new_bw_state->min_cdclk = DIV_ROUND_UP(max_bw, 64); if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) { int ret = intel_atomic_lock_global_state(&new_bw_state->base); From 6731eb046cf71e30a79e60bae8ed31f5450928fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Mar 2022 21:12:05 +0200 Subject: [PATCH 00293/11454] drm/i915: Properly write lock bw_state when it changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code also forgets to call intel_atomic_lock_global_state() when other stuff besides the final min_cdlck changes in the state. That means we may throw away data which actually has changed, and thus we can't be at all sure what the code ends up doing during subsequent commits. Do the write lock properly. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-8-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_bw.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 8155f2309f80..a0a69d8db132 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -678,6 +678,28 @@ intel_atomic_get_bw_state(struct intel_atomic_state *state) return to_intel_bw_state(bw_state); } +static bool intel_bw_state_changed(struct drm_i915_private *i915, + const struct intel_bw_state *old_bw_state, + const struct intel_bw_state *new_bw_state) +{ + enum pipe pipe; + + for_each_pipe(i915, pipe) { + const struct intel_dbuf_bw *old_crtc_bw = + &old_bw_state->dbuf_bw[pipe]; + const struct intel_dbuf_bw *new_crtc_bw = + &new_bw_state->dbuf_bw[pipe]; + enum dbuf_slice slice; + + for_each_dbuf_slice(i915, slice) { + if (old_crtc_bw->used_bw[slice] != new_crtc_bw->used_bw[slice]) + return true; + } + } + + return old_bw_state->min_cdclk != new_bw_state->min_cdclk; +} + static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state, const struct intel_crtc_state *crtc_state) { @@ -765,7 +787,7 @@ int intel_bw_calc_min_cdclk(struct intel_atomic_state *state) new_bw_state->min_cdclk = DIV_ROUND_UP(max_bw, 64); - if (new_bw_state->min_cdclk != old_bw_state->min_cdclk) { + if (intel_bw_state_changed(dev_priv, old_bw_state, new_bw_state)) { int ret = intel_atomic_lock_global_state(&new_bw_state->base); if (ret) From 5ac860cc52540df8bca27e0bb25b6744df67e8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Mar 2022 21:12:06 +0200 Subject: [PATCH 00294/11454] drm/i915: Fix DBUF bandwidth vs. cdclk handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make the dbuf bandwidth min cdclk calculations match the spec more closely. Supposedly the arbiter can only guarantee an equal share of the total bandwidth of the slice to each active plane on that slice. So we take the max bandwidth of any of the planes on each slice and multiply that by the number of active planes on the slice to get a worst case estimate on how much bandwidth we require. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-9-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_bw.c | 163 ++++++++++++++------- drivers/gpu/drm/i915/display/intel_bw.h | 10 +- drivers/gpu/drm/i915/display/intel_cdclk.c | 67 ++++----- drivers/gpu/drm/i915/display/intel_cdclk.h | 2 + 4 files changed, 150 insertions(+), 92 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index a0a69d8db132..307a5a1c7788 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -692,12 +692,34 @@ static bool intel_bw_state_changed(struct drm_i915_private *i915, enum dbuf_slice slice; for_each_dbuf_slice(i915, slice) { - if (old_crtc_bw->used_bw[slice] != new_crtc_bw->used_bw[slice]) + if (old_crtc_bw->max_bw[slice] != new_crtc_bw->max_bw[slice] || + old_crtc_bw->active_planes[slice] != new_crtc_bw->active_planes[slice]) return true; } } - return old_bw_state->min_cdclk != new_bw_state->min_cdclk; + return false; +} + +static void skl_plane_calc_dbuf_bw(struct intel_bw_state *bw_state, + struct intel_crtc *crtc, + enum plane_id plane_id, + const struct skl_ddb_entry *ddb, + unsigned int data_rate) +{ + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + struct intel_dbuf_bw *crtc_bw = &bw_state->dbuf_bw[crtc->pipe]; + unsigned int dbuf_mask = skl_ddb_dbuf_slice_mask(i915, ddb); + enum dbuf_slice slice; + + /* + * The arbiter can only really guarantee an + * equal share of the total bw to each plane. + */ + for_each_dbuf_slice_in_mask(i915, slice, dbuf_mask) { + crtc_bw->max_bw[slice] = max(crtc_bw->max_bw[slice], data_rate); + crtc_bw->active_planes[slice] |= BIT(plane_id); + } } static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state, @@ -708,46 +730,77 @@ static void skl_crtc_calc_dbuf_bw(struct intel_bw_state *bw_state, struct intel_dbuf_bw *crtc_bw = &bw_state->dbuf_bw[crtc->pipe]; enum plane_id plane_id; - memset(&crtc_bw->used_bw, 0, sizeof(crtc_bw->used_bw)); + memset(crtc_bw, 0, sizeof(*crtc_bw)); if (!crtc_state->hw.active) return; for_each_plane_id_on_crtc(crtc, plane_id) { - const struct skl_ddb_entry *ddb = - &crtc_state->wm.skl.plane_ddb[plane_id]; - unsigned int data_rate = crtc_state->data_rate[plane_id]; - unsigned int dbuf_mask = skl_ddb_dbuf_slice_mask(i915, ddb); - enum dbuf_slice slice; + /* + * We assume cursors are small enough + * to not cause bandwidth problems. + */ + if (plane_id == PLANE_CURSOR) + continue; - for_each_dbuf_slice_in_mask(i915, slice, dbuf_mask) - crtc_bw->used_bw[slice] += data_rate; - } + skl_plane_calc_dbuf_bw(bw_state, crtc, plane_id, + &crtc_state->wm.skl.plane_ddb[plane_id], + crtc_state->data_rate[plane_id]); - if (DISPLAY_VER(i915) >= 11) - return; - - for_each_plane_id_on_crtc(crtc, plane_id) { - const struct skl_ddb_entry *ddb = - &crtc_state->wm.skl.plane_ddb_y[plane_id]; - unsigned int data_rate = crtc_state->data_rate_y[plane_id]; - unsigned int dbuf_mask = skl_ddb_dbuf_slice_mask(i915, ddb); - enum dbuf_slice slice; - - for_each_dbuf_slice_in_mask(i915, slice, dbuf_mask) - crtc_bw->used_bw[slice] += data_rate; + if (DISPLAY_VER(i915) < 11) + skl_plane_calc_dbuf_bw(bw_state, crtc, plane_id, + &crtc_state->wm.skl.plane_ddb_y[plane_id], + crtc_state->data_rate[plane_id]); } } -int intel_bw_calc_min_cdclk(struct intel_atomic_state *state) +/* "Maximum Data Buffer Bandwidth" */ +static int +intel_bw_dbuf_min_cdclk(struct drm_i915_private *i915, + const struct intel_bw_state *bw_state) +{ + unsigned int total_max_bw = 0; + enum dbuf_slice slice; + + for_each_dbuf_slice(i915, slice) { + int num_active_planes = 0; + unsigned int max_bw = 0; + enum pipe pipe; + + /* + * The arbiter can only really guarantee an + * equal share of the total bw to each plane. + */ + for_each_pipe(i915, pipe) { + const struct intel_dbuf_bw *crtc_bw = &bw_state->dbuf_bw[pipe]; + + max_bw = max(crtc_bw->max_bw[slice], max_bw); + num_active_planes += hweight8(crtc_bw->active_planes[slice]); + } + max_bw *= num_active_planes; + + total_max_bw = max(total_max_bw, max_bw); + } + + return DIV_ROUND_UP(total_max_bw, 64); +} + +int intel_bw_min_cdclk(struct drm_i915_private *i915, + const struct intel_bw_state *bw_state) +{ + return intel_bw_dbuf_min_cdclk(i915, bw_state); +} + +int intel_bw_calc_min_cdclk(struct intel_atomic_state *state, + bool *need_cdclk_calc) { struct drm_i915_private *dev_priv = to_i915(state->base.dev); struct intel_bw_state *new_bw_state = NULL; - struct intel_bw_state *old_bw_state = NULL; + const struct intel_bw_state *old_bw_state = NULL; + const struct intel_cdclk_state *cdclk_state; const struct intel_crtc_state *crtc_state; + int old_min_cdclk, new_min_cdclk; struct intel_crtc *crtc; - int max_bw = 0; - enum pipe pipe; int i; if (DISPLAY_VER(dev_priv) < 9) @@ -766,34 +819,46 @@ int intel_bw_calc_min_cdclk(struct intel_atomic_state *state) if (!old_bw_state) return 0; - for_each_pipe(dev_priv, pipe) { - struct intel_dbuf_bw *crtc_bw; - enum dbuf_slice slice; - - crtc_bw = &new_bw_state->dbuf_bw[pipe]; - - for_each_dbuf_slice(dev_priv, slice) { - /* - * Current experimental observations show that contrary - * to BSpec we get underruns once we exceed 64 * CDCLK - * for slices in total. - * As a temporary measure in order not to keep CDCLK - * bumped up all the time we calculate CDCLK according - * to this formula for overall bw consumed by slices. - */ - max_bw += crtc_bw->used_bw[slice]; - } - } - - new_bw_state->min_cdclk = DIV_ROUND_UP(max_bw, 64); - if (intel_bw_state_changed(dev_priv, old_bw_state, new_bw_state)) { int ret = intel_atomic_lock_global_state(&new_bw_state->base); - if (ret) return ret; } + old_min_cdclk = intel_bw_min_cdclk(dev_priv, old_bw_state); + new_min_cdclk = intel_bw_min_cdclk(dev_priv, new_bw_state); + + /* + * No need to check against the cdclk state if + * the min cdclk for the dbuf doesn't increase. + * + * Ie. we only ever increase the cdclk due to dbuf + * requirements. This can reduce back and forth + * display blinking due to constant cdclk changes. + */ + if (new_min_cdclk <= old_min_cdclk) + return 0; + + cdclk_state = intel_atomic_get_cdclk_state(state); + if (IS_ERR(cdclk_state)) + return PTR_ERR(cdclk_state); + + /* + * No need to recalculate the cdclk state if + * the min cdclk for the dbuf doesn't increase. + * + * Ie. we only ever increase the cdclk due to dbuf + * requirements. This can reduce back and forth + * display blinking due to constant cdclk changes. + */ + if (new_min_cdclk <= cdclk_state->bw_min_cdclk) + return 0; + + drm_dbg_kms(&dev_priv->drm, + "new bandwidth min cdclk (%d kHz) > old min cdclk (%d kHz)\n", + new_min_cdclk, cdclk_state->bw_min_cdclk); + *need_cdclk_calc = true; + return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_bw.h b/drivers/gpu/drm/i915/display/intel_bw.h index 6acdf1245b3a..92fc09a8c824 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.h +++ b/drivers/gpu/drm/i915/display/intel_bw.h @@ -17,7 +17,8 @@ struct intel_atomic_state; struct intel_crtc_state; struct intel_dbuf_bw { - int used_bw[I915_MAX_DBUF_SLICES]; + unsigned int max_bw[I915_MAX_DBUF_SLICES]; + u8 active_planes[I915_MAX_DBUF_SLICES]; }; struct intel_bw_state { @@ -42,8 +43,6 @@ struct intel_bw_state { unsigned int data_rate[I915_MAX_PIPES]; u8 num_active_planes[I915_MAX_PIPES]; - - int min_cdclk; }; #define to_intel_bw_state(x) container_of((x), struct intel_bw_state, base) @@ -64,6 +63,9 @@ void intel_bw_crtc_update(struct intel_bw_state *bw_state, const struct intel_crtc_state *crtc_state); int icl_pcode_restrict_qgv_points(struct drm_i915_private *dev_priv, u32 points_mask); -int intel_bw_calc_min_cdclk(struct intel_atomic_state *state); +int intel_bw_calc_min_cdclk(struct intel_atomic_state *state, + bool *need_cdclk_calc); +int intel_bw_min_cdclk(struct drm_i915_private *i915, + const struct intel_bw_state *bw_state); #endif /* __INTEL_BW_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.c b/drivers/gpu/drm/i915/display/intel_cdclk.c index 5d0c2f8b0533..b2017d8161b4 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.c +++ b/drivers/gpu/drm/i915/display/intel_cdclk.c @@ -2318,13 +2318,6 @@ int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state) dev_priv->max_cdclk_freq)); } - if (min_cdclk > dev_priv->max_cdclk_freq) { - drm_dbg_kms(&dev_priv->drm, - "required cdclk (%d kHz) exceeds max (%d kHz)\n", - min_cdclk, dev_priv->max_cdclk_freq); - return -EINVAL; - } - return min_cdclk; } @@ -2332,7 +2325,7 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state) { struct intel_atomic_state *state = cdclk_state->base.state; struct drm_i915_private *dev_priv = to_i915(state->base.dev); - struct intel_bw_state *bw_state = NULL; + const struct intel_bw_state *bw_state; struct intel_crtc *crtc; struct intel_crtc_state *crtc_state; int min_cdclk, i; @@ -2345,10 +2338,6 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state) if (min_cdclk < 0) return min_cdclk; - bw_state = intel_atomic_get_bw_state(state); - if (IS_ERR(bw_state)) - return PTR_ERR(bw_state); - if (cdclk_state->min_cdclk[crtc->pipe] == min_cdclk) continue; @@ -2359,14 +2348,31 @@ static int intel_compute_min_cdclk(struct intel_cdclk_state *cdclk_state) return ret; } - min_cdclk = cdclk_state->force_min_cdclk; - for_each_pipe(dev_priv, pipe) { + bw_state = intel_atomic_get_new_bw_state(state); + if (bw_state) { + min_cdclk = intel_bw_min_cdclk(dev_priv, bw_state); + + if (cdclk_state->bw_min_cdclk != min_cdclk) { + int ret; + + cdclk_state->bw_min_cdclk = min_cdclk; + + ret = intel_atomic_lock_global_state(&cdclk_state->base); + if (ret) + return ret; + } + } + + min_cdclk = max(cdclk_state->force_min_cdclk, + cdclk_state->bw_min_cdclk); + for_each_pipe(dev_priv, pipe) min_cdclk = max(cdclk_state->min_cdclk[pipe], min_cdclk); - if (!bw_state) - continue; - - min_cdclk = max(bw_state->min_cdclk, min_cdclk); + if (min_cdclk > dev_priv->max_cdclk_freq) { + drm_dbg_kms(&dev_priv->drm, + "required cdclk (%d kHz) exceeds max (%d kHz)\n", + min_cdclk, dev_priv->max_cdclk_freq); + return -EINVAL; } return min_cdclk; @@ -2647,14 +2653,10 @@ intel_atomic_get_cdclk_state(struct intel_atomic_state *state) int intel_cdclk_atomic_check(struct intel_atomic_state *state, bool *need_cdclk_calc) { - struct drm_i915_private *i915 = to_i915(state->base.dev); const struct intel_cdclk_state *old_cdclk_state; const struct intel_cdclk_state *new_cdclk_state; struct intel_plane_state *plane_state; - struct intel_bw_state *new_bw_state; struct intel_plane *plane; - int min_cdclk = 0; - enum pipe pipe; int ret; int i; @@ -2669,6 +2671,10 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state, return ret; } + ret = intel_bw_calc_min_cdclk(state, need_cdclk_calc); + if (ret) + return ret; + old_cdclk_state = intel_atomic_get_old_cdclk_state(state); new_cdclk_state = intel_atomic_get_new_cdclk_state(state); @@ -2676,23 +2682,6 @@ int intel_cdclk_atomic_check(struct intel_atomic_state *state, old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk) *need_cdclk_calc = true; - ret = intel_bw_calc_min_cdclk(state); - if (ret) - return ret; - - new_bw_state = intel_atomic_get_new_bw_state(state); - - if (!new_cdclk_state || !new_bw_state) - return 0; - - for_each_pipe(i915, pipe) { - min_cdclk = max(new_cdclk_state->min_cdclk[pipe], min_cdclk); - - /* Currently do this change only if we need to increase */ - if (new_bw_state->min_cdclk > min_cdclk) - *need_cdclk_calc = true; - } - return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_cdclk.h b/drivers/gpu/drm/i915/display/intel_cdclk.h index df66f66fbad0..b535cf6a7d9e 100644 --- a/drivers/gpu/drm/i915/display/intel_cdclk.h +++ b/drivers/gpu/drm/i915/display/intel_cdclk.h @@ -36,6 +36,8 @@ struct intel_cdclk_state { */ struct intel_cdclk_config actual; + /* minimum acceptable cdclk to satisfy bandwidth requirements */ + int bw_min_cdclk; /* minimum acceptable cdclk for each pipe */ int min_cdclk[I915_MAX_PIPES]; /* minimum acceptable voltage level for each pipe */ From ea0839691816b9742ca1371d4e1645192f1a733d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 3 Mar 2022 21:12:07 +0200 Subject: [PATCH 00295/11454] drm/i915: Add "maximum pipe read bandwidth" checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make sure the CDCLK is high enough to support the so called "maximum pipe read bandwidth" limitation. Specified as 51.2 x CDCLK. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220303191207.27931-10-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_bw.c | 36 +++++++++++++++++++++---- drivers/gpu/drm/i915/display/intel_bw.h | 1 + 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index 307a5a1c7788..ac11ff19e47d 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -599,6 +599,18 @@ static unsigned int intel_bw_crtc_data_rate(const struct intel_crtc_state *crtc_ return data_rate; } +/* "Maximum Pipe Read Bandwidth" */ +static int intel_bw_crtc_min_cdclk(const struct intel_crtc_state *crtc_state) +{ + struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); + struct drm_i915_private *i915 = to_i915(crtc->base.dev); + + if (DISPLAY_VER(i915) < 12) + return 0; + + return DIV_ROUND_UP_ULL(mul_u32_u32(intel_bw_crtc_data_rate(crtc_state), 10), 512); +} + void intel_bw_crtc_update(struct intel_bw_state *bw_state, const struct intel_crtc_state *crtc_state) { @@ -696,6 +708,9 @@ static bool intel_bw_state_changed(struct drm_i915_private *i915, old_crtc_bw->active_planes[slice] != new_crtc_bw->active_planes[slice]) return true; } + + if (old_bw_state->min_cdclk[pipe] != new_bw_state->min_cdclk[pipe]) + return true; } return false; @@ -788,7 +803,15 @@ intel_bw_dbuf_min_cdclk(struct drm_i915_private *i915, int intel_bw_min_cdclk(struct drm_i915_private *i915, const struct intel_bw_state *bw_state) { - return intel_bw_dbuf_min_cdclk(i915, bw_state); + enum pipe pipe; + int min_cdclk; + + min_cdclk = intel_bw_dbuf_min_cdclk(i915, bw_state); + + for_each_pipe(i915, pipe) + min_cdclk = max(bw_state->min_cdclk[pipe], min_cdclk); + + return min_cdclk; } int intel_bw_calc_min_cdclk(struct intel_atomic_state *state, @@ -814,6 +837,9 @@ int intel_bw_calc_min_cdclk(struct intel_atomic_state *state, old_bw_state = intel_atomic_get_old_bw_state(state); skl_crtc_calc_dbuf_bw(new_bw_state, crtc_state); + + new_bw_state->min_cdclk[crtc->pipe] = + intel_bw_crtc_min_cdclk(crtc_state); } if (!old_bw_state) @@ -830,9 +856,9 @@ int intel_bw_calc_min_cdclk(struct intel_atomic_state *state, /* * No need to check against the cdclk state if - * the min cdclk for the dbuf doesn't increase. + * the min cdclk doesn't increase. * - * Ie. we only ever increase the cdclk due to dbuf + * Ie. we only ever increase the cdclk due to bandwidth * requirements. This can reduce back and forth * display blinking due to constant cdclk changes. */ @@ -845,9 +871,9 @@ int intel_bw_calc_min_cdclk(struct intel_atomic_state *state, /* * No need to recalculate the cdclk state if - * the min cdclk for the dbuf doesn't increase. + * the min cdclk doesn't increase. * - * Ie. we only ever increase the cdclk due to dbuf + * Ie. we only ever increase the cdclk due to bandwidth * requirements. This can reduce back and forth * display blinking due to constant cdclk changes. */ diff --git a/drivers/gpu/drm/i915/display/intel_bw.h b/drivers/gpu/drm/i915/display/intel_bw.h index 92fc09a8c824..cb7ee3a24a58 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.h +++ b/drivers/gpu/drm/i915/display/intel_bw.h @@ -41,6 +41,7 @@ struct intel_bw_state { */ u16 qgv_points_mask; + int min_cdclk[I915_MAX_PIPES]; unsigned int data_rate[I915_MAX_PIPES]; u8 num_active_planes[I915_MAX_PIPES]; }; From cc436b1c674e4247b4d4873f2236039f697f4e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Feb 2022 12:03:48 +0200 Subject: [PATCH 00296/11454] drm/gma500: Use drm_mode_copy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct drm_display_mode embeds a list head, so overwriting the full struct with another one will corrupt the list (if the destination mode is on a list). Use drm_mode_copy() instead which explicitly preserves the list head of the destination mode. Even if we know the destination mode is not on any list using drm_mode_copy() seems decent as it sets a good example. Bad examples of not using it might eventually get copied into code where preserving the list head actually matters. Obviously one case not covered here is when the mode itself is embedded in a larger structure and the whole structure is copied. But if we are careful when copying into modes embedded in structures I think we can be a little more reassured that bogus list heads haven't been propagated in. @is_mode_copy@ @@ drm_mode_copy(...) { ... } @depends on !is_mode_copy@ struct drm_display_mode *mode; expression E, S; @@ ( - *mode = E + drm_mode_copy(mode, &E) | - memcpy(mode, E, S) + drm_mode_copy(mode, E) ) @depends on !is_mode_copy@ struct drm_display_mode mode; expression E; @@ ( - mode = E + drm_mode_copy(&mode, &E) | - memcpy(&mode, E, S) + drm_mode_copy(&mode, E) ) @@ struct drm_display_mode *mode; @@ - &*mode + mode Cc: Patrik Jakobsson Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220218100403.7028-8-ville.syrjala@linux.intel.com Acked-by: Patrik Jakobsson --- drivers/gpu/drm/gma500/oaktrail_crtc.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index 36c7c2686c90..79fc602b35bc 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -385,12 +385,8 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, if (!gma_power_begin(dev, true)) return 0; - memcpy(&gma_crtc->saved_mode, - mode, - sizeof(struct drm_display_mode)); - memcpy(&gma_crtc->saved_adjusted_mode, - adjusted_mode, - sizeof(struct drm_display_mode)); + drm_mode_copy(&gma_crtc->saved_mode, mode); + drm_mode_copy(&gma_crtc->saved_adjusted_mode, adjusted_mode); list_for_each_entry(connector, &mode_config->connector_list, head) { if (!connector->encoder || connector->encoder->crtc != crtc) From 6185587b6675e1852c49235e00fb76f7d81ff0d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Fri, 18 Feb 2022 12:03:57 +0200 Subject: [PATCH 00297/11454] drm/tilcdc: Use drm_mode_copy() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct drm_display_mode embeds a list head, so overwriting the full struct with another one will corrupt the list (if the destination mode is on a list). Use drm_mode_copy() instead which explicitly preserves the list head of the destination mode. Even if we know the destination mode is not on any list using drm_mode_copy() seems decent as it sets a good example. Bad examples of not using it might eventually get copied into code where preserving the list head actually matters. Obviously one case not covered here is when the mode itself is embedded in a larger structure and the whole structure is copied. But if we are careful when copying into modes embedded in structures I think we can be a little more reassured that bogus list heads haven't been propagated in. @is_mode_copy@ @@ drm_mode_copy(...) { ... } @depends on !is_mode_copy@ struct drm_display_mode *mode; expression E, S; @@ ( - *mode = E + drm_mode_copy(mode, &E) | - memcpy(mode, E, S) + drm_mode_copy(mode, E) ) @depends on !is_mode_copy@ struct drm_display_mode mode; expression E; @@ ( - mode = E + drm_mode_copy(&mode, &E) | - memcpy(&mode, E, S) + drm_mode_copy(&mode, E) ) @@ struct drm_display_mode *mode; @@ - &*mode + mode Cc: Jyri Sarha Cc: Tomi Valkeinen Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220218100403.7028-17-ville.syrjala@linux.intel.com Reviewed-by: Tomi Valkeinen --- drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 29890d704cb4..853c6b443fff 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -433,7 +433,7 @@ static void tilcdc_crtc_set_mode(struct drm_crtc *crtc) set_scanout(crtc, fb); - crtc->hwmode = crtc->state->adjusted_mode; + drm_mode_copy(&crtc->hwmode, &crtc->state->adjusted_mode); tilcdc_crtc->hvtotal_us = tilcdc_mode_hvtotal(&crtc->hwmode); From 54903c7a6b40e34c3b0da3a3a5bb93f909295ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Tue, 15 Mar 2022 15:27:52 +0200 Subject: [PATCH 00298/11454] drm/i915: s/enable/active/ for DRRS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename the DRRS functiosn to say "(de)activate" rather than "enable/disable". This let's us differentiate between the logically enabled vs. actually currently active cases. v2: Fix kernel doc for intel_drrs_deactivate() Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220315132752.11849-10-ville.syrjala@linux.intel.com Reviewed-by: José Roberto de Souza --- drivers/gpu/drm/i915/display/intel_display.c | 4 ++-- .../drm/i915/display/intel_display_debugfs.c | 15 ++++++++----- drivers/gpu/drm/i915/display/intel_drrs.c | 22 ++++++++++--------- drivers/gpu/drm/i915/display/intel_drrs.h | 6 ++--- 4 files changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 39dbc7f69d4d..3d2ff258f0a9 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1249,7 +1249,7 @@ static void intel_post_plane_update(struct intel_atomic_state *state, !needs_cursorclk_wa(new_crtc_state)) icl_wa_cursorclkgating(dev_priv, pipe, false); - intel_drrs_enable(new_crtc_state); + intel_drrs_activate(new_crtc_state); } static void intel_crtc_enable_flip_done(struct intel_atomic_state *state, @@ -1327,7 +1327,7 @@ static void intel_pre_plane_update(struct intel_atomic_state *state, intel_atomic_get_new_crtc_state(state, crtc); enum pipe pipe = crtc->pipe; - intel_drrs_disable(old_crtc_state); + intel_drrs_deactivate(old_crtc_state); intel_psr_pre_plane_update(state, crtc); diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index 101e57384832..c1e74a13a082 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -1159,6 +1159,9 @@ static int i915_drrs_status(struct seq_file *m, void *unused) seq_puts(m, "\n"); for_each_intel_crtc(&dev_priv->drm, crtc) { + const struct intel_crtc_state *crtc_state = + to_intel_crtc_state(crtc->base.state); + seq_printf(m, "[CRTC:%d:%s]:\n", crtc->base.base.id, crtc->base.name); @@ -1166,7 +1169,10 @@ static int i915_drrs_status(struct seq_file *m, void *unused) /* DRRS Supported */ seq_printf(m, "\tDRRS Enabled: %s\n", - str_yes_no(intel_drrs_is_enabled(crtc))); + str_yes_no(crtc_state->has_drrs)); + + seq_printf(m, "\tDRRS Active: %s\n", + str_yes_no(intel_drrs_is_active(crtc))); seq_printf(m, "\tBusy_frontbuffer_bits: 0x%X\n", crtc->drrs.busy_frontbuffer_bits); @@ -1864,13 +1870,12 @@ static int i915_drrs_ctl_set(void *data, u64 val) } drm_dbg(&dev_priv->drm, - "Manually %sabling DRRS. %llu\n", - val ? "en" : "dis", val); + "Manually %sactivating DRRS\n", val ? "" : "de"); if (val) - intel_drrs_enable(crtc_state); + intel_drrs_activate(crtc_state); else - intel_drrs_disable(crtc_state); + intel_drrs_deactivate(crtc_state); out: drm_modeset_unlock(&crtc->base.mutex); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 9a341ab1a848..a5c7d58b36e0 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -147,7 +147,7 @@ intel_drrs_set_refresh_rate_m_n(struct intel_crtc *crtc, &crtc->drrs.m2_n2 : &crtc->drrs.m_n); } -bool intel_drrs_is_enabled(struct intel_crtc *crtc) +bool intel_drrs_is_active(struct intel_crtc *crtc) { return crtc->drrs.cpu_transcoder != INVALID_TRANSCODER; } @@ -189,12 +189,12 @@ static unsigned int intel_drrs_frontbuffer_bits(const struct intel_crtc_state *c } /** - * intel_drrs_enable - init drrs struct if supported - * @crtc_state: A pointer to the active crtc state. + * intel_drrs_activate - activate DRRS + * @crtc_state: the crtc state * - * Initializes frontbuffer_bits and drrs.dp + * Activates DRRS on the crtc. */ -void intel_drrs_enable(const struct intel_crtc_state *crtc_state) +void intel_drrs_activate(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -221,10 +221,12 @@ void intel_drrs_enable(const struct intel_crtc_state *crtc_state) } /** - * intel_drrs_disable - Disable DRRS - * @old_crtc_state: Pointer to old crtc_state. + * intel_drrs_deactivate - deactivate DRRS + * @old_crtc_state: the old crtc state + * + * Deactivates DRRS on the crtc. */ -void intel_drrs_disable(const struct intel_crtc_state *old_crtc_state) +void intel_drrs_deactivate(const struct intel_crtc_state *old_crtc_state) { struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); @@ -239,7 +241,7 @@ void intel_drrs_disable(const struct intel_crtc_state *old_crtc_state) mutex_lock(&crtc->drrs.mutex); - if (intel_drrs_is_enabled(crtc)) + if (intel_drrs_is_active(crtc)) intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_HIGH); crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; @@ -257,7 +259,7 @@ static void intel_drrs_downclock_work(struct work_struct *work) mutex_lock(&crtc->drrs.mutex); - if (intel_drrs_is_enabled(crtc) && !crtc->drrs.busy_frontbuffer_bits) + if (intel_drrs_is_active(crtc) && !crtc->drrs.busy_frontbuffer_bits) intel_drrs_set_state(crtc, DRRS_REFRESH_RATE_LOW); mutex_unlock(&crtc->drrs.mutex); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index 6e84b8e800a6..e2f78cc10061 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -16,9 +16,9 @@ struct intel_crtc_state; struct intel_connector; const char *intel_drrs_type_str(enum drrs_type drrs_type); -bool intel_drrs_is_enabled(struct intel_crtc *crtc); -void intel_drrs_enable(const struct intel_crtc_state *crtc_state); -void intel_drrs_disable(const struct intel_crtc_state *crtc_state); +bool intel_drrs_is_active(struct intel_crtc *crtc); +void intel_drrs_activate(const struct intel_crtc_state *crtc_state); +void intel_drrs_deactivate(const struct intel_crtc_state *crtc_state); void intel_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_drrs_flush(struct drm_i915_private *dev_priv, From 7d14db8b4d83164c2fafed2ee5a12877103b5775 Mon Sep 17 00:00:00 2001 From: Andi Shyti Date: Mon, 21 Mar 2022 14:27:59 +0200 Subject: [PATCH 00299/11454] drm/i915/debugfs: Do not return '0' if there is nothing to return Change functions that always return '0' to be void type. Signed-off-by: Andi Shyti Reviewed-by: Maciej Patelczyk Signed-off-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20220321122759.227091-1-andi.shyti@linux.intel.com --- drivers/gpu/drm/i915/gt/intel_gt_debugfs.c | 7 ++++--- drivers/gpu/drm/i915/gt/intel_gt_debugfs.h | 2 +- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c | 16 ++++++++-------- drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.h | 4 ++-- drivers/gpu/drm/i915/i915_debugfs.c | 9 ++++++--- 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_debugfs.c index 6f45b131a001..d886fdc2c694 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_debugfs.c @@ -30,7 +30,7 @@ int intel_gt_debugfs_reset_show(struct intel_gt *gt, u64 *val) } } -int intel_gt_debugfs_reset_store(struct intel_gt *gt, u64 val) +void intel_gt_debugfs_reset_store(struct intel_gt *gt, u64 val) { /* Flush any previous reset before applying for a new one */ wait_event(gt->reset.queue, @@ -38,7 +38,6 @@ int intel_gt_debugfs_reset_store(struct intel_gt *gt, u64 val) intel_gt_handle_error(gt, val, I915_ERROR_CAPTURE, "Manually reset engine mask to %llx", val); - return 0; } /* @@ -52,7 +51,9 @@ static int __intel_gt_debugfs_reset_show(void *data, u64 *val) static int __intel_gt_debugfs_reset_store(void *data, u64 val) { - return intel_gt_debugfs_reset_store(data, val); + intel_gt_debugfs_reset_store(data, val); + + return 0; } DEFINE_SIMPLE_ATTRIBUTE(reset_fops, __intel_gt_debugfs_reset_show, diff --git a/drivers/gpu/drm/i915/gt/intel_gt_debugfs.h b/drivers/gpu/drm/i915/gt/intel_gt_debugfs.h index 17e79b735cfe..e4110eebf093 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_debugfs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_debugfs.h @@ -48,6 +48,6 @@ void intel_gt_debugfs_register_files(struct dentry *root, /* functions that need to be accessed by the upper level non-gt interfaces */ int intel_gt_debugfs_reset_show(struct intel_gt *gt, u64 *val); -int intel_gt_debugfs_reset_store(struct intel_gt *gt, u64 val); +void intel_gt_debugfs_reset_store(struct intel_gt *gt, u64 val); #endif /* INTEL_GT_DEBUGFS_H */ diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c index 37765919fe32..57a81a1d7dd1 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.c @@ -23,38 +23,38 @@ #include "intel_uncore.h" #include "vlv_sideband.h" -int intel_gt_pm_debugfs_forcewake_user_open(struct intel_gt *gt) +void intel_gt_pm_debugfs_forcewake_user_open(struct intel_gt *gt) { atomic_inc(>->user_wakeref); intel_gt_pm_get(gt); if (GRAPHICS_VER(gt->i915) >= 6) intel_uncore_forcewake_user_get(gt->uncore); - - return 0; } -int intel_gt_pm_debugfs_forcewake_user_release(struct intel_gt *gt) +void intel_gt_pm_debugfs_forcewake_user_release(struct intel_gt *gt) { if (GRAPHICS_VER(gt->i915) >= 6) intel_uncore_forcewake_user_put(gt->uncore); intel_gt_pm_put(gt); atomic_dec(>->user_wakeref); - - return 0; } static int forcewake_user_open(struct inode *inode, struct file *file) { struct intel_gt *gt = inode->i_private; - return intel_gt_pm_debugfs_forcewake_user_open(gt); + intel_gt_pm_debugfs_forcewake_user_open(gt); + + return 0; } static int forcewake_user_release(struct inode *inode, struct file *file) { struct intel_gt *gt = inode->i_private; - return intel_gt_pm_debugfs_forcewake_user_release(gt); + intel_gt_pm_debugfs_forcewake_user_release(gt); + + return 0; } static const struct file_operations forcewake_user_fops = { diff --git a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.h b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.h index a8457887ec65..0ace8c2da0ac 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_pm_debugfs.h @@ -14,7 +14,7 @@ void intel_gt_pm_debugfs_register(struct intel_gt *gt, struct dentry *root); void intel_gt_pm_frequency_dump(struct intel_gt *gt, struct drm_printer *m); /* functions that need to be accessed by the upper level non-gt interfaces */ -int intel_gt_pm_debugfs_forcewake_user_open(struct intel_gt *gt); -int intel_gt_pm_debugfs_forcewake_user_release(struct intel_gt *gt); +void intel_gt_pm_debugfs_forcewake_user_open(struct intel_gt *gt); +void intel_gt_pm_debugfs_forcewake_user_release(struct intel_gt *gt); #endif /* INTEL_GT_PM_DEBUGFS_H */ diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 946bbe57bfe5..9658b4ca669a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -578,8 +578,9 @@ static int i915_wedged_get(void *data, u64 *val) static int i915_wedged_set(void *data, u64 val) { struct drm_i915_private *i915 = data; + intel_gt_debugfs_reset_store(to_gt(i915), val); - return intel_gt_debugfs_reset_store(to_gt(i915), val); + return 0; } DEFINE_SIMPLE_ATTRIBUTE(i915_wedged_fops, @@ -727,15 +728,17 @@ static int i915_sseu_status(struct seq_file *m, void *unused) static int i915_forcewake_open(struct inode *inode, struct file *file) { struct drm_i915_private *i915 = inode->i_private; + intel_gt_pm_debugfs_forcewake_user_open(to_gt(i915)); - return intel_gt_pm_debugfs_forcewake_user_open(to_gt(i915)); + return 0; } static int i915_forcewake_release(struct inode *inode, struct file *file) { struct drm_i915_private *i915 = inode->i_private; + intel_gt_pm_debugfs_forcewake_user_release(to_gt(i915)); - return intel_gt_pm_debugfs_forcewake_user_release(to_gt(i915)); + return 0; } static const struct file_operations i915_forcewake_fops = { From 6f30158f4014d346552cf3b999fd060e856e66d3 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Mar 2022 15:59:55 +0200 Subject: [PATCH 00300/11454] drm/i915/gt: fix i915_reg_t initialization The initialization is there only to silence the compiler, but use the correct initializer for i915_reg_t. Cc: Lucas De Marchi Signed-off-by: Jani Nikula Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321135955.922791-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/gt/intel_ring_submission.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gt/intel_ring_submission.c b/drivers/gpu/drm/i915/gt/intel_ring_submission.c index 6d7ec3bf1f32..5423bfd301ad 100644 --- a/drivers/gpu/drm/i915/gt/intel_ring_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_ring_submission.c @@ -767,7 +767,7 @@ static int mi_set_context(struct i915_request *rq, if (GRAPHICS_VER(i915) == 7) { if (num_engines) { struct intel_engine_cs *signaller; - i915_reg_t last_reg = {}; /* keep gcc quiet */ + i915_reg_t last_reg = INVALID_MMIO_REG; /* keep gcc quiet */ *cs++ = MI_LOAD_REGISTER_IMM(num_engines); for_each_engine(signaller, engine->gt, id) { From 055f15e7be2e03634b54bae53feb134ff1240d13 Mon Sep 17 00:00:00 2001 From: Michael Cheng Date: Mon, 21 Mar 2022 15:38:15 -0700 Subject: [PATCH 00301/11454] drm/i915/gt: Re-work intel_write_status_page Re-work intel_write_status_page to use drm_clflush_virt_range. This will prevent compiler errors when building for non-x86 architectures. Signed-off-by: Michael Cheng Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220321223819.72833-2-michael.cheng@intel.com --- drivers/gpu/drm/i915/gt/intel_engine.h | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine.h b/drivers/gpu/drm/i915/gt/intel_engine.h index 1c0ab05c3c40..1431f1e9dbee 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine.h +++ b/drivers/gpu/drm/i915/gt/intel_engine.h @@ -4,6 +4,7 @@ #include #include +#include #include #include @@ -143,15 +144,9 @@ intel_write_status_page(struct intel_engine_cs *engine, int reg, u32 value) * of extra paranoia to try and ensure that the HWS takes the value * we give and that it doesn't end up trapped inside the CPU! */ - if (static_cpu_has(X86_FEATURE_CLFLUSH)) { - mb(); - clflush(&engine->status_page.addr[reg]); - engine->status_page.addr[reg] = value; - clflush(&engine->status_page.addr[reg]); - mb(); - } else { - WRITE_ONCE(engine->status_page.addr[reg], value); - } + drm_clflush_virt_range(&engine->status_page.addr[reg], sizeof(value)); + WRITE_ONCE(engine->status_page.addr[reg], value); + drm_clflush_virt_range(&engine->status_page.addr[reg], sizeof(value)); } /* From dc0406820ee750f17d516824666fbd6fe5b34537 Mon Sep 17 00:00:00 2001 From: Michael Cheng Date: Mon, 21 Mar 2022 15:38:16 -0700 Subject: [PATCH 00302/11454] drm/i915/gt: Drop invalidate_csb_entries Drop invalidate_csb_entries and directly call drm_clflush_virt_range. This allows for one less function call, and prevent complier errors when building for non-x86 architectures. v2(Michael Cheng): Drop invalidate_csb_entries function and directly invoke drm_clflush_virt_range. Thanks to Tvrtko for the sugguestion. v3(Michael Cheng): Use correct parameters for drm_clflush_virt_range. Thanks to Tvrtko for pointing this out. v4(Michael Cheng): Simplify &execlists->csb_status[0] to execlists->csb_status. Thanks to Matt Roper for the suggestion. Signed-off-by: Michael Cheng Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220321223819.72833-3-michael.cheng@intel.com --- .../gpu/drm/i915/gt/intel_execlists_submission.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index ba42bede183c..436d935d53c2 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -1650,12 +1650,6 @@ cancel_port_requests(struct intel_engine_execlists * const execlists, return inactive; } -static void invalidate_csb_entries(const u64 *first, const u64 *last) -{ - clflush((void *)first); - clflush((void *)last); -} - /* * Starting with Gen12, the status has a new format: * @@ -2003,7 +1997,7 @@ process_csb(struct intel_engine_cs *engine, struct i915_request **inactive) * the wash as hardware, working or not, will need to do the * invalidation before. */ - invalidate_csb_entries(&buf[0], &buf[num_entries - 1]); + drm_clflush_virt_range(&buf[0], num_entries * sizeof(buf[0])); /* * We assume that any event reflects a change in context flow @@ -2787,8 +2781,9 @@ static void reset_csb_pointers(struct intel_engine_cs *engine) /* Check that the GPU does indeed update the CSB entries! */ memset(execlists->csb_status, -1, (reset_value + 1) * sizeof(u64)); - invalidate_csb_entries(&execlists->csb_status[0], - &execlists->csb_status[reset_value]); + drm_clflush_virt_range(execlists->csb_status, + execlists->csb_size * + sizeof(execlists->csb_status)); /* Once more for luck and our trusty paranoia */ ENGINE_WRITE(engine, RING_CONTEXT_STATUS_PTR, From 92b0cba49e80759e4b67757e0eb3499575dc7e06 Mon Sep 17 00:00:00 2001 From: Michael Cheng Date: Mon, 21 Mar 2022 15:38:17 -0700 Subject: [PATCH 00303/11454] drm/i915/gt: Re-work reset_csb Use drm_clflush_virt_range instead of directly invoking clflush. This will prevent compiler errors when building for non-x86 architectures. v2(Michael Cheng): Remove extra clflush v3(Michael Cheng): Remove memory barrier since drm_clflush_virt_range takes care of it. v4(Michael Cheng): Get the size of value and not the size of the pointer when passing in execlists->csb_write. Thanks to Matt Roper for pointing this out. Signed-off-by: Michael Cheng Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220321223819.72833-4-michael.cheng@intel.com --- drivers/gpu/drm/i915/gt/intel_execlists_submission.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 436d935d53c2..4247fe11a105 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2952,9 +2952,8 @@ reset_csb(struct intel_engine_cs *engine, struct i915_request **inactive) { struct intel_engine_execlists * const execlists = &engine->execlists; - mb(); /* paranoia: read the CSB pointers from after the reset */ - clflush(execlists->csb_write); - mb(); + drm_clflush_virt_range(execlists->csb_write, + sizeof(execlists->csb_write[0])); inactive = process_csb(engine, inactive); /* drain preemption events */ From 89754df82f1565f2223293c0a0062b779a33d136 Mon Sep 17 00:00:00 2001 From: Michael Cheng Date: Mon, 21 Mar 2022 15:38:18 -0700 Subject: [PATCH 00304/11454] drm/i915/: Re-work clflush_write32 Use drm_clflush_virt_range instead of clflushopt and remove the memory barrier, since drm_clflush_virt_range takes care of that. v2(Michael Cheng): Use sizeof(*addr) instead of sizeof(addr) to get the actual size of the page. Thanks to Matt Roper for pointing this out. Signed-off-by: Michael Cheng Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220321223819.72833-5-michael.cheng@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c index 3dd69832c4c5..d71fcd4ee68e 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_execbuffer.c @@ -1322,10 +1322,8 @@ static void *reloc_vaddr(struct i915_vma *vma, static void clflush_write32(u32 *addr, u32 value, unsigned int flushes) { if (unlikely(flushes & (CLFLUSH_BEFORE | CLFLUSH_AFTER))) { - if (flushes & CLFLUSH_BEFORE) { - clflushopt(addr); - mb(); - } + if (flushes & CLFLUSH_BEFORE) + drm_clflush_virt_range(addr, sizeof(*addr)); *addr = value; @@ -1337,7 +1335,7 @@ static void clflush_write32(u32 *addr, u32 value, unsigned int flushes) * to ensure ordering of clflush wrt to the system. */ if (flushes & CLFLUSH_AFTER) - clflushopt(addr); + drm_clflush_virt_range(addr, sizeof(*addr)); } else *addr = value; } From 61c5ed946da28e45edc3470e8d9f4da19cb15c8d Mon Sep 17 00:00:00 2001 From: Michael Cheng Date: Mon, 21 Mar 2022 15:38:19 -0700 Subject: [PATCH 00305/11454] drm/i915/gt: replace cache_clflush_range Replace all occurrence of cache_clflush_range with drm_clflush_virt_range. This will prevent compile errors on non-x86 platforms. Signed-off-by: Michael Cheng Reviewed-by: Matt Roper Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220321223819.72833-6-michael.cheng@intel.com --- drivers/gpu/drm/i915/gt/gen8_ppgtt.c | 12 ++++++------ drivers/gpu/drm/i915/gt/intel_execlists_submission.c | 2 +- drivers/gpu/drm/i915/gt/intel_gtt.c | 2 +- drivers/gpu/drm/i915/gt/intel_ppgtt.c | 2 +- drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c index f574da00eff1..c7bd5d71b03e 100644 --- a/drivers/gpu/drm/i915/gt/gen8_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/gen8_ppgtt.c @@ -454,11 +454,11 @@ gen8_ppgtt_insert_pte(struct i915_ppgtt *ppgtt, pd = pdp->entry[gen8_pd_index(idx, 2)]; } - clflush_cache_range(vaddr, PAGE_SIZE); + drm_clflush_virt_range(vaddr, PAGE_SIZE); vaddr = px_vaddr(i915_pt_entry(pd, gen8_pd_index(idx, 1))); } } while (1); - clflush_cache_range(vaddr, PAGE_SIZE); + drm_clflush_virt_range(vaddr, PAGE_SIZE); return idx; } @@ -631,7 +631,7 @@ static void gen8_ppgtt_insert_huge(struct i915_address_space *vm, } } while (rem >= page_size && index < I915_PDES); - clflush_cache_range(vaddr, PAGE_SIZE); + drm_clflush_virt_range(vaddr, PAGE_SIZE); /* * Is it safe to mark the 2M block as 64K? -- Either we have @@ -647,7 +647,7 @@ static void gen8_ppgtt_insert_huge(struct i915_address_space *vm, I915_GTT_PAGE_SIZE_2M)))) { vaddr = px_vaddr(pd); vaddr[maybe_64K] |= GEN8_PDE_IPS_64K; - clflush_cache_range(vaddr, PAGE_SIZE); + drm_clflush_virt_range(vaddr, PAGE_SIZE); page_size = I915_GTT_PAGE_SIZE_64K; /* @@ -668,7 +668,7 @@ static void gen8_ppgtt_insert_huge(struct i915_address_space *vm, for (i = 1; i < index; i += 16) memset64(vaddr + i, encode, 15); - clflush_cache_range(vaddr, PAGE_SIZE); + drm_clflush_virt_range(vaddr, PAGE_SIZE); } } @@ -722,7 +722,7 @@ static void gen8_ppgtt_insert_entry(struct i915_address_space *vm, vaddr = px_vaddr(pt); vaddr[gen8_pd_index(idx, 0)] = gen8_pte_encode(addr, level, flags); - clflush_cache_range(&vaddr[gen8_pd_index(idx, 0)], sizeof(*vaddr)); + drm_clflush_virt_range(&vaddr[gen8_pd_index(idx, 0)], sizeof(*vaddr)); } static void __xehpsdv_ppgtt_insert_entry_lm(struct i915_address_space *vm, diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 4247fe11a105..43575e8c68a4 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2827,7 +2827,7 @@ static void execlists_sanitize(struct intel_engine_cs *engine) sanitize_hwsp(engine); /* And scrub the dirty cachelines for the HWSP */ - clflush_cache_range(engine->status_page.addr, PAGE_SIZE); + drm_clflush_virt_range(engine->status_page.addr, PAGE_SIZE); intel_engine_reset_pinned_contexts(engine); } diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index aed6de2d5a79..719fd31eee80 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -298,7 +298,7 @@ fill_page_dma(struct drm_i915_gem_object *p, const u64 val, unsigned int count) void *vaddr = __px_vaddr(p); memset64(vaddr, val, count); - clflush_cache_range(vaddr, PAGE_SIZE); + drm_clflush_virt_range(vaddr, PAGE_SIZE); } static void poison_scratch_page(struct drm_i915_gem_object *scratch) diff --git a/drivers/gpu/drm/i915/gt/intel_ppgtt.c b/drivers/gpu/drm/i915/gt/intel_ppgtt.c index d91e2beb7517..d8b94d638559 100644 --- a/drivers/gpu/drm/i915/gt/intel_ppgtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ppgtt.c @@ -91,7 +91,7 @@ write_dma_entry(struct drm_i915_gem_object * const pdma, u64 * const vaddr = __px_vaddr(pdma); vaddr[idx] = encoded_entry; - clflush_cache_range(&vaddr[idx], sizeof(u64)); + drm_clflush_virt_range(&vaddr[idx], sizeof(u64)); } void diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 9ec03234d2c2..42c9e8b7bf42 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -3581,7 +3581,7 @@ static void guc_sanitize(struct intel_engine_cs *engine) sanitize_hwsp(engine); /* And scrub the dirty cachelines for the HWSP */ - clflush_cache_range(engine->status_page.addr, PAGE_SIZE); + drm_clflush_virt_range(engine->status_page.addr, PAGE_SIZE); intel_engine_reset_pinned_contexts(engine); } From 24492514ccbd57121f168bb14939f32d8905d579 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:15 -0700 Subject: [PATCH 00306/11454] drm/i915/guc: Update GuC ADS size for error capture lists Update GuC ADS size allocation to include space for the lists of error state capture register descriptors. Then, populate GuC ADS with the lists of registers we want GuC to report back to host on engine reset events. This list should include global, engine-class and engine-instance registers for every engine-class type on the current hardware. Ensure we allocate a persistent store for the register lists that are populated into ADS so that we don't need to allocate memory during GT resets when GuC is reloaded and ADS population happens again. NOTE: Start with a sample static table of register lists to layout the framework before adding real registers in subsequent patch. This static register tables are a different format from the ADS populated list. Signed-off-by: Alan Previn Reviewed-by: Matthew Brost Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-2-alan.previn.teres.alexis@intel.com --- drivers/gpu/drm/i915/Makefile | 1 + drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 91 +++++ drivers/gpu/drm/i915/gt/uc/intel_guc.c | 13 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 9 +- drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c | 127 +++++- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 374 ++++++++++++++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 22 ++ drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 8 + 8 files changed, 628 insertions(+), 17 deletions(-) create mode 100644 drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c create mode 100644 drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h diff --git a/drivers/gpu/drm/i915/Makefile b/drivers/gpu/drm/i915/Makefile index 9801aaa9885d..c837a29ffac8 100644 --- a/drivers/gpu/drm/i915/Makefile +++ b/drivers/gpu/drm/i915/Makefile @@ -186,6 +186,7 @@ i915-y += gt/uc/intel_uc.o \ gt/uc/intel_uc_fw.o \ gt/uc/intel_guc.o \ gt/uc/intel_guc_ads.o \ + gt/uc/intel_guc_capture.o \ gt/uc/intel_guc_ct.o \ gt/uc/intel_guc_debugfs.o \ gt/uc/intel_guc_fw.o \ diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h new file mode 100644 index 000000000000..919ed985f09a --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -0,0 +1,91 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021-2022 Intel Corporation + */ + +#ifndef _INTEL_GUC_CAPTURE_FWIF_H +#define _INTEL_GUC_CAPTURE_FWIF_H + +#include +#include "intel_guc_fwif.h" + +struct intel_guc; +struct file; + +/** + * struct guc_debug_capture_list_header / struct guc_debug_capture_list + * + * As part of ADS registration, these header structures (followed by + * an array of 'struct guc_mmio_reg' entries) are used to register with + * GuC microkernel the list of registers we want it to dump out prior + * to a engine reset. + */ +struct guc_debug_capture_list_header { + u32 info; +#define GUC_CAPTURELISTHDR_NUMDESCR GENMASK(15, 0) +} __packed; + +struct guc_debug_capture_list { + struct guc_debug_capture_list_header header; + struct guc_mmio_reg regs[0]; +} __packed; + +/** + * struct __guc_mmio_reg_descr / struct __guc_mmio_reg_descr_group + * + * intel_guc_capture module uses these structures to maintain static + * tables (per unique platform) that consists of lists of registers + * (offsets, names, flags,...) that are used at the ADS regisration + * time as well as during runtime processing and reporting of error- + * capture states generated by GuC just prior to engine reset events. + */ +struct __guc_mmio_reg_descr { + i915_reg_t reg; + u32 flags; + u32 mask; + const char *regname; +}; + +struct __guc_mmio_reg_descr_group { + const struct __guc_mmio_reg_descr *list; + u32 num_regs; + u32 owner; /* see enum guc_capture_owner */ + u32 type; /* see enum guc_capture_type */ + u32 engine; /* as per MAX_ENGINE_CLASS */ +}; + +/** + * struct __guc_capture_ads_cache + * + * A structure to cache register lists that were populated and registered + * with GuC at startup during ADS registration. This allows much quicker + * GuC resets without re-parsing all the tables for the given gt. + */ +struct __guc_capture_ads_cache { + bool is_valid; + void *ptr; + size_t size; + int status; +}; + +/** + * struct intel_guc_state_capture + * + * Internal context of the intel_guc_capture module. + */ +struct intel_guc_state_capture { + /** + * @reglists: static table of register lists used for error-capture state. + */ + const struct __guc_mmio_reg_descr_group *reglists; + + /** + * @ads_cache: cached register lists that is ADS format ready + */ + struct __guc_capture_ads_cache ads_cache[GUC_CAPTURE_LIST_INDEX_MAX] + [GUC_CAPTURE_LIST_TYPE_MAX] + [GUC_MAX_ENGINE_CLASSES]; + void *ads_null_cache; +}; + +#endif /* _INTEL_GUC_CAPTURE_FWIF_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.c b/drivers/gpu/drm/i915/gt/uc/intel_guc.c index 447a976c9f25..cda7e4bb8bac 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.c @@ -9,8 +9,9 @@ #include "gt/intel_gt_pm_irq.h" #include "gt/intel_gt_regs.h" #include "intel_guc.h" -#include "intel_guc_slpc.h" #include "intel_guc_ads.h" +#include "intel_guc_capture.h" +#include "intel_guc_slpc.h" #include "intel_guc_submission.h" #include "i915_drv.h" #include "i915_irq.h" @@ -362,9 +363,14 @@ int intel_guc_init(struct intel_guc *guc) if (ret) goto err_fw; - ret = intel_guc_ads_create(guc); + ret = intel_guc_capture_init(guc); if (ret) goto err_log; + + ret = intel_guc_ads_create(guc); + if (ret) + goto err_capture; + GEM_BUG_ON(!guc->ads_vma); ret = intel_guc_ct_init(&guc->ct); @@ -403,6 +409,8 @@ err_ct: intel_guc_ct_fini(&guc->ct); err_ads: intel_guc_ads_destroy(guc); +err_capture: + intel_guc_capture_destroy(guc); err_log: intel_guc_log_destroy(&guc->log); err_fw: @@ -430,6 +438,7 @@ void intel_guc_fini(struct intel_guc *guc) intel_guc_ct_fini(&guc->ct); intel_guc_ads_destroy(guc); + intel_guc_capture_destroy(guc); intel_guc_log_destroy(&guc->log); intel_uc_fw_fini(&guc->fw); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index e439e6c1ac8b..de32367831c6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -10,18 +10,19 @@ #include #include -#include "intel_uncore.h" +#include "intel_guc_ct.h" #include "intel_guc_fw.h" #include "intel_guc_fwif.h" -#include "intel_guc_ct.h" #include "intel_guc_log.h" #include "intel_guc_reg.h" #include "intel_guc_slpc_types.h" #include "intel_uc_fw.h" +#include "intel_uncore.h" #include "i915_utils.h" #include "i915_vma.h" struct __guc_ads_blob; +struct intel_guc_state_capture; /** * struct intel_guc - Top level structure of GuC. @@ -38,6 +39,8 @@ struct intel_guc { struct intel_guc_ct ct; /** @slpc: sub-structure containing SLPC related data and objects */ struct intel_guc_slpc slpc; + /** @capture: the error-state-capture module's data and objects */ + struct intel_guc_state_capture *capture; /** @sched_engine: Global engine used to submit requests to GuC */ struct i915_sched_engine *sched_engine; @@ -162,6 +165,8 @@ struct intel_guc { struct guc_mmio_reg *ads_regset; /** @ads_golden_ctxt_size: size of the golden contexts in the ADS */ u32 ads_golden_ctxt_size; + /** @ads_capture_size: size of register lists in the ADS used for error capture */ + u32 ads_capture_size; /** @ads_engine_usage_size: size of engine usage in the ADS */ u32 ads_engine_usage_size; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c index feb372fc0b48..17004bca4d24 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_ads.c @@ -11,6 +11,7 @@ #include "gt/intel_lrc.h" #include "gt/shmem_utils.h" #include "intel_guc_ads.h" +#include "intel_guc_capture.h" #include "intel_guc_fwif.h" #include "intel_uc.h" #include "i915_drv.h" @@ -86,8 +87,7 @@ static u32 guc_ads_golden_ctxt_size(struct intel_guc *guc) static u32 guc_ads_capture_size(struct intel_guc *guc) { - /* FIXME: Allocate a proper capture list */ - return PAGE_ALIGN(PAGE_SIZE); + return PAGE_ALIGN(guc->ads_capture_size); } static u32 guc_ads_private_data_size(struct intel_guc *guc) @@ -611,24 +611,119 @@ static void guc_init_golden_context(struct intel_guc *guc) GEM_BUG_ON(guc->ads_golden_ctxt_size != total_size); } -static void guc_capture_list_init(struct intel_guc *guc) +static int +guc_capture_prep_lists(struct intel_guc *guc) { + struct intel_gt *gt = guc_to_gt(guc); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + u32 ads_ggtt, capture_offset, null_ggtt, total_size = 0; + struct guc_gt_system_info local_info; + struct iosys_map info_map; + bool ads_is_mapped; + size_t size = 0; + void *ptr; int i, j; - u32 addr_ggtt, offset; - offset = guc_ads_capture_offset(guc); - addr_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma) + offset; + ads_is_mapped = !iosys_map_is_null(&guc->ads_map); + if (ads_is_mapped) { + capture_offset = guc_ads_capture_offset(guc); + ads_ggtt = intel_guc_ggtt_offset(guc, guc->ads_vma); + info_map = IOSYS_MAP_INIT_OFFSET(&guc->ads_map, + offsetof(struct __guc_ads_blob, system_info)); + } else { + memset(&local_info, 0, sizeof(local_info)); + iosys_map_set_vaddr(&info_map, &local_info); + fill_engine_enable_masks(gt, &info_map); + } - /* FIXME: Populate a proper capture list */ + /* first, set aside the first page for a capture_list with zero descriptors */ + total_size = PAGE_SIZE; + if (ads_is_mapped) { + if (!intel_guc_capture_getnullheader(guc, &ptr, &size)) + iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size); + null_ggtt = ads_ggtt + capture_offset; + capture_offset += PAGE_SIZE; + } for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; i++) { for (j = 0; j < GUC_MAX_ENGINE_CLASSES; j++) { - ads_blob_write(guc, ads.capture_instance[i][j], addr_ggtt); - ads_blob_write(guc, ads.capture_class[i][j], addr_ggtt); - } - ads_blob_write(guc, ads.capture_global[i], addr_ggtt); + /* null list if we dont have said engine or list */ + if (!info_map_read(&info_map, engine_enabled_masks[j])) { + if (ads_is_mapped) { + ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); + ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); + } + continue; + } + if (intel_guc_capture_getlistsize(guc, i, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + j, &size)) { + if (ads_is_mapped) + ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); + goto engine_instance_list; + } + total_size += size; + if (ads_is_mapped) { + if (total_size > guc->ads_capture_size || + intel_guc_capture_getlist(guc, i, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + j, &ptr)) { + ads_blob_write(guc, ads.capture_class[i][j], null_ggtt); + continue; + } + ads_blob_write(guc, ads.capture_class[i][j], ads_ggtt + + capture_offset); + iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size); + capture_offset += size; + } +engine_instance_list: + if (intel_guc_capture_getlistsize(guc, i, + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + j, &size)) { + if (ads_is_mapped) + ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); + continue; + } + total_size += size; + if (ads_is_mapped) { + if (total_size > guc->ads_capture_size || + intel_guc_capture_getlist(guc, i, + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + j, &ptr)) { + ads_blob_write(guc, ads.capture_instance[i][j], null_ggtt); + continue; + } + ads_blob_write(guc, ads.capture_instance[i][j], ads_ggtt + + capture_offset); + iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size); + capture_offset += size; + } + } + if (intel_guc_capture_getlistsize(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &size)) { + if (ads_is_mapped) + ads_blob_write(guc, ads.capture_global[i], null_ggtt); + continue; + } + total_size += size; + if (ads_is_mapped) { + if (total_size > guc->ads_capture_size || + intel_guc_capture_getlist(guc, i, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, + &ptr)) { + ads_blob_write(guc, ads.capture_global[i], null_ggtt); + continue; + } + ads_blob_write(guc, ads.capture_global[i], ads_ggtt + capture_offset); + iosys_map_memcpy_to(&guc->ads_map, capture_offset, ptr, size); + capture_offset += size; + } } + + if (guc->ads_capture_size && guc->ads_capture_size != PAGE_ALIGN(total_size)) + drm_warn(&i915->drm, "GuC->ADS->Capture alloc size changed from %d to %d\n", + guc->ads_capture_size, PAGE_ALIGN(total_size)); + + return PAGE_ALIGN(total_size); } static void __guc_ads_init(struct intel_guc *guc) @@ -666,8 +761,8 @@ static void __guc_ads_init(struct intel_guc *guc) base = intel_guc_ggtt_offset(guc, guc->ads_vma); - /* Capture list for hang debug */ - guc_capture_list_init(guc); + /* Lists for error capture debug */ + guc_capture_prep_lists(guc); /* ADS */ ads_blob_write(guc, ads.scheduler_policies, base + @@ -715,6 +810,12 @@ int intel_guc_ads_create(struct intel_guc *guc) return ret; guc->ads_golden_ctxt_size = ret; + /* Likewise the capture lists: */ + ret = guc_capture_prep_lists(guc); + if (ret < 0) + return ret; + guc->ads_capture_size = ret; + /* Now the total size can be determined: */ size = guc_ads_blob_size(guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c new file mode 100644 index 000000000000..4adfa14699d4 --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -0,0 +1,374 @@ +// SPDX-License-Identifier: MIT +/* + * Copyright © 2021-2022 Intel Corporation + */ + +#include + +#include + +#include "gt/intel_engine_regs.h" +#include "gt/intel_gt.h" +#include "gt/intel_gt_regs.h" +#include "guc_capture_fwif.h" +#include "intel_guc_capture.h" +#include "intel_guc_fwif.h" +#include "i915_drv.h" +#include "i915_memcpy.h" +#include "i915_reg.h" + +/* + * Define all device tables of GuC error capture register lists + * NOTE: For engine-registers, GuC only needs the register offsets + * from the engine-mmio-base + */ +/* XE_LPD - Global */ +static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { + { GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG" } +}; + +/* XE_LPD - Render / Compute Per-Class */ +static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { + { EIR, 0, 0, "EIR" } +}; + +/* XE_LPD - Render / Compute Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { + { RING_HEAD(0), 0, 0, "RING_HEAD" }, + { RING_TAIL(0), 0, 0, "RING_TAIL" }, +}; + +/* XE_LPD - Media Decode/Encode Per-Class */ +static const struct __guc_mmio_reg_descr xe_lpd_vd_class_regs[] = { +}; + +/* XE_LPD - Media Decode/Encode Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { + { RING_HEAD(0), 0, 0, "RING_HEAD" }, + { RING_TAIL(0), 0, 0, "RING_TAIL" }, +}; + +/* XE_LPD - Video Enhancement Per-Class */ +static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { +}; + +/* XE_LPD - Video Enhancement Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { + { RING_HEAD(0), 0, 0, "RING_HEAD" }, + { RING_TAIL(0), 0, 0, "RING_TAIL" }, +}; + +#define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) +#define TO_GCAP_DEF_TYPE(x) (GUC_CAPTURE_LIST_TYPE_##x) +#define MAKE_REGLIST(regslist, regsowner, regstype, class) \ + { \ + regslist, \ + ARRAY_SIZE(regslist), \ + TO_GCAP_DEF_OWNER(regsowner), \ + TO_GCAP_DEF_TYPE(regstype), \ + class, \ + } + +/* List of lists */ +static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { + MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0), + MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_vd_class_regs, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), + MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), + MAKE_REGLIST(xe_lpd_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), + {} +}; + +static const struct __guc_mmio_reg_descr_group * +guc_capture_get_device_reglist(struct intel_guc *guc) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + + if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) || + IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) { + return xe_lpd_lists; + } + + return NULL; +} + +static const struct __guc_mmio_reg_descr_group * +guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, + u32 owner, u32 type, u32 id) +{ + int i; + + if (!reglists) + return NULL; + + for (i = 0; reglists[i].list; ++i) { + if (reglists[i].owner == owner && reglists[i].type == type && + (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) + return ®lists[i]; + } + + return NULL; +} + +static const char * +__stringify_owner(u32 owner) +{ + switch (owner) { + case GUC_CAPTURE_LIST_INDEX_PF: + return "PF"; + case GUC_CAPTURE_LIST_INDEX_VF: + return "VF"; + default: + return "unknown"; + } + + return ""; +} + +static const char * +__stringify_type(u32 type) +{ + switch (type) { + case GUC_CAPTURE_LIST_TYPE_GLOBAL: + return "Global"; + case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: + return "Class"; + case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: + return "Instance"; + default: + return "unknown"; + } + + return ""; +} + +static const char * +__stringify_engclass(u32 class) +{ + switch (class) { + case GUC_RENDER_CLASS: + return "Render"; + case GUC_VIDEO_CLASS: + return "Video"; + case GUC_VIDEOENHANCE_CLASS: + return "VideoEnhance"; + case GUC_BLITTER_CLASS: + return "Blitter"; + case GUC_COMPUTE_CLASS: + return "Compute"; + default: + return "unknown"; + } + + return ""; +} + +static void +guc_capture_warn_with_list_info(struct drm_i915_private *i915, char *msg, + u32 owner, u32 type, u32 classid) +{ + if (type == GUC_CAPTURE_LIST_TYPE_GLOBAL) + drm_dbg(&i915->drm, "GuC-capture: %s for %s %s-Registers.\n", msg, + __stringify_owner(owner), __stringify_type(type)); + else + drm_dbg(&i915->drm, "GuC-capture: %s for %s %s-Registers on %s-Engine\n", msg, + __stringify_owner(owner), __stringify_type(type), + __stringify_engclass(classid)); +} + +static int +guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + struct guc_mmio_reg *ptr, u16 num_entries) +{ + u32 i = 0; + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists; + const struct __guc_mmio_reg_descr_group *match; + + if (!reglists) + return -ENODEV; + + match = guc_capture_get_one_list(reglists, owner, type, classid); + if (match) { + for (i = 0; i < num_entries && i < match->num_regs; ++i) { + ptr[i].offset = match->list[i].reg.reg; + ptr[i].value = 0xDEADF00D; + ptr[i].flags = match->list[i].flags; + ptr[i].mask = match->list[i].mask; + } + return 0; + } + + guc_capture_warn_with_list_info(i915, "Missing register list init", owner, type, + classid); + + return -ENODATA; +} + +static int +guc_cap_list_num_regs(struct intel_guc_state_capture *gc, u32 owner, u32 type, u32 classid) +{ + const struct __guc_mmio_reg_descr_group *match; + + match = guc_capture_get_one_list(gc->reglists, owner, type, classid); + if (!match) + return 0; + + return match->num_regs; +} + +int +intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + size_t *size) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct intel_guc_state_capture *gc = guc->capture; + struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid]; + int num_regs; + + if (!gc->reglists) + return -ENODEV; + + if (cache->is_valid) { + *size = cache->size; + return cache->status; + } + + num_regs = guc_cap_list_num_regs(gc, owner, type, classid); + if (!num_regs) { + guc_capture_warn_with_list_info(i915, "Missing register list size", + owner, type, classid); + return -ENODATA; + } + + *size = PAGE_ALIGN((sizeof(struct guc_debug_capture_list)) + + (num_regs * sizeof(struct guc_mmio_reg))); + + return 0; +} + +int +intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + void **outptr) +{ + struct intel_guc_state_capture *gc = guc->capture; + struct __guc_capture_ads_cache *cache = &gc->ads_cache[owner][type][classid]; + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct guc_debug_capture_list *listnode; + int ret, num_regs; + u8 *caplist, *tmp; + size_t size = 0; + + if (!gc->reglists) + return -ENODEV; + + if (cache->is_valid) { + *outptr = cache->ptr; + return cache->status; + } + + ret = intel_guc_capture_getlistsize(guc, owner, type, classid, &size); + if (ret) { + cache->is_valid = true; + cache->ptr = NULL; + cache->size = 0; + cache->status = ret; + return ret; + } + + caplist = kzalloc(size, GFP_KERNEL); + if (!caplist) { + drm_dbg(&i915->drm, "GuC-capture: failed to alloc cached caplist"); + return -ENOMEM; + } + + /* populate capture list header */ + tmp = caplist; + num_regs = guc_cap_list_num_regs(guc->capture, owner, type, classid); + listnode = (struct guc_debug_capture_list *)tmp; + listnode->header.info = FIELD_PREP(GUC_CAPTURELISTHDR_NUMDESCR, (u32)num_regs); + + /* populate list of register descriptor */ + tmp += sizeof(struct guc_debug_capture_list); + guc_capture_list_init(guc, owner, type, classid, (struct guc_mmio_reg *)tmp, num_regs); + + /* cache this list */ + cache->is_valid = true; + cache->ptr = caplist; + cache->size = size; + cache->status = 0; + + *outptr = caplist; + + return 0; +} + +int +intel_guc_capture_getnullheader(struct intel_guc *guc, + void **outptr, size_t *size) +{ + struct intel_guc_state_capture *gc = guc->capture; + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int tmp = sizeof(u32) * 4; + void *null_header; + + if (gc->ads_null_cache) { + *outptr = gc->ads_null_cache; + *size = tmp; + return 0; + } + + null_header = kzalloc(tmp, GFP_KERNEL); + if (!null_header) { + drm_dbg(&i915->drm, "GuC-capture: failed to alloc cached nulllist"); + return -ENOMEM; + } + + gc->ads_null_cache = null_header; + *outptr = null_header; + *size = tmp; + + return 0; +} + +static void +guc_capture_free_ads_cache(struct intel_guc_state_capture *gc) +{ + int i, j, k; + struct __guc_capture_ads_cache *cache; + + for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) { + for (j = 0; j < GUC_CAPTURE_LIST_TYPE_MAX; ++j) { + for (k = 0; k < GUC_MAX_ENGINE_CLASSES; ++k) { + cache = &gc->ads_cache[i][j][k]; + if (cache->is_valid) + kfree(cache->ptr); + } + } + } + kfree(gc->ads_null_cache); +} + +void intel_guc_capture_destroy(struct intel_guc *guc) +{ + if (!guc->capture) + return; + + guc_capture_free_ads_cache(guc->capture); + + kfree(guc->capture); + guc->capture = NULL; +} + +int intel_guc_capture_init(struct intel_guc *guc) +{ + guc->capture = kzalloc(sizeof(*guc->capture), GFP_KERNEL); + if (!guc->capture) + return -ENOMEM; + + guc->capture->reglists = guc_capture_get_device_reglist(guc); + + return 0; +} diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h new file mode 100644 index 000000000000..8de7704e12eb --- /dev/null +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2021-2021 Intel Corporation + */ + +#ifndef _INTEL_GUC_CAPTURE_H +#define _INTEL_GUC_CAPTURE_H + +#include + +struct guc_gt_system_info; +struct intel_guc; + +int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + void **outptr); +int intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, + size_t *size); +int intel_guc_capture_getnullheader(struct intel_guc *guc, void **outptr, size_t *size); +void intel_guc_capture_destroy(struct intel_guc *guc); +int intel_guc_capture_init(struct intel_guc *guc); + +#endif /* _INTEL_GUC_CAPTURE_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index 78590372b85f..d18037493953 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -314,6 +314,14 @@ enum { GUC_CAPTURE_LIST_INDEX_MAX = 2, }; +/*Register-types of GuC capture register lists */ +enum guc_capture_type { + GUC_CAPTURE_LIST_TYPE_GLOBAL = 0, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + GUC_CAPTURE_LIST_TYPE_MAX, +}; + /* GuC Additional Data Struct */ struct guc_ads { struct guc_mmio_reg_set reg_state_list[GUC_MAX_ENGINE_CLASSES][GUC_MAX_INSTANCES_PER_CLASS]; From 8b72c21618de6039d53b3300d4d5f3a3dd69c077 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:16 -0700 Subject: [PATCH 00307/11454] drm/i915/guc: Add XE_LP static registers for GuC error capture. Add device specific tables and register lists to cover different engines class types for GuC error state capture for XE_LP products. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-3-alan.previn.teres.alexis@intel.com --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 112 ++++++++++++++---- drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h | 6 +- 2 files changed, 95 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 4adfa14699d4..478308f33d34 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -22,40 +22,106 @@ * NOTE: For engine-registers, GuC only needs the register offsets * from the engine-mmio-base */ +#define COMMON_GEN12BASE_GLOBAL \ + { GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0" }, \ + { GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1" }, \ + { FORCEWAKE_MT, 0, 0, "FORCEWAKE" }, \ + { GEN12_AUX_ERR_DBG, 0, 0, "AUX_ERR_DBG" }, \ + { GEN12_GAM_DONE, 0, 0, "GAM_DONE" }, \ + { GEN12_RING_FAULT_REG, 0, 0, "FAULT_REG" } + +#define COMMON_GEN12BASE_ENGINE_INSTANCE \ + { RING_PSMI_CTL(0), 0, 0, "RC PSMI" }, \ + { RING_ESR(0), 0, 0, "ESR" }, \ + { RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LDW" }, \ + { RING_DMA_FADD_UDW(0), 0, 0, "RING_DMA_FADD_UDW" }, \ + { RING_IPEIR(0), 0, 0, "IPEIR" }, \ + { RING_IPEHR(0), 0, 0, "IPEHR" }, \ + { RING_INSTPS(0), 0, 0, "INSTPS" }, \ + { RING_BBADDR(0), 0, 0, "RING_BBADDR_LOW32" }, \ + { RING_BBADDR_UDW(0), 0, 0, "RING_BBADDR_UP32" }, \ + { RING_BBSTATE(0), 0, 0, "BB_STATE" }, \ + { CCID(0), 0, 0, "CCID" }, \ + { RING_ACTHD(0), 0, 0, "ACTHD_LDW" }, \ + { RING_ACTHD_UDW(0), 0, 0, "ACTHD_UDW" }, \ + { RING_INSTPM(0), 0, 0, "INSTPM" }, \ + { RING_INSTDONE(0), 0, 0, "INSTDONE" }, \ + { RING_NOPID(0), 0, 0, "RING_NOPID" }, \ + { RING_START(0), 0, 0, "START" }, \ + { RING_HEAD(0), 0, 0, "HEAD" }, \ + { RING_TAIL(0), 0, 0, "TAIL" }, \ + { RING_CTL(0), 0, 0, "CTL" }, \ + { RING_MI_MODE(0), 0, 0, "MODE" }, \ + { RING_CONTEXT_CONTROL(0), 0, 0, "RING_CONTEXT_CONTROL" }, \ + { RING_HWS_PGA(0), 0, 0, "HWS" }, \ + { RING_MODE_GEN7(0), 0, 0, "GFX_MODE" }, \ + { GEN8_RING_PDP_LDW(0, 0), 0, 0, "PDP0_LDW" }, \ + { GEN8_RING_PDP_UDW(0, 0), 0, 0, "PDP0_UDW" }, \ + { GEN8_RING_PDP_LDW(0, 1), 0, 0, "PDP1_LDW" }, \ + { GEN8_RING_PDP_UDW(0, 1), 0, 0, "PDP1_UDW" }, \ + { GEN8_RING_PDP_LDW(0, 2), 0, 0, "PDP2_LDW" }, \ + { GEN8_RING_PDP_UDW(0, 2), 0, 0, "PDP2_UDW" }, \ + { GEN8_RING_PDP_LDW(0, 3), 0, 0, "PDP3_LDW" }, \ + { GEN8_RING_PDP_UDW(0, 3), 0, 0, "PDP3_UDW" } + +#define COMMON_GEN12BASE_HAS_EU \ + { EIR, 0, 0, "EIR" } + +#define COMMON_GEN12BASE_RENDER \ + { GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE" }, \ + { GEN12_SC_INSTDONE_EXTRA, 0, 0, "GEN12_SC_INSTDONE_EXTRA" }, \ + { GEN12_SC_INSTDONE_EXTRA2, 0, 0, "GEN12_SC_INSTDONE_EXTRA2" } + +#define COMMON_GEN12BASE_VEC \ + { GEN12_SFC_DONE(0), 0, 0, "SFC_DONE[0]" }, \ + { GEN12_SFC_DONE(1), 0, 0, "SFC_DONE[1]" }, \ + { GEN12_SFC_DONE(2), 0, 0, "SFC_DONE[2]" }, \ + { GEN12_SFC_DONE(3), 0, 0, "SFC_DONE[3]" } + /* XE_LPD - Global */ static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { - { GEN12_RING_FAULT_REG, 0, 0, "GEN12_RING_FAULT_REG" } + COMMON_GEN12BASE_GLOBAL, }; /* XE_LPD - Render / Compute Per-Class */ static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { - { EIR, 0, 0, "EIR" } + COMMON_GEN12BASE_HAS_EU, + COMMON_GEN12BASE_RENDER, }; /* XE_LPD - Render / Compute Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { - { RING_HEAD(0), 0, 0, "RING_HEAD" }, - { RING_TAIL(0), 0, 0, "RING_TAIL" }, + COMMON_GEN12BASE_ENGINE_INSTANCE, }; /* XE_LPD - Media Decode/Encode Per-Class */ static const struct __guc_mmio_reg_descr xe_lpd_vd_class_regs[] = { + COMMON_GEN12BASE_ENGINE_INSTANCE, }; /* XE_LPD - Media Decode/Encode Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { - { RING_HEAD(0), 0, 0, "RING_HEAD" }, - { RING_TAIL(0), 0, 0, "RING_TAIL" }, + COMMON_GEN12BASE_ENGINE_INSTANCE, }; /* XE_LPD - Video Enhancement Per-Class */ static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { + COMMON_GEN12BASE_VEC, }; /* XE_LPD - Video Enhancement Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { - { RING_HEAD(0), 0, 0, "RING_HEAD" }, - { RING_TAIL(0), 0, 0, "RING_TAIL" }, + COMMON_GEN12BASE_ENGINE_INSTANCE, +}; + +/* XE_LPD - Blitter Per-Engine-Instance */ +static const struct __guc_mmio_reg_descr xe_lpd_blt_inst_regs[] = { + COMMON_GEN12BASE_ENGINE_INSTANCE, +}; + +/* XE_LPD - Blitter Per-Class */ +/* XE_LPD - Media Decode/Encode Per-Class */ +static const struct __guc_mmio_reg_descr empty_regs_list[] = { }; #define TO_GCAP_DEF_OWNER(x) (GUC_CAPTURE_LIST_INDEX_##x) @@ -74,10 +140,12 @@ static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0), MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), - MAKE_REGLIST(xe_lpd_vd_class_regs, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), MAKE_REGLIST(xe_lpd_vec_class_regs, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS), + MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS), {} }; @@ -191,20 +259,24 @@ guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, return -ENODEV; match = guc_capture_get_one_list(reglists, owner, type, classid); - if (match) { - for (i = 0; i < num_entries && i < match->num_regs; ++i) { - ptr[i].offset = match->list[i].reg.reg; - ptr[i].value = 0xDEADF00D; - ptr[i].flags = match->list[i].flags; - ptr[i].mask = match->list[i].mask; - } - return 0; + if (!match) { + guc_capture_warn_with_list_info(i915, "Missing register list init", owner, type, + classid); + return -ENODATA; } - guc_capture_warn_with_list_info(i915, "Missing register list init", owner, type, - classid); + for (i = 0; i < num_entries && i < match->num_regs; ++i) { + ptr[i].offset = match->list[i].reg.reg; + ptr[i].value = 0xDEADF00D; + ptr[i].flags = match->list[i].flags; + ptr[i].mask = match->list[i].mask; + } - return -ENODATA; + if (i < num_entries) + drm_dbg(&i915->drm, "GuC-capture: Init reglist short %d out %d.\n", + (int)i, (int)num_entries); + + return 0; } static int diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h index d18037493953..f21b6de46a99 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_fwif.h @@ -285,13 +285,13 @@ struct guc_mmio_reg { u32 offset; u32 value; u32 flags; - u32 mask; #define GUC_REGSET_MASKED BIT(0) #define GUC_REGSET_NEEDS_STEERING BIT(1) #define GUC_REGSET_MASKED_WITH_VALUE BIT(2) #define GUC_REGSET_RESTORE_ONLY BIT(3) -#define GUC_REGSET_STEERING_GROUP GENMASK(15, 12) -#define GUC_REGSET_STEERING_INSTANCE GENMASK(23, 20) +#define GUC_REGSET_STEERING_GROUP GENMASK(15, 12) +#define GUC_REGSET_STEERING_INSTANCE GENMASK(23, 20) + u32 mask; } __packed; /* GuC register sets */ From 193be3f448ca75f9bfd36a7b489201f3572a8b49 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:17 -0700 Subject: [PATCH 00308/11454] drm/i915/guc: Add XE_LP steered register lists support Add the ability for runtime allocation and freeing of steered register list extentions that depend on the detected HW config fuses. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-4-alan.previn.teres.alexis@intel.com --- drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 9 + .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 184 ++++++++++++++++-- 2 files changed, 178 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 919ed985f09a..6c199433945d 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -52,6 +52,7 @@ struct __guc_mmio_reg_descr_group { u32 owner; /* see enum guc_capture_owner */ u32 type; /* see enum guc_capture_type */ u32 engine; /* as per MAX_ENGINE_CLASS */ + struct __guc_mmio_reg_descr *extlist; /* only used for steered registers */ }; /** @@ -79,6 +80,14 @@ struct intel_guc_state_capture { */ const struct __guc_mmio_reg_descr_group *reglists; + /** + * @extlists: allocated table of steered register lists used for error-capture state. + * + * NOTE: steered registers have multiple instances depending on the HW configuration + * (slices or dual-sub-slices) and thus depends on HW fuses discovered at startup + */ + struct __guc_mmio_reg_descr_group *extlists; + /** * @ads_cache: cached register lists that is ADS format ready */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 478308f33d34..45ed09f3453d 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -133,6 +133,7 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = { TO_GCAP_DEF_OWNER(regsowner), \ TO_GCAP_DEF_TYPE(regstype), \ class, \ + NULL, \ } /* List of lists */ @@ -149,19 +150,6 @@ static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { {} }; -static const struct __guc_mmio_reg_descr_group * -guc_capture_get_device_reglist(struct intel_guc *guc) -{ - struct drm_i915_private *i915 = guc_to_gt(guc)->i915; - - if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) || - IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) { - return xe_lpd_lists; - } - - return NULL; -} - static const struct __guc_mmio_reg_descr_group * guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, u32 owner, u32 type, u32 id) @@ -180,6 +168,145 @@ guc_capture_get_one_list(const struct __guc_mmio_reg_descr_group *reglists, return NULL; } +static struct __guc_mmio_reg_descr_group * +guc_capture_get_one_ext_list(struct __guc_mmio_reg_descr_group *reglists, + u32 owner, u32 type, u32 id) +{ + int i; + + if (!reglists) + return NULL; + + for (i = 0; reglists[i].extlist; ++i) { + if (reglists[i].owner == owner && reglists[i].type == type && + (reglists[i].engine == id || reglists[i].type == GUC_CAPTURE_LIST_TYPE_GLOBAL)) + return ®lists[i]; + } + + return NULL; +} + +static void guc_capture_free_extlists(struct __guc_mmio_reg_descr_group *reglists) +{ + int i = 0; + + if (!reglists) + return; + + while (reglists[i].extlist) + kfree(reglists[i++].extlist); +} + +struct __ext_steer_reg { + const char *name; + i915_reg_t reg; +}; + +static const struct __ext_steer_reg xe_extregs[] = { + {"GEN7_SAMPLER_INSTDONE", GEN7_SAMPLER_INSTDONE}, + {"GEN7_ROW_INSTDONE", GEN7_ROW_INSTDONE} +}; + +static void __fill_ext_reg(struct __guc_mmio_reg_descr *ext, + const struct __ext_steer_reg *extlist, + int slice_id, int subslice_id) +{ + ext->reg = extlist->reg; + ext->flags = FIELD_PREP(GUC_REGSET_STEERING_GROUP, slice_id); + ext->flags |= FIELD_PREP(GUC_REGSET_STEERING_INSTANCE, subslice_id); + ext->regname = extlist->name; +} + +static int +__alloc_ext_regs(struct __guc_mmio_reg_descr_group *newlist, + const struct __guc_mmio_reg_descr_group *rootlist, int num_regs) +{ + struct __guc_mmio_reg_descr *list; + + list = kcalloc(num_regs, sizeof(struct __guc_mmio_reg_descr), GFP_KERNEL); + if (!list) + return -ENOMEM; + + newlist->extlist = list; + newlist->num_regs = num_regs; + newlist->owner = rootlist->owner; + newlist->engine = rootlist->engine; + newlist->type = rootlist->type; + + return 0; +} + +static void +guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc, + const struct __guc_mmio_reg_descr_group *lists) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int slice, subslice, i, num_steer_regs, num_tot_regs = 0; + const struct __guc_mmio_reg_descr_group *list; + struct __guc_mmio_reg_descr_group *extlists; + struct __guc_mmio_reg_descr *extarray; + struct sseu_dev_info *sseu; + + /* In XE_LPD we only have steered registers for the render-class */ + list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS); + /* skip if extlists was previously allocated */ + if (!list || guc->capture->extlists) + return; + + num_steer_regs = ARRAY_SIZE(xe_extregs); + + sseu = >->info.sseu; + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) + num_tot_regs += num_steer_regs; + + if (!num_tot_regs) + return; + + /* allocate an extra for an end marker */ + extlists = kcalloc(2, sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL); + if (!extlists) + return; + + if (__alloc_ext_regs(&extlists[0], list, num_tot_regs)) { + kfree(extlists); + return; + } + + extarray = extlists[0].extlist; + for_each_instdone_slice_subslice(i915, sseu, slice, subslice) { + for (i = 0; i < num_steer_regs; ++i) { + __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice); + ++extarray; + } + } + + guc->capture->extlists = extlists; +} + +static const struct __guc_mmio_reg_descr_group * +guc_capture_get_device_reglist(struct intel_guc *guc) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + + if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) || + IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) { + /* + * For certain engine classes, there are slice and subslice + * level registers requiring steering. We allocate and populate + * these at init time based on hw config add it as an extension + * list at the end of the pre-populated render list. + */ + guc_capture_alloc_steered_lists_xe_lpd(guc, xe_lpd_lists); + return xe_lpd_lists; + } + + drm_warn(&i915->drm, "No GuC-capture register lists\n"); + + return NULL; +} + static const char * __stringify_owner(u32 owner) { @@ -250,10 +377,12 @@ static int guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, struct guc_mmio_reg *ptr, u16 num_entries) { - u32 i = 0; + u32 i = 0, j = 0; struct drm_i915_private *i915 = guc_to_gt(guc)->i915; const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists; + struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists; const struct __guc_mmio_reg_descr_group *match; + struct __guc_mmio_reg_descr_group *matchext; if (!reglists) return -ENODEV; @@ -272,6 +401,17 @@ guc_capture_list_init(struct intel_guc *guc, u32 owner, u32 type, u32 classid, ptr[i].mask = match->list[i].mask; } + matchext = guc_capture_get_one_ext_list(extlists, owner, type, classid); + if (matchext) { + for (i = match->num_regs, j = 0; i < num_entries && + i < (match->num_regs + matchext->num_regs) && + j < matchext->num_regs; ++i, ++j) { + ptr[i].offset = matchext->extlist[j].reg.reg; + ptr[i].value = 0xDEADF00D; + ptr[i].flags = matchext->extlist[j].flags; + ptr[i].mask = matchext->extlist[j].mask; + } + } if (i < num_entries) drm_dbg(&i915->drm, "GuC-capture: Init reglist short %d out %d.\n", (int)i, (int)num_entries); @@ -283,12 +423,20 @@ static int guc_cap_list_num_regs(struct intel_guc_state_capture *gc, u32 owner, u32 type, u32 classid) { const struct __guc_mmio_reg_descr_group *match; + struct __guc_mmio_reg_descr_group *matchext; + int num_regs; match = guc_capture_get_one_list(gc->reglists, owner, type, classid); if (!match) return 0; - return match->num_regs; + num_regs = match->num_regs; + + matchext = guc_capture_get_one_ext_list(gc->extlists, owner, type, classid); + if (matchext) + num_regs += matchext->num_regs; + + return num_regs; } int @@ -432,6 +580,12 @@ void intel_guc_capture_destroy(struct intel_guc *guc) kfree(guc->capture); guc->capture = NULL; + + guc_capture_free_extlists(guc->capture->extlists); + kfree(guc->capture->extlists); + + kfree(guc->capture); + guc->capture = NULL; } int intel_guc_capture_init(struct intel_guc *guc) From 33a220f6fcfc7fd9819f96aac69356593a63b10f Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:18 -0700 Subject: [PATCH 00309/11454] drm/i915/guc: Add DG2 registers for GuC error state capture. Add additional DG2 registers for GuC error state capture. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-5-alan.previn.teres.alexis@intel.com --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 80 ++++++++++++++++++- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 45ed09f3453d..7c3d9943ecdd 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -285,20 +285,94 @@ guc_capture_alloc_steered_lists_xe_lpd(struct intel_guc *guc, guc->capture->extlists = extlists; } +static const struct __ext_steer_reg xehpg_extregs[] = { + {"XEHPG_INSTDONE_GEOM_SVG", XEHPG_INSTDONE_GEOM_SVG} +}; + +static bool __has_xehpg_extregs(u32 ipver) +{ + return (ipver >= IP_VER(12, 55)); +} + +static void +guc_capture_alloc_steered_lists_xe_hpg(struct intel_guc *guc, + const struct __guc_mmio_reg_descr_group *lists, + u32 ipver) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct sseu_dev_info *sseu; + int slice, subslice, i, iter, num_steer_regs, num_tot_regs = 0; + const struct __guc_mmio_reg_descr_group *list; + struct __guc_mmio_reg_descr_group *extlists; + struct __guc_mmio_reg_descr *extarray; + + /* In XE_LP / HPG we only have render-class steering registers during error-capture */ + list = guc_capture_get_one_list(lists, GUC_CAPTURE_LIST_INDEX_PF, + GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, GUC_RENDER_CLASS); + /* skip if extlists was previously allocated */ + if (!list || guc->capture->extlists) + return; + + num_steer_regs = ARRAY_SIZE(xe_extregs); + if (__has_xehpg_extregs(ipver)) + num_steer_regs += ARRAY_SIZE(xehpg_extregs); + + sseu = >->info.sseu; + for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) { + num_tot_regs += num_steer_regs; + } + + if (!num_tot_regs) + return; + + /* allocate an extra for an end marker */ + extlists = kcalloc(2, sizeof(struct __guc_mmio_reg_descr_group), GFP_KERNEL); + if (!extlists) + return; + + if (__alloc_ext_regs(&extlists[0], list, num_tot_regs)) { + kfree(extlists); + return; + } + + extarray = extlists[0].extlist; + for_each_instdone_gslice_dss_xehp(i915, sseu, iter, slice, subslice) { + for (i = 0; i < ARRAY_SIZE(xe_extregs); ++i) { + __fill_ext_reg(extarray, &xe_extregs[i], slice, subslice); + ++extarray; + } + if (__has_xehpg_extregs(ipver)) { + for (i = 0; i < ARRAY_SIZE(xehpg_extregs); ++i) { + __fill_ext_reg(extarray, &xehpg_extregs[i], slice, subslice); + ++extarray; + } + } + } + + drm_dbg(&i915->drm, "GuC-capture found %d-ext-regs.\n", num_tot_regs); + guc->capture->extlists = extlists; +} + static const struct __guc_mmio_reg_descr_group * guc_capture_get_device_reglist(struct intel_guc *guc) { struct drm_i915_private *i915 = guc_to_gt(guc)->i915; - if (IS_TIGERLAKE(i915) || IS_ROCKETLAKE(i915) || - IS_ALDERLAKE_S(i915) || IS_ALDERLAKE_P(i915)) { + if (GRAPHICS_VER(i915) > 11) { /* * For certain engine classes, there are slice and subslice * level registers requiring steering. We allocate and populate * these at init time based on hw config add it as an extension * list at the end of the pre-populated render list. */ - guc_capture_alloc_steered_lists_xe_lpd(guc, xe_lpd_lists); + if (IS_DG2(i915)) + guc_capture_alloc_steered_lists_xe_hpg(guc, xe_lpd_lists, IP_VER(12, 55)); + else if (IS_XEHPSDV(i915)) + guc_capture_alloc_steered_lists_xe_hpg(guc, xe_lpd_lists, IP_VER(12, 50)); + else + guc_capture_alloc_steered_lists_xe_lpd(guc, xe_lpd_lists); + return xe_lpd_lists; } From dce2bd5423374973f2a66d6e00e932eb0a5d32d6 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:19 -0700 Subject: [PATCH 00310/11454] drm/i915/guc: Add Gen9 registers for GuC error state capture. Abstract out a Gen9 register list as the default for all other platforms we don't yet formally support GuC submission on. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-6-alan.previn.teres.alexis@intel.com --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 82 +++++++++++++------ 1 file changed, 59 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 7c3d9943ecdd..63ef407a2fd0 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -22,15 +22,24 @@ * NOTE: For engine-registers, GuC only needs the register offsets * from the engine-mmio-base */ +#define COMMON_BASE_GLOBAL \ + { FORCEWAKE_MT, 0, 0, "FORCEWAKE" } + +#define COMMON_GEN9BASE_GLOBAL \ + { GEN8_FAULT_TLB_DATA0, 0, 0, "GEN8_FAULT_TLB_DATA0" }, \ + { GEN8_FAULT_TLB_DATA1, 0, 0, "GEN8_FAULT_TLB_DATA1" }, \ + { ERROR_GEN6, 0, 0, "ERROR_GEN6" }, \ + { DONE_REG, 0, 0, "DONE_REG" }, \ + { HSW_GTT_CACHE_EN, 0, 0, "HSW_GTT_CACHE_EN" } + #define COMMON_GEN12BASE_GLOBAL \ { GEN12_FAULT_TLB_DATA0, 0, 0, "GEN12_FAULT_TLB_DATA0" }, \ { GEN12_FAULT_TLB_DATA1, 0, 0, "GEN12_FAULT_TLB_DATA1" }, \ - { FORCEWAKE_MT, 0, 0, "FORCEWAKE" }, \ { GEN12_AUX_ERR_DBG, 0, 0, "AUX_ERR_DBG" }, \ { GEN12_GAM_DONE, 0, 0, "GAM_DONE" }, \ { GEN12_RING_FAULT_REG, 0, 0, "FAULT_REG" } -#define COMMON_GEN12BASE_ENGINE_INSTANCE \ +#define COMMON_BASE_ENGINE_INSTANCE \ { RING_PSMI_CTL(0), 0, 0, "RC PSMI" }, \ { RING_ESR(0), 0, 0, "ESR" }, \ { RING_DMA_FADD(0), 0, 0, "RING_DMA_FADD_LDW" }, \ @@ -64,11 +73,13 @@ { GEN8_RING_PDP_LDW(0, 3), 0, 0, "PDP3_LDW" }, \ { GEN8_RING_PDP_UDW(0, 3), 0, 0, "PDP3_UDW" } -#define COMMON_GEN12BASE_HAS_EU \ +#define COMMON_BASE_HAS_EU \ { EIR, 0, 0, "EIR" } +#define COMMON_BASE_RENDER \ + { GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE" } + #define COMMON_GEN12BASE_RENDER \ - { GEN7_SC_INSTDONE, 0, 0, "GEN7_SC_INSTDONE" }, \ { GEN12_SC_INSTDONE_EXTRA, 0, 0, "GEN12_SC_INSTDONE_EXTRA" }, \ { GEN12_SC_INSTDONE_EXTRA2, 0, 0, "GEN12_SC_INSTDONE_EXTRA2" } @@ -80,28 +91,26 @@ /* XE_LPD - Global */ static const struct __guc_mmio_reg_descr xe_lpd_global_regs[] = { + COMMON_BASE_GLOBAL, + COMMON_GEN9BASE_GLOBAL, COMMON_GEN12BASE_GLOBAL, }; /* XE_LPD - Render / Compute Per-Class */ static const struct __guc_mmio_reg_descr xe_lpd_rc_class_regs[] = { - COMMON_GEN12BASE_HAS_EU, + COMMON_BASE_HAS_EU, + COMMON_BASE_RENDER, COMMON_GEN12BASE_RENDER, }; -/* XE_LPD - Render / Compute Per-Engine-Instance */ +/* GEN9/XE_LPD - Render / Compute Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_rc_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE, + COMMON_BASE_ENGINE_INSTANCE, }; -/* XE_LPD - Media Decode/Encode Per-Class */ -static const struct __guc_mmio_reg_descr xe_lpd_vd_class_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE, -}; - -/* XE_LPD - Media Decode/Encode Per-Engine-Instance */ +/* GEN9/XE_LPD - Media Decode/Encode Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_vd_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE, + COMMON_BASE_ENGINE_INSTANCE, }; /* XE_LPD - Video Enhancement Per-Class */ @@ -109,18 +118,33 @@ static const struct __guc_mmio_reg_descr xe_lpd_vec_class_regs[] = { COMMON_GEN12BASE_VEC, }; -/* XE_LPD - Video Enhancement Per-Engine-Instance */ +/* GEN9/XE_LPD - Video Enhancement Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_vec_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE, + COMMON_BASE_ENGINE_INSTANCE, }; -/* XE_LPD - Blitter Per-Engine-Instance */ +/* GEN9/XE_LPD - Blitter Per-Engine-Instance */ static const struct __guc_mmio_reg_descr xe_lpd_blt_inst_regs[] = { - COMMON_GEN12BASE_ENGINE_INSTANCE, + COMMON_BASE_ENGINE_INSTANCE, }; -/* XE_LPD - Blitter Per-Class */ -/* XE_LPD - Media Decode/Encode Per-Class */ +/* GEN9 - Global */ +static const struct __guc_mmio_reg_descr default_global_regs[] = { + COMMON_BASE_GLOBAL, + COMMON_GEN9BASE_GLOBAL, +}; + +static const struct __guc_mmio_reg_descr default_rc_class_regs[] = { + COMMON_BASE_HAS_EU, + COMMON_BASE_RENDER, +}; + +/* + * Empty lists: + * GEN9/XE_LPD - Blitter Per-Class + * GEN9/XE_LPD - Media Decode/Encode Per-Class + * GEN9 - VEC Class + */ static const struct __guc_mmio_reg_descr empty_regs_list[] = { }; @@ -137,6 +161,19 @@ static const struct __guc_mmio_reg_descr empty_regs_list[] = { } /* List of lists */ +static struct __guc_mmio_reg_descr_group default_lists[] = { + MAKE_REGLIST(default_global_regs, PF, GLOBAL, 0), + MAKE_REGLIST(default_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), + MAKE_REGLIST(xe_lpd_rc_inst_regs, PF, ENGINE_INSTANCE, GUC_RENDER_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEO_CLASS), + MAKE_REGLIST(xe_lpd_vd_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEO_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(xe_lpd_vec_inst_regs, PF, ENGINE_INSTANCE, GUC_VIDEOENHANCE_CLASS), + MAKE_REGLIST(empty_regs_list, PF, ENGINE_CLASS, GUC_BLITTER_CLASS), + MAKE_REGLIST(xe_lpd_blt_inst_regs, PF, ENGINE_INSTANCE, GUC_BLITTER_CLASS), + {} +}; + static const struct __guc_mmio_reg_descr_group xe_lpd_lists[] = { MAKE_REGLIST(xe_lpd_global_regs, PF, GLOBAL, 0), MAKE_REGLIST(xe_lpd_rc_class_regs, PF, ENGINE_CLASS, GUC_RENDER_CLASS), @@ -376,9 +413,8 @@ guc_capture_get_device_reglist(struct intel_guc *guc) return xe_lpd_lists; } - drm_warn(&i915->drm, "No GuC-capture register lists\n"); - - return NULL; + /* if GuC submission is enabled on a non-POR platform, just use a common baseline */ + return default_lists; } static const char * From bd1a78b04b68fb8cba94309f6d426dfc50eba873 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:20 -0700 Subject: [PATCH 00311/11454] drm/i915/guc: Add GuC's error state capture output structures. Add GuC's error capture output structures and definitions as how they would appear in GuC log buffer's error capture subregion after an error state capture G2H event notification. Signed-off-by: Alan Previn Reviewed-by: Matthew Brost Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-7-alan.previn.teres.alexis@intel.com --- drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 6c199433945d..8824c5eba355 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -55,6 +55,53 @@ struct __guc_mmio_reg_descr_group { struct __guc_mmio_reg_descr *extlist; /* only used for steered registers */ }; +/** + * struct guc_state_capture_header_t / struct guc_state_capture_t / + * guc_state_capture_group_header_t / guc_state_capture_group_t + * + * Prior to resetting engines that have hung or faulted, GuC microkernel + * reports the engine error-state (register values that was read) by + * logging them into the shared GuC log buffer using these hierarchy + * of structures. + */ +struct guc_state_capture_header_t { + u32 owner; +#define CAP_HDR_CAPTURE_VFID GENMASK(7, 0) + u32 info; +#define CAP_HDR_CAPTURE_TYPE GENMASK(3, 0) /* see enum guc_capture_type */ +#define CAP_HDR_ENGINE_CLASS GENMASK(7, 4) /* see GUC_MAX_ENGINE_CLASSES */ +#define CAP_HDR_ENGINE_INSTANCE GENMASK(11, 8) + u32 lrca; /* if type-instance, LRCA (address) that hung, else set to ~0 */ + u32 guc_id; /* if type-instance, context index of hung context, else set to ~0 */ + u32 num_mmios; +#define CAP_HDR_NUM_MMIOS GENMASK(9, 0) +} __packed; + +struct guc_state_capture_t { + struct guc_state_capture_header_t header; + struct guc_mmio_reg mmio_entries[0]; +} __packed; + +enum guc_capture_group_types { + GUC_STATE_CAPTURE_GROUP_TYPE_FULL, + GUC_STATE_CAPTURE_GROUP_TYPE_PARTIAL, + GUC_STATE_CAPTURE_GROUP_TYPE_MAX, +}; + +struct guc_state_capture_group_header_t { + u32 owner; +#define CAP_GRP_HDR_CAPTURE_VFID GENMASK(7, 0) + u32 info; +#define CAP_GRP_HDR_NUM_CAPTURES GENMASK(7, 0) +#define CAP_GRP_HDR_CAPTURE_TYPE GENMASK(15, 8) /* guc_capture_group_types */ +} __packed; + +/* this is the top level structure where an error-capture dump starts */ +struct guc_state_capture_group_t { + struct guc_state_capture_group_header_t grp_header; + struct guc_state_capture_t capture_entries[0]; +} __packed; + /** * struct __guc_capture_ads_cache * From 580329a3a4a2ffb5168b43e7a1fc1610e6bcae98 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:21 -0700 Subject: [PATCH 00312/11454] drm/i915/guc: Update GuC-log relay function names For the sake of better code readibility, change previous relay logging function names with "capture_logs" to "copy_debug_logs" to differentiate from error capture functions that will use a different region of the same buffer. Signed-off-by: Alan Previn Reviewed-by: Matthew Brost Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-8-alan.previn.teres.alexis@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 35 ++++++++++++---------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index b53f61f3101f..bf3abb7e69b0 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -11,7 +11,7 @@ #include "i915_memcpy.h" #include "intel_guc_log.h" -static void guc_log_capture_logs(struct intel_guc_log *log); +static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); /** * DOC: GuC firmware log @@ -197,7 +197,7 @@ static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) return 0; } -static void guc_read_update_log_buffer(struct intel_guc_log *log) +static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; struct guc_log_buffer_state *log_buf_state, *log_buf_snapshot_state; @@ -222,7 +222,7 @@ static void guc_read_update_log_buffer(struct intel_guc_log *log) * Used rate limited to avoid deluge of messages, logs might be * getting consumed by User at a slow rate. */ - DRM_ERROR_RATELIMITED("no sub-buffer to capture logs\n"); + DRM_ERROR_RATELIMITED("no sub-buffer to copy general logs\n"); log->relay.full_count++; goto out_unlock; @@ -300,15 +300,15 @@ out_unlock: mutex_unlock(&log->relay.lock); } -static void capture_logs_work(struct work_struct *work) +static void copy_debug_logs_work(struct work_struct *work) { struct intel_guc_log *log = container_of(work, struct intel_guc_log, relay.flush_work); - guc_log_capture_logs(log); + guc_log_copy_debuglogs_for_relay(log); } -static int guc_log_map(struct intel_guc_log *log) +static int guc_log_relay_map(struct intel_guc_log *log) { void *vaddr; @@ -331,7 +331,7 @@ static int guc_log_map(struct intel_guc_log *log) return 0; } -static void guc_log_unmap(struct intel_guc_log *log) +static void guc_log_relay_unmap(struct intel_guc_log *log) { lockdep_assert_held(&log->relay.lock); @@ -342,7 +342,7 @@ static void guc_log_unmap(struct intel_guc_log *log) void intel_guc_log_init_early(struct intel_guc_log *log) { mutex_init(&log->relay.lock); - INIT_WORK(&log->relay.flush_work, capture_logs_work); + INIT_WORK(&log->relay.flush_work, copy_debug_logs_work); log->relay.started = false; } @@ -357,8 +357,11 @@ static int guc_log_relay_create(struct intel_guc_log *log) lockdep_assert_held(&log->relay.lock); GEM_BUG_ON(!log->vma); - /* Keep the size of sub buffers same as shared log buffer */ - subbuf_size = log->vma->size; + /* + * Keep the size of sub buffers same as shared log buffer + * but GuC log-events excludes the error-state-capture logs + */ + subbuf_size = log->vma->size - CAPTURE_BUFFER_SIZE; /* * Store up to 8 snapshots, which is large enough to buffer sufficient @@ -393,13 +396,13 @@ static void guc_log_relay_destroy(struct intel_guc_log *log) log->relay.channel = NULL; } -static void guc_log_capture_logs(struct intel_guc_log *log) +static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { struct intel_guc *guc = log_to_guc(log); struct drm_i915_private *dev_priv = guc_to_gt(guc)->i915; intel_wakeref_t wakeref; - guc_read_update_log_buffer(log); + _guc_log_copy_debuglogs_for_relay(log); /* * Generally device is expected to be active only at this @@ -565,7 +568,7 @@ int intel_guc_log_relay_open(struct intel_guc_log *log) if (ret) goto out_unlock; - ret = guc_log_map(log); + ret = guc_log_relay_map(log); if (ret) goto out_relay; @@ -615,8 +618,8 @@ void intel_guc_log_relay_flush(struct intel_guc_log *log) with_intel_runtime_pm(guc_to_gt(guc)->uncore->rpm, wakeref) guc_action_flush_log(guc); - /* GuC would have updated log buffer by now, so capture it */ - guc_log_capture_logs(log); + /* GuC would have updated log buffer by now, so copy it */ + guc_log_copy_debuglogs_for_relay(log); } /* @@ -645,7 +648,7 @@ void intel_guc_log_relay_close(struct intel_guc_log *log) mutex_lock(&log->relay.lock); GEM_BUG_ON(!intel_guc_log_relay_created(log)); - guc_log_unmap(log); + guc_log_relay_unmap(log); guc_log_relay_destroy(log); mutex_unlock(&log->relay.lock); } From daff407a083da2a50bc5a46c07756a9ccd7842df Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:22 -0700 Subject: [PATCH 00313/11454] drm/i915/guc: Add capture region into intel_guc_log GuC log buffer regions for debug-log-events, crash-dumps and error-state-capture are all part of a single bo allocation that also includes the guc_log_buffer_state structures. Now that we support it, increase the size allocation for error-capture. Since the error-capture region is accessed at non-deterministic times (as part of GuC triggered context reset) while debug-log- events region is accessed as part of relay logging or during debugfs triggered dumps, move the mapping and unmapping of the shared buffer into intel_guc_log_create and intel_guc_log_destroy so that it's always mapped throughout life of GuC operation. Additionally, while here, update the guc log region layout diagram to follow the order according to the enum definition as per the GuC interface. NOTE: A future effort to visit (part of baseline code) is that buf_addr should be updated to be a io_sys_map and use the io_sys_map wrapper functions to access the various GuC log buffer regions. Signed-off-by: Alan Previn Reviewed-by: Matthew Brost Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-9-alan.previn.teres.alexis@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 59 +++++++++++++--------- drivers/gpu/drm/i915/gt/uc/intel_guc_log.h | 3 +- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index bf3abb7e69b0..38968fdbbb6f 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -25,7 +25,8 @@ static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); static int guc_action_flush_log_complete(struct intel_guc *guc) { u32 action[] = { - INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE + INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE, + GUC_DEBUG_LOG_BUFFER }; return intel_guc_send(guc, action, ARRAY_SIZE(action)); @@ -136,7 +137,7 @@ static void guc_move_to_next_buf(struct intel_guc_log *log) smp_wmb(); /* All data has been written, so now move the offset of sub buffer. */ - relay_reserve(log->relay.channel, log->vma->obj->base.size); + relay_reserve(log->relay.channel, log->vma->obj->base.size - CAPTURE_BUFFER_SIZE); /* Switch to the next sub buffer */ relay_flush(log->relay.channel); @@ -212,7 +213,8 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) goto out_unlock; /* Get the pointer to shared GuC log buffer */ - log_buf_state = src_data = log->relay.buf_addr; + src_data = log->buf_addr; + log_buf_state = src_data; /* Get the pointer to local buffer to store the logs */ log_buf_snapshot_state = dst_data = guc_get_write_buffer(log); @@ -232,7 +234,8 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) src_data += PAGE_SIZE; dst_data += PAGE_SIZE; - for (type = GUC_DEBUG_LOG_BUFFER; type < GUC_MAX_LOG_BUFFER; type++) { + /* For relay logging, we exclude error state capture */ + for (type = GUC_DEBUG_LOG_BUFFER; type <= GUC_CRASH_DUMP_LOG_BUFFER; type++) { /* * Make a copy of the state structure, inside GuC log buffer * (which is uncached mapped), on the stack to avoid reading @@ -310,23 +313,17 @@ static void copy_debug_logs_work(struct work_struct *work) static int guc_log_relay_map(struct intel_guc_log *log) { - void *vaddr; - lockdep_assert_held(&log->relay.lock); - if (!log->vma) + if (!log->vma || !log->buf_addr) return -ENODEV; /* - * Create a WC (Uncached for read) vmalloc mapping of log - * buffer pages, so that we can directly get the data - * (up-to-date) from memory. + * WC vmalloc mapping of log buffer pages was done at + * GuC Log Init time, but lets keep a ref for book-keeping */ - vaddr = i915_gem_object_pin_map_unlocked(log->vma->obj, I915_MAP_WC); - if (IS_ERR(vaddr)) - return PTR_ERR(vaddr); - - log->relay.buf_addr = vaddr; + i915_gem_object_get(log->vma->obj); + log->relay.buf_in_use = true; return 0; } @@ -335,8 +332,8 @@ static void guc_log_relay_unmap(struct intel_guc_log *log) { lockdep_assert_held(&log->relay.lock); - i915_gem_object_unpin_map(log->vma->obj); - log->relay.buf_addr = NULL; + i915_gem_object_put(log->vma->obj); + log->relay.buf_in_use = false; } void intel_guc_log_init_early(struct intel_guc_log *log) @@ -442,6 +439,7 @@ int intel_guc_log_create(struct intel_guc_log *log) { struct intel_guc *guc = log_to_guc(log); struct i915_vma *vma; + void *vaddr; u32 guc_log_size; int ret; @@ -449,20 +447,21 @@ int intel_guc_log_create(struct intel_guc_log *log) /* * GuC Log buffer Layout + * (this ordering must follow "enum guc_log_buffer_type" definition) * * +===============================+ 00B - * | Crash dump state header | - * +-------------------------------+ 32B * | Debug state header | + * +-------------------------------+ 32B + * | Crash dump state header | * +-------------------------------+ 64B * | Capture state header | * +-------------------------------+ 96B * | | * +===============================+ PAGE_SIZE (4KB) - * | Crash Dump logs | - * +===============================+ + CRASH_SIZE * | Debug logs | * +===============================+ + DEBUG_SIZE + * | Crash Dump logs | + * +===============================+ + CRASH_SIZE * | Capture logs | * +===============================+ + CAPTURE_SIZE */ @@ -476,6 +475,17 @@ int intel_guc_log_create(struct intel_guc_log *log) } log->vma = vma; + /* + * Create a WC (Uncached for read) vmalloc mapping up front immediate access to + * data from memory during critical events such as error capture + */ + vaddr = i915_gem_object_pin_map_unlocked(log->vma->obj, I915_MAP_WC); + if (IS_ERR(vaddr)) { + ret = PTR_ERR(vaddr); + i915_vma_unpin_and_release(&log->vma, 0); + goto err; + } + log->buf_addr = vaddr; log->level = __get_default_log_level(log); DRM_DEBUG_DRIVER("guc_log_level=%d (%s, verbose:%s, verbosity:%d)\n", @@ -486,13 +496,14 @@ int intel_guc_log_create(struct intel_guc_log *log) return 0; err: - DRM_ERROR("Failed to allocate GuC log buffer. %d\n", ret); + DRM_ERROR("Failed to allocate or map GuC log buffer. %d\n", ret); return ret; } void intel_guc_log_destroy(struct intel_guc_log *log) { - i915_vma_unpin_and_release(&log->vma, 0); + log->buf_addr = NULL; + i915_vma_unpin_and_release(&log->vma, I915_VMA_RELEASE_MAP); } int intel_guc_log_set_level(struct intel_guc_log *log, u32 level) @@ -537,7 +548,7 @@ out_unlock: bool intel_guc_log_relay_created(const struct intel_guc_log *log) { - return log->relay.buf_addr; + return log->buf_addr; } int intel_guc_log_relay_open(struct intel_guc_log *log) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h index d7e1b6471fed..e1345fca7729 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h @@ -49,8 +49,9 @@ struct intel_guc; struct intel_guc_log { u32 level; struct i915_vma *vma; + void *buf_addr; struct { - void *buf_addr; + bool buf_in_use; bool started; struct work_struct flush_work; struct rchan *channel; From d7c15d76a5547eec420aa9b2940c3e5e7cb77a5a Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:23 -0700 Subject: [PATCH 00314/11454] drm/i915/guc: Check sizing of guc_capture output Add intel_guc_capture_output_min_size_est function to provide a reasonable minimum size for error-capture region before allocating the shared buffer. Signed-off-by: Alan Previn Reviewed-by: Matthew Brost Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-10-alan.previn.teres.alexis@intel.com --- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 49 +++++++++++++++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 5 ++ 3 files changed, 55 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 63ef407a2fd0..ff862a704529 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -663,6 +663,55 @@ intel_guc_capture_getnullheader(struct intel_guc *guc, return 0; } +#define GUC_CAPTURE_OVERBUFFER_MULTIPLIER 3 + +int +intel_guc_capture_output_min_size_est(struct intel_guc *guc) +{ + struct intel_gt *gt = guc_to_gt(guc); + struct intel_engine_cs *engine; + enum intel_engine_id id; + int worst_min_size = 0, num_regs = 0; + size_t tmp = 0; + + /* + * If every single engine-instance suffered a failure in quick succession but + * were all unrelated, then a burst of multiple error-capture events would dump + * registers for every one engine instance, one at a time. In this case, GuC + * would even dump the global-registers repeatedly. + * + * For each engine instance, there would be 1 x guc_state_capture_group_t output + * followed by 3 x guc_state_capture_t lists. The latter is how the register + * dumps are split across different register types (where the '3' are global vs class + * vs instance). Finally, let's multiply the whole thing by 3x (just so we are + * not limited to just 1 round of data in a worst case full register dump log) + * + * NOTE: intel_guc_log that allocates the log buffer would round this size up to + * a power of two. + */ + + for_each_engine(engine, gt, id) { + worst_min_size += sizeof(struct guc_state_capture_group_header_t) + + (3 * sizeof(struct guc_state_capture_header_t)); + + if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp)) + num_regs += tmp; + + if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS, + engine->class, &tmp)) { + num_regs += tmp; + } + if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE, + engine->class, &tmp)) { + num_regs += tmp; + } + } + + worst_min_size += (num_regs * sizeof(struct guc_mmio_reg)); + + return (worst_min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER); +} + static void guc_capture_free_ads_cache(struct intel_guc_state_capture *gc) { diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index 8de7704e12eb..540d72079462 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -11,6 +11,7 @@ struct guc_gt_system_info; struct intel_guc; +int intel_guc_capture_output_min_size_est(struct intel_guc *guc); int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, void **outptr); int intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 classid, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index 38968fdbbb6f..b58c7af62553 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -9,6 +9,7 @@ #include "i915_drv.h" #include "i915_irq.h" #include "i915_memcpy.h" +#include "intel_guc_capture.h" #include "intel_guc_log.h" static void guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log); @@ -465,6 +466,10 @@ int intel_guc_log_create(struct intel_guc_log *log) * | Capture logs | * +===============================+ + CAPTURE_SIZE */ + if (intel_guc_capture_output_min_size_est(guc) > CAPTURE_BUFFER_SIZE) + DRM_WARN("GuC log buffer for state_capture maybe too small. %d < %d\n", + CAPTURE_BUFFER_SIZE, intel_guc_capture_output_min_size_est(guc)); + guc_log_size = PAGE_SIZE + CRASH_BUFFER_SIZE + DEBUG_BUFFER_SIZE + CAPTURE_BUFFER_SIZE; From f5718a7265a6f562dc706e0b610f060ded4c3739 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:24 -0700 Subject: [PATCH 00315/11454] drm/i915/guc: Extract GuC error capture lists on G2H notification. - Upon the G2H Notify-Err-Capture event, parse through the GuC Log Buffer (error-capture-subregion) and generate one or more capture-nodes. A single node represents a single "engine- instance-capture-dump" and contains at least 3 register lists: global, engine-class and engine-instance. An internal link list is maintained to store one or more nodes. - Because the link-list node generation happen before the call to i915_gpu_codedump, duplicate global and engine-class register lists for each engine-instance register dump if we find dependent-engine resets in a engine-capture-group. - When i915_gpu_coredump calls into capture_engine, (in a subsequent patch) we detach the matching node (guc-id, LRCA, etc) from the link list above and attach it to i915_gpu_coredump's intel_engine_coredump structure when have matching LRCA/guc-id/engine-instance. Additional notes to be aware of: - GuC generates the error capture dump into the GuC log buffer but this buffer is one big log buffer with 3 independent subregions within it. Each subregion is populated with different content and used in different ways and timings but all regions operate behave as independent ring buffers. Each guc-log subregion (general-logs, crash-dump and error- capture) has it's own guc_log_buffer_state that contain independent read and write pointers. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-11-alan.previn.teres.alexis@intel.com --- .../gpu/drm/i915/gt/uc/abi/guc_actions_abi.h | 7 + drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 56 ++ .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 561 +++++++++++++++++- .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 1 + drivers/gpu/drm/i915/gt/uc/intel_guc_log.c | 26 +- drivers/gpu/drm/i915/gt/uc/intel_guc_log.h | 4 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 10 +- 7 files changed, 652 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h index f9b3dd146a7e..9ad6df1b6fbc 100644 --- a/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h +++ b/drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h @@ -172,4 +172,11 @@ enum intel_guc_sleep_state_status { #define GUC_LOG_CONTROL_VERBOSITY_MASK (0xF << GUC_LOG_CONTROL_VERBOSITY_SHIFT) #define GUC_LOG_CONTROL_DEFAULT_LOGGING (1 << 8) +enum intel_guc_state_capture_event_status { + INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_SUCCESS = 0x0, + INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE = 0x1, +}; + +#define INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK 0x000000FF + #endif /* _ABI_GUC_ACTIONS_ABI_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 8824c5eba355..5d959e62d146 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -12,6 +12,52 @@ struct intel_guc; struct file; +/** + * struct __guc_capture_bufstate + * + * Book-keeping structure used to track read and write pointers + * as we extract error capture data from the GuC-log-buffer's + * error-capture region as a stream of dwords. + */ +struct __guc_capture_bufstate { + u32 size; + void *data; + u32 rd; + u32 wr; +}; + +/** + * struct __guc_capture_parsed_output - extracted error capture node + * + * A single unit of extracted error-capture output data grouped together + * at an engine-instance level. We keep these nodes in a linked list. + * See outlist below. + */ +struct __guc_capture_parsed_output { + /* + * A single set of 3 capture lists: a global-list + * an engine-class-list and an engine-instance list. + * outlist in __guc_capture_parsed_output will keep + * a linked list of these nodes that will eventually + * be detached from outlist and attached into to + * i915_gpu_codedump in response to a context reset + */ + struct list_head link; + bool is_partial; + u32 eng_class; + u32 eng_inst; + u32 guc_id; + u32 lrca; + struct gcap_reg_list_info { + u32 vfid; + u32 num_regs; + struct guc_mmio_reg *regs; + } reginfo[GUC_CAPTURE_LIST_TYPE_MAX]; +#define GCAP_PARSED_REGLIST_INDEX_GLOBAL BIT(GUC_CAPTURE_LIST_TYPE_GLOBAL) +#define GCAP_PARSED_REGLIST_INDEX_ENGCLASS BIT(GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS) +#define GCAP_PARSED_REGLIST_INDEX_ENGINST BIT(GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) +}; + /** * struct guc_debug_capture_list_header / struct guc_debug_capture_list * @@ -142,6 +188,16 @@ struct intel_guc_state_capture { [GUC_CAPTURE_LIST_TYPE_MAX] [GUC_MAX_ENGINE_CLASSES]; void *ads_null_cache; + + /** + * @outlist: allocated nodes with parsed engine-instance error capture data + * + * A linked list of parsed GuC error-capture output data before + * reporting with formatting via i915_gpu_coredump. Each node in this linked list shall + * contain a single engine-capture including global, engine-class and + * engine-instance register dumps as per guc_capture_parsed_output_node + */ + struct list_head outlist; }; #endif /* _INTEL_GUC_CAPTURE_FWIF_H */ diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index ff862a704529..25a5f1013e43 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -14,6 +14,8 @@ #include "intel_guc_capture.h" #include "intel_guc_fwif.h" #include "i915_drv.h" +#include "i915_gpu_error.h" +#include "i915_irq.h" #include "i915_memcpy.h" #include "i915_reg.h" @@ -674,6 +676,9 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) int worst_min_size = 0, num_regs = 0; size_t tmp = 0; + if (!guc->capture) + return -ENODEV; + /* * If every single engine-instance suffered a failure in quick succession but * were all unrelated, then a burst of multiple error-capture events would dump @@ -692,7 +697,7 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) for_each_engine(engine, gt, id) { worst_min_size += sizeof(struct guc_state_capture_group_header_t) + - (3 * sizeof(struct guc_state_capture_header_t)); + (3 * sizeof(struct guc_state_capture_header_t)); if (!intel_guc_capture_getlistsize(guc, 0, GUC_CAPTURE_LIST_TYPE_GLOBAL, 0, &tmp)) num_regs += tmp; @@ -712,6 +717,555 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) return (worst_min_size * GUC_CAPTURE_OVERBUFFER_MULTIPLIER); } +/* + * KMD Init time flows: + * -------------------- + * --> alloc A: GuC input capture regs lists (registered to GuC via ADS). + * intel_guc_ads acquires the register lists by calling + * intel_guc_capture_list_size and intel_guc_capture_list_get 'n' times, + * where n = 1 for global-reg-list + + * num_engine_classes for class-reg-list + + * num_engine_classes for instance-reg-list + * (since all instances of the same engine-class type + * have an identical engine-instance register-list). + * ADS module also calls separately for PF vs VF. + * + * --> alloc B: GuC output capture buf (registered via guc_init_params(log_param)) + * Size = #define CAPTURE_BUFFER_SIZE (warns if on too-small) + * Note2: 'x 3' to hold multiple capture groups + * + * GUC Runtime notify capture: + * -------------------------- + * --> G2H STATE_CAPTURE_NOTIFICATION + * L--> intel_guc_capture_process + * L--> Loop through B (head..tail) and for each engine instance's + * err-state-captured register-list we find, we alloc 'C': + * --> alloc C: A capture-output-node structure that includes misc capture info along + * with 3 register list dumps (global, engine-class and engine-instance) + * This node is dynamically allocated and populated with the error-capture + * data from GuC and then it's added into guc->capture->outlist linked + * list. This list is used for matchup and printout by i915_gpu_coredump + * and err_print_gt, (when user invokes the error capture sysfs). + */ + +static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) +{ + if (buf->wr >= buf->rd) + return (buf->wr - buf->rd); + return (buf->size - buf->rd) + buf->wr; +} + +static int guc_capture_buf_cnt_to_end(struct __guc_capture_bufstate *buf) +{ + if (buf->rd > buf->wr) + return (buf->size - buf->rd); + return (buf->wr - buf->rd); +} + +/* + * GuC's error-capture output is a ring buffer populated in a byte-stream fashion: + * + * The GuC Log buffer region for error-capture is managed like a ring buffer. + * The GuC firmware dumps error capture logs into this ring in a byte-stream flow. + * Additionally, as per the current and foreseeable future, all packed error- + * capture output structures are dword aligned. + * + * That said, if the GuC firmware is in the midst of writing a structure that is larger + * than one dword but the tail end of the err-capture buffer-region has lesser space left, + * we would need to extract that structure one dword at a time straddled across the end, + * onto the start of the ring. + * + * Below function, guc_capture_log_remove_dw is a helper for that. All callers of this + * function would typically do a straight-up memcpy from the ring contents and will only + * call this helper if their structure-extraction is straddling across the end of the + * ring. GuC firmware does not add any padding. The reason for the no-padding is to ease + * scalability for future expansion of output data types without requiring a redesign + * of the flow controls. + */ +static int +guc_capture_log_remove_dw(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + u32 *dw) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int tries = 2; + int avail = 0; + u32 *src_data; + + if (!guc_capture_buf_cnt(buf)) + return 0; + + while (tries--) { + avail = guc_capture_buf_cnt_to_end(buf); + if (avail >= sizeof(u32)) { + src_data = (u32 *)(buf->data + buf->rd); + *dw = *src_data; + buf->rd += 4; + return 4; + } + if (avail) + drm_dbg(&i915->drm, "GuC-Cap-Logs not dword aligned, skipping.\n"); + buf->rd = 0; + } + + return 0; +} + +static bool +guc_capture_data_extracted(struct __guc_capture_bufstate *b, + int size, void *dest) +{ + if (guc_capture_buf_cnt_to_end(b) >= size) { + memcpy(dest, (b->data + b->rd), size); + b->rd += size; + return true; + } + return false; +} + +static int +guc_capture_log_get_group_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + struct guc_state_capture_group_header_t *ghdr) +{ + int read = 0; + int fullsize = sizeof(struct guc_state_capture_group_header_t); + + if (fullsize > guc_capture_buf_cnt(buf)) + return -1; + + if (guc_capture_data_extracted(buf, fullsize, (void *)ghdr)) + return 0; + + read += guc_capture_log_remove_dw(guc, buf, &ghdr->owner); + read += guc_capture_log_remove_dw(guc, buf, &ghdr->info); + if (read != fullsize) + return -1; + + return 0; +} + +static int +guc_capture_log_get_data_hdr(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + struct guc_state_capture_header_t *hdr) +{ + int read = 0; + int fullsize = sizeof(struct guc_state_capture_header_t); + + if (fullsize > guc_capture_buf_cnt(buf)) + return -1; + + if (guc_capture_data_extracted(buf, fullsize, (void *)hdr)) + return 0; + + read += guc_capture_log_remove_dw(guc, buf, &hdr->owner); + read += guc_capture_log_remove_dw(guc, buf, &hdr->info); + read += guc_capture_log_remove_dw(guc, buf, &hdr->lrca); + read += guc_capture_log_remove_dw(guc, buf, &hdr->guc_id); + read += guc_capture_log_remove_dw(guc, buf, &hdr->num_mmios); + if (read != fullsize) + return -1; + + return 0; +} + +static int +guc_capture_log_get_register(struct intel_guc *guc, struct __guc_capture_bufstate *buf, + struct guc_mmio_reg *reg) +{ + int read = 0; + int fullsize = sizeof(struct guc_mmio_reg); + + if (fullsize > guc_capture_buf_cnt(buf)) + return -1; + + if (guc_capture_data_extracted(buf, fullsize, (void *)reg)) + return 0; + + read += guc_capture_log_remove_dw(guc, buf, ®->offset); + read += guc_capture_log_remove_dw(guc, buf, ®->value); + read += guc_capture_log_remove_dw(guc, buf, ®->flags); + read += guc_capture_log_remove_dw(guc, buf, ®->mask); + if (read != fullsize) + return -1; + + return 0; +} + +static void +guc_capture_delete_one_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node) +{ + int i; + + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) + kfree(node->reginfo[i].regs); + list_del(&node->link); + kfree(node); +} + +static void +guc_capture_delete_nodes(struct intel_guc *guc) +{ + /* + * NOTE: At the end of driver operation, we must assume that we + * have nodes in outlist from unclaimed error capture events + * that occurred prior to shutdown. + */ + if (!list_empty(&guc->capture->outlist)) { + struct __guc_capture_parsed_output *n, *ntmp; + + list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) + guc_capture_delete_one_node(guc, n); + } +} + +static void +guc_capture_add_node_to_list(struct __guc_capture_parsed_output *node, + struct list_head *list) +{ + list_add_tail(&node->link, list); +} + +static void +guc_capture_add_node_to_outlist(struct intel_guc_state_capture *gc, + struct __guc_capture_parsed_output *node) +{ + guc_capture_add_node_to_list(node, &gc->outlist); +} + +static void +guc_capture_init_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node) +{ + INIT_LIST_HEAD(&node->link); +} + +static struct __guc_capture_parsed_output * +guc_capture_alloc_one_node(struct intel_guc *guc) +{ + struct __guc_capture_parsed_output *new; + + new = kzalloc(sizeof(*new), GFP_KERNEL); + if (!new) + return NULL; + + guc_capture_init_node(guc, new); + + return new; +} + +static struct __guc_capture_parsed_output * +guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output *original, + u32 keep_reglist_mask) +{ + struct __guc_capture_parsed_output *new; + int i; + + new = guc_capture_alloc_one_node(guc); + if (!new) + return NULL; + if (!original) + return new; + + new->is_partial = original->is_partial; + + /* copy reg-lists that we want to clone */ + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (keep_reglist_mask & BIT(i)) { + new->reginfo[i].regs = kcalloc(original->reginfo[i].num_regs, + sizeof(struct guc_mmio_reg), GFP_KERNEL); + if (!new->reginfo[i].regs) + goto bail_clone; + + memcpy(new->reginfo[i].regs, original->reginfo[i].regs, + original->reginfo[i].num_regs * sizeof(struct guc_mmio_reg)); + new->reginfo[i].num_regs = original->reginfo[i].num_regs; + new->reginfo[i].vfid = original->reginfo[i].vfid; + + if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS) { + new->eng_class = original->eng_class; + } else if (i == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) { + new->eng_inst = original->eng_inst; + new->guc_id = original->guc_id; + new->lrca = original->lrca; + } + } + } + + return new; + +bail_clone: + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) + kfree(new->reginfo[i].regs); + kfree(new); + return NULL; +} + +static int +guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstate *buf) +{ + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct guc_state_capture_group_header_t ghdr = {0}; + struct guc_state_capture_header_t hdr = {0}; + struct __guc_capture_parsed_output *node = NULL; + struct guc_mmio_reg *regs = NULL; + int i, numlists, numregs, ret = 0; + enum guc_capture_type datatype; + struct guc_mmio_reg tmp; + bool is_partial = false; + + i = guc_capture_buf_cnt(buf); + if (!i) + return -ENODATA; + if (i % sizeof(u32)) { + drm_warn(&i915->drm, "GuC Capture new entries unaligned\n"); + ret = -EIO; + goto bailout; + } + + /* first get the capture group header */ + if (guc_capture_log_get_group_hdr(guc, buf, &ghdr)) { + ret = -EIO; + goto bailout; + } + /* + * we would typically expect a layout as below where n would be expected to be + * anywhere between 3 to n where n > 3 if we are seeing multiple dependent engine + * instances being reset together. + * ____________________________________________ + * | Capture Group | + * | ________________________________________ | + * | | Capture Group Header: | | + * | | - num_captures = 5 | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture1: | | + * | | Hdr: GLOBAL, numregs=a | | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... rega | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture2: | | + * | | Hdr: CLASS=RENDER/COMPUTE, numregs=b| | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... regb | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture3: | | + * | | Hdr: INSTANCE=RCS, numregs=c | | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... regc | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture4: | | + * | | Hdr: CLASS=RENDER/COMPUTE, numregs=d| | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... regd | | | + * | | |__________________________________| | | + * | |______________________________________| | + * | ________________________________________ | + * | | Capture5: | | + * | | Hdr: INSTANCE=CCS0, numregs=e | | + * | | ____________________________________ | | + * | | | Reglist | | | + * | | | - reg1, reg2, ... rege | | | + * | | |__________________________________| | | + * | |______________________________________| | + * |__________________________________________| + */ + is_partial = FIELD_GET(CAP_GRP_HDR_CAPTURE_TYPE, ghdr.info); + numlists = FIELD_GET(CAP_GRP_HDR_NUM_CAPTURES, ghdr.info); + + while (numlists--) { + if (guc_capture_log_get_data_hdr(guc, buf, &hdr)) { + ret = -EIO; + break; + } + + datatype = FIELD_GET(CAP_HDR_CAPTURE_TYPE, hdr.info); + if (datatype > GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE) { + /* unknown capture type - skip over to next capture set */ + numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios); + while (numregs--) { + if (guc_capture_log_get_register(guc, buf, &tmp)) { + ret = -EIO; + break; + } + } + continue; + } else if (node) { + /* + * Based on the current capture type and what we have so far, + * decide if we should add the current node into the internal + * linked list for match-up when i915_gpu_coredump calls later + * (and alloc a blank node for the next set of reglists) + * or continue with the same node or clone the current node + * but only retain the global or class registers (such as the + * case of dependent engine resets). + */ + if (datatype == GUC_CAPTURE_LIST_TYPE_GLOBAL) { + guc_capture_add_node_to_outlist(guc->capture, node); + node = NULL; + } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS && + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS].regs) { + /* Add to list, clone node and duplicate global list */ + guc_capture_add_node_to_outlist(guc->capture, node); + node = guc_capture_clone_node(guc, node, + GCAP_PARSED_REGLIST_INDEX_GLOBAL); + } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE && + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE].regs) { + /* Add to list, clone node and duplicate global + class lists */ + guc_capture_add_node_to_outlist(guc->capture, node); + node = guc_capture_clone_node(guc, node, + (GCAP_PARSED_REGLIST_INDEX_GLOBAL | + GCAP_PARSED_REGLIST_INDEX_ENGCLASS)); + } + } + + if (!node) { + node = guc_capture_alloc_one_node(guc); + if (!node) { + ret = -ENOMEM; + break; + } + if (datatype != GUC_CAPTURE_LIST_TYPE_GLOBAL) + drm_dbg(&i915->drm, "GuC Capture missing global dump: %08x!\n", + datatype); + } + node->is_partial = is_partial; + node->reginfo[datatype].vfid = FIELD_GET(CAP_HDR_CAPTURE_VFID, hdr.owner); + switch (datatype) { + case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: + node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info); + node->eng_inst = FIELD_GET(CAP_HDR_ENGINE_INSTANCE, hdr.info); + node->lrca = hdr.lrca; + node->guc_id = hdr.guc_id; + break; + case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: + node->eng_class = FIELD_GET(CAP_HDR_ENGINE_CLASS, hdr.info); + break; + default: + break; + } + + regs = NULL; + numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios); + if (numregs) { + regs = kcalloc(numregs, sizeof(struct guc_mmio_reg), GFP_KERNEL); + if (!regs) { + ret = -ENOMEM; + break; + } + } + node->reginfo[datatype].num_regs = numregs; + node->reginfo[datatype].regs = regs; + i = 0; + while (numregs--) { + if (guc_capture_log_get_register(guc, buf, ®s[i++])) { + ret = -EIO; + break; + } + } + } + +bailout: + if (node) { + /* If we have data, add to linked list for match-up when i915_gpu_coredump calls */ + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + if (node->reginfo[i].regs) { + guc_capture_add_node_to_outlist(guc->capture, node); + node = NULL; + break; + } + } + /* else free it */ + kfree(node); + } + return ret; +} + +static int __guc_capture_flushlog_complete(struct intel_guc *guc) +{ + u32 action[] = { + INTEL_GUC_ACTION_LOG_BUFFER_FILE_FLUSH_COMPLETE, + GUC_CAPTURE_LOG_BUFFER + }; + + return intel_guc_send(guc, action, ARRAY_SIZE(action)); +} + +static void __guc_capture_process_output(struct intel_guc *guc) +{ + unsigned int buffer_size, read_offset, write_offset, full_count; + struct intel_uc *uc = container_of(guc, typeof(*uc), guc); + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + struct guc_log_buffer_state log_buf_state_local; + struct guc_log_buffer_state *log_buf_state; + struct __guc_capture_bufstate buf; + void *src_data = NULL; + bool new_overflow; + int ret; + + log_buf_state = guc->log.buf_addr + + (sizeof(struct guc_log_buffer_state) * GUC_CAPTURE_LOG_BUFFER); + src_data = guc->log.buf_addr + intel_guc_get_log_buffer_offset(GUC_CAPTURE_LOG_BUFFER); + + /* + * Make a copy of the state structure, inside GuC log buffer + * (which is uncached mapped), on the stack to avoid reading + * from it multiple times. + */ + memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state)); + buffer_size = intel_guc_get_log_buffer_size(GUC_CAPTURE_LOG_BUFFER); + read_offset = log_buf_state_local.read_ptr; + write_offset = log_buf_state_local.sampled_write_ptr; + full_count = log_buf_state_local.buffer_full_cnt; + + /* Bookkeeping stuff */ + guc->log.stats[GUC_CAPTURE_LOG_BUFFER].flush += log_buf_state_local.flush_to_file; + new_overflow = intel_guc_check_log_buf_overflow(&guc->log, GUC_CAPTURE_LOG_BUFFER, + full_count); + + /* Now copy the actual logs. */ + if (unlikely(new_overflow)) { + /* copy the whole buffer in case of overflow */ + read_offset = 0; + write_offset = buffer_size; + } else if (unlikely((read_offset > buffer_size) || + (write_offset > buffer_size))) { + drm_err(&i915->drm, "invalid GuC log capture buffer state!\n"); + /* copy whole buffer as offsets are unreliable */ + read_offset = 0; + write_offset = buffer_size; + } + + buf.size = buffer_size; + buf.rd = read_offset; + buf.wr = write_offset; + buf.data = src_data; + + if (!uc->reset_in_progress) { + do { + ret = guc_capture_extract_reglists(guc, &buf); + } while (ret >= 0); + } + + /* Update the state of log buffer err-cap state */ + log_buf_state->read_ptr = write_offset; + log_buf_state->flush_to_file = 0; + __guc_capture_flushlog_complete(guc); +} + +void intel_guc_capture_process(struct intel_guc *guc) +{ + if (guc->capture) + __guc_capture_process_output(guc); +} + static void guc_capture_free_ads_cache(struct intel_guc_state_capture *gc) { @@ -737,8 +1291,7 @@ void intel_guc_capture_destroy(struct intel_guc *guc) guc_capture_free_ads_cache(guc->capture); - kfree(guc->capture); - guc->capture = NULL; + guc_capture_delete_nodes(guc); guc_capture_free_extlists(guc->capture->extlists); kfree(guc->capture->extlists); @@ -755,5 +1308,7 @@ int intel_guc_capture_init(struct intel_guc *guc) guc->capture->reglists = guc_capture_get_device_reglist(guc); + INIT_LIST_HEAD(&guc->capture->outlist); + return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index 540d72079462..d821cc6468ea 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -11,6 +11,7 @@ struct guc_gt_system_info; struct intel_guc; +void intel_guc_capture_process(struct intel_guc *guc); int intel_guc_capture_output_min_size_est(struct intel_guc *guc); int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, void **outptr); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c index b58c7af62553..74034eba8f27 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.c @@ -158,9 +158,9 @@ static void *guc_get_write_buffer(struct intel_guc_log *log) return relay_reserve(log->relay.channel, 0); } -static bool guc_check_log_buf_overflow(struct intel_guc_log *log, - enum guc_log_buffer_type type, - unsigned int full_cnt) +bool intel_guc_check_log_buf_overflow(struct intel_guc_log *log, + enum guc_log_buffer_type type, + unsigned int full_cnt) { unsigned int prev_full_cnt = log->stats[type].sampled_overflow; bool overflow = false; @@ -183,7 +183,7 @@ static bool guc_check_log_buf_overflow(struct intel_guc_log *log, return overflow; } -static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) +unsigned int intel_guc_get_log_buffer_size(enum guc_log_buffer_type type) { switch (type) { case GUC_DEBUG_LOG_BUFFER: @@ -199,6 +199,20 @@ static unsigned int guc_get_log_buffer_size(enum guc_log_buffer_type type) return 0; } +size_t intel_guc_get_log_buffer_offset(enum guc_log_buffer_type type) +{ + enum guc_log_buffer_type i; + size_t offset = PAGE_SIZE;/* for the log_buffer_states */ + + for (i = GUC_DEBUG_LOG_BUFFER; i < GUC_MAX_LOG_BUFFER; ++i) { + if (i == type) + break; + offset += intel_guc_get_log_buffer_size(i); + } + + return offset; +} + static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) { unsigned int buffer_size, read_offset, write_offset, bytes_to_copy, full_cnt; @@ -244,14 +258,14 @@ static void _guc_log_copy_debuglogs_for_relay(struct intel_guc_log *log) */ memcpy(&log_buf_state_local, log_buf_state, sizeof(struct guc_log_buffer_state)); - buffer_size = guc_get_log_buffer_size(type); + buffer_size = intel_guc_get_log_buffer_size(type); read_offset = log_buf_state_local.read_ptr; write_offset = log_buf_state_local.sampled_write_ptr; full_cnt = log_buf_state_local.buffer_full_cnt; /* Bookkeeping stuff */ log->stats[type].flush += log_buf_state_local.flush_to_file; - new_overflow = guc_check_log_buf_overflow(log, type, full_cnt); + new_overflow = intel_guc_check_log_buf_overflow(log, type, full_cnt); /* Update the state of shared log buffer */ log_buf_state->read_ptr = write_offset; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h index e1345fca7729..18007e639be9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_log.h @@ -67,6 +67,10 @@ struct intel_guc_log { }; void intel_guc_log_init_early(struct intel_guc_log *log); +bool intel_guc_check_log_buf_overflow(struct intel_guc_log *log, enum guc_log_buffer_type type, + unsigned int full_cnt); +unsigned int intel_guc_get_log_buffer_size(enum guc_log_buffer_type type); +size_t intel_guc_get_log_buffer_offset(enum guc_log_buffer_type type); int intel_guc_log_create(struct intel_guc_log *log); void intel_guc_log_destroy(struct intel_guc_log *log); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 42c9e8b7bf42..120d339a367a 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -25,6 +25,7 @@ #include "gt/intel_ring.h" #include "intel_guc_ads.h" +#include "intel_guc_capture.h" #include "intel_guc_submission.h" #include "i915_drv.h" @@ -4095,17 +4096,18 @@ int intel_guc_context_reset_process_msg(struct intel_guc *guc, int intel_guc_error_capture_process_msg(struct intel_guc *guc, const u32 *msg, u32 len) { - int status; + u32 status; if (unlikely(len != 1)) { drm_dbg(&guc_to_gt(guc)->i915->drm, "Invalid length %u", len); return -EPROTO; } - status = msg[0]; - drm_info(&guc_to_gt(guc)->i915->drm, "Got error capture: status = %d", status); + status = msg[0] & INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_MASK; + if (status == INTEL_GUC_STATE_CAPTURE_EVENT_STATUS_NOSPACE) + drm_warn(&guc_to_gt(guc)->i915->drm, "G2H-Error capture no space"); - /* FIXME: Do something with the capture */ + intel_guc_capture_process(guc); return 0; } From 247f8071d589333cd0fc559c8802edd13e21e203 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:25 -0700 Subject: [PATCH 00316/11454] drm/i915/guc: Pre-allocate output nodes for extraction In the rare but possible scenario where we are in the midst of multiple GuC error-capture (and engine reset) events and the user also triggers a forced full GT reset or the internal watchdog triggers the same, intel_guc_submission_reset_prepare's call to flush_work(&guc->ct.requests.worker) can cause the G2H message handler to trigger intel_guc_capture_store_snapshot upon receiving new G2H error-capture notifications. This can happen despite the prior call to disable_submission(guc);. However, there's no race-free way for intel_guc_capture_store_snapshot to know that we are in the midst of a reset. That said, we can never dynamically allocate the output nodes in this handler. Thus, we shall pre-allocate a fixed number of empty nodes up front (at the time of ADS registration) that we can consume from or return to an internal cached list of nodes. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-12-alan.previn.teres.alexis@intel.com --- drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h | 19 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 177 ++++++++++++++---- 2 files changed, 161 insertions(+), 35 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h index 5d959e62d146..3624abfd22d1 100644 --- a/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h +++ b/drivers/gpu/drm/i915/gt/uc/guc_capture_fwif.h @@ -31,7 +31,7 @@ struct __guc_capture_bufstate { * * A single unit of extracted error-capture output data grouped together * at an engine-instance level. We keep these nodes in a linked list. - * See outlist below. + * See cachelist and outlist below. */ struct __guc_capture_parsed_output { /* @@ -190,7 +190,22 @@ struct intel_guc_state_capture { void *ads_null_cache; /** - * @outlist: allocated nodes with parsed engine-instance error capture data + * @cachelist: Pool of pre-allocated nodes for error capture output + * + * We need this pool of pre-allocated nodes because we cannot + * dynamically allocate new nodes when receiving the G2H notification + * because the event handlers for all G2H event-processing is called + * by the ct processing worker queue and when that queue is being + * processed, there is no absoluate guarantee that we are not in the + * midst of a GT reset operation (which doesn't allow allocations). + */ + struct list_head cachelist; +#define PREALLOC_NODES_MAX_COUNT (3 * GUC_MAX_ENGINE_CLASSES * GUC_MAX_INSTANCES_PER_CLASS) +#define PREALLOC_NODES_DEFAULT_NUMREGS 64 + int max_mmio_per_node; + + /** + * @outlist: Pool of pre-allocated nodes for error capture output * * A linked list of parsed GuC error-capture output data before * reporting with formatting via i915_gpu_coredump. Each node in this linked list shall diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 25a5f1013e43..6af86c255a40 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -581,6 +581,8 @@ intel_guc_capture_getlistsize(struct intel_guc *guc, u32 owner, u32 type, u32 cl return 0; } +static void guc_capture_create_prealloc_nodes(struct intel_guc *guc); + int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, void **outptr) @@ -601,6 +603,12 @@ intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classi return cache->status; } + /* + * ADS population of input registers is a good + * time to pre-allocate cachelist output nodes + */ + guc_capture_create_prealloc_nodes(guc); + ret = intel_guc_capture_getlistsize(guc, owner, type, classid, &size); if (ret) { cache->is_valid = true; @@ -742,7 +750,8 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) * err-state-captured register-list we find, we alloc 'C': * --> alloc C: A capture-output-node structure that includes misc capture info along * with 3 register list dumps (global, engine-class and engine-instance) - * This node is dynamically allocated and populated with the error-capture + * This node is created from a pre-allocated list of blank nodes in + * guc->capture->cachelist and populated with the error-capture * data from GuC and then it's added into guc->capture->outlist linked * list. This list is used for matchup and printout by i915_gpu_coredump * and err_print_gt, (when user invokes the error capture sysfs). @@ -902,19 +911,20 @@ guc_capture_delete_one_node(struct intel_guc *guc, struct __guc_capture_parsed_o } static void -guc_capture_delete_nodes(struct intel_guc *guc) +guc_capture_delete_prealloc_nodes(struct intel_guc *guc) { + struct __guc_capture_parsed_output *n, *ntmp; + /* * NOTE: At the end of driver operation, we must assume that we - * have nodes in outlist from unclaimed error capture events - * that occurred prior to shutdown. + * have prealloc nodes in both the cachelist as well as outlist + * if unclaimed error capture events occurred prior to shutdown. */ - if (!list_empty(&guc->capture->outlist)) { - struct __guc_capture_parsed_output *n, *ntmp; + list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) + guc_capture_delete_one_node(guc, n); - list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) - guc_capture_delete_one_node(guc, n); - } + list_for_each_entry_safe(n, ntmp, &guc->capture->cachelist, link) + guc_capture_delete_one_node(guc, n); } static void @@ -931,21 +941,80 @@ guc_capture_add_node_to_outlist(struct intel_guc_state_capture *gc, guc_capture_add_node_to_list(node, &gc->outlist); } +static void +guc_capture_add_node_to_cachelist(struct intel_guc_state_capture *gc, + struct __guc_capture_parsed_output *node) +{ + guc_capture_add_node_to_list(node, &gc->cachelist); +} + static void guc_capture_init_node(struct intel_guc *guc, struct __guc_capture_parsed_output *node) { + struct guc_mmio_reg *tmp[GUC_CAPTURE_LIST_TYPE_MAX]; + int i; + + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + tmp[i] = node->reginfo[i].regs; + memset(tmp[i], 0, sizeof(struct guc_mmio_reg) * + guc->capture->max_mmio_per_node); + } + memset(node, 0, sizeof(*node)); + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) + node->reginfo[i].regs = tmp[i]; + INIT_LIST_HEAD(&node->link); } +static struct __guc_capture_parsed_output * +guc_capture_get_prealloc_node(struct intel_guc *guc) +{ + struct __guc_capture_parsed_output *found = NULL; + + if (!list_empty(&guc->capture->cachelist)) { + struct __guc_capture_parsed_output *n, *ntmp; + + /* get first avail node from the cache list */ + list_for_each_entry_safe(n, ntmp, &guc->capture->cachelist, link) { + found = n; + list_del(&n->link); + break; + } + } else { + struct __guc_capture_parsed_output *n, *ntmp; + + /* traverse down and steal back the oldest node already allocated */ + list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) { + found = n; + } + if (found) + list_del(&found->link); + } + if (found) + guc_capture_init_node(guc, found); + + return found; +} + static struct __guc_capture_parsed_output * guc_capture_alloc_one_node(struct intel_guc *guc) { struct __guc_capture_parsed_output *new; + int i; new = kzalloc(sizeof(*new), GFP_KERNEL); if (!new) return NULL; + for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + new->reginfo[i].regs = kcalloc(guc->capture->max_mmio_per_node, + sizeof(struct guc_mmio_reg), GFP_KERNEL); + if (!new->reginfo[i].regs) { + while (i) + kfree(new->reginfo[--i].regs); + return NULL; + } + } guc_capture_init_node(guc, new); return new; @@ -958,7 +1027,7 @@ guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output struct __guc_capture_parsed_output *new; int i; - new = guc_capture_alloc_one_node(guc); + new = guc_capture_get_prealloc_node(guc); if (!new) return NULL; if (!original) @@ -969,13 +1038,12 @@ guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output /* copy reg-lists that we want to clone */ for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { if (keep_reglist_mask & BIT(i)) { - new->reginfo[i].regs = kcalloc(original->reginfo[i].num_regs, - sizeof(struct guc_mmio_reg), GFP_KERNEL); - if (!new->reginfo[i].regs) - goto bail_clone; + GEM_BUG_ON(original->reginfo[i].num_regs > + guc->capture->max_mmio_per_node); memcpy(new->reginfo[i].regs, original->reginfo[i].regs, original->reginfo[i].num_regs * sizeof(struct guc_mmio_reg)); + new->reginfo[i].num_regs = original->reginfo[i].num_regs; new->reginfo[i].vfid = original->reginfo[i].vfid; @@ -990,12 +1058,58 @@ guc_capture_clone_node(struct intel_guc *guc, struct __guc_capture_parsed_output } return new; +} -bail_clone: - for (i = 0; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) - kfree(new->reginfo[i].regs); - kfree(new); - return NULL; +static void +__guc_capture_create_prealloc_nodes(struct intel_guc *guc) +{ + struct __guc_capture_parsed_output *node = NULL; + struct drm_i915_private *i915 = guc_to_gt(guc)->i915; + int i; + + for (i = 0; i < PREALLOC_NODES_MAX_COUNT; ++i) { + node = guc_capture_alloc_one_node(guc); + if (!node) { + drm_warn(&i915->drm, "GuC Capture pre-alloc-cache failure\n"); + /* dont free the priors, use what we got and cleanup at shutdown */ + return; + } + guc_capture_add_node_to_cachelist(guc->capture, node); + } +} + +static int +guc_get_max_reglist_count(struct intel_guc *guc) +{ + int i, j, k, tmp, maxregcount = 0; + + for (i = 0; i < GUC_CAPTURE_LIST_INDEX_MAX; ++i) { + for (j = 0; j < GUC_CAPTURE_LIST_TYPE_MAX; ++j) { + for (k = 0; k < GUC_MAX_ENGINE_CLASSES; ++k) { + if (j == GUC_CAPTURE_LIST_TYPE_GLOBAL && k > 0) + continue; + + tmp = guc_cap_list_num_regs(guc->capture, i, j, k); + if (tmp > maxregcount) + maxregcount = tmp; + } + } + } + if (!maxregcount) + maxregcount = PREALLOC_NODES_DEFAULT_NUMREGS; + + return maxregcount; +} + +static void +guc_capture_create_prealloc_nodes(struct intel_guc *guc) +{ + /* skip if we've already done the pre-alloc */ + if (guc->capture->max_mmio_per_node) + return; + + guc->capture->max_mmio_per_node = guc_get_max_reglist_count(guc); + __guc_capture_create_prealloc_nodes(guc); } static int @@ -1111,13 +1225,13 @@ guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstat guc_capture_add_node_to_outlist(guc->capture, node); node = NULL; } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS && - node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS].regs) { + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS].num_regs) { /* Add to list, clone node and duplicate global list */ guc_capture_add_node_to_outlist(guc->capture, node); node = guc_capture_clone_node(guc, node, GCAP_PARSED_REGLIST_INDEX_GLOBAL); } else if (datatype == GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE && - node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE].regs) { + node->reginfo[GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE].num_regs) { /* Add to list, clone node and duplicate global + class lists */ guc_capture_add_node_to_outlist(guc->capture, node); node = guc_capture_clone_node(guc, node, @@ -1127,7 +1241,7 @@ guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstat } if (!node) { - node = guc_capture_alloc_one_node(guc); + node = guc_capture_get_prealloc_node(guc); if (!node) { ret = -ENOMEM; break; @@ -1152,17 +1266,13 @@ guc_capture_extract_reglists(struct intel_guc *guc, struct __guc_capture_bufstat break; } - regs = NULL; numregs = FIELD_GET(CAP_HDR_NUM_MMIOS, hdr.num_mmios); - if (numregs) { - regs = kcalloc(numregs, sizeof(struct guc_mmio_reg), GFP_KERNEL); - if (!regs) { - ret = -ENOMEM; - break; - } + if (numregs > guc->capture->max_mmio_per_node) { + drm_dbg(&i915->drm, "GuC Capture list extraction clipped by prealloc!\n"); + numregs = guc->capture->max_mmio_per_node; } node->reginfo[datatype].num_regs = numregs; - node->reginfo[datatype].regs = regs; + regs = node->reginfo[datatype].regs; i = 0; while (numregs--) { if (guc_capture_log_get_register(guc, buf, ®s[i++])) { @@ -1182,8 +1292,8 @@ bailout: break; } } - /* else free it */ - kfree(node); + if (node) /* else return it back to cache list */ + guc_capture_add_node_to_cachelist(guc->capture, node); } return ret; } @@ -1291,7 +1401,7 @@ void intel_guc_capture_destroy(struct intel_guc *guc) guc_capture_free_ads_cache(guc->capture); - guc_capture_delete_nodes(guc); + guc_capture_delete_prealloc_nodes(guc); guc_capture_free_extlists(guc->capture->extlists); kfree(guc->capture->extlists); @@ -1309,6 +1419,7 @@ int intel_guc_capture_init(struct intel_guc *guc) guc->capture->reglists = guc_capture_get_device_reglist(guc); INIT_LIST_HEAD(&guc->capture->outlist); + INIT_LIST_HEAD(&guc->capture->cachelist); return 0; } From a6f0f9cf330a86971f587333762d9a61a218bc30 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:26 -0700 Subject: [PATCH 00317/11454] drm/i915/guc: Plumb GuC-capture into gpu_coredump Add a flags parameter through all of the coredump creation functions. Add a bitmask flag to indicate if the top level gpu_coredump event is triggered in response to a GuC context reset notification. Using that flag, ensure all coredump functions that read or print mmio-register values related to work submission or command-streamer engines are skipped and replaced with a calls guc-capture module equivalent functions to retrieve or print the register dump. While here, split out display related register reading and printing into its own function that is called agnostic to whether GuC had triggered the reset. For now, introduce an empty printing function that can filled in on a subsequent patch just to handle formatting. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-13-alan.previn.teres.alexis@intel.com --- .../drm/i915/gt/intel_execlists_submission.c | 4 +- drivers/gpu/drm/i915/gt/intel_reset.c | 2 +- .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 70 +++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 9 + .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 2 +- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_gpu_error.c | 268 ++++++++++++------ drivers/gpu/drm/i915/i915_gpu_error.h | 30 +- 8 files changed, 289 insertions(+), 98 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c index 43575e8c68a4..e181029c1e3e 100644 --- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c +++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c @@ -2229,11 +2229,11 @@ static struct execlists_capture *capture_regs(struct intel_engine_cs *engine) if (!cap->error) goto err_cap; - cap->error->gt = intel_gt_coredump_alloc(engine->gt, gfp); + cap->error->gt = intel_gt_coredump_alloc(engine->gt, gfp, CORE_DUMP_FLAG_NONE); if (!cap->error->gt) goto err_gpu; - cap->error->gt->engine = intel_engine_coredump_alloc(engine, gfp); + cap->error->gt->engine = intel_engine_coredump_alloc(engine, gfp, CORE_DUMP_FLAG_NONE); if (!cap->error->gt->engine) goto err_gt; diff --git a/drivers/gpu/drm/i915/gt/intel_reset.c b/drivers/gpu/drm/i915/gt/intel_reset.c index 82713264b96c..2d120bd391a2 100644 --- a/drivers/gpu/drm/i915/gt/intel_reset.c +++ b/drivers/gpu/drm/i915/gt/intel_reset.c @@ -1318,7 +1318,7 @@ void intel_gt_handle_error(struct intel_gt *gt, engine_mask &= gt->info.engine_mask; if (flags & I915_ERROR_CAPTURE) { - i915_capture_error_state(gt, engine_mask); + i915_capture_error_state(gt, engine_mask, CORE_DUMP_FLAG_NONE); intel_gt_clear_error_registers(gt, engine_mask); } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 6af86c255a40..59b4476697c6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -10,6 +10,7 @@ #include "gt/intel_engine_regs.h" #include "gt/intel_gt.h" #include "gt/intel_gt_regs.h" +#include "gt/intel_lrc.h" #include "guc_capture_fwif.h" #include "intel_guc_capture.h" #include "intel_guc_fwif.h" @@ -755,6 +756,18 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) * data from GuC and then it's added into guc->capture->outlist linked * list. This list is used for matchup and printout by i915_gpu_coredump * and err_print_gt, (when user invokes the error capture sysfs). + * + * GUC --> notify context reset: + * ----------------------------- + * --> G2H CONTEXT RESET + * L--> guc_handle_context_reset --> i915_capture_error_state + * L--> i915_gpu_coredump(..IS_GUC_CAPTURE) --> gt_record_engines + * --> capture_engine(..IS_GUC_CAPTURE) + * L--> intel_guc_capture_get_matching_node is where + * detach C from internal linked list and add it into + * intel_engine_coredump struct (if the context and + * engine of the event notification matches a node + * in the link list). */ static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) @@ -1370,6 +1383,63 @@ static void __guc_capture_process_output(struct intel_guc *guc) __guc_capture_flushlog_complete(guc); } +#if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) + +int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, + const struct intel_engine_coredump *ee) +{ + return 0; +} + +#endif //CONFIG_DRM_I915_CAPTURE_ERROR + +void intel_guc_capture_free_node(struct intel_engine_coredump *ee) +{ + if (!ee || !ee->guc_capture_node) + return; + + guc_capture_add_node_to_cachelist(ee->capture, ee->guc_capture_node); + ee->capture = NULL; + ee->guc_capture_node = NULL; +} + +void intel_guc_capture_get_matching_node(struct intel_gt *gt, + struct intel_engine_coredump *ee, + struct intel_context *ce) +{ + struct __guc_capture_parsed_output *n, *ntmp; + struct drm_i915_private *i915; + struct intel_guc *guc; + + if (!gt || !ee || !ce) + return; + + i915 = gt->i915; + guc = >->uc.guc; + if (!guc->capture) + return; + + GEM_BUG_ON(ee->guc_capture_node); + /* + * Look for a matching GuC reported error capture node from + * the internal output link-list based on lrca, guc-id and engine + * identification. + */ + list_for_each_entry_safe(n, ntmp, &guc->capture->outlist, link) { + if (n->eng_inst == GUC_ID_TO_ENGINE_INSTANCE(ee->engine->guc_id) && + n->eng_class == GUC_ID_TO_ENGINE_CLASS(ee->engine->guc_id) && + n->guc_id && n->guc_id == ce->guc_id.id && + (n->lrca & CTX_GTT_ADDRESS_MASK) && (n->lrca & CTX_GTT_ADDRESS_MASK) == + (ce->lrc.lrca & CTX_GTT_ADDRESS_MASK)) { + list_del(&n->link); + ee->guc_capture_node = n; + ee->capture = guc->capture; + return; + } + } + drm_dbg(&i915->drm, "GuC capture can't match ee to node\n"); +} + void intel_guc_capture_process(struct intel_guc *guc) { if (guc->capture) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index d821cc6468ea..a8688928f88e 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -8,9 +8,18 @@ #include +struct drm_i915_error_state_buf; struct guc_gt_system_info; +struct intel_context; +struct intel_engine_coredump; +struct intel_gt; struct intel_guc; +void intel_guc_capture_free_node(struct intel_engine_coredump *ee); +int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *m, + const struct intel_engine_coredump *ee); +void intel_guc_capture_get_matching_node(struct intel_gt *gt, struct intel_engine_coredump *ee, + struct intel_context *ce); void intel_guc_capture_process(struct intel_guc *guc); int intel_guc_capture_output_min_size_est(struct intel_guc *guc); int intel_guc_capture_getlist(struct intel_guc *guc, u32 owner, u32 type, u32 classid, diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index 120d339a367a..f797c49762c9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4031,7 +4031,7 @@ static void capture_error_state(struct intel_guc *guc, intel_engine_set_hung_context(engine, ce); with_intel_runtime_pm(&i915->runtime_pm, wakeref) - i915_capture_error_state(gt, engine->mask); + i915_capture_error_state(gt, engine->mask, CORE_DUMP_FLAG_IS_GUC_CAPTURE); atomic_inc(&i915->gpu_error.reset_engine_count[engine->uabi_class]); } diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 9658b4ca669a..1279ea394af7 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -307,7 +307,7 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file) gpu = NULL; with_intel_runtime_pm(&i915->runtime_pm, wakeref) - gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES); + gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES, CORE_DUMP_FLAG_NONE); if (IS_ERR(gpu)) return PTR_ERR(gpu); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 81f70099525a..c76d8df4c190 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -46,6 +46,7 @@ #include "gt/intel_gt.h" #include "gt/intel_gt_pm.h" #include "gt/intel_gt_regs.h" +#include "gt/uc/intel_guc_capture.h" #include "i915_driver.h" #include "i915_drv.h" @@ -593,15 +594,11 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, ee->vm_info.pp_dir_base); } } - err_printf(m, " hung: %u\n", ee->hung); - err_printf(m, " engine reset count: %u\n", ee->reset_count); for (n = 0; n < ee->num_ports; n++) { err_printf(m, " ELSP[%d]:", n); error_print_request(m, " ", &ee->execlist[n]); } - - error_print_context(m, " Active context: ", &ee->context); } void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) @@ -713,23 +710,30 @@ static void err_print_gt_info(struct drm_i915_error_state_buf *m, intel_sseu_print_topology(gt->_gt->i915, >->info.sseu, &p); } -static void err_print_gt(struct drm_i915_error_state_buf *m, - struct intel_gt_coredump *gt) +static void err_print_gt_display(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + err_printf(m, "IER: 0x%08x\n", gt->ier); + err_printf(m, "DERRMR: 0x%08x\n", gt->derrmr); +} + +static void err_print_gt_global_nonguc(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) { - const struct intel_engine_coredump *ee; int i; err_printf(m, "GT awake: %s\n", yesno(gt->awake)); err_printf(m, "EIR: 0x%08x\n", gt->eir); - err_printf(m, "IER: 0x%08x\n", gt->ier); + err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er); + for (i = 0; i < gt->ngtier; i++) err_printf(m, "GTIER[%d]: 0x%08x\n", i, gt->gtier[i]); - err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er); - err_printf(m, "FORCEWAKE: 0x%08x\n", gt->forcewake); - err_printf(m, "DERRMR: 0x%08x\n", gt->derrmr); +} - for (i = 0; i < gt->nfence; i++) - err_printf(m, " fence[%d] = %08llx\n", i, gt->fence[i]); +static void err_print_gt_global(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + err_printf(m, "FORCEWAKE: 0x%08x\n", gt->forcewake); if (IS_GRAPHICS_VER(m->i915, 6, 11)) { err_printf(m, "ERROR: 0x%08x\n", gt->error); @@ -768,19 +772,38 @@ static void err_print_gt(struct drm_i915_error_state_buf *m, err_printf(m, " GAM_DONE: 0x%08x\n", gt->gam_done); } +} + +static void err_print_gt_fences(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + int i; + + for (i = 0; i < gt->nfence; i++) + err_printf(m, " fence[%d] = %08llx\n", i, gt->fence[i]); +} + +static void err_print_gt_engines(struct drm_i915_error_state_buf *m, + struct intel_gt_coredump *gt) +{ + const struct intel_engine_coredump *ee; for (ee = gt->engine; ee; ee = ee->next) { const struct i915_vma_coredump *vma; - error_print_engine(m, ee); + if (ee->guc_capture_node) + intel_guc_capture_print_engine_node(m, ee); + else + error_print_engine(m, ee); + + err_printf(m, " hung: %u\n", ee->hung); + err_printf(m, " engine reset count: %u\n", ee->reset_count); + error_print_context(m, " Active context: ", &ee->context); + for (vma = ee->vma; vma; vma = vma->next) print_error_vma(m, ee->engine, vma); } - if (gt->uc) - err_print_uc(m, gt->uc); - - err_print_gt_info(m, gt); } static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, @@ -836,8 +859,30 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, err_printf(m, "RPM wakelock: %s\n", yesno(error->wakelock)); err_printf(m, "PM suspended: %s\n", yesno(error->suspended)); - if (error->gt) - err_print_gt(m, error->gt); + if (error->gt) { + bool print_guc_capture = false; + + if (error->gt->uc && error->gt->uc->is_guc_capture) + print_guc_capture = true; + + err_print_gt_display(m, error->gt); + err_print_gt_global_nonguc(m, error->gt); + err_print_gt_fences(m, error->gt); + + /* + * GuC dumped global, eng-class and eng-instance registers together + * as part of engine state dump so we print in err_print_gt_engines + */ + if (!print_guc_capture) + err_print_gt_global(m, error->gt); + + err_print_gt_engines(m, error->gt); + + if (error->gt->uc) + err_print_uc(m, error->gt->uc); + + err_print_gt_info(m, error->gt); + } if (error->overlay) intel_overlay_print_error_state(m, error->overlay); @@ -985,6 +1030,7 @@ static void cleanup_gt(struct intel_gt_coredump *gt) gt->engine = ee->next; i915_vma_coredump_free(ee->vma); + intel_guc_capture_free_node(ee); kfree(ee); } @@ -1436,7 +1482,7 @@ static void add_vma_coredump(struct intel_engine_coredump *ee, } struct intel_engine_coredump * -intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp) +intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_flags) { struct intel_engine_coredump *ee; @@ -1446,8 +1492,10 @@ intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp) ee->engine = engine; - engine_record_registers(ee); - engine_record_execlists(ee); + if (!(dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE)) { + engine_record_registers(ee); + engine_record_execlists(ee); + } return ee; } @@ -1511,7 +1559,8 @@ intel_engine_coredump_add_vma(struct intel_engine_coredump *ee, static struct intel_engine_coredump * capture_engine(struct intel_engine_cs *engine, - struct i915_vma_compress *compress) + struct i915_vma_compress *compress, + u32 dump_flags) { struct intel_engine_capture_vma *capture = NULL; struct intel_engine_coredump *ee; @@ -1519,7 +1568,7 @@ capture_engine(struct intel_engine_cs *engine, struct i915_request *rq = NULL; unsigned long flags; - ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL); + ee = intel_engine_coredump_alloc(engine, ALLOW_FAIL, dump_flags); if (!ee) return NULL; @@ -1552,6 +1601,8 @@ capture_engine(struct intel_engine_cs *engine, i915_request_put(rq); goto no_request_capture; } + if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) + intel_guc_capture_get_matching_node(engine->gt, ee, ce); intel_engine_coredump_add_vma(ee, capture, compress); i915_request_put(rq); @@ -1566,7 +1617,8 @@ no_request_capture: static void gt_record_engines(struct intel_gt_coredump *gt, intel_engine_mask_t engine_mask, - struct i915_vma_compress *compress) + struct i915_vma_compress *compress, + u32 dump_flags) { struct intel_engine_cs *engine; enum intel_engine_id id; @@ -1577,7 +1629,7 @@ gt_record_engines(struct intel_gt_coredump *gt, /* Refill our page pool before entering atomic section */ pool_refill(&compress->pool, ALLOW_FAIL); - ee = capture_engine(engine, compress); + ee = capture_engine(engine, compress, dump_flags); if (!ee) continue; @@ -1585,6 +1637,8 @@ gt_record_engines(struct intel_gt_coredump *gt, gt->simulated |= ee->simulated; if (ee->simulated) { + if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) + intel_guc_capture_free_node(ee); kfree(ee); continue; } @@ -1620,8 +1674,74 @@ gt_record_uc(struct intel_gt_coredump *gt, return error_uc; } -/* Capture all registers which don't fit into another category. */ -static void gt_record_regs(struct intel_gt_coredump *gt) +/* Capture display registers. */ +static void gt_record_display_regs(struct intel_gt_coredump *gt) +{ + struct intel_uncore *uncore = gt->_gt->uncore; + struct drm_i915_private *i915 = uncore->i915; + + if (GRAPHICS_VER(i915) >= 6) + gt->derrmr = intel_uncore_read(uncore, DERRMR); + + if (GRAPHICS_VER(i915) >= 8) + gt->ier = intel_uncore_read(uncore, GEN8_DE_MISC_IER); + else if (IS_VALLEYVIEW(i915)) + gt->ier = intel_uncore_read(uncore, VLV_IER); + else if (HAS_PCH_SPLIT(i915)) + gt->ier = intel_uncore_read(uncore, DEIER); + else if (GRAPHICS_VER(i915) == 2) + gt->ier = intel_uncore_read16(uncore, GEN2_IER); + else + gt->ier = intel_uncore_read(uncore, GEN2_IER); +} + +/* Capture all other registers that GuC doesn't capture. */ +static void gt_record_global_nonguc_regs(struct intel_gt_coredump *gt) +{ + struct intel_uncore *uncore = gt->_gt->uncore; + struct drm_i915_private *i915 = uncore->i915; + int i; + + if (IS_VALLEYVIEW(i915)) { + gt->gtier[0] = intel_uncore_read(uncore, GTIER); + gt->ngtier = 1; + } else if (GRAPHICS_VER(i915) >= 11) { + gt->gtier[0] = + intel_uncore_read(uncore, + GEN11_RENDER_COPY_INTR_ENABLE); + gt->gtier[1] = + intel_uncore_read(uncore, GEN11_VCS_VECS_INTR_ENABLE); + gt->gtier[2] = + intel_uncore_read(uncore, GEN11_GUC_SG_INTR_ENABLE); + gt->gtier[3] = + intel_uncore_read(uncore, + GEN11_GPM_WGBOXPERF_INTR_ENABLE); + gt->gtier[4] = + intel_uncore_read(uncore, + GEN11_CRYPTO_RSVD_INTR_ENABLE); + gt->gtier[5] = + intel_uncore_read(uncore, + GEN11_GUNIT_CSME_INTR_ENABLE); + gt->ngtier = 6; + } else if (GRAPHICS_VER(i915) >= 8) { + for (i = 0; i < 4; i++) + gt->gtier[i] = + intel_uncore_read(uncore, GEN8_GT_IER(i)); + gt->ngtier = 4; + } else if (HAS_PCH_SPLIT(i915)) { + gt->gtier[0] = intel_uncore_read(uncore, GTIER); + gt->ngtier = 1; + } + + gt->eir = intel_uncore_read(uncore, EIR); + gt->pgtbl_er = intel_uncore_read(uncore, PGTBL_ER); +} + +/* + * Capture all registers that relate to workload submission. + * NOTE: In GuC submission, when GuC resets an engine, it can dump these for us + */ +static void gt_record_global_regs(struct intel_gt_coredump *gt) { struct intel_uncore *uncore = gt->_gt->uncore; struct drm_i915_private *i915 = uncore->i915; @@ -1637,11 +1757,8 @@ static void gt_record_regs(struct intel_gt_coredump *gt) */ /* 1: Registers specific to a single generation */ - if (IS_VALLEYVIEW(i915)) { - gt->gtier[0] = intel_uncore_read(uncore, GTIER); - gt->ier = intel_uncore_read(uncore, VLV_IER); + if (IS_VALLEYVIEW(i915)) gt->forcewake = intel_uncore_read_fw(uncore, FORCEWAKE_VLV); - } if (GRAPHICS_VER(i915) == 7) gt->err_int = intel_uncore_read(uncore, GEN7_ERR_INT); @@ -1669,7 +1786,6 @@ static void gt_record_regs(struct intel_gt_coredump *gt) gt->forcewake = intel_uncore_read_fw(uncore, FORCEWAKE_MT); if (GRAPHICS_VER(i915) >= 6) { - gt->derrmr = intel_uncore_read(uncore, DERRMR); if (GRAPHICS_VER(i915) < 12) { gt->error = intel_uncore_read(uncore, ERROR_GEN6); gt->done_reg = intel_uncore_read(uncore, DONE_REG); @@ -1705,44 +1821,6 @@ static void gt_record_regs(struct intel_gt_coredump *gt) gt->gam_done = intel_uncore_read(uncore, GEN12_GAM_DONE); } - - /* 4: Everything else */ - if (GRAPHICS_VER(i915) >= 11) { - gt->ier = intel_uncore_read(uncore, GEN8_DE_MISC_IER); - gt->gtier[0] = - intel_uncore_read(uncore, - GEN11_RENDER_COPY_INTR_ENABLE); - gt->gtier[1] = - intel_uncore_read(uncore, GEN11_VCS_VECS_INTR_ENABLE); - gt->gtier[2] = - intel_uncore_read(uncore, GEN11_GUC_SG_INTR_ENABLE); - gt->gtier[3] = - intel_uncore_read(uncore, - GEN11_GPM_WGBOXPERF_INTR_ENABLE); - gt->gtier[4] = - intel_uncore_read(uncore, - GEN11_CRYPTO_RSVD_INTR_ENABLE); - gt->gtier[5] = - intel_uncore_read(uncore, - GEN11_GUNIT_CSME_INTR_ENABLE); - gt->ngtier = 6; - } else if (GRAPHICS_VER(i915) >= 8) { - gt->ier = intel_uncore_read(uncore, GEN8_DE_MISC_IER); - for (i = 0; i < 4; i++) - gt->gtier[i] = - intel_uncore_read(uncore, GEN8_GT_IER(i)); - gt->ngtier = 4; - } else if (HAS_PCH_SPLIT(i915)) { - gt->ier = intel_uncore_read(uncore, DEIER); - gt->gtier[0] = intel_uncore_read(uncore, GTIER); - gt->ngtier = 1; - } else if (GRAPHICS_VER(i915) == 2) { - gt->ier = intel_uncore_read16(uncore, GEN2_IER); - } else if (!IS_VALLEYVIEW(i915)) { - gt->ier = intel_uncore_read(uncore, GEN2_IER); - } - gt->eir = intel_uncore_read(uncore, EIR); - gt->pgtbl_er = intel_uncore_read(uncore, PGTBL_ER); } static void gt_record_info(struct intel_gt_coredump *gt) @@ -1854,7 +1932,7 @@ i915_gpu_coredump_alloc(struct drm_i915_private *i915, gfp_t gfp) #define DAY_AS_SECONDS(x) (24 * 60 * 60 * (x)) struct intel_gt_coredump * -intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp) +intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp, u32 dump_flags) { struct intel_gt_coredump *gc; @@ -1865,7 +1943,21 @@ intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp) gc->_gt = gt; gc->awake = intel_gt_pm_is_awake(gt); - gt_record_regs(gc); + gt_record_display_regs(gc); + gt_record_global_nonguc_regs(gc); + + /* + * GuC dumps global, eng-class and eng-instance registers + * (that can change as part of engine state during execution) + * before an engine is reset due to a hung context. + * GuC captures and reports all three groups of registers + * together as a single set before the engine is reset. + * Thus, if GuC triggered the context reset we retrieve + * the register values as part of gt_record_engines. + */ + if (!(dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE)) + gt_record_global_regs(gc); + gt_record_fences(gc); return gc; @@ -1899,7 +1991,7 @@ void i915_vma_capture_finish(struct intel_gt_coredump *gt, } static struct i915_gpu_coredump * -__i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) +__i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { struct drm_i915_private *i915 = gt->i915; struct i915_gpu_coredump *error; @@ -1913,7 +2005,7 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) if (!error) return ERR_PTR(-ENOMEM); - error->gt = intel_gt_coredump_alloc(gt, ALLOW_FAIL); + error->gt = intel_gt_coredump_alloc(gt, ALLOW_FAIL, dump_flags); if (error->gt) { struct i915_vma_compress *compress; @@ -1924,11 +2016,19 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) return ERR_PTR(-ENOMEM); } - gt_record_info(error->gt); - gt_record_engines(error->gt, engine_mask, compress); - - if (INTEL_INFO(i915)->has_gt_uc) + if (INTEL_INFO(i915)->has_gt_uc) { error->gt->uc = gt_record_uc(error->gt, compress); + if (error->gt->uc) { + if (dump_flags & CORE_DUMP_FLAG_IS_GUC_CAPTURE) + error->gt->uc->is_guc_capture = true; + else + GEM_BUG_ON(error->gt->uc->is_guc_capture); + } + } + + gt_record_info(error->gt); + gt_record_engines(error->gt, engine_mask, compress, dump_flags); + i915_vma_capture_finish(error->gt, compress); @@ -1941,7 +2041,7 @@ __i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) } struct i915_gpu_coredump * -i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) +i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { static DEFINE_MUTEX(capture_mutex); int ret = mutex_lock_interruptible(&capture_mutex); @@ -1950,7 +2050,7 @@ i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask) if (ret) return ERR_PTR(ret); - dump = __i915_gpu_coredump(gt, engine_mask); + dump = __i915_gpu_coredump(gt, engine_mask, dump_flags); mutex_unlock(&capture_mutex); return dump; @@ -1997,11 +2097,11 @@ void i915_error_state_store(struct i915_gpu_coredump *error) * to pick up. */ void i915_capture_error_state(struct intel_gt *gt, - intel_engine_mask_t engine_mask) + intel_engine_mask_t engine_mask, u32 dump_flags) { struct i915_gpu_coredump *error; - error = i915_gpu_coredump(gt, engine_mask); + error = i915_gpu_coredump(gt, engine_mask, dump_flags); if (IS_ERR(error)) { cmpxchg(>->i915->gpu_error.first_error, NULL, error); return; diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index c3ccc8266865..cc08675064f6 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -53,6 +53,8 @@ struct i915_request_coredump { struct i915_sched_attr sched_attr; }; +struct __guc_capture_parsed_output; + struct intel_engine_coredump { const struct intel_engine_cs *engine; @@ -84,6 +86,10 @@ struct intel_engine_coredump { u32 rc_psmi; /* sleep state */ struct intel_instdone instdone; + /* GuC matched capture-lists info */ + struct intel_guc_state_capture *capture; + struct __guc_capture_parsed_output *guc_capture_node; + struct i915_gem_context_coredump { char comm[TASK_COMM_LEN]; @@ -124,7 +130,6 @@ struct intel_gt_coredump { u32 pgtbl_er; u32 ier; u32 gtier[6], ngtier; - u32 derrmr; u32 forcewake; u32 error; /* gen6+ */ u32 err_int; /* gen7 */ @@ -137,9 +142,12 @@ struct intel_gt_coredump { u32 gfx_mode; u32 gtt_cache; u32 aux_err; /* gen12 */ - u32 sfc_done[I915_MAX_SFC]; /* gen12 */ u32 gam_done; /* gen12 */ + /* Display related */ + u32 derrmr; + u32 sfc_done[I915_MAX_SFC]; /* gen12 */ + u32 nfence; u64 fence[I915_MAX_NUM_FENCES]; @@ -149,6 +157,7 @@ struct intel_gt_coredump { struct intel_uc_fw guc_fw; struct intel_uc_fw huc_fw; struct i915_vma_coredump *guc_log; + bool is_guc_capture; } *uc; struct intel_gt_coredump *next; @@ -221,24 +230,27 @@ static inline u32 i915_reset_engine_count(struct i915_gpu_error *error, return atomic_read(&error->reset_engine_count[engine->uabi_class]); } +#define CORE_DUMP_FLAG_NONE 0x0 +#define CORE_DUMP_FLAG_IS_GUC_CAPTURE BIT(0) + #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) __printf(2, 3) void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); struct i915_gpu_coredump *i915_gpu_coredump(struct intel_gt *gt, - intel_engine_mask_t engine_mask); + intel_engine_mask_t engine_mask, u32 dump_flags); void i915_capture_error_state(struct intel_gt *gt, - intel_engine_mask_t engine_mask); + intel_engine_mask_t engine_mask, u32 dump_flags); struct i915_gpu_coredump * i915_gpu_coredump_alloc(struct drm_i915_private *i915, gfp_t gfp); struct intel_gt_coredump * -intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp); +intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp, u32 dump_flags); struct intel_engine_coredump * -intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp); +intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_flags); struct intel_engine_capture_vma * intel_engine_coredump_add_request(struct intel_engine_coredump *ee, @@ -282,7 +294,7 @@ void i915_disable_error_state(struct drm_i915_private *i915, int err); #else static inline void -i915_capture_error_state(struct intel_gt *gt, intel_engine_mask_t engine_mask) +i915_capture_error_state(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags) { } @@ -293,13 +305,13 @@ i915_gpu_coredump_alloc(struct drm_i915_private *i915, gfp_t gfp) } static inline struct intel_gt_coredump * -intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp) +intel_gt_coredump_alloc(struct intel_gt *gt, gfp_t gfp, u32 dump_flags) { return NULL; } static inline struct intel_engine_coredump * -intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp) +intel_engine_coredump_alloc(struct intel_engine_cs *engine, gfp_t gfp, u32 dump_flags) { return NULL; } From a0f1f7b4f74fc6eaee0b6783af40dacf431df7b4 Mon Sep 17 00:00:00 2001 From: Alan Previn Date: Mon, 21 Mar 2022 09:45:27 -0700 Subject: [PATCH 00318/11454] drm/i915/guc: Print the GuC error capture output register list. Print the GuC captured error state register list (string names and values) when gpu_coredump_state printout is invoked via the i915 debugfs for flushing the gpu error-state that was captured prior. Since GuC could have reported multiple engine register dumps in a single notification event, parse the captured data (appearing as a stream of structures) to identify each dump as a different 'engine-capture-group-output'. Finally, for each 'engine-capture-group-output' that is found, verify if the engine register dump corresponds to the engine_coredump content that was previously populated by the i915_gpu_coredump function. That function would have copied the context's vma's including the bacth buffer during the G2H-context-reset notification that occurred earlier. Perform this verification check by comparing guc_id, lrca and engine- instance obtained from the 'engine-capture-group-output' vs a copy of that same info taken during i915_gpu_coredump. If they match, then print those vma's as well (such as the batch buffers). NOTE: the output format was verified using the gem_exec_capture IGT test. Signed-off-by: Alan Previn Reviewed-by: Umesh Nerlige Ramappa Signed-off-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220321164527.2500062-14-alan.previn.teres.alexis@intel.com --- drivers/gpu/drm/i915/gt/intel_engine_cs.c | 4 +- drivers/gpu/drm/i915/gt/uc/intel_guc.h | 3 + .../gpu/drm/i915/gt/uc/intel_guc_capture.c | 161 ++++++++++++++++++ .../gpu/drm/i915/gt/uc/intel_guc_capture.h | 2 +- .../gpu/drm/i915/gt/uc/intel_guc_submission.c | 6 +- drivers/gpu/drm/i915/i915_debugfs.c | 1 + drivers/gpu/drm/i915/i915_gpu_error.c | 16 +- drivers/gpu/drm/i915/i915_gpu_error.h | 5 + 8 files changed, 183 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_engine_cs.c b/drivers/gpu/drm/i915/gt/intel_engine_cs.c index 624117c55d1b..a3035a76747f 100644 --- a/drivers/gpu/drm/i915/gt/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/intel_engine_cs.c @@ -1712,9 +1712,7 @@ static void intel_engine_print_registers(struct intel_engine_cs *engine, drm_printf(m, "\tIPEHR: 0x%08x\n", ENGINE_READ(engine, IPEHR)); } - if (intel_engine_uses_guc(engine)) { - /* nothing to print yet */ - } else if (HAS_EXECLISTS(dev_priv)) { + if (HAS_EXECLISTS(dev_priv) && !intel_engine_uses_guc(engine)) { struct i915_request * const *port, *rq; const u32 *hws = &engine->status_page.addr[I915_HWS_CSB_BUF0_INDEX]; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc.h b/drivers/gpu/drm/i915/gt/uc/intel_guc.h index de32367831c6..4e431c14b118 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h @@ -438,6 +438,9 @@ int intel_guc_engine_failure_process_msg(struct intel_guc *guc, int intel_guc_error_capture_process_msg(struct intel_guc *guc, const u32 *msg, u32 len); +struct intel_engine_cs * +intel_guc_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance); + void intel_guc_find_hung_context(struct intel_engine_cs *engine); int intel_guc_global_policies_update(struct intel_guc *guc); diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index 59b4476697c6..afdcbe63e9eb 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -768,6 +768,21 @@ intel_guc_capture_output_min_size_est(struct intel_guc *guc) * intel_engine_coredump struct (if the context and * engine of the event notification matches a node * in the link list). + * + * User Sysfs / Debugfs + * -------------------- + * --> i915_gpu_coredump_copy_to_buffer-> + * L--> err_print_to_sgl --> err_print_gt + * L--> error_print_guc_captures + * L--> intel_guc_capture_print_node prints the + * register lists values of the attached node + * on the error-engine-dump being reported. + * L--> i915_reset_error_state ... -->__i915_gpu_coredump_free + * L--> ... cleanup_gt --> + * L--> intel_guc_capture_free_node returns the + * capture-output-node back to the internal + * cachelist for reuse. + * */ static int guc_capture_buf_cnt(struct __guc_capture_bufstate *buf) @@ -1385,9 +1400,155 @@ static void __guc_capture_process_output(struct intel_guc *guc) #if IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) +static const char * +guc_capture_reg_to_str(const struct intel_guc *guc, u32 owner, u32 type, + u32 class, u32 id, u32 offset, u32 *is_ext) +{ + const struct __guc_mmio_reg_descr_group *reglists = guc->capture->reglists; + struct __guc_mmio_reg_descr_group *extlists = guc->capture->extlists; + const struct __guc_mmio_reg_descr_group *match; + struct __guc_mmio_reg_descr_group *matchext; + int j; + + *is_ext = 0; + if (!reglists) + return NULL; + + match = guc_capture_get_one_list(reglists, owner, type, id); + if (!match) + return NULL; + + for (j = 0; j < match->num_regs; ++j) { + if (offset == match->list[j].reg.reg) + return match->list[j].regname; + } + if (extlists) { + matchext = guc_capture_get_one_ext_list(extlists, owner, type, id); + if (!matchext) + return NULL; + for (j = 0; j < matchext->num_regs; ++j) { + if (offset == matchext->extlist[j].reg.reg) { + *is_ext = 1; + return matchext->extlist[j].regname; + } + } + } + + return NULL; +} + +#ifdef CONFIG_DRM_I915_DEBUG_GUC +#define __out(a, ...) \ + do { \ + drm_warn((&(a)->i915->drm), __VA_ARGS__); \ + i915_error_printf((a), __VA_ARGS__); \ + } while (0) +#else +#define __out(a, ...) \ + i915_error_printf(a, __VA_ARGS__) +#endif + +#define GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng) \ + do { \ + __out(ebuf, " i915-Eng-Name: %s command stream\n", \ + (eng)->name); \ + __out(ebuf, " i915-Eng-Inst-Class: 0x%02x\n", (eng)->class); \ + __out(ebuf, " i915-Eng-Inst-Id: 0x%02x\n", (eng)->instance); \ + __out(ebuf, " i915-Eng-LogicalMask: 0x%08x\n", \ + (eng)->logical_mask); \ + } while (0) + +#define GCAP_PRINT_GUC_INST_INFO(ebuf, node) \ + do { \ + __out(ebuf, " GuC-Engine-Inst-Id: 0x%08x\n", \ + (node)->eng_inst); \ + __out(ebuf, " GuC-Context-Id: 0x%08x\n", (node)->guc_id); \ + __out(ebuf, " LRCA: 0x%08x\n", (node)->lrca); \ + } while (0) + int intel_guc_capture_print_engine_node(struct drm_i915_error_state_buf *ebuf, const struct intel_engine_coredump *ee) { + const char *grptype[GUC_STATE_CAPTURE_GROUP_TYPE_MAX] = { + "full-capture", + "partial-capture" + }; + const char *datatype[GUC_CAPTURE_LIST_TYPE_MAX] = { + "Global", + "Engine-Class", + "Engine-Instance" + }; + struct intel_guc_state_capture *cap; + struct __guc_capture_parsed_output *node; + struct intel_engine_cs *eng; + struct guc_mmio_reg *regs; + struct intel_guc *guc; + const char *str; + int numregs, i, j; + u32 is_ext; + + if (!ebuf || !ee) + return -EINVAL; + cap = ee->capture; + if (!cap || !ee->engine) + return -ENODEV; + + guc = &ee->engine->gt->uc.guc; + + __out(ebuf, "global --- GuC Error Capture on %s command stream:\n", + ee->engine->name); + + node = ee->guc_capture_node; + if (!node) { + __out(ebuf, " No matching ee-node\n"); + return 0; + } + + __out(ebuf, "Coverage: %s\n", grptype[node->is_partial]); + + for (i = GUC_CAPTURE_LIST_TYPE_GLOBAL; i < GUC_CAPTURE_LIST_TYPE_MAX; ++i) { + __out(ebuf, " RegListType: %s\n", + datatype[i % GUC_CAPTURE_LIST_TYPE_MAX]); + __out(ebuf, " Owner-Id: %d\n", node->reginfo[i].vfid); + + switch (i) { + case GUC_CAPTURE_LIST_TYPE_GLOBAL: + default: + break; + case GUC_CAPTURE_LIST_TYPE_ENGINE_CLASS: + __out(ebuf, " GuC-Eng-Class: %d\n", node->eng_class); + __out(ebuf, " i915-Eng-Class: %d\n", + guc_class_to_engine_class(node->eng_class)); + break; + case GUC_CAPTURE_LIST_TYPE_ENGINE_INSTANCE: + eng = intel_guc_lookup_engine(guc, node->eng_class, node->eng_inst); + if (eng) + GCAP_PRINT_INTEL_ENG_INFO(ebuf, eng); + else + __out(ebuf, " i915-Eng-Lookup Fail!\n"); + GCAP_PRINT_GUC_INST_INFO(ebuf, node); + break; + } + + numregs = node->reginfo[i].num_regs; + __out(ebuf, " NumRegs: %d\n", numregs); + j = 0; + while (numregs--) { + regs = node->reginfo[i].regs; + str = guc_capture_reg_to_str(guc, GUC_CAPTURE_LIST_INDEX_PF, i, + node->eng_class, 0, regs[j].offset, &is_ext); + if (!str) + __out(ebuf, " REG-0x%08x", regs[j].offset); + else + __out(ebuf, " %s", str); + if (is_ext) + __out(ebuf, "[%ld][%ld]", + FIELD_GET(GUC_REGSET_STEERING_GROUP, regs[j].flags), + FIELD_GET(GUC_REGSET_STEERING_INSTANCE, regs[j].flags)); + __out(ebuf, ": 0x%08x\n", regs[j].value); + ++j; + } + } return 0; } diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h index a8688928f88e..d3d7bd0b6db6 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.h @@ -10,8 +10,8 @@ struct drm_i915_error_state_buf; struct guc_gt_system_info; -struct intel_context; struct intel_engine_coredump; +struct intel_context; struct intel_gt; struct intel_guc; diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c index f797c49762c9..e1612c393781 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c @@ -4112,8 +4112,8 @@ int intel_guc_error_capture_process_msg(struct intel_guc *guc, return 0; } -static struct intel_engine_cs * -guc_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance) +struct intel_engine_cs * +intel_guc_lookup_engine(struct intel_guc *guc, u8 guc_class, u8 instance) { struct intel_gt *gt = guc_to_gt(guc); u8 engine_class = guc_class_to_engine_class(guc_class); @@ -4162,7 +4162,7 @@ int intel_guc_engine_failure_process_msg(struct intel_guc *guc, instance = msg[1]; reason = msg[2]; - engine = guc_lookup_engine(guc, guc_class, instance); + engine = intel_guc_lookup_engine(guc, guc_class, instance); if (unlikely(!engine)) { drm_err(>->i915->drm, "Invalid engine %d:%d", guc_class, instance); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 1279ea394af7..e6fcfde3ee38 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -308,6 +308,7 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file) gpu = NULL; with_intel_runtime_pm(&i915->runtime_pm, wakeref) gpu = i915_gpu_coredump(to_gt(i915), ALL_ENGINES, CORE_DUMP_FLAG_NONE); + if (IS_ERR(gpu)) return PTR_ERR(gpu); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index c76d8df4c190..f41eb4d12b34 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -530,8 +530,8 @@ __find_vma(struct i915_vma_coredump *vma, const char *name) return NULL; } -static struct i915_vma_coredump * -find_batch(const struct intel_engine_coredump *ee) +struct i915_vma_coredump * +intel_gpu_error_find_batch(const struct intel_engine_coredump *ee) { return __find_vma(ee->vma, "batch"); } @@ -559,7 +559,7 @@ static void error_print_engine(struct drm_i915_error_state_buf *m, error_print_instdone(m, ee); - batch = find_batch(ee); + batch = intel_gpu_error_find_batch(ee); if (batch) { u64 start = batch->gtt_offset; u64 end = start + batch->gtt_size; @@ -610,9 +610,9 @@ void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) va_end(args); } -static void print_error_vma(struct drm_i915_error_state_buf *m, - const struct intel_engine_cs *engine, - const struct i915_vma_coredump *vma) +void intel_gpu_error_print_vma(struct drm_i915_error_state_buf *m, + const struct intel_engine_cs *engine, + const struct i915_vma_coredump *vma) { char out[ASCII85_BUFSZ]; struct page *page; @@ -681,7 +681,7 @@ static void err_print_uc(struct drm_i915_error_state_buf *m, intel_uc_fw_dump(&error_uc->guc_fw, &p); intel_uc_fw_dump(&error_uc->huc_fw, &p); - print_error_vma(m, NULL, error_uc->guc_log); + intel_gpu_error_print_vma(m, NULL, error_uc->guc_log); } static void err_free_sgl(struct scatterlist *sgl) @@ -801,7 +801,7 @@ static void err_print_gt_engines(struct drm_i915_error_state_buf *m, error_print_context(m, " Active context: ", &ee->context); for (vma = ee->vma; vma; vma = vma->next) - print_error_vma(m, ee->engine, vma); + intel_gpu_error_print_vma(m, ee->engine, vma); } } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index cc08675064f6..09159ff01411 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -237,6 +237,11 @@ static inline u32 i915_reset_engine_count(struct i915_gpu_error *error, __printf(2, 3) void i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...); +void intel_gpu_error_print_vma(struct drm_i915_error_state_buf *m, + const struct intel_engine_cs *engine, + const struct i915_vma_coredump *vma); +struct i915_vma_coredump * +intel_gpu_error_find_batch(const struct intel_engine_coredump *ee); struct i915_gpu_coredump *i915_gpu_coredump(struct intel_gt *gt, intel_engine_mask_t engine_mask, u32 dump_flags); From 2db80f93869d491be57cbc2b36f30d0d3a0e5bde Mon Sep 17 00:00:00 2001 From: Niels Dossche Date: Mon, 21 Mar 2022 12:58:23 +0200 Subject: [PATCH 00319/11454] ath11k: acquire ab->base_lock in unassign when finding the peer by addr ath11k_peer_find_by_addr states via lockdep that ab->base_lock must be held when calling that function in order to protect the list. All callers except ath11k_mac_op_unassign_vif_chanctx have that lock acquired when calling ath11k_peer_find_by_addr. That lock is also not transitively held by a path towards ath11k_mac_op_unassign_vif_chanctx. The solution is to acquire the lock when calling ath11k_peer_find_by_addr inside ath11k_mac_op_unassign_vif_chanctx. I am currently working on a static analyser to detect missing locks and this was a reported case. I manually verified the report by looking at the code, but I do not have real hardware so this is compile tested only. Fixes: 701e48a43e15 ("ath11k: add packet log support for QCA6390") Signed-off-by: Niels Dossche Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220314215253.92658-1-dossche.niels@gmail.com --- drivers/net/wireless/ath/ath11k/mac.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 7cf1ea276e24..62d9558a8e85 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -7133,6 +7133,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, struct ath11k *ar = hw->priv; struct ath11k_base *ab = ar->ab; struct ath11k_vif *arvif = (void *)vif->drv_priv; + struct ath11k_peer *peer; int ret; mutex_lock(&ar->conf_mutex); @@ -7144,9 +7145,13 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, WARN_ON(!arvif->is_started); if (ab->hw_params.vdev_start_delay && - arvif->vdev_type == WMI_VDEV_TYPE_MONITOR && - ath11k_peer_find_by_addr(ab, ar->mac_addr)) - ath11k_peer_delete(ar, arvif->vdev_id, ar->mac_addr); + arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { + spin_lock_bh(&ab->base_lock); + peer = ath11k_peer_find_by_addr(ab, ar->mac_addr); + spin_unlock_bh(&ab->base_lock); + if (peer) + ath11k_peer_delete(ar, arvif->vdev_id, ar->mac_addr); + } if (arvif->vdev_type == WMI_VDEV_TYPE_MONITOR) { ret = ath11k_mac_monitor_stop(ar); From 7fb376ad7d3f200575b9f9374e21b39d30b57267 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 21 Mar 2022 13:03:23 +0200 Subject: [PATCH 00320/11454] ath11k: remove unused ATH11K_BD_IE_BOARD_EXT Currently ATH11K_BD_IE_BOARD_EXT is not used, so remove it. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220319023543.14288-2-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/hw.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 27ca4a9c20fc..1c701e16a3b5 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -293,7 +293,6 @@ enum ath11k_bd_ie_board_type { enum ath11k_bd_ie_type { /* contains sub IEs of enum ath11k_bd_ie_board_type */ ATH11K_BD_IE_BOARD = 0, - ATH11K_BD_IE_BOARD_EXT = 1, }; struct ath11k_hw_regs { From 0c104b6163e344e972dbbd255ca2441c171a8a87 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 21 Mar 2022 13:03:29 +0200 Subject: [PATCH 00321/11454] ath11k: disable regdb support for QCA6390 Currently it does not have regdb files for QCA6390, so disable its regdb support feature now. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-05266-QCAHSTSWPLZ_V2_TO_X86-1 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220319023543.14288-3-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 104149050205..700fd4ff62e4 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -219,7 +219,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .num_peers = 512, .supports_suspend = true, .hal_desc_sz = sizeof(struct hal_rx_desc_ipq8074), - .supports_regdb = true, + .supports_regdb = false, .fix_l1ss = true, .credit_flow = true, .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390, From 13da397f884d9c9a3fb6616206eeb6c6ab097287 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 28 Feb 2022 01:46:03 -0500 Subject: [PATCH 00322/11454] ath11k: add support for device recovery for QCA6390/WCN6855 Currently ath11k has device recovery logic, it is introduced by this patch "ath11k: Add support for subsystem recovery" which is upstream by https://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git/commit/?h=ath11k-bringup&id=3a7b4838b6f6f234239f263ef3dc02e612a083ad. The patch is for AHB devices such as IPQ8074, it has remote proc module which is used to download the firmware and boots the processor which firmware is running on. If firmware crashed, remote proc module will detect it and download and boot firmware again. Below command will trigger a firmware crash, and then user can test feature of device recovery. Test command: echo assert > /sys/kernel/debug/ath11k/qca6390\ hw2.0/simulate_fw_crash echo assert > /sys/kernel/debug/ath11k/wcn6855\ hw2.0/simulate_fw_crash Unfortunately, QCA6390 is PCIe bus, it does not have the remote proc module, it use mhi module to communicate between firmware and ath11k. So ath11k does not support device recovery for QCA6390 currently. This patch is to add the extra logic which is different for QCA6390. When firmware crashed, MHI_CB_EE_RDDM event will be indicate by firmware and then ath11k_mhi_op_status_cb which is the callback of mhi_controller will receive the MHI_CB_EE_RDDM event, then ath11k will start to do recovery process, ath11k_core_reset() calls ath11k_hif_power_down()/ath11k_hif_power_up(), then the mhi/ath11k will start to download and boot firmware. There are some logic to avoid deadloop recovery and two simultaneous recovery operations. And because it has muti-radios for the soc, so it add some logic in ath11k_mac_op_reconfig_complete() to make sure all radios has reconfig complete and then complete the device recovery. Also it add workqueue_aux, because ab->workqueue is used when receive ATH11K_QMI_EVENT_FW_READY in recovery process(queue_work(ab->workqueue, &ab->restart_work)), and ath11k_core_reset will wait for max ATH11K_RESET_TIMEOUT_HZ for the previous restart_work finished, if ath11k_core_reset also queued in ab->workqueue, then it will delay restart_work of previous recovery and lead previous recovery fail. ath11k recovery success for QCA6390/WCN6855 after apply this patch. Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1 Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03003-QCAHSPSWPL_V1_V2_SILICONZ_LITE-2 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220228064606.8981-2-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 68 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/core.h | 13 +++++ drivers/net/wireless/ath/ath11k/mac.c | 18 +++++++ drivers/net/wireless/ath/ath11k/mhi.c | 33 +++++++++++++ 4 files changed, 132 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 700fd4ff62e4..97ee3dd230ed 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1381,6 +1381,65 @@ static void ath11k_core_restart(struct work_struct *work) complete(&ab->driver_recovery); } +static void ath11k_core_reset(struct work_struct *work) +{ + struct ath11k_base *ab = container_of(work, struct ath11k_base, reset_work); + int reset_count, fail_cont_count; + long time_left; + + if (!(test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))) { + ath11k_warn(ab, "ignore reset dev flags 0x%lx\n", ab->dev_flags); + return; + } + + /* Sometimes the recovery will fail and then the next all recovery fail, + * this is to avoid infinite recovery since it can not recovery success. + */ + fail_cont_count = atomic_read(&ab->fail_cont_count); + + if (fail_cont_count >= ATH11K_RESET_MAX_FAIL_COUNT_FINAL) + return; + + if (fail_cont_count >= ATH11K_RESET_MAX_FAIL_COUNT_FIRST && + time_before(jiffies, ab->reset_fail_timeout)) + return; + + reset_count = atomic_inc_return(&ab->reset_count); + + if (reset_count > 1) { + /* Sometimes it happened another reset worker before the previous one + * completed, then the second reset worker will destroy the previous one, + * thus below is to avoid that. + */ + ath11k_warn(ab, "already reseting count %d\n", reset_count); + + reinit_completion(&ab->reset_complete); + time_left = wait_for_completion_timeout(&ab->reset_complete, + ATH11K_RESET_TIMEOUT_HZ); + + if (time_left) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, "to skip reset\n"); + atomic_dec(&ab->reset_count); + return; + } + + ab->reset_fail_timeout = jiffies + ATH11K_RESET_FAIL_TIMEOUT_HZ; + /* Record the continuous recovery fail count when recovery failed*/ + atomic_inc(&ab->fail_cont_count); + } + + ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset starting\n"); + + ab->is_reset = true; + atomic_set(&ab->recovery_count, 0); + + ath11k_hif_power_down(ab); + ath11k_qmi_free_resource(ab); + ath11k_hif_power_up(ab); + + ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset started\n"); +} + static int ath11k_init_hw_params(struct ath11k_base *ab) { const struct ath11k_hw_params *hw_params = NULL; @@ -1450,6 +1509,7 @@ EXPORT_SYMBOL(ath11k_core_deinit); void ath11k_core_free(struct ath11k_base *ab) { + destroy_workqueue(ab->workqueue_aux); destroy_workqueue(ab->workqueue); kfree(ab); @@ -1472,9 +1532,14 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, if (!ab->workqueue) goto err_sc_free; + ab->workqueue_aux = create_singlethread_workqueue("ath11k_aux_wq"); + if (!ab->workqueue_aux) + goto err_free_wq; + mutex_init(&ab->core_lock); spin_lock_init(&ab->base_lock); mutex_init(&ab->vdev_id_11d_lock); + init_completion(&ab->reset_complete); INIT_LIST_HEAD(&ab->peers); init_waitqueue_head(&ab->peer_mapping_wq); @@ -1483,6 +1548,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, INIT_WORK(&ab->restart_work, ath11k_core_restart); INIT_WORK(&ab->update_11d_work, ath11k_update_11d); INIT_WORK(&ab->rfkill_work, ath11k_rfkill_work); + INIT_WORK(&ab->reset_work, ath11k_core_reset); timer_setup(&ab->rx_replenish_retry, ath11k_ce_rx_replenish_retry, 0); init_completion(&ab->htc_suspend); init_completion(&ab->wow.wakeup_completed); @@ -1493,6 +1559,8 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, return ab; +err_free_wq: + destroy_workqueue(ab->workqueue); err_sc_free: kfree(ab); return NULL; diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index e556beb945ac..bd31413d84ca 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -40,6 +40,10 @@ extern unsigned int ath11k_frame_mode; #define ATH11K_MON_TIMER_INTERVAL 10 +#define ATH11K_RESET_TIMEOUT_HZ (20 * HZ) +#define ATH11K_RESET_MAX_FAIL_COUNT_FIRST 3 +#define ATH11K_RESET_MAX_FAIL_COUNT_FINAL 5 +#define ATH11K_RESET_FAIL_TIMEOUT_HZ (20 * HZ) enum ath11k_supported_bw { ATH11K_BW_20 = 0, @@ -820,6 +824,15 @@ struct ath11k_base { struct work_struct restart_work; struct work_struct update_11d_work; u8 new_alpha2[3]; + struct workqueue_struct *workqueue_aux; + struct work_struct reset_work; + atomic_t reset_count; + atomic_t recovery_count; + bool is_reset; + struct completion reset_complete; + /* continuous recovery fail count */ + atomic_t fail_cont_count; + unsigned long reset_fail_timeout; struct { /* protected by data_lock */ u32 fw_crash_counter; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 62d9558a8e85..f2979dc00fdb 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -7915,6 +7915,8 @@ ath11k_mac_op_reconfig_complete(struct ieee80211_hw *hw, enum ieee80211_reconfig_type reconfig_type) { struct ath11k *ar = hw->priv; + struct ath11k_base *ab = ar->ab; + int recovery_count; if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) return; @@ -7926,6 +7928,22 @@ ath11k_mac_op_reconfig_complete(struct ieee80211_hw *hw, ar->pdev->pdev_id); ar->state = ATH11K_STATE_ON; ieee80211_wake_queues(ar->hw); + + if (ab->is_reset) { + recovery_count = atomic_inc_return(&ab->recovery_count); + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "recovery count %d\n", recovery_count); + /* When there are multiple radios in an SOC, + * the recovery has to be done for each radio + */ + if (recovery_count == ab->num_radios) { + atomic_dec(&ab->reset_count); + complete(&ab->reset_complete); + ab->is_reset = false; + atomic_set(&ab->fail_cont_count, 0); + ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset success\n"); + } + } } mutex_unlock(&ar->conf_mutex); diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c index fc3524e83e52..61d83be4841f 100644 --- a/drivers/net/wireless/ath/ath11k/mhi.c +++ b/drivers/net/wireless/ath/ath11k/mhi.c @@ -292,15 +292,48 @@ static void ath11k_mhi_op_runtime_put(struct mhi_controller *mhi_cntrl) { } +static char *ath11k_mhi_op_callback_to_str(enum mhi_callback reason) +{ + switch (reason) { + case MHI_CB_IDLE: + return "MHI_CB_IDLE"; + case MHI_CB_PENDING_DATA: + return "MHI_CB_PENDING_DATA"; + case MHI_CB_LPM_ENTER: + return "MHI_CB_LPM_ENTER"; + case MHI_CB_LPM_EXIT: + return "MHI_CB_LPM_EXIT"; + case MHI_CB_EE_RDDM: + return "MHI_CB_EE_RDDM"; + case MHI_CB_EE_MISSION_MODE: + return "MHI_CB_EE_MISSION_MODE"; + case MHI_CB_SYS_ERROR: + return "MHI_CB_SYS_ERROR"; + case MHI_CB_FATAL_ERROR: + return "MHI_CB_FATAL_ERROR"; + case MHI_CB_BW_REQ: + return "MHI_CB_BW_REQ"; + default: + return "UNKNOWN"; + } +}; + static void ath11k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl, enum mhi_callback cb) { struct ath11k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev); + ath11k_dbg(ab, ATH11K_DBG_BOOT, "mhi notify status reason %s\n", + ath11k_mhi_op_callback_to_str(cb)); + switch (cb) { case MHI_CB_SYS_ERROR: ath11k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n"); break; + case MHI_CB_EE_RDDM: + if (!(test_bit(ATH11K_FLAG_UNREGISTERING, &ab->dev_flags))) + queue_work(ab->workqueue_aux, &ab->reset_work); + break; default: break; } From 38194f3a605e4a961f28bc38a73a4f4d43123968 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 21 Mar 2022 13:16:57 +0200 Subject: [PATCH 00323/11454] ath11k: add synchronization operation between reconfigure of mac80211 and ath11k_base ieee80211_reconfig() of mac80211 is the main function for recovery of each ieee80211_hw and ath11k, and ath11k_core_reconfigure_on_crash() is the main function for recovery of ath11k_base, it has more than one ieee80211_hw and ath11k for each ath11k_base, so it need to add synchronization between them, otherwise it has many issue. For example, when ath11k_core_reconfigure_on_crash() is not complete, mac80211 send a hw scan request to ath11k, it leads firmware crash, because firmware has not been initialized at that moment, firmware is only finished downloaded and loaded, it can not receive scan command. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03003-QCAHSPSWPL_V1_V2_SILICONZ_LITE-2 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220228064606.8981-3-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 51 ++++++++++++++++++++++---- drivers/net/wireless/ath/ath11k/core.h | 5 +++ drivers/net/wireless/ath/ath11k/mac.c | 22 +++++++++++ 3 files changed, 70 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 97ee3dd230ed..612efaeabcf4 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1302,12 +1302,11 @@ static void ath11k_update_11d(struct work_struct *work) } } -static void ath11k_core_restart(struct work_struct *work) +static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) { - struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work); struct ath11k *ar; struct ath11k_pdev *pdev; - int i, ret = 0; + int i; spin_lock_bh(&ab->base_lock); ab->stats.fw_crash_counter++; @@ -1340,12 +1339,13 @@ static void ath11k_core_restart(struct work_struct *work) wake_up(&ab->wmi_ab.tx_credits_wq); wake_up(&ab->peer_mapping_wq); +} - ret = ath11k_core_reconfigure_on_crash(ab); - if (ret) { - ath11k_err(ab, "failed to reconfigure driver on crash recovery\n"); - return; - } +static void ath11k_core_post_reconfigure_recovery(struct ath11k_base *ab) +{ + struct ath11k *ar; + struct ath11k_pdev *pdev; + int i; for (i = 0; i < ab->num_radios; i++) { pdev = &ab->pdevs[i]; @@ -1381,6 +1381,27 @@ static void ath11k_core_restart(struct work_struct *work) complete(&ab->driver_recovery); } +static void ath11k_core_restart(struct work_struct *work) +{ + struct ath11k_base *ab = container_of(work, struct ath11k_base, restart_work); + int ret; + + if (!ab->is_reset) + ath11k_core_pre_reconfigure_recovery(ab); + + ret = ath11k_core_reconfigure_on_crash(ab); + if (ret) { + ath11k_err(ab, "failed to reconfigure driver on crash recovery\n"); + return; + } + + if (ab->is_reset) + complete_all(&ab->reconfigure_complete); + + if (!ab->is_reset) + ath11k_core_post_reconfigure_recovery(ab); +} + static void ath11k_core_reset(struct work_struct *work) { struct ath11k_base *ab = container_of(work, struct ath11k_base, reset_work); @@ -1432,6 +1453,18 @@ static void ath11k_core_reset(struct work_struct *work) ab->is_reset = true; atomic_set(&ab->recovery_count, 0); + reinit_completion(&ab->recovery_start); + atomic_set(&ab->recovery_start_count, 0); + + ath11k_core_pre_reconfigure_recovery(ab); + + reinit_completion(&ab->reconfigure_complete); + ath11k_core_post_reconfigure_recovery(ab); + + ath11k_dbg(ab, ATH11K_DBG_BOOT, "waiting recovery start...\n"); + + time_left = wait_for_completion_timeout(&ab->recovery_start, + ATH11K_RECOVER_START_TIMEOUT_HZ); ath11k_hif_power_down(ab); ath11k_qmi_free_resource(ab); @@ -1540,6 +1573,8 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, spin_lock_init(&ab->base_lock); mutex_init(&ab->vdev_id_11d_lock); init_completion(&ab->reset_complete); + init_completion(&ab->reconfigure_complete); + init_completion(&ab->recovery_start); INIT_LIST_HEAD(&ab->peers); init_waitqueue_head(&ab->peer_mapping_wq); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index bd31413d84ca..70eb6e418422 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -44,6 +44,8 @@ extern unsigned int ath11k_frame_mode; #define ATH11K_RESET_MAX_FAIL_COUNT_FIRST 3 #define ATH11K_RESET_MAX_FAIL_COUNT_FINAL 5 #define ATH11K_RESET_FAIL_TIMEOUT_HZ (20 * HZ) +#define ATH11K_RECONFIGURE_TIMEOUT_HZ (10 * HZ) +#define ATH11K_RECOVER_START_TIMEOUT_HZ (20 * HZ) enum ath11k_supported_bw { ATH11K_BW_20 = 0, @@ -828,8 +830,11 @@ struct ath11k_base { struct work_struct reset_work; atomic_t reset_count; atomic_t recovery_count; + atomic_t recovery_start_count; bool is_reset; struct completion reset_complete; + struct completion reconfigure_complete; + struct completion recovery_start; /* continuous recovery fail count */ atomic_t fail_cont_count; unsigned long reset_fail_timeout; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index f2979dc00fdb..34a62933ccd2 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -5749,6 +5749,27 @@ static int ath11k_mac_config_mon_status_default(struct ath11k *ar, bool enable) return ret; } +static void ath11k_mac_wait_reconfigure(struct ath11k_base *ab) +{ + int recovery_start_count; + + if (!ab->is_reset) + return; + + recovery_start_count = atomic_inc_return(&ab->recovery_start_count); + ath11k_dbg(ab, ATH11K_DBG_MAC, "recovery start count %d\n", recovery_start_count); + + if (recovery_start_count == ab->num_radios) { + complete(&ab->recovery_start); + ath11k_dbg(ab, ATH11K_DBG_MAC, "recovery started success\n"); + } + + ath11k_dbg(ab, ATH11K_DBG_MAC, "waiting reconfigure...\n"); + + wait_for_completion_timeout(&ab->reconfigure_complete, + ATH11K_RECONFIGURE_TIMEOUT_HZ); +} + static int ath11k_mac_op_start(struct ieee80211_hw *hw) { struct ath11k *ar = hw->priv; @@ -5765,6 +5786,7 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) break; case ATH11K_STATE_RESTARTING: ar->state = ATH11K_STATE_RESTARTED; + ath11k_mac_wait_reconfigure(ab); break; case ATH11K_STATE_RESTARTED: case ATH11K_STATE_WEDGED: From 78e3e6094220a71504e7136c42b49fc8ed3a72b4 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 21 Mar 2022 13:17:03 +0200 Subject: [PATCH 00324/11454] ath11k: Add hw-restart option to simulate_fw_crash Add hw-restart to directly restart wlan. Like UTF mode start it will restart hardware and download firmware again. Usage: 1. Run command: echo hw-restart > /sys/kernel/debug/ath11k/qca6390\ hw2.0/simulate_fw_crash echo hw-restart > /sys/kernel/debug/ath11k/wcn6855\ hw2.0/simulate_fw_crash 2. wlan will be restart and do recovery process and success. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03003-QCAHSPSWPL_V1_V2_SILICONZ_LITE-2 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220228064606.8981-4-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/debugfs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c index a82266c8befc..9648e0017393 100644 --- a/drivers/net/wireless/ath/ath11k/debugfs.c +++ b/drivers/net/wireless/ath/ath11k/debugfs.c @@ -596,6 +596,10 @@ static ssize_t ath11k_write_simulate_fw_crash(struct file *file, ret = ath11k_wmi_force_fw_hang_cmd(ar, ATH11K_WMI_FW_HANG_ASSERT_TYPE, ATH11K_WMI_FW_HANG_DELAY); + } else if (!strcmp(buf, "hw-restart")) { + ath11k_info(ab, "user requested hw restart\n"); + queue_work(ab->workqueue_aux, &ab->reset_work); + ret = 0; } else { ret = -EINVAL; goto exit; From 0d7a8a6204ea9271f1d0a8c66a9fd2f54d2e3cbc Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 21 Mar 2022 13:17:08 +0200 Subject: [PATCH 00325/11454] ath11k: fix the warning of dev_wake in mhi_pm_disable_transition() When test device recovery with below command, it has warning in message as below. echo assert > /sys/kernel/debug/ath11k/wcn6855\ hw2.0/simulate_fw_crash echo assert > /sys/kernel/debug/ath11k/qca6390\ hw2.0/simulate_fw_crash warning message: [ 1965.642121] ath11k_pci 0000:06:00.0: simulating firmware assert crash [ 1968.471364] ieee80211 phy0: Hardware restart was requested [ 1968.511305] ------------[ cut here ]------------ [ 1968.511368] WARNING: CPU: 3 PID: 1546 at drivers/bus/mhi/core/pm.c:505 mhi_pm_disable_transition+0xb37/0xda0 [mhi] [ 1968.511443] Modules linked in: ath11k_pci ath11k mac80211 libarc4 cfg80211 qmi_helpers qrtr_mhi mhi qrtr nvme nvme_core [ 1968.511563] CPU: 3 PID: 1546 Comm: kworker/u17:0 Kdump: loaded Tainted: G W 5.17.0-rc3-wt-ath+ #579 [ 1968.511629] Hardware name: Intel(R) Client Systems NUC8i7HVK/NUC8i7HVB, BIOS HNKBLi70.86A.0067.2021.0528.1339 05/28/2021 [ 1968.511704] Workqueue: mhi_hiprio_wq mhi_pm_st_worker [mhi] [ 1968.511787] RIP: 0010:mhi_pm_disable_transition+0xb37/0xda0 [mhi] [ 1968.511870] Code: a9 fe ff ff 4c 89 ff 44 89 04 24 e8 03 46 f6 e5 44 8b 04 24 41 83 f8 01 0f 84 21 fe ff ff e9 4c fd ff ff 0f 0b e9 af f8 ff ff <0f> 0b e9 5c f8 ff ff 48 89 df e8 da 9e ee e3 e9 12 fd ff ff 4c 89 [ 1968.511923] RSP: 0018:ffffc900024efbf0 EFLAGS: 00010286 [ 1968.511969] RAX: 00000000ffffffff RBX: ffff88811d241250 RCX: ffffffffc0176922 [ 1968.512014] RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffff888118a90a24 [ 1968.512059] RBP: ffff888118a90800 R08: 0000000000000000 R09: ffff888118a90a27 [ 1968.512102] R10: ffffed1023152144 R11: 0000000000000001 R12: ffff888118a908ac [ 1968.512229] R13: ffff888118a90928 R14: dffffc0000000000 R15: ffff888118a90a24 [ 1968.512310] FS: 0000000000000000(0000) GS:ffff888234200000(0000) knlGS:0000000000000000 [ 1968.512405] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1968.512493] CR2: 00007f5538f443a8 CR3: 000000016dc28001 CR4: 00000000003706e0 [ 1968.512587] Call Trace: [ 1968.512672] [ 1968.512751] ? _raw_spin_unlock_irq+0x1f/0x40 [ 1968.512859] mhi_pm_st_worker+0x3ac/0x790 [mhi] [ 1968.512959] ? mhi_pm_mission_mode_transition.isra.0+0x7d0/0x7d0 [mhi] [ 1968.513063] process_one_work+0x86a/0x1400 [ 1968.513184] ? pwq_dec_nr_in_flight+0x230/0x230 [ 1968.513312] ? move_linked_works+0x125/0x290 [ 1968.513416] worker_thread+0x6db/0xf60 [ 1968.513536] ? process_one_work+0x1400/0x1400 [ 1968.513627] kthread+0x241/0x2d0 [ 1968.513733] ? kthread_complete_and_exit+0x20/0x20 [ 1968.513821] ret_from_fork+0x22/0x30 [ 1968.513924] Reason is mhi_deassert_dev_wake() from mhi_device_put() is called but mhi_assert_dev_wake() from __mhi_device_get_sync() is not called in progress of recovery. Commit 8e0559921f9a ("bus: mhi: core: Skip device wake in error or shutdown state") add check for the pm_state of mhi in __mhi_device_get_sync(), and the pm_state is not the normal state untill recovery is completed, so it leads the dev_wake is not 0 and above warning print in mhi_pm_disable_transition() while checking mhi_cntrl->dev_wake. Add check in ath11k_pci_write32()/ath11k_pci_read32() to skip call mhi_device_put() if mhi_device_get_sync() does not really do wake, then the warning gone. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03003-QCAHSPSWPL_V1_V2_SILICONZ_LITE-2 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220228064606.8981-5-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/pci.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c index 903758751c99..8a3ff12057e8 100644 --- a/drivers/net/wireless/ath/ath11k/pci.c +++ b/drivers/net/wireless/ath/ath11k/pci.c @@ -191,6 +191,7 @@ void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value) { struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); u32 window_start; + int ret = 0; /* for offset beyond BAR + 4K - 32, may * need to wakeup MHI to access. @@ -198,7 +199,7 @@ void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value) if (ab->hw_params.wakeup_mhi && test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && offset >= ACCESS_ALWAYS_OFF) - mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); + ret = mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); if (offset < WINDOW_START) { iowrite32(value, ab->mem + offset); @@ -222,7 +223,8 @@ void ath11k_pci_write32(struct ath11k_base *ab, u32 offset, u32 value) if (ab->hw_params.wakeup_mhi && test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && - offset >= ACCESS_ALWAYS_OFF) + offset >= ACCESS_ALWAYS_OFF && + !ret) mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); } @@ -230,6 +232,7 @@ u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset) { struct ath11k_pci *ab_pci = ath11k_pci_priv(ab); u32 val, window_start; + int ret = 0; /* for offset beyond BAR + 4K - 32, may * need to wakeup MHI to access. @@ -237,7 +240,7 @@ u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset) if (ab->hw_params.wakeup_mhi && test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && offset >= ACCESS_ALWAYS_OFF) - mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); + ret = mhi_device_get_sync(ab_pci->mhi_ctrl->mhi_dev); if (offset < WINDOW_START) { val = ioread32(ab->mem + offset); @@ -261,7 +264,8 @@ u32 ath11k_pci_read32(struct ath11k_base *ab, u32 offset) if (ab->hw_params.wakeup_mhi && test_bit(ATH11K_PCI_FLAG_INIT_DONE, &ab_pci->flags) && - offset >= ACCESS_ALWAYS_OFF) + offset >= ACCESS_ALWAYS_OFF && + !ret) mhi_device_put(ab_pci->mhi_ctrl->mhi_dev); return val; From 1e4ac7173c9394de7f54a4a861377ac3f030c614 Mon Sep 17 00:00:00 2001 From: Baochen Qiang Date: Mon, 11 Oct 2021 13:56:02 +0800 Subject: [PATCH 00326/11454] ath11k: enable PLATFORM_CAP_PCIE_GLOBAL_RESET QMI host capability In Qualcomm ARM platforms there is WL_EN pin and other power regulators which can be controlled at platform side to completely reset the chip. For most of x86 and other platforms, the chip is connected via PCIe M.2 interface, and there is no way to control WL_EN pin. Instead the host driver needs to reset the chip via PCIE_SOC_GLOBAL_RESET hardware register, just like ath11k does currently. But when using PCIE_SOC_GLOBAL_RESET there are some hardware registers which are not cleared/restored. To handle those cases we can enable PLATFORM_CAP_PCIE_GLOBAL_RESET QMI host capability to tell the firmware to do some platform specific operations after firmware download. This does not fix any known issues, but is recommended by the firmware team, so enable the capability on QCA6390 and WCN6855 PCI devices. It is currently unclear if this should be enabled also on QCN9074, so leave it disabled for now. On AHB devices this is not needed as they don't use PCIE_SOC_GLOBAL_RESET. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-01720.1-QCAHSPSWPL_V1_V2_SILICONZ_LITE-1 Signed-off-by: Baochen Qiang Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20211011055602.77342-1-bqiang@codeaurora.org --- drivers/net/wireless/ath/ath11k/core.c | 6 ++++++ drivers/net/wireless/ath/ath11k/hw.h | 1 + drivers/net/wireless/ath/ath11k/qmi.c | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 612efaeabcf4..9cfba73b9e22 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -100,6 +100,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .fw_wmi_diag_event = false, .current_cc_support = false, .dbr_debug_support = true, + .global_reset = false, }, { .hw_rev = ATH11K_HW_IPQ6018_HW10, @@ -166,6 +167,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .fw_wmi_diag_event = false, .current_cc_support = false, .dbr_debug_support = true, + .global_reset = false, }, { .name = "qca6390 hw2.0", @@ -231,6 +233,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .fw_wmi_diag_event = true, .current_cc_support = true, .dbr_debug_support = false, + .global_reset = true, }, { .name = "qcn9074 hw1.0", @@ -296,6 +299,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .fw_wmi_diag_event = false, .current_cc_support = false, .dbr_debug_support = true, + .global_reset = false, }, { .name = "wcn6855 hw2.0", @@ -361,6 +365,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .fw_wmi_diag_event = true, .current_cc_support = true, .dbr_debug_support = false, + .global_reset = true, }, { .name = "wcn6855 hw2.1", @@ -425,6 +430,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = { .fw_wmi_diag_event = true, .current_cc_support = true, .dbr_debug_support = false, + .global_reset = true, }, }; diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 1c701e16a3b5..5955c6f5da24 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -194,6 +194,7 @@ struct ath11k_hw_params { bool fw_wmi_diag_event; bool current_cc_support; bool dbr_debug_support; + bool global_reset; }; struct ath11k_hw_ops { diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index ec110fe81378..ffb8aa7dfb02 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -15,6 +15,7 @@ #define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02 #define HOST_CSTATE_BIT 0x04 +#define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08 #define FW_BUILD_ID_MASK "QC_IMAGE_VERSION_STRING=" @@ -1676,6 +1677,9 @@ static int ath11k_qmi_host_cap_send(struct ath11k_base *ab) req.nm_modem |= SLEEP_CLOCK_SELECT_INTERNAL_BIT; } + if (ab->hw_params.global_reset) + req.nm_modem |= PLATFORM_CAP_PCIE_GLOBAL_RESET; + ath11k_dbg(ab, ATH11K_DBG_QMI, "qmi host cap request\n"); ret = qmi_txn_init(&ab->qmi.handle, &txn, From c89717bd0a0f4fd35e86ea26072de608482a7710 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Tue, 22 Mar 2022 14:17:36 +0100 Subject: [PATCH 00327/11454] drm/gma500: Use managed drmm_mode_config_init() Signed-off-by: Patrik Jakobsson Reviewed-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220322131742.11566-1-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/framebuffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 45df9de22007..2b99c996fdc2 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -514,7 +514,8 @@ void psb_modeset_init(struct drm_device *dev) struct pci_dev *pdev = to_pci_dev(dev->dev); int i; - drm_mode_config_init(dev); + if (drmm_mode_config_init(dev)) + return; dev->mode_config.min_width = 0; dev->mode_config.min_height = 0; @@ -546,6 +547,5 @@ void psb_modeset_cleanup(struct drm_device *dev) if (dev_priv->modeset) { drm_kms_helper_poll_fini(dev); psb_fbdev_fini(dev); - drm_mode_config_cleanup(dev); } } From 3e712b3cfb580752e5d0f848883bf2d074f09bdd Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Tue, 22 Mar 2022 14:17:37 +0100 Subject: [PATCH 00328/11454] drm/gma500: Uninstall interrupts on driver removal Reloading the driver revealed that the interrupt handler never got uninstalled. Signed-off-by: Patrik Jakobsson Reviewed-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220322131742.11566-2-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/psb_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index 82d51e9821ad..b231fddb8817 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -173,6 +173,8 @@ static void psb_driver_unload(struct drm_device *dev) gma_backlight_exit(dev); psb_modeset_cleanup(dev); + gma_irq_uninstall(dev); + if (dev_priv->ops->chip_teardown) dev_priv->ops->chip_teardown(dev); From b1a7d0ddb169774c3db5afe9e64124daea7fdd9f Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Tue, 22 Mar 2022 14:17:38 +0100 Subject: [PATCH 00329/11454] drm/gma500: Make use of the drm connector iterator This makes sure we're using proper locking when iterating the list of connectors. Signed-off-by: Patrik Jakobsson Reviewed-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220322131742.11566-3-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/cdv_device.c | 10 ++++++-- drivers/gpu/drm/gma500/cdv_intel_display.c | 9 +++++-- drivers/gpu/drm/gma500/framebuffer.c | 6 +++-- drivers/gpu/drm/gma500/gma_display.c | 16 ++++++++----- drivers/gpu/drm/gma500/oaktrail_crtc.c | 17 ++++++++----- drivers/gpu/drm/gma500/oaktrail_lvds.c | 15 ++++++------ drivers/gpu/drm/gma500/psb_device.c | 28 +++++++++++++++------- drivers/gpu/drm/gma500/psb_drv.c | 10 ++++---- drivers/gpu/drm/gma500/psb_intel_display.c | 15 ++++++++---- 9 files changed, 84 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c index f854f58bcbb3..dd32b484dd82 100644 --- a/drivers/gpu/drm/gma500/cdv_device.c +++ b/drivers/gpu/drm/gma500/cdv_device.c @@ -262,6 +262,7 @@ static int cdv_save_display_registers(struct drm_device *dev) struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); struct psb_save_area *regs = &dev_priv->regs; + struct drm_connector_list_iter conn_iter; struct drm_connector *connector; dev_dbg(dev->dev, "Saving GPU registers.\n"); @@ -298,8 +299,10 @@ static int cdv_save_display_registers(struct drm_device *dev) regs->cdv.saveIER = REG_READ(PSB_INT_ENABLE_R); regs->cdv.saveIMR = REG_READ(PSB_INT_MASK_R); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) connector->funcs->dpms(connector, DRM_MODE_DPMS_OFF); + drm_connector_list_iter_end(&conn_iter); return 0; } @@ -317,6 +320,7 @@ static int cdv_restore_display_registers(struct drm_device *dev) struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct pci_dev *pdev = to_pci_dev(dev->dev); struct psb_save_area *regs = &dev_priv->regs; + struct drm_connector_list_iter conn_iter; struct drm_connector *connector; u32 temp; @@ -373,8 +377,10 @@ static int cdv_restore_display_registers(struct drm_device *dev) drm_mode_config_reset(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, head) + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) connector->funcs->dpms(connector, DRM_MODE_DPMS_ON); + drm_connector_list_iter_end(&conn_iter); /* Resume the modeset for every activated CRTC */ drm_helper_resume_force_mode(dev); diff --git a/drivers/gpu/drm/gma500/cdv_intel_display.c b/drivers/gpu/drm/gma500/cdv_intel_display.c index 94ebc48a4349..0c3ddcdc29dc 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_display.c +++ b/drivers/gpu/drm/gma500/cdv_intel_display.c @@ -584,13 +584,14 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, bool ok; bool is_lvds = false; bool is_dp = false; - struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector_list_iter conn_iter; struct drm_connector *connector; const struct gma_limit_t *limit; u32 ddi_select = 0; bool is_edp = false; - list_for_each_entry(connector, &mode_config->connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { struct gma_encoder *gma_encoder = gma_attached_encoder(connector); @@ -613,10 +614,14 @@ static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc, is_edp = true; break; default: + drm_connector_list_iter_end(&conn_iter); DRM_ERROR("invalid output type.\n"); return 0; } + + break; } + drm_connector_list_iter_end(&conn_iter); if (dev_priv->dplla_96mhz) /* low-end sku, 96/100 mhz */ diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 2b99c996fdc2..0ac6ea5fd3a1 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c @@ -451,6 +451,7 @@ static const struct drm_mode_config_funcs psb_mode_funcs = { static void psb_setup_outputs(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct drm_connector_list_iter conn_iter; struct drm_connector *connector; drm_mode_create_scaling_mode_property(dev); @@ -461,8 +462,8 @@ static void psb_setup_outputs(struct drm_device *dev) "backlight", 0, 100); dev_priv->ops->output_init(dev); - list_for_each_entry(connector, &dev->mode_config.connector_list, - head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { struct gma_encoder *gma_encoder = gma_attached_encoder(connector); struct drm_encoder *encoder = &gma_encoder->base; int crtc_mask = 0, clone_mask = 0; @@ -505,6 +506,7 @@ static void psb_setup_outputs(struct drm_device *dev) encoder->possible_clones = gma_connector_clones(dev, clone_mask); } + drm_connector_list_iter_end(&conn_iter); } void psb_modeset_init(struct drm_device *dev) diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 1d7964c339f4..e8157464d9eb 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -27,17 +27,21 @@ bool gma_pipe_has_type(struct drm_crtc *crtc, int type) { struct drm_device *dev = crtc->dev; - struct drm_mode_config *mode_config = &dev->mode_config; - struct drm_connector *l_entry; + struct drm_connector_list_iter conn_iter; + struct drm_connector *connector; - list_for_each_entry(l_entry, &mode_config->connector_list, head) { - if (l_entry->encoder && l_entry->encoder->crtc == crtc) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + if (connector->encoder && connector->encoder->crtc == crtc) { struct gma_encoder *gma_encoder = - gma_attached_encoder(l_entry); - if (gma_encoder->type == type) + gma_attached_encoder(connector); + if (gma_encoder->type == type) { + drm_connector_list_iter_end(&conn_iter); return true; + } } } + drm_connector_list_iter_end(&conn_iter); return false; } diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c index 79fc602b35bc..22398d34853a 100644 --- a/drivers/gpu/drm/gma500/oaktrail_crtc.c +++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c @@ -372,9 +372,9 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, bool ok, is_sdvo = false; bool is_lvds = false; bool is_mipi = false; - struct drm_mode_config *mode_config = &dev->mode_config; struct gma_encoder *gma_encoder = NULL; uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; + struct drm_connector_list_iter conn_iter; struct drm_connector *connector; int i; int need_aux = gma_pipe_has_type(crtc, INTEL_OUTPUT_SDVO) ? 1 : 0; @@ -388,7 +388,8 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, drm_mode_copy(&gma_crtc->saved_mode, mode); drm_mode_copy(&gma_crtc->saved_adjusted_mode, adjusted_mode); - list_for_each_entry(connector, &mode_config->connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { if (!connector->encoder || connector->encoder->crtc != crtc) continue; @@ -405,8 +406,16 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, is_mipi = true; break; } + + break; } + if (gma_encoder) + drm_object_property_get_value(&connector->base, + dev->mode_config.scaling_mode_property, &scalingType); + + drm_connector_list_iter_end(&conn_iter); + /* Disable the VGA plane that we never use */ for (i = 0; i <= need_aux; i++) REG_WRITE_WITH_AUX(VGACNTRL, VGA_DISP_DISABLE, i); @@ -420,10 +429,6 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc, (mode->crtc_vdisplay - 1), i); } - if (gma_encoder) - drm_object_property_get_value(&connector->base, - dev->mode_config.scaling_mode_property, &scalingType); - if (scalingType == DRM_MODE_SCALE_NO_SCALE) { /* Moorestown doesn't have register support for centering so * we need to mess with the h/vblank and h/vsync start and diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c index 28b995ef2844..04852dbc7fb3 100644 --- a/drivers/gpu/drm/gma500/oaktrail_lvds.c +++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c @@ -85,7 +85,7 @@ static void oaktrail_lvds_mode_set(struct drm_encoder *encoder, struct drm_device *dev = encoder->dev; struct drm_psb_private *dev_priv = to_drm_psb_private(dev); struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; - struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector_list_iter conn_iter; struct drm_connector *connector = NULL; struct drm_crtc *crtc = encoder->crtc; u32 lvds_port; @@ -112,21 +112,22 @@ static void oaktrail_lvds_mode_set(struct drm_encoder *encoder, REG_WRITE(LVDS, lvds_port); /* Find the connector we're trying to set up */ - list_for_each_entry(connector, &mode_config->connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { if (connector->encoder && connector->encoder->crtc == crtc) break; } - if (list_entry_is_head(connector, &mode_config->connector_list, head)) { + if (!connector) { + drm_connector_list_iter_end(&conn_iter); DRM_ERROR("Couldn't find connector when setting mode"); gma_power_end(dev); return; } - drm_object_property_get_value( - &connector->base, - dev->mode_config.scaling_mode_property, - &v); + drm_object_property_get_value( &connector->base, + dev->mode_config.scaling_mode_property, &v); + drm_connector_list_iter_end(&conn_iter); if (v == DRM_MODE_SCALE_NO_SCALE) REG_WRITE(PFIT_CONTROL, 0); diff --git a/drivers/gpu/drm/gma500/psb_device.c b/drivers/gpu/drm/gma500/psb_device.c index 59f325165667..71534f4ca834 100644 --- a/drivers/gpu/drm/gma500/psb_device.c +++ b/drivers/gpu/drm/gma500/psb_device.c @@ -168,8 +168,10 @@ static void psb_init_pm(struct drm_device *dev) static int psb_save_display_registers(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct gma_connector *gma_connector; struct drm_crtc *crtc; - struct gma_connector *connector; + struct drm_connector_list_iter conn_iter; + struct drm_connector *connector; struct psb_state *regs = &dev_priv->regs.psb; /* Display arbitration control + watermarks */ @@ -189,9 +191,13 @@ static int psb_save_display_registers(struct drm_device *dev) dev_priv->ops->save_crtc(crtc); } - list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) - if (connector->save) - connector->save(&connector->base); + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + gma_connector = to_gma_connector(connector); + if (gma_connector->save) + gma_connector->save(connector); + } + drm_connector_list_iter_end(&conn_iter); drm_modeset_unlock_all(dev); return 0; @@ -206,8 +212,10 @@ static int psb_save_display_registers(struct drm_device *dev) static int psb_restore_display_registers(struct drm_device *dev) { struct drm_psb_private *dev_priv = to_drm_psb_private(dev); + struct gma_connector *gma_connector; struct drm_crtc *crtc; - struct gma_connector *connector; + struct drm_connector_list_iter conn_iter; + struct drm_connector *connector; struct psb_state *regs = &dev_priv->regs.psb; /* Display arbitration + watermarks */ @@ -228,9 +236,13 @@ static int psb_restore_display_registers(struct drm_device *dev) if (drm_helper_crtc_in_use(crtc)) dev_priv->ops->restore_crtc(crtc); - list_for_each_entry(connector, &dev->mode_config.connector_list, base.head) - if (connector->restore) - connector->restore(&connector->base); + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { + gma_connector = to_gma_connector(connector); + if (gma_connector->restore) + gma_connector->restore(connector); + } + drm_connector_list_iter_end(&conn_iter); drm_modeset_unlock_all(dev); return 0; diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index b231fddb8817..bb0e3288e35b 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -236,10 +236,11 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) struct drm_psb_private *dev_priv = to_drm_psb_private(dev); unsigned long resource_start, resource_len; unsigned long irqflags; - int ret = -ENOMEM; + struct drm_connector_list_iter conn_iter; struct drm_connector *connector; struct gma_encoder *gma_encoder; struct psb_gtt *pg; + int ret = -ENOMEM; /* initializing driver private data */ @@ -390,9 +391,9 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) psb_fbdev_init(dev); drm_kms_helper_poll_init(dev); - /* Only add backlight support if we have LVDS output */ - list_for_each_entry(connector, &dev->mode_config.connector_list, - head) { + /* Only add backlight support if we have LVDS or MIPI output */ + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { gma_encoder = gma_attached_encoder(connector); switch (gma_encoder->type) { @@ -402,6 +403,7 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags) break; } } + drm_connector_list_iter_end(&conn_iter); if (ret) return ret; diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index a99859b5b13a..fb8234f4d128 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -106,7 +106,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, u32 dpll = 0, fp = 0, dspcntr, pipeconf; bool ok, is_sdvo = false; bool is_lvds = false, is_tv = false; - struct drm_mode_config *mode_config = &dev->mode_config; + struct drm_connector_list_iter conn_iter; struct drm_connector *connector; const struct gma_limit_t *limit; @@ -116,7 +116,8 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, return 0; } - list_for_each_entry(connector, &mode_config->connector_list, head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { struct gma_encoder *gma_encoder = gma_attached_encoder(connector); if (!connector->encoder @@ -135,6 +136,7 @@ static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, break; } } + drm_connector_list_iter_end(&conn_iter); refclk = 96000; @@ -534,16 +536,19 @@ struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) int gma_connector_clones(struct drm_device *dev, int type_mask) { - int index_mask = 0; + struct drm_connector_list_iter conn_iter; struct drm_connector *connector; + int index_mask = 0; int entry = 0; - list_for_each_entry(connector, &dev->mode_config.connector_list, - head) { + drm_connector_list_iter_begin(dev, &conn_iter); + drm_for_each_connector_iter(connector, &conn_iter) { struct gma_encoder *gma_encoder = gma_attached_encoder(connector); if (type_mask & (1 << gma_encoder->type)) index_mask |= (1 << entry); entry++; } + drm_connector_list_iter_end(&conn_iter); + return index_mask; } From 9f8308f4c94afc7486ea4ad41298031af0b91a92 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Tue, 22 Mar 2022 14:17:39 +0100 Subject: [PATCH 00330/11454] drm/gma500: gma500 don't register non-hotpluggable connectors According to docs we should only register connectors that are hotpluggable. No connectors in gma500 are hotpluggable. Signed-off-by: Patrik Jakobsson Reviewed-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220322131742.11566-4-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/cdv_intel_crt.c | 3 --- drivers/gpu/drm/gma500/cdv_intel_dp.c | 3 --- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 2 -- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 2 -- drivers/gpu/drm/gma500/oaktrail_hdmi.c | 1 - drivers/gpu/drm/gma500/oaktrail_lvds.c | 1 - drivers/gpu/drm/gma500/psb_intel_lvds.c | 2 -- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 2 -- 8 files changed, 16 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 4a9bb4994a26..1ae0fbbda0eb 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -194,7 +194,6 @@ static void cdv_intel_crt_destroy(struct drm_connector *connector) struct gma_encoder *gma_encoder = gma_attached_encoder(connector); psb_intel_i2c_destroy(gma_encoder->ddc_bus); - drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -281,8 +280,6 @@ void cdv_intel_crt_init(struct drm_device *dev, drm_connector_helper_add(connector, &cdv_intel_crt_connector_helper_funcs); - drm_connector_register(connector); - return; failed_ddc: drm_encoder_cleanup(&gma_encoder->base); diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index f562e91337c7..3fba9d4e785d 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -1866,7 +1866,6 @@ cdv_intel_dp_destroy(struct drm_connector *connector) intel_dp->panel_fixed_mode = NULL; } i2c_del_adapter(&intel_dp->adapter); - drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -1990,8 +1989,6 @@ cdv_intel_dp_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev connector->interlace_allowed = false; connector->doublescan_allowed = false; - drm_connector_register(connector); - /* Set up the DDC bus. */ switch (output_reg) { case DP_B: diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index e525689f84f0..e0d4c49b3c92 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -245,7 +245,6 @@ static void cdv_hdmi_destroy(struct drm_connector *connector) struct gma_encoder *gma_encoder = gma_attached_encoder(connector); psb_intel_i2c_destroy(gma_encoder->i2c_bus); - drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -352,7 +351,6 @@ void cdv_hdmi_init(struct drm_device *dev, hdmi_priv->hdmi_i2c_adapter = &(gma_encoder->i2c_bus->adapter); hdmi_priv->dev = dev; - drm_connector_register(connector); return; failed_ddc: diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index 9e1cdb11023c..851a3cc4653e 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -329,7 +329,6 @@ static void cdv_intel_lvds_destroy(struct drm_connector *connector) struct gma_encoder *gma_encoder = gma_attached_encoder(connector); psb_intel_i2c_destroy(gma_encoder->i2c_bus); - drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -647,7 +646,6 @@ void cdv_intel_lvds_init(struct drm_device *dev, out: mutex_unlock(&dev->mode_config.mutex); - drm_connector_register(connector); return; failed_find: diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c index 6eef60a5ac27..b5946a1cdcd5 100644 --- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c +++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c @@ -654,7 +654,6 @@ void oaktrail_hdmi_init(struct drm_device *dev, connector->display_info.subpixel_order = SubPixelHorizontalRGB; connector->interlace_allowed = false; connector->doublescan_allowed = false; - drm_connector_register(connector); dev_info(dev->dev, "HDMI initialised.\n"); return; diff --git a/drivers/gpu/drm/gma500/oaktrail_lvds.c b/drivers/gpu/drm/gma500/oaktrail_lvds.c index 04852dbc7fb3..aed5de8f8245 100644 --- a/drivers/gpu/drm/gma500/oaktrail_lvds.c +++ b/drivers/gpu/drm/gma500/oaktrail_lvds.c @@ -401,7 +401,6 @@ void oaktrail_lvds_init(struct drm_device *dev, out: mutex_unlock(&dev->mode_config.mutex); - drm_connector_register(connector); return; failed_find: diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index ac97e0d3c7dd..ec8f0b504ccc 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -525,7 +525,6 @@ void psb_intel_lvds_destroy(struct drm_connector *connector) struct psb_intel_lvds_priv *lvds_priv = gma_encoder->dev_priv; psb_intel_i2c_destroy(lvds_priv->ddc_bus); - drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -782,7 +781,6 @@ void psb_intel_lvds_init(struct drm_device *dev, */ out: mutex_unlock(&dev->mode_config.mutex); - drm_connector_register(connector); return; failed_find: diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 042c4392e676..5b72a759a182 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -1542,7 +1542,6 @@ static int psb_intel_sdvo_get_modes(struct drm_connector *connector) static void psb_intel_sdvo_destroy(struct drm_connector *connector) { - drm_connector_unregister(connector); drm_connector_cleanup(connector); kfree(connector); } @@ -1932,7 +1931,6 @@ psb_intel_sdvo_connector_init(struct psb_intel_sdvo_connector *connector, connector->base.restore = psb_intel_sdvo_restore; gma_connector_attach_encoder(&connector->base, &encoder->base); - drm_connector_register(&connector->base.base); } static void From 12e67cca85a06b1227b0fd797d436ddffadd01a8 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Tue, 22 Mar 2022 14:17:40 +0100 Subject: [PATCH 00331/11454] drm/gma500: Free the correct connector allocation The allocation is made for the gma_connector object so we must use the same address when free()ing the object. Signed-off-by: Patrik Jakobsson Reviewed-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220322131742.11566-5-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/cdv_intel_crt.c | 3 ++- drivers/gpu/drm/gma500/cdv_intel_dp.c | 3 ++- drivers/gpu/drm/gma500/cdv_intel_hdmi.c | 3 ++- drivers/gpu/drm/gma500/cdv_intel_lvds.c | 3 ++- drivers/gpu/drm/gma500/psb_intel_lvds.c | 3 ++- drivers/gpu/drm/gma500/psb_intel_sdvo.c | 4 +++- 6 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/gma500/cdv_intel_crt.c b/drivers/gpu/drm/gma500/cdv_intel_crt.c index 1ae0fbbda0eb..6bcd18c63c31 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_crt.c +++ b/drivers/gpu/drm/gma500/cdv_intel_crt.c @@ -191,11 +191,12 @@ static enum drm_connector_status cdv_intel_crt_detect( static void cdv_intel_crt_destroy(struct drm_connector *connector) { + struct gma_connector *gma_connector = to_gma_connector(connector); struct gma_encoder *gma_encoder = gma_attached_encoder(connector); psb_intel_i2c_destroy(gma_encoder->ddc_bus); drm_connector_cleanup(connector); - kfree(connector); + kfree(gma_connector); } static int cdv_intel_crt_get_modes(struct drm_connector *connector) diff --git a/drivers/gpu/drm/gma500/cdv_intel_dp.c b/drivers/gpu/drm/gma500/cdv_intel_dp.c index 3fba9d4e785d..72b1b2fc3c27 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_dp.c +++ b/drivers/gpu/drm/gma500/cdv_intel_dp.c @@ -1857,6 +1857,7 @@ done: static void cdv_intel_dp_destroy(struct drm_connector *connector) { + struct gma_connector *gma_connector = to_gma_connector(connector); struct gma_encoder *gma_encoder = gma_attached_encoder(connector); struct cdv_intel_dp *intel_dp = gma_encoder->dev_priv; @@ -1867,7 +1868,7 @@ cdv_intel_dp_destroy(struct drm_connector *connector) } i2c_del_adapter(&intel_dp->adapter); drm_connector_cleanup(connector); - kfree(connector); + kfree(gma_connector); } static const struct drm_encoder_helper_funcs cdv_intel_dp_helper_funcs = { diff --git a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c index e0d4c49b3c92..8987e555e113 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_hdmi.c +++ b/drivers/gpu/drm/gma500/cdv_intel_hdmi.c @@ -242,11 +242,12 @@ static enum drm_mode_status cdv_hdmi_mode_valid(struct drm_connector *connector, static void cdv_hdmi_destroy(struct drm_connector *connector) { + struct gma_connector *gma_connector = to_gma_connector(connector); struct gma_encoder *gma_encoder = gma_attached_encoder(connector); psb_intel_i2c_destroy(gma_encoder->i2c_bus); drm_connector_cleanup(connector); - kfree(connector); + kfree(gma_connector); } static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = { diff --git a/drivers/gpu/drm/gma500/cdv_intel_lvds.c b/drivers/gpu/drm/gma500/cdv_intel_lvds.c index 851a3cc4653e..98d9f5483a7c 100644 --- a/drivers/gpu/drm/gma500/cdv_intel_lvds.c +++ b/drivers/gpu/drm/gma500/cdv_intel_lvds.c @@ -326,11 +326,12 @@ static int cdv_intel_lvds_get_modes(struct drm_connector *connector) */ static void cdv_intel_lvds_destroy(struct drm_connector *connector) { + struct gma_connector *gma_connector = to_gma_connector(connector); struct gma_encoder *gma_encoder = gma_attached_encoder(connector); psb_intel_i2c_destroy(gma_encoder->i2c_bus); drm_connector_cleanup(connector); - kfree(connector); + kfree(gma_connector); } static int cdv_intel_lvds_set_property(struct drm_connector *connector, diff --git a/drivers/gpu/drm/gma500/psb_intel_lvds.c b/drivers/gpu/drm/gma500/psb_intel_lvds.c index ec8f0b504ccc..cad00380b386 100644 --- a/drivers/gpu/drm/gma500/psb_intel_lvds.c +++ b/drivers/gpu/drm/gma500/psb_intel_lvds.c @@ -521,12 +521,13 @@ static int psb_intel_lvds_get_modes(struct drm_connector *connector) */ void psb_intel_lvds_destroy(struct drm_connector *connector) { + struct gma_connector *gma_connector = to_gma_connector(connector); struct gma_encoder *gma_encoder = gma_attached_encoder(connector); struct psb_intel_lvds_priv *lvds_priv = gma_encoder->dev_priv; psb_intel_i2c_destroy(lvds_priv->ddc_bus); drm_connector_cleanup(connector); - kfree(connector); + kfree(gma_connector); } int psb_intel_lvds_set_property(struct drm_connector *connector, diff --git a/drivers/gpu/drm/gma500/psb_intel_sdvo.c b/drivers/gpu/drm/gma500/psb_intel_sdvo.c index 5b72a759a182..a85aace25548 100644 --- a/drivers/gpu/drm/gma500/psb_intel_sdvo.c +++ b/drivers/gpu/drm/gma500/psb_intel_sdvo.c @@ -1542,8 +1542,10 @@ static int psb_intel_sdvo_get_modes(struct drm_connector *connector) static void psb_intel_sdvo_destroy(struct drm_connector *connector) { + struct gma_connector *gma_connector = to_gma_connector(connector); + drm_connector_cleanup(connector); - kfree(connector); + kfree(gma_connector); } static bool psb_intel_sdvo_detect_hdmi_audio(struct drm_connector *connector) From d9f6e81272de653812e8b2aa77c93f16939e02e9 Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Tue, 22 Mar 2022 14:17:41 +0100 Subject: [PATCH 00332/11454] drm/gma500: Declare a few functions static These functions are not used outside of their file scope so can be declared as static. Signed-off-by: Patrik Jakobsson Reviewed-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220322131742.11566-6-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/gma_display.c | 15 +++++++-------- drivers/gpu/drm/gma500/psb_drv.c | 2 +- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index e8157464d9eb..369bc1f751cb 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -176,9 +176,9 @@ void gma_crtc_load_lut(struct drm_crtc *crtc) } } -int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, u16 *blue, - u32 size, - struct drm_modeset_acquire_ctx *ctx) +static int gma_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green, + u16 *blue, u32 size, + struct drm_modeset_acquire_ctx *ctx) { gma_crtc_load_lut(crtc); @@ -323,10 +323,9 @@ void gma_crtc_dpms(struct drm_crtc *crtc, int mode) REG_WRITE(DSPARB, 0x3F3E); } -int gma_crtc_cursor_set(struct drm_crtc *crtc, - struct drm_file *file_priv, - uint32_t handle, - uint32_t width, uint32_t height) +static int gma_crtc_cursor_set(struct drm_crtc *crtc, + struct drm_file *file_priv, uint32_t handle, + uint32_t width, uint32_t height) { struct drm_device *dev = crtc->dev; struct drm_psb_private *dev_priv = to_drm_psb_private(dev); @@ -439,7 +438,7 @@ unref_cursor: return ret; } -int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) +static int gma_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) { struct drm_device *dev = crtc->dev; struct gma_crtc *gma_crtc = to_gma_crtc(crtc); diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index bb0e3288e35b..2aff54d505e2 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c @@ -100,7 +100,7 @@ static const struct drm_ioctl_desc psb_ioctls[] = { * * Soft reset the graphics engine and then reload the necessary registers. */ -void psb_spank(struct drm_psb_private *dev_priv) +static void psb_spank(struct drm_psb_private *dev_priv) { PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET | _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET | From 52e527f28776e4a8188fed0fe092d9f4d5e39f1c Mon Sep 17 00:00:00 2001 From: Patrik Jakobsson Date: Tue, 22 Mar 2022 14:17:42 +0100 Subject: [PATCH 00333/11454] drm/gma500: Add crtc prefix to vblank functions These functions operate on a crtc and should be prefixed properly. Suggested-by: Thomas Zimmermann Signed-off-by: Patrik Jakobsson Reviewed-by: Thomas Zimmermann Acked-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220322131742.11566-7-patrik.r.jakobsson@gmail.com --- drivers/gpu/drm/gma500/gma_display.c | 6 +++--- drivers/gpu/drm/gma500/psb_irq.c | 6 +++--- drivers/gpu/drm/gma500/psb_irq.h | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/gma500/gma_display.c b/drivers/gpu/drm/gma500/gma_display.c index 369bc1f751cb..34ec3fca09ba 100644 --- a/drivers/gpu/drm/gma500/gma_display.c +++ b/drivers/gpu/drm/gma500/gma_display.c @@ -575,9 +575,9 @@ const struct drm_crtc_funcs gma_crtc_funcs = { .set_config = gma_crtc_set_config, .destroy = gma_crtc_destroy, .page_flip = gma_crtc_page_flip, - .enable_vblank = gma_enable_vblank, - .disable_vblank = gma_disable_vblank, - .get_vblank_counter = gma_get_vblank_counter, + .enable_vblank = gma_crtc_enable_vblank, + .disable_vblank = gma_crtc_disable_vblank, + .get_vblank_counter = gma_crtc_get_vblank_counter, }; /* diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c index 2e8ded532930..e6e6d61bbeab 100644 --- a/drivers/gpu/drm/gma500/psb_irq.c +++ b/drivers/gpu/drm/gma500/psb_irq.c @@ -371,7 +371,7 @@ void gma_irq_uninstall(struct drm_device *dev) free_irq(pdev->irq, dev); } -int gma_enable_vblank(struct drm_crtc *crtc) +int gma_crtc_enable_vblank(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; @@ -404,7 +404,7 @@ int gma_enable_vblank(struct drm_crtc *crtc) return 0; } -void gma_disable_vblank(struct drm_crtc *crtc) +void gma_crtc_disable_vblank(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; @@ -428,7 +428,7 @@ void gma_disable_vblank(struct drm_crtc *crtc) /* Called from drm generic code, passed a 'crtc', which * we use as a pipe index */ -u32 gma_get_vblank_counter(struct drm_crtc *crtc) +u32 gma_crtc_get_vblank_counter(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; unsigned int pipe = crtc->index; diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h index c22878914f5b..b51e395194ff 100644 --- a/drivers/gpu/drm/gma500/psb_irq.h +++ b/drivers/gpu/drm/gma500/psb_irq.h @@ -20,9 +20,9 @@ void gma_irq_postinstall(struct drm_device *dev); int gma_irq_install(struct drm_device *dev, unsigned int irq); void gma_irq_uninstall(struct drm_device *dev); -int gma_enable_vblank(struct drm_crtc *crtc); -void gma_disable_vblank(struct drm_crtc *crtc); -u32 gma_get_vblank_counter(struct drm_crtc *crtc); +int gma_crtc_enable_vblank(struct drm_crtc *crtc); +void gma_crtc_disable_vblank(struct drm_crtc *crtc); +u32 gma_crtc_get_vblank_counter(struct drm_crtc *crtc); void gma_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); void gma_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); From cc2f2df48a17980e815fa09a43b81861f7ebad85 Mon Sep 17 00:00:00 2001 From: Nicolas Belin Date: Wed, 16 Mar 2022 14:57:31 +0100 Subject: [PATCH 00334/11454] dt-bindings: display: bridge: it66121: Add audio support Update the ITE bridge HDMI it66121 bindings in order to support audio. Signed-off-by: Nicolas Belin Acked-by: Rob Herring Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20220316135733.173950-2-nbelin@baylibre.com --- .../devicetree/bindings/display/bridge/ite,it66121.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml b/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml index 6ec1d5fbb8bc..c6e81f532215 100644 --- a/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml +++ b/Documentation/devicetree/bindings/display/bridge/ite,it66121.yaml @@ -38,6 +38,9 @@ properties: interrupts: maxItems: 1 + "#sound-dai-cells": + const: 0 + ports: $ref: /schemas/graph.yaml#/properties/ports From 003a1bd6a2a55c16cb2451153533dbedb12bebec Mon Sep 17 00:00:00 2001 From: Nicolas Belin Date: Wed, 16 Mar 2022 14:57:32 +0100 Subject: [PATCH 00335/11454] drm: bridge: it66121: Fix the register page length Set the register page length or window length to 0x100 according to the documentation. Fixes: 988156dc2fc9 ("drm: bridge: add it66121 driver") Signed-off-by: Nicolas Belin Acked-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20220316135733.173950-3-nbelin@baylibre.com --- drivers/gpu/drm/bridge/ite-it66121.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index 69288cf894b9..e81c106e2c2b 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -227,7 +227,7 @@ static const struct regmap_range_cfg it66121_regmap_banks[] = { .selector_mask = 0x1, .selector_shift = 0, .window_start = 0x00, - .window_len = 0x130, + .window_len = 0x100, }, }; From e0fd83dbe92426e4f09b01111d260d2a7dc72fdb Mon Sep 17 00:00:00 2001 From: Nicolas Belin Date: Wed, 16 Mar 2022 14:57:33 +0100 Subject: [PATCH 00336/11454] drm: bridge: it66121: Add audio support Adding the audio support on the HDMI bridge for I2S only. Signed-off-by: Nicolas Belin Signed-off-by: Andy.Hsieh Reviewed-by: Neil Armstrong Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20220316135733.173950-4-nbelin@baylibre.com --- drivers/gpu/drm/bridge/ite-it66121.c | 627 +++++++++++++++++++++++++++ 1 file changed, 627 insertions(+) diff --git a/drivers/gpu/drm/bridge/ite-it66121.c b/drivers/gpu/drm/bridge/ite-it66121.c index e81c106e2c2b..448c58e60c11 100644 --- a/drivers/gpu/drm/bridge/ite-it66121.c +++ b/drivers/gpu/drm/bridge/ite-it66121.c @@ -27,6 +27,8 @@ #include #include +#include + #define IT66121_VENDOR_ID0_REG 0x00 #define IT66121_VENDOR_ID1_REG 0x01 #define IT66121_DEVICE_ID0_REG 0x02 @@ -155,6 +157,9 @@ #define IT66121_AV_MUTE_ON BIT(0) #define IT66121_AV_MUTE_BLUESCR BIT(1) +#define IT66121_PKT_CTS_CTRL_REG 0xC5 +#define IT66121_PKT_CTS_CTRL_SEL BIT(1) + #define IT66121_PKT_GEN_CTRL_REG 0xC6 #define IT66121_PKT_GEN_CTRL_ON BIT(0) #define IT66121_PKT_GEN_CTRL_RPT BIT(1) @@ -202,6 +207,89 @@ #define IT66121_EDID_SLEEP_US 20000 #define IT66121_EDID_TIMEOUT_US 200000 #define IT66121_EDID_FIFO_SIZE 32 + +#define IT66121_CLK_CTRL0_REG 0x58 +#define IT66121_CLK_CTRL0_AUTO_OVER_SAMPLING BIT(4) +#define IT66121_CLK_CTRL0_EXT_MCLK_MASK GENMASK(3, 2) +#define IT66121_CLK_CTRL0_EXT_MCLK_128FS (0 << 2) +#define IT66121_CLK_CTRL0_EXT_MCLK_256FS BIT(2) +#define IT66121_CLK_CTRL0_EXT_MCLK_512FS (2 << 2) +#define IT66121_CLK_CTRL0_EXT_MCLK_1024FS (3 << 2) +#define IT66121_CLK_CTRL0_AUTO_IPCLK BIT(0) +#define IT66121_CLK_STATUS1_REG 0x5E +#define IT66121_CLK_STATUS2_REG 0x5F + +#define IT66121_AUD_CTRL0_REG 0xE0 +#define IT66121_AUD_SWL (3 << 6) +#define IT66121_AUD_16BIT (0 << 6) +#define IT66121_AUD_18BIT BIT(6) +#define IT66121_AUD_20BIT (2 << 6) +#define IT66121_AUD_24BIT (3 << 6) +#define IT66121_AUD_SPDIFTC BIT(5) +#define IT66121_AUD_SPDIF BIT(4) +#define IT66121_AUD_I2S (0 << 4) +#define IT66121_AUD_EN_I2S3 BIT(3) +#define IT66121_AUD_EN_I2S2 BIT(2) +#define IT66121_AUD_EN_I2S1 BIT(1) +#define IT66121_AUD_EN_I2S0 BIT(0) +#define IT66121_AUD_CTRL0_AUD_SEL BIT(4) + +#define IT66121_AUD_CTRL1_REG 0xE1 +#define IT66121_AUD_FIFOMAP_REG 0xE2 +#define IT66121_AUD_CTRL3_REG 0xE3 +#define IT66121_AUD_SRCVALID_FLAT_REG 0xE4 +#define IT66121_AUD_FLAT_SRC0 BIT(4) +#define IT66121_AUD_FLAT_SRC1 BIT(5) +#define IT66121_AUD_FLAT_SRC2 BIT(6) +#define IT66121_AUD_FLAT_SRC3 BIT(7) +#define IT66121_AUD_HDAUDIO_REG 0xE5 + +#define IT66121_AUD_PKT_CTS0_REG 0x130 +#define IT66121_AUD_PKT_CTS1_REG 0x131 +#define IT66121_AUD_PKT_CTS2_REG 0x132 +#define IT66121_AUD_PKT_N0_REG 0x133 +#define IT66121_AUD_PKT_N1_REG 0x134 +#define IT66121_AUD_PKT_N2_REG 0x135 + +#define IT66121_AUD_CHST_MODE_REG 0x191 +#define IT66121_AUD_CHST_CAT_REG 0x192 +#define IT66121_AUD_CHST_SRCNUM_REG 0x193 +#define IT66121_AUD_CHST_CHTNUM_REG 0x194 +#define IT66121_AUD_CHST_CA_FS_REG 0x198 +#define IT66121_AUD_CHST_OFS_WL_REG 0x199 + +#define IT66121_AUD_PKT_CTS_CNT0_REG 0x1A0 +#define IT66121_AUD_PKT_CTS_CNT1_REG 0x1A1 +#define IT66121_AUD_PKT_CTS_CNT2_REG 0x1A2 + +#define IT66121_AUD_FS_22P05K 0x4 +#define IT66121_AUD_FS_44P1K 0x0 +#define IT66121_AUD_FS_88P2K 0x8 +#define IT66121_AUD_FS_176P4K 0xC +#define IT66121_AUD_FS_24K 0x6 +#define IT66121_AUD_FS_48K 0x2 +#define IT66121_AUD_FS_96K 0xA +#define IT66121_AUD_FS_192K 0xE +#define IT66121_AUD_FS_768K 0x9 +#define IT66121_AUD_FS_32K 0x3 +#define IT66121_AUD_FS_OTHER 0x1 + +#define IT66121_AUD_SWL_21BIT 0xD +#define IT66121_AUD_SWL_24BIT 0xB +#define IT66121_AUD_SWL_23BIT 0x9 +#define IT66121_AUD_SWL_22BIT 0x5 +#define IT66121_AUD_SWL_20BIT 0x3 +#define IT66121_AUD_SWL_17BIT 0xC +#define IT66121_AUD_SWL_19BIT 0x8 +#define IT66121_AUD_SWL_18BIT 0x4 +#define IT66121_AUD_SWL_16BIT 0x2 +#define IT66121_AUD_SWL_NOT_INDICATED 0x0 + +#define IT66121_VENDOR_ID0 0x54 +#define IT66121_VENDOR_ID1 0x49 +#define IT66121_DEVICE_ID0 0x12 +#define IT66121_DEVICE_ID1 0x06 +#define IT66121_DEVICE_MASK 0x0F #define IT66121_AFE_CLK_HIGH 80000 /* Khz */ struct it66121_ctx { @@ -216,6 +304,13 @@ struct it66121_ctx { u32 bus_width; struct mutex lock; /* Protects fields below and device registers */ struct hdmi_avi_infoframe hdmi_avi_infoframe; + struct { + struct platform_device *pdev; + u8 ch_enable; + u8 fs; + u8 swl; + bool auto_cts; + } audio; }; static const struct regmap_range_cfg it66121_regmap_banks[] = { @@ -886,6 +981,536 @@ unlock: return IRQ_HANDLED; } +static int it661221_set_chstat(struct it66121_ctx *ctx, u8 iec60958_chstat[]) +{ + int ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_CHST_MODE_REG, iec60958_chstat[0] & 0x7C); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_CHST_CAT_REG, iec60958_chstat[1]); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_CHST_SRCNUM_REG, iec60958_chstat[2] & 0x0F); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_CHST_CHTNUM_REG, + (iec60958_chstat[2] >> 4) & 0x0F); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_CHST_CA_FS_REG, iec60958_chstat[3]); + if (ret) + return ret; + + return regmap_write(ctx->regmap, IT66121_AUD_CHST_OFS_WL_REG, iec60958_chstat[4]); +} + +static int it661221_set_lpcm_audio(struct it66121_ctx *ctx, u8 audio_src_num, u8 audio_swl) +{ + int ret; + unsigned int audio_enable = 0; + unsigned int audio_format = 0; + + switch (audio_swl) { + case 16: + audio_enable |= IT66121_AUD_16BIT; + break; + case 18: + audio_enable |= IT66121_AUD_18BIT; + break; + case 20: + audio_enable |= IT66121_AUD_20BIT; + break; + case 24: + default: + audio_enable |= IT66121_AUD_24BIT; + break; + } + + audio_format |= 0x40; + switch (audio_src_num) { + case 4: + audio_enable |= IT66121_AUD_EN_I2S3 | IT66121_AUD_EN_I2S2 | + IT66121_AUD_EN_I2S1 | IT66121_AUD_EN_I2S0; + break; + case 3: + audio_enable |= IT66121_AUD_EN_I2S2 | IT66121_AUD_EN_I2S1 | + IT66121_AUD_EN_I2S0; + break; + case 2: + audio_enable |= IT66121_AUD_EN_I2S1 | IT66121_AUD_EN_I2S0; + break; + case 1: + default: + audio_format &= ~0x40; + audio_enable |= IT66121_AUD_EN_I2S0; + break; + } + + audio_format |= 0x01; + ctx->audio.ch_enable = audio_enable; + + ret = regmap_write(ctx->regmap, IT66121_AUD_CTRL0_REG, audio_enable & 0xF0); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_CTRL1_REG, audio_format); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_FIFOMAP_REG, 0xE4); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_CTRL3_REG, 0x00); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_SRCVALID_FLAT_REG, 0x00); + if (ret) + return ret; + + return regmap_write(ctx->regmap, IT66121_AUD_HDAUDIO_REG, 0x00); +} + +static int it661221_set_ncts(struct it66121_ctx *ctx, u8 fs) +{ + int ret; + unsigned int n; + + switch (fs) { + case IT66121_AUD_FS_32K: + n = 4096; + break; + case IT66121_AUD_FS_44P1K: + n = 6272; + break; + case IT66121_AUD_FS_48K: + n = 6144; + break; + case IT66121_AUD_FS_88P2K: + n = 12544; + break; + case IT66121_AUD_FS_96K: + n = 12288; + break; + case IT66121_AUD_FS_176P4K: + n = 25088; + break; + case IT66121_AUD_FS_192K: + n = 24576; + break; + case IT66121_AUD_FS_768K: + n = 24576; + break; + default: + n = 6144; + break; + } + + ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_N0_REG, (u8)((n) & 0xFF)); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_N1_REG, (u8)((n >> 8) & 0xFF)); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_PKT_N2_REG, (u8)((n >> 16) & 0xF)); + if (ret) + return ret; + + if (ctx->audio.auto_cts) { + u8 loop_cnt = 255; + u8 cts_stable_cnt = 0; + unsigned int sum_cts = 0; + unsigned int cts = 0; + unsigned int last_cts = 0; + unsigned int diff; + unsigned int val; + + while (loop_cnt--) { + msleep(30); + regmap_read(ctx->regmap, IT66121_AUD_PKT_CTS_CNT2_REG, &val); + cts = val << 12; + regmap_read(ctx->regmap, IT66121_AUD_PKT_CTS_CNT1_REG, &val); + cts |= val << 4; + regmap_read(ctx->regmap, IT66121_AUD_PKT_CTS_CNT0_REG, &val); + cts |= val >> 4; + if (cts == 0) { + continue; + } else { + if (last_cts > cts) + diff = last_cts - cts; + else + diff = cts - last_cts; + last_cts = cts; + if (diff < 5) { + cts_stable_cnt++; + sum_cts += cts; + } else { + cts_stable_cnt = 0; + sum_cts = 0; + continue; + } + + if (cts_stable_cnt >= 32) { + last_cts = (sum_cts >> 5); + break; + } + } + } + + regmap_write(ctx->regmap, IT66121_AUD_PKT_CTS0_REG, (u8)((last_cts) & 0xFF)); + regmap_write(ctx->regmap, IT66121_AUD_PKT_CTS1_REG, (u8)((last_cts >> 8) & 0xFF)); + regmap_write(ctx->regmap, IT66121_AUD_PKT_CTS2_REG, (u8)((last_cts >> 16) & 0x0F)); + } + + ret = regmap_write(ctx->regmap, 0xF8, 0xC3); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, 0xF8, 0xA5); + if (ret) + return ret; + + if (ctx->audio.auto_cts) { + ret = regmap_write_bits(ctx->regmap, IT66121_PKT_CTS_CTRL_REG, + IT66121_PKT_CTS_CTRL_SEL, + 1); + } else { + ret = regmap_write_bits(ctx->regmap, IT66121_PKT_CTS_CTRL_REG, + IT66121_PKT_CTS_CTRL_SEL, + 0); + } + + if (ret) + return ret; + + return regmap_write(ctx->regmap, 0xF8, 0xFF); +} + +static int it661221_audio_output_enable(struct it66121_ctx *ctx, bool enable) +{ + int ret; + + if (enable) { + ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, + IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, + 0); + if (ret) + return ret; + + ret = regmap_write_bits(ctx->regmap, IT66121_AUD_CTRL0_REG, + IT66121_AUD_EN_I2S3 | IT66121_AUD_EN_I2S2 | + IT66121_AUD_EN_I2S1 | IT66121_AUD_EN_I2S0, + ctx->audio.ch_enable); + } else { + ret = regmap_write_bits(ctx->regmap, IT66121_AUD_CTRL0_REG, + IT66121_AUD_EN_I2S3 | IT66121_AUD_EN_I2S2 | + IT66121_AUD_EN_I2S1 | IT66121_AUD_EN_I2S0, + ctx->audio.ch_enable & 0xF0); + if (ret) + return ret; + + ret = regmap_write_bits(ctx->regmap, IT66121_SW_RST_REG, + IT66121_SW_RST_AUD | IT66121_SW_RST_AREF, + IT66121_SW_RST_AUD | IT66121_SW_RST_AREF); + } + + return ret; +} + +static int it661221_audio_ch_enable(struct it66121_ctx *ctx, bool enable) +{ + int ret; + + if (enable) { + ret = regmap_write(ctx->regmap, IT66121_AUD_SRCVALID_FLAT_REG, 0); + if (ret) + return ret; + + ret = regmap_write(ctx->regmap, IT66121_AUD_CTRL0_REG, ctx->audio.ch_enable); + } else { + ret = regmap_write(ctx->regmap, IT66121_AUD_CTRL0_REG, ctx->audio.ch_enable & 0xF0); + } + + return ret; +} + +static int it66121_audio_hw_params(struct device *dev, void *data, + struct hdmi_codec_daifmt *daifmt, + struct hdmi_codec_params *params) +{ + u8 fs; + u8 swl; + int ret; + struct it66121_ctx *ctx = dev_get_drvdata(dev); + static u8 iec60958_chstat[5]; + unsigned int channels = params->channels; + unsigned int sample_rate = params->sample_rate; + unsigned int sample_width = params->sample_width; + + mutex_lock(&ctx->lock); + dev_dbg(dev, "%s: %u, %u, %u, %u\n", __func__, + daifmt->fmt, sample_rate, sample_width, channels); + + switch (daifmt->fmt) { + case HDMI_I2S: + dev_dbg(dev, "Using HDMI I2S\n"); + break; + default: + dev_err(dev, "Invalid or unsupported DAI format %d\n", daifmt->fmt); + ret = -EINVAL; + goto out; + } + + // Set audio clock recovery (N/CTS) + ret = regmap_write(ctx->regmap, IT66121_CLK_CTRL0_REG, + IT66121_CLK_CTRL0_AUTO_OVER_SAMPLING | + IT66121_CLK_CTRL0_EXT_MCLK_256FS | + IT66121_CLK_CTRL0_AUTO_IPCLK); + if (ret) + goto out; + + ret = regmap_write_bits(ctx->regmap, IT66121_AUD_CTRL0_REG, + IT66121_AUD_CTRL0_AUD_SEL, 0); // remove spdif selection + if (ret) + goto out; + + switch (sample_rate) { + case 44100L: + fs = IT66121_AUD_FS_44P1K; + break; + case 88200L: + fs = IT66121_AUD_FS_88P2K; + break; + case 176400L: + fs = IT66121_AUD_FS_176P4K; + break; + case 32000L: + fs = IT66121_AUD_FS_32K; + break; + case 48000L: + fs = IT66121_AUD_FS_48K; + break; + case 96000L: + fs = IT66121_AUD_FS_96K; + break; + case 192000L: + fs = IT66121_AUD_FS_192K; + break; + case 768000L: + fs = IT66121_AUD_FS_768K; + break; + default: + fs = IT66121_AUD_FS_48K; + break; + } + + ctx->audio.fs = fs; + ret = it661221_set_ncts(ctx, fs); + if (ret) { + dev_err(dev, "Failed to set N/CTS: %d\n", ret); + goto out; + } + + // Set audio format register (except audio channel enable) + ret = it661221_set_lpcm_audio(ctx, (channels + 1) / 2, sample_width); + if (ret) { + dev_err(dev, "Failed to set LPCM audio: %d\n", ret); + goto out; + } + + // Set audio channel status + iec60958_chstat[0] = 0; + if ((channels + 1) / 2 == 1) + iec60958_chstat[0] |= 0x1; + iec60958_chstat[0] &= ~(1 << 1); + iec60958_chstat[1] = 0; + iec60958_chstat[2] = (channels + 1) / 2; + iec60958_chstat[2] |= (channels << 4) & 0xF0; + iec60958_chstat[3] = fs; + + switch (sample_width) { + case 21L: + swl = IT66121_AUD_SWL_21BIT; + break; + case 24L: + swl = IT66121_AUD_SWL_24BIT; + break; + case 23L: + swl = IT66121_AUD_SWL_23BIT; + break; + case 22L: + swl = IT66121_AUD_SWL_22BIT; + break; + case 20L: + swl = IT66121_AUD_SWL_20BIT; + break; + case 17L: + swl = IT66121_AUD_SWL_17BIT; + break; + case 19L: + swl = IT66121_AUD_SWL_19BIT; + break; + case 18L: + swl = IT66121_AUD_SWL_18BIT; + break; + case 16L: + swl = IT66121_AUD_SWL_16BIT; + break; + default: + swl = IT66121_AUD_SWL_NOT_INDICATED; + break; + } + + iec60958_chstat[4] = (((~fs) << 4) & 0xF0) | swl; + ret = it661221_set_chstat(ctx, iec60958_chstat); + if (ret) { + dev_err(dev, "Failed to set channel status: %d\n", ret); + goto out; + } + + // Enable audio channel enable while input clock stable (if SPDIF). + ret = it661221_audio_ch_enable(ctx, true); + if (ret) { + dev_err(dev, "Failed to enable audio channel: %d\n", ret); + goto out; + } + + ret = regmap_write_bits(ctx->regmap, IT66121_INT_MASK1_REG, + IT66121_INT_MASK1_AUD_OVF, + 0); + if (ret) + goto out; + + dev_dbg(dev, "HDMI audio enabled.\n"); +out: + mutex_unlock(&ctx->lock); + + return ret; +} + +static int it66121_audio_startup(struct device *dev, void *data) +{ + int ret; + struct it66121_ctx *ctx = dev_get_drvdata(dev); + + dev_dbg(dev, "%s\n", __func__); + + mutex_lock(&ctx->lock); + ret = it661221_audio_output_enable(ctx, true); + if (ret) + dev_err(dev, "Failed to enable audio output: %d\n", ret); + + mutex_unlock(&ctx->lock); + + return ret; +} + +static void it66121_audio_shutdown(struct device *dev, void *data) +{ + int ret; + struct it66121_ctx *ctx = dev_get_drvdata(dev); + + dev_dbg(dev, "%s\n", __func__); + + mutex_lock(&ctx->lock); + ret = it661221_audio_output_enable(ctx, false); + if (ret) + dev_err(dev, "Failed to disable audio output: %d\n", ret); + + mutex_unlock(&ctx->lock); +} + +static int it66121_audio_mute(struct device *dev, void *data, + bool enable, int direction) +{ + int ret; + struct it66121_ctx *ctx = dev_get_drvdata(dev); + + dev_dbg(dev, "%s: enable=%s, direction=%d\n", + __func__, enable ? "true" : "false", direction); + + mutex_lock(&ctx->lock); + + if (enable) { + ret = regmap_write_bits(ctx->regmap, IT66121_AUD_SRCVALID_FLAT_REG, + IT66121_AUD_FLAT_SRC0 | IT66121_AUD_FLAT_SRC1 | + IT66121_AUD_FLAT_SRC2 | IT66121_AUD_FLAT_SRC3, + IT66121_AUD_FLAT_SRC0 | IT66121_AUD_FLAT_SRC1 | + IT66121_AUD_FLAT_SRC2 | IT66121_AUD_FLAT_SRC3); + } else { + ret = regmap_write_bits(ctx->regmap, IT66121_AUD_SRCVALID_FLAT_REG, + IT66121_AUD_FLAT_SRC0 | IT66121_AUD_FLAT_SRC1 | + IT66121_AUD_FLAT_SRC2 | IT66121_AUD_FLAT_SRC3, + 0); + } + + mutex_unlock(&ctx->lock); + + return ret; +} + +static int it66121_audio_get_eld(struct device *dev, void *data, + u8 *buf, size_t len) +{ + struct it66121_ctx *ctx = dev_get_drvdata(dev); + + mutex_lock(&ctx->lock); + + memcpy(buf, ctx->connector->eld, + min(sizeof(ctx->connector->eld), len)); + + mutex_unlock(&ctx->lock); + + return 0; +} + +static const struct hdmi_codec_ops it66121_audio_codec_ops = { + .hw_params = it66121_audio_hw_params, + .audio_startup = it66121_audio_startup, + .audio_shutdown = it66121_audio_shutdown, + .mute_stream = it66121_audio_mute, + .get_eld = it66121_audio_get_eld, + .no_capture_mute = 1, +}; + +static int it66121_audio_codec_init(struct it66121_ctx *ctx, struct device *dev) +{ + struct hdmi_codec_pdata codec_data = { + .ops = &it66121_audio_codec_ops, + .i2s = 1, /* Only i2s support for now */ + .spdif = 0, + .max_i2s_channels = 8, + }; + + dev_dbg(dev, "%s\n", __func__); + + if (!of_property_read_bool(dev->of_node, "#sound-dai-cells")) { + dev_info(dev, "No \"#sound-dai-cells\", no audio\n"); + return 0; + } + + ctx->audio.pdev = platform_device_register_data(dev, + HDMI_CODEC_DRV_NAME, + PLATFORM_DEVID_AUTO, + &codec_data, + sizeof(codec_data)); + + if (IS_ERR(ctx->audio.pdev)) { + dev_err(dev, "Failed to initialize HDMI audio codec: %d\n", + PTR_ERR_OR_ZERO(ctx->audio.pdev)); + } + + return PTR_ERR_OR_ZERO(ctx->audio.pdev); +} + static int it66121_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -988,6 +1613,8 @@ static int it66121_probe(struct i2c_client *client, return ret; } + it66121_audio_codec_init(ctx, dev); + drm_bridge_add(&ctx->bridge); dev_info(ctx->dev, "IT66121 revision %d probed\n", revision_id); From 0941a4e3c629c902e7d229218dbc36a146ca699c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 3 Nov 2021 09:34:29 +0100 Subject: [PATCH 00337/11454] drm/etnaviv: stop using dma_resv_excl_fence v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can get the excl fence together with the shared ones as well. v2: rename the member to fences as well Signed-off-by: Christian König Reviewed-by: Daniel Vetter Reviewed-by: Lucas Stach Cc: Lucas Stach Cc: Russell King Cc: Christian Gmeiner Cc: etnaviv@lists.freedesktop.org Link: https://patchwork.freedesktop.org/patch/msgid/20220321135856.1331-5-christian.koenig@amd.com --- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 5 ++-- drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 14 ++++-------- drivers/gpu/drm/etnaviv/etnaviv_sched.c | 24 ++++++-------------- 3 files changed, 14 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h index 98e60df882b6..8983a0ef383e 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h @@ -80,9 +80,8 @@ struct etnaviv_gem_submit_bo { u64 va; struct etnaviv_gem_object *obj; struct etnaviv_vram_mapping *mapping; - struct dma_fence *excl; - unsigned int nr_shared; - struct dma_fence **shared; + unsigned int nr_fences; + struct dma_fence **fences; }; /* Created per submit-ioctl, to track bo's and cmdstream bufs, etc, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c index 4eb00a0cb650..592cbb38609a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c @@ -188,15 +188,11 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit) if (submit->flags & ETNA_SUBMIT_NO_IMPLICIT) continue; - if (bo->flags & ETNA_SUBMIT_BO_WRITE) { - ret = dma_resv_get_fences(robj, true, &bo->nr_shared, - &bo->shared); - if (ret) - return ret; - } else { - bo->excl = dma_fence_get(dma_resv_excl_fence(robj)); - } - + ret = dma_resv_get_fences(robj, + bo->flags & ETNA_SUBMIT_BO_WRITE, + &bo->nr_fences, &bo->fences); + if (ret) + return ret; } return ret; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index 35e5ef7dbdcc..a8452ce10e3a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -39,31 +39,21 @@ etnaviv_sched_dependency(struct drm_sched_job *sched_job, struct etnaviv_gem_submit_bo *bo = &submit->bos[i]; int j; - if (bo->excl) { - fence = bo->excl; - bo->excl = NULL; - - if (!dma_fence_is_signaled(fence)) - return fence; - - dma_fence_put(fence); - } - - for (j = 0; j < bo->nr_shared; j++) { - if (!bo->shared[j]) + for (j = 0; j < bo->nr_fences; j++) { + if (!bo->fences[j]) continue; - fence = bo->shared[j]; - bo->shared[j] = NULL; + fence = bo->fences[j]; + bo->fences[j] = NULL; if (!dma_fence_is_signaled(fence)) return fence; dma_fence_put(fence); } - kfree(bo->shared); - bo->nr_shared = 0; - bo->shared = NULL; + kfree(bo->fences); + bo->nr_fences = 0; + bo->fences = NULL; } return NULL; From f30bceab16d1d6a97cbe262623e25ed2873896f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 22 Sep 2021 13:01:04 +0200 Subject: [PATCH 00338/11454] RDMA: use dma_resv_wait() instead of extracting the fence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use dma_resv_wait() instead of extracting the exclusive fence and waiting on it manually. Signed-off-by: Christian König Reviewed-by: Daniel Vetter Acked-by: Jason Gunthorpe Cc: Jason Gunthorpe Cc: Leon Romanovsky Cc: Maor Gottlieb Cc: Gal Pressman Cc: linux-media@vger.kernel.org Cc: linaro-mm-sig@lists.linaro.org Link: https://patchwork.freedesktop.org/patch/msgid/20220321135856.1331-4-christian.koenig@amd.com --- drivers/infiniband/core/umem_dmabuf.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c index f0760741f281..d32cd7538835 100644 --- a/drivers/infiniband/core/umem_dmabuf.c +++ b/drivers/infiniband/core/umem_dmabuf.c @@ -16,7 +16,6 @@ int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) { struct sg_table *sgt; struct scatterlist *sg; - struct dma_fence *fence; unsigned long start, end, cur = 0; unsigned int nmap = 0; int i; @@ -68,11 +67,8 @@ wait_fence: * may be not up-to-date. Wait for the exporter to finish * the migration. */ - fence = dma_resv_excl_fence(umem_dmabuf->attach->dmabuf->resv); - if (fence) - return dma_fence_wait(fence, false); - - return 0; + return dma_resv_wait_timeout(umem_dmabuf->attach->dmabuf->resv, false, + false, MAX_SCHEDULE_TIMEOUT); } EXPORT_SYMBOL(ib_umem_dmabuf_map_pages); From 548e7432dc2da475a18077b612e8d55b8ff51891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 24 Sep 2021 10:55:45 +0200 Subject: [PATCH 00339/11454] dma-buf: add dma_resv_replace_fences v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function allows to replace fences from the shared fence list when we can gurantee that the operation represented by the original fence has finished or no accesses to the resources protected by the dma_resv object any more when the new fence finishes. Then use this function in the amdkfd code when BOs are unmapped from the process. v2: add an example when this is usefull. Signed-off-by: Christian König Reviewed-by: Felix Kuehling Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220321135856.1331-1-christian.koenig@amd.com --- drivers/dma-buf/dma-resv.c | 45 +++++++++++++++++ .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 49 +++---------------- include/linux/dma-resv.h | 2 + 3 files changed, 54 insertions(+), 42 deletions(-) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index b51416405e86..509060861cf3 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -289,6 +289,51 @@ replace: } EXPORT_SYMBOL(dma_resv_add_shared_fence); +/** + * dma_resv_replace_fences - replace fences in the dma_resv obj + * @obj: the reservation object + * @context: the context of the fences to replace + * @replacement: the new fence to use instead + * + * Replace fences with a specified context with a new fence. Only valid if the + * operation represented by the original fence has no longer access to the + * resources represented by the dma_resv object when the new fence completes. + * + * And example for using this is replacing a preemption fence with a page table + * update fence which makes the resource inaccessible. + */ +void dma_resv_replace_fences(struct dma_resv *obj, uint64_t context, + struct dma_fence *replacement) +{ + struct dma_resv_list *list; + struct dma_fence *old; + unsigned int i; + + dma_resv_assert_held(obj); + + write_seqcount_begin(&obj->seq); + + old = dma_resv_excl_fence(obj); + if (old->context == context) { + RCU_INIT_POINTER(obj->fence_excl, dma_fence_get(replacement)); + dma_fence_put(old); + } + + list = dma_resv_shared_list(obj); + for (i = 0; list && i < list->shared_count; ++i) { + old = rcu_dereference_protected(list->shared[i], + dma_resv_held(obj)); + if (old->context != context) + continue; + + rcu_assign_pointer(list->shared[i], dma_fence_get(replacement)); + dma_fence_put(old); + } + + write_seqcount_end(&obj->seq); +} +EXPORT_SYMBOL(dma_resv_replace_fences); + /** * dma_resv_add_excl_fence - Add an exclusive fence. * @obj: the reservation object diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index f9bab963a948..b6f266f612ea 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -253,53 +253,18 @@ void amdgpu_amdkfd_release_notify(struct amdgpu_bo *bo) static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, struct amdgpu_amdkfd_fence *ef) { - struct dma_resv *resv = bo->tbo.base.resv; - struct dma_resv_list *old, *new; - unsigned int i, j, k; + struct dma_fence *replacement; if (!ef) return -EINVAL; - old = dma_resv_shared_list(resv); - if (!old) - return 0; - - new = kmalloc(struct_size(new, shared, old->shared_max), GFP_KERNEL); - if (!new) - return -ENOMEM; - - /* Go through all the shared fences in the resevation object and sort - * the interesting ones to the end of the list. + /* TODO: Instead of block before we should use the fence of the page + * table update and TLB flush here directly. */ - for (i = 0, j = old->shared_count, k = 0; i < old->shared_count; ++i) { - struct dma_fence *f; - - f = rcu_dereference_protected(old->shared[i], - dma_resv_held(resv)); - - if (f->context == ef->base.context) - RCU_INIT_POINTER(new->shared[--j], f); - else - RCU_INIT_POINTER(new->shared[k++], f); - } - new->shared_max = old->shared_max; - new->shared_count = k; - - /* Install the new fence list, seqcount provides the barriers */ - write_seqcount_begin(&resv->seq); - RCU_INIT_POINTER(resv->fence, new); - write_seqcount_end(&resv->seq); - - /* Drop the references to the removed fences or move them to ef_list */ - for (i = j; i < old->shared_count; ++i) { - struct dma_fence *f; - - f = rcu_dereference_protected(new->shared[i], - dma_resv_held(resv)); - dma_fence_put(f); - } - kfree_rcu(old, rcu); - + replacement = dma_fence_get_stub(); + dma_resv_replace_fences(bo->tbo.base.resv, ef->base.context, + replacement); + dma_fence_put(replacement); return 0; } diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index afdfdfac729f..3f53177bdb46 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -468,6 +468,8 @@ void dma_resv_init(struct dma_resv *obj); void dma_resv_fini(struct dma_resv *obj); int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences); void dma_resv_add_shared_fence(struct dma_resv *obj, struct dma_fence *fence); +void dma_resv_replace_fences(struct dma_resv *obj, uint64_t context, + struct dma_fence *fence); void dma_resv_add_excl_fence(struct dma_resv *obj, struct dma_fence *fence); int dma_resv_get_fences(struct dma_resv *obj, bool write, unsigned int *num_fences, struct dma_fence ***fences); From 8938d48451f5d7cb565dfa68aa0bd0e81985da09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 24 Sep 2021 14:19:22 +0200 Subject: [PATCH 00340/11454] dma-buf: finally make the dma_resv_list private v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Drivers should never touch this directly. v2: drop kerneldoc for now internal handling Signed-off-by: Christian König Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220321135856.1331-2-christian.koenig@amd.com --- drivers/dma-buf/dma-resv.c | 11 +++++++++++ include/linux/dma-resv.h | 26 +------------------------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index 509060861cf3..5001e9b4420a 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -56,6 +56,12 @@ DEFINE_WD_CLASS(reservation_ww_class); EXPORT_SYMBOL(reservation_ww_class); +struct dma_resv_list { + struct rcu_head rcu; + u32 shared_count, shared_max; + struct dma_fence __rcu *shared[]; +}; + /** * dma_resv_list_alloc - allocate fence list * @shared_max: number of fences we need space for @@ -133,6 +139,11 @@ void dma_resv_fini(struct dma_resv *obj) } EXPORT_SYMBOL(dma_resv_fini); +static inline struct dma_resv_list *dma_resv_shared_list(struct dma_resv *obj) +{ + return rcu_dereference_check(obj->fence, dma_resv_held(obj)); +} + /** * dma_resv_reserve_shared - Reserve space to add shared fences to * a dma_resv. diff --git a/include/linux/dma-resv.h b/include/linux/dma-resv.h index 3f53177bdb46..202cc65d0621 100644 --- a/include/linux/dma-resv.h +++ b/include/linux/dma-resv.h @@ -47,18 +47,7 @@ extern struct ww_class reservation_ww_class; -/** - * struct dma_resv_list - a list of shared fences - * @rcu: for internal use - * @shared_count: table of shared fences - * @shared_max: for growing shared fence table - * @shared: shared fence table - */ -struct dma_resv_list { - struct rcu_head rcu; - u32 shared_count, shared_max; - struct dma_fence __rcu *shared[]; -}; +struct dma_resv_list; /** * struct dma_resv - a reservation object manages fences for a buffer @@ -451,19 +440,6 @@ dma_resv_excl_fence(struct dma_resv *obj) return rcu_dereference_check(obj->fence_excl, dma_resv_held(obj)); } -/** - * dma_resv_shared_list - get the reservation object's shared fence list - * @obj: the reservation object - * - * Returns the shared fence list. Caller must either hold the objects - * through dma_resv_lock() or the RCU read side lock through rcu_read_lock(), - * or one of the variants of each - */ -static inline struct dma_resv_list *dma_resv_shared_list(struct dma_resv *obj) -{ - return rcu_dereference_check(obj->fence, dma_resv_held(obj)); -} - void dma_resv_init(struct dma_resv *obj); void dma_resv_fini(struct dma_resv *obj); int dma_resv_reserve_shared(struct dma_resv *obj, unsigned int num_fences); From 3dd4834a6efe4eb3c086526e1870bb768776d86a Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Thu, 17 Mar 2022 17:47:24 +0800 Subject: [PATCH 00341/11454] drm/bridge: it6505: Fix build error If DRM_ITE_IT6505 is y but DRM_DP_HELPER is m, building failed: drivers/gpu/drm/bridge/ite-it6505.o: In function `it6505_i2c_remove': ite-it6505.c:(.text+0x35c): undefined reference to `drm_dp_aux_unregister' drivers/gpu/drm/bridge/ite-it6505.o: In function `it6505_dpcd_read': ite-it6505.c:(.text+0x420): undefined reference to `drm_dp_dpcd_read' drivers/gpu/drm/bridge/ite-it6505.o: In function `it6505_get_dpcd': ite-it6505.c:(.text+0x4a4): undefined reference to `drm_dp_dpcd_read' drivers/gpu/drm/bridge/ite-it6505.o: In function `it6505_dpcd_write': ite-it6505.c:(.text+0x52c): undefined reference to `drm_dp_dpcd_write' Select DRM_DP_HELPER for DRM_ITE_IT6505 to fix this. Fixes: b5c84a9edcd4 ("drm/bridge: add it6505 driver") Signed-off-by: YueHaibing Reviewed-by: Robert Foss Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220317094724.25972-1-yuehaibing@huawei.com --- drivers/gpu/drm/bridge/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index c86f5be4dfe0..1b8721a7a6df 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -78,6 +78,7 @@ config DRM_DISPLAY_CONNECTOR config DRM_ITE_IT6505 tristate "ITE IT6505 DisplayPort bridge" depends on OF + select DRM_DP_HELPER select DRM_KMS_HELPER select EXTCON help From 6135ee07702781cd8206bcb1c202c4630d6e3c9c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 22 Feb 2022 17:40:36 +0100 Subject: [PATCH 00342/11454] drm/vc4: hdmi: Rename pixel_rate variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The pixel_rate field in the vc4_hdmi_connector_state struct actually stores the TMDS character rate, let's rename it for consistency. Suggested-by: Ville Syrjälä Signed-off-by: Maxime Ripard Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220222164042.403112-2-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 40 +++++++++++++++--------------- drivers/gpu/drm/vc4/vc4_hdmi.h | 2 +- drivers/gpu/drm/vc4/vc4_hdmi_phy.c | 2 +- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index 335385f5b3fb..c70e5059b077 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -343,7 +343,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) if (!new_state) return NULL; - new_state->pixel_rate = vc4_state->pixel_rate; + new_state->tmds_char_rate = vc4_state->tmds_char_rate; __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); return &new_state->base; @@ -1028,7 +1028,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, struct vc4_hdmi_connector_state *vc4_conn_state = conn_state_to_vc4_hdmi_conn_state(conn_state); struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; - unsigned long pixel_rate = vc4_conn_state->pixel_rate; + unsigned long tmds_char_rate = vc4_conn_state->tmds_char_rate; unsigned long bvb_rate, hsm_rate; unsigned long flags; int ret; @@ -1051,7 +1051,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, * Additionally, the AXI clock needs to be at least 25% of * pixel clock, but HSM ends up being the limiting factor. */ - hsm_rate = max_t(unsigned long, 120000000, (pixel_rate / 100) * 101); + hsm_rate = max_t(unsigned long, 120000000, (tmds_char_rate / 100) * 101); ret = clk_set_min_rate(vc4_hdmi->hsm_clock, hsm_rate); if (ret) { DRM_ERROR("Failed to set HSM clock rate: %d\n", ret); @@ -1064,7 +1064,7 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, goto out; } - ret = clk_set_rate(vc4_hdmi->pixel_clock, pixel_rate); + ret = clk_set_rate(vc4_hdmi->pixel_clock, tmds_char_rate); if (ret) { DRM_ERROR("Failed to set pixel clock rate: %d\n", ret); goto err_put_runtime_pm; @@ -1079,9 +1079,9 @@ static void vc4_hdmi_encoder_pre_crtc_configure(struct drm_encoder *encoder, vc4_hdmi_cec_update_clk_div(vc4_hdmi); - if (pixel_rate > 297000000) + if (tmds_char_rate > 297000000) bvb_rate = 300000000; - else if (pixel_rate > 148500000) + else if (tmds_char_rate > 148500000) bvb_rate = 150000000; else bvb_rate = 75000000; @@ -1255,8 +1255,8 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, struct vc4_hdmi_connector_state *vc4_state = conn_state_to_vc4_hdmi_conn_state(conn_state); struct drm_display_mode *mode = &crtc_state->adjusted_mode; struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); - unsigned long long pixel_rate = mode->clock * 1000; - unsigned long long tmds_rate; + unsigned long long tmds_char_rate = mode->clock * 1000; + unsigned long long tmds_bit_rate; if (vc4_hdmi->variant->unsupported_odd_h_timings && ((mode->hdisplay % 2) || (mode->hsync_start % 2) || @@ -1269,32 +1269,32 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, * bandwidth). Slightly lower the frequency to bring it out of * the WiFi range. */ - tmds_rate = pixel_rate * 10; + tmds_bit_rate = tmds_char_rate * 10; if (vc4_hdmi->disable_wifi_frequencies && - (tmds_rate >= WIFI_2_4GHz_CH1_MIN_FREQ && - tmds_rate <= WIFI_2_4GHz_CH1_MAX_FREQ)) { + (tmds_bit_rate >= WIFI_2_4GHz_CH1_MIN_FREQ && + tmds_bit_rate <= WIFI_2_4GHz_CH1_MAX_FREQ)) { mode->clock = 238560; - pixel_rate = mode->clock * 1000; + tmds_char_rate = mode->clock * 1000; } if (conn_state->max_bpc == 12) { - pixel_rate = pixel_rate * 150; - do_div(pixel_rate, 100); + tmds_char_rate = tmds_char_rate * 150; + do_div(tmds_char_rate, 100); } else if (conn_state->max_bpc == 10) { - pixel_rate = pixel_rate * 125; - do_div(pixel_rate, 100); + tmds_char_rate = tmds_char_rate * 125; + do_div(tmds_char_rate, 100); } if (mode->flags & DRM_MODE_FLAG_DBLCLK) - pixel_rate = pixel_rate * 2; + tmds_char_rate = tmds_char_rate * 2; - if (pixel_rate > vc4_hdmi->variant->max_pixel_clock) + if (tmds_char_rate > vc4_hdmi->variant->max_pixel_clock) return -EINVAL; - if (vc4_hdmi->disable_4kp60 && (pixel_rate > HDMI_14_MAX_TMDS_CLK)) + if (vc4_hdmi->disable_4kp60 && (tmds_char_rate > HDMI_14_MAX_TMDS_CLK)) return -EINVAL; - vc4_state->pixel_rate = pixel_rate; + vc4_state->tmds_char_rate = tmds_char_rate; return 0; } diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 2b6aaafc020a..37a87d7e167a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -234,7 +234,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) struct vc4_hdmi_connector_state { struct drm_connector_state base; - unsigned long long pixel_rate; + unsigned long long tmds_char_rate; }; static inline struct vc4_hdmi_connector_state * diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c index 62148f0dc284..ec24999bf96d 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_phy.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi_phy.c @@ -365,7 +365,7 @@ void vc5_hdmi_phy_init(struct vc4_hdmi *vc4_hdmi, { const struct phy_lane_settings *chan0_settings, *chan1_settings, *chan2_settings, *clock_settings; const struct vc4_hdmi_variant *variant = vc4_hdmi->variant; - unsigned long long pixel_freq = conn_state->pixel_rate; + unsigned long long pixel_freq = conn_state->tmds_char_rate; unsigned long long vco_freq; unsigned char word_sel; unsigned long flags; From ccbf364f329cd43c9b148a2613881a8890f97237 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 22 Feb 2022 17:40:37 +0100 Subject: [PATCH 00343/11454] drm/vc4: hdmi: Move clock validation to its own function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our code is doing the same clock rate validation in multiple instances. Let's create a helper to share the rate validation. Signed-off-by: Maxime Ripard Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220222164042.403112-3-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index c70e5059b077..d4cebb524578 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1245,6 +1245,19 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, mutex_unlock(&vc4_hdmi->mutex); } +static enum drm_mode_status +vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, + unsigned long long clock) +{ + if (clock > vc4_hdmi->variant->max_pixel_clock) + return MODE_CLOCK_HIGH; + + if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL #define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL @@ -1288,10 +1301,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, if (mode->flags & DRM_MODE_FLAG_DBLCLK) tmds_char_rate = tmds_char_rate * 2; - if (tmds_char_rate > vc4_hdmi->variant->max_pixel_clock) - return -EINVAL; - - if (vc4_hdmi->disable_4kp60 && (tmds_char_rate > HDMI_14_MAX_TMDS_CLK)) + if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, tmds_char_rate) != MODE_OK) return -EINVAL; vc4_state->tmds_char_rate = tmds_char_rate; @@ -1310,13 +1320,7 @@ vc4_hdmi_encoder_mode_valid(struct drm_encoder *encoder, (mode->hsync_end % 2) || (mode->htotal % 2))) return MODE_H_ILLEGAL; - if ((mode->clock * 1000) > vc4_hdmi->variant->max_pixel_clock) - return MODE_CLOCK_HIGH; - - if (vc4_hdmi->disable_4kp60 && vc4_hdmi_mode_needs_scrambling(mode)) - return MODE_CLOCK_HIGH; - - return MODE_OK; + return vc4_hdmi_encoder_clock_valid(vc4_hdmi, mode->clock * 1000); } static const struct drm_encoder_helper_funcs vc4_hdmi_encoder_helper_funcs = { From 595dcf4eb859d043de9919f50d44272304e75422 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 22 Feb 2022 17:40:38 +0100 Subject: [PATCH 00344/11454] drm/vc4: hdmi: Move clock calculation into its own function MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code to compute our clock rate for a given setup will be called in multiple places in the next patches, so let's create a separate function for it. Signed-off-by: Maxime Ripard Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220222164042.403112-4-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 52 ++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index d4cebb524578..e5d9d54ce20a 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1258,6 +1258,38 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, return MODE_OK; } +static unsigned long long +vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, + unsigned int bpc) +{ + unsigned long long clock = mode->clock * 1000; + + if (mode->flags & DRM_MODE_FLAG_DBLCLK) + clock = clock * 2; + + clock = clock * bpc; + do_div(clock, 8); + + return clock; +} + +static int +vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi, + struct vc4_hdmi_connector_state *vc4_state, + const struct drm_display_mode *mode, + unsigned int bpc) +{ + unsigned long long clock; + + clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc); + if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, clock) != MODE_OK) + return -EINVAL; + + vc4_state->tmds_char_rate = clock; + + return 0; +} + #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL #define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL @@ -1270,6 +1302,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); unsigned long long tmds_char_rate = mode->clock * 1000; unsigned long long tmds_bit_rate; + int ret; if (vc4_hdmi->variant->unsupported_odd_h_timings && ((mode->hdisplay % 2) || (mode->hsync_start % 2) || @@ -1290,21 +1323,10 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, tmds_char_rate = mode->clock * 1000; } - if (conn_state->max_bpc == 12) { - tmds_char_rate = tmds_char_rate * 150; - do_div(tmds_char_rate, 100); - } else if (conn_state->max_bpc == 10) { - tmds_char_rate = tmds_char_rate * 125; - do_div(tmds_char_rate, 100); - } - - if (mode->flags & DRM_MODE_FLAG_DBLCLK) - tmds_char_rate = tmds_char_rate * 2; - - if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, tmds_char_rate) != MODE_OK) - return -EINVAL; - - vc4_state->tmds_char_rate = tmds_char_rate; + ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, mode, + conn_state->max_bpc); + if (ret) + return ret; return 0; } From 15a809211a6971cac5262c309aeadddc158c64d9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 22 Feb 2022 17:40:39 +0100 Subject: [PATCH 00345/11454] drm/vc4: hdmi: Take the sink maximum TMDS clock into account MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the function that validates that the clock isn't too high, we've only taken our controller limitations into account so far. However, the sink can have a limit on the maximum TMDS clock it can deal with too which is exposed through the EDID and the drm_display_info. Make sure we check it. Signed-off-by: Maxime Ripard Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220222164042.403112-5-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index e5d9d54ce20a..e8e70727b5f3 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1249,12 +1249,18 @@ static enum drm_mode_status vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, unsigned long long clock) { + const struct drm_connector *connector = &vc4_hdmi->connector; + const struct drm_display_info *info = &connector->display_info; + if (clock > vc4_hdmi->variant->max_pixel_clock) return MODE_CLOCK_HIGH; if (vc4_hdmi->disable_4kp60 && clock > HDMI_14_MAX_TMDS_CLK) return MODE_CLOCK_HIGH; + if (info->max_tmds_clock && clock > (info->max_tmds_clock * 1000)) + return MODE_CLOCK_HIGH; + return MODE_OK; } From f785dcfc596c378a19af01a6a337b8b67e5e4534 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 22 Feb 2022 17:40:40 +0100 Subject: [PATCH 00346/11454] drm/vc4: hdmi: Take bpp into account for the scrambler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current code only base its decision for whether the scrambler must be enabled or not on the pixel clock of the mode, but doesn't take the bits per color into account. Let's leverage the new function to compute the clock rate in the scrambler setup code. Signed-off-by: Maxime Ripard Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220222164042.403112-6-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 16 ++++++++++++---- drivers/gpu/drm/vc4/vc4_hdmi.h | 5 +++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index e8e70727b5f3..e58488416883 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -99,9 +99,16 @@ #define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) -static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode) +static unsigned long long +vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, + unsigned int bpc); + +static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode, + unsigned int bpc) { - return (mode->clock * 1000) > HDMI_14_MAX_TMDS_CLK; + unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc); + + return clock > HDMI_14_MAX_TMDS_CLK; } static bool vc4_hdmi_is_full_range_rgb(struct vc4_hdmi *vc4_hdmi, @@ -272,7 +279,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) struct drm_display_mode *mode; list_for_each_entry(mode, &connector->probed_modes, head) { - if (vc4_hdmi_mode_needs_scrambling(mode)) { + if (vc4_hdmi_mode_needs_scrambling(mode, 8)) { drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz."); drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60."); } @@ -613,7 +620,7 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) if (!vc4_hdmi_supports_scrambling(encoder, mode)) return; - if (!vc4_hdmi_mode_needs_scrambling(mode)) + if (!vc4_hdmi_mode_needs_scrambling(mode, vc4_hdmi->output_bpc)) return; drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); @@ -1242,6 +1249,7 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, mutex_lock(&vc4_hdmi->mutex); drm_mode_copy(&vc4_hdmi->saved_adjusted_mode, &crtc_state->adjusted_mode); + vc4_hdmi->output_bpc = conn_state->max_bpc; mutex_unlock(&vc4_hdmi->mutex); } diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 37a87d7e167a..cb744bc5489b 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -216,6 +216,11 @@ struct vc4_hdmi { * the scrambler on? Protected by @mutex. */ bool scdc_enabled; + + /** + * @output_bpc: BPC currently being used. Protected by @mutex. + */ + unsigned int output_bpc; }; static inline struct vc4_hdmi * From dd39d024a8471e88951f8494f19e693c9e3185a9 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 22 Feb 2022 17:40:41 +0100 Subject: [PATCH 00347/11454] drm/vc4: hdmi: Always try to have the highest bpc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we take the max_bpc property as the bpc value and do not try anything else. However, what the other drivers seem to be doing is that they would try with the highest bpc allowed by the max_bpc property and the hardware capabilities, test if it results in an acceptable configuration, and if not decrease the bpc and try again. Let's use the same logic. Signed-off-by: Maxime Ripard Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220222164042.403112-7-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 44 ++++++++++++++++++++++++++++++---- drivers/gpu/drm/vc4/vc4_hdmi.h | 4 +++- 2 files changed, 43 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index e58488416883..da36f529e7c2 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -351,6 +351,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) return NULL; new_state->tmds_char_rate = vc4_state->tmds_char_rate; + new_state->output_bpc = vc4_state->output_bpc; __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); return &new_state->base; @@ -905,6 +906,8 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, struct drm_display_mode *mode) { + const struct vc4_hdmi_connector_state *vc4_state = + conn_state_to_vc4_hdmi_conn_state(state); bool hsync_pos = mode->flags & DRM_MODE_FLAG_PHSYNC; bool vsync_pos = mode->flags & DRM_MODE_FLAG_PVSYNC; bool interlaced = mode->flags & DRM_MODE_FLAG_INTERLACE; @@ -952,7 +955,7 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, HDMI_WRITE(HDMI_VERTB0, vertb_even); HDMI_WRITE(HDMI_VERTB1, vertb); - switch (state->max_bpc) { + switch (vc4_state->output_bpc) { case 12: gcp = 6; gcp_en = true; @@ -1245,11 +1248,13 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, struct drm_connector_state *conn_state) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); + struct vc4_hdmi_connector_state *vc4_state = + conn_state_to_vc4_hdmi_conn_state(conn_state); mutex_lock(&vc4_hdmi->mutex); drm_mode_copy(&vc4_hdmi->saved_adjusted_mode, &crtc_state->adjusted_mode); - vc4_hdmi->output_bpc = conn_state->max_bpc; + vc4_hdmi->output_bpc = vc4_state->output_bpc; mutex_unlock(&vc4_hdmi->mutex); } @@ -1304,6 +1309,38 @@ vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi, return 0; } +static int +vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi, + struct vc4_hdmi_connector_state *vc4_state, + const struct drm_display_mode *mode) +{ + struct drm_connector_state *conn_state = &vc4_state->base; + unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12); + unsigned int bpc; + int ret; + + for (bpc = max_bpc; bpc >= 8; bpc -= 2) { + drm_dbg(dev, "Trying with a %d bpc output\n", bpc); + + ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, + mode, bpc); + if (ret) + continue; + + vc4_state->output_bpc = bpc; + + drm_dbg(dev, + "Mode %ux%u @ %uHz: Found configuration: bpc: %u, clock: %llu\n", + mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), + vc4_state->output_bpc, + vc4_state->tmds_char_rate); + + break; + } + + return ret; +} + #define WIFI_2_4GHz_CH1_MIN_FREQ 2400000000ULL #define WIFI_2_4GHz_CH1_MAX_FREQ 2422000000ULL @@ -1337,8 +1374,7 @@ static int vc4_hdmi_encoder_atomic_check(struct drm_encoder *encoder, tmds_char_rate = mode->clock * 1000; } - ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, mode, - conn_state->max_bpc); + ret = vc4_hdmi_encoder_compute_config(vc4_hdmi, vc4_state, mode); if (ret) return ret; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index cb744bc5489b..79a1a10c40a8 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -218,7 +218,8 @@ struct vc4_hdmi { bool scdc_enabled; /** - * @output_bpc: BPC currently being used. Protected by @mutex. + * @output_bpc: Copy of @vc4_connector_state.output_bpc for use + * outside of KMS hooks. Protected by @mutex. */ unsigned int output_bpc; }; @@ -240,6 +241,7 @@ encoder_to_vc4_hdmi(struct drm_encoder *encoder) struct vc4_hdmi_connector_state { struct drm_connector_state base; unsigned long long tmds_char_rate; + unsigned int output_bpc; }; static inline struct vc4_hdmi_connector_state * From e769a3504e273309c9fe4a417d427c8dbff4cf1c Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Tue, 22 Feb 2022 17:40:42 +0100 Subject: [PATCH 00348/11454] drm/vc4: hdmi: Support HDMI YUV output MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In addition to the RGB444 output, the BCM2711 HDMI controller supports the YUV444 and YUV422 output formats. Let's add support for them in the driver, but still use RGB as the preferred format. Signed-off-by: Maxime Ripard Acked-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220222164042.403112-8-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_hdmi.c | 291 ++++++++++++++++++++++++++-- drivers/gpu/drm/vc4/vc4_hdmi.h | 14 ++ drivers/gpu/drm/vc4/vc4_hdmi_regs.h | 6 + drivers/gpu/drm/vc4/vc4_regs.h | 16 ++ 4 files changed, 311 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index da36f529e7c2..cf4ba83420d5 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -99,14 +99,30 @@ #define HDMI_14_MAX_TMDS_CLK (340 * 1000 * 1000) +static const char * const output_format_str[] = { + [VC4_HDMI_OUTPUT_RGB] = "RGB", + [VC4_HDMI_OUTPUT_YUV420] = "YUV 4:2:0", + [VC4_HDMI_OUTPUT_YUV422] = "YUV 4:2:2", + [VC4_HDMI_OUTPUT_YUV444] = "YUV 4:4:4", +}; + +static const char *vc4_hdmi_output_fmt_str(enum vc4_hdmi_output_format fmt) +{ + if (fmt >= ARRAY_SIZE(output_format_str)) + return "invalid"; + + return output_format_str[fmt]; +} + static unsigned long long vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, - unsigned int bpc); + unsigned int bpc, enum vc4_hdmi_output_format fmt); static bool vc4_hdmi_mode_needs_scrambling(const struct drm_display_mode *mode, - unsigned int bpc) + unsigned int bpc, + enum vc4_hdmi_output_format fmt) { - unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc); + unsigned long long clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); return clock > HDMI_14_MAX_TMDS_CLK; } @@ -279,7 +295,7 @@ static int vc4_hdmi_connector_get_modes(struct drm_connector *connector) struct drm_display_mode *mode; list_for_each_entry(mode, &connector->probed_modes, head) { - if (vc4_hdmi_mode_needs_scrambling(mode, 8)) { + if (vc4_hdmi_mode_needs_scrambling(mode, 8, VC4_HDMI_OUTPUT_RGB)) { drm_warn_once(drm, "The core clock cannot reach frequencies high enough to support 4k @ 60Hz."); drm_warn_once(drm, "Please change your config.txt file to add hdmi_enable_4kp60."); } @@ -336,6 +352,7 @@ static void vc4_hdmi_connector_reset(struct drm_connector *connector) new_state->base.max_bpc = 8; new_state->base.max_requested_bpc = 8; + new_state->output_format = VC4_HDMI_OUTPUT_RGB; drm_atomic_helper_connector_tv_reset(connector); } @@ -352,6 +369,7 @@ vc4_hdmi_connector_duplicate_state(struct drm_connector *connector) new_state->tmds_char_rate = vc4_state->tmds_char_rate; new_state->output_bpc = vc4_state->output_bpc; + new_state->output_format = vc4_state->output_format; __drm_atomic_helper_connector_duplicate_state(connector, &new_state->base); return &new_state->base; @@ -495,11 +513,38 @@ static void vc4_hdmi_write_infoframe(struct drm_encoder *encoder, DRM_ERROR("Failed to wait for infoframe to start: %d\n", ret); } +static void vc4_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame, + enum vc4_hdmi_output_format fmt) +{ + switch (fmt) { + case VC4_HDMI_OUTPUT_RGB: + frame->colorspace = HDMI_COLORSPACE_RGB; + break; + + case VC4_HDMI_OUTPUT_YUV420: + frame->colorspace = HDMI_COLORSPACE_YUV420; + break; + + case VC4_HDMI_OUTPUT_YUV422: + frame->colorspace = HDMI_COLORSPACE_YUV422; + break; + + case VC4_HDMI_OUTPUT_YUV444: + frame->colorspace = HDMI_COLORSPACE_YUV444; + break; + + default: + break; + } +} + static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) { struct vc4_hdmi *vc4_hdmi = encoder_to_vc4_hdmi(encoder); struct drm_connector *connector = &vc4_hdmi->connector; struct drm_connector_state *cstate = connector->state; + struct vc4_hdmi_connector_state *vc4_state = + conn_state_to_vc4_hdmi_conn_state(cstate); const struct drm_display_mode *mode = &vc4_hdmi->saved_adjusted_mode; union hdmi_infoframe frame; int ret; @@ -519,6 +564,7 @@ static void vc4_hdmi_set_avi_infoframe(struct drm_encoder *encoder) HDMI_QUANTIZATION_RANGE_FULL : HDMI_QUANTIZATION_RANGE_LIMITED); drm_hdmi_avi_infoframe_colorimetry(&frame.avi, cstate); + vc4_hdmi_avi_infoframe_colorspace(&frame.avi, vc4_state->output_format); drm_hdmi_avi_infoframe_bars(&frame.avi, cstate); vc4_hdmi_write_infoframe(encoder, &frame); @@ -621,7 +667,9 @@ static void vc4_hdmi_enable_scrambling(struct drm_encoder *encoder) if (!vc4_hdmi_supports_scrambling(encoder, mode)) return; - if (!vc4_hdmi_mode_needs_scrambling(mode, vc4_hdmi->output_bpc)) + if (!vc4_hdmi_mode_needs_scrambling(mode, + vc4_hdmi->output_bpc, + vc4_hdmi->output_format)) return; drm_scdc_set_high_tmds_clock_ratio(vc4_hdmi->ddc, true); @@ -816,6 +864,39 @@ static const u16 vc5_hdmi_csc_full_rgb_to_limited_rgb[3][4] = { { 0x0000, 0x0000, 0x1b80, 0x0400 }, }; +/* + * Conversion between Full Range RGB and Full Range YUV422 using the + * BT.709 Colorspace + * + * + * [ 0.181906 0.611804 0.061758 16 ] + * [ -0.100268 -0.337232 0.437500 128 ] + * [ 0.437500 -0.397386 -0.040114 128 ] + * + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets + */ +static const u16 vc5_hdmi_csc_full_rgb_to_limited_yuv422_bt709[3][4] = { + { 0x05d2, 0x1394, 0x01fa, 0x0400 }, + { 0xfccc, 0xf536, 0x0e00, 0x2000 }, + { 0x0e00, 0xf34a, 0xfeb8, 0x2000 }, +}; + +/* + * Conversion between Full Range RGB and Full Range YUV444 using the + * BT.709 Colorspace + * + * [ -0.100268 -0.337232 0.437500 128 ] + * [ 0.437500 -0.397386 -0.040114 128 ] + * [ 0.181906 0.611804 0.061758 16 ] + * + * Matrix is signed 2p13 fixed point, with signed 9p6 offsets + */ +static const u16 vc5_hdmi_csc_full_rgb_to_limited_yuv444_bt709[3][4] = { + { 0xfccc, 0xf536, 0x0e00, 0x2000 }, + { 0x0e00, 0xf34a, 0xfeb8, 0x2000 }, + { 0x05d2, 0x1394, 0x01fa, 0x0400 }, +}; + static void vc5_hdmi_set_csc_coeffs(struct vc4_hdmi *vc4_hdmi, const u16 coeffs[3][4]) { @@ -833,19 +914,53 @@ static void vc5_hdmi_csc_setup(struct vc4_hdmi *vc4_hdmi, struct drm_connector_state *state, const struct drm_display_mode *mode) { + struct vc4_hdmi_connector_state *vc4_state = + conn_state_to_vc4_hdmi_conn_state(state); unsigned long flags; + u32 if_cfg = 0; + u32 if_xbar = 0x543210; + u32 csc_chan_ctl = 0; u32 csc_ctl = VC5_MT_CP_CSC_CTL_ENABLE | VC4_SET_FIELD(VC4_HD_CSC_CTL_MODE_CUSTOM, VC5_MT_CP_CSC_CTL_MODE); spin_lock_irqsave(&vc4_hdmi->hw_lock, flags); - HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, 0x354021); + switch (vc4_state->output_format) { + case VC4_HDMI_OUTPUT_YUV444: + vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_yuv444_bt709); + break; - if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) - vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb); - else - vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity); + case VC4_HDMI_OUTPUT_YUV422: + csc_ctl |= VC4_SET_FIELD(VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD, + VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422) | + VC5_MT_CP_CSC_CTL_USE_444_TO_422 | + VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION; + csc_chan_ctl |= VC4_SET_FIELD(VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE, + VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP); + + if_cfg |= VC4_SET_FIELD(VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY, + VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422); + + vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_yuv422_bt709); + break; + + case VC4_HDMI_OUTPUT_RGB: + if_xbar = 0x354021; + + if (!vc4_hdmi_is_full_range_rgb(vc4_hdmi, mode)) + vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_to_limited_rgb); + else + vc5_hdmi_set_csc_coeffs(vc4_hdmi, vc5_hdmi_csc_full_rgb_unity); + break; + + default: + break; + } + + HDMI_WRITE(HDMI_VEC_INTERFACE_CFG, if_cfg); + HDMI_WRITE(HDMI_VEC_INTERFACE_XBAR, if_xbar); + HDMI_WRITE(HDMI_CSC_CHANNEL_CTL, csc_chan_ctl); HDMI_WRITE(HDMI_CSC_CTL, csc_ctl); spin_unlock_irqrestore(&vc4_hdmi->hw_lock, flags); @@ -971,6 +1086,15 @@ static void vc5_hdmi_set_timings(struct vc4_hdmi *vc4_hdmi, break; } + /* + * YCC422 is always 36-bit and not considered deep colour so + * doesn't signal in GCP. + */ + if (vc4_state->output_format == VC4_HDMI_OUTPUT_YUV422) { + gcp = 4; + gcp_en = false; + } + reg = HDMI_READ(HDMI_DEEP_COLOR_CONFIG_1); reg &= ~(VC5_HDMI_DEEP_COLOR_CONFIG_1_INIT_PACK_PHASE_MASK | VC5_HDMI_DEEP_COLOR_CONFIG_1_COLOR_DEPTH_MASK); @@ -1255,9 +1379,94 @@ static void vc4_hdmi_encoder_atomic_mode_set(struct drm_encoder *encoder, drm_mode_copy(&vc4_hdmi->saved_adjusted_mode, &crtc_state->adjusted_mode); vc4_hdmi->output_bpc = vc4_state->output_bpc; + vc4_hdmi->output_format = vc4_state->output_format; mutex_unlock(&vc4_hdmi->mutex); } +static bool +vc4_hdmi_sink_supports_format_bpc(const struct vc4_hdmi *vc4_hdmi, + const struct drm_display_info *info, + const struct drm_display_mode *mode, + unsigned int format, unsigned int bpc) +{ + struct drm_device *dev = vc4_hdmi->connector.dev; + u8 vic = drm_match_cea_mode(mode); + + if (vic == 1 && bpc != 8) { + drm_dbg(dev, "VIC1 requires a bpc of 8, got %u\n", bpc); + return false; + } + + if (!info->is_hdmi && + (format != VC4_HDMI_OUTPUT_RGB || bpc != 8)) { + drm_dbg(dev, "DVI Monitors require an RGB output at 8 bpc\n"); + return false; + } + + switch (format) { + case VC4_HDMI_OUTPUT_RGB: + drm_dbg(dev, "RGB Format, checking the constraints.\n"); + + if (!(info->color_formats & DRM_COLOR_FORMAT_RGB444)) + return false; + + if (bpc == 10 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30)) { + drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); + return false; + } + + if (bpc == 12 && !(info->edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_36)) { + drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); + return false; + } + + drm_dbg(dev, "RGB format supported in that configuration.\n"); + + return true; + + case VC4_HDMI_OUTPUT_YUV422: + drm_dbg(dev, "YUV422 format, checking the constraints.\n"); + + if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR422)) { + drm_dbg(dev, "Sink doesn't support YUV422.\n"); + return false; + } + + if (bpc != 12) { + drm_dbg(dev, "YUV422 only supports 12 bpc.\n"); + return false; + } + + drm_dbg(dev, "YUV422 format supported in that configuration.\n"); + + return true; + + case VC4_HDMI_OUTPUT_YUV444: + drm_dbg(dev, "YUV444 format, checking the constraints.\n"); + + if (!(info->color_formats & DRM_COLOR_FORMAT_YCBCR444)) { + drm_dbg(dev, "Sink doesn't support YUV444.\n"); + return false; + } + + if (bpc == 10 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_30)) { + drm_dbg(dev, "10 BPC but sink doesn't support Deep Color 30.\n"); + return false; + } + + if (bpc == 12 && !(info->edid_hdmi_ycbcr444_dc_modes & DRM_EDID_HDMI_DC_36)) { + drm_dbg(dev, "12 BPC but sink doesn't support Deep Color 36.\n"); + return false; + } + + drm_dbg(dev, "YUV444 format supported in that configuration.\n"); + + return true; + } + + return false; +} + static enum drm_mode_status vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, unsigned long long clock) @@ -1279,13 +1488,17 @@ vc4_hdmi_encoder_clock_valid(const struct vc4_hdmi *vc4_hdmi, static unsigned long long vc4_hdmi_encoder_compute_mode_clock(const struct drm_display_mode *mode, - unsigned int bpc) + unsigned int bpc, + enum vc4_hdmi_output_format fmt) { unsigned long long clock = mode->clock * 1000; if (mode->flags & DRM_MODE_FLAG_DBLCLK) clock = clock * 2; + if (fmt == VC4_HDMI_OUTPUT_YUV422) + bpc = 8; + clock = clock * bpc; do_div(clock, 8); @@ -1296,11 +1509,11 @@ static int vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi, struct vc4_hdmi_connector_state *vc4_state, const struct drm_display_mode *mode, - unsigned int bpc) + unsigned int bpc, unsigned int fmt) { unsigned long long clock; - clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc); + clock = vc4_hdmi_encoder_compute_mode_clock(mode, bpc, fmt); if (vc4_hdmi_encoder_clock_valid(vc4_hdmi, clock) != MODE_OK) return -EINVAL; @@ -1309,11 +1522,56 @@ vc4_hdmi_encoder_compute_clock(const struct vc4_hdmi *vc4_hdmi, return 0; } +static int +vc4_hdmi_encoder_compute_format(const struct vc4_hdmi *vc4_hdmi, + struct vc4_hdmi_connector_state *vc4_state, + const struct drm_display_mode *mode, + unsigned int bpc) +{ + struct drm_device *dev = vc4_hdmi->connector.dev; + const struct drm_connector *connector = &vc4_hdmi->connector; + const struct drm_display_info *info = &connector->display_info; + unsigned int format; + + drm_dbg(dev, "Trying with an RGB output\n"); + + format = VC4_HDMI_OUTPUT_RGB; + if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { + int ret; + + ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, + mode, bpc, format); + if (!ret) { + vc4_state->output_format = format; + return 0; + } + } + + drm_dbg(dev, "Failed, Trying with an YUV422 output\n"); + + format = VC4_HDMI_OUTPUT_YUV422; + if (vc4_hdmi_sink_supports_format_bpc(vc4_hdmi, info, mode, format, bpc)) { + int ret; + + ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, + mode, bpc, format); + if (!ret) { + vc4_state->output_format = format; + return 0; + } + } + + drm_dbg(dev, "Failed. No Format Supported for that bpc count.\n"); + + return -EINVAL; +} + static int vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi, struct vc4_hdmi_connector_state *vc4_state, const struct drm_display_mode *mode) { + struct drm_device *dev = vc4_hdmi->connector.dev; struct drm_connector_state *conn_state = &vc4_state->base; unsigned int max_bpc = clamp_t(unsigned int, conn_state->max_bpc, 8, 12); unsigned int bpc; @@ -1322,17 +1580,18 @@ vc4_hdmi_encoder_compute_config(const struct vc4_hdmi *vc4_hdmi, for (bpc = max_bpc; bpc >= 8; bpc -= 2) { drm_dbg(dev, "Trying with a %d bpc output\n", bpc); - ret = vc4_hdmi_encoder_compute_clock(vc4_hdmi, vc4_state, - mode, bpc); + ret = vc4_hdmi_encoder_compute_format(vc4_hdmi, vc4_state, + mode, bpc); if (ret) continue; vc4_state->output_bpc = bpc; drm_dbg(dev, - "Mode %ux%u @ %uHz: Found configuration: bpc: %u, clock: %llu\n", + "Mode %ux%u @ %uHz: Found configuration: bpc: %u, fmt: %s, clock: %llu\n", mode->hdisplay, mode->vdisplay, drm_mode_vrefresh(mode), vc4_state->output_bpc, + vc4_hdmi_output_fmt_str(vc4_state->output_format), vc4_state->tmds_char_rate); break; diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.h b/drivers/gpu/drm/vc4/vc4_hdmi.h index 79a1a10c40a8..b642971a811e 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi.h @@ -117,6 +117,13 @@ struct vc4_hdmi_audio { bool streaming; }; +enum vc4_hdmi_output_format { + VC4_HDMI_OUTPUT_RGB, + VC4_HDMI_OUTPUT_YUV422, + VC4_HDMI_OUTPUT_YUV444, + VC4_HDMI_OUTPUT_YUV420, +}; + /* General HDMI hardware state. */ struct vc4_hdmi { struct vc4_hdmi_audio audio; @@ -222,6 +229,12 @@ struct vc4_hdmi { * outside of KMS hooks. Protected by @mutex. */ unsigned int output_bpc; + + /** + * @output_format: Copy of @vc4_connector_state.output_format + * for use outside of KMS hooks. Protected by @mutex. + */ + enum vc4_hdmi_output_format output_format; }; static inline struct vc4_hdmi * @@ -242,6 +255,7 @@ struct vc4_hdmi_connector_state { struct drm_connector_state base; unsigned long long tmds_char_rate; unsigned int output_bpc; + enum vc4_hdmi_output_format output_format; }; static inline struct vc4_hdmi_connector_state * diff --git a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h index fc971506bd4f..a040356b6bdc 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi_regs.h +++ b/drivers/gpu/drm/vc4/vc4_hdmi_regs.h @@ -54,6 +54,7 @@ enum vc4_hdmi_field { HDMI_CSC_24_23, HDMI_CSC_32_31, HDMI_CSC_34_33, + HDMI_CSC_CHANNEL_CTL, HDMI_CSC_CTL, /* @@ -119,6 +120,7 @@ enum vc4_hdmi_field { HDMI_TX_PHY_POWERDOWN_CTL, HDMI_TX_PHY_RESET_CTL, HDMI_TX_PHY_TMDS_CLK_WORD_SEL, + HDMI_VEC_INTERFACE_CFG, HDMI_VEC_INTERFACE_XBAR, HDMI_VERTA0, HDMI_VERTA1, @@ -244,6 +246,7 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi0_fields[] = { VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4), VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), + VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec), VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), @@ -289,6 +292,7 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi0_fields[] = { VC5_CSC_REG(HDMI_CSC_24_23, 0x010), VC5_CSC_REG(HDMI_CSC_32_31, 0x014), VC5_CSC_REG(HDMI_CSC_34_33, 0x018), + VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), }; static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi1_fields[] = { @@ -324,6 +328,7 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi1_fields[] = { VC4_HDMI_REG(HDMI_SCRAMBLER_CTL, 0x1c4), VC5_DVP_REG(HDMI_CLOCK_STOP, 0x0bc), + VC5_DVP_REG(HDMI_VEC_INTERFACE_CFG, 0x0ec), VC5_DVP_REG(HDMI_VEC_INTERFACE_XBAR, 0x0f0), VC5_PHY_REG(HDMI_TX_PHY_RESET_CTL, 0x000), @@ -369,6 +374,7 @@ static const struct vc4_hdmi_register __maybe_unused vc5_hdmi_hdmi1_fields[] = { VC5_CSC_REG(HDMI_CSC_24_23, 0x010), VC5_CSC_REG(HDMI_CSC_32_31, 0x014), VC5_CSC_REG(HDMI_CSC_34_33, 0x018), + VC5_CSC_REG(HDMI_CSC_CHANNEL_CTL, 0x02c), }; static inline diff --git a/drivers/gpu/drm/vc4/vc4_regs.h b/drivers/gpu/drm/vc4/vc4_regs.h index 33410718089e..c8210247cf24 100644 --- a/drivers/gpu/drm/vc4/vc4_regs.h +++ b/drivers/gpu/drm/vc4/vc4_regs.h @@ -774,11 +774,27 @@ enum { # define VC4_HD_CSC_CTL_RGB2YCC BIT(1) # define VC4_HD_CSC_CTL_ENABLE BIT(0) +# define VC5_MT_CP_CSC_CTL_USE_444_TO_422 BIT(6) +# define VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_MASK \ + VC4_MASK(5, 4) +# define VC5_MT_CP_CSC_CTL_FILTER_MODE_444_TO_422_STANDARD \ + 3 +# define VC5_MT_CP_CSC_CTL_USE_RNG_SUPPRESSION BIT(3) # define VC5_MT_CP_CSC_CTL_ENABLE BIT(2) # define VC5_MT_CP_CSC_CTL_MODE_MASK VC4_MASK(1, 0) +# define VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_MASK \ + VC4_MASK(7, 6) +# define VC5_MT_CP_CHANNEL_CTL_OUTPUT_REMAP_LEGACY_STYLE \ + 2 + # define VC4_DVP_HT_CLOCK_STOP_PIXEL BIT(1) +# define VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_MASK \ + VC4_MASK(3, 2) +# define VC5_DVP_HT_VEC_INTERFACE_CFG_SEL_422_FORMAT_422_LEGACY \ + 2 + /* HVS display list information. */ #define HVS_BOOTLOADER_DLIST_END 32 From 62abdc06c50eb18e3fa62f7136e66842a96f6b58 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Wed, 23 Mar 2022 11:14:16 +0200 Subject: [PATCH 00349/11454] ath11k: add fallback board name without variant while searching board-2.bin Sometimes it has a variant value which read from DT or SMBIOS by ath11k, and meanwhile it does not have the matched board name in board-2.bin, then it will failed at boot up phase. Add fallback board name which removed variant value and search again in board-2.bin when failed with variant and try to load the board data again to increase boot up success rate. dmesg log after this patch: [169547.248472] ath11k_pci 0000:05:00.0: boot using board name 'bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262,variant=test' [169547.248565] ath11k_pci 0000:05:00.0: boot firmware request ath11k/WCN6855/hw2.0/board-2.bin size 180324 [169547.248568] ath11k_pci 0000:05:00.0: board name [169547.248570] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 76 65 6e 64 6f 72 3d 31 bus=pci,vendor=1 [169547.248571] ath11k_pci 0000:05:00.0: 00000010: 37 63 62 2c 64 65 76 69 63 65 3d 31 31 30 33 2c 7cb,device=1103, [169547.248572] ath11k_pci 0000:05:00.0: 00000020: 73 75 62 73 79 73 74 65 6d 2d 76 65 6e 64 6f 72 subsystem-vendor [169547.248574] ath11k_pci 0000:05:00.0: 00000030: 3d 31 37 63 62 2c 73 75 62 73 79 73 74 65 6d 2d =17cb,subsystem- [169547.248575] ath11k_pci 0000:05:00.0: 00000040: 64 65 76 69 63 65 3d 33 33 37 34 2c 71 6d 69 2d device=3374,qmi- [169547.248576] ath11k_pci 0000:05:00.0: 00000050: 63 68 69 70 2d 69 64 3d 32 2c 71 6d 69 2d 62 6f chip-id=2,qmi-bo [169547.248577] ath11k_pci 0000:05:00.0: 00000060: 61 72 64 2d 69 64 3d 32 36 32 ard-id=262 [169547.248578] ath11k_pci 0000:05:00.0: board name [169547.248579] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 76 65 6e 64 6f 72 3d 31 bus=pci,vendor=1 [169547.248581] ath11k_pci 0000:05:00.0: 00000010: 37 63 62 2c 64 65 76 69 63 65 3d 31 31 30 33 2c 7cb,device=1103, [169547.248582] ath11k_pci 0000:05:00.0: 00000020: 73 75 62 73 79 73 74 65 6d 2d 76 65 6e 64 6f 72 subsystem-vendor [169547.248583] ath11k_pci 0000:05:00.0: 00000030: 3d 31 37 63 62 2c 73 75 62 73 79 73 74 65 6d 2d =17cb,subsystem- [169547.248584] ath11k_pci 0000:05:00.0: 00000040: 64 65 76 69 63 65 3d 33 33 37 34 2c 71 6d 69 2d device=3374,qmi- [169547.248585] ath11k_pci 0000:05:00.0: 00000050: 63 68 69 70 2d 69 64 3d 32 2c 71 6d 69 2d 62 6f chip-id=2,qmi-bo [169547.248587] ath11k_pci 0000:05:00.0: 00000060: 61 72 64 2d 69 64 3d 32 36 36 ard-id=266 [169547.248588] ath11k_pci 0000:05:00.0: board name [169547.248589] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 76 65 6e 64 6f 72 3d 31 bus=pci,vendor=1 [169547.248590] ath11k_pci 0000:05:00.0: 00000010: 37 63 62 2c 64 65 76 69 63 65 3d 31 31 30 33 2c 7cb,device=1103, [169547.248591] ath11k_pci 0000:05:00.0: 00000020: 73 75 62 73 79 73 74 65 6d 2d 76 65 6e 64 6f 72 subsystem-vendor [169547.248592] ath11k_pci 0000:05:00.0: 00000030: 3d 31 37 63 62 2c 73 75 62 73 79 73 74 65 6d 2d =17cb,subsystem- [169547.248594] ath11k_pci 0000:05:00.0: 00000040: 64 65 76 69 63 65 3d 33 33 37 34 2c 71 6d 69 2d device=3374,qmi- [169547.248595] ath11k_pci 0000:05:00.0: 00000050: 63 68 69 70 2d 69 64 3d 31 38 2c 71 6d 69 2d 62 chip-id=18,qmi-b [169547.248596] ath11k_pci 0000:05:00.0: 00000060: 6f 61 72 64 2d 69 64 3d 32 36 36 oard-id=266 [169547.248597] ath11k_pci 0000:05:00.0: failed to fetch board data for bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262,variant=test from ath11k/WCN6855/hw2.0/board-2.bin [169547.248476] ath11k_pci 0000:05:00.0: boot using board name 'bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262' [169547.248634] ath11k_pci 0000:05:00.0: boot firmware request ath11k/WCN6855/hw2.0/board-2.bin size 180324 [169547.248636] ath11k_pci 0000:05:00.0: board name [169547.248637] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 76 65 6e 64 6f 72 3d 31 bus=pci,vendor=1 [169547.248638] ath11k_pci 0000:05:00.0: 00000010: 37 63 62 2c 64 65 76 69 63 65 3d 31 31 30 33 2c 7cb,device=1103, [169547.248639] ath11k_pci 0000:05:00.0: 00000020: 73 75 62 73 79 73 74 65 6d 2d 76 65 6e 64 6f 72 subsystem-vendor [169547.248641] ath11k_pci 0000:05:00.0: 00000030: 3d 31 37 63 62 2c 73 75 62 73 79 73 74 65 6d 2d =17cb,subsystem- [169547.248642] ath11k_pci 0000:05:00.0: 00000040: 64 65 76 69 63 65 3d 33 33 37 34 2c 71 6d 69 2d device=3374,qmi- [169547.248643] ath11k_pci 0000:05:00.0: 00000050: 63 68 69 70 2d 69 64 3d 32 2c 71 6d 69 2d 62 6f chip-id=2,qmi-bo [169547.248645] ath11k_pci 0000:05:00.0: 00000060: 61 72 64 2d 69 64 3d 32 36 32 ard-id=262 [169547.248646] ath11k_pci 0000:05:00.0: boot found match for name 'bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262' [169547.248647] ath11k_pci 0000:05:00.0: boot found board data for 'bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262' [169547.248649] ath11k_pci 0000:05:00.0: using board api 2 Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220315104721.26649-2-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 48 ++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 9cfba73b9e22..6e7f952b315d 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -571,13 +571,13 @@ int ath11k_core_check_dt(struct ath11k_base *ab) return 0; } -static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, - size_t name_len) +static int __ath11k_core_create_board_name(struct ath11k_base *ab, char *name, + size_t name_len, bool with_variant) { /* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */ char variant[9 + ATH11K_QMI_BDF_EXT_STR_LENGTH] = { 0 }; - if (ab->qmi.target.bdf_ext[0] != '\0') + if (with_variant && ab->qmi.target.bdf_ext[0] != '\0') scnprintf(variant, sizeof(variant), ",variant=%s", ab->qmi.target.bdf_ext); @@ -607,6 +607,18 @@ static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, return 0; } +static int ath11k_core_create_board_name(struct ath11k_base *ab, char *name, + size_t name_len) +{ + return __ath11k_core_create_board_name(ab, name, name_len, true); +} + +static int ath11k_core_create_fallback_board_name(struct ath11k_base *ab, char *name, + size_t name_len) +{ + return __ath11k_core_create_board_name(ab, name, name_len, false); +} + const struct firmware *ath11k_core_firmware_request(struct ath11k_base *ab, const char *file) { @@ -810,7 +822,7 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, out: if (!bd->data || !bd->len) { - ath11k_err(ab, + ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch board data for %s from %s\n", boardname, filepath); ret = -ENODATA; @@ -842,10 +854,13 @@ int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab, #define BOARD_NAME_SIZE 200 int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) { - char boardname[BOARD_NAME_SIZE]; + char boardname[BOARD_NAME_SIZE], fallback_boardname[BOARD_NAME_SIZE]; + char *filename, filepath[100]; int ret; - ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE); + filename = ATH11K_BOARD_API2_FILE; + + ret = ath11k_core_create_board_name(ab, boardname, sizeof(boardname)); if (ret) { ath11k_err(ab, "failed to create board name: %d", ret); return ret; @@ -856,10 +871,29 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) if (!ret) goto success; + ret = ath11k_core_create_fallback_board_name(ab, fallback_boardname, + sizeof(fallback_boardname)); + if (ret) { + ath11k_err(ab, "failed to create fallback board name: %d", ret); + return ret; + } + + ret = ath11k_core_fetch_board_data_api_n(ab, bd, fallback_boardname); + if (!ret) + goto success; + ab->bd_api = 1; ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_DEFAULT_BOARD_FILE); if (ret) { - ath11k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n", + ath11k_core_create_firmware_path(ab, filename, + filepath, sizeof(filepath)); + ath11k_err(ab, "failed to fetch board data for %s from %s\n", + boardname, filepath); + if (memcmp(boardname, fallback_boardname, strlen(boardname))) + ath11k_err(ab, "failed to fetch board data for %s from %s\n", + fallback_boardname, filepath); + + ath11k_err(ab, "failed to fetch board.bin from %s\n", ab->hw_params.fw.dir); return ret; } From 9d97114d222047c0699bbdbf8f128907f423bbe6 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Wed, 23 Mar 2022 11:14:17 +0200 Subject: [PATCH 00350/11454] ath11k: add read variant from SMBIOS for download board data This is to read variant from SMBIOS such as read from DT, the variant string will be used to one part of string which used to search board data from board-2.bin. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220315104721.26649-3-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 70 ++++++++++++++++++++++++++ drivers/net/wireless/ath/ath11k/core.h | 20 +++++++- drivers/net/wireless/ath/ath11k/qmi.c | 4 ++ 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 6e7f952b315d..7b91b029074f 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -9,6 +9,7 @@ #include #include #include + #include "core.h" #include "dp_tx.h" #include "dp_rx.h" @@ -548,6 +549,75 @@ int ath11k_core_resume(struct ath11k_base *ab) } EXPORT_SYMBOL(ath11k_core_resume); +static void ath11k_core_check_bdfext(const struct dmi_header *hdr, void *data) +{ + struct ath11k_base *ab = data; + const char *magic = ATH11K_SMBIOS_BDF_EXT_MAGIC; + struct ath11k_smbios_bdf *smbios = (struct ath11k_smbios_bdf *)hdr; + ssize_t copied; + size_t len; + int i; + + if (ab->qmi.target.bdf_ext[0] != '\0') + return; + + if (hdr->type != ATH11K_SMBIOS_BDF_EXT_TYPE) + return; + + if (hdr->length != ATH11K_SMBIOS_BDF_EXT_LENGTH) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "wrong smbios bdf ext type length (%d).\n", + hdr->length); + return; + } + + if (!smbios->bdf_enabled) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, "bdf variant name not found.\n"); + return; + } + + /* Only one string exists (per spec) */ + if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "bdf variant magic does not match.\n"); + return; + } + + len = min_t(size_t, + strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext)); + for (i = 0; i < len; i++) { + if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "bdf variant name contains non ascii chars.\n"); + return; + } + } + + /* Copy extension name without magic prefix */ + copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic), + sizeof(ab->qmi.target.bdf_ext)); + if (copied < 0) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "bdf variant string is longer than the buffer can accommodate\n"); + return; + } + + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "found and validated bdf variant smbios_type 0x%x bdf %s\n", + ATH11K_SMBIOS_BDF_EXT_TYPE, ab->qmi.target.bdf_ext); +} + +int ath11k_core_check_smbios(struct ath11k_base *ab) +{ + ab->qmi.target.bdf_ext[0] = '\0'; + dmi_walk(ath11k_core_check_bdfext, ab); + + if (ab->qmi.target.bdf_ext[0] == '\0') + return -ENODATA; + + return 0; +} + int ath11k_core_check_dt(struct ath11k_base *ab) { size_t max_len = sizeof(ab->qmi.target.bdf_ext); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 70eb6e418422..6b272eb8bb4a 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include "qmi.h" #include "htc.h" #include "wmi.h" @@ -37,6 +39,15 @@ #define ATH11K_INVALID_HW_MAC_ID 0xFF #define ATH11K_CONNECTION_LOSS_HZ (3 * HZ) +/* SMBIOS type containing Board Data File Name Extension */ +#define ATH11K_SMBIOS_BDF_EXT_TYPE 0xF8 + +/* SMBIOS type structure length (excluding strings-set) */ +#define ATH11K_SMBIOS_BDF_EXT_LENGTH 0x9 + +/* The magic used by QCA spec */ +#define ATH11K_SMBIOS_BDF_EXT_MAGIC "BDF_" + extern unsigned int ath11k_frame_mode; #define ATH11K_MON_TIMER_INTERVAL 10 @@ -154,6 +165,13 @@ struct ath11k_ext_irq_grp { struct net_device napi_ndev; }; +struct ath11k_smbios_bdf { + struct dmi_header hdr; + u32 padding; + u8 bdf_enabled; + u8 bdf_ext[]; +}; + #define HEHANDLE_CAP_PHYINFO_SIZE 3 #define HECAP_PHYINFO_SIZE 9 #define HECAP_MACINFO_SIZE 5 @@ -1046,7 +1064,7 @@ int ath11k_core_fetch_board_data_api_1(struct ath11k_base *ab, const char *name); void ath11k_core_free_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd); int ath11k_core_check_dt(struct ath11k_base *ath11k); - +int ath11k_core_check_smbios(struct ath11k_base *ab); void ath11k_core_halt(struct ath11k *ar); int ath11k_core_resume(struct ath11k_base *ab); int ath11k_core_suspend(struct ath11k_base *ab); diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c index ffb8aa7dfb02..0442faa3b7af 100644 --- a/drivers/net/wireless/ath/ath11k/qmi.c +++ b/drivers/net/wireless/ath/ath11k/qmi.c @@ -2095,6 +2095,10 @@ static int ath11k_qmi_request_target_cap(struct ath11k_base *ab) ab->qmi.target.fw_build_timestamp, fw_build_id); + r = ath11k_core_check_smbios(ab); + if (r) + ath11k_dbg(ab, ATH11K_DBG_QMI, "SMBIOS bdf variant name not set.\n"); + r = ath11k_core_check_dt(ab); if (r) ath11k_dbg(ab, ATH11K_DBG_QMI, "DT bdf variant name not set.\n"); From 7b0c70d92a435913f6e11d6a248b935697e8a3eb Mon Sep 17 00:00:00 2001 From: Karthikeyan Periyasamy Date: Wed, 23 Mar 2022 11:14:17 +0200 Subject: [PATCH 00351/11454] ath11k: Add peer rhash table support When more clients (128) are connected, the UL data traffic KPI measurement is low compared to single client. This issue is due to more CPU cycles spent on the peer lookup operation with more clients. So reduce the peer lookup operation by modifying the linear based lookup operation into the rhash based lookup operation. This improve the peak throughput measurement. Since this is a software algorithm change, it is applicable for all the platforms. TCP UL 128 Clients test case Observation (64bit system): Previous: ~550 Mbps Now : ~860 Mbps Tested-on: QCN9074 hw1.0 PCI WLAN.HK.2.5.0.1-01067-QCAHKSWPL_SILICONZ-1 Signed-off-by: Karthikeyan Periyasamy Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/1644036628-5334-1-git-send-email-quic_periyasa@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 3 +- drivers/net/wireless/ath/ath11k/core.h | 14 + drivers/net/wireless/ath/ath11k/mac.c | 16 +- drivers/net/wireless/ath/ath11k/peer.c | 366 ++++++++++++++++++++++--- drivers/net/wireless/ath/ath11k/peer.h | 10 +- 5 files changed, 374 insertions(+), 35 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 7b91b029074f..2a867237e817 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -1680,6 +1680,7 @@ struct ath11k_base *ath11k_core_alloc(struct device *dev, size_t priv_size, goto err_free_wq; mutex_init(&ab->core_lock); + mutex_init(&ab->tbl_mtx_lock); spin_lock_init(&ab->base_lock); mutex_init(&ab->vdev_id_11d_lock); init_completion(&ab->reset_complete); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 6b272eb8bb4a..41001ec174e2 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef ATH11K_CORE_H @@ -12,6 +13,7 @@ #include #include #include +#include #include "qmi.h" #include "htc.h" #include "wmi.h" @@ -803,6 +805,18 @@ struct ath11k_base { struct ath11k_pdev __rcu *pdevs_active[MAX_RADIOS]; struct ath11k_hal_reg_capabilities_ext hal_reg_cap[MAX_RADIOS]; unsigned long long free_vdev_map; + + /* To synchronize rhash tbl write operation */ + struct mutex tbl_mtx_lock; + + /* The rhashtable containing struct ath11k_peer keyed by mac addr */ + struct rhashtable *rhead_peer_addr; + struct rhashtable_params rhash_peer_addr_param; + + /* The rhashtable containing struct ath11k_peer keyed by id */ + struct rhashtable *rhead_peer_id; + struct rhashtable_params rhash_peer_id_param; + struct list_head peers; wait_queue_head_t peer_mapping_wq; u8 mac_addr[ETH_ALEN]; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 34a62933ccd2..7a7641e8e325 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. - * Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -875,13 +875,16 @@ void ath11k_mac_peer_cleanup_all(struct ath11k *ar) lockdep_assert_held(&ar->conf_mutex); + mutex_lock(&ab->tbl_mtx_lock); spin_lock_bh(&ab->base_lock); list_for_each_entry_safe(peer, tmp, &ab->peers, list) { ath11k_peer_rx_tid_cleanup(ar, peer); + ath11k_peer_rhash_delete(ab, peer); list_del(&peer->list); kfree(peer); } spin_unlock_bh(&ab->base_lock); + mutex_unlock(&ab->tbl_mtx_lock); ar->num_peers = 0; ar->num_stations = 0; @@ -4554,6 +4557,7 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, } ath11k_mac_dec_num_stations(arvif, sta); + mutex_lock(&ar->ab->tbl_mtx_lock); spin_lock_bh(&ar->ab->base_lock); peer = ath11k_peer_find(ar->ab, arvif->vdev_id, sta->addr); if (skip_peer_delete && peer) { @@ -4561,12 +4565,14 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw, } else if (peer && peer->sta == sta) { ath11k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n", vif->addr, arvif->vdev_id); + ath11k_peer_rhash_delete(ar->ab, peer); peer->sta = NULL; list_del(&peer->list); kfree(peer); ar->num_peers--; } spin_unlock_bh(&ar->ab->base_lock); + mutex_unlock(&ar->ab->tbl_mtx_lock); kfree(arsta->tx_stats); arsta->tx_stats = NULL; @@ -8574,6 +8580,8 @@ void ath11k_mac_unregister(struct ath11k_base *ab) __ath11k_mac_unregister(ar); } + + ath11k_peer_rhash_tbl_destroy(ab); } static int __ath11k_mac_register(struct ath11k *ar) @@ -8802,6 +8810,10 @@ int ath11k_mac_register(struct ath11k_base *ab) ab->cc_freq_hz = IPQ8074_CC_FREQ_HERTZ; ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS(ab))) - 1; + ret = ath11k_peer_rhash_tbl_init(ab); + if (ret) + return ret; + for (i = 0; i < ab->num_radios; i++) { pdev = &ab->pdevs[i]; ar = pdev->ar; @@ -8831,6 +8843,8 @@ err_cleanup: __ath11k_mac_unregister(ar); } + ath11k_peer_rhash_tbl_destroy(ab); + return ret; } diff --git a/drivers/net/wireless/ath/ath11k/peer.c b/drivers/net/wireless/ath/ath11k/peer.c index 392985b873bf..9e22aaf34b88 100644 --- a/drivers/net/wireless/ath/ath11k/peer.c +++ b/drivers/net/wireless/ath/ath11k/peer.c @@ -1,12 +1,30 @@ // SPDX-License-Identifier: BSD-3-Clause-Clear /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "core.h" #include "peer.h" #include "debug.h" +static struct ath11k_peer *ath11k_peer_find_list_by_id(struct ath11k_base *ab, + int peer_id) +{ + struct ath11k_peer *peer; + + lockdep_assert_held(&ab->base_lock); + + list_for_each_entry(peer, &ab->peers, list) { + if (peer->peer_id != peer_id) + continue; + + return peer; + } + + return NULL; +} + struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, const u8 *addr) { @@ -26,25 +44,6 @@ struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id, return NULL; } -static struct ath11k_peer *ath11k_peer_find_by_pdev_idx(struct ath11k_base *ab, - u8 pdev_idx, const u8 *addr) -{ - struct ath11k_peer *peer; - - lockdep_assert_held(&ab->base_lock); - - list_for_each_entry(peer, &ab->peers, list) { - if (peer->pdev_idx != pdev_idx) - continue; - if (!ether_addr_equal(peer->addr, addr)) - continue; - - return peer; - } - - return NULL; -} - struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, const u8 *addr) { @@ -52,14 +51,13 @@ struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab, lockdep_assert_held(&ab->base_lock); - list_for_each_entry(peer, &ab->peers, list) { - if (!ether_addr_equal(peer->addr, addr)) - continue; + if (!ab->rhead_peer_addr) + return NULL; - return peer; - } + peer = rhashtable_lookup_fast(ab->rhead_peer_addr, addr, + ab->rhash_peer_addr_param); - return NULL; + return peer; } struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, @@ -69,11 +67,13 @@ struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab, lockdep_assert_held(&ab->base_lock); - list_for_each_entry(peer, &ab->peers, list) - if (peer_id == peer->peer_id) - return peer; + if (!ab->rhead_peer_id) + return NULL; - return NULL; + peer = rhashtable_lookup_fast(ab->rhead_peer_id, &peer_id, + ab->rhash_peer_id_param); + + return peer; } struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab, @@ -99,7 +99,7 @@ void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id) spin_lock_bh(&ab->base_lock); - peer = ath11k_peer_find_by_id(ab, peer_id); + peer = ath11k_peer_find_list_by_id(ab, peer_id); if (!peer) { ath11k_warn(ab, "peer-unmap-event: unknown peer id %d\n", peer_id); @@ -167,6 +167,76 @@ static int ath11k_wait_for_peer_common(struct ath11k_base *ab, int vdev_id, return 0; } +static inline int ath11k_peer_rhash_insert(struct ath11k_base *ab, + struct rhashtable *rtbl, + struct rhash_head *rhead, + struct rhashtable_params *params, + void *key) +{ + struct ath11k_peer *tmp; + + lockdep_assert_held(&ab->tbl_mtx_lock); + + tmp = rhashtable_lookup_get_insert_fast(rtbl, rhead, *params); + + if (!tmp) + return 0; + else if (IS_ERR(tmp)) + return PTR_ERR(tmp); + else + return -EEXIST; +} + +static inline int ath11k_peer_rhash_remove(struct ath11k_base *ab, + struct rhashtable *rtbl, + struct rhash_head *rhead, + struct rhashtable_params *params) +{ + int ret; + + lockdep_assert_held(&ab->tbl_mtx_lock); + + ret = rhashtable_remove_fast(rtbl, rhead, *params); + if (ret && ret != -ENOENT) + return ret; + + return 0; +} + +static int ath11k_peer_rhash_add(struct ath11k_base *ab, struct ath11k_peer *peer) +{ + int ret; + + lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&ab->tbl_mtx_lock); + + if (!ab->rhead_peer_id || !ab->rhead_peer_addr) + return -EPERM; + + ret = ath11k_peer_rhash_insert(ab, ab->rhead_peer_id, &peer->rhash_id, + &ab->rhash_peer_id_param, &peer->peer_id); + if (ret) { + ath11k_warn(ab, "failed to add peer %pM with id %d in rhash_id ret %d\n", + peer->addr, peer->peer_id, ret); + return ret; + } + + ret = ath11k_peer_rhash_insert(ab, ab->rhead_peer_addr, &peer->rhash_addr, + &ab->rhash_peer_addr_param, &peer->addr); + if (ret) { + ath11k_warn(ab, "failed to add peer %pM with id %d in rhash_addr ret %d\n", + peer->addr, peer->peer_id, ret); + goto err_clean; + } + + return 0; + +err_clean: + ath11k_peer_rhash_remove(ab, ab->rhead_peer_id, &peer->rhash_id, + &ab->rhash_peer_id_param); + return ret; +} + void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id) { struct ath11k_peer *peer, *tmp; @@ -174,6 +244,7 @@ void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id) lockdep_assert_held(&ar->conf_mutex); + mutex_lock(&ab->tbl_mtx_lock); spin_lock_bh(&ab->base_lock); list_for_each_entry_safe(peer, tmp, &ab->peers, list) { if (peer->vdev_id != vdev_id) @@ -182,12 +253,14 @@ void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id) ath11k_warn(ab, "removing stale peer %pM from vdev_id %d\n", peer->addr, vdev_id); + ath11k_peer_rhash_delete(ab, peer); list_del(&peer->list); kfree(peer); ar->num_peers--; } spin_unlock_bh(&ab->base_lock); + mutex_unlock(&ab->tbl_mtx_lock); } static int ath11k_wait_for_peer_deleted(struct ath11k *ar, int vdev_id, const u8 *addr) @@ -220,14 +293,35 @@ int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr) { int ret; + struct ath11k_peer *peer; + struct ath11k_base *ab = ar->ab; lockdep_assert_held(&ar->conf_mutex); + mutex_lock(&ab->tbl_mtx_lock); + spin_lock_bh(&ab->base_lock); + + peer = ath11k_peer_find_by_addr(ab, addr); + if (!peer) { + spin_unlock_bh(&ab->base_lock); + mutex_unlock(&ab->tbl_mtx_lock); + + ath11k_warn(ab, + "failed to find peer vdev_id %d addr %pM in delete\n", + vdev_id, addr); + return -EINVAL; + } + + ath11k_peer_rhash_delete(ab, peer); + + spin_unlock_bh(&ab->base_lock); + mutex_unlock(&ab->tbl_mtx_lock); + reinit_completion(&ar->peer_delete_done); ret = ath11k_wmi_send_peer_delete_cmd(ar, addr, vdev_id); if (ret) { - ath11k_warn(ar->ab, + ath11k_warn(ab, "failed to delete peer vdev_id %d addr %pM ret %d\n", vdev_id, addr, ret); return ret; @@ -276,7 +370,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, } spin_lock_bh(&ar->ab->base_lock); - peer = ath11k_peer_find_by_pdev_idx(ar->ab, ar->pdev_idx, param->peer_addr); + peer = ath11k_peer_find_by_addr(ar->ab, param->peer_addr); if (peer) { spin_unlock_bh(&ar->ab->base_lock); return -EINVAL; @@ -296,11 +390,13 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, if (ret) return ret; + mutex_lock(&ar->ab->tbl_mtx_lock); spin_lock_bh(&ar->ab->base_lock); peer = ath11k_peer_find(ar->ab, param->vdev_id, param->peer_addr); if (!peer) { spin_unlock_bh(&ar->ab->base_lock); + mutex_unlock(&ar->ab->tbl_mtx_lock); ath11k_warn(ar->ab, "failed to find peer %pM on vdev %i after creation\n", param->peer_addr, param->vdev_id); @@ -308,6 +404,13 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, goto cleanup; } + ret = ath11k_peer_rhash_add(ar->ab, peer); + if (ret) { + spin_unlock_bh(&ar->ab->base_lock); + mutex_unlock(&ar->ab->tbl_mtx_lock); + goto cleanup; + } + peer->pdev_idx = ar->pdev_idx; peer->sta = sta; @@ -332,6 +435,7 @@ int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif, ar->num_peers++; spin_unlock_bh(&ar->ab->base_lock); + mutex_unlock(&ar->ab->tbl_mtx_lock); return 0; @@ -343,3 +447,201 @@ cleanup: return ret; } + +int ath11k_peer_rhash_delete(struct ath11k_base *ab, struct ath11k_peer *peer) +{ + int ret; + + lockdep_assert_held(&ab->base_lock); + lockdep_assert_held(&ab->tbl_mtx_lock); + + if (!ab->rhead_peer_id || !ab->rhead_peer_addr) + return -EPERM; + + ret = ath11k_peer_rhash_remove(ab, ab->rhead_peer_addr, &peer->rhash_addr, + &ab->rhash_peer_addr_param); + if (ret) { + ath11k_warn(ab, "failed to remove peer %pM id %d in rhash_addr ret %d\n", + peer->addr, peer->peer_id, ret); + return ret; + } + + ret = ath11k_peer_rhash_remove(ab, ab->rhead_peer_id, &peer->rhash_id, + &ab->rhash_peer_id_param); + if (ret) { + ath11k_warn(ab, "failed to remove peer %pM id %d in rhash_id ret %d\n", + peer->addr, peer->peer_id, ret); + return ret; + } + + return 0; +} + +static int ath11k_peer_rhash_id_tbl_init(struct ath11k_base *ab) +{ + struct rhashtable_params *param; + struct rhashtable *rhash_id_tbl; + int ret; + size_t size; + + lockdep_assert_held(&ab->tbl_mtx_lock); + + if (ab->rhead_peer_id) + return 0; + + size = sizeof(*ab->rhead_peer_id); + rhash_id_tbl = kzalloc(size, GFP_KERNEL); + if (!rhash_id_tbl) { + ath11k_warn(ab, "failed to init rhash id table due to no mem (size %zu)\n", + size); + return -ENOMEM; + } + + param = &ab->rhash_peer_id_param; + + param->key_offset = offsetof(struct ath11k_peer, peer_id); + param->head_offset = offsetof(struct ath11k_peer, rhash_id); + param->key_len = sizeof_field(struct ath11k_peer, peer_id); + param->automatic_shrinking = true; + param->nelem_hint = ab->num_radios * TARGET_NUM_PEERS_PDEV(ab); + + ret = rhashtable_init(rhash_id_tbl, param); + if (ret) { + ath11k_warn(ab, "failed to init peer id rhash table %d\n", ret); + goto err_free; + } + + spin_lock_bh(&ab->base_lock); + + if (!ab->rhead_peer_id) { + ab->rhead_peer_id = rhash_id_tbl; + } else { + spin_unlock_bh(&ab->base_lock); + goto cleanup_tbl; + } + + spin_unlock_bh(&ab->base_lock); + + return 0; + +cleanup_tbl: + rhashtable_destroy(rhash_id_tbl); +err_free: + kfree(rhash_id_tbl); + + return ret; +} + +static int ath11k_peer_rhash_addr_tbl_init(struct ath11k_base *ab) +{ + struct rhashtable_params *param; + struct rhashtable *rhash_addr_tbl; + int ret; + size_t size; + + lockdep_assert_held(&ab->tbl_mtx_lock); + + if (ab->rhead_peer_addr) + return 0; + + size = sizeof(*ab->rhead_peer_addr); + rhash_addr_tbl = kzalloc(size, GFP_KERNEL); + if (!rhash_addr_tbl) { + ath11k_warn(ab, "failed to init rhash addr table due to no mem (size %zu)\n", + size); + return -ENOMEM; + } + + param = &ab->rhash_peer_addr_param; + + param->key_offset = offsetof(struct ath11k_peer, addr); + param->head_offset = offsetof(struct ath11k_peer, rhash_addr); + param->key_len = sizeof_field(struct ath11k_peer, addr); + param->automatic_shrinking = true; + param->nelem_hint = ab->num_radios * TARGET_NUM_PEERS_PDEV(ab); + + ret = rhashtable_init(rhash_addr_tbl, param); + if (ret) { + ath11k_warn(ab, "failed to init peer addr rhash table %d\n", ret); + goto err_free; + } + + spin_lock_bh(&ab->base_lock); + + if (!ab->rhead_peer_addr) { + ab->rhead_peer_addr = rhash_addr_tbl; + } else { + spin_unlock_bh(&ab->base_lock); + goto cleanup_tbl; + } + + spin_unlock_bh(&ab->base_lock); + + return 0; + +cleanup_tbl: + rhashtable_destroy(rhash_addr_tbl); +err_free: + kfree(rhash_addr_tbl); + + return ret; +} + +static inline void ath11k_peer_rhash_id_tbl_destroy(struct ath11k_base *ab) +{ + lockdep_assert_held(&ab->tbl_mtx_lock); + + if (!ab->rhead_peer_id) + return; + + rhashtable_destroy(ab->rhead_peer_id); + kfree(ab->rhead_peer_id); + ab->rhead_peer_id = NULL; +} + +static inline void ath11k_peer_rhash_addr_tbl_destroy(struct ath11k_base *ab) +{ + lockdep_assert_held(&ab->tbl_mtx_lock); + + if (!ab->rhead_peer_addr) + return; + + rhashtable_destroy(ab->rhead_peer_addr); + kfree(ab->rhead_peer_addr); + ab->rhead_peer_addr = NULL; +} + +int ath11k_peer_rhash_tbl_init(struct ath11k_base *ab) +{ + int ret; + + mutex_lock(&ab->tbl_mtx_lock); + + ret = ath11k_peer_rhash_id_tbl_init(ab); + if (ret) + goto out; + + ret = ath11k_peer_rhash_addr_tbl_init(ab); + if (ret) + goto cleanup_tbl; + + mutex_unlock(&ab->tbl_mtx_lock); + + return 0; + +cleanup_tbl: + ath11k_peer_rhash_id_tbl_destroy(ab); +out: + mutex_unlock(&ab->tbl_mtx_lock); + return ret; +} + +void ath11k_peer_rhash_tbl_destroy(struct ath11k_base *ab) +{ + mutex_lock(&ab->tbl_mtx_lock); + + ath11k_peer_rhash_addr_tbl_destroy(ab); + ath11k_peer_rhash_id_tbl_destroy(ab); + + mutex_unlock(&ab->tbl_mtx_lock); +} diff --git a/drivers/net/wireless/ath/ath11k/peer.h b/drivers/net/wireless/ath/ath11k/peer.h index 63fe5665badf..6dd17bafe3a0 100644 --- a/drivers/net/wireless/ath/ath11k/peer.h +++ b/drivers/net/wireless/ath/ath11k/peer.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: BSD-3-Clause-Clear */ /* * Copyright (c) 2018-2019 The Linux Foundation. All rights reserved. + * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef ATH11K_PEER_H @@ -20,6 +21,11 @@ struct ath11k_peer { struct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1]; struct dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1]; + /* peer id based rhashtable list pointer */ + struct rhash_head rhash_id; + /* peer addr based rhashtable list pointer */ + struct rhash_head rhash_addr; + /* Info used in MMIC verification of * RX fragments */ @@ -47,5 +53,7 @@ int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id, const u8 *addr); struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab, int vdev_id); - +int ath11k_peer_rhash_tbl_init(struct ath11k_base *ab); +void ath11k_peer_rhash_tbl_destroy(struct ath11k_base *ab); +int ath11k_peer_rhash_delete(struct ath11k_base *ab, struct ath11k_peer *peer); #endif /* _PEER_H_ */ From 26c31016fe7eb1911e9ffa50dbaac6f2c42c799c Mon Sep 17 00:00:00 2001 From: Wenli Looi Date: Sun, 20 Mar 2022 17:30:05 -0600 Subject: [PATCH 00352/11454] ath9k: make ATH_SREV macros more consistent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes the macros more consistent and removes hidden dependencies on ah for macros that take _ah as a parameter. This change does not appear to affect the final binary. Signed-off-by: Wenli Looi Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220320233010.123106-2-wlooi@ucalgary.ca --- drivers/net/wireless/ath/ath9k/reg.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 653e79611830..8983ea6fc727 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -834,8 +834,8 @@ ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) -#define AR_SREV_9100(ah) \ - ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) +#define AR_SREV_9100(_ah) \ + (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9100)) #define AR_SREV_9100_OR_LATER(_ah) \ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) @@ -891,7 +891,7 @@ #define AR_SREV_9300_20_OR_LATER(_ah) \ ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9300) #define AR_SREV_9300_22(_ah) \ - (AR_SREV_9300(ah) && \ + (AR_SREV_9300((_ah)) && \ ((_ah)->hw_version.macRev == AR_SREV_REVISION_9300_22)) #define AR_SREV_9330(_ah) \ @@ -994,8 +994,8 @@ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9561)) #define AR_SREV_SOC(_ah) \ - (AR_SREV_9340(_ah) || AR_SREV_9531(_ah) || AR_SREV_9550(ah) || \ - AR_SREV_9561(ah)) + (AR_SREV_9340(_ah) || AR_SREV_9531(_ah) || AR_SREV_9550(_ah) || \ + AR_SREV_9561(_ah)) /* NOTE: When adding chips newer than Peacock, add chip check here */ #define AR_SREV_9580_10_OR_LATER(_ah) \ From a96474a794e11eda2c96b06270178ac1ccd6e1c0 Mon Sep 17 00:00:00 2001 From: Wenli Looi Date: Sun, 20 Mar 2022 17:30:06 -0600 Subject: [PATCH 00353/11454] ath9k: split set11nRateFlags and set11nChainSel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This makes the code clearer since set11nRateFlags currently sets both the rate flags and chain sel. This may also be required for QCN550x support, where the rate flags and chain sel are in separate fields. This change does not appear to affect the final binary. Signed-off-by: Wenli Looi Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220320233010.123106-3-wlooi@ucalgary.ca --- drivers/net/wireless/ath/ath9k/ar9002_mac.c | 9 +++++---- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 9 +++++---- drivers/net/wireless/ath/ath9k/mac.h | 6 ++++-- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9002_mac.c b/drivers/net/wireless/ath/ath9k/ar9002_mac.c index fba5a847c3bb..a8c0e8e2d78c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_mac.c @@ -301,10 +301,11 @@ ar9002_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) WRITE_ONCE(ads->ds_ctl5, set11nPktDurRTSCTS(i->rates, 2) | set11nPktDurRTSCTS(i->rates, 3)); - WRITE_ONCE(ads->ds_ctl7, set11nRateFlags(i->rates, 0) - | set11nRateFlags(i->rates, 1) - | set11nRateFlags(i->rates, 2) - | set11nRateFlags(i->rates, 3) + WRITE_ONCE(ads->ds_ctl7, + set11nRateFlags(i->rates, 0) | set11nChainSel(i->rates, 0) + | set11nRateFlags(i->rates, 1) | set11nChainSel(i->rates, 1) + | set11nRateFlags(i->rates, 2) | set11nChainSel(i->rates, 2) + | set11nRateFlags(i->rates, 3) | set11nChainSel(i->rates, 3) | SM(i->rtscts_rate, AR_RTSCTSRate)); WRITE_ONCE(ads->ds_ctl9, SM(i->txpower[1], AR_XmitPower1)); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index 5184a0aacfe2..ff8ab58e67d9 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -144,10 +144,11 @@ ar9003_set_txdesc(struct ath_hw *ah, void *ds, struct ath_tx_info *i) WRITE_ONCE(ads->ctl16, set11nPktDurRTSCTS(i->rates, 2) | set11nPktDurRTSCTS(i->rates, 3)); - WRITE_ONCE(ads->ctl18, set11nRateFlags(i->rates, 0) - | set11nRateFlags(i->rates, 1) - | set11nRateFlags(i->rates, 2) - | set11nRateFlags(i->rates, 3) + WRITE_ONCE(ads->ctl18, + set11nRateFlags(i->rates, 0) | set11nChainSel(i->rates, 0) + | set11nRateFlags(i->rates, 1) | set11nChainSel(i->rates, 1) + | set11nRateFlags(i->rates, 2) | set11nChainSel(i->rates, 2) + | set11nRateFlags(i->rates, 3) | set11nChainSel(i->rates, 3) | SM(i->rtscts_rate, AR_RTSCTSRate)); WRITE_ONCE(ads->ctl19, AR_Not_Sounding); diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h index fd6aa49adadf..af44b33814dd 100644 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ b/drivers/net/wireless/ath/ath9k/mac.h @@ -35,8 +35,10 @@ |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ AR_GI##_index : 0) \ |((_series)[_index].RateFlags & ATH9K_RATESERIES_STBC ? \ - AR_STBC##_index : 0) \ - |SM((_series)[_index].ChSel, AR_ChainSel##_index)) + AR_STBC##_index : 0)) + +#define set11nChainSel(_series, _index) \ + (SM((_series)[_index].ChSel, AR_ChainSel##_index)) #define CCK_SIFS_TIME 10 #define CCK_PREAMBLE_BITS 144 From 3096a4d9eb9bf8a0975c222bd7013d2db323d749 Mon Sep 17 00:00:00 2001 From: Wenli Looi Date: Sun, 20 Mar 2022 17:30:07 -0600 Subject: [PATCH 00354/11454] ath9k: use AR9300_MAX_CHAINS when appropriate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace other constants with AR9300_MAX_CHAINS when appropriate. This change does not appear to affect the final binary. Signed-off-by: Wenli Looi Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220320233010.123106-4-wlooi@ucalgary.ca --- drivers/net/wireless/ath/ath9k/ar9003_calib.c | 2 +- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index dc24da1ff00b..6ca089f15629 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -177,7 +177,7 @@ static void ar9003_hw_iqcal_collect(struct ath_hw *ah) int i; /* Accumulate IQ cal measures for active chains */ - for (i = 0; i < AR5416_MAX_CHAINS; i++) { + for (i = 0; i < AR9300_MAX_CHAINS; i++) { if (ah->txchainmask & BIT(i)) { ah->totalPowerMeasI[i] += REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index b0a4ca3559fd..669b49b560a1 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3911,7 +3911,7 @@ static void ar9003_hw_atten_apply(struct ath_hw *ah, struct ath9k_channel *chan) } /* Test value. if 0 then attenuation is unused. Don't load anything. */ - for (i = 0; i < 3; i++) { + for (i = 0; i < AR9300_MAX_CHAINS; i++) { if (ah->txchainmask & BIT(i)) { value = ar9003_hw_atten_chain_get(ah, i, chan); REG_RMW_FIELD(ah, ext_atten_reg[i], @@ -5126,7 +5126,7 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) frequency, correction[0], correction[1], correction[2]); /* Store calibrated noise floor values */ - for (ichain = 0; ichain < AR5416_MAX_CHAINS; ichain++) + for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) if (mode) { ah->nf_5g.cal[ichain] = nf_cal[ichain]; ah->nf_5g.pwr[ichain] = nf_pwr[ichain]; From 9aaff3864b603408c02c629957ae8d8ff5d5a4f2 Mon Sep 17 00:00:00 2001 From: Wenli Looi Date: Sun, 20 Mar 2022 17:30:08 -0600 Subject: [PATCH 00355/11454] ath9k: fix ar9003_get_eepmisc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The current implementation is reading the wrong eeprom type. Fixes: d8ec2e2a63e8 ("ath9k: Add an eeprom_ops callback for retrieving the eepmisc value") Signed-off-by: Wenli Looi Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220320233010.123106-5-wlooi@ucalgary.ca --- drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 669b49b560a1..a109a44a1999 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -5615,7 +5615,7 @@ unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, static u8 ar9003_get_eepmisc(struct ath_hw *ah) { - return ah->eeprom.map4k.baseEepHeader.eepMisc; + return ah->eeprom.ar9300_eep.baseEepHeader.opCapFlags.eepMisc; } const struct eeprom_ops eep_ar9300_ops = { From 193025378c446d53fa36bfefc33c170f1ec374c8 Mon Sep 17 00:00:00 2001 From: Wenli Looi Date: Sun, 20 Mar 2022 17:30:09 -0600 Subject: [PATCH 00356/11454] ath9k: refactor ar9003_hw_spur_mitigate_ofdm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to ar9003_hw_spur_mitigate_mrc_cck, simplify the code by using ar9003_get_spur_chan_ptr. This may also be required for QCN550x support, to provide an abstraction over the underlying EEPROM format. Signed-off-by: Wenli Looi Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220320233010.123106-6-wlooi@ucalgary.ca --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 25 +++++++-------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index daf30f9946b4..dc0e5ea25673 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -523,21 +523,10 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, int synth_freq; int range = 10; int freq_offset = 0; - int mode; - u8* spurChansPtr; + u8 *spur_fbin_ptr = ar9003_get_spur_chan_ptr(ah, IS_CHAN_2GHZ(chan)); unsigned int i; - struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; - if (IS_CHAN_5GHZ(chan)) { - spurChansPtr = &(eep->modalHeader5G.spurChans[0]); - mode = 0; - } - else { - spurChansPtr = &(eep->modalHeader2G.spurChans[0]); - mode = 1; - } - - if (spurChansPtr[0] == 0) + if (spur_fbin_ptr[0] == 0) return; /* No spur in the mode */ if (IS_CHAN_HT40(chan)) { @@ -554,16 +543,18 @@ static void ar9003_hw_spur_mitigate_ofdm(struct ath_hw *ah, ar9003_hw_spur_ofdm_clear(ah); - for (i = 0; i < AR_EEPROM_MODAL_SPURS && spurChansPtr[i]; i++) { - freq_offset = ath9k_hw_fbin2freq(spurChansPtr[i], mode); + for (i = 0; i < AR_EEPROM_MODAL_SPURS && spur_fbin_ptr[i]; i++) { + freq_offset = ath9k_hw_fbin2freq(spur_fbin_ptr[i], + IS_CHAN_2GHZ(chan)); freq_offset -= synth_freq; if (abs(freq_offset) < range) { ar9003_hw_spur_ofdm_work(ah, chan, freq_offset, range, synth_freq); if (AR_SREV_9565(ah) && (i < 4)) { - freq_offset = ath9k_hw_fbin2freq(spurChansPtr[i + 1], - mode); + freq_offset = + ath9k_hw_fbin2freq(spur_fbin_ptr[i + 1], + IS_CHAN_2GHZ(chan)); freq_offset -= synth_freq; if (abs(freq_offset) < range) ar9003_hw_spur_ofdm_9565(ah, freq_offset); From 673424ce0e77450c24b300153387e271f470fc7c Mon Sep 17 00:00:00 2001 From: Wenli Looi Date: Sun, 20 Mar 2022 17:30:10 -0600 Subject: [PATCH 00357/11454] ath9k: add functions to get paprd rate mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes some code duplication with le32_to_cpu. This may also be required for QCN550x support, to provide an abstraction over the underlying EEPROM format. Signed-off-by: Wenli Looi Acked-by: Toke Høiland-Jørgensen Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220320233010.123106-7-wlooi@ucalgary.ca --- .../net/wireless/ath/ath9k/ar9003_eeprom.c | 33 ++++++++++--------- .../net/wireless/ath/ath9k/ar9003_eeprom.h | 2 ++ drivers/net/wireless/ath/ath9k/ar9003_paprd.c | 10 +++--- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index a109a44a1999..abf12de0e381 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -5449,8 +5449,6 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, { struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); struct ath_common *common = ath9k_hw_common(ah); - struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; - struct ar9300_modal_eep_header *modal_hdr; u8 targetPowerValT2[ar9300RateSize]; u8 target_power_val_t2_eep[ar9300RateSize]; u8 targetPowerValT2_tpc[ar9300RateSize]; @@ -5465,17 +5463,12 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah, ar9003_hw_get_target_power_eeprom(ah, chan, targetPowerValT2); if (ar9003_is_paprd_enabled(ah)) { - if (IS_CHAN_2GHZ(chan)) - modal_hdr = &eep->modalHeader2G; - else - modal_hdr = &eep->modalHeader5G; - ah->paprd_ratemask = - le32_to_cpu(modal_hdr->papdRateMaskHt20) & + ar9003_get_paprd_rate_mask_ht20(ah, IS_CHAN_2GHZ(chan)) & AR9300_PAPRD_RATE_MASK; ah->paprd_ratemask_ht40 = - le32_to_cpu(modal_hdr->papdRateMaskHt40) & + ar9003_get_paprd_rate_mask_ht40(ah, IS_CHAN_2GHZ(chan)) & AR9300_PAPRD_RATE_MASK; paprd_scale_factor = ar9003_get_paprd_scale_factor(ah, chan); @@ -5592,23 +5585,33 @@ u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is2ghz) return ar9003_modal_header(ah, is2ghz)->spurChans; } +u32 ar9003_get_paprd_rate_mask_ht20(struct ath_hw *ah, bool is2ghz) +{ + return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->papdRateMaskHt20); +} + +u32 ar9003_get_paprd_rate_mask_ht40(struct ath_hw *ah, bool is2ghz) +{ + return le32_to_cpu(ar9003_modal_header(ah, is2ghz)->papdRateMaskHt40); +} + unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, struct ath9k_channel *chan) { - struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + bool is2ghz = IS_CHAN_2GHZ(chan); - if (IS_CHAN_2GHZ(chan)) - return MS(le32_to_cpu(eep->modalHeader2G.papdRateMaskHt20), + if (is2ghz) + return MS(ar9003_get_paprd_rate_mask_ht20(ah, is2ghz), AR9300_PAPRD_SCALE_1); else { if (chan->channel >= 5700) - return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20), + return MS(ar9003_get_paprd_rate_mask_ht20(ah, is2ghz), AR9300_PAPRD_SCALE_1); else if (chan->channel >= 5400) - return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), + return MS(ar9003_get_paprd_rate_mask_ht40(ah, is2ghz), AR9300_PAPRD_SCALE_2); else - return MS(le32_to_cpu(eep->modalHeader5G.papdRateMaskHt40), + return MS(ar9003_get_paprd_rate_mask_ht40(ah, is2ghz), AR9300_PAPRD_SCALE_1); } } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index e8fda54acfe3..f8ae20318302 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -363,6 +363,8 @@ u32 ar9003_hw_ant_ctrl_common_2_get(struct ath_hw *ah, bool is2ghz); u8 *ar9003_get_spur_chan_ptr(struct ath_hw *ah, bool is_2ghz); +u32 ar9003_get_paprd_rate_mask_ht20(struct ath_hw *ah, bool is2ghz); +u32 ar9003_get_paprd_rate_mask_ht40(struct ath_hw *ah, bool is2ghz); unsigned int ar9003_get_paprd_scale_factor(struct ath_hw *ah, struct ath9k_channel *chan); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c index 34e100940284..b2d53b6c0ffd 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c @@ -21,7 +21,7 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val) { struct ath9k_channel *chan = ah->curchan; - struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + bool is2ghz = IS_CHAN_2GHZ(chan); /* * 3 bits for modalHeader5G.papdRateMaskHt20 @@ -36,17 +36,17 @@ void ar9003_paprd_enable(struct ath_hw *ah, bool val) * -- disable PAPRD for lower band 5GHz */ - if (IS_CHAN_5GHZ(chan)) { + if (!is2ghz) { if (chan->channel >= UPPER_5G_SUB_BAND_START) { - if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20) + if (ar9003_get_paprd_rate_mask_ht20(ah, is2ghz) & BIT(30)) val = false; } else if (chan->channel >= MID_5G_SUB_BAND_START) { - if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20) + if (ar9003_get_paprd_rate_mask_ht20(ah, is2ghz) & BIT(29)) val = false; } else { - if (le32_to_cpu(eep->modalHeader5G.papdRateMaskHt20) + if (ar9003_get_paprd_rate_mask_ht20(ah, is2ghz) & BIT(28)) val = false; } From 194d250cdc4a40ccbd179afd522a9e9846957402 Mon Sep 17 00:00:00 2001 From: Liu Zixian Date: Tue, 22 Mar 2022 17:17:30 +0800 Subject: [PATCH 00358/11454] drm/virtio: fix NULL pointer dereference in virtio_gpu_conn_get_modes drm_cvt_mode may return NULL and we should check it. This bug is found by syzkaller: FAULT_INJECTION stacktrace: [ 168.567394] FAULT_INJECTION: forcing a failure. name failslab, interval 1, probability 0, space 0, times 1 [ 168.567403] CPU: 1 PID: 6425 Comm: syz Kdump: loaded Not tainted 4.19.90-vhulk2201.1.0.h1035.kasan.eulerosv2r10.aarch64 #1 [ 168.567406] Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015 [ 168.567408] Call trace: [ 168.567414] dump_backtrace+0x0/0x310 [ 168.567418] show_stack+0x28/0x38 [ 168.567423] dump_stack+0xec/0x15c [ 168.567427] should_fail+0x3ac/0x3d0 [ 168.567437] __should_failslab+0xb8/0x120 [ 168.567441] should_failslab+0x28/0xc0 [ 168.567445] kmem_cache_alloc_trace+0x50/0x640 [ 168.567454] drm_mode_create+0x40/0x90 [ 168.567458] drm_cvt_mode+0x48/0xc78 [ 168.567477] virtio_gpu_conn_get_modes+0xa8/0x140 [virtio_gpu] [ 168.567485] drm_helper_probe_single_connector_modes+0x3a4/0xd80 [ 168.567492] drm_mode_getconnector+0x2e0/0xa70 [ 168.567496] drm_ioctl_kernel+0x11c/0x1d8 [ 168.567514] drm_ioctl+0x558/0x6d0 [ 168.567522] do_vfs_ioctl+0x160/0xf30 [ 168.567525] ksys_ioctl+0x98/0xd8 [ 168.567530] __arm64_sys_ioctl+0x50/0xc8 [ 168.567536] el0_svc_common+0xc8/0x320 [ 168.567540] el0_svc_handler+0xf8/0x160 [ 168.567544] el0_svc+0x10/0x218 KASAN stacktrace: [ 168.567561] BUG: KASAN: null-ptr-deref in virtio_gpu_conn_get_modes+0xb4/0x140 [virtio_gpu] [ 168.567565] Read of size 4 at addr 0000000000000054 by task syz/6425 [ 168.567566] [ 168.567571] CPU: 1 PID: 6425 Comm: syz Kdump: loaded Not tainted 4.19.90-vhulk2201.1.0.h1035.kasan.eulerosv2r10.aarch64 #1 [ 168.567573] Hardware name: QEMU KVM Virtual Machine, BIOS 0.0.0 02/06/2015 [ 168.567575] Call trace: [ 168.567578] dump_backtrace+0x0/0x310 [ 168.567582] show_stack+0x28/0x38 [ 168.567586] dump_stack+0xec/0x15c [ 168.567591] kasan_report+0x244/0x2f0 [ 168.567594] __asan_load4+0x58/0xb0 [ 168.567607] virtio_gpu_conn_get_modes+0xb4/0x140 [virtio_gpu] [ 168.567612] drm_helper_probe_single_connector_modes+0x3a4/0xd80 [ 168.567617] drm_mode_getconnector+0x2e0/0xa70 [ 168.567621] drm_ioctl_kernel+0x11c/0x1d8 [ 168.567624] drm_ioctl+0x558/0x6d0 [ 168.567628] do_vfs_ioctl+0x160/0xf30 [ 168.567632] ksys_ioctl+0x98/0xd8 [ 168.567636] __arm64_sys_ioctl+0x50/0xc8 [ 168.567641] el0_svc_common+0xc8/0x320 [ 168.567645] el0_svc_handler+0xf8/0x160 [ 168.567649] el0_svc+0x10/0x218 Signed-off-by: Liu Zixian Link: http://patchwork.freedesktop.org/patch/msgid/20220322091730.1653-1-liuzixian4@huawei.com Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_display.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 5b00310ac4cd..f73352e7b832 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -179,6 +179,8 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector) DRM_DEBUG("add mode: %dx%d\n", width, height); mode = drm_cvt_mode(connector->dev, width, height, 60, false, false, false); + if (!mode) + return count; mode->type |= DRM_MODE_TYPE_PREFERRED; drm_mode_probed_add(connector, mode); count++; From ec3cbb30893be248d180dd748ee9148d408a99d1 Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Sat, 19 Feb 2022 09:03:01 -0800 Subject: [PATCH 00359/11454] drm/virtio: Remove restriction of non-zero blob_flags With native userspace drivers in guest, a lot of GEM objects need to be neither shared nor mappable. And in fact making everything mappable and/or sharable results in unreasonably high fd usage in host VMM. Signed-off-by: Rob Clark Reviewed-by: Chia-I Wu Link: http://patchwork.freedesktop.org/patch/msgid/20220219170301.545432-1-robdclark@gmail.com Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/virtio/virtgpu_ioctl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index c708bab555c6..77743fd2c61a 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -609,8 +609,7 @@ static int verify_blob(struct virtio_gpu_device *vgdev, if (!vgdev->has_resource_blob) return -EINVAL; - if ((rc_blob->blob_flags & ~VIRTGPU_BLOB_FLAG_USE_MASK) || - !rc_blob->blob_flags) + if (rc_blob->blob_flags & ~VIRTGPU_BLOB_FLAG_USE_MASK) return -EINVAL; if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) { From 59ab4ee012f0166873ae15d235b2450f21dcb5e7 Mon Sep 17 00:00:00 2001 From: Cong Liu Date: Thu, 24 Mar 2022 18:49:28 +0800 Subject: [PATCH 00360/11454] drm/qxl: fix qxl can't use in arm64 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit qxl use ioremap to map ram_header and rom, in the arm64 implementation, the device is mapped as DEVICE_nGnRE, it can not support unaligned access. and qxl is a virtual device, it can be treated more like RAM than actual MMIO registers. use ioremap_wc() replace it. Signed-off-by: Cong Liu Acked-by: Christian König Link: http://patchwork.freedesktop.org/patch/msgid/20220324104928.2959545-1-liucong2@kylinos.cn Signed-off-by: Gerd Hoffmann --- drivers/gpu/drm/qxl/qxl_kms.c | 4 ++-- drivers/gpu/drm/qxl/qxl_ttm.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index 4dc5ad13f12c..a054e4a00fe8 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -165,7 +165,7 @@ int qxl_device_init(struct qxl_device *qdev, (int)qdev->surfaceram_size / 1024, (sb == 4) ? "64bit" : "32bit"); - qdev->rom = ioremap(qdev->rom_base, qdev->rom_size); + qdev->rom = ioremap_wc(qdev->rom_base, qdev->rom_size); if (!qdev->rom) { pr_err("Unable to ioremap ROM\n"); r = -ENOMEM; @@ -183,7 +183,7 @@ int qxl_device_init(struct qxl_device *qdev, goto rom_unmap; } - qdev->ram_header = ioremap(qdev->vram_base + + qdev->ram_header = ioremap_wc(qdev->vram_base + qdev->rom->ram_header_offset, sizeof(*qdev->ram_header)); if (!qdev->ram_header) { diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index b2e33d5ba5d0..95df5750f47f 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -82,13 +82,13 @@ int qxl_ttm_io_mem_reserve(struct ttm_device *bdev, case TTM_PL_VRAM: mem->bus.is_iomem = true; mem->bus.offset = (mem->start << PAGE_SHIFT) + qdev->vram_base; - mem->bus.caching = ttm_cached; + mem->bus.caching = ttm_write_combined; break; case TTM_PL_PRIV: mem->bus.is_iomem = true; mem->bus.offset = (mem->start << PAGE_SHIFT) + qdev->surfaceram_base; - mem->bus.caching = ttm_cached; + mem->bus.caching = ttm_write_combined; break; default: return -EINVAL; From 034d47b25b2ce627f1e1b04242d72db4180f3525 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Fri, 25 Mar 2022 09:49:16 +0000 Subject: [PATCH 00361/11454] drm/i915/uapi: Document DRM_I915_QUERY_HWCONFIG_BLOB UAPI with absolutely no documentation should not have been added - clarify blob format and content will be described externally. Fixes: 78e1fb3112c0 ("drm/i915/uapi: Add query for hwconfig blob") Signed-off-by: Tvrtko Ursulin Co-developed-by: Jordan Justen Cc: Jon Bloomfield Cc: Daniel Vetter Cc: John Harrison Cc: Jon Ewins Cc: Joonas Lahtinen Cc: Rodrigo Vivi Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220325094916.2186367-1-tvrtko.ursulin@linux.intel.com [tursulin: Fixed spelling s/meading/meaning/.] --- include/uapi/drm/i915_drm.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/uapi/drm/i915_drm.h b/include/uapi/drm/i915_drm.h index 071ffd9d51f1..9ab021c4d632 100644 --- a/include/uapi/drm/i915_drm.h +++ b/include/uapi/drm/i915_drm.h @@ -2683,6 +2683,9 @@ struct drm_i915_perf_oa_config { * * The behaviour is determined by the @query_id. Note that exactly what * @data_ptr is also depends on the specific @query_id. + * + * For specific queries see: + * * `GuC HWCONFIG blob uAPI`_ */ struct drm_i915_query_item { /** @query_id: The id for this query */ @@ -3135,6 +3138,16 @@ struct drm_i915_query_memory_regions { struct drm_i915_memory_region_info regions[]; }; +/** + * DOC: GuC HWCONFIG blob uAPI + * + * The GuC produces a blob with information about the current device. + * i915 reads this blob from GuC and makes it available via this uAPI. + * + * The format and meaning of the blob content are documented in the + * Programmer's Reference Manual. + */ + /** * struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added * extension support using struct i915_user_extension. From 31d5c52346cce168022b69b962023186b03eb43c Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 14 Mar 2022 14:38:19 -0400 Subject: [PATCH 00362/11454] drm/amdgpu: make amdgpu_display_framebuffer_init() static It's not used outside of amdgpu_display.c. Reviewed-by: Guchun Chen Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 13 +++++++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 4 ---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index fae5c1debfad..b2bcc8b4eb82 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -41,6 +41,11 @@ #include #include +static int amdgpu_display_framebuffer_init(struct drm_device *dev, + struct amdgpu_framebuffer *rfb, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj); + static void amdgpu_display_flip_callback(struct dma_fence *f, struct dma_fence_cb *cb) { @@ -1099,10 +1104,10 @@ err: return ret; } -int amdgpu_display_framebuffer_init(struct drm_device *dev, - struct amdgpu_framebuffer *rfb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj) +static int amdgpu_display_framebuffer_init(struct drm_device *dev, + struct amdgpu_framebuffer *rfb, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj) { struct amdgpu_device *adev = drm_to_adev(dev); int ret, i; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index a546cb3cfa18..db9fe00486bc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -600,10 +600,6 @@ int amdgpu_display_gem_fb_verify_and_init( struct drm_device *dev, struct amdgpu_framebuffer *rfb, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, struct drm_gem_object *obj); -int amdgpu_display_framebuffer_init(struct drm_device *dev, - struct amdgpu_framebuffer *rfb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); int amdgpufb_remove(struct drm_device *dev, struct drm_framebuffer *fb); From 60da2f7440f22dba48944602c2a0373068f13880 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 14 Mar 2022 14:40:33 -0400 Subject: [PATCH 00363/11454] drm/amdgpu: drop amdgpu_display_gem_fb_init() Unused. Reviewed-by: Guchun Chen Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 25 --------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 4 ---- 2 files changed, 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index b2bcc8b4eb82..8eeaf6f12d35 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -1044,31 +1044,6 @@ static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb return r; } -int amdgpu_display_gem_fb_init(struct drm_device *dev, - struct amdgpu_framebuffer *rfb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj) -{ - int ret; - - rfb->base.obj[0] = obj; - drm_helper_mode_fill_fb_struct(dev, &rfb->base, mode_cmd); - - ret = amdgpu_display_framebuffer_init(dev, rfb, mode_cmd, obj); - if (ret) - goto err; - - ret = drm_framebuffer_init(dev, &rfb->base, &amdgpu_fb_funcs); - if (ret) - goto err; - - return 0; -err: - drm_dbg_kms(dev, "Failed to init gem fb: %d\n", ret); - rfb->base.obj[0] = NULL; - return ret; -} - int amdgpu_display_gem_fb_verify_and_init( struct drm_device *dev, struct amdgpu_framebuffer *rfb, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index db9fe00486bc..d637f3f2357c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -592,10 +592,6 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev, int *hpos, ktime_t *stime, ktime_t *etime, const struct drm_display_mode *mode); -int amdgpu_display_gem_fb_init(struct drm_device *dev, - struct amdgpu_framebuffer *rfb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); int amdgpu_display_gem_fb_verify_and_init( struct drm_device *dev, struct amdgpu_framebuffer *rfb, struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, From c5b266810c5105b6c115de6236247049c23502db Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Mon, 14 Mar 2022 14:42:03 -0400 Subject: [PATCH 00364/11454] drm/amdgpu: make amdgpu_display_gem_fb_verify_and_init() static Unused outside of amdgpu_display.c. Reviewed-by: Guchun Chen Reviewed-by: Aurabindo Pillai Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 9 +++++---- drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h | 5 ----- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 8eeaf6f12d35..ee21b242ccf6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -1044,10 +1044,11 @@ static int amdgpu_display_get_fb_info(const struct amdgpu_framebuffer *amdgpu_fb return r; } -int amdgpu_display_gem_fb_verify_and_init( - struct drm_device *dev, struct amdgpu_framebuffer *rfb, - struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj) +static int amdgpu_display_gem_fb_verify_and_init(struct drm_device *dev, + struct amdgpu_framebuffer *rfb, + struct drm_file *file_priv, + const struct drm_mode_fb_cmd2 *mode_cmd, + struct drm_gem_object *obj) { int ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index d637f3f2357c..e8da738b309e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -592,11 +592,6 @@ int amdgpu_display_get_crtc_scanoutpos(struct drm_device *dev, int *hpos, ktime_t *stime, ktime_t *etime, const struct drm_display_mode *mode); -int amdgpu_display_gem_fb_verify_and_init( - struct drm_device *dev, struct amdgpu_framebuffer *rfb, - struct drm_file *file_priv, const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); - int amdgpufb_remove(struct drm_device *dev, struct drm_framebuffer *fb); void amdgpu_enc_destroy(struct drm_encoder *encoder); From eed41975307a365d1c0f6ed5c388b130ffdd2664 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Tue, 15 Mar 2022 17:07:21 +0800 Subject: [PATCH 00365/11454] drm/amdkfd: refine event_interrupt_poison_consumption Combine reading and setting poison flag as one atomic operation and add print message for the function. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c index 7eedbcd14828..a992798ff8b6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -93,20 +93,19 @@ enum SQ_INTERRUPT_ERROR_TYPE { static void event_interrupt_poison_consumption(struct kfd_dev *dev, uint16_t pasid, uint16_t source_id) { - int ret = -EINVAL; + int old_poison, ret = -EINVAL; struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); if (!p) return; /* all queues of a process will be unmapped in one time */ - if (atomic_read(&p->poison)) { - kfd_unref_process(p); - return; - } - - atomic_set(&p->poison, 1); + old_poison = atomic_cmpxchg(&p->poison, 0, 1); kfd_unref_process(p); + if (old_poison) + return; + + pr_warn("RAS poison consumption handling\n"); switch (source_id) { case SOC15_INTSRC_SQ_INTERRUPT_MSG: From 9d8a8d78d95261241fdc009ff5b44cfa9f78c8e7 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Wed, 16 Mar 2022 12:03:51 +0800 Subject: [PATCH 00366/11454] drm/amdkfd: replace source_id with client_id for RAS poison consumption Client ID is more accruate here and we can deal with more different cases with client ID. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c index a992798ff8b6..7db2421a3340 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -91,7 +91,7 @@ enum SQ_INTERRUPT_ERROR_TYPE { #define KFD_SQ_INT_DATA__ERR_TYPE__SHIFT 20 static void event_interrupt_poison_consumption(struct kfd_dev *dev, - uint16_t pasid, uint16_t source_id) + uint16_t pasid, uint16_t client_id) { int old_poison, ret = -EINVAL; struct kfd_process *p = kfd_lookup_process_by_pasid(pasid); @@ -105,13 +105,22 @@ static void event_interrupt_poison_consumption(struct kfd_dev *dev, if (old_poison) return; - pr_warn("RAS poison consumption handling\n"); + pr_warn("RAS poison consumption handling: client id %d\n", client_id); - switch (source_id) { - case SOC15_INTSRC_SQ_INTERRUPT_MSG: + switch (client_id) { + case SOC15_IH_CLIENTID_SE0SH: + case SOC15_IH_CLIENTID_SE1SH: + case SOC15_IH_CLIENTID_SE2SH: + case SOC15_IH_CLIENTID_SE3SH: + case SOC15_IH_CLIENTID_UTCL2: ret = kfd_dqm_evict_pasid(dev->dqm, pasid); break; - case SOC15_INTSRC_SDMA_ECC: + case SOC15_IH_CLIENTID_SDMA0: + case SOC15_IH_CLIENTID_SDMA1: + case SOC15_IH_CLIENTID_SDMA2: + case SOC15_IH_CLIENTID_SDMA3: + case SOC15_IH_CLIENTID_SDMA4: + break; default: break; } @@ -269,7 +278,7 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev, sq_intr_err); if (sq_intr_err != SQ_INTERRUPT_ERROR_TYPE_ILLEGAL_INST && sq_intr_err != SQ_INTERRUPT_ERROR_TYPE_MEMVIOL) { - event_interrupt_poison_consumption(dev, pasid, source_id); + event_interrupt_poison_consumption(dev, pasid, client_id); return; } break; @@ -290,7 +299,7 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev, if (source_id == SOC15_INTSRC_SDMA_TRAP) { kfd_signal_event_interrupt(pasid, context_id0 & 0xfffffff, 28); } else if (source_id == SOC15_INTSRC_SDMA_ECC) { - event_interrupt_poison_consumption(dev, pasid, source_id); + event_interrupt_poison_consumption(dev, pasid, client_id); return; } } else if (client_id == SOC15_IH_CLIENTID_VMC || From 6475ae2b742876aa9b2a0aff7ba60f5c81917614 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Tue, 15 Mar 2022 17:48:18 +0800 Subject: [PATCH 00367/11454] drm/amdgpu: add UTCL2 RAS poison query for Aldebaran (v2) Add help functions to query and reset RAS UTCL2 poison status. v2: implement it on amdgpu side and kfd only calls it. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 8 ++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h | 1 + drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c | 14 ++++++++++++++ 4 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 6ca1db3c243f..c18c4be1e4ac 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -724,3 +724,11 @@ void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bo else if (reset) amdgpu_amdkfd_gpu_reset(adev); } + +bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev) +{ + if (adev->gfx.ras->query_utcl2_poison_status) + return adev->gfx.ras->query_utcl2_poison_status(adev); + else + return false; +} diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 4cb14c2fe53f..0838926a8ef0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -301,6 +301,7 @@ void amdgpu_amdkfd_ras_poison_consumption_handler(struct amdgpu_device *adev, bool amdgpu_amdkfd_bo_mapped_to_dev(struct amdgpu_device *adev, struct kgd_mem *mem); void amdgpu_amdkfd_block_mmu_notifications(void *p); int amdgpu_amdkfd_criu_resume(void *p); +bool amdgpu_amdkfd_ras_query_utcl2_poison_status(struct amdgpu_device *adev); #if IS_ENABLED(CONFIG_HSA_AMD) void amdgpu_amdkfd_gpuvm_init_mem_limits(void); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h index dcb3c7871c73..5ed9b8a4c571 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.h @@ -202,6 +202,7 @@ struct amdgpu_cu_info { struct amdgpu_gfx_ras { struct amdgpu_ras_block_object ras_block; void (*enable_watchdog_timer)(struct amdgpu_device *adev); + bool (*query_utcl2_poison_status)(struct amdgpu_device *adev); }; struct amdgpu_gfx_funcs { diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c index 7653ebd0e67b..3a797424579c 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_2.c @@ -1930,6 +1930,19 @@ static void gfx_v9_4_2_reset_sq_timeout_status(struct amdgpu_device *adev) mutex_unlock(&adev->grbm_idx_mutex); } +static bool gfx_v9_4_2_query_uctl2_poison_status(struct amdgpu_device *adev) +{ + u32 status = 0; + struct amdgpu_vmhub *hub; + + hub = &adev->vmhub[AMDGPU_GFXHUB_0]; + status = RREG32(hub->vm_l2_pro_fault_status); + /* reset page fault status */ + WREG32_P(hub->vm_l2_pro_fault_cntl, 1, ~1); + + return REG_GET_FIELD(status, VM_L2_PROTECTION_FAULT_STATUS, FED); +} + struct amdgpu_ras_block_hw_ops gfx_v9_4_2_ras_ops = { .ras_error_inject = &gfx_v9_4_2_ras_error_inject, .query_ras_error_count = &gfx_v9_4_2_query_ras_error_count, @@ -1943,4 +1956,5 @@ struct amdgpu_gfx_ras gfx_v9_4_2_ras = { .hw_ops = &gfx_v9_4_2_ras_ops, }, .enable_watchdog_timer = &gfx_v9_4_2_enable_watchdog_timer, + .query_utcl2_poison_status = gfx_v9_4_2_query_uctl2_poison_status, }; From 1990e29b1900758f596434204d4067955f6e904e Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Wed, 16 Mar 2022 14:38:12 +0800 Subject: [PATCH 00368/11454] drm/amdkfd: add RAS poison consumption handling for UTCL2 (v2) Do RAS page retirement and use gpu reset as fallback in UTCL2 fault handler. v2: replace vm fault event with posion consumed event in UTCL2 poison consumption. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c index 7db2421a3340..56902b5bb7b6 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -308,6 +308,12 @@ static void event_interrupt_wq_v9(struct kfd_dev *dev, struct kfd_vm_fault_info info = {0}; uint16_t ring_id = SOC15_RING_ID_FROM_IH_ENTRY(ih_ring_entry); + if (client_id == SOC15_IH_CLIENTID_UTCL2 && + amdgpu_amdkfd_ras_query_utcl2_poison_status(dev->adev)) { + event_interrupt_poison_consumption(dev, pasid, client_id); + return; + } + info.vmid = vmid; info.mc_id = client_id; info.page_addr = ih_ring_entry[4] | From 2f78f0d3e3a89e76a7fe184fdef19efd85063f61 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 15 Mar 2022 20:19:59 +0000 Subject: [PATCH 00369/11454] drm/amdgpu: Fix spelling mistake "regiser" -> "register" There is a spelling mistake in a dev_error error message. Fix it. Signed-off-by: Colin Ian King Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c index a025f080aa6a..9aa355a5ac3c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_virt.c @@ -919,7 +919,7 @@ static u32 amdgpu_virt_rlcg_reg_rw(struct amdgpu_device *adev, u32 offset, u32 v "wrong operation type, rlcg failed to program reg: 0x%05x\n", offset); } else if (tmp & AMDGPU_RLCG_REG_NOT_IN_RANGE) { dev_err(adev->dev, - "regiser is not in range, rlcg failed to program reg: 0x%05x\n", offset); + "register is not in range, rlcg failed to program reg: 0x%05x\n", offset); } else { dev_err(adev->dev, "unknown error type, rlcg failed to program reg: 0x%05x\n", offset); From f3fa490960e8acf089ace0301a7ccb6d44ec9641 Mon Sep 17 00:00:00 2001 From: Guchun Chen Date: Wed, 16 Mar 2022 14:51:31 +0800 Subject: [PATCH 00370/11454] drm/amdgpu: drop redundant check of harvest info Harvest bit setting in IP data structure promises this, so no need to set it explicitly. Signed-off-by: Guchun Chen Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c index e4fcbb385a62..5a182288391b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_discovery.c @@ -1150,13 +1150,6 @@ void amdgpu_discovery_harvest_ip(struct amdgpu_device *adev) adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK; adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK; } - if ((adev->pdev->device == 0x731E && - (adev->pdev->revision == 0xC6 || adev->pdev->revision == 0xC7)) || - (adev->pdev->device == 0x7340 && adev->pdev->revision == 0xC9) || - (adev->pdev->device == 0x7360 && adev->pdev->revision == 0xC7)) { - adev->harvest_ip_mask |= AMD_HARVEST_IP_VCN_MASK; - adev->harvest_ip_mask |= AMD_HARVEST_IP_JPEG_MASK; - } } union gc_info { From 4268d081619a55019e44bf0a62222d47e1e09470 Mon Sep 17 00:00:00 2001 From: Ahmad Othman Date: Fri, 4 Mar 2022 11:56:19 -0500 Subject: [PATCH 00371/11454] drm/amd/display: Fix HDCP SEND AKI INIT error [why] HDCP sends AKI INIT error in case of multiple display on dock [how] Add new checks and method to handle display adjustment for multiple display cases Reviewed-by: Wenjing Liu Acked-by: Alex Hung Signed-off-by: Ahmad Othman Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/modules/hdcp/hdcp.c | 38 ++++++++++++++++++- .../gpu/drm/amd/display/modules/hdcp/hdcp.h | 8 ++++ .../drm/amd/display/modules/inc/mod_hdcp.h | 2 +- 3 files changed, 46 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c index 3e81850a7ffe..5e01c6e24cbc 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.c @@ -251,6 +251,33 @@ out: return status; } +static enum mod_hdcp_status update_display_adjustments(struct mod_hdcp *hdcp, + struct mod_hdcp_display *display, + struct mod_hdcp_display_adjustment *adj) +{ + enum mod_hdcp_status status = MOD_HDCP_STATUS_NOT_IMPLEMENTED; + + if (is_in_authenticated_states(hdcp) && + is_dp_mst_hdcp(hdcp) && + display->adjust.disable == true && + adj->disable == false) { + display->adjust.disable = false; + if (is_hdcp1(hdcp)) + status = mod_hdcp_hdcp1_enable_dp_stream_encryption(hdcp); + else if (is_hdcp2(hdcp)) + status = mod_hdcp_hdcp2_enable_dp_stream_encryption(hdcp); + + if (status != MOD_HDCP_STATUS_SUCCESS) + display->adjust.disable = true; + } + + if (status == MOD_HDCP_STATUS_SUCCESS && + memcmp(adj, &display->adjust, + sizeof(struct mod_hdcp_display_adjustment)) != 0) + status = MOD_HDCP_STATUS_NOT_IMPLEMENTED; + + return status; +} /* * Implementation of functions in mod_hdcp.h */ @@ -391,7 +418,7 @@ out: return status; } -enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp, +enum mod_hdcp_status mod_hdcp_update_display(struct mod_hdcp *hdcp, uint8_t index, struct mod_hdcp_link_adjustment *link_adjust, struct mod_hdcp_display_adjustment *display_adjust, @@ -419,6 +446,15 @@ enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp, goto out; } + if (memcmp(link_adjust, &hdcp->connection.link.adjust, + sizeof(struct mod_hdcp_link_adjustment)) == 0 && + memcmp(display_adjust, &display->adjust, + sizeof(struct mod_hdcp_display_adjustment)) != 0) { + status = update_display_adjustments(hdcp, display, display_adjust); + if (status != MOD_HDCP_STATUS_NOT_IMPLEMENTED) + goto out; + } + /* stop current authentication */ status = reset_authentication(hdcp, output); if (status != MOD_HDCP_STATUS_SUCCESS) diff --git a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h index 8502263d2968..4e7021c3c845 100644 --- a/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/hdcp/hdcp.h @@ -445,6 +445,14 @@ static inline uint8_t is_in_hdcp2_dp_states(struct mod_hdcp *hdcp) current_state(hdcp) <= HDCP2_DP_STATE_END); } +static inline uint8_t is_in_authenticated_states(struct mod_hdcp *hdcp) +{ + return (current_state(hdcp) == D1_A4_AUTHENTICATED || + current_state(hdcp) == H1_A45_AUTHENTICATED || + current_state(hdcp) == D2_A5_AUTHENTICATED || + current_state(hdcp) == H2_A5_AUTHENTICATED); +} + static inline uint8_t is_hdcp1(struct mod_hdcp *hdcp) { return (is_in_hdcp1_states(hdcp) || is_in_hdcp1_dp_states(hdcp)); diff --git a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h index f7420c3f5672..3348bb97ef81 100644 --- a/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h +++ b/drivers/gpu/drm/amd/display/modules/inc/mod_hdcp.h @@ -294,7 +294,7 @@ enum mod_hdcp_status mod_hdcp_remove_display(struct mod_hdcp *hdcp, uint8_t index, struct mod_hdcp_output *output); /* called per display to apply new authentication adjustment */ -enum mod_hdcp_status mod_hdcp_update_authentication(struct mod_hdcp *hdcp, +enum mod_hdcp_status mod_hdcp_update_display(struct mod_hdcp *hdcp, uint8_t index, struct mod_hdcp_link_adjustment *link_adjust, struct mod_hdcp_display_adjustment *display_adjust, From ed94aca6dbca2519cb71a73c2d276c97fe857596 Mon Sep 17 00:00:00 2001 From: Tao Zhou Date: Mon, 21 Mar 2022 15:45:31 +0800 Subject: [PATCH 00372/11454] drm/amdkfd: print unmap queue status for RAS poison consumption (v3) Print the status out when it passes, and also tell user gpu reset is triggered when we fall back to legacy way. v2: make the message more explicit. v3: change succeeds to succeeded. replace pr_warn with dev_warn. Signed-off-by: Tao Zhou Reviewed-by: Hawking Zhang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c index 56902b5bb7b6..03c29bdd89a1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_int_process_v9.c @@ -105,8 +105,6 @@ static void event_interrupt_poison_consumption(struct kfd_dev *dev, if (old_poison) return; - pr_warn("RAS poison consumption handling: client id %d\n", client_id); - switch (client_id) { case SOC15_IH_CLIENTID_SE0SH: case SOC15_IH_CLIENTID_SE1SH: @@ -130,10 +128,17 @@ static void event_interrupt_poison_consumption(struct kfd_dev *dev, /* resetting queue passes, do page retirement without gpu reset * resetting queue fails, fallback to gpu reset solution */ - if (!ret) + if (!ret) { + dev_warn(dev->adev->dev, + "RAS poison consumption, unmap queue flow succeeded: client id %d\n", + client_id); amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, false); - else + } else { + dev_warn(dev->adev->dev, + "RAS poison consumption, fall back to gpu reset flow: client id %d\n", + client_id); amdgpu_amdkfd_ras_poison_consumption_handler(dev->adev, true); + } } static bool event_interrupt_isr_v9(struct kfd_dev *dev, From 31f714b44959821f44fae105bd1d024b0f6b7ed5 Mon Sep 17 00:00:00 2001 From: Anthony Koo Date: Sun, 13 Mar 2022 14:06:05 -0400 Subject: [PATCH 00373/11454] drm/amd/display: [FW Promotion] Release 0.0.109.0 Reviewed-by: Aric Cyr Acked-by: Alex Hung Signed-off-by: Anthony Koo Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h index 71214c7a60fc..ce773b56a778 100644 --- a/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h +++ b/drivers/gpu/drm/amd/display/dmub/inc/dmub_cmd.h @@ -46,10 +46,10 @@ /* Firmware versioning. */ #ifdef DMUB_EXPOSE_VERSION -#define DMUB_FW_VERSION_GIT_HASH 0x929554ba +#define DMUB_FW_VERSION_GIT_HASH 0x51b95a35 #define DMUB_FW_VERSION_MAJOR 0 #define DMUB_FW_VERSION_MINOR 0 -#define DMUB_FW_VERSION_REVISION 108 +#define DMUB_FW_VERSION_REVISION 109 #define DMUB_FW_VERSION_TEST 0 #define DMUB_FW_VERSION_VBIOS 0 #define DMUB_FW_VERSION_HOTFIX 0 From 1918a0455d360457b2fbcda889cff19876d01b9e Mon Sep 17 00:00:00 2001 From: Aric Cyr Date: Sun, 13 Mar 2022 21:04:59 -0400 Subject: [PATCH 00374/11454] drm/amd/display: 3.2.178 This version brings along following fixes: - HDCP SEND AKI INIT error - fix audio format not updated after edid updated - Reduce stack size - FEC check in timing validation - Add fSMC_MSG_SetDtbClk support - Update VTEM Infopacket definition - [FW Promotion] Release 0.0.109.0 Acked-by: Alex Hung Signed-off-by: Aric Cyr Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 9f4d926d54e7..ced40fe218ac 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -47,7 +47,7 @@ struct aux_payload; struct set_config_cmd_payload; struct dmub_notification; -#define DC_VER "3.2.177" +#define DC_VER "3.2.178" #define MAX_SURFACES 3 #define MAX_PLANES 6 From 26f4712aedbdf4b9f5e3888a50a2a4b130ee4a9b Mon Sep 17 00:00:00 2001 From: Melissa Wen Date: Mon, 7 Mar 2022 14:47:59 -0100 Subject: [PATCH 00375/11454] drm/amd/display: move FPU related code from dcn31 to dml/dcn31 folder Creates FPU files in dml/dcn31 folder to centralize FPU operations from 3.1x drivers and moves all FPU-associated code from dcn31 driver to there. It includes the struct _vcs_dpi_ip_params_st and _vcs_dpi_soc_bounding_box_st and functions: - dcn31_calculate_wm_and_dlg_fp() - dcn31_update_bw_bounding_box() adding dc_assert_fp_enabled to them and drop DC_FP_START/END inside functions that was moved to dml folder, as required. Signed-off-by: Melissa Wen Reviewed-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn31/Makefile | 26 -- .../drm/amd/display/dc/dcn31/dcn31_resource.c | 355 +-------------- .../drm/amd/display/dc/dcn31/dcn31_resource.h | 4 +- drivers/gpu/drm/amd/display/dc/dml/Makefile | 2 + .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.c | 406 ++++++++++++++++++ .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.h | 39 ++ 6 files changed, 451 insertions(+), 381 deletions(-) create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c create mode 100644 drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile index d20e3b8ccc30..ec041e3cda30 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn31/Makefile @@ -15,32 +15,6 @@ DCN31 = dcn31_resource.o dcn31_hubbub.o dcn31_hwseq.o dcn31_init.o dcn31_hubp.o dcn31_apg.o dcn31_hpo_dp_stream_encoder.o dcn31_hpo_dp_link_encoder.o \ dcn31_afmt.o dcn31_vpg.o -ifdef CONFIG_X86 -CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o := -msse -endif - -ifdef CONFIG_PPC64 -CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o := -mhard-float -maltivec -endif - -ifdef CONFIG_CC_IS_GCC -ifeq ($(call cc-ifversion, -lt, 0701, y), y) -IS_OLD_GCC = 1 -endif -CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -mhard-float -endif - -ifdef CONFIG_X86 -ifdef IS_OLD_GCC -# Stack alignment mismatch, proceed with caution. -# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 -# (8B stack alignment). -CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -mpreferred-stack-boundary=4 -else -CFLAGS_$(AMDDALPATH)/dc/dcn31/dcn31_resource.o += -msse2 -endif -endif - AMD_DAL_DCN31 = $(addprefix $(AMDDALPATH)/dc/dcn31/,$(DCN31)) AMD_DISPLAY_FILES += $(AMD_DAL_DCN31) diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c index 338235bcef4a..bf130b2435ab 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.c @@ -65,6 +65,7 @@ #include "virtual/virtual_stream_encoder.h" #include "dce110/dce110_resource.h" #include "dml/display_mode_vba.h" +#include "dml/dcn31/dcn31_fpu.h" #include "dcn31/dcn31_dccg.h" #include "dcn10/dcn10_resource.h" #include "dcn31_panel_cntl.h" @@ -102,152 +103,6 @@ #define DC_LOGGER_INIT(logger) -#define DCN3_1_DEFAULT_DET_SIZE 384 - -struct _vcs_dpi_ip_params_st dcn3_1_ip = { - .gpuvm_enable = 1, - .gpuvm_max_page_table_levels = 1, - .hostvm_enable = 1, - .hostvm_max_page_table_levels = 2, - .rob_buffer_size_kbytes = 64, - .det_buffer_size_kbytes = DCN3_1_DEFAULT_DET_SIZE, - .config_return_buffer_size_in_kbytes = 1792, - .compressed_buffer_segment_size_in_kbytes = 64, - .meta_fifo_size_in_kentries = 32, - .zero_size_buffer_entries = 512, - .compbuf_reserved_space_64b = 256, - .compbuf_reserved_space_zs = 64, - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .meta_chunk_size_kbytes = 2, - .min_meta_chunk_size_bytes = 256, - .writeback_chunk_size_kbytes = 8, - .ptoi_supported = false, - .num_dsc = 3, - .maximum_dsc_bits_per_component = 10, - .dsc422_native_support = false, - .is_line_buffer_bpp_fixed = true, - .line_buffer_fixed_bpp = 48, - .line_buffer_size_bits = 789504, - .max_line_buffer_lines = 12, - .writeback_interface_buffer_size_kbytes = 90, - .max_num_dpp = 4, - .max_num_otg = 4, - .max_num_hdmi_frl_outputs = 1, - .max_num_wb = 1, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 6, - .max_vscl_ratio = 6, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dpte_buffer_size_in_pte_reqs_luma = 64, - .dpte_buffer_size_in_pte_reqs_chroma = 34, - .dispclk_ramp_margin_percent = 1, - .max_inter_dcn_tile_repeaters = 8, - .cursor_buffer_size = 16, - .cursor_chunk_size = 2, - .writeback_line_buffer_buffer_size = 0, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_max_hscl_taps = 1, - .writeback_max_vscl_taps = 1, - .dppclk_delay_subtotal = 46, - .dppclk_delay_scl = 50, - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_cnvc_formatter = 27, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 119, - .dynamic_metadata_vm_enabled = false, - .odm_combine_4to1_supported = false, - .dcc_supported = true, -}; - -struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = { - /*TODO: correct dispclk/dppclk voltage level determination*/ - .clock_limits = { - { - .state = 0, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 600.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 186.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 1, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 209.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 2, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 209.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 3, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 371.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 4, - .dispclk_mhz = 1200.0, - .dppclk_mhz = 1200.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 417.0, - .dtbclk_mhz = 625.0, - }, - }, - .num_states = 5, - .sr_exit_time_us = 9.0, - .sr_enter_plus_exit_time_us = 11.0, - .sr_exit_z8_time_us = 442.0, - .sr_enter_plus_exit_z8_time_us = 560.0, - .writeback_latency_us = 12.0, - .dram_channel_width_bytes = 4, - .round_trip_ping_latency_dcfclk_cycles = 106, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, - .pct_ideal_sdp_bw_after_urgent = 80.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 65.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0, - .max_avg_sdp_bw_use_normal_percent = 60.0, - .max_avg_dram_bw_use_normal_percent = 60.0, - .fabric_datapath_to_dcn_data_return_bytes = 32, - .return_bus_width_bytes = 64, - .downspread_percent = 0.38, - .dcn_downspread_percent = 0.5, - .gpuvm_min_page_size_bytes = 4096, - .hostvm_min_page_size_bytes = 4096, - .do_urgent_latency_adjustment = false, - .urgent_latency_adjustment_fabric_clock_component_us = 0, - .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, -}; - enum dcn31_clk_src_array_id { DCN31_CLK_SRC_PLL0, DCN31_CLK_SRC_PLL1, @@ -1869,143 +1724,6 @@ void dcn31_update_soc_for_wm_a(struct dc *dc, struct dc_state *context) } } -static void dcn31_calculate_wm_and_dlg_fp( - struct dc *dc, struct dc_state *context, - display_e2e_pipe_params_st *pipes, - int pipe_cnt, - int vlevel) -{ - int i, pipe_idx; - double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; - - if (context->bw_ctx.dml.soc.min_dcfclk > dcfclk) - dcfclk = context->bw_ctx.dml.soc.min_dcfclk; - - /* We don't recalculate clocks for 0 pipe configs, which can block - * S0i3 as high clocks will block low power states - * Override any clocks that can block S0i3 to min here - */ - if (pipe_cnt == 0) { - context->bw_ctx.bw.dcn.clk.dcfclk_khz = dcfclk; // always should be vlevel 0 - return; - } - - pipes[0].clks_cfg.voltage = vlevel; - pipes[0].clks_cfg.dcfclk_mhz = dcfclk; - pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; - -#if 0 // TODO - /* Set B: - * TODO - */ - if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].valid) { - if (vlevel == 0) { - pipes[0].clks_cfg.voltage = 1; - pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dcfclk_mhz; - } - context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us; - context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us; - context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us; - } - context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - - pipes[0].clks_cfg.voltage = vlevel; - pipes[0].clks_cfg.dcfclk_mhz = dcfclk; - - /* Set C: - * TODO - */ - if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) { - context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us; - context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us; - context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us; - } - context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.c.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - - /* Set D: - * TODO - */ - if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].valid) { - context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us; - context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us; - context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us; - } - context->bw_ctx.bw.dcn.watermarks.d.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.d.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; -#endif - - /* Set A: - * All clocks min required - * - * Set A calculated last so that following calculations are based on Set A - */ - dc->res_pool->funcs->update_soc_for_wm_a(dc, context); - context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - context->bw_ctx.bw.dcn.watermarks.a.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; - /* TODO: remove: */ - context->bw_ctx.bw.dcn.watermarks.b = context->bw_ctx.bw.dcn.watermarks.a; - context->bw_ctx.bw.dcn.watermarks.c = context->bw_ctx.bw.dcn.watermarks.a; - context->bw_ctx.bw.dcn.watermarks.d = context->bw_ctx.bw.dcn.watermarks.a; - /* end remove*/ - - for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { - if (!context->res_ctx.pipe_ctx[i].stream) - continue; - - pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt); - pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); - - if (dc->config.forced_clocks || dc->debug.max_disp_clk) { - pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz; - pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz; - } - if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000) - pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0; - if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) - pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0; - - pipe_idx++; - } - - DC_FP_START(); - dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); - DC_FP_END(); -} - void dcn31_calculate_wm_and_dlg( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, @@ -2073,77 +1791,6 @@ static struct dc_cap_funcs cap_funcs = { .get_dcc_compression_cap = dcn20_get_dcc_compression_cap }; -void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ - struct clk_limit_table *clk_table = &bw_params->clk_table; - struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; - unsigned int i, closest_clk_lvl; - int j; - - // Default clock levels are used for diags, which may lead to overclocking. - if (!IS_DIAG_DC(dc->ctx->dce_environment)) { - int max_dispclk_mhz = 0, max_dppclk_mhz = 0; - - dcn3_1_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; - dcn3_1_ip.max_num_dpp = dc->res_pool->pipe_count; - dcn3_1_soc.num_chans = bw_params->num_channels; - - ASSERT(clk_table->num_entries); - - /* Prepass to find max clocks independent of voltage level. */ - for (i = 0; i < clk_table->num_entries; ++i) { - if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz) - max_dispclk_mhz = clk_table->entries[i].dispclk_mhz; - if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz) - max_dppclk_mhz = clk_table->entries[i].dppclk_mhz; - } - - for (i = 0; i < clk_table->num_entries; i++) { - /* loop backwards*/ - for (closest_clk_lvl = 0, j = dcn3_1_soc.num_states - 1; j >= 0; j--) { - if ((unsigned int) dcn3_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { - closest_clk_lvl = j; - break; - } - } - - clock_limits[i].state = i; - - /* Clocks dependent on voltage level. */ - clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; - clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; - - /* Clocks independent of voltage level. */ - clock_limits[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : - dcn3_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz; - - clock_limits[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : - dcn3_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz; - - clock_limits[i].dram_bw_per_chan_gbps = dcn3_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; - clock_limits[i].dscclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; - clock_limits[i].dtbclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; - clock_limits[i].phyclk_d18_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; - clock_limits[i].phyclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; - } - for (i = 0; i < clk_table->num_entries; i++) - dcn3_1_soc.clock_limits[i] = clock_limits[i]; - if (clk_table->num_entries) { - dcn3_1_soc.num_states = clk_table->num_entries; - } - } - - dcn3_1_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; - dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; - - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - dml_init_instance(&dc->dml, &dcn3_1_soc, &dcn3_1_ip, DML_PROJECT_DCN31); - else - dml_init_instance(&dc->dml, &dcn3_1_soc, &dcn3_1_ip, DML_PROJECT_DCN31_FPGA); -} - static struct resource_funcs dcn31_res_pool_funcs = { .destroy = dcn31_destroy_resource_pool, .link_enc_create = dcn31_link_encoder_create, diff --git a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h index 4b7ab21ea15b..1ce6509c1ed1 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn31/dcn31_resource.h @@ -31,6 +31,9 @@ #define TO_DCN31_RES_POOL(pool)\ container_of(pool, struct dcn31_resource_pool, base) +extern struct _vcs_dpi_ip_params_st dcn3_1_ip; +extern struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc; + struct dcn31_resource_pool { struct resource_pool base; }; @@ -47,7 +50,6 @@ int dcn31_populate_dml_pipes_from_context( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, bool fast_validate); -void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); void dcn31_update_soc_for_wm_a(struct dc *dc, struct dc_state *context); struct resource_pool *dcn31_create_resource_pool( diff --git a/drivers/gpu/drm/amd/display/dc/dml/Makefile b/drivers/gpu/drm/amd/display/dc/dml/Makefile index 28978ce62f87..ee911452c048 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dml/Makefile @@ -71,6 +71,7 @@ CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_mode_vba_30.o := $(dml_ccflags) $(fram CFLAGS_$(AMDDALPATH)/dc/dml/dcn30/display_rq_dlg_calc_30.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_mode_vba_31.o := $(dml_ccflags) $(frame_warn_flag) CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/display_rq_dlg_calc_31.o := $(dml_ccflags) +CFLAGS_$(AMDDALPATH)/dc/dml/dcn31/dcn31_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn301/dcn301_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn302/dcn302_fpu.o := $(dml_ccflags) CFLAGS_$(AMDDALPATH)/dc/dml/dcn303/dcn303_fpu.o := $(dml_ccflags) @@ -114,6 +115,7 @@ DML += dcn20/display_rq_dlg_calc_20v2.o dcn20/display_mode_vba_20v2.o DML += dcn21/display_rq_dlg_calc_21.o dcn21/display_mode_vba_21.o DML += dcn30/display_mode_vba_30.o dcn30/display_rq_dlg_calc_30.o DML += dcn31/display_mode_vba_31.o dcn31/display_rq_dlg_calc_31.o +DML += dcn31/dcn31_fpu.o DML += dcn301/dcn301_fpu.o DML += dcn302/dcn302_fpu.o DML += dcn303/dcn303_fpu.o diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c new file mode 100644 index 000000000000..7ff8fe9e8712 --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c @@ -0,0 +1,406 @@ +/* + * Copyright 2019-2021 Advanced Micro Devices, Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: AMD + * + */ + +#include "resource.h" +#include "clk_mgr.h" + +#include "dml/dcn20/dcn20_fpu.h" +#include "dcn31_fpu.h" + +/** + * DOC: DCN31x FPU manipulation Overview + * + * The DCN architecture relies on FPU operations, which require special + * compilation flags and the use of kernel_fpu_begin/end functions; ideally, we + * want to avoid spreading FPU access across multiple files. With this idea in + * mind, this file aims to centralize all DCN3.1.x functions that require FPU + * access in a single place. Code in this file follows the following code + * pattern: + * + * 1. Functions that use FPU operations should be isolated in static functions. + * 2. The FPU functions should have the noinline attribute to ensure anything + * that deals with FP register is contained within this call. + * 3. All function that needs to be accessed outside this file requires a + * public interface that not uses any FPU reference. + * 4. Developers **must not** use DC_FP_START/END in this file, but they need + * to ensure that the caller invokes it before access any function available + * in this file. For this reason, public functions in this file must invoke + * dc_assert_fp_enabled(); + */ + +struct _vcs_dpi_ip_params_st dcn3_1_ip = { + .gpuvm_enable = 1, + .gpuvm_max_page_table_levels = 1, + .hostvm_enable = 1, + .hostvm_max_page_table_levels = 2, + .rob_buffer_size_kbytes = 64, + .det_buffer_size_kbytes = DCN3_1_DEFAULT_DET_SIZE, + .config_return_buffer_size_in_kbytes = 1792, + .compressed_buffer_segment_size_in_kbytes = 64, + .meta_fifo_size_in_kentries = 32, + .zero_size_buffer_entries = 512, + .compbuf_reserved_space_64b = 256, + .compbuf_reserved_space_zs = 64, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .meta_chunk_size_kbytes = 2, + .min_meta_chunk_size_bytes = 256, + .writeback_chunk_size_kbytes = 8, + .ptoi_supported = false, + .num_dsc = 3, + .maximum_dsc_bits_per_component = 10, + .dsc422_native_support = false, + .is_line_buffer_bpp_fixed = true, + .line_buffer_fixed_bpp = 48, + .line_buffer_size_bits = 789504, + .max_line_buffer_lines = 12, + .writeback_interface_buffer_size_kbytes = 90, + .max_num_dpp = 4, + .max_num_otg = 4, + .max_num_hdmi_frl_outputs = 1, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 6, + .max_vscl_ratio = 6, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dpte_buffer_size_in_pte_reqs_luma = 64, + .dpte_buffer_size_in_pte_reqs_chroma = 34, + .dispclk_ramp_margin_percent = 1, + .max_inter_dcn_tile_repeaters = 8, + .cursor_buffer_size = 16, + .cursor_chunk_size = 2, + .writeback_line_buffer_buffer_size = 0, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_max_hscl_taps = 1, + .writeback_max_vscl_taps = 1, + .dppclk_delay_subtotal = 46, + .dppclk_delay_scl = 50, + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_cnvc_formatter = 27, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 119, + .dynamic_metadata_vm_enabled = false, + .odm_combine_4to1_supported = false, + .dcc_supported = true, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = { + /*TODO: correct dispclk/dppclk voltage level determination*/ + .clock_limits = { + { + .state = 0, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 600.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 186.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 1, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 209.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 2, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 209.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 3, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 371.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 4, + .dispclk_mhz = 1200.0, + .dppclk_mhz = 1200.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 417.0, + .dtbclk_mhz = 625.0, + }, + }, + .num_states = 5, + .sr_exit_time_us = 9.0, + .sr_enter_plus_exit_time_us = 11.0, + .sr_exit_z8_time_us = 442.0, + .sr_enter_plus_exit_z8_time_us = 560.0, + .writeback_latency_us = 12.0, + .dram_channel_width_bytes = 4, + .round_trip_ping_latency_dcfclk_cycles = 106, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_sdp_bw_after_urgent = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 65.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0, + .max_avg_sdp_bw_use_normal_percent = 60.0, + .max_avg_dram_bw_use_normal_percent = 60.0, + .fabric_datapath_to_dcn_data_return_bytes = 32, + .return_bus_width_bytes = 64, + .downspread_percent = 0.38, + .dcn_downspread_percent = 0.5, + .gpuvm_min_page_size_bytes = 4096, + .hostvm_min_page_size_bytes = 4096, + .do_urgent_latency_adjustment = false, + .urgent_latency_adjustment_fabric_clock_component_us = 0, + .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, +}; + + +void dcn31_calculate_wm_and_dlg_fp( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel) +{ + int i, pipe_idx; + double dcfclk = context->bw_ctx.dml.vba.DCFCLKState[vlevel][context->bw_ctx.dml.vba.maxMpcComb]; + + dc_assert_fp_enabled(); + + if (context->bw_ctx.dml.soc.min_dcfclk > dcfclk) + dcfclk = context->bw_ctx.dml.soc.min_dcfclk; + + /* We don't recalculate clocks for 0 pipe configs, which can block + * S0i3 as high clocks will block low power states + * Override any clocks that can block S0i3 to min here + */ + if (pipe_cnt == 0) { + context->bw_ctx.bw.dcn.clk.dcfclk_khz = dcfclk; // always should be vlevel 0 + return; + } + + pipes[0].clks_cfg.voltage = vlevel; + pipes[0].clks_cfg.dcfclk_mhz = dcfclk; + pipes[0].clks_cfg.socclk_mhz = context->bw_ctx.dml.soc.clock_limits[vlevel].socclk_mhz; + +#if 0 // TODO + /* Set B: + * TODO + */ + if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].valid) { + if (vlevel == 0) { + pipes[0].clks_cfg.voltage = 1; + pipes[0].clks_cfg.dcfclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dcfclk_mhz; + } + context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us; + context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us; + context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us; + } + context->bw_ctx.bw.dcn.watermarks.b.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.b.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + + pipes[0].clks_cfg.voltage = vlevel; + pipes[0].clks_cfg.dcfclk_mhz = dcfclk; + + /* Set C: + * TODO + */ + if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid) { + context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us; + context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us; + context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us; + } + context->bw_ctx.bw.dcn.watermarks.c.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.c.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + + /* Set D: + * TODO + */ + if (dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].valid) { + context->bw_ctx.dml.soc.dram_clock_change_latency_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us; + context->bw_ctx.dml.soc.sr_enter_plus_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us; + context->bw_ctx.dml.soc.sr_exit_time_us = dc->clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us; + } + context->bw_ctx.bw.dcn.watermarks.d.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.d.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; +#endif + + /* Set A: + * All clocks min required + * + * Set A calculated last so that following calculations are based on Set A + */ + dc->res_pool->funcs->update_soc_for_wm_a(dc, context); + context->bw_ctx.bw.dcn.watermarks.a.urgent_ns = get_wm_urgent(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = get_wm_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_ns = get_wm_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.pstate_change_ns = get_wm_dram_clock_change(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_enter_plus_exit_z8_ns = get_wm_z8_stutter_enter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.cstate_pstate.cstate_exit_z8_ns = get_wm_z8_stutter_exit(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.pte_meta_urgent_ns = get_wm_memory_trip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_nom = get_fraction_of_urgent_bandwidth(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.frac_urg_bw_flip = get_fraction_of_urgent_bandwidth_imm_flip(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + context->bw_ctx.bw.dcn.watermarks.a.urgent_latency_ns = get_urgent_latency(&context->bw_ctx.dml, pipes, pipe_cnt) * 1000; + /* TODO: remove: */ + context->bw_ctx.bw.dcn.watermarks.b = context->bw_ctx.bw.dcn.watermarks.a; + context->bw_ctx.bw.dcn.watermarks.c = context->bw_ctx.bw.dcn.watermarks.a; + context->bw_ctx.bw.dcn.watermarks.d = context->bw_ctx.bw.dcn.watermarks.a; + /* end remove*/ + + for (i = 0, pipe_idx = 0; i < dc->res_pool->pipe_count; i++) { + if (!context->res_ctx.pipe_ctx[i].stream) + continue; + + pipes[pipe_idx].clks_cfg.dispclk_mhz = get_dispclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt); + pipes[pipe_idx].clks_cfg.dppclk_mhz = get_dppclk_calculated(&context->bw_ctx.dml, pipes, pipe_cnt, pipe_idx); + + if (dc->config.forced_clocks || dc->debug.max_disp_clk) { + pipes[pipe_idx].clks_cfg.dispclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dispclk_mhz; + pipes[pipe_idx].clks_cfg.dppclk_mhz = context->bw_ctx.dml.soc.clock_limits[0].dppclk_mhz; + } + if (dc->debug.min_disp_clk_khz > pipes[pipe_idx].clks_cfg.dispclk_mhz * 1000) + pipes[pipe_idx].clks_cfg.dispclk_mhz = dc->debug.min_disp_clk_khz / 1000.0; + if (dc->debug.min_dpp_clk_khz > pipes[pipe_idx].clks_cfg.dppclk_mhz * 1000) + pipes[pipe_idx].clks_cfg.dppclk_mhz = dc->debug.min_dpp_clk_khz / 1000.0; + + pipe_idx++; + } + + dcn20_calculate_dlg_params(dc, context, pipes, pipe_cnt, vlevel); +} + +void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + struct clk_limit_table *clk_table = &bw_params->clk_table; + struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; + unsigned int i, closest_clk_lvl; + int j; + + dc_assert_fp_enabled(); + + // Default clock levels are used for diags, which may lead to overclocking. + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + int max_dispclk_mhz = 0, max_dppclk_mhz = 0; + + dcn3_1_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; + dcn3_1_ip.max_num_dpp = dc->res_pool->pipe_count; + dcn3_1_soc.num_chans = bw_params->num_channels; + + ASSERT(clk_table->num_entries); + + /* Prepass to find max clocks independent of voltage level. */ + for (i = 0; i < clk_table->num_entries; ++i) { + if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz) + max_dispclk_mhz = clk_table->entries[i].dispclk_mhz; + if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz) + max_dppclk_mhz = clk_table->entries[i].dppclk_mhz; + } + + for (i = 0; i < clk_table->num_entries; i++) { + /* loop backwards*/ + for (closest_clk_lvl = 0, j = dcn3_1_soc.num_states - 1; j >= 0; j--) { + if ((unsigned int) dcn3_1_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { + closest_clk_lvl = j; + break; + } + } + + clock_limits[i].state = i; + + /* Clocks dependent on voltage level. */ + clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; + clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; + + /* Clocks independent of voltage level. */ + clock_limits[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : + dcn3_1_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + + clock_limits[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : + dcn3_1_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + + clock_limits[i].dram_bw_per_chan_gbps = dcn3_1_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + clock_limits[i].dscclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + clock_limits[i].dtbclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + clock_limits[i].phyclk_d18_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + clock_limits[i].phyclk_mhz = dcn3_1_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + } + for (i = 0; i < clk_table->num_entries; i++) + dcn3_1_soc.clock_limits[i] = clock_limits[i]; + if (clk_table->num_entries) { + dcn3_1_soc.num_states = clk_table->num_entries; + } + } + + dcn3_1_soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + dc->dml.soc.dispclk_dppclk_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + dml_init_instance(&dc->dml, &dcn3_1_soc, &dcn3_1_ip, DML_PROJECT_DCN31); + else + dml_init_instance(&dc->dml, &dcn3_1_soc, &dcn3_1_ip, DML_PROJECT_DCN31_FPGA); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h new file mode 100644 index 000000000000..baadb5150e7d --- /dev/null +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h @@ -0,0 +1,39 @@ +/* + * Copyright 2019-2021 Advanced Micro Devices, Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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. + * + * Authors: AMD + * + */ + +#ifndef __DCN31_FPU_H__ +#define __DCN31_FPU_H__ + +#define DCN3_1_DEFAULT_DET_SIZE 384 + +void dcn31_calculate_wm_and_dlg_fp( + struct dc *dc, struct dc_state *context, + display_e2e_pipe_params_st *pipes, + int pipe_cnt, + int vlevel); + +void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); + +#endif /* __DCN31_FPU_H__*/ From fa896297b31b1100ad13f83a7dd83a715e815042 Mon Sep 17 00:00:00 2001 From: Melissa Wen Date: Mon, 7 Mar 2022 14:48:00 -0100 Subject: [PATCH 00376/11454] drm/amd/display: move FPU related code from dcn315 to dml/dcn31 folder Moves related structs and dcn315_update_bw_bounding_box from dcn315 driver code to dml/dcn31_fpu that centralizes FPU code for DCN 3.1x. Signed-off-by: Melissa Wen Reviewed-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn315/Makefile | 26 -- .../amd/display/dc/dcn315/dcn315_resource.c | 232 +----------------- .../amd/display/dc/dcn315/dcn315_resource.h | 3 + .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.c | 228 +++++++++++++++++ .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.h | 3 + 5 files changed, 235 insertions(+), 257 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/Makefile b/drivers/gpu/drm/amd/display/dc/dcn315/Makefile index c831ad46e81c..59381d24800b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn315/Makefile @@ -25,32 +25,6 @@ DCN315 = dcn315_resource.o -ifdef CONFIG_X86 -CFLAGS_$(AMDDALPATH)/dc/dcn315/dcn315_resource.o := -msse -endif - -ifdef CONFIG_PPC64 -CFLAGS_$(AMDDALPATH)/dc/dcn315/dcn315_resource.o := -mhard-float -maltivec -endif - -ifdef CONFIG_CC_IS_GCC -ifeq ($(call cc-ifversion, -lt, 0701, y), y) -IS_OLD_GCC = 1 -endif -CFLAGS_$(AMDDALPATH)/dc/dcn315/dcn315_resource.o += -mhard-float -endif - -ifdef CONFIG_X86 -ifdef IS_OLD_GCC -# Stack alignment mismatch, proceed with caution. -# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 -# (8B stack alignment). -CFLAGS_$(AMDDALPATH)/dc/dcn315/dcn315_resource.o += -mpreferred-stack-boundary=4 -else -CFLAGS_$(AMDDALPATH)/dc/dcn315/dcn315_resource.o += -msse2 -endif -endif - AMD_DAL_DCN315 = $(addprefix $(AMDDALPATH)/dc/dcn315/,$(DCN315)) AMD_DISPLAY_FILES += $(AMD_DAL_DCN315) diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c index 06adb77c206b..fadb89326999 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.c @@ -66,6 +66,7 @@ #include "virtual/virtual_stream_encoder.h" #include "dce110/dce110_resource.h" #include "dml/display_mode_vba.h" +#include "dml/dcn31/dcn31_fpu.h" #include "dcn31/dcn31_dccg.h" #include "dcn10/dcn10_resource.h" #include "dcn31/dcn31_panel_cntl.h" @@ -133,158 +134,9 @@ #include "link_enc_cfg.h" -#define DC_LOGGER_INIT(logger) - -#define DCN3_15_DEFAULT_DET_SIZE 192 #define DCN3_15_MAX_DET_SIZE 384 -#define DCN3_15_MIN_COMPBUF_SIZE_KB 128 #define DCN3_15_CRB_SEGMENT_SIZE_KB 64 -struct _vcs_dpi_ip_params_st dcn3_15_ip = { - .gpuvm_enable = 1, - .gpuvm_max_page_table_levels = 1, - .hostvm_enable = 1, - .hostvm_max_page_table_levels = 2, - .rob_buffer_size_kbytes = 64, - .det_buffer_size_kbytes = DCN3_15_DEFAULT_DET_SIZE, - .min_comp_buffer_size_kbytes = DCN3_15_MIN_COMPBUF_SIZE_KB, - .config_return_buffer_size_in_kbytes = 1024, - .compressed_buffer_segment_size_in_kbytes = 64, - .meta_fifo_size_in_kentries = 32, - .zero_size_buffer_entries = 512, - .compbuf_reserved_space_64b = 256, - .compbuf_reserved_space_zs = 64, - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .meta_chunk_size_kbytes = 2, - .min_meta_chunk_size_bytes = 256, - .writeback_chunk_size_kbytes = 8, - .ptoi_supported = false, - .num_dsc = 3, - .maximum_dsc_bits_per_component = 10, - .dsc422_native_support = false, - .is_line_buffer_bpp_fixed = true, - .line_buffer_fixed_bpp = 49, - .line_buffer_size_bits = 789504, - .max_line_buffer_lines = 12, - .writeback_interface_buffer_size_kbytes = 90, - .max_num_dpp = 4, - .max_num_otg = 4, - .max_num_hdmi_frl_outputs = 1, - .max_num_wb = 1, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 6, - .max_vscl_ratio = 6, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dpte_buffer_size_in_pte_reqs_luma = 64, - .dpte_buffer_size_in_pte_reqs_chroma = 34, - .dispclk_ramp_margin_percent = 1, - .max_inter_dcn_tile_repeaters = 9, - .cursor_buffer_size = 16, - .cursor_chunk_size = 2, - .writeback_line_buffer_buffer_size = 0, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_max_hscl_taps = 1, - .writeback_max_vscl_taps = 1, - .dppclk_delay_subtotal = 46, - .dppclk_delay_scl = 50, - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_cnvc_formatter = 27, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 119, - .dynamic_metadata_vm_enabled = false, - .odm_combine_4to1_supported = false, - .dcc_supported = true, -}; - -struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = { - /*TODO: correct dispclk/dppclk voltage level determination*/ - .clock_limits = { - { - .state = 0, - .dispclk_mhz = 1372.0, - .dppclk_mhz = 1372.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 417.0, - .dtbclk_mhz = 600.0, - }, - { - .state = 1, - .dispclk_mhz = 1372.0, - .dppclk_mhz = 1372.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 417.0, - .dtbclk_mhz = 600.0, - }, - { - .state = 2, - .dispclk_mhz = 1372.0, - .dppclk_mhz = 1372.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 417.0, - .dtbclk_mhz = 600.0, - }, - { - .state = 3, - .dispclk_mhz = 1372.0, - .dppclk_mhz = 1372.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 417.0, - .dtbclk_mhz = 600.0, - }, - { - .state = 4, - .dispclk_mhz = 1372.0, - .dppclk_mhz = 1372.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 417.0, - .dtbclk_mhz = 600.0, - }, - }, - .num_states = 5, - .sr_exit_time_us = 9.0, - .sr_enter_plus_exit_time_us = 11.0, - .sr_exit_z8_time_us = 50.0, - .sr_enter_plus_exit_z8_time_us = 50.0, - .writeback_latency_us = 12.0, - .dram_channel_width_bytes = 4, - .round_trip_ping_latency_dcfclk_cycles = 106, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, - .pct_ideal_sdp_bw_after_urgent = 80.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 65.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0, - .max_avg_sdp_bw_use_normal_percent = 60.0, - .max_avg_dram_bw_use_normal_percent = 60.0, - .fabric_datapath_to_dcn_data_return_bytes = 32, - .return_bus_width_bytes = 64, - .downspread_percent = 0.38, - .dcn_downspread_percent = 0.38, - .gpuvm_min_page_size_bytes = 4096, - .hostvm_min_page_size_bytes = 4096, - .do_urgent_latency_adjustment = false, - .urgent_latency_adjustment_fabric_clock_component_us = 0, - .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, -}; - enum dcn31_clk_src_array_id { DCN31_CLK_SRC_PLL0, DCN31_CLK_SRC_PLL1, @@ -1859,88 +1711,6 @@ static struct dc_cap_funcs cap_funcs = { .get_dcc_compression_cap = dcn20_get_dcc_compression_cap }; -static void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ - struct clk_limit_table *clk_table = &bw_params->clk_table; - struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; - unsigned int i, closest_clk_lvl; - int max_dispclk_mhz = 0, max_dppclk_mhz = 0; - int j; - - // Default clock levels are used for diags, which may lead to overclocking. - if (!IS_DIAG_DC(dc->ctx->dce_environment)) { - - dcn3_15_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; - dcn3_15_ip.max_num_dpp = dc->res_pool->pipe_count; - dcn3_15_soc.num_chans = bw_params->num_channels; - - ASSERT(clk_table->num_entries); - - /* Prepass to find max clocks independent of voltage level. */ - for (i = 0; i < clk_table->num_entries; ++i) { - if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz) - max_dispclk_mhz = clk_table->entries[i].dispclk_mhz; - if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz) - max_dppclk_mhz = clk_table->entries[i].dppclk_mhz; - } - - for (i = 0; i < clk_table->num_entries; i++) { - /* loop backwards*/ - for (closest_clk_lvl = 0, j = dcn3_15_soc.num_states - 1; j >= 0; j--) { - if ((unsigned int) dcn3_15_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { - closest_clk_lvl = j; - break; - } - } - if (clk_table->num_entries == 1) { - /*smu gives one DPM level, let's take the highest one*/ - closest_clk_lvl = dcn3_15_soc.num_states - 1; - } - - clock_limits[i].state = i; - - /* Clocks dependent on voltage level. */ - clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - if (clk_table->num_entries == 1 && - clock_limits[i].dcfclk_mhz < dcn3_15_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) { - /*SMU fix not released yet*/ - clock_limits[i].dcfclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].dcfclk_mhz; - } - clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; - clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; - - /* Clocks independent of voltage level. */ - clock_limits[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : - dcn3_15_soc.clock_limits[closest_clk_lvl].dispclk_mhz; - - clock_limits[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : - dcn3_15_soc.clock_limits[closest_clk_lvl].dppclk_mhz; - - clock_limits[i].dram_bw_per_chan_gbps = dcn3_15_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; - clock_limits[i].dscclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].dscclk_mhz; - clock_limits[i].dtbclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; - clock_limits[i].phyclk_d18_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; - clock_limits[i].phyclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].phyclk_mhz; - } - for (i = 0; i < clk_table->num_entries; i++) - dcn3_15_soc.clock_limits[i] = clock_limits[i]; - if (clk_table->num_entries) { - dcn3_15_soc.num_states = clk_table->num_entries; - } - } - - if (max_dispclk_mhz) { - dcn3_15_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; - dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; - } - - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31); - else - dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31_FPGA); -} - static struct resource_funcs dcn315_res_pool_funcs = { .destroy = dcn315_destroy_resource_pool, .link_enc_create = dcn31_link_encoder_create, diff --git a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h index f3a36820a31f..39929fa67a51 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn315/dcn315_resource.h @@ -31,6 +31,9 @@ #define TO_DCN315_RES_POOL(pool)\ container_of(pool, struct dcn315_resource_pool, base) +extern struct _vcs_dpi_ip_params_st dcn3_15_ip; +extern struct _vcs_dpi_ip_params_st dcn3_15_soc; + struct dcn315_resource_pool { struct resource_pool base; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c index 7ff8fe9e8712..f70b47ef850c 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c @@ -194,6 +194,150 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_1_soc = { .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, }; +struct _vcs_dpi_ip_params_st dcn3_15_ip = { + .gpuvm_enable = 1, + .gpuvm_max_page_table_levels = 1, + .hostvm_enable = 1, + .hostvm_max_page_table_levels = 2, + .rob_buffer_size_kbytes = 64, + .det_buffer_size_kbytes = DCN3_15_DEFAULT_DET_SIZE, + .min_comp_buffer_size_kbytes = DCN3_15_MIN_COMPBUF_SIZE_KB, + .config_return_buffer_size_in_kbytes = 1024, + .compressed_buffer_segment_size_in_kbytes = 64, + .meta_fifo_size_in_kentries = 32, + .zero_size_buffer_entries = 512, + .compbuf_reserved_space_64b = 256, + .compbuf_reserved_space_zs = 64, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .meta_chunk_size_kbytes = 2, + .min_meta_chunk_size_bytes = 256, + .writeback_chunk_size_kbytes = 8, + .ptoi_supported = false, + .num_dsc = 3, + .maximum_dsc_bits_per_component = 10, + .dsc422_native_support = false, + .is_line_buffer_bpp_fixed = true, + .line_buffer_fixed_bpp = 49, + .line_buffer_size_bits = 789504, + .max_line_buffer_lines = 12, + .writeback_interface_buffer_size_kbytes = 90, + .max_num_dpp = 4, + .max_num_otg = 4, + .max_num_hdmi_frl_outputs = 1, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 6, + .max_vscl_ratio = 6, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dpte_buffer_size_in_pte_reqs_luma = 64, + .dpte_buffer_size_in_pte_reqs_chroma = 34, + .dispclk_ramp_margin_percent = 1, + .max_inter_dcn_tile_repeaters = 9, + .cursor_buffer_size = 16, + .cursor_chunk_size = 2, + .writeback_line_buffer_buffer_size = 0, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_max_hscl_taps = 1, + .writeback_max_vscl_taps = 1, + .dppclk_delay_subtotal = 46, + .dppclk_delay_scl = 50, + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_cnvc_formatter = 27, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 119, + .dynamic_metadata_vm_enabled = false, + .odm_combine_4to1_supported = false, + .dcc_supported = true, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = { + /*TODO: correct dispclk/dppclk voltage level determination*/ + .clock_limits = { + { + .state = 0, + .dispclk_mhz = 1372.0, + .dppclk_mhz = 1372.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 417.0, + .dtbclk_mhz = 600.0, + }, + { + .state = 1, + .dispclk_mhz = 1372.0, + .dppclk_mhz = 1372.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 417.0, + .dtbclk_mhz = 600.0, + }, + { + .state = 2, + .dispclk_mhz = 1372.0, + .dppclk_mhz = 1372.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 417.0, + .dtbclk_mhz = 600.0, + }, + { + .state = 3, + .dispclk_mhz = 1372.0, + .dppclk_mhz = 1372.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 417.0, + .dtbclk_mhz = 600.0, + }, + { + .state = 4, + .dispclk_mhz = 1372.0, + .dppclk_mhz = 1372.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 417.0, + .dtbclk_mhz = 600.0, + }, + }, + .num_states = 5, + .sr_exit_time_us = 9.0, + .sr_enter_plus_exit_time_us = 11.0, + .sr_exit_z8_time_us = 50.0, + .sr_enter_plus_exit_z8_time_us = 50.0, + .writeback_latency_us = 12.0, + .dram_channel_width_bytes = 4, + .round_trip_ping_latency_dcfclk_cycles = 106, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_sdp_bw_after_urgent = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 65.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0, + .max_avg_sdp_bw_use_normal_percent = 60.0, + .max_avg_dram_bw_use_normal_percent = 60.0, + .fabric_datapath_to_dcn_data_return_bytes = 32, + .return_bus_width_bytes = 64, + .downspread_percent = 0.38, + .dcn_downspread_percent = 0.38, + .gpuvm_min_page_size_bytes = 4096, + .hostvm_min_page_size_bytes = 4096, + .do_urgent_latency_adjustment = false, + .urgent_latency_adjustment_fabric_clock_component_us = 0, + .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, +}; void dcn31_calculate_wm_and_dlg_fp( struct dc *dc, struct dc_state *context, @@ -404,3 +548,87 @@ void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params else dml_init_instance(&dc->dml, &dcn3_1_soc, &dcn3_1_ip, DML_PROJECT_DCN31_FPGA); } + +void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + struct clk_limit_table *clk_table = &bw_params->clk_table; + struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; + unsigned int i, closest_clk_lvl; + int max_dispclk_mhz = 0, max_dppclk_mhz = 0; + int j; + + dc_assert_fp_enabled(); + + // Default clock levels are used for diags, which may lead to overclocking. + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + + dcn3_15_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; + dcn3_15_ip.max_num_dpp = dc->res_pool->pipe_count; + dcn3_15_soc.num_chans = bw_params->num_channels; + + ASSERT(clk_table->num_entries); + + /* Prepass to find max clocks independent of voltage level. */ + for (i = 0; i < clk_table->num_entries; ++i) { + if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz) + max_dispclk_mhz = clk_table->entries[i].dispclk_mhz; + if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz) + max_dppclk_mhz = clk_table->entries[i].dppclk_mhz; + } + + for (i = 0; i < clk_table->num_entries; i++) { + /* loop backwards*/ + for (closest_clk_lvl = 0, j = dcn3_15_soc.num_states - 1; j >= 0; j--) { + if ((unsigned int) dcn3_15_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { + closest_clk_lvl = j; + break; + } + } + if (clk_table->num_entries == 1) { + /*smu gives one DPM level, let's take the highest one*/ + closest_clk_lvl = dcn3_15_soc.num_states - 1; + } + + clock_limits[i].state = i; + + /* Clocks dependent on voltage level. */ + clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + if (clk_table->num_entries == 1 && + clock_limits[i].dcfclk_mhz < dcn3_15_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) { + /*SMU fix not released yet*/ + clock_limits[i].dcfclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].dcfclk_mhz; + } + clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; + clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; + + /* Clocks independent of voltage level. */ + clock_limits[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : + dcn3_15_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + + clock_limits[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : + dcn3_15_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + + clock_limits[i].dram_bw_per_chan_gbps = dcn3_15_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + clock_limits[i].dscclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + clock_limits[i].dtbclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + clock_limits[i].phyclk_d18_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + clock_limits[i].phyclk_mhz = dcn3_15_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + } + for (i = 0; i < clk_table->num_entries; i++) + dcn3_15_soc.clock_limits[i] = clock_limits[i]; + if (clk_table->num_entries) { + dcn3_15_soc.num_states = clk_table->num_entries; + } + } + + if (max_dispclk_mhz) { + dcn3_15_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; + dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; + } + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31); + else + dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31_FPGA); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h index baadb5150e7d..b15b587cf8c4 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h @@ -27,6 +27,8 @@ #define __DCN31_FPU_H__ #define DCN3_1_DEFAULT_DET_SIZE 384 +#define DCN3_15_DEFAULT_DET_SIZE 192 +#define DCN3_15_MIN_COMPBUF_SIZE_KB 128 void dcn31_calculate_wm_and_dlg_fp( struct dc *dc, struct dc_state *context, @@ -35,5 +37,6 @@ void dcn31_calculate_wm_and_dlg_fp( int vlevel); void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); +void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); #endif /* __DCN31_FPU_H__*/ From 3f8951cc123f102a4e21d61390993bc7d142b723 Mon Sep 17 00:00:00 2001 From: Melissa Wen Date: Mon, 7 Mar 2022 14:48:01 -0100 Subject: [PATCH 00377/11454] drm/amd/display: move FPU related code from dcn316 to dml/dcn31 folder Moves FPU-related structs and dcn316_update_bw_bounding_box from dcn316 driver to dml/dcn31 that centralize FPU operations for DCN 3.1x Signed-off-by: Melissa Wen Reviewed-by: Alex Hung Tested-by: Daniel Wheeler Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn316/Makefile | 26 -- .../amd/display/dc/dcn316/dcn316_resource.c | 231 +----------------- .../amd/display/dc/dcn316/dcn316_resource.h | 3 + .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.c | 229 +++++++++++++++++ .../drm/amd/display/dc/dml/dcn31/dcn31_fpu.h | 2 + 5 files changed, 235 insertions(+), 256 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/Makefile b/drivers/gpu/drm/amd/display/dc/dcn316/Makefile index cd87b687c5e2..819d44a9439b 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/Makefile +++ b/drivers/gpu/drm/amd/display/dc/dcn316/Makefile @@ -25,32 +25,6 @@ DCN316 = dcn316_resource.o -ifdef CONFIG_X86 -CFLAGS_$(AMDDALPATH)/dc/dcn316/dcn316_resource.o := -msse -endif - -ifdef CONFIG_PPC64 -CFLAGS_$(AMDDALPATH)/dc/dcn316/dcn316_resource.o := -mhard-float -maltivec -endif - -ifdef CONFIG_CC_IS_GCC -ifeq ($(call cc-ifversion, -lt, 0701, y), y) -IS_OLD_GCC = 1 -endif -CFLAGS_$(AMDDALPATH)/dc/dcn316/dcn316_resource.o += -mhard-float -endif - -ifdef CONFIG_X86 -ifdef IS_OLD_GCC -# Stack alignment mismatch, proceed with caution. -# GCC < 7.1 cannot compile code using `double` and -mpreferred-stack-boundary=3 -# (8B stack alignment). -CFLAGS_$(AMDDALPATH)/dc/dcn316/dcn316_resource.o += -mpreferred-stack-boundary=4 -else -CFLAGS_$(AMDDALPATH)/dc/dcn316/dcn316_resource.o += -msse2 -endif -endif - AMD_DAL_DCN316 = $(addprefix $(AMDDALPATH)/dc/dcn316/,$(DCN316)) AMD_DISPLAY_FILES += $(AMD_DAL_DCN316) diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c index 8decc3ccf8ca..d73145dab173 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.c @@ -66,6 +66,7 @@ #include "virtual/virtual_stream_encoder.h" #include "dce110/dce110_resource.h" #include "dml/display_mode_vba.h" +#include "dml/dcn31/dcn31_fpu.h" #include "dcn31/dcn31_dccg.h" #include "dcn10/dcn10_resource.h" #include "dcn31/dcn31_panel_cntl.h" @@ -123,157 +124,10 @@ #include "link_enc_cfg.h" -#define DC_LOGGER_INIT(logger) - -#define DCN3_16_DEFAULT_DET_SIZE 192 #define DCN3_16_MAX_DET_SIZE 384 #define DCN3_16_MIN_COMPBUF_SIZE_KB 128 #define DCN3_16_CRB_SEGMENT_SIZE_KB 64 -struct _vcs_dpi_ip_params_st dcn3_16_ip = { - .gpuvm_enable = 1, - .gpuvm_max_page_table_levels = 1, - .hostvm_enable = 1, - .hostvm_max_page_table_levels = 2, - .rob_buffer_size_kbytes = 64, - .det_buffer_size_kbytes = DCN3_16_DEFAULT_DET_SIZE, - .config_return_buffer_size_in_kbytes = 1024, - .compressed_buffer_segment_size_in_kbytes = 64, - .meta_fifo_size_in_kentries = 32, - .zero_size_buffer_entries = 512, - .compbuf_reserved_space_64b = 256, - .compbuf_reserved_space_zs = 64, - .dpp_output_buffer_pixels = 2560, - .opp_output_buffer_lines = 1, - .pixel_chunk_size_kbytes = 8, - .meta_chunk_size_kbytes = 2, - .min_meta_chunk_size_bytes = 256, - .writeback_chunk_size_kbytes = 8, - .ptoi_supported = false, - .num_dsc = 3, - .maximum_dsc_bits_per_component = 10, - .dsc422_native_support = false, - .is_line_buffer_bpp_fixed = true, - .line_buffer_fixed_bpp = 48, - .line_buffer_size_bits = 789504, - .max_line_buffer_lines = 12, - .writeback_interface_buffer_size_kbytes = 90, - .max_num_dpp = 4, - .max_num_otg = 4, - .max_num_hdmi_frl_outputs = 1, - .max_num_wb = 1, - .max_dchub_pscl_bw_pix_per_clk = 4, - .max_pscl_lb_bw_pix_per_clk = 2, - .max_lb_vscl_bw_pix_per_clk = 4, - .max_vscl_hscl_bw_pix_per_clk = 4, - .max_hscl_ratio = 6, - .max_vscl_ratio = 6, - .max_hscl_taps = 8, - .max_vscl_taps = 8, - .dpte_buffer_size_in_pte_reqs_luma = 64, - .dpte_buffer_size_in_pte_reqs_chroma = 34, - .dispclk_ramp_margin_percent = 1, - .max_inter_dcn_tile_repeaters = 8, - .cursor_buffer_size = 16, - .cursor_chunk_size = 2, - .writeback_line_buffer_buffer_size = 0, - .writeback_min_hscl_ratio = 1, - .writeback_min_vscl_ratio = 1, - .writeback_max_hscl_ratio = 1, - .writeback_max_vscl_ratio = 1, - .writeback_max_hscl_taps = 1, - .writeback_max_vscl_taps = 1, - .dppclk_delay_subtotal = 46, - .dppclk_delay_scl = 50, - .dppclk_delay_scl_lb_only = 16, - .dppclk_delay_cnvc_formatter = 27, - .dppclk_delay_cnvc_cursor = 6, - .dispclk_delay_subtotal = 119, - .dynamic_metadata_vm_enabled = false, - .odm_combine_4to1_supported = false, - .dcc_supported = true, -}; - -struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = { - /*TODO: correct dispclk/dppclk voltage level determination*/ - .clock_limits = { - { - .state = 0, - .dispclk_mhz = 556.0, - .dppclk_mhz = 556.0, - .phyclk_mhz = 600.0, - .phyclk_d18_mhz = 445.0, - .dscclk_mhz = 186.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 1, - .dispclk_mhz = 625.0, - .dppclk_mhz = 625.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 209.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 2, - .dispclk_mhz = 625.0, - .dppclk_mhz = 625.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 209.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 3, - .dispclk_mhz = 1112.0, - .dppclk_mhz = 1112.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 371.0, - .dtbclk_mhz = 625.0, - }, - { - .state = 4, - .dispclk_mhz = 1250.0, - .dppclk_mhz = 1250.0, - .phyclk_mhz = 810.0, - .phyclk_d18_mhz = 667.0, - .dscclk_mhz = 417.0, - .dtbclk_mhz = 625.0, - }, - }, - .num_states = 5, - .sr_exit_time_us = 9.0, - .sr_enter_plus_exit_time_us = 11.0, - .sr_exit_z8_time_us = 442.0, - .sr_enter_plus_exit_z8_time_us = 560.0, - .writeback_latency_us = 12.0, - .dram_channel_width_bytes = 4, - .round_trip_ping_latency_dcfclk_cycles = 106, - .urgent_latency_pixel_data_only_us = 4.0, - .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, - .urgent_latency_vm_data_only_us = 4.0, - .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, - .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, - .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, - .pct_ideal_sdp_bw_after_urgent = 80.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 65.0, - .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, - .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0, - .max_avg_sdp_bw_use_normal_percent = 60.0, - .max_avg_dram_bw_use_normal_percent = 60.0, - .fabric_datapath_to_dcn_data_return_bytes = 32, - .return_bus_width_bytes = 64, - .downspread_percent = 0.38, - .dcn_downspread_percent = 0.5, - .gpuvm_min_page_size_bytes = 4096, - .hostvm_min_page_size_bytes = 4096, - .do_urgent_latency_adjustment = false, - .urgent_latency_adjustment_fabric_clock_component_us = 0, - .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, -}; - enum dcn31_clk_src_array_id { DCN31_CLK_SRC_PLL0, DCN31_CLK_SRC_PLL1, @@ -1859,89 +1713,6 @@ static struct dc_cap_funcs cap_funcs = { .get_dcc_compression_cap = dcn20_get_dcc_compression_cap }; -static void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) -{ - struct clk_limit_table *clk_table = &bw_params->clk_table; - struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; - unsigned int i, closest_clk_lvl; - int max_dispclk_mhz = 0, max_dppclk_mhz = 0; - int j; - - // Default clock levels are used for diags, which may lead to overclocking. - if (!IS_DIAG_DC(dc->ctx->dce_environment)) { - - dcn3_16_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; - dcn3_16_ip.max_num_dpp = dc->res_pool->pipe_count; - dcn3_16_soc.num_chans = bw_params->num_channels; - - ASSERT(clk_table->num_entries); - - /* Prepass to find max clocks independent of voltage level. */ - for (i = 0; i < clk_table->num_entries; ++i) { - if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz) - max_dispclk_mhz = clk_table->entries[i].dispclk_mhz; - if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz) - max_dppclk_mhz = clk_table->entries[i].dppclk_mhz; - } - - for (i = 0; i < clk_table->num_entries; i++) { - /* loop backwards*/ - for (closest_clk_lvl = 0, j = dcn3_16_soc.num_states - 1; j >= 0; j--) { - if ((unsigned int) dcn3_16_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { - closest_clk_lvl = j; - break; - } - } - // Ported from DCN315 - if (clk_table->num_entries == 1) { - /*smu gives one DPM level, let's take the highest one*/ - closest_clk_lvl = dcn3_16_soc.num_states - 1; - } - - clock_limits[i].state = i; - - /* Clocks dependent on voltage level. */ - clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; - if (clk_table->num_entries == 1 && - clock_limits[i].dcfclk_mhz < dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) { - /*SMU fix not released yet*/ - clock_limits[i].dcfclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz; - } - clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; - clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; - clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; - - /* Clocks independent of voltage level. */ - clock_limits[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : - dcn3_16_soc.clock_limits[closest_clk_lvl].dispclk_mhz; - - clock_limits[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : - dcn3_16_soc.clock_limits[closest_clk_lvl].dppclk_mhz; - - clock_limits[i].dram_bw_per_chan_gbps = dcn3_16_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; - clock_limits[i].dscclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dscclk_mhz; - clock_limits[i].dtbclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; - clock_limits[i].phyclk_d18_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; - clock_limits[i].phyclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_mhz; - } - for (i = 0; i < clk_table->num_entries; i++) - dcn3_16_soc.clock_limits[i] = clock_limits[i]; - if (clk_table->num_entries) { - dcn3_16_soc.num_states = clk_table->num_entries; - } - } - - if (max_dispclk_mhz) { - dcn3_16_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; - dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; - } - - if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) - dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31); - else - dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31_FPGA); -} - static struct resource_funcs dcn316_res_pool_funcs = { .destroy = dcn316_destroy_resource_pool, .link_enc_create = dcn31_link_encoder_create, diff --git a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h index 9d0d60cb9482..0dc5a6c13ae7 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h +++ b/drivers/gpu/drm/amd/display/dc/dcn316/dcn316_resource.h @@ -31,6 +31,9 @@ #define TO_DCN316_RES_POOL(pool)\ container_of(pool, struct dcn316_resource_pool, base) +extern struct _vcs_dpi_ip_params_st dcn3_16_ip; +extern struct _vcs_dpi_ip_params_st dcn3_16_soc; + struct dcn316_resource_pool { struct resource_pool base; }; diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c index f70b47ef850c..a0a2e125c9c8 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.c @@ -339,6 +339,150 @@ struct _vcs_dpi_soc_bounding_box_st dcn3_15_soc = { .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, }; +struct _vcs_dpi_ip_params_st dcn3_16_ip = { + .gpuvm_enable = 1, + .gpuvm_max_page_table_levels = 1, + .hostvm_enable = 1, + .hostvm_max_page_table_levels = 2, + .rob_buffer_size_kbytes = 64, + .det_buffer_size_kbytes = DCN3_16_DEFAULT_DET_SIZE, + .config_return_buffer_size_in_kbytes = 1024, + .compressed_buffer_segment_size_in_kbytes = 64, + .meta_fifo_size_in_kentries = 32, + .zero_size_buffer_entries = 512, + .compbuf_reserved_space_64b = 256, + .compbuf_reserved_space_zs = 64, + .dpp_output_buffer_pixels = 2560, + .opp_output_buffer_lines = 1, + .pixel_chunk_size_kbytes = 8, + .meta_chunk_size_kbytes = 2, + .min_meta_chunk_size_bytes = 256, + .writeback_chunk_size_kbytes = 8, + .ptoi_supported = false, + .num_dsc = 3, + .maximum_dsc_bits_per_component = 10, + .dsc422_native_support = false, + .is_line_buffer_bpp_fixed = true, + .line_buffer_fixed_bpp = 48, + .line_buffer_size_bits = 789504, + .max_line_buffer_lines = 12, + .writeback_interface_buffer_size_kbytes = 90, + .max_num_dpp = 4, + .max_num_otg = 4, + .max_num_hdmi_frl_outputs = 1, + .max_num_wb = 1, + .max_dchub_pscl_bw_pix_per_clk = 4, + .max_pscl_lb_bw_pix_per_clk = 2, + .max_lb_vscl_bw_pix_per_clk = 4, + .max_vscl_hscl_bw_pix_per_clk = 4, + .max_hscl_ratio = 6, + .max_vscl_ratio = 6, + .max_hscl_taps = 8, + .max_vscl_taps = 8, + .dpte_buffer_size_in_pte_reqs_luma = 64, + .dpte_buffer_size_in_pte_reqs_chroma = 34, + .dispclk_ramp_margin_percent = 1, + .max_inter_dcn_tile_repeaters = 8, + .cursor_buffer_size = 16, + .cursor_chunk_size = 2, + .writeback_line_buffer_buffer_size = 0, + .writeback_min_hscl_ratio = 1, + .writeback_min_vscl_ratio = 1, + .writeback_max_hscl_ratio = 1, + .writeback_max_vscl_ratio = 1, + .writeback_max_hscl_taps = 1, + .writeback_max_vscl_taps = 1, + .dppclk_delay_subtotal = 46, + .dppclk_delay_scl = 50, + .dppclk_delay_scl_lb_only = 16, + .dppclk_delay_cnvc_formatter = 27, + .dppclk_delay_cnvc_cursor = 6, + .dispclk_delay_subtotal = 119, + .dynamic_metadata_vm_enabled = false, + .odm_combine_4to1_supported = false, + .dcc_supported = true, +}; + +struct _vcs_dpi_soc_bounding_box_st dcn3_16_soc = { + /*TODO: correct dispclk/dppclk voltage level determination*/ + .clock_limits = { + { + .state = 0, + .dispclk_mhz = 556.0, + .dppclk_mhz = 556.0, + .phyclk_mhz = 600.0, + .phyclk_d18_mhz = 445.0, + .dscclk_mhz = 186.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 1, + .dispclk_mhz = 625.0, + .dppclk_mhz = 625.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 209.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 2, + .dispclk_mhz = 625.0, + .dppclk_mhz = 625.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 209.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 3, + .dispclk_mhz = 1112.0, + .dppclk_mhz = 1112.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 371.0, + .dtbclk_mhz = 625.0, + }, + { + .state = 4, + .dispclk_mhz = 1250.0, + .dppclk_mhz = 1250.0, + .phyclk_mhz = 810.0, + .phyclk_d18_mhz = 667.0, + .dscclk_mhz = 417.0, + .dtbclk_mhz = 625.0, + }, + }, + .num_states = 5, + .sr_exit_time_us = 9.0, + .sr_enter_plus_exit_time_us = 11.0, + .sr_exit_z8_time_us = 442.0, + .sr_enter_plus_exit_z8_time_us = 560.0, + .writeback_latency_us = 12.0, + .dram_channel_width_bytes = 4, + .round_trip_ping_latency_dcfclk_cycles = 106, + .urgent_latency_pixel_data_only_us = 4.0, + .urgent_latency_pixel_mixed_with_vm_data_us = 4.0, + .urgent_latency_vm_data_only_us = 4.0, + .urgent_out_of_order_return_per_channel_pixel_only_bytes = 4096, + .urgent_out_of_order_return_per_channel_pixel_and_vm_bytes = 4096, + .urgent_out_of_order_return_per_channel_vm_only_bytes = 4096, + .pct_ideal_sdp_bw_after_urgent = 80.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_only = 65.0, + .pct_ideal_dram_sdp_bw_after_urgent_pixel_and_vm = 60.0, + .pct_ideal_dram_sdp_bw_after_urgent_vm_only = 30.0, + .max_avg_sdp_bw_use_normal_percent = 60.0, + .max_avg_dram_bw_use_normal_percent = 60.0, + .fabric_datapath_to_dcn_data_return_bytes = 32, + .return_bus_width_bytes = 64, + .downspread_percent = 0.38, + .dcn_downspread_percent = 0.5, + .gpuvm_min_page_size_bytes = 4096, + .hostvm_min_page_size_bytes = 4096, + .do_urgent_latency_adjustment = false, + .urgent_latency_adjustment_fabric_clock_component_us = 0, + .urgent_latency_adjustment_fabric_clock_reference_mhz = 0, +}; + void dcn31_calculate_wm_and_dlg_fp( struct dc *dc, struct dc_state *context, display_e2e_pipe_params_st *pipes, @@ -632,3 +776,88 @@ void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_param else dml_init_instance(&dc->dml, &dcn3_15_soc, &dcn3_15_ip, DML_PROJECT_DCN31_FPGA); } + +void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params) +{ + struct clk_limit_table *clk_table = &bw_params->clk_table; + struct _vcs_dpi_voltage_scaling_st clock_limits[DC__VOLTAGE_STATES]; + unsigned int i, closest_clk_lvl; + int max_dispclk_mhz = 0, max_dppclk_mhz = 0; + int j; + + dc_assert_fp_enabled(); + + // Default clock levels are used for diags, which may lead to overclocking. + if (!IS_DIAG_DC(dc->ctx->dce_environment)) { + + dcn3_16_ip.max_num_otg = dc->res_pool->res_cap->num_timing_generator; + dcn3_16_ip.max_num_dpp = dc->res_pool->pipe_count; + dcn3_16_soc.num_chans = bw_params->num_channels; + + ASSERT(clk_table->num_entries); + + /* Prepass to find max clocks independent of voltage level. */ + for (i = 0; i < clk_table->num_entries; ++i) { + if (clk_table->entries[i].dispclk_mhz > max_dispclk_mhz) + max_dispclk_mhz = clk_table->entries[i].dispclk_mhz; + if (clk_table->entries[i].dppclk_mhz > max_dppclk_mhz) + max_dppclk_mhz = clk_table->entries[i].dppclk_mhz; + } + + for (i = 0; i < clk_table->num_entries; i++) { + /* loop backwards*/ + for (closest_clk_lvl = 0, j = dcn3_16_soc.num_states - 1; j >= 0; j--) { + if ((unsigned int) dcn3_16_soc.clock_limits[j].dcfclk_mhz <= clk_table->entries[i].dcfclk_mhz) { + closest_clk_lvl = j; + break; + } + } + // Ported from DCN315 + if (clk_table->num_entries == 1) { + /*smu gives one DPM level, let's take the highest one*/ + closest_clk_lvl = dcn3_16_soc.num_states - 1; + } + + clock_limits[i].state = i; + + /* Clocks dependent on voltage level. */ + clock_limits[i].dcfclk_mhz = clk_table->entries[i].dcfclk_mhz; + if (clk_table->num_entries == 1 && + clock_limits[i].dcfclk_mhz < dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz) { + /*SMU fix not released yet*/ + clock_limits[i].dcfclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dcfclk_mhz; + } + clock_limits[i].fabricclk_mhz = clk_table->entries[i].fclk_mhz; + clock_limits[i].socclk_mhz = clk_table->entries[i].socclk_mhz; + clock_limits[i].dram_speed_mts = clk_table->entries[i].memclk_mhz * 2 * clk_table->entries[i].wck_ratio; + + /* Clocks independent of voltage level. */ + clock_limits[i].dispclk_mhz = max_dispclk_mhz ? max_dispclk_mhz : + dcn3_16_soc.clock_limits[closest_clk_lvl].dispclk_mhz; + + clock_limits[i].dppclk_mhz = max_dppclk_mhz ? max_dppclk_mhz : + dcn3_16_soc.clock_limits[closest_clk_lvl].dppclk_mhz; + + clock_limits[i].dram_bw_per_chan_gbps = dcn3_16_soc.clock_limits[closest_clk_lvl].dram_bw_per_chan_gbps; + clock_limits[i].dscclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dscclk_mhz; + clock_limits[i].dtbclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].dtbclk_mhz; + clock_limits[i].phyclk_d18_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_d18_mhz; + clock_limits[i].phyclk_mhz = dcn3_16_soc.clock_limits[closest_clk_lvl].phyclk_mhz; + } + for (i = 0; i < clk_table->num_entries; i++) + dcn3_16_soc.clock_limits[i] = clock_limits[i]; + if (clk_table->num_entries) { + dcn3_16_soc.num_states = clk_table->num_entries; + } + } + + if (max_dispclk_mhz) { + dcn3_16_soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; + dc->dml.soc.dispclk_dppclk_vco_speed_mhz = max_dispclk_mhz * 2; + } + + if (!IS_FPGA_MAXIMUS_DC(dc->ctx->dce_environment)) + dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31); + else + dml_init_instance(&dc->dml, &dcn3_16_soc, &dcn3_16_ip, DML_PROJECT_DCN31_FPGA); +} diff --git a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h index b15b587cf8c4..24ac19c83687 100644 --- a/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h +++ b/drivers/gpu/drm/amd/display/dc/dml/dcn31/dcn31_fpu.h @@ -29,6 +29,7 @@ #define DCN3_1_DEFAULT_DET_SIZE 384 #define DCN3_15_DEFAULT_DET_SIZE 192 #define DCN3_15_MIN_COMPBUF_SIZE_KB 128 +#define DCN3_16_DEFAULT_DET_SIZE 192 void dcn31_calculate_wm_and_dlg_fp( struct dc *dc, struct dc_state *context, @@ -38,5 +39,6 @@ void dcn31_calculate_wm_and_dlg_fp( void dcn31_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); void dcn315_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); +void dcn316_update_bw_bounding_box(struct dc *dc, struct clk_bw_params *bw_params); #endif /* __DCN31_FPU_H__*/ From 6e97c2f9689227b3fb6e2563127669f2146b5df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 14 Mar 2022 13:11:28 +0100 Subject: [PATCH 00378/11454] drm/amdgpu: move VM PDEs to idle after update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the page tables to the idle list after updating the PDEs. We have gone back and forth with that a couple of times because of problems with the inter PD dependencies, but it should work now that we have the state handling cleanly separated. Signed-off-by: Christian König Acked-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 42 ++++++-------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index fc4563cf2828..eb9b86466336 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1363,25 +1363,6 @@ static int amdgpu_vm_update_pde(struct amdgpu_vm_update_params *params, 1, 0, flags); } -/** - * amdgpu_vm_invalidate_pds - mark all PDs as invalid - * - * @adev: amdgpu_device pointer - * @vm: related vm - * - * Mark all PD level as invalid after an error. - */ -static void amdgpu_vm_invalidate_pds(struct amdgpu_device *adev, - struct amdgpu_vm *vm) -{ - struct amdgpu_vm_pt_cursor cursor; - struct amdgpu_vm_bo_base *entry; - - for_each_amdgpu_vm_pt_dfs_safe(adev, vm, NULL, cursor, entry) - if (entry->bo && !entry->moved) - amdgpu_vm_bo_relocated(entry); -} - /** * amdgpu_vm_update_pdes - make sure that all directories are valid * @@ -1398,6 +1379,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, struct amdgpu_vm *vm, bool immediate) { struct amdgpu_vm_update_params params; + struct amdgpu_vm_bo_base *entry; int r, idx; if (list_empty(&vm->relocated)) @@ -1413,16 +1395,9 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, r = vm->update_funcs->prepare(¶ms, NULL, AMDGPU_SYNC_EXPLICIT); if (r) - goto exit; - - while (!list_empty(&vm->relocated)) { - struct amdgpu_vm_bo_base *entry; - - entry = list_first_entry(&vm->relocated, - struct amdgpu_vm_bo_base, - vm_status); - amdgpu_vm_bo_idle(entry); + goto error; + list_for_each_entry(entry, &vm->relocated, vm_status) { r = amdgpu_vm_update_pde(¶ms, vm, entry); if (r) goto error; @@ -1431,12 +1406,15 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, r = vm->update_funcs->commit(¶ms, &vm->last_update); if (r) goto error; - drm_dev_exit(idx); - return 0; + + while (!list_empty(&vm->relocated)) { + entry = list_first_entry(&vm->relocated, + struct amdgpu_vm_bo_base, + vm_status); + amdgpu_vm_bo_idle(entry); + } error: - amdgpu_vm_invalidate_pds(adev, vm); -exit: drm_dev_exit(idx); return r; } From 184a69ca4d4125eee07f853cde45ee19dd21c437 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 15 Mar 2022 08:51:24 +0100 Subject: [PATCH 00379/11454] drm/amdgpu: separate VM PT handling into amdgpu_vm_pt.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Separate the VM page table backend operations from the state machine since the amdgpu_vm.c file is becoming to complex. The allocating, freeing and updating page tables and page directories can easily be moved into a separate file. While at it cleanup everything checkpatch.pl reported and rename the functions a bit to make more clear that they belong together. Signed-off-by: Christian König Acked-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/Makefile | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 953 +-------------------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 16 + drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 979 ++++++++++++++++++++++ 4 files changed, 1006 insertions(+), 944 deletions(-) create mode 100644 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 40e2c6e2df79..7d7af43a258f 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -49,7 +49,7 @@ amdgpu-y += amdgpu_device.o amdgpu_kms.o \ amdgpu_cs.o amdgpu_bios.o amdgpu_benchmark.o \ atombios_dp.o amdgpu_afmt.o amdgpu_trace_points.o \ atombios_encoders.o amdgpu_sa.o atombios_i2c.o \ - amdgpu_dma_buf.o amdgpu_vm.o amdgpu_ib.o amdgpu_pll.o \ + amdgpu_dma_buf.o amdgpu_vm.o amdgpu_vm_pt.o amdgpu_ib.o amdgpu_pll.o \ amdgpu_ucode.o amdgpu_bo_list.o amdgpu_ctx.o amdgpu_sync.o \ amdgpu_gtt_mgr.o amdgpu_preempt_mgr.o amdgpu_vram_mgr.o amdgpu_virt.o \ amdgpu_atomfirmware.o amdgpu_vf_error.o amdgpu_sched.o \ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index eb9b86466336..accebbac2f29 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -154,108 +154,6 @@ static inline void amdgpu_vm_eviction_unlock(struct amdgpu_vm *vm) mutex_unlock(&vm->eviction_lock); } -/** - * amdgpu_vm_level_shift - return the addr shift for each level - * - * @adev: amdgpu_device pointer - * @level: VMPT level - * - * Returns: - * The number of bits the pfn needs to be right shifted for a level. - */ -static unsigned amdgpu_vm_level_shift(struct amdgpu_device *adev, - unsigned level) -{ - switch (level) { - case AMDGPU_VM_PDB2: - case AMDGPU_VM_PDB1: - case AMDGPU_VM_PDB0: - return 9 * (AMDGPU_VM_PDB0 - level) + - adev->vm_manager.block_size; - case AMDGPU_VM_PTB: - return 0; - default: - return ~0; - } -} - -/** - * amdgpu_vm_num_entries - return the number of entries in a PD/PT - * - * @adev: amdgpu_device pointer - * @level: VMPT level - * - * Returns: - * The number of entries in a page directory or page table. - */ -static unsigned amdgpu_vm_num_entries(struct amdgpu_device *adev, - unsigned level) -{ - unsigned shift = amdgpu_vm_level_shift(adev, - adev->vm_manager.root_level); - - if (level == adev->vm_manager.root_level) - /* For the root directory */ - return round_up(adev->vm_manager.max_pfn, 1ULL << shift) - >> shift; - else if (level != AMDGPU_VM_PTB) - /* Everything in between */ - return 512; - else - /* For the page tables on the leaves */ - return AMDGPU_VM_PTE_COUNT(adev); -} - -/** - * amdgpu_vm_num_ats_entries - return the number of ATS entries in the root PD - * - * @adev: amdgpu_device pointer - * - * Returns: - * The number of entries in the root page directory which needs the ATS setting. - */ -static unsigned amdgpu_vm_num_ats_entries(struct amdgpu_device *adev) -{ - unsigned shift; - - shift = amdgpu_vm_level_shift(adev, adev->vm_manager.root_level); - return AMDGPU_GMC_HOLE_START >> (shift + AMDGPU_GPU_PAGE_SHIFT); -} - -/** - * amdgpu_vm_entries_mask - the mask to get the entry number of a PD/PT - * - * @adev: amdgpu_device pointer - * @level: VMPT level - * - * Returns: - * The mask to extract the entry number of a PD/PT from an address. - */ -static uint32_t amdgpu_vm_entries_mask(struct amdgpu_device *adev, - unsigned int level) -{ - if (level <= adev->vm_manager.root_level) - return 0xffffffff; - else if (level != AMDGPU_VM_PTB) - return 0x1ff; - else - return AMDGPU_VM_PTE_COUNT(adev) - 1; -} - -/** - * amdgpu_vm_bo_size - returns the size of the BOs in bytes - * - * @adev: amdgpu_device pointer - * @level: VMPT level - * - * Returns: - * The size of the BO for a page directory or page table in bytes. - */ -static unsigned amdgpu_vm_bo_size(struct amdgpu_device *adev, unsigned level) -{ - return AMDGPU_GPU_PAGE_ALIGN(amdgpu_vm_num_entries(adev, level) * 8); -} - /** * amdgpu_vm_bo_evicted - vm_bo is evicted * @@ -358,9 +256,8 @@ static void amdgpu_vm_bo_done(struct amdgpu_vm_bo_base *vm_bo) * Initialize a bo_va_base structure and add it to the appropriate lists * */ -static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, - struct amdgpu_vm *vm, - struct amdgpu_bo *bo) +void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, + struct amdgpu_vm *vm, struct amdgpu_bo *bo) { base->vm = vm; base->bo = bo; @@ -395,228 +292,6 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, amdgpu_vm_bo_evicted(base); } -/** - * amdgpu_vm_pt_parent - get the parent page directory - * - * @pt: child page table - * - * Helper to get the parent entry for the child page table. NULL if we are at - * the root page directory. - */ -static struct amdgpu_vm_bo_base *amdgpu_vm_pt_parent(struct amdgpu_vm_bo_base *pt) -{ - struct amdgpu_bo *parent = pt->bo->parent; - - if (!parent) - return NULL; - - return parent->vm_bo; -} - -/* - * amdgpu_vm_pt_cursor - state for for_each_amdgpu_vm_pt - */ -struct amdgpu_vm_pt_cursor { - uint64_t pfn; - struct amdgpu_vm_bo_base *parent; - struct amdgpu_vm_bo_base *entry; - unsigned level; -}; - -/** - * amdgpu_vm_pt_start - start PD/PT walk - * - * @adev: amdgpu_device pointer - * @vm: amdgpu_vm structure - * @start: start address of the walk - * @cursor: state to initialize - * - * Initialize a amdgpu_vm_pt_cursor to start a walk. - */ -static void amdgpu_vm_pt_start(struct amdgpu_device *adev, - struct amdgpu_vm *vm, uint64_t start, - struct amdgpu_vm_pt_cursor *cursor) -{ - cursor->pfn = start; - cursor->parent = NULL; - cursor->entry = &vm->root; - cursor->level = adev->vm_manager.root_level; -} - -/** - * amdgpu_vm_pt_descendant - go to child node - * - * @adev: amdgpu_device pointer - * @cursor: current state - * - * Walk to the child node of the current node. - * Returns: - * True if the walk was possible, false otherwise. - */ -static bool amdgpu_vm_pt_descendant(struct amdgpu_device *adev, - struct amdgpu_vm_pt_cursor *cursor) -{ - unsigned mask, shift, idx; - - if ((cursor->level == AMDGPU_VM_PTB) || !cursor->entry || - !cursor->entry->bo) - return false; - - mask = amdgpu_vm_entries_mask(adev, cursor->level); - shift = amdgpu_vm_level_shift(adev, cursor->level); - - ++cursor->level; - idx = (cursor->pfn >> shift) & mask; - cursor->parent = cursor->entry; - cursor->entry = &to_amdgpu_bo_vm(cursor->entry->bo)->entries[idx]; - return true; -} - -/** - * amdgpu_vm_pt_sibling - go to sibling node - * - * @adev: amdgpu_device pointer - * @cursor: current state - * - * Walk to the sibling node of the current node. - * Returns: - * True if the walk was possible, false otherwise. - */ -static bool amdgpu_vm_pt_sibling(struct amdgpu_device *adev, - struct amdgpu_vm_pt_cursor *cursor) -{ - unsigned shift, num_entries; - - /* Root doesn't have a sibling */ - if (!cursor->parent) - return false; - - /* Go to our parents and see if we got a sibling */ - shift = amdgpu_vm_level_shift(adev, cursor->level - 1); - num_entries = amdgpu_vm_num_entries(adev, cursor->level - 1); - - if (cursor->entry == &to_amdgpu_bo_vm(cursor->parent->bo)->entries[num_entries - 1]) - return false; - - cursor->pfn += 1ULL << shift; - cursor->pfn &= ~((1ULL << shift) - 1); - ++cursor->entry; - return true; -} - -/** - * amdgpu_vm_pt_ancestor - go to parent node - * - * @cursor: current state - * - * Walk to the parent node of the current node. - * Returns: - * True if the walk was possible, false otherwise. - */ -static bool amdgpu_vm_pt_ancestor(struct amdgpu_vm_pt_cursor *cursor) -{ - if (!cursor->parent) - return false; - - --cursor->level; - cursor->entry = cursor->parent; - cursor->parent = amdgpu_vm_pt_parent(cursor->parent); - return true; -} - -/** - * amdgpu_vm_pt_next - get next PD/PT in hieratchy - * - * @adev: amdgpu_device pointer - * @cursor: current state - * - * Walk the PD/PT tree to the next node. - */ -static void amdgpu_vm_pt_next(struct amdgpu_device *adev, - struct amdgpu_vm_pt_cursor *cursor) -{ - /* First try a newborn child */ - if (amdgpu_vm_pt_descendant(adev, cursor)) - return; - - /* If that didn't worked try to find a sibling */ - while (!amdgpu_vm_pt_sibling(adev, cursor)) { - /* No sibling, go to our parents and grandparents */ - if (!amdgpu_vm_pt_ancestor(cursor)) { - cursor->pfn = ~0ll; - return; - } - } -} - -/** - * amdgpu_vm_pt_first_dfs - start a deep first search - * - * @adev: amdgpu_device structure - * @vm: amdgpu_vm structure - * @start: optional cursor to start with - * @cursor: state to initialize - * - * Starts a deep first traversal of the PD/PT tree. - */ -static void amdgpu_vm_pt_first_dfs(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct amdgpu_vm_pt_cursor *start, - struct amdgpu_vm_pt_cursor *cursor) -{ - if (start) - *cursor = *start; - else - amdgpu_vm_pt_start(adev, vm, 0, cursor); - while (amdgpu_vm_pt_descendant(adev, cursor)); -} - -/** - * amdgpu_vm_pt_continue_dfs - check if the deep first search should continue - * - * @start: starting point for the search - * @entry: current entry - * - * Returns: - * True when the search should continue, false otherwise. - */ -static bool amdgpu_vm_pt_continue_dfs(struct amdgpu_vm_pt_cursor *start, - struct amdgpu_vm_bo_base *entry) -{ - return entry && (!start || entry != start->entry); -} - -/** - * amdgpu_vm_pt_next_dfs - get the next node for a deep first search - * - * @adev: amdgpu_device structure - * @cursor: current state - * - * Move the cursor to the next node in a deep first search. - */ -static void amdgpu_vm_pt_next_dfs(struct amdgpu_device *adev, - struct amdgpu_vm_pt_cursor *cursor) -{ - if (!cursor->entry) - return; - - if (!cursor->parent) - cursor->entry = NULL; - else if (amdgpu_vm_pt_sibling(adev, cursor)) - while (amdgpu_vm_pt_descendant(adev, cursor)); - else - amdgpu_vm_pt_ancestor(cursor); -} - -/* - * for_each_amdgpu_vm_pt_dfs_safe - safe deep first search of all PDs/PTs - */ -#define for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry) \ - for (amdgpu_vm_pt_first_dfs((adev), (vm), (start), &(cursor)), \ - (entry) = (cursor).entry, amdgpu_vm_pt_next_dfs((adev), &(cursor));\ - amdgpu_vm_pt_continue_dfs((start), (entry)); \ - (entry) = (cursor).entry, amdgpu_vm_pt_next_dfs((adev), &(cursor))) - /** * amdgpu_vm_get_pd_bo - add the VM PD to a validation list * @@ -783,312 +458,6 @@ bool amdgpu_vm_ready(struct amdgpu_vm *vm) return ret && list_empty(&vm->evicted); } -/** - * amdgpu_vm_clear_bo - initially clear the PDs/PTs - * - * @adev: amdgpu_device pointer - * @vm: VM to clear BO from - * @vmbo: BO to clear - * @immediate: use an immediate update - * - * Root PD needs to be reserved when calling this. - * - * Returns: - * 0 on success, errno otherwise. - */ -static int amdgpu_vm_clear_bo(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct amdgpu_bo_vm *vmbo, - bool immediate) -{ - struct ttm_operation_ctx ctx = { true, false }; - unsigned level = adev->vm_manager.root_level; - struct amdgpu_vm_update_params params; - struct amdgpu_bo *ancestor = &vmbo->bo; - struct amdgpu_bo *bo = &vmbo->bo; - unsigned entries, ats_entries; - uint64_t addr; - int r, idx; - - /* Figure out our place in the hierarchy */ - if (ancestor->parent) { - ++level; - while (ancestor->parent->parent) { - ++level; - ancestor = ancestor->parent; - } - } - - entries = amdgpu_bo_size(bo) / 8; - if (!vm->pte_support_ats) { - ats_entries = 0; - - } else if (!bo->parent) { - ats_entries = amdgpu_vm_num_ats_entries(adev); - ats_entries = min(ats_entries, entries); - entries -= ats_entries; - - } else { - struct amdgpu_vm_bo_base *pt; - - pt = ancestor->vm_bo; - ats_entries = amdgpu_vm_num_ats_entries(adev); - if ((pt - to_amdgpu_bo_vm(vm->root.bo)->entries) >= ats_entries) { - ats_entries = 0; - } else { - ats_entries = entries; - entries = 0; - } - } - - r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); - if (r) - return r; - - if (vmbo->shadow) { - struct amdgpu_bo *shadow = vmbo->shadow; - - r = ttm_bo_validate(&shadow->tbo, &shadow->placement, &ctx); - if (r) - return r; - } - - if (!drm_dev_enter(adev_to_drm(adev), &idx)) - return -ENODEV; - - r = vm->update_funcs->map_table(vmbo); - if (r) - goto exit; - - memset(¶ms, 0, sizeof(params)); - params.adev = adev; - params.vm = vm; - params.immediate = immediate; - - r = vm->update_funcs->prepare(¶ms, NULL, AMDGPU_SYNC_EXPLICIT); - if (r) - goto exit; - - addr = 0; - if (ats_entries) { - uint64_t value = 0, flags; - - flags = AMDGPU_PTE_DEFAULT_ATC; - if (level != AMDGPU_VM_PTB) { - /* Handle leaf PDEs as PTEs */ - flags |= AMDGPU_PDE_PTE; - amdgpu_gmc_get_vm_pde(adev, level, &value, &flags); - } - - r = vm->update_funcs->update(¶ms, vmbo, addr, 0, ats_entries, - value, flags); - if (r) - goto exit; - - addr += ats_entries * 8; - } - - if (entries) { - uint64_t value = 0, flags = 0; - - if (adev->asic_type >= CHIP_VEGA10) { - if (level != AMDGPU_VM_PTB) { - /* Handle leaf PDEs as PTEs */ - flags |= AMDGPU_PDE_PTE; - amdgpu_gmc_get_vm_pde(adev, level, - &value, &flags); - } else { - /* Workaround for fault priority problem on GMC9 */ - flags = AMDGPU_PTE_EXECUTABLE; - } - } - - r = vm->update_funcs->update(¶ms, vmbo, addr, 0, entries, - value, flags); - if (r) - goto exit; - } - - r = vm->update_funcs->commit(¶ms, NULL); -exit: - drm_dev_exit(idx); - return r; -} - -/** - * amdgpu_vm_pt_create - create bo for PD/PT - * - * @adev: amdgpu_device pointer - * @vm: requesting vm - * @level: the page table level - * @immediate: use a immediate update - * @vmbo: pointer to the buffer object pointer - */ -static int amdgpu_vm_pt_create(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - int level, bool immediate, - struct amdgpu_bo_vm **vmbo) -{ - struct amdgpu_bo_param bp; - struct amdgpu_bo *bo; - struct dma_resv *resv; - unsigned int num_entries; - int r; - - memset(&bp, 0, sizeof(bp)); - - bp.size = amdgpu_vm_bo_size(adev, level); - bp.byte_align = AMDGPU_GPU_PAGE_SIZE; - bp.domain = AMDGPU_GEM_DOMAIN_VRAM; - bp.domain = amdgpu_bo_get_preferred_domain(adev, bp.domain); - bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | - AMDGPU_GEM_CREATE_CPU_GTT_USWC; - - if (level < AMDGPU_VM_PTB) - num_entries = amdgpu_vm_num_entries(adev, level); - else - num_entries = 0; - - bp.bo_ptr_size = struct_size((*vmbo), entries, num_entries); - - if (vm->use_cpu_for_update) - bp.flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; - - bp.type = ttm_bo_type_kernel; - bp.no_wait_gpu = immediate; - if (vm->root.bo) - bp.resv = vm->root.bo->tbo.base.resv; - - r = amdgpu_bo_create_vm(adev, &bp, vmbo); - if (r) - return r; - - bo = &(*vmbo)->bo; - if (vm->is_compute_context || (adev->flags & AMD_IS_APU)) { - (*vmbo)->shadow = NULL; - return 0; - } - - if (!bp.resv) - WARN_ON(dma_resv_lock(bo->tbo.base.resv, - NULL)); - resv = bp.resv; - memset(&bp, 0, sizeof(bp)); - bp.size = amdgpu_vm_bo_size(adev, level); - bp.domain = AMDGPU_GEM_DOMAIN_GTT; - bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC; - bp.type = ttm_bo_type_kernel; - bp.resv = bo->tbo.base.resv; - bp.bo_ptr_size = sizeof(struct amdgpu_bo); - - r = amdgpu_bo_create(adev, &bp, &(*vmbo)->shadow); - - if (!resv) - dma_resv_unlock(bo->tbo.base.resv); - - if (r) { - amdgpu_bo_unref(&bo); - return r; - } - - (*vmbo)->shadow->parent = amdgpu_bo_ref(bo); - amdgpu_bo_add_to_shadow_list(*vmbo); - - return 0; -} - -/** - * amdgpu_vm_alloc_pts - Allocate a specific page table - * - * @adev: amdgpu_device pointer - * @vm: VM to allocate page tables for - * @cursor: Which page table to allocate - * @immediate: use an immediate update - * - * Make sure a specific page table or directory is allocated. - * - * Returns: - * 1 if page table needed to be allocated, 0 if page table was already - * allocated, negative errno if an error occurred. - */ -static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct amdgpu_vm_pt_cursor *cursor, - bool immediate) -{ - struct amdgpu_vm_bo_base *entry = cursor->entry; - struct amdgpu_bo *pt_bo; - struct amdgpu_bo_vm *pt; - int r; - - if (entry->bo) - return 0; - - r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt); - if (r) - return r; - - /* Keep a reference to the root directory to avoid - * freeing them up in the wrong order. - */ - pt_bo = &pt->bo; - pt_bo->parent = amdgpu_bo_ref(cursor->parent->bo); - amdgpu_vm_bo_base_init(entry, vm, pt_bo); - r = amdgpu_vm_clear_bo(adev, vm, pt, immediate); - if (r) - goto error_free_pt; - - return 0; - -error_free_pt: - amdgpu_bo_unref(&pt->shadow); - amdgpu_bo_unref(&pt_bo); - return r; -} - -/** - * amdgpu_vm_free_table - fre one PD/PT - * - * @entry: PDE to free - */ -static void amdgpu_vm_free_table(struct amdgpu_vm_bo_base *entry) -{ - struct amdgpu_bo *shadow; - - if (!entry->bo) - return; - shadow = amdgpu_bo_shadowed(entry->bo); - entry->bo->vm_bo = NULL; - list_del(&entry->vm_status); - amdgpu_bo_unref(&shadow); - amdgpu_bo_unref(&entry->bo); -} - -/** - * amdgpu_vm_free_pts - free PD/PT levels - * - * @adev: amdgpu device structure - * @vm: amdgpu vm structure - * @start: optional cursor where to start freeing PDs/PTs - * - * Free the page directory or page table level and all sub levels. - */ -static void amdgpu_vm_free_pts(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct amdgpu_vm_pt_cursor *start) -{ - struct amdgpu_vm_pt_cursor cursor; - struct amdgpu_vm_bo_base *entry; - - vm->bulk_moveable = false; - - for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry) - amdgpu_vm_free_table(entry); - - if (start) - amdgpu_vm_free_table(start->entry); -} - /** * amdgpu_vm_check_compute_bug - check whether asic has compute vm bug * @@ -1335,34 +704,6 @@ uint64_t amdgpu_vm_map_gart(const dma_addr_t *pages_addr, uint64_t addr) return result; } -/** - * amdgpu_vm_update_pde - update a single level in the hierarchy - * - * @params: parameters for the update - * @vm: requested vm - * @entry: entry to update - * - * Makes sure the requested entry in parent is up to date. - */ -static int amdgpu_vm_update_pde(struct amdgpu_vm_update_params *params, - struct amdgpu_vm *vm, - struct amdgpu_vm_bo_base *entry) -{ - struct amdgpu_vm_bo_base *parent = amdgpu_vm_pt_parent(entry); - struct amdgpu_bo *bo = parent->bo, *pbo; - uint64_t pde, pt, flags; - unsigned level; - - for (level = 0, pbo = bo->parent; pbo; ++level) - pbo = pbo->parent; - - level += params->adev->vm_manager.root_level; - amdgpu_gmc_get_pde_for_bo(entry->bo, level, &pt, &flags); - pde = (entry - to_amdgpu_bo_vm(parent->bo)->entries) * 8; - return vm->update_funcs->update(params, to_amdgpu_bo_vm(bo), pde, pt, - 1, 0, flags); -} - /** * amdgpu_vm_update_pdes - make sure that all directories are valid * @@ -1398,7 +739,7 @@ int amdgpu_vm_update_pdes(struct amdgpu_device *adev, goto error; list_for_each_entry(entry, &vm->relocated, vm_status) { - r = amdgpu_vm_update_pde(¶ms, vm, entry); + r = amdgpu_vm_pde_update(¶ms, entry); if (r) goto error; } @@ -1419,252 +760,6 @@ error: return r; } -/* - * amdgpu_vm_update_flags - figure out flags for PTE updates - * - * Make sure to set the right flags for the PTEs at the desired level. - */ -static void amdgpu_vm_update_flags(struct amdgpu_vm_update_params *params, - struct amdgpu_bo_vm *pt, unsigned int level, - uint64_t pe, uint64_t addr, - unsigned int count, uint32_t incr, - uint64_t flags) - -{ - if (level != AMDGPU_VM_PTB) { - flags |= AMDGPU_PDE_PTE; - amdgpu_gmc_get_vm_pde(params->adev, level, &addr, &flags); - - } else if (params->adev->asic_type >= CHIP_VEGA10 && - !(flags & AMDGPU_PTE_VALID) && - !(flags & AMDGPU_PTE_PRT)) { - - /* Workaround for fault priority problem on GMC9 */ - flags |= AMDGPU_PTE_EXECUTABLE; - } - - params->vm->update_funcs->update(params, pt, pe, addr, count, incr, - flags); -} - -/** - * amdgpu_vm_fragment - get fragment for PTEs - * - * @params: see amdgpu_vm_update_params definition - * @start: first PTE to handle - * @end: last PTE to handle - * @flags: hw mapping flags - * @frag: resulting fragment size - * @frag_end: end of this fragment - * - * Returns the first possible fragment for the start and end address. - */ -static void amdgpu_vm_fragment(struct amdgpu_vm_update_params *params, - uint64_t start, uint64_t end, uint64_t flags, - unsigned int *frag, uint64_t *frag_end) -{ - /** - * The MC L1 TLB supports variable sized pages, based on a fragment - * field in the PTE. When this field is set to a non-zero value, page - * granularity is increased from 4KB to (1 << (12 + frag)). The PTE - * flags are considered valid for all PTEs within the fragment range - * and corresponding mappings are assumed to be physically contiguous. - * - * The L1 TLB can store a single PTE for the whole fragment, - * significantly increasing the space available for translation - * caching. This leads to large improvements in throughput when the - * TLB is under pressure. - * - * The L2 TLB distributes small and large fragments into two - * asymmetric partitions. The large fragment cache is significantly - * larger. Thus, we try to use large fragments wherever possible. - * Userspace can support this by aligning virtual base address and - * allocation size to the fragment size. - * - * Starting with Vega10 the fragment size only controls the L1. The L2 - * is now directly feed with small/huge/giant pages from the walker. - */ - unsigned max_frag; - - if (params->adev->asic_type < CHIP_VEGA10) - max_frag = params->adev->vm_manager.fragment_size; - else - max_frag = 31; - - /* system pages are non continuously */ - if (params->pages_addr) { - *frag = 0; - *frag_end = end; - return; - } - - /* This intentionally wraps around if no bit is set */ - *frag = min((unsigned)ffs(start) - 1, (unsigned)fls64(end - start) - 1); - if (*frag >= max_frag) { - *frag = max_frag; - *frag_end = end & ~((1ULL << max_frag) - 1); - } else { - *frag_end = start + (1 << *frag); - } -} - -/** - * amdgpu_vm_update_ptes - make sure that page tables are valid - * - * @params: see amdgpu_vm_update_params definition - * @start: start of GPU address range - * @end: end of GPU address range - * @dst: destination address to map to, the next dst inside the function - * @flags: mapping flags - * - * Update the page tables in the range @start - @end. - * - * Returns: - * 0 for success, -EINVAL for failure. - */ -static int amdgpu_vm_update_ptes(struct amdgpu_vm_update_params *params, - uint64_t start, uint64_t end, - uint64_t dst, uint64_t flags) -{ - struct amdgpu_device *adev = params->adev; - struct amdgpu_vm_pt_cursor cursor; - uint64_t frag_start = start, frag_end; - unsigned int frag; - int r; - - /* figure out the initial fragment */ - amdgpu_vm_fragment(params, frag_start, end, flags, &frag, &frag_end); - - /* walk over the address space and update the PTs */ - amdgpu_vm_pt_start(adev, params->vm, start, &cursor); - while (cursor.pfn < end) { - unsigned shift, parent_shift, mask; - uint64_t incr, entry_end, pe_start; - struct amdgpu_bo *pt; - - if (!params->unlocked) { - /* make sure that the page tables covering the - * address range are actually allocated - */ - r = amdgpu_vm_alloc_pts(params->adev, params->vm, - &cursor, params->immediate); - if (r) - return r; - } - - shift = amdgpu_vm_level_shift(adev, cursor.level); - parent_shift = amdgpu_vm_level_shift(adev, cursor.level - 1); - if (params->unlocked) { - /* Unlocked updates are only allowed on the leaves */ - if (amdgpu_vm_pt_descendant(adev, &cursor)) - continue; - } else if (adev->asic_type < CHIP_VEGA10 && - (flags & AMDGPU_PTE_VALID)) { - /* No huge page support before GMC v9 */ - if (cursor.level != AMDGPU_VM_PTB) { - if (!amdgpu_vm_pt_descendant(adev, &cursor)) - return -ENOENT; - continue; - } - } else if (frag < shift) { - /* We can't use this level when the fragment size is - * smaller than the address shift. Go to the next - * child entry and try again. - */ - if (amdgpu_vm_pt_descendant(adev, &cursor)) - continue; - } else if (frag >= parent_shift) { - /* If the fragment size is even larger than the parent - * shift we should go up one level and check it again. - */ - if (!amdgpu_vm_pt_ancestor(&cursor)) - return -EINVAL; - continue; - } - - pt = cursor.entry->bo; - if (!pt) { - /* We need all PDs and PTs for mapping something, */ - if (flags & AMDGPU_PTE_VALID) - return -ENOENT; - - /* but unmapping something can happen at a higher - * level. - */ - if (!amdgpu_vm_pt_ancestor(&cursor)) - return -EINVAL; - - pt = cursor.entry->bo; - shift = parent_shift; - frag_end = max(frag_end, ALIGN(frag_start + 1, - 1ULL << shift)); - } - - /* Looks good so far, calculate parameters for the update */ - incr = (uint64_t)AMDGPU_GPU_PAGE_SIZE << shift; - mask = amdgpu_vm_entries_mask(adev, cursor.level); - pe_start = ((cursor.pfn >> shift) & mask) * 8; - entry_end = ((uint64_t)mask + 1) << shift; - entry_end += cursor.pfn & ~(entry_end - 1); - entry_end = min(entry_end, end); - - do { - struct amdgpu_vm *vm = params->vm; - uint64_t upd_end = min(entry_end, frag_end); - unsigned nptes = (upd_end - frag_start) >> shift; - uint64_t upd_flags = flags | AMDGPU_PTE_FRAG(frag); - - /* This can happen when we set higher level PDs to - * silent to stop fault floods. - */ - nptes = max(nptes, 1u); - - trace_amdgpu_vm_update_ptes(params, frag_start, upd_end, - min(nptes, 32u), dst, incr, upd_flags, - vm->task_info.pid, - vm->immediate.fence_context); - amdgpu_vm_update_flags(params, to_amdgpu_bo_vm(pt), - cursor.level, pe_start, dst, - nptes, incr, upd_flags); - - pe_start += nptes * 8; - dst += nptes * incr; - - frag_start = upd_end; - if (frag_start >= frag_end) { - /* figure out the next fragment */ - amdgpu_vm_fragment(params, frag_start, end, - flags, &frag, &frag_end); - if (frag < shift) - break; - } - } while (frag_start < entry_end); - - if (amdgpu_vm_pt_descendant(adev, &cursor)) { - /* Free all child entries. - * Update the tables with the flags and addresses and free up subsequent - * tables in the case of huge pages or freed up areas. - * This is the maximum you can free, because all other page tables are not - * completely covered by the range and so potentially still in use. - */ - while (cursor.pfn < frag_start) { - /* Make sure previous mapping is freed */ - if (cursor.entry->bo) { - params->table_freed = true; - amdgpu_vm_free_pts(adev, params->vm, &cursor); - } - amdgpu_vm_pt_next(adev, &cursor); - } - - } else if (frag >= shift) { - /* or just move on to the next on the same level. */ - amdgpu_vm_pt_next(adev, &cursor); - } - } - - return 0; -} - /** * amdgpu_vm_bo_update_mapping - update a mapping in the vm page table * @@ -1785,7 +880,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, } tmp = start + num_entries; - r = amdgpu_vm_update_ptes(¶ms, start, tmp, addr, flags); + r = amdgpu_vm_ptes_update(¶ms, start, tmp, addr, flags); if (r) goto error_unlock; @@ -2964,7 +2059,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm) amdgpu_vm_bo_base_init(&vm->root, vm, root_bo); - r = amdgpu_vm_clear_bo(adev, vm, root, false); + r = amdgpu_vm_pt_clear(adev, vm, root, false); if (r) goto error_unreserve; @@ -2992,34 +2087,6 @@ error_free_immediate: return r; } -/** - * amdgpu_vm_check_clean_reserved - check if a VM is clean - * - * @adev: amdgpu_device pointer - * @vm: the VM to check - * - * check all entries of the root PD, if any subsequent PDs are allocated, - * it means there are page table creating and filling, and is no a clean - * VM - * - * Returns: - * 0 if this VM is clean - */ -static int amdgpu_vm_check_clean_reserved(struct amdgpu_device *adev, - struct amdgpu_vm *vm) -{ - enum amdgpu_vm_level root = adev->vm_manager.root_level; - unsigned int entries = amdgpu_vm_num_entries(adev, root); - unsigned int i = 0; - - for (i = 0; i < entries; i++) { - if (to_amdgpu_bo_vm(vm->root.bo)->entries[i].bo) - return -EINVAL; - } - - return 0; -} - /** * amdgpu_vm_make_compute - Turn a GFX VM into a compute VM * @@ -3049,17 +2116,17 @@ int amdgpu_vm_make_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm) return r; /* Sanity checks */ - r = amdgpu_vm_check_clean_reserved(adev, vm); - if (r) + if (!amdgpu_vm_pt_is_root_clean(adev, vm)) { + r = -EINVAL; goto unreserve_bo; + } /* Check if PD needs to be reinitialized and do it before * changing any other state, in case it fails. */ if (pte_support_ats != vm->pte_support_ats) { vm->pte_support_ats = pte_support_ats; - r = amdgpu_vm_clear_bo(adev, vm, - to_amdgpu_bo_vm(vm->root.bo), + r = amdgpu_vm_pt_clear(adev, vm, to_amdgpu_bo_vm(vm->root.bo), false); if (r) goto unreserve_bo; @@ -3147,7 +2214,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) amdgpu_vm_free_mapping(adev, vm, mapping, NULL); } - amdgpu_vm_free_pts(adev, vm, NULL); + amdgpu_vm_pt_free_root(adev, vm); amdgpu_bo_unreserve(root); amdgpu_bo_unref(&root); WARN_ON(vm->root.bo); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index a40a6a993bb0..1731681914f5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -397,6 +397,8 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, struct dma_fence **fence); int amdgpu_vm_handle_moved(struct amdgpu_device *adev, struct amdgpu_vm *vm); +void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, + struct amdgpu_vm *vm, struct amdgpu_bo *bo); int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, struct amdgpu_device *bo_adev, struct amdgpu_vm *vm, bool immediate, @@ -458,6 +460,20 @@ void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo); void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem, uint64_t *gtt_mem, uint64_t *cpu_mem); +int amdgpu_vm_pt_clear(struct amdgpu_device *adev, struct amdgpu_vm *vm, + struct amdgpu_bo_vm *vmbo, bool immediate); +int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm, + int level, bool immediate, struct amdgpu_bo_vm **vmbo); +void amdgpu_vm_pt_free_root(struct amdgpu_device *adev, struct amdgpu_vm *vm); +bool amdgpu_vm_pt_is_root_clean(struct amdgpu_device *adev, + struct amdgpu_vm *vm); + +int amdgpu_vm_pde_update(struct amdgpu_vm_update_params *params, + struct amdgpu_vm_bo_base *entry); +int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params, + uint64_t start, uint64_t end, + uint64_t dst, uint64_t flags); + #if defined(CONFIG_DEBUG_FS) void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m); #endif diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c new file mode 100644 index 000000000000..a821ada5f8ca --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c @@ -0,0 +1,979 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/* + * Copyright 2022 Advanced Micro Devices, Inc. + * + * 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, sublicense, + * 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 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 NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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 "amdgpu.h" +#include "amdgpu_trace.h" +#include "amdgpu_vm.h" + +/* + * amdgpu_vm_pt_cursor - state for for_each_amdgpu_vm_pt + */ +struct amdgpu_vm_pt_cursor { + uint64_t pfn; + struct amdgpu_vm_bo_base *parent; + struct amdgpu_vm_bo_base *entry; + unsigned int level; +}; + +/** + * amdgpu_vm_pt_level_shift - return the addr shift for each level + * + * @adev: amdgpu_device pointer + * @level: VMPT level + * + * Returns: + * The number of bits the pfn needs to be right shifted for a level. + */ +static unsigned int amdgpu_vm_pt_level_shift(struct amdgpu_device *adev, + unsigned int level) +{ + switch (level) { + case AMDGPU_VM_PDB2: + case AMDGPU_VM_PDB1: + case AMDGPU_VM_PDB0: + return 9 * (AMDGPU_VM_PDB0 - level) + + adev->vm_manager.block_size; + case AMDGPU_VM_PTB: + return 0; + default: + return ~0; + } +} + +/** + * amdgpu_vm_pt_num_entries - return the number of entries in a PD/PT + * + * @adev: amdgpu_device pointer + * @level: VMPT level + * + * Returns: + * The number of entries in a page directory or page table. + */ +static unsigned int amdgpu_vm_pt_num_entries(struct amdgpu_device *adev, + unsigned int level) +{ + unsigned int shift; + + shift = amdgpu_vm_pt_level_shift(adev, adev->vm_manager.root_level); + if (level == adev->vm_manager.root_level) + /* For the root directory */ + return round_up(adev->vm_manager.max_pfn, 1ULL << shift) + >> shift; + else if (level != AMDGPU_VM_PTB) + /* Everything in between */ + return 512; + + /* For the page tables on the leaves */ + return AMDGPU_VM_PTE_COUNT(adev); +} + +/** + * amdgpu_vm_pt_num_ats_entries - return the number of ATS entries in the root PD + * + * @adev: amdgpu_device pointer + * + * Returns: + * The number of entries in the root page directory which needs the ATS setting. + */ +static unsigned int amdgpu_vm_pt_num_ats_entries(struct amdgpu_device *adev) +{ + unsigned int shift; + + shift = amdgpu_vm_pt_level_shift(adev, adev->vm_manager.root_level); + return AMDGPU_GMC_HOLE_START >> (shift + AMDGPU_GPU_PAGE_SHIFT); +} + +/** + * amdgpu_vm_pt_entries_mask - the mask to get the entry number of a PD/PT + * + * @adev: amdgpu_device pointer + * @level: VMPT level + * + * Returns: + * The mask to extract the entry number of a PD/PT from an address. + */ +static uint32_t amdgpu_vm_pt_entries_mask(struct amdgpu_device *adev, + unsigned int level) +{ + if (level <= adev->vm_manager.root_level) + return 0xffffffff; + else if (level != AMDGPU_VM_PTB) + return 0x1ff; + else + return AMDGPU_VM_PTE_COUNT(adev) - 1; +} + +/** + * amdgpu_vm_pt_size - returns the size of the page table in bytes + * + * @adev: amdgpu_device pointer + * @level: VMPT level + * + * Returns: + * The size of the BO for a page directory or page table in bytes. + */ +static unsigned int amdgpu_vm_pt_size(struct amdgpu_device *adev, + unsigned int level) +{ + return AMDGPU_GPU_PAGE_ALIGN(amdgpu_vm_pt_num_entries(adev, level) * 8); +} + +/** + * amdgpu_vm_pt_parent - get the parent page directory + * + * @pt: child page table + * + * Helper to get the parent entry for the child page table. NULL if we are at + * the root page directory. + */ +static struct amdgpu_vm_bo_base * +amdgpu_vm_pt_parent(struct amdgpu_vm_bo_base *pt) +{ + struct amdgpu_bo *parent = pt->bo->parent; + + if (!parent) + return NULL; + + return parent->vm_bo; +} + +/** + * amdgpu_vm_pt_start - start PD/PT walk + * + * @adev: amdgpu_device pointer + * @vm: amdgpu_vm structure + * @start: start address of the walk + * @cursor: state to initialize + * + * Initialize a amdgpu_vm_pt_cursor to start a walk. + */ +static void amdgpu_vm_pt_start(struct amdgpu_device *adev, + struct amdgpu_vm *vm, uint64_t start, + struct amdgpu_vm_pt_cursor *cursor) +{ + cursor->pfn = start; + cursor->parent = NULL; + cursor->entry = &vm->root; + cursor->level = adev->vm_manager.root_level; +} + +/** + * amdgpu_vm_pt_descendant - go to child node + * + * @adev: amdgpu_device pointer + * @cursor: current state + * + * Walk to the child node of the current node. + * Returns: + * True if the walk was possible, false otherwise. + */ +static bool amdgpu_vm_pt_descendant(struct amdgpu_device *adev, + struct amdgpu_vm_pt_cursor *cursor) +{ + unsigned int mask, shift, idx; + + if ((cursor->level == AMDGPU_VM_PTB) || !cursor->entry || + !cursor->entry->bo) + return false; + + mask = amdgpu_vm_pt_entries_mask(adev, cursor->level); + shift = amdgpu_vm_pt_level_shift(adev, cursor->level); + + ++cursor->level; + idx = (cursor->pfn >> shift) & mask; + cursor->parent = cursor->entry; + cursor->entry = &to_amdgpu_bo_vm(cursor->entry->bo)->entries[idx]; + return true; +} + +/** + * amdgpu_vm_pt_sibling - go to sibling node + * + * @adev: amdgpu_device pointer + * @cursor: current state + * + * Walk to the sibling node of the current node. + * Returns: + * True if the walk was possible, false otherwise. + */ +static bool amdgpu_vm_pt_sibling(struct amdgpu_device *adev, + struct amdgpu_vm_pt_cursor *cursor) +{ + + unsigned int shift, num_entries; + struct amdgpu_bo_vm *parent; + + /* Root doesn't have a sibling */ + if (!cursor->parent) + return false; + + /* Go to our parents and see if we got a sibling */ + shift = amdgpu_vm_pt_level_shift(adev, cursor->level - 1); + num_entries = amdgpu_vm_pt_num_entries(adev, cursor->level - 1); + parent = to_amdgpu_bo_vm(cursor->parent->bo); + + if (cursor->entry == &parent->entries[num_entries - 1]) + return false; + + cursor->pfn += 1ULL << shift; + cursor->pfn &= ~((1ULL << shift) - 1); + ++cursor->entry; + return true; +} + +/** + * amdgpu_vm_pt_ancestor - go to parent node + * + * @cursor: current state + * + * Walk to the parent node of the current node. + * Returns: + * True if the walk was possible, false otherwise. + */ +static bool amdgpu_vm_pt_ancestor(struct amdgpu_vm_pt_cursor *cursor) +{ + if (!cursor->parent) + return false; + + --cursor->level; + cursor->entry = cursor->parent; + cursor->parent = amdgpu_vm_pt_parent(cursor->parent); + return true; +} + +/** + * amdgpu_vm_pt_next - get next PD/PT in hieratchy + * + * @adev: amdgpu_device pointer + * @cursor: current state + * + * Walk the PD/PT tree to the next node. + */ +static void amdgpu_vm_pt_next(struct amdgpu_device *adev, + struct amdgpu_vm_pt_cursor *cursor) +{ + /* First try a newborn child */ + if (amdgpu_vm_pt_descendant(adev, cursor)) + return; + + /* If that didn't worked try to find a sibling */ + while (!amdgpu_vm_pt_sibling(adev, cursor)) { + /* No sibling, go to our parents and grandparents */ + if (!amdgpu_vm_pt_ancestor(cursor)) { + cursor->pfn = ~0ll; + return; + } + } +} + +/** + * amdgpu_vm_pt_first_dfs - start a deep first search + * + * @adev: amdgpu_device structure + * @vm: amdgpu_vm structure + * @start: optional cursor to start with + * @cursor: state to initialize + * + * Starts a deep first traversal of the PD/PT tree. + */ +static void amdgpu_vm_pt_first_dfs(struct amdgpu_device *adev, + struct amdgpu_vm *vm, + struct amdgpu_vm_pt_cursor *start, + struct amdgpu_vm_pt_cursor *cursor) +{ + if (start) + *cursor = *start; + else + amdgpu_vm_pt_start(adev, vm, 0, cursor); + + while (amdgpu_vm_pt_descendant(adev, cursor)) + ; +} + +/** + * amdgpu_vm_pt_continue_dfs - check if the deep first search should continue + * + * @start: starting point for the search + * @entry: current entry + * + * Returns: + * True when the search should continue, false otherwise. + */ +static bool amdgpu_vm_pt_continue_dfs(struct amdgpu_vm_pt_cursor *start, + struct amdgpu_vm_bo_base *entry) +{ + return entry && (!start || entry != start->entry); +} + +/** + * amdgpu_vm_pt_next_dfs - get the next node for a deep first search + * + * @adev: amdgpu_device structure + * @cursor: current state + * + * Move the cursor to the next node in a deep first search. + */ +static void amdgpu_vm_pt_next_dfs(struct amdgpu_device *adev, + struct amdgpu_vm_pt_cursor *cursor) +{ + if (!cursor->entry) + return; + + if (!cursor->parent) + cursor->entry = NULL; + else if (amdgpu_vm_pt_sibling(adev, cursor)) + while (amdgpu_vm_pt_descendant(adev, cursor)) + ; + else + amdgpu_vm_pt_ancestor(cursor); +} + +/* + * for_each_amdgpu_vm_pt_dfs_safe - safe deep first search of all PDs/PTs + */ +#define for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry) \ + for (amdgpu_vm_pt_first_dfs((adev), (vm), (start), &(cursor)), \ + (entry) = (cursor).entry, amdgpu_vm_pt_next_dfs((adev), &(cursor));\ + amdgpu_vm_pt_continue_dfs((start), (entry)); \ + (entry) = (cursor).entry, amdgpu_vm_pt_next_dfs((adev), &(cursor))) + +/** + * amdgpu_vm_pt_clear - initially clear the PDs/PTs + * + * @adev: amdgpu_device pointer + * @vm: VM to clear BO from + * @vmbo: BO to clear + * @immediate: use an immediate update + * + * Root PD needs to be reserved when calling this. + * + * Returns: + * 0 on success, errno otherwise. + */ +int amdgpu_vm_pt_clear(struct amdgpu_device *adev, struct amdgpu_vm *vm, + struct amdgpu_bo_vm *vmbo, bool immediate) +{ + unsigned int level = adev->vm_manager.root_level; + struct ttm_operation_ctx ctx = { true, false }; + struct amdgpu_vm_update_params params; + struct amdgpu_bo *ancestor = &vmbo->bo; + unsigned int entries, ats_entries; + struct amdgpu_bo *bo = &vmbo->bo; + uint64_t addr; + int r, idx; + + /* Figure out our place in the hierarchy */ + if (ancestor->parent) { + ++level; + while (ancestor->parent->parent) { + ++level; + ancestor = ancestor->parent; + } + } + + entries = amdgpu_bo_size(bo) / 8; + if (!vm->pte_support_ats) { + ats_entries = 0; + + } else if (!bo->parent) { + ats_entries = amdgpu_vm_pt_num_ats_entries(adev); + ats_entries = min(ats_entries, entries); + entries -= ats_entries; + + } else { + struct amdgpu_vm_bo_base *pt; + + pt = ancestor->vm_bo; + ats_entries = amdgpu_vm_pt_num_ats_entries(adev); + if ((pt - to_amdgpu_bo_vm(vm->root.bo)->entries) >= + ats_entries) { + ats_entries = 0; + } else { + ats_entries = entries; + entries = 0; + } + } + + r = ttm_bo_validate(&bo->tbo, &bo->placement, &ctx); + if (r) + return r; + + if (vmbo->shadow) { + struct amdgpu_bo *shadow = vmbo->shadow; + + r = ttm_bo_validate(&shadow->tbo, &shadow->placement, &ctx); + if (r) + return r; + } + + if (!drm_dev_enter(adev_to_drm(adev), &idx)) + return -ENODEV; + + r = vm->update_funcs->map_table(vmbo); + if (r) + goto exit; + + memset(¶ms, 0, sizeof(params)); + params.adev = adev; + params.vm = vm; + params.immediate = immediate; + + r = vm->update_funcs->prepare(¶ms, NULL, AMDGPU_SYNC_EXPLICIT); + if (r) + goto exit; + + addr = 0; + if (ats_entries) { + uint64_t value = 0, flags; + + flags = AMDGPU_PTE_DEFAULT_ATC; + if (level != AMDGPU_VM_PTB) { + /* Handle leaf PDEs as PTEs */ + flags |= AMDGPU_PDE_PTE; + amdgpu_gmc_get_vm_pde(adev, level, &value, &flags); + } + + r = vm->update_funcs->update(¶ms, vmbo, addr, 0, + ats_entries, value, flags); + if (r) + goto exit; + + addr += ats_entries * 8; + } + + if (entries) { + uint64_t value = 0, flags = 0; + + if (adev->asic_type >= CHIP_VEGA10) { + if (level != AMDGPU_VM_PTB) { + /* Handle leaf PDEs as PTEs */ + flags |= AMDGPU_PDE_PTE; + amdgpu_gmc_get_vm_pde(adev, level, + &value, &flags); + } else { + /* Workaround for fault priority problem on GMC9 */ + flags = AMDGPU_PTE_EXECUTABLE; + } + } + + r = vm->update_funcs->update(¶ms, vmbo, addr, 0, entries, + value, flags); + if (r) + goto exit; + } + + r = vm->update_funcs->commit(¶ms, NULL); +exit: + drm_dev_exit(idx); + return r; +} + +/** + * amdgpu_vm_pt_create - create bo for PD/PT + * + * @adev: amdgpu_device pointer + * @vm: requesting vm + * @level: the page table level + * @immediate: use a immediate update + * @vmbo: pointer to the buffer object pointer + */ +int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct amdgpu_vm *vm, + int level, bool immediate, struct amdgpu_bo_vm **vmbo) +{ + struct amdgpu_bo_param bp; + struct amdgpu_bo *bo; + struct dma_resv *resv; + unsigned int num_entries; + int r; + + memset(&bp, 0, sizeof(bp)); + + bp.size = amdgpu_vm_pt_size(adev, level); + bp.byte_align = AMDGPU_GPU_PAGE_SIZE; + bp.domain = AMDGPU_GEM_DOMAIN_VRAM; + bp.domain = amdgpu_bo_get_preferred_domain(adev, bp.domain); + bp.flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS | + AMDGPU_GEM_CREATE_CPU_GTT_USWC; + + if (level < AMDGPU_VM_PTB) + num_entries = amdgpu_vm_pt_num_entries(adev, level); + else + num_entries = 0; + + bp.bo_ptr_size = struct_size((*vmbo), entries, num_entries); + + if (vm->use_cpu_for_update) + bp.flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED; + + bp.type = ttm_bo_type_kernel; + bp.no_wait_gpu = immediate; + if (vm->root.bo) + bp.resv = vm->root.bo->tbo.base.resv; + + r = amdgpu_bo_create_vm(adev, &bp, vmbo); + if (r) + return r; + + bo = &(*vmbo)->bo; + if (vm->is_compute_context || (adev->flags & AMD_IS_APU)) { + (*vmbo)->shadow = NULL; + return 0; + } + + if (!bp.resv) + WARN_ON(dma_resv_lock(bo->tbo.base.resv, + NULL)); + resv = bp.resv; + memset(&bp, 0, sizeof(bp)); + bp.size = amdgpu_vm_pt_size(adev, level); + bp.domain = AMDGPU_GEM_DOMAIN_GTT; + bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC; + bp.type = ttm_bo_type_kernel; + bp.resv = bo->tbo.base.resv; + bp.bo_ptr_size = sizeof(struct amdgpu_bo); + + r = amdgpu_bo_create(adev, &bp, &(*vmbo)->shadow); + + if (!resv) + dma_resv_unlock(bo->tbo.base.resv); + + if (r) { + amdgpu_bo_unref(&bo); + return r; + } + + (*vmbo)->shadow->parent = amdgpu_bo_ref(bo); + amdgpu_bo_add_to_shadow_list(*vmbo); + + return 0; +} + +/** + * amdgpu_vm_pt_alloc - Allocate a specific page table + * + * @adev: amdgpu_device pointer + * @vm: VM to allocate page tables for + * @cursor: Which page table to allocate + * @immediate: use an immediate update + * + * Make sure a specific page table or directory is allocated. + * + * Returns: + * 1 if page table needed to be allocated, 0 if page table was already + * allocated, negative errno if an error occurred. + */ +static int amdgpu_vm_pt_alloc(struct amdgpu_device *adev, + struct amdgpu_vm *vm, + struct amdgpu_vm_pt_cursor *cursor, + bool immediate) +{ + struct amdgpu_vm_bo_base *entry = cursor->entry; + struct amdgpu_bo *pt_bo; + struct amdgpu_bo_vm *pt; + int r; + + if (entry->bo) + return 0; + + r = amdgpu_vm_pt_create(adev, vm, cursor->level, immediate, &pt); + if (r) + return r; + + /* Keep a reference to the root directory to avoid + * freeing them up in the wrong order. + */ + pt_bo = &pt->bo; + pt_bo->parent = amdgpu_bo_ref(cursor->parent->bo); + amdgpu_vm_bo_base_init(entry, vm, pt_bo); + r = amdgpu_vm_pt_clear(adev, vm, pt, immediate); + if (r) + goto error_free_pt; + + return 0; + +error_free_pt: + amdgpu_bo_unref(&pt->shadow); + amdgpu_bo_unref(&pt_bo); + return r; +} + +/** + * amdgpu_vm_free_table - fre one PD/PT + * + * @entry: PDE to free + */ +static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry) +{ + struct amdgpu_bo *shadow; + + if (!entry->bo) + return; + shadow = amdgpu_bo_shadowed(entry->bo); + entry->bo->vm_bo = NULL; + list_del(&entry->vm_status); + amdgpu_bo_unref(&shadow); + amdgpu_bo_unref(&entry->bo); +} + +/** + * amdgpu_vm_pt_free_dfs - free PD/PT levels + * + * @adev: amdgpu device structure + * @vm: amdgpu vm structure + * @start: optional cursor where to start freeing PDs/PTs + * + * Free the page directory or page table level and all sub levels. + */ +static void amdgpu_vm_pt_free_dfs(struct amdgpu_device *adev, + struct amdgpu_vm *vm, + struct amdgpu_vm_pt_cursor *start) +{ + struct amdgpu_vm_pt_cursor cursor; + struct amdgpu_vm_bo_base *entry; + + vm->bulk_moveable = false; + + for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry) + amdgpu_vm_pt_free(entry); + + if (start) + amdgpu_vm_pt_free(start->entry); +} + +/** + * amdgpu_vm_pt_free_root - free root PD + * @adev: amdgpu device structure + * @vm: amdgpu vm structure + * + * Free the root page directory and everything below it. + */ +void amdgpu_vm_pt_free_root(struct amdgpu_device *adev, struct amdgpu_vm *vm) +{ + amdgpu_vm_pt_free_dfs(adev, vm, NULL); +} + +/** + * amdgpu_vm_pt_is_root_clean - check if a root PD is clean + * + * @adev: amdgpu_device pointer + * @vm: the VM to check + * + * Check all entries of the root PD, if any subsequent PDs are allocated, + * it means there are page table creating and filling, and is no a clean + * VM + * + * Returns: + * 0 if this VM is clean + */ +bool amdgpu_vm_pt_is_root_clean(struct amdgpu_device *adev, + struct amdgpu_vm *vm) +{ + enum amdgpu_vm_level root = adev->vm_manager.root_level; + unsigned int entries = amdgpu_vm_pt_num_entries(adev, root); + unsigned int i = 0; + + for (i = 0; i < entries; i++) { + if (to_amdgpu_bo_vm(vm->root.bo)->entries[i].bo) + return false; + } + return true; +} + +/** + * amdgpu_vm_pde_update - update a single level in the hierarchy + * + * @params: parameters for the update + * @entry: entry to update + * + * Makes sure the requested entry in parent is up to date. + */ +int amdgpu_vm_pde_update(struct amdgpu_vm_update_params *params, + struct amdgpu_vm_bo_base *entry) +{ + struct amdgpu_vm_bo_base *parent = amdgpu_vm_pt_parent(entry); + struct amdgpu_bo *bo = parent->bo, *pbo; + struct amdgpu_vm *vm = params->vm; + uint64_t pde, pt, flags; + unsigned int level; + + for (level = 0, pbo = bo->parent; pbo; ++level) + pbo = pbo->parent; + + level += params->adev->vm_manager.root_level; + amdgpu_gmc_get_pde_for_bo(entry->bo, level, &pt, &flags); + pde = (entry - to_amdgpu_bo_vm(parent->bo)->entries) * 8; + return vm->update_funcs->update(params, to_amdgpu_bo_vm(bo), pde, pt, + 1, 0, flags); +} + +/* + * amdgpu_vm_pte_update_flags - figure out flags for PTE updates + * + * Make sure to set the right flags for the PTEs at the desired level. + */ +static void amdgpu_vm_pte_update_flags(struct amdgpu_vm_update_params *params, + struct amdgpu_bo_vm *pt, + unsigned int level, + uint64_t pe, uint64_t addr, + unsigned int count, uint32_t incr, + uint64_t flags) + +{ + if (level != AMDGPU_VM_PTB) { + flags |= AMDGPU_PDE_PTE; + amdgpu_gmc_get_vm_pde(params->adev, level, &addr, &flags); + + } else if (params->adev->asic_type >= CHIP_VEGA10 && + !(flags & AMDGPU_PTE_VALID) && + !(flags & AMDGPU_PTE_PRT)) { + + /* Workaround for fault priority problem on GMC9 */ + flags |= AMDGPU_PTE_EXECUTABLE; + } + + params->vm->update_funcs->update(params, pt, pe, addr, count, incr, + flags); +} + +/** + * amdgpu_vm_pte_fragment - get fragment for PTEs + * + * @params: see amdgpu_vm_update_params definition + * @start: first PTE to handle + * @end: last PTE to handle + * @flags: hw mapping flags + * @frag: resulting fragment size + * @frag_end: end of this fragment + * + * Returns the first possible fragment for the start and end address. + */ +static void amdgpu_vm_pte_fragment(struct amdgpu_vm_update_params *params, + uint64_t start, uint64_t end, uint64_t flags, + unsigned int *frag, uint64_t *frag_end) +{ + /** + * The MC L1 TLB supports variable sized pages, based on a fragment + * field in the PTE. When this field is set to a non-zero value, page + * granularity is increased from 4KB to (1 << (12 + frag)). The PTE + * flags are considered valid for all PTEs within the fragment range + * and corresponding mappings are assumed to be physically contiguous. + * + * The L1 TLB can store a single PTE for the whole fragment, + * significantly increasing the space available for translation + * caching. This leads to large improvements in throughput when the + * TLB is under pressure. + * + * The L2 TLB distributes small and large fragments into two + * asymmetric partitions. The large fragment cache is significantly + * larger. Thus, we try to use large fragments wherever possible. + * Userspace can support this by aligning virtual base address and + * allocation size to the fragment size. + * + * Starting with Vega10 the fragment size only controls the L1. The L2 + * is now directly feed with small/huge/giant pages from the walker. + */ + unsigned int max_frag; + + if (params->adev->asic_type < CHIP_VEGA10) + max_frag = params->adev->vm_manager.fragment_size; + else + max_frag = 31; + + /* system pages are non continuously */ + if (params->pages_addr) { + *frag = 0; + *frag_end = end; + return; + } + + /* This intentionally wraps around if no bit is set */ + *frag = min_t(unsigned int, ffs(start) - 1, fls64(end - start) - 1); + if (*frag >= max_frag) { + *frag = max_frag; + *frag_end = end & ~((1ULL << max_frag) - 1); + } else { + *frag_end = start + (1 << *frag); + } +} + +/** + * amdgpu_vm_ptes_update - make sure that page tables are valid + * + * @params: see amdgpu_vm_update_params definition + * @start: start of GPU address range + * @end: end of GPU address range + * @dst: destination address to map to, the next dst inside the function + * @flags: mapping flags + * + * Update the page tables in the range @start - @end. + * + * Returns: + * 0 for success, -EINVAL for failure. + */ +int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params, + uint64_t start, uint64_t end, + uint64_t dst, uint64_t flags) +{ + struct amdgpu_device *adev = params->adev; + struct amdgpu_vm_pt_cursor cursor; + uint64_t frag_start = start, frag_end; + unsigned int frag; + int r; + + /* figure out the initial fragment */ + amdgpu_vm_pte_fragment(params, frag_start, end, flags, &frag, + &frag_end); + + /* walk over the address space and update the PTs */ + amdgpu_vm_pt_start(adev, params->vm, start, &cursor); + while (cursor.pfn < end) { + unsigned int shift, parent_shift, mask; + uint64_t incr, entry_end, pe_start; + struct amdgpu_bo *pt; + + if (!params->unlocked) { + /* make sure that the page tables covering the + * address range are actually allocated + */ + r = amdgpu_vm_pt_alloc(params->adev, params->vm, + &cursor, params->immediate); + if (r) + return r; + } + + shift = amdgpu_vm_pt_level_shift(adev, cursor.level); + parent_shift = amdgpu_vm_pt_level_shift(adev, cursor.level - 1); + if (params->unlocked) { + /* Unlocked updates are only allowed on the leaves */ + if (amdgpu_vm_pt_descendant(adev, &cursor)) + continue; + } else if (adev->asic_type < CHIP_VEGA10 && + (flags & AMDGPU_PTE_VALID)) { + /* No huge page support before GMC v9 */ + if (cursor.level != AMDGPU_VM_PTB) { + if (!amdgpu_vm_pt_descendant(adev, &cursor)) + return -ENOENT; + continue; + } + } else if (frag < shift) { + /* We can't use this level when the fragment size is + * smaller than the address shift. Go to the next + * child entry and try again. + */ + if (amdgpu_vm_pt_descendant(adev, &cursor)) + continue; + } else if (frag >= parent_shift) { + /* If the fragment size is even larger than the parent + * shift we should go up one level and check it again. + */ + if (!amdgpu_vm_pt_ancestor(&cursor)) + return -EINVAL; + continue; + } + + pt = cursor.entry->bo; + if (!pt) { + /* We need all PDs and PTs for mapping something, */ + if (flags & AMDGPU_PTE_VALID) + return -ENOENT; + + /* but unmapping something can happen at a higher + * level. + */ + if (!amdgpu_vm_pt_ancestor(&cursor)) + return -EINVAL; + + pt = cursor.entry->bo; + shift = parent_shift; + frag_end = max(frag_end, ALIGN(frag_start + 1, + 1ULL << shift)); + } + + /* Looks good so far, calculate parameters for the update */ + incr = (uint64_t)AMDGPU_GPU_PAGE_SIZE << shift; + mask = amdgpu_vm_pt_entries_mask(adev, cursor.level); + pe_start = ((cursor.pfn >> shift) & mask) * 8; + entry_end = ((uint64_t)mask + 1) << shift; + entry_end += cursor.pfn & ~(entry_end - 1); + entry_end = min(entry_end, end); + + do { + struct amdgpu_vm *vm = params->vm; + uint64_t upd_end = min(entry_end, frag_end); + unsigned int nptes = (upd_end - frag_start) >> shift; + uint64_t upd_flags = flags | AMDGPU_PTE_FRAG(frag); + + /* This can happen when we set higher level PDs to + * silent to stop fault floods. + */ + nptes = max(nptes, 1u); + + trace_amdgpu_vm_update_ptes(params, frag_start, upd_end, + min(nptes, 32u), dst, incr, + upd_flags, + vm->task_info.pid, + vm->immediate.fence_context); + amdgpu_vm_pte_update_flags(params, to_amdgpu_bo_vm(pt), + cursor.level, pe_start, dst, + nptes, incr, upd_flags); + + pe_start += nptes * 8; + dst += nptes * incr; + + frag_start = upd_end; + if (frag_start >= frag_end) { + /* figure out the next fragment */ + amdgpu_vm_pte_fragment(params, frag_start, end, + flags, &frag, &frag_end); + if (frag < shift) + break; + } + } while (frag_start < entry_end); + + if (amdgpu_vm_pt_descendant(adev, &cursor)) { + /* Free all child entries. + * Update the tables with the flags and addresses and free up subsequent + * tables in the case of huge pages or freed up areas. + * This is the maximum you can free, because all other page tables are not + * completely covered by the range and so potentially still in use. + */ + while (cursor.pfn < frag_start) { + /* Make sure previous mapping is freed */ + if (cursor.entry->bo) { + params->table_freed = true; + amdgpu_vm_pt_free_dfs(adev, params->vm, + &cursor); + } + amdgpu_vm_pt_next(adev, &cursor); + } + + } else if (frag >= shift) { + /* or just move on to the next on the same level. */ + amdgpu_vm_pt_next(adev, &cursor); + } + } + + return 0; +} From e997b82745a5b2419bc5b72735811d7162ac994a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 8 Mar 2022 15:06:49 +0100 Subject: [PATCH 00380/11454] drm/amdgpu: simplify VM update tracking a bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store the 64bit sequence directly. Makes it simpler to use and saves a bit of fence reference counting overhead. Signed-off-by: Christian König Acked-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 40 +++++++----------------- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 9 ++---- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h | 2 +- 4 files changed, 16 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c index 92a70fb57fa3..4f1399573107 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c @@ -276,19 +276,15 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm, struct amdgpu_device *adev = ring->adev; unsigned vmhub = ring->funcs->vmhub; uint64_t fence_context = adev->fence_context + ring->idx; - struct dma_fence *updates = sync->last_vm_update; bool needs_flush = vm->use_cpu_for_update; - int r = 0; + uint64_t updates = sync->last_vm_update; + int r; *id = vm->reserved_vmid[vmhub]; - if (updates && (*id)->flushed_updates && - updates->context == (*id)->flushed_updates->context && - !dma_fence_is_later(updates, (*id)->flushed_updates)) - updates = NULL; - if ((*id)->owner != vm->immediate.fence_context || - job->vm_pd_addr != (*id)->pd_gpu_addr || - updates || !(*id)->last_flush || + (*id)->pd_gpu_addr != job->vm_pd_addr || + (*id)->flushed_updates < updates || + !(*id)->last_flush || ((*id)->last_flush->context != fence_context && !dma_fence_is_signaled((*id)->last_flush))) { struct dma_fence *tmp; @@ -302,8 +298,7 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm, tmp = amdgpu_sync_peek_fence(&(*id)->active, ring); if (tmp) { *id = NULL; - r = amdgpu_sync_fence(sync, tmp); - return r; + return amdgpu_sync_fence(sync, tmp); } needs_flush = true; } @@ -315,10 +310,7 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm, if (r) return r; - if (updates) { - dma_fence_put((*id)->flushed_updates); - (*id)->flushed_updates = dma_fence_get(updates); - } + (*id)->flushed_updates = updates; job->vm_needs_flush = needs_flush; return 0; } @@ -346,7 +338,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm, unsigned vmhub = ring->funcs->vmhub; struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; uint64_t fence_context = adev->fence_context + ring->idx; - struct dma_fence *updates = sync->last_vm_update; + uint64_t updates = sync->last_vm_update; int r; job->vm_needs_flush = vm->use_cpu_for_update; @@ -354,7 +346,6 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm, /* Check if we can use a VMID already assigned to this VM */ list_for_each_entry_reverse((*id), &id_mgr->ids_lru, list) { bool needs_flush = vm->use_cpu_for_update; - struct dma_fence *flushed; /* Check all the prerequisites to using this VMID */ if ((*id)->owner != vm->immediate.fence_context) @@ -368,8 +359,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm, !dma_fence_is_signaled((*id)->last_flush))) needs_flush = true; - flushed = (*id)->flushed_updates; - if (updates && (!flushed || dma_fence_is_later(updates, flushed))) + if ((*id)->flushed_updates < updates) needs_flush = true; if (needs_flush && !adev->vm_manager.concurrent_flush) @@ -382,11 +372,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm, if (r) return r; - if (updates && (!flushed || dma_fence_is_later(updates, flushed))) { - dma_fence_put((*id)->flushed_updates); - (*id)->flushed_updates = dma_fence_get(updates); - } - + (*id)->flushed_updates = updates; job->vm_needs_flush |= needs_flush; return 0; } @@ -432,8 +418,6 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring, goto error; if (!id) { - struct dma_fence *updates = sync->last_vm_update; - /* Still no ID to use? Then use the idle one found earlier */ id = idle; @@ -442,8 +426,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring, if (r) goto error; - dma_fence_put(id->flushed_updates); - id->flushed_updates = dma_fence_get(updates); + id->flushed_updates = sync->last_vm_update; job->vm_needs_flush = true; } @@ -610,7 +593,6 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev) struct amdgpu_vmid *id = &id_mgr->ids[j]; amdgpu_sync_free(&id->active); - dma_fence_put(id->flushed_updates); dma_fence_put(id->last_flush); dma_fence_put(id->pasid_mapping); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h index 0c3b4fa1f936..06c8a0034fa5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.h @@ -47,7 +47,7 @@ struct amdgpu_vmid { uint64_t pd_gpu_addr; /* last flushed PD/PT update */ - struct dma_fence *flushed_updates; + uint64_t flushed_updates; uint32_t current_gpu_reset_count; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c index 40e06745fae9..05e1af9998a3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c @@ -51,7 +51,7 @@ static struct kmem_cache *amdgpu_sync_slab; void amdgpu_sync_create(struct amdgpu_sync *sync) { hash_init(sync->fences); - sync->last_vm_update = NULL; + sync->last_vm_update = 0; } /** @@ -184,7 +184,7 @@ int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence) if (!fence) return 0; - amdgpu_sync_keep_later(&sync->last_vm_update, fence); + sync->last_vm_update = max(sync->last_vm_update, fence->seqno); return amdgpu_sync_fence(sync, fence); } @@ -376,8 +376,7 @@ int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone) } } - dma_fence_put(clone->last_vm_update); - clone->last_vm_update = dma_fence_get(source->last_vm_update); + clone->last_vm_update = source->last_vm_update; return 0; } @@ -419,8 +418,6 @@ void amdgpu_sync_free(struct amdgpu_sync *sync) dma_fence_put(e->fence); kmem_cache_free(amdgpu_sync_slab, e); } - - dma_fence_put(sync->last_vm_update); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h index 7c0fe20c470d..876c1ee8869c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h @@ -43,7 +43,7 @@ enum amdgpu_sync_mode { */ struct amdgpu_sync { DECLARE_HASHTABLE(fences, 4); - struct dma_fence *last_vm_update; + uint64_t last_vm_update; }; void amdgpu_sync_create(struct amdgpu_sync *sync); From 5255e146c99a677d4d55fdb988544bd20c539a0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 15 Mar 2022 15:27:45 +0100 Subject: [PATCH 00381/11454] drm/amdgpu: rework TLB flushing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of tracking the VM updates through the dependencies just use a sequence counter for page table updates which indicates the need to flush the TLB. This reduces the need to flush the TLB drastically. v2: squash in NULL check fix (Christian) Signed-off-by: Christian König Acked-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 8 ++-- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 6 +-- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c | 20 --------- drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h | 2 - drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 57 ++++++++++++++++++++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 15 +++++++ 6 files changed, 76 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 970b065e9a6b..88681abc5f8c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -810,7 +810,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (r) return r; - r = amdgpu_sync_vm_fence(&p->job->sync, fpriv->prt_va->last_pt_update); + r = amdgpu_sync_fence(&p->job->sync, fpriv->prt_va->last_pt_update); if (r) return r; @@ -821,7 +821,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (r) return r; - r = amdgpu_sync_vm_fence(&p->job->sync, bo_va->last_pt_update); + r = amdgpu_sync_fence(&p->job->sync, bo_va->last_pt_update); if (r) return r; } @@ -840,7 +840,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (r) return r; - r = amdgpu_sync_vm_fence(&p->job->sync, bo_va->last_pt_update); + r = amdgpu_sync_fence(&p->job->sync, bo_va->last_pt_update); if (r) return r; } @@ -853,7 +853,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (r) return r; - r = amdgpu_sync_vm_fence(&p->job->sync, vm->last_update); + r = amdgpu_sync_fence(&p->job->sync, vm->last_update); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c index 4f1399573107..558f90e11d78 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c @@ -277,7 +277,7 @@ static int amdgpu_vmid_grab_reserved(struct amdgpu_vm *vm, unsigned vmhub = ring->funcs->vmhub; uint64_t fence_context = adev->fence_context + ring->idx; bool needs_flush = vm->use_cpu_for_update; - uint64_t updates = sync->last_vm_update; + uint64_t updates = amdgpu_vm_tlb_seq(vm); int r; *id = vm->reserved_vmid[vmhub]; @@ -338,7 +338,7 @@ static int amdgpu_vmid_grab_used(struct amdgpu_vm *vm, unsigned vmhub = ring->funcs->vmhub; struct amdgpu_vmid_mgr *id_mgr = &adev->vm_manager.id_mgr[vmhub]; uint64_t fence_context = adev->fence_context + ring->idx; - uint64_t updates = sync->last_vm_update; + uint64_t updates = amdgpu_vm_tlb_seq(vm); int r; job->vm_needs_flush = vm->use_cpu_for_update; @@ -426,7 +426,7 @@ int amdgpu_vmid_grab(struct amdgpu_vm *vm, struct amdgpu_ring *ring, if (r) goto error; - id->flushed_updates = sync->last_vm_update; + id->flushed_updates = amdgpu_vm_tlb_seq(vm); job->vm_needs_flush = true; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c index 05e1af9998a3..edd49dd27422 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.c @@ -51,7 +51,6 @@ static struct kmem_cache *amdgpu_sync_slab; void amdgpu_sync_create(struct amdgpu_sync *sync) { hash_init(sync->fences); - sync->last_vm_update = 0; } /** @@ -171,23 +170,6 @@ int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f) return 0; } -/** - * amdgpu_sync_vm_fence - remember to sync to this VM fence - * - * @sync: sync object to add fence to - * @fence: the VM fence to add - * - * Add the fence to the sync object and remember it as VM update. - */ -int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence) -{ - if (!fence) - return 0; - - sync->last_vm_update = max(sync->last_vm_update, fence->seqno); - return amdgpu_sync_fence(sync, fence); -} - /* Determine based on the owner and mode if we should sync to a fence or not */ static bool amdgpu_sync_test_fence(struct amdgpu_device *adev, enum amdgpu_sync_mode mode, @@ -376,8 +358,6 @@ int amdgpu_sync_clone(struct amdgpu_sync *source, struct amdgpu_sync *clone) } } - clone->last_vm_update = source->last_vm_update; - return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h index 876c1ee8869c..2d5c613cda10 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sync.h @@ -43,12 +43,10 @@ enum amdgpu_sync_mode { */ struct amdgpu_sync { DECLARE_HASHTABLE(fences, 4); - uint64_t last_vm_update; }; void amdgpu_sync_create(struct amdgpu_sync *sync); int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f); -int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence); int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, struct dma_resv *resv, enum amdgpu_sync_mode mode, void *owner); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index accebbac2f29..ecdcf652ba41 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -88,6 +88,21 @@ struct amdgpu_prt_cb { struct dma_fence_cb cb; }; +/** + * amdgpu_vm_tlb_seq_cb - Helper to increment the TLB flush sequence + */ +struct amdgpu_vm_tlb_seq_cb { + /** + * @vm: pointer to the amdgpu_vm structure to set the fence sequence on + */ + struct amdgpu_vm *vm; + + /** + * @cb: callback + */ + struct dma_fence_cb cb; +}; + /** * amdgpu_vm_set_pasid - manage pasid and vm ptr mapping * @@ -760,6 +775,23 @@ error: return r; } +/** + * amdgpu_vm_tlb_seq_cb - make sure to increment tlb sequence + * @fence: unused + * @cb: the callback structure + * + * Increments the tlb sequence to make sure that future CS execute a VM flush. + */ +static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence, + struct dma_fence_cb *cb) +{ + struct amdgpu_vm_tlb_seq_cb *tlb_cb; + + tlb_cb = container_of(cb, typeof(*tlb_cb), cb); + atomic64_inc(&tlb_cb->vm->tlb_seq); + kfree(tlb_cb); +} + /** * amdgpu_vm_bo_update_mapping - update a mapping in the vm page table * @@ -795,6 +827,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, bool *table_freed) { struct amdgpu_vm_update_params params; + struct amdgpu_vm_tlb_seq_cb *tlb_cb; struct amdgpu_res_cursor cursor; enum amdgpu_sync_mode sync_mode; int r, idx; @@ -802,6 +835,12 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, if (!drm_dev_enter(adev_to_drm(adev), &idx)) return -ENODEV; + tlb_cb = kmalloc(sizeof(*tlb_cb), GFP_KERNEL); + if (!tlb_cb) { + r = -ENOMEM; + goto error_unlock; + } + memset(¶ms, 0, sizeof(params)); params.adev = adev; params.vm = vm; @@ -820,7 +859,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, amdgpu_vm_eviction_lock(vm); if (vm->evicting) { r = -EBUSY; - goto error_unlock; + goto error_free; } if (!unlocked && !dma_fence_is_signaled(vm->last_unlocked)) { @@ -833,7 +872,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, r = vm->update_funcs->prepare(¶ms, resv, sync_mode); if (r) - goto error_unlock; + goto error_free; amdgpu_res_first(pages_addr ? NULL : res, offset, (last - start + 1) * AMDGPU_GPU_PAGE_SIZE, &cursor); @@ -882,7 +921,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, tmp = start + num_entries; r = amdgpu_vm_ptes_update(¶ms, start, tmp, addr, flags); if (r) - goto error_unlock; + goto error_free; amdgpu_res_next(&cursor, num_entries * AMDGPU_GPU_PAGE_SIZE); start = tmp; @@ -890,9 +929,21 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, r = vm->update_funcs->commit(¶ms, fence); + if (!unlocked && (!(flags & AMDGPU_PTE_VALID) || params.table_freed)) { + tlb_cb->vm = vm; + if (!fence || !*fence || + dma_fence_add_callback(*fence, &tlb_cb->cb, + amdgpu_vm_tlb_seq_cb)) + amdgpu_vm_tlb_seq_cb(NULL, &tlb_cb->cb); + tlb_cb = NULL; + } + if (table_freed) *table_freed = *table_freed || params.table_freed; +error_free: + kfree(tlb_cb); + error_unlock: amdgpu_vm_eviction_unlock(vm); drm_dev_exit(idx); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 1731681914f5..38a1eab1ff74 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -284,6 +284,9 @@ struct amdgpu_vm { struct drm_sched_entity immediate; struct drm_sched_entity delayed; + /* Last finished delayed update */ + atomic64_t tlb_seq; + /* Last unlocked submission to the scheduler entities */ struct dma_fence *last_unlocked; @@ -478,4 +481,16 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params *params, void amdgpu_debugfs_vm_bo_info(struct amdgpu_vm *vm, struct seq_file *m); #endif +/** + * amdgpu_vm_tlb_seq - return tlb flush sequence number + * @vm: the amdgpu_vm structure to query + * + * Returns the tlb flush sequence number which indicates that the VM TLBs needs + * to be invalidated whenever the sequence number change. + */ +static inline uint64_t amdgpu_vm_tlb_seq(struct amdgpu_vm *vm) +{ + return atomic64_read(&vm->tlb_seq); +} + #endif From bffa91dadf599155200b3efb46217ec108078a30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 17 Mar 2022 09:53:55 +0100 Subject: [PATCH 00382/11454] drm/amdkfd: start using tlb_seq from the VM subsystem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of trying to figure out if a TLB flush is necessary or not use the information provided by the VM subsystem now. Signed-off-by: Christian König Reviewed-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 1 + drivers/gpu/drm/amd/amdkfd/kfd_process.c | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index f36062be9ca8..945982a5d688 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -705,6 +705,7 @@ struct kfd_process_device { /* VM context for GPUVM allocations */ struct file *drm_file; void *drm_priv; + uint64_t tlb_seq; /* GPUVM allocations storage */ struct idr alloc_idr; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 59c04b2d383b..4a8a047b7593 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -1560,6 +1560,7 @@ int kfd_process_device_init_vm(struct kfd_process_device *pdd, return ret; } pdd->drm_priv = drm_file->private_data; + pdd->tlb_seq = 0; ret = kfd_process_device_reserve_ib_mem(pdd); if (ret) @@ -1949,8 +1950,14 @@ int kfd_reserved_mem_mmap(struct kfd_dev *dev, struct kfd_process *process, void kfd_flush_tlb(struct kfd_process_device *pdd, enum TLB_FLUSH_TYPE type) { + struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv); + uint64_t tlb_seq = amdgpu_vm_tlb_seq(vm); struct kfd_dev *dev = pdd->dev; + if (pdd->tlb_seq == tlb_seq) + return; + + pdd->tlb_seq = tlb_seq; if (dev->dqm->sched_policy == KFD_SCHED_POLICY_NO_HWS) { /* Nothing to flush until a VMID is assigned, which * only happens when the first queue is created. From 4d30a83c740e9904c7f54f071ec121f9e6932f63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 17 Mar 2022 14:08:36 +0100 Subject: [PATCH 00383/11454] drm/amdkfd: use tlb_seq from the VM subsystem for SVM as well v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of hand rolling the table_freed parameter. v2: add some changes suggested by Philip Signed-off-by: Christian König Reviewed-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 5 ++--- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 18 ++++++++---------- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 19 ++++++++----------- drivers/gpu/drm/amd/amdkfd/kfd_process.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 7 +++---- 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 0838926a8ef0..f8b9f27adcf5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -273,9 +273,8 @@ int amdgpu_amdkfd_gpuvm_alloc_memory_of_gpu( int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv, uint64_t *size); -int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( - struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv, - bool *table_freed); +int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(struct amdgpu_device *adev, + struct kgd_mem *mem, void *drm_priv); int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( struct amdgpu_device *adev, struct kgd_mem *mem, void *drm_priv); int amdgpu_amdkfd_gpuvm_sync_memory( diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index cd89d2e46852..57b521bb1eec 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1093,8 +1093,7 @@ static void unmap_bo_from_gpuvm(struct kgd_mem *mem, static int update_gpuvm_pte(struct kgd_mem *mem, struct kfd_mem_attachment *entry, - struct amdgpu_sync *sync, - bool *table_freed) + struct amdgpu_sync *sync) { struct amdgpu_bo_va *bo_va = entry->bo_va; struct amdgpu_device *adev = entry->adev; @@ -1105,7 +1104,7 @@ static int update_gpuvm_pte(struct kgd_mem *mem, return ret; /* Update the page tables */ - ret = amdgpu_vm_bo_update(adev, bo_va, false, table_freed); + ret = amdgpu_vm_bo_update(adev, bo_va, false, NULL); if (ret) { pr_err("amdgpu_vm_bo_update failed\n"); return ret; @@ -1117,8 +1116,7 @@ static int update_gpuvm_pte(struct kgd_mem *mem, static int map_bo_to_gpuvm(struct kgd_mem *mem, struct kfd_mem_attachment *entry, struct amdgpu_sync *sync, - bool no_update_pte, - bool *table_freed) + bool no_update_pte) { int ret; @@ -1135,7 +1133,7 @@ static int map_bo_to_gpuvm(struct kgd_mem *mem, if (no_update_pte) return 0; - ret = update_gpuvm_pte(mem, entry, sync, table_freed); + ret = update_gpuvm_pte(mem, entry, sync); if (ret) { pr_err("update_gpuvm_pte() failed\n"); goto update_gpuvm_pte_failed; @@ -1745,7 +1743,7 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu( int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( struct amdgpu_device *adev, struct kgd_mem *mem, - void *drm_priv, bool *table_freed) + void *drm_priv) { struct amdgpu_vm *avm = drm_priv_to_vm(drm_priv); int ret; @@ -1832,7 +1830,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu( entry->va, entry->va + bo_size, entry); ret = map_bo_to_gpuvm(mem, entry, ctx.sync, - is_invalid_userptr, table_freed); + is_invalid_userptr); if (ret) { pr_err("Failed to map bo to gpuvm\n"); goto out_unreserve; @@ -2300,7 +2298,7 @@ static int validate_invalid_user_pages(struct amdkfd_process_info *process_info) continue; kfd_mem_dmaunmap_attachment(mem, attachment); - ret = update_gpuvm_pte(mem, attachment, &sync, NULL); + ret = update_gpuvm_pte(mem, attachment, &sync); if (ret) { pr_err("%s: update PTE failed\n", __func__); /* make sure this gets validated again */ @@ -2506,7 +2504,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) continue; kfd_mem_dmaunmap_attachment(mem, attachment); - ret = update_gpuvm_pte(mem, attachment, &sync_obj, NULL); + ret = update_gpuvm_pte(mem, attachment, &sync_obj); if (ret) { pr_debug("Memory eviction: update PTE failed. Try again\n"); goto validate_map_fail; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c index 607f65ab39ac..60438193c0c1 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_chardev.c @@ -1146,7 +1146,6 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, long err = 0; int i; uint32_t *devices_arr = NULL; - bool table_freed = false; if (!args->n_devices) { pr_debug("Device IDs array empty\n"); @@ -1208,7 +1207,7 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu( peer_pdd->dev->adev, (struct kgd_mem *)mem, - peer_pdd->drm_priv, &table_freed); + peer_pdd->drm_priv); if (err) { struct pci_dev *pdev = peer_pdd->dev->adev->pdev; @@ -1233,13 +1232,11 @@ static int kfd_ioctl_map_memory_to_gpu(struct file *filep, } /* Flush TLBs after waiting for the page table updates to complete */ - if (table_freed || !kfd_flush_tlb_after_unmap(dev)) { - for (i = 0; i < args->n_devices; i++) { - peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); - if (WARN_ON_ONCE(!peer_pdd)) - continue; - kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); - } + for (i = 0; i < args->n_devices; i++) { + peer_pdd = kfd_process_device_data_by_id(p, devices_arr[i]); + if (WARN_ON_ONCE(!peer_pdd)) + continue; + kfd_flush_tlb(peer_pdd, TLB_FLUSH_LEGACY); } kfree(devices_arr); @@ -2206,8 +2203,8 @@ static int criu_restore_bo(struct kfd_process *p, if (IS_ERR(peer_pdd)) return PTR_ERR(peer_pdd); - ret = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(peer->adev, kgd_mem, peer_pdd->drm_priv, - NULL); + ret = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(peer->adev, kgd_mem, + peer_pdd->drm_priv); if (ret) { pr_err("Failed to map to gpu %d/%d\n", j, p->n_pdds); return ret; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index 4a8a047b7593..ac8123c1ee8f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -722,7 +722,7 @@ static int kfd_process_alloc_gpuvm(struct kfd_process_device *pdd, goto err_alloc_mem; err = amdgpu_amdkfd_gpuvm_map_memory_to_gpu(kdev->adev, *mem, - pdd->drm_priv, NULL); + pdd->drm_priv); if (err) goto err_map_mem; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index 3b8856b4cece..bf6354f539d8 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1243,7 +1243,6 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange, { struct amdgpu_device *adev = pdd->dev->adev; struct amdgpu_vm *vm = drm_priv_to_vm(pdd->drm_priv); - bool table_freed = false; uint64_t pte_flags; unsigned long last_start; int last_domain; @@ -1284,7 +1283,7 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange, last_start - prange->start, NULL, dma_addr, &vm->last_update, - &table_freed); + NULL); for (j = last_start - prange->start; j <= i; j++) dma_addr[j] |= last_domain; @@ -1306,8 +1305,6 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange, if (fence) *fence = dma_fence_get(vm->last_update); - if (table_freed) - kfd_flush_tlb(pdd, TLB_FLUSH_LEGACY); out: return r; } @@ -1363,6 +1360,8 @@ svm_range_map_to_gpus(struct svm_range *prange, unsigned long offset, break; } } + + kfd_flush_tlb(pdd, TLB_FLUSH_LEGACY); } return r; From 8f8cc3fb43508a2b1682e3809d6d39ce1871a5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Thu, 17 Mar 2022 14:29:22 +0100 Subject: [PATCH 00384/11454] drm/amdgpu: remove table_freed param from the VM code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Better to leave the decision when to flush the VM changes in the TLB to the VM code. Signed-off-by: Christian König Reviewed-by: Philip Yang Reviewed-by: Felix Kuehling Signed-off-by: Alex Deucher --- .../gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 6 +++--- drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 21 +++++++------------ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 4 ++-- drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 5 ++--- 6 files changed, 16 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 57b521bb1eec..8b14c55a0793 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1104,7 +1104,7 @@ static int update_gpuvm_pte(struct kgd_mem *mem, return ret; /* Update the page tables */ - ret = amdgpu_vm_bo_update(adev, bo_va, false, NULL); + ret = amdgpu_vm_bo_update(adev, bo_va, false); if (ret) { pr_err("amdgpu_vm_bo_update failed\n"); return ret; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 88681abc5f8c..12bad207bb0f 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -806,7 +806,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (r) return r; - r = amdgpu_vm_bo_update(adev, fpriv->prt_va, false, NULL); + r = amdgpu_vm_bo_update(adev, fpriv->prt_va, false); if (r) return r; @@ -817,7 +817,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (amdgpu_mcbp || amdgpu_sriov_vf(adev)) { bo_va = fpriv->csa_va; BUG_ON(!bo_va); - r = amdgpu_vm_bo_update(adev, bo_va, false, NULL); + r = amdgpu_vm_bo_update(adev, bo_va, false); if (r) return r; @@ -836,7 +836,7 @@ static int amdgpu_cs_vm_handling(struct amdgpu_cs_parser *p) if (bo_va == NULL) continue; - r = amdgpu_vm_bo_update(adev, bo_va, false, NULL); + r = amdgpu_vm_bo_update(adev, bo_va, false); if (r) return r; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 57b74d35052f..89c6d6f1d4fa 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -612,7 +612,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, if (operation == AMDGPU_VA_OP_MAP || operation == AMDGPU_VA_OP_REPLACE) { - r = amdgpu_vm_bo_update(adev, bo_va, false, NULL); + r = amdgpu_vm_bo_update(adev, bo_va, false); if (r) goto error; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index ecdcf652ba41..48f326609976 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -808,7 +808,6 @@ static void amdgpu_vm_tlb_seq_cb(struct dma_fence *fence, * @res: ttm_resource to map * @pages_addr: DMA addresses to use for mapping * @fence: optional resulting fence - * @table_freed: return true if page table is freed * * Fill in the page table entries between @start and @last. * @@ -823,8 +822,7 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, uint64_t flags, uint64_t offset, struct ttm_resource *res, dma_addr_t *pages_addr, - struct dma_fence **fence, - bool *table_freed) + struct dma_fence **fence) { struct amdgpu_vm_update_params params; struct amdgpu_vm_tlb_seq_cb *tlb_cb; @@ -938,9 +936,6 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, tlb_cb = NULL; } - if (table_freed) - *table_freed = *table_freed || params.table_freed; - error_free: kfree(tlb_cb); @@ -1000,7 +995,6 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem, * @adev: amdgpu_device pointer * @bo_va: requested BO and VM object * @clear: if true clear the entries - * @table_freed: return true if page table is freed * * Fill in the page table entries for @bo_va. * @@ -1008,7 +1002,7 @@ void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem, * 0 for success, -EINVAL for failure. */ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, - bool clear, bool *table_freed) + bool clear) { struct amdgpu_bo *bo = bo_va->base.bo; struct amdgpu_vm *vm = bo_va->base.vm; @@ -1087,7 +1081,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, resv, mapping->start, mapping->last, update_flags, mapping->offset, mem, - pages_addr, last_update, table_freed); + pages_addr, last_update); if (r) return r; } @@ -1281,7 +1275,7 @@ int amdgpu_vm_clear_freed(struct amdgpu_device *adev, r = amdgpu_vm_bo_update_mapping(adev, adev, vm, false, false, resv, mapping->start, mapping->last, init_pte_value, - 0, NULL, NULL, &f, NULL); + 0, NULL, NULL, &f); amdgpu_vm_free_mapping(adev, vm, mapping, f); if (r) { dma_fence_put(f); @@ -1323,7 +1317,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, list_for_each_entry_safe(bo_va, tmp, &vm->moved, base.vm_status) { /* Per VM BOs never need to bo cleared in the page tables */ - r = amdgpu_vm_bo_update(adev, bo_va, false, NULL); + r = amdgpu_vm_bo_update(adev, bo_va, false); if (r) return r; } @@ -1342,7 +1336,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, else clear = true; - r = amdgpu_vm_bo_update(adev, bo_va, clear, NULL); + r = amdgpu_vm_bo_update(adev, bo_va, clear); if (r) return r; @@ -2526,8 +2520,7 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, } r = amdgpu_vm_bo_update_mapping(adev, adev, vm, true, false, NULL, addr, - addr, flags, value, NULL, NULL, NULL, - NULL); + addr, flags, value, NULL, NULL, NULL); if (r) goto error_unlock; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 38a1eab1ff74..6b7682fe84f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -410,10 +410,10 @@ int amdgpu_vm_bo_update_mapping(struct amdgpu_device *adev, uint64_t flags, uint64_t offset, struct ttm_resource *res, dma_addr_t *pages_addr, - struct dma_fence **fence, bool *free_table); + struct dma_fence **fence); int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, - bool clear, bool *table_freed); + bool clear); bool amdgpu_vm_evictable(struct amdgpu_bo *bo); void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, struct amdgpu_bo *bo, bool evicted); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index bf6354f539d8..27533f6057e0 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -1190,7 +1190,7 @@ svm_range_unmap_from_gpu(struct amdgpu_device *adev, struct amdgpu_vm *vm, return amdgpu_vm_bo_update_mapping(adev, adev, vm, false, true, NULL, start, last, init_pte_value, 0, - NULL, NULL, fence, NULL); + NULL, NULL, fence); } static int @@ -1282,8 +1282,7 @@ svm_range_map_to_gpu(struct kfd_process_device *pdd, struct svm_range *prange, prange->start + i, pte_flags, last_start - prange->start, NULL, dma_addr, - &vm->last_update, - NULL); + &vm->last_update); for (j = last_start - prange->start; j <= i; j++) dma_addr[j] |= last_domain; From c0c73850637c6ad6a56a6b5ee181897cb35c6c31 Mon Sep 17 00:00:00 2001 From: Daniele Ceraolo Spurio Date: Wed, 23 Mar 2022 17:04:39 -0700 Subject: [PATCH 00385/11454] drm/i915/guc: Correctly free guc capture struct on error On error the "new" allocation is not freed, so add the required kfree. Fixes: 247f8071d5893 ("drm/i915/guc: Pre-allocate output nodes for extraction") Signed-off-by: Daniele Ceraolo Spurio Cc: Alan Previn Cc: John Harrison Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220324000439.2370440-1-daniele.ceraolospurio@intel.com --- drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c index afdcbe63e9eb..c4e25966d3e9 100644 --- a/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c +++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_capture.c @@ -1040,6 +1040,7 @@ guc_capture_alloc_one_node(struct intel_guc *guc) if (!new->reginfo[i].regs) { while (i) kfree(new->reginfo[--i].regs); + kfree(new); return NULL; } } From be658e705d08d14eb1b7803c89e6964b5d1c5c0a Mon Sep 17 00:00:00 2001 From: CQ Tang Date: Thu, 24 Mar 2022 14:31:23 +0000 Subject: [PATCH 00386/11454] drm/i915: add lmem_size modparam MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lmem_size is used to limit the amount of lmem for testing purposes. Default is to use hardware available lmem size. Signed-off-by: CQ Tang Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Nirmoy Das Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220324143123.348590-2-matthew.auld@intel.com --- drivers/gpu/drm/i915/gt/intel_region_lmem.c | 4 ++++ drivers/gpu/drm/i915/i915_params.c | 3 +++ drivers/gpu/drm/i915/i915_params.h | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_region_lmem.c b/drivers/gpu/drm/i915/gt/intel_region_lmem.c index 783d81072c3b..f5111c0a0060 100644 --- a/drivers/gpu/drm/i915/gt/intel_region_lmem.c +++ b/drivers/gpu/drm/i915/gt/intel_region_lmem.c @@ -123,6 +123,10 @@ static struct intel_memory_region *setup_lmem(struct intel_gt *gt) lmem_size = intel_uncore_read64(&i915->uncore, GEN12_GSMBASE); } + if (i915->params.lmem_size > 0) { + lmem_size = min_t(resource_size_t, lmem_size, + mul_u32_u32(i915->params.lmem_size, SZ_1M)); + } io_start = pci_resource_start(pdev, 2); io_size = min(pci_resource_len(pdev, 2), lmem_size); diff --git a/drivers/gpu/drm/i915/i915_params.c b/drivers/gpu/drm/i915/i915_params.c index eea355c2fc28..d898141cf208 100644 --- a/drivers/gpu/drm/i915/i915_params.c +++ b/drivers/gpu/drm/i915/i915_params.c @@ -200,6 +200,9 @@ i915_param_named_unsafe(request_timeout_ms, uint, 0600, "Default request/fence/batch buffer expiration timeout."); #endif +i915_param_named_unsafe(lmem_size, uint, 0400, + "Set the lmem size(in MiB) for each region. (default: 0, all memory)"); + static __always_inline void _print_param(struct drm_printer *p, const char *name, const char *type, diff --git a/drivers/gpu/drm/i915/i915_params.h b/drivers/gpu/drm/i915/i915_params.h index c779a6f85c7e..b5e7ea45d191 100644 --- a/drivers/gpu/drm/i915/i915_params.h +++ b/drivers/gpu/drm/i915/i915_params.h @@ -73,6 +73,7 @@ struct drm_printer; param(int, enable_dpcd_backlight, -1, 0600) \ param(char *, force_probe, CONFIG_DRM_I915_FORCE_PROBE, 0400) \ param(unsigned int, request_timeout_ms, CONFIG_DRM_I915_REQUEST_TIMEOUT, CONFIG_DRM_I915_REQUEST_TIMEOUT ? 0600 : 0) \ + param(unsigned int, lmem_size, 0, 0400) \ /* leave bools at the end to not create holes */ \ param(bool, enable_hangcheck, true, 0600) \ param(bool, load_detect_test, false, 0600) \ From 86ad0397250c585096d242dc3c0f774320ed1a80 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Wed, 19 Jan 2022 12:23:09 +0200 Subject: [PATCH 00387/11454] drm: omapdrm: simplify omap_gem_pin Move tiler related code to its own function. Signed-off-by: Ivaylo Dimitrov Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/1642587791-13222-2-git-send-email-ivo.g.dimitrov.75@gmail.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 75 +++++++++++++++++------------- 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index b0fa17409b66..bb12cb49c92a 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -750,6 +750,46 @@ void omap_gem_dma_sync_buffer(struct drm_gem_object *obj, } } +static int omap_gem_pin_tiler(struct drm_gem_object *obj) +{ + struct omap_gem_object *omap_obj = to_omap_bo(obj); + u32 npages = obj->size >> PAGE_SHIFT; + enum tiler_fmt fmt = gem2fmt(omap_obj->flags); + struct tiler_block *block; + int ret; + + BUG_ON(omap_obj->block); + + if (omap_obj->flags & OMAP_BO_TILED_MASK) { + block = tiler_reserve_2d(fmt, omap_obj->width, omap_obj->height, + PAGE_SIZE); + } else { + block = tiler_reserve_1d(obj->size); + } + + if (IS_ERR(block)) { + ret = PTR_ERR(block); + dev_err(obj->dev->dev, "could not remap: %d (%d)\n", ret, fmt); + goto fail; + } + + /* TODO: enable async refill.. */ + ret = tiler_pin(block, omap_obj->pages, npages, omap_obj->roll, true); + if (ret) { + tiler_release(block); + dev_err(obj->dev->dev, "could not pin: %d\n", ret); + goto fail; + } + + omap_obj->dma_addr = tiler_ssptr(block); + omap_obj->block = block; + + DBG("got dma address: %pad", &omap_obj->dma_addr); + +fail: + return ret; +} + /** * omap_gem_pin() - Pin a GEM object in memory * @obj: the GEM object @@ -774,11 +814,6 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) { if (refcount_read(&omap_obj->dma_addr_cnt) == 0) { - u32 npages = obj->size >> PAGE_SHIFT; - enum tiler_fmt fmt = gem2fmt(omap_obj->flags); - struct tiler_block *block; - - BUG_ON(omap_obj->block); refcount_set(&omap_obj->dma_addr_cnt, 1); @@ -786,35 +821,9 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) if (ret) goto fail; - if (omap_obj->flags & OMAP_BO_TILED_MASK) { - block = tiler_reserve_2d(fmt, - omap_obj->width, - omap_obj->height, PAGE_SIZE); - } else { - block = tiler_reserve_1d(obj->size); - } - - if (IS_ERR(block)) { - ret = PTR_ERR(block); - dev_err(obj->dev->dev, - "could not remap: %d (%d)\n", ret, fmt); + ret = omap_gem_pin_tiler(obj); + if (ret) goto fail; - } - - /* TODO: enable async refill.. */ - ret = tiler_pin(block, omap_obj->pages, npages, - omap_obj->roll, true); - if (ret) { - tiler_release(block); - dev_err(obj->dev->dev, - "could not pin: %d\n", ret); - goto fail; - } - - omap_obj->dma_addr = tiler_ssptr(block); - omap_obj->block = block; - - DBG("got dma address: %pad", &omap_obj->dma_addr); } else { refcount_inc(&omap_obj->dma_addr_cnt); } From 1948d28db6215d055930f0cbb6e300622ede5931 Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Wed, 19 Jan 2022 12:23:10 +0200 Subject: [PATCH 00388/11454] drm: omapdrm: Support exporting of non-contiguous GEM BOs Currently code allocates non-scanout BOs from SHMEM and those objects are accessible to userspace by mmap(). However, on devices with no DMM (like OMAP3), the same objects are not accessible by kernel drivers that want to render to them as code refuses to export them. In turn this means that on devices with no DMM, all buffers must be allocated as scanout, otherwise only CPU can access them. On those devices, scanout buffers are allocated from CMA, making those allocations highly unreliable. Fix that by implementing functionality to export SHMEM backed buffers on devices with no DMM. This makes CMA memory only being used when needed, instead for every buffer that has to be off-CPU rendered. Tested on Motorola Droid4 and Nokia N900 Signed-off-by: Ivaylo Dimitrov Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/1642587791-13222-3-git-send-email-ivo.g.dimitrov.75@gmail.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 125 ++++++++++++---------- drivers/gpu/drm/omapdrm/omap_gem.h | 3 +- drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 5 +- 3 files changed, 73 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index bb12cb49c92a..41c1a6d83b2b 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -38,7 +38,7 @@ struct omap_gem_object { /** roll applied when mapping to DMM */ u32 roll; - /** protects dma_addr_cnt, block, pages, dma_addrs and vaddr */ + /** protects pin_cnt, block, pages, dma_addrs and vaddr */ struct mutex lock; /** @@ -50,24 +50,24 @@ struct omap_gem_object { * - buffers imported from dmabuf (with the OMAP_BO_MEM_DMABUF flag set) * if they are physically contiguous (when sgt->orig_nents == 1) * - * - buffers mapped through the TILER when dma_addr_cnt is not zero, in - * which case the DMA address points to the TILER aperture + * - buffers mapped through the TILER when pin_cnt is not zero, in which + * case the DMA address points to the TILER aperture * * Physically contiguous buffers have their DMA address equal to the * physical address as we don't remap those buffers through the TILER. * * Buffers mapped to the TILER have their DMA address pointing to the - * TILER aperture. As TILER mappings are refcounted (through - * dma_addr_cnt) the DMA address must be accessed through omap_gem_pin() - * to ensure that the mapping won't disappear unexpectedly. References - * must be released with omap_gem_unpin(). + * TILER aperture. As TILER mappings are refcounted (through pin_cnt) + * the DMA address must be accessed through omap_gem_pin() to ensure + * that the mapping won't disappear unexpectedly. References must be + * released with omap_gem_unpin(). */ dma_addr_t dma_addr; /** - * # of users of dma_addr + * # of users */ - refcount_t dma_addr_cnt; + refcount_t pin_cnt; /** * If the buffer has been imported from a dmabuf the OMAP_DB_DMABUF flag @@ -812,32 +812,28 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) mutex_lock(&omap_obj->lock); - if (!omap_gem_is_contiguous(omap_obj) && priv->has_dmm) { - if (refcount_read(&omap_obj->dma_addr_cnt) == 0) { + if (!omap_gem_is_contiguous(omap_obj)) { + if (refcount_read(&omap_obj->pin_cnt) == 0) { - refcount_set(&omap_obj->dma_addr_cnt, 1); + refcount_set(&omap_obj->pin_cnt, 1); ret = omap_gem_attach_pages(obj); if (ret) goto fail; - ret = omap_gem_pin_tiler(obj); - if (ret) - goto fail; + if (priv->has_dmm) { + ret = omap_gem_pin_tiler(obj); + if (ret) + goto fail; + } } else { - refcount_inc(&omap_obj->dma_addr_cnt); + refcount_inc(&omap_obj->pin_cnt); } - - if (dma_addr) - *dma_addr = omap_obj->dma_addr; - } else if (omap_gem_is_contiguous(omap_obj)) { - if (dma_addr) - *dma_addr = omap_obj->dma_addr; - } else { - ret = -EINVAL; - goto fail; } + if (dma_addr) + *dma_addr = omap_obj->dma_addr; + fail: mutex_unlock(&omap_obj->lock); @@ -856,27 +852,29 @@ static void omap_gem_unpin_locked(struct drm_gem_object *obj) struct omap_gem_object *omap_obj = to_omap_bo(obj); int ret; - if (omap_gem_is_contiguous(omap_obj) || !priv->has_dmm) + if (omap_gem_is_contiguous(omap_obj)) return; - if (refcount_dec_and_test(&omap_obj->dma_addr_cnt)) { + if (refcount_dec_and_test(&omap_obj->pin_cnt)) { if (omap_obj->sgt) { sg_free_table(omap_obj->sgt); kfree(omap_obj->sgt); omap_obj->sgt = NULL; } - ret = tiler_unpin(omap_obj->block); - if (ret) { - dev_err(obj->dev->dev, - "could not unpin pages: %d\n", ret); + if (priv->has_dmm) { + ret = tiler_unpin(omap_obj->block); + if (ret) { + dev_err(obj->dev->dev, + "could not unpin pages: %d\n", ret); + } + ret = tiler_release(omap_obj->block); + if (ret) { + dev_err(obj->dev->dev, + "could not release unmap: %d\n", ret); + } + omap_obj->dma_addr = 0; + omap_obj->block = NULL; } - ret = tiler_release(omap_obj->block); - if (ret) { - dev_err(obj->dev->dev, - "could not release unmap: %d\n", ret); - } - omap_obj->dma_addr = 0; - omap_obj->block = NULL; } } @@ -909,7 +907,7 @@ int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient, mutex_lock(&omap_obj->lock); - if ((refcount_read(&omap_obj->dma_addr_cnt) > 0) && omap_obj->block && + if ((refcount_read(&omap_obj->pin_cnt) > 0) && omap_obj->block && (omap_obj->flags & OMAP_BO_TILED_MASK)) { *dma_addr = tiler_tsptr(omap_obj->block, orient, x, y); ret = 0; @@ -977,7 +975,8 @@ int omap_gem_put_pages(struct drm_gem_object *obj) return 0; } -struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj) +struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj, + enum dma_data_direction dir) { struct omap_gem_object *omap_obj = to_omap_bo(obj); dma_addr_t addr; @@ -1002,28 +1001,44 @@ struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj) goto err_unpin; } - if (omap_obj->flags & OMAP_BO_TILED_MASK) { - enum tiler_fmt fmt = gem2fmt(omap_obj->flags); + if (addr) { + if (omap_obj->flags & OMAP_BO_TILED_MASK) { + enum tiler_fmt fmt = gem2fmt(omap_obj->flags); - len = omap_obj->width << (int)fmt; - count = omap_obj->height; - stride = tiler_stride(fmt, 0); + len = omap_obj->width << (int)fmt; + count = omap_obj->height; + stride = tiler_stride(fmt, 0); + } else { + len = obj->size; + count = 1; + stride = 0; + } } else { - len = obj->size; - count = 1; - stride = 0; + count = obj->size >> PAGE_SHIFT; } ret = sg_alloc_table(sgt, count, GFP_KERNEL); if (ret) goto err_free; - for_each_sg(sgt->sgl, sg, count, i) { - sg_set_page(sg, phys_to_page(addr), len, offset_in_page(addr)); - sg_dma_address(sg) = addr; - sg_dma_len(sg) = len; + /* this must be after omap_gem_pin() to ensure we have pages attached */ + omap_gem_dma_sync_buffer(obj, dir); - addr += stride; + if (addr) { + for_each_sg(sgt->sgl, sg, count, i) { + sg_set_page(sg, phys_to_page(addr), len, + offset_in_page(addr)); + sg_dma_address(sg) = addr; + sg_dma_len(sg) = len; + + addr += stride; + } + } else { + for_each_sg(sgt->sgl, sg, count, i) { + sg_set_page(sg, omap_obj->pages[i], PAGE_SIZE, 0); + sg_dma_address(sg) = omap_obj->dma_addrs[i]; + sg_dma_len(sg) = PAGE_SIZE; + } } omap_obj->sgt = sgt; @@ -1133,7 +1148,7 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m) seq_printf(m, "%08x: %2d (%2d) %08llx %pad (%2d) %p %4d", omap_obj->flags, obj->name, kref_read(&obj->refcount), off, &omap_obj->dma_addr, - refcount_read(&omap_obj->dma_addr_cnt), + refcount_read(&omap_obj->pin_cnt), omap_obj->vaddr, omap_obj->roll); if (omap_obj->flags & OMAP_BO_TILED_MASK) { @@ -1196,7 +1211,7 @@ static void omap_gem_free_object(struct drm_gem_object *obj) mutex_lock(&omap_obj->lock); /* The object should not be pinned. */ - WARN_ON(refcount_read(&omap_obj->dma_addr_cnt) > 0); + WARN_ON(refcount_read(&omap_obj->pin_cnt) > 0); if (omap_obj->pages) { if (omap_obj->flags & OMAP_BO_MEM_DMABUF) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.h b/drivers/gpu/drm/omapdrm/omap_gem.h index 19209e319663..4d4488939f6b 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.h +++ b/drivers/gpu/drm/omapdrm/omap_gem.h @@ -82,7 +82,8 @@ u32 omap_gem_flags(struct drm_gem_object *obj); int omap_gem_rotated_dma_addr(struct drm_gem_object *obj, u32 orient, int x, int y, dma_addr_t *dma_addr); int omap_gem_tiled_stride(struct drm_gem_object *obj, u32 orient); -struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj); +struct sg_table *omap_gem_get_sg(struct drm_gem_object *obj, + enum dma_data_direction dir); void omap_gem_put_sg(struct drm_gem_object *obj, struct sg_table *sgt); #endif /* __OMAPDRM_GEM_H__ */ diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index ab3fc86e7256..393f82e26927 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c @@ -23,13 +23,10 @@ static struct sg_table *omap_gem_map_dma_buf( { struct drm_gem_object *obj = attachment->dmabuf->priv; struct sg_table *sg; - sg = omap_gem_get_sg(obj); + sg = omap_gem_get_sg(obj, dir); if (IS_ERR(sg)) return sg; - /* this must be after omap_gem_pin() to ensure we have pages attached */ - omap_gem_dma_sync_buffer(obj, dir); - return sg; } From 3ccd59f93004c369cc4c0f0939f80cb069f0fc2d Mon Sep 17 00:00:00 2001 From: Ivaylo Dimitrov Date: Wed, 19 Jan 2022 12:23:11 +0200 Subject: [PATCH 00389/11454] drm: omapdrm: Do no allocate non-scanout GEMs through DMM/TILER On devices with DMM, all allocations are done through either DMM or TILER. DMM/TILER being a limited resource means that such allocations will start to fail before actual free memory is exhausted. What is even worse is that with time DMM/TILER space gets fragmented to the point that even if we have enough free DMM/TILER space and free memory, allocation fails because there is no big enough free block in DMM/TILER space. Such failures can be easily observed with OMAP xorg DDX, for example - starting few GUI applications (so buffers for their windows are allocated) and then rotating landscape<->portrait while closing and opening new windows soon results in allocation failures. Fix that by mapping buffers through DMM/TILER only when really needed, like, for scanout buffers. Signed-off-by: Ivaylo Dimitrov Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/1642587791-13222-4-git-send-email-ivo.g.dimitrov.75@gmail.com --- drivers/gpu/drm/omapdrm/omap_gem.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 41c1a6d83b2b..cf571796fd26 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -821,10 +821,12 @@ int omap_gem_pin(struct drm_gem_object *obj, dma_addr_t *dma_addr) if (ret) goto fail; - if (priv->has_dmm) { - ret = omap_gem_pin_tiler(obj); - if (ret) - goto fail; + if (omap_obj->flags & OMAP_BO_SCANOUT) { + if (priv->has_dmm) { + ret = omap_gem_pin_tiler(obj); + if (ret) + goto fail; + } } } else { refcount_inc(&omap_obj->pin_cnt); @@ -861,6 +863,8 @@ static void omap_gem_unpin_locked(struct drm_gem_object *obj) kfree(omap_obj->sgt); omap_obj->sgt = NULL; } + if (!(omap_obj->flags & OMAP_BO_SCANOUT)) + return; if (priv->has_dmm) { ret = tiler_unpin(omap_obj->block); if (ret) { From 73867c8709b569cdd7fda67f01dfe02c8d055521 Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Tue, 15 Mar 2022 13:32:46 +0530 Subject: [PATCH 00390/11454] drm/i915/display: Remove check for low voltage sku for max dp source rate The low voltage sku check can be ignored as OEMs need to consider that when designing the board and then put any limits in VBT. Same is now changed in Bspec pages. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5272 Signed-off-by: Ankit Nautiyal Reviewed-by: Imre Deak Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20220315080247.1161844-2-ankit.k.nautiyal@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 32 +++---------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 9e19165fd175..5e6b134aaa15 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -388,23 +388,13 @@ static int dg2_max_source_rate(struct intel_dp *intel_dp) return intel_dp_is_edp(intel_dp) ? 810000 : 1350000; } -static bool is_low_voltage_sku(struct drm_i915_private *i915, enum phy phy) -{ - u32 voltage; - - voltage = intel_de_read(i915, ICL_PORT_COMP_DW3(phy)) & VOLTAGE_INFO_MASK; - - return voltage == VOLTAGE_INFO_0_85V; -} - static int icl_max_source_rate(struct intel_dp *intel_dp) { struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port); - if (intel_phy_is_combo(dev_priv, phy) && - (is_low_voltage_sku(dev_priv, phy) || !intel_dp_is_edp(intel_dp))) + if (intel_phy_is_combo(dev_priv, phy) && !intel_dp_is_edp(intel_dp)) return 540000; return 810000; @@ -412,23 +402,7 @@ static int icl_max_source_rate(struct intel_dp *intel_dp) static int ehl_max_source_rate(struct intel_dp *intel_dp) { - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(dev_priv, dig_port->base.port); - - if (intel_dp_is_edp(intel_dp) || is_low_voltage_sku(dev_priv, phy)) - return 540000; - - return 810000; -} - -static int dg1_max_source_rate(struct intel_dp *intel_dp) -{ - struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp); - struct drm_i915_private *i915 = to_i915(dig_port->base.base.dev); - enum phy phy = intel_port_to_phy(i915, dig_port->base.port); - - if (intel_phy_is_combo(i915, phy) && is_low_voltage_sku(i915, phy)) + if (intel_dp_is_edp(intel_dp)) return 540000; return 810000; @@ -471,7 +445,7 @@ intel_dp_set_source_rates(struct intel_dp *intel_dp) max_rate = dg2_max_source_rate(intel_dp); else if (IS_ALDERLAKE_P(dev_priv) || IS_ALDERLAKE_S(dev_priv) || IS_DG1(dev_priv) || IS_ROCKETLAKE(dev_priv)) - max_rate = dg1_max_source_rate(intel_dp); + max_rate = 810000; else if (IS_JSL_EHL(dev_priv)) max_rate = ehl_max_source_rate(intel_dp); else From 3fd6afb623ba0f908af4f81794ccdff4dd5e671e Mon Sep 17 00:00:00 2001 From: Ankit Nautiyal Date: Wed, 23 Mar 2022 15:13:07 +0530 Subject: [PATCH 00391/11454] drm/i915/intel_combo_phy: Print I/O voltage info Print I/O voltage and process info for each combo phy ports. v2: Used drm_dbg_kms for logs. (Jani) Added names for different voltage levels. (Imre) v3: Used const char * for names. (Jani) v4: Dropped the procom values and changed commit msg (Imre) Suggested-by: Imre Deak Signed-off-by: Ankit Nautiyal Reviewed-by: Imre Deak Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20220323094307.2439004-1-ankit.k.nautiyal@intel.com --- .../gpu/drm/i915/display/intel_combo_phy.c | 35 +++++++++++++------ 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_combo_phy.c b/drivers/gpu/drm/i915/display/intel_combo_phy.c index 4dfe77351b8b..64890f39c3cc 100644 --- a/drivers/gpu/drm/i915/display/intel_combo_phy.c +++ b/drivers/gpu/drm/i915/display/intel_combo_phy.c @@ -25,18 +25,29 @@ enum { }; static const struct icl_procmon { + const char *name; u32 dw1, dw9, dw10; } icl_procmon_values[] = { - [PROCMON_0_85V_DOT_0] = - { .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, }, - [PROCMON_0_95V_DOT_0] = - { .dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB, }, - [PROCMON_0_95V_DOT_1] = - { .dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5, }, - [PROCMON_1_05V_DOT_0] = - { .dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1, }, - [PROCMON_1_05V_DOT_1] = - { .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, }, + [PROCMON_0_85V_DOT_0] = { + .name = "0.85V dot0 (low-voltage)", + .dw1 = 0x00000000, .dw9 = 0x62AB67BB, .dw10 = 0x51914F96, + }, + [PROCMON_0_95V_DOT_0] = { + .name = "0.95V dot0", + .dw1 = 0x00000000, .dw9 = 0x86E172C7, .dw10 = 0x77CA5EAB, + }, + [PROCMON_0_95V_DOT_1] = { + .name = "0.95V dot1", + .dw1 = 0x00000000, .dw9 = 0x93F87FE1, .dw10 = 0x8AE871C5, + }, + [PROCMON_1_05V_DOT_0] = { + .name = "1.05V dot0", + .dw1 = 0x00000000, .dw9 = 0x98FA82DD, .dw10 = 0x89E46DC1, + }, + [PROCMON_1_05V_DOT_1] = { + .name = "1.05V dot1", + .dw1 = 0x00440000, .dw9 = 0x9A00AB25, .dw10 = 0x8AE38FF1, + }, }; static const struct icl_procmon * @@ -113,6 +124,10 @@ static bool icl_verify_procmon_ref_values(struct drm_i915_private *dev_priv, procmon = icl_get_procmon_ref_values(dev_priv, phy); + drm_dbg_kms(&dev_priv->drm, + "Combo PHY %c Voltage/Process Info : %s\n", + phy_name(phy), procmon->name); + ret = check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW1(phy), (0xff << 16) | 0xff, procmon->dw1); ret &= check_phy_reg(dev_priv, phy, ICL_PORT_COMP_DW9(phy), From b2beae327e039736299f3c6559f3467323fe68c5 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Wed, 23 Mar 2022 21:18:56 -0400 Subject: [PATCH 00392/11454] ath11k: store and send country code to firmware after recovery Currently ath11k does not send the country code to firmware after device recovery, as a result the regdomain info is reported from firmware by default. Regdomain info is important, so ath11k also need to restore it to the value which was used before recovery. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220324011856.11014-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 1 + drivers/net/wireless/ath/ath11k/core.h | 1 + drivers/net/wireless/ath/ath11k/mac.c | 8 ++++++++ drivers/net/wireless/ath/ath11k/reg.c | 1 + 4 files changed, 11 insertions(+) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 2a867237e817..9395a5a271f1 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1404,6 +1404,7 @@ static void ath11k_update_11d(struct work_struct *work) pdev = &ab->pdevs[i]; ar = pdev->ar; + memcpy(&ar->alpha2, &set_current_param.alpha2, 2); ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param); if (ret) ath11k_warn(ar->ab, diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index 41001ec174e2..b4d58e01fffa 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -671,6 +671,7 @@ struct ath11k { int hw_rate_code; u8 twt_enabled; bool nlo_enabled; + u8 alpha2[REG_ALPHA2_LEN + 1]; }; struct ath11k_band_cap { diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 7a7641e8e325..9caa8b87c313 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -7957,6 +7957,14 @@ ath11k_mac_op_reconfig_complete(struct ieee80211_hw *hw, ar->state = ATH11K_STATE_ON; ieee80211_wake_queues(ar->hw); + if (ar->ab->hw_params.current_cc_support && + ar->alpha2[0] != 0 && ar->alpha2[1] != 0) { + struct wmi_set_current_country_params set_current_param = {}; + + memcpy(&set_current_param.alpha2, ar->alpha2, 2); + ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param); + } + if (ab->is_reset) { recovery_count = atomic_inc_return(&ab->recovery_count); ath11k_dbg(ab, ATH11K_DBG_BOOT, diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c index 81e11cde31d7..35eb1a0c04dc 100644 --- a/drivers/net/wireless/ath/ath11k/reg.c +++ b/drivers/net/wireless/ath/ath11k/reg.c @@ -83,6 +83,7 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) */ if (ar->ab->hw_params.current_cc_support) { memcpy(&set_current_param.alpha2, request->alpha2, 2); + memcpy(&ar->alpha2, &set_current_param.alpha2, 2); ret = ath11k_wmi_send_set_current_country_cmd(ar, &set_current_param); if (ret) ath11k_warn(ar->ab, From 27f26359de9b63131a4990ec341dba969860f2fa Mon Sep 17 00:00:00 2001 From: Xin Ji Date: Tue, 22 Mar 2022 16:02:12 +0800 Subject: [PATCH 00393/11454] drm/bridge: anx7625: Set downstream sink into normal status As downstream sink was set into standby mode while bridge disabled, this patch used for setting downstream sink into normal status while enable bridge. Signed-off-by: Xin Ji Reviewed-by: Pin-Yen Lin Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220322080213.1487134-1-xji@analogixsemi.com --- drivers/gpu/drm/bridge/analogix/anx7625.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index 9a2a19ad4202..dcf3275a00fe 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -924,12 +924,20 @@ static void anx7625_dp_start(struct anx7625_data *ctx) { int ret; struct device *dev = &ctx->client->dev; + u8 data; if (!ctx->display_timing_valid) { DRM_DEV_ERROR(dev, "mipi not set display timing yet.\n"); return; } + dev_dbg(dev, "set downstream sink into normal\n"); + /* Downstream sink enter into normal mode */ + data = 1; + ret = anx7625_aux_trans(ctx, DP_AUX_NATIVE_WRITE, 0x000600, 1, &data); + if (ret < 0) + dev_err(dev, "IO error : set sink into normal mode fail\n"); + /* Disable HDCP */ anx7625_write_and(ctx, ctx->i2c.rx_p1_client, 0xee, 0x9f); From e795df5bbcf27abd6250a0fb9fa8ad7a9748959f Mon Sep 17 00:00:00 2001 From: Andrey Grodzovsky Date: Mon, 28 Mar 2022 09:25:32 -0400 Subject: [PATCH 00394/11454] drm/sched: Fix htmldoc warning. Fixes the warning. Signed-off-by: Andrey Grodzovsky Reported-by: Stephen Rothwell Reviewed-by: Alex Deucher Link: https://patchwork.freedesktop.org/patch/msgid/20220328132532.406572-1-andrey.grodzovsky@amd.com --- include/drm/gpu_scheduler.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h index 944f83ef9f2e..0fca8f38bee4 100644 --- a/include/drm/gpu_scheduler.h +++ b/include/drm/gpu_scheduler.h @@ -270,6 +270,7 @@ struct drm_sched_fence *to_drm_sched_fence(struct dma_fence *f); * @sched: the scheduler instance on which this job is scheduled. * @s_fence: contains the fences for the scheduling of job. * @finish_cb: the callback for the finished fence. + * @work: Helper to reschdeule job kill to different context. * @id: a unique id assigned to each job scheduled on the scheduler. * @karma: increment on every hang caused by this job. If this exceeds the hang * limit of the scheduler then the job is marked guilty and will not From 7e4e0e5c38493b81cef7e2d6420d85bf783eb73d Mon Sep 17 00:00:00 2001 From: Uma Shankar Date: Thu, 24 Mar 2022 17:34:38 +0530 Subject: [PATCH 00395/11454] drm/i915/display: Extend DP HDR support to hsw+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HSW+ platforms are able to send out HDR Metadata SDP DIP packet as GMP. Hence, extending the support for HDR on DP encoders for the same. v2: Limited to non eDP ports on hsw/bdw and removed it for lspcon as it is done separately (suggested by Ville) v3: Added helper and limited eDP restriction to port A (Ville) v4: Dropped some redundant checks (Ville) Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/5389 Cc: Ville Syrjälä Signed-off-by: Uma Shankar Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220324120438.1876445-1-uma.shankar@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 5e6b134aaa15..6b6dc382be56 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4887,6 +4887,25 @@ bool intel_dp_is_port_edp(struct drm_i915_private *dev_priv, enum port port) return intel_bios_is_port_edp(dev_priv, port); } +static bool +has_gamut_metadata_dip(struct drm_i915_private *i915, enum port port) +{ + if (intel_bios_is_lspcon_present(i915, port)) + return false; + + if (DISPLAY_VER(i915) >= 11) + return true; + + if (port == PORT_A) + return false; + + if (IS_HASWELL(i915) || IS_BROADWELL(i915) || + DISPLAY_VER(i915) >= 9) + return true; + + return false; +} + static void intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connector) { @@ -4913,7 +4932,7 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect intel_attach_dp_colorspace_property(connector); } - if (IS_GEMINILAKE(dev_priv) || DISPLAY_VER(dev_priv) >= 11) + if (has_gamut_metadata_dip(dev_priv, port)) drm_object_attach_property(&connector->base, connector->dev->mode_config.hdr_output_metadata_property, 0); From 5d8539d2fbe39ce24e76dfe72b7de7093d3fac6d Mon Sep 17 00:00:00 2001 From: Darren Powell Date: Fri, 4 Mar 2022 23:45:25 -0500 Subject: [PATCH 00396/11454] amdgpu/pm: Add new hwmgr API function "emit_clock_levels" Extend commit 7f36948c92b2 ("amdgpu/pm: Implement new API function "emit" that accepts buffer base and write offset") Add new hwmgr API function "emit_clock_levels" - add member emit_clock_levels to pp_hwmgr_func - Implemented pp_dpm_emit_clock_levels - add pp_dpm_emit_clock_levels to pp_dpm_funcs Signed-off-by: Darren Powell Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- .../gpu/drm/amd/pm/powerplay/amd_powerplay.c | 17 +++++++++++++++++ drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h | 2 ++ 2 files changed, 19 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c index a2da46bf3985..dbed72c1e0c6 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c +++ b/drivers/gpu/drm/amd/pm/powerplay/amd_powerplay.c @@ -671,6 +671,22 @@ static int pp_dpm_force_clock_level(void *handle, return hwmgr->hwmgr_func->force_clock_level(hwmgr, type, mask); } +static int pp_dpm_emit_clock_levels(void *handle, + enum pp_clock_type type, + char *buf, + int *offset) +{ + struct pp_hwmgr *hwmgr = handle; + + if (!hwmgr || !hwmgr->pm_en) + return -EOPNOTSUPP; + + if (!hwmgr->hwmgr_func->emit_clock_levels) + return -ENOENT; + + return hwmgr->hwmgr_func->emit_clock_levels(hwmgr, type, buf, offset); +} + static int pp_dpm_print_clock_levels(void *handle, enum pp_clock_type type, char *buf) { @@ -1535,6 +1551,7 @@ static const struct amd_pm_funcs pp_dpm_funcs = { .get_pp_table = pp_dpm_get_pp_table, .set_pp_table = pp_dpm_set_pp_table, .force_clock_level = pp_dpm_force_clock_level, + .emit_clock_levels = pp_dpm_emit_clock_levels, .print_clock_levels = pp_dpm_print_clock_levels, .get_sclk_od = pp_dpm_get_sclk_od, .set_sclk_od = pp_dpm_set_sclk_od, diff --git a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h index 4f7f2f455301..27f8d0e0e6a8 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h +++ b/drivers/gpu/drm/amd/pm/powerplay/inc/hwmgr.h @@ -313,6 +313,8 @@ struct pp_hwmgr_func { int (*get_max_high_clocks)(struct pp_hwmgr *hwmgr, struct amd_pp_simple_clock_info *clocks); int (*power_off_asic)(struct pp_hwmgr *hwmgr); int (*force_clock_level)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, uint32_t mask); + int (*emit_clock_levels)(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, char *buf, int *offset); int (*print_clock_levels)(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf); int (*powergate_gfx)(struct pp_hwmgr *hwmgr, bool enable); int (*get_sclk_od)(struct pp_hwmgr *hwmgr); From a63e6b83c21424b6ecfca7ecbf605f9af75ae296 Mon Sep 17 00:00:00 2001 From: Darren Powell Date: Mon, 7 Mar 2022 21:40:35 -0500 Subject: [PATCH 00397/11454] amdgpu/pm: Implement emit_clk_levels for vega10 (v1) - implement emit_clk_levels for vega10, based on print_clk_levels, but using sysfs_emit rather than sprintf - modify local int vars to use uint32_t to match arg type of called functions - add return of error codes - refactor OD_XXX cases to return early with -EOPNOTSUPP if !(hwmgr->od_enabled) Signed-off-by: Darren Powell Reviewed-by: Evan Quan Signed-off-by: Alex Deucher --- .../drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c index 37324f2009ca..99bfe5efe171 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/vega10_hwmgr.c @@ -4625,6 +4625,152 @@ static int vega10_get_current_pcie_link_speed_level(struct pp_hwmgr *hwmgr) >> PSWUSP0_PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; } +static int vega10_emit_clock_levels(struct pp_hwmgr *hwmgr, + enum pp_clock_type type, char *buf, int *offset) +{ + struct vega10_hwmgr *data = hwmgr->backend; + struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table); + struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table); + struct vega10_single_dpm_table *soc_table = &(data->dpm_table.soc_table); + struct vega10_single_dpm_table *dcef_table = &(data->dpm_table.dcef_table); + struct vega10_odn_clock_voltage_dependency_table *podn_vdd_dep = NULL; + uint32_t gen_speed, lane_width, current_gen_speed, current_lane_width; + PPTable_t *pptable = &(data->smc_state_table.pp_table); + + uint32_t i, now, count = 0; + int ret = 0; + + switch (type) { + case PP_SCLK: + if (data->registry_data.sclk_dpm_key_disabled) + return -EOPNOTSUPP; + + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentGfxclkIndex, &now); + if (unlikely(ret != 0)) + return ret; + + if (hwmgr->pp_one_vf && + (hwmgr->dpm_level == AMD_DPM_FORCED_LEVEL_PROFILE_PEAK)) + count = 5; + else + count = sclk_table->count; + for (i = 0; i < count; i++) + *offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n", + i, sclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; + case PP_MCLK: + if (data->registry_data.mclk_dpm_key_disabled) + return -EOPNOTSUPP; + + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentUclkIndex, &now); + if (unlikely(ret != 0)) + return ret; + + for (i = 0; i < mclk_table->count; i++) + *offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n", + i, mclk_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; + case PP_SOCCLK: + if (data->registry_data.socclk_dpm_key_disabled) + return -EOPNOTSUPP; + + ret = smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetCurrentSocclkIndex, &now); + if (unlikely(ret != 0)) + return ret; + + for (i = 0; i < soc_table->count; i++) + *offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n", + i, soc_table->dpm_levels[i].value / 100, + (i == now) ? "*" : ""); + break; + case PP_DCEFCLK: + if (data->registry_data.dcefclk_dpm_key_disabled) + return -EOPNOTSUPP; + + ret = smum_send_msg_to_smc_with_parameter(hwmgr, + PPSMC_MSG_GetClockFreqMHz, + CLK_DCEFCLK, &now); + if (unlikely(ret != 0)) + return ret; + + for (i = 0; i < dcef_table->count; i++) + *offset += sysfs_emit_at(buf, *offset, "%d: %uMhz %s\n", + i, dcef_table->dpm_levels[i].value / 100, + (dcef_table->dpm_levels[i].value / 100 == now) ? + "*" : ""); + break; + case PP_PCIE: + current_gen_speed = + vega10_get_current_pcie_link_speed_level(hwmgr); + current_lane_width = + vega10_get_current_pcie_link_width_level(hwmgr); + for (i = 0; i < NUM_LINK_LEVELS; i++) { + gen_speed = pptable->PcieGenSpeed[i]; + lane_width = pptable->PcieLaneCount[i]; + + *offset += sysfs_emit_at(buf, *offset, "%d: %s %s %s\n", i, + (gen_speed == 0) ? "2.5GT/s," : + (gen_speed == 1) ? "5.0GT/s," : + (gen_speed == 2) ? "8.0GT/s," : + (gen_speed == 3) ? "16.0GT/s," : "", + (lane_width == 1) ? "x1" : + (lane_width == 2) ? "x2" : + (lane_width == 3) ? "x4" : + (lane_width == 4) ? "x8" : + (lane_width == 5) ? "x12" : + (lane_width == 6) ? "x16" : "", + (current_gen_speed == gen_speed) && + (current_lane_width == lane_width) ? + "*" : ""); + } + break; + + case OD_SCLK: + if (!hwmgr->od_enabled) + return -EOPNOTSUPP; + + *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_SCLK"); + podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_sclk; + for (i = 0; i < podn_vdd_dep->count; i++) + *offset += sysfs_emit_at(buf, *offset, "%d: %10uMhz %10umV\n", + i, podn_vdd_dep->entries[i].clk / 100, + podn_vdd_dep->entries[i].vddc); + break; + case OD_MCLK: + if (!hwmgr->od_enabled) + return -EOPNOTSUPP; + + *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_MCLK"); + podn_vdd_dep = &data->odn_dpm_table.vdd_dep_on_mclk; + for (i = 0; i < podn_vdd_dep->count; i++) + *offset += sysfs_emit_at(buf, *offset, "%d: %10uMhz %10umV\n", + i, podn_vdd_dep->entries[i].clk/100, + podn_vdd_dep->entries[i].vddc); + break; + case OD_RANGE: + if (!hwmgr->od_enabled) + return -EOPNOTSUPP; + + *offset += sysfs_emit_at(buf, *offset, "%s:\n", "OD_RANGE"); + *offset += sysfs_emit_at(buf, *offset, "SCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.gfx_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.engineClock/100); + *offset += sysfs_emit_at(buf, *offset, "MCLK: %7uMHz %10uMHz\n", + data->golden_dpm_table.mem_table.dpm_levels[0].value/100, + hwmgr->platform_descriptor.overdriveLimit.memoryClock/100); + *offset += sysfs_emit_at(buf, *offset, "VDDC: %7umV %11umV\n", + data->odn_dpm_table.min_vddc, + data->odn_dpm_table.max_vddc); + break; + default: + ret = -ENOENT; + break; + } + return ret; +} + static int vega10_print_clock_levels(struct pp_hwmgr *hwmgr, enum pp_clock_type type, char *buf) { @@ -5559,6 +5705,7 @@ static const struct pp_hwmgr_func vega10_hwmgr_funcs = { .set_watermarks_for_clocks_ranges = vega10_set_watermarks_for_clocks_ranges, .display_clock_voltage_request = vega10_display_clock_voltage_request, .force_clock_level = vega10_force_clock_level, + .emit_clock_levels = vega10_emit_clock_levels, .print_clock_levels = vega10_print_clock_levels, .display_config_changed = vega10_display_configuration_changed_task, .powergate_uvd = vega10_power_gate_uvd, From e3026a057f9675884840979f17cd230e52685792 Mon Sep 17 00:00:00 2001 From: Boyuan Zhang Date: Thu, 24 Mar 2022 12:19:06 -0400 Subject: [PATCH 00398/11454] drm/amdgpu/vcn3: send smu interface type For VCN FW to detect ASIC type, in order to use different mailbox registers. V2: simplify codes and fix format issue. Signed-off-by: Boyuan Zhang Acked-by Huang Rui Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 7 +++++++ drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index e2fde88aaf5e..f06fb7f882e2 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -159,6 +159,7 @@ #define AMDGPU_VCN_MULTI_QUEUE_FLAG (1 << 8) #define AMDGPU_VCN_SW_RING_FLAG (1 << 9) #define AMDGPU_VCN_FW_LOGGING_FLAG (1 << 10) +#define AMDGPU_VCN_SMU_VERSION_INFO_FLAG (1 << 11) #define AMDGPU_VCN_IB_FLAG_DECODE_BUFFER 0x00000001 #define AMDGPU_VCN_CMD_FLAG_MSG_BUFFER 0x00000001 @@ -279,6 +280,11 @@ struct amdgpu_fw_shared_fw_logging { uint32_t size; }; +struct amdgpu_fw_shared_smu_interface_info { + uint8_t smu_interface_type; + uint8_t padding[3]; +}; + struct amdgpu_fw_shared { uint32_t present_flag_0; uint8_t pad[44]; @@ -287,6 +293,7 @@ struct amdgpu_fw_shared { struct amdgpu_fw_shared_multi_queue multi_queue; struct amdgpu_fw_shared_sw_ring sw_ring; struct amdgpu_fw_shared_fw_logging fw_log; + struct amdgpu_fw_shared_smu_interface_info smu_interface_info; }; struct amdgpu_vcn_fwlog { diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index 0d590183328f..e1cca0a10653 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -219,6 +219,11 @@ static int vcn_v3_0_sw_init(void *handle) cpu_to_le32(AMDGPU_VCN_MULTI_QUEUE_FLAG) | cpu_to_le32(AMDGPU_VCN_FW_SHARED_FLAG_0_RB); fw_shared->sw_ring.is_enabled = cpu_to_le32(DEC_SW_RING_ENABLED); + fw_shared->present_flag_0 |= AMDGPU_VCN_SMU_VERSION_INFO_FLAG; + if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 1, 2)) + fw_shared->smu_interface_info.smu_interface_type = 2; + else if (adev->ip_versions[UVD_HWIP][0] == IP_VERSION(3, 1, 1)) + fw_shared->smu_interface_info.smu_interface_type = 1; if (amdgpu_vcnfw_log) amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]); From 8ecad8d66d7f03ccc8fa7b4921d45041e9b77680 Mon Sep 17 00:00:00 2001 From: Lijo Lazar Date: Fri, 25 Mar 2022 13:19:36 +0530 Subject: [PATCH 00399/11454] drm/amd/pm: Check feature support using IP version Instead of ASIC type, use GC and MP1 IP versions for feature support checks. Signed-off-by: Lijo Lazar Reviewed-by: Kevin Wang Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 73 ++++++++++++++++-------------- 1 file changed, 40 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c index 5cd67ddf8495..9ce597ded31d 100644 --- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c @@ -1954,8 +1954,9 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ uint32_t mask, enum amdgpu_device_attr_states *states) { struct device_attribute *dev_attr = &attr->dev_attr; + uint32_t mp1_ver = adev->ip_versions[MP1_HWIP][0]; + uint32_t gc_ver = adev->ip_versions[GC_HWIP][0]; const char *attr_name = dev_attr->attr.name; - enum amd_asic_type asic_type = adev->asic_type; if (!(attr->flags & mask)) { *states = ATTR_STATE_UNSUPPORTED; @@ -1965,53 +1966,55 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ #define DEVICE_ATTR_IS(_name) (!strcmp(attr_name, #_name)) if (DEVICE_ATTR_IS(pp_dpm_socclk)) { - if (asic_type < CHIP_VEGA10) + if (gc_ver < IP_VERSION(9, 0, 0)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_dcefclk)) { - if (asic_type < CHIP_VEGA10 || - asic_type == CHIP_ARCTURUS || - asic_type == CHIP_ALDEBARAN) + if (gc_ver < IP_VERSION(9, 0, 0) || + gc_ver == IP_VERSION(9, 4, 1) || + gc_ver == IP_VERSION(9, 4, 2)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_fclk)) { - if (asic_type < CHIP_VEGA20) + if (mp1_ver < IP_VERSION(10, 0, 0)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_od_clk_voltage)) { *states = ATTR_STATE_UNSUPPORTED; if (amdgpu_dpm_is_overdrive_supported(adev)) *states = ATTR_STATE_SUPPORTED; } else if (DEVICE_ATTR_IS(mem_busy_percent)) { - if (adev->flags & AMD_IS_APU || asic_type == CHIP_VEGA10) + if (adev->flags & AMD_IS_APU || gc_ver == IP_VERSION(9, 0, 1)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pcie_bw)) { /* PCIe Perf counters won't work on APU nodes */ if (adev->flags & AMD_IS_APU) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(unique_id)) { - if (asic_type != CHIP_VEGA10 && - asic_type != CHIP_VEGA20 && - asic_type != CHIP_ARCTURUS && - asic_type != CHIP_ALDEBARAN) + if (gc_ver != IP_VERSION(9, 0, 1) && + gc_ver != IP_VERSION(9, 4, 0) && + gc_ver != IP_VERSION(9, 4, 1) && + gc_ver != IP_VERSION(9, 4, 2)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_features)) { - if (adev->flags & AMD_IS_APU || asic_type < CHIP_VEGA10) + if (adev->flags & AMD_IS_APU || gc_ver < IP_VERSION(9, 0, 0)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(gpu_metrics)) { - if (asic_type < CHIP_VEGA12) + if (gc_ver < IP_VERSION(9, 1, 0)) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_vclk)) { - if (!(asic_type == CHIP_VANGOGH || asic_type == CHIP_SIENNA_CICHLID)) + if (!(gc_ver == IP_VERSION(10, 3, 1) || + gc_ver == IP_VERSION(10, 3, 0))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_dpm_dclk)) { - if (!(asic_type == CHIP_VANGOGH || asic_type == CHIP_SIENNA_CICHLID)) + if (!(gc_ver == IP_VERSION(10, 3, 1) || + gc_ver == IP_VERSION(10, 3, 0))) *states = ATTR_STATE_UNSUPPORTED; } else if (DEVICE_ATTR_IS(pp_power_profile_mode)) { if (amdgpu_dpm_get_power_profile_mode(adev, NULL) == -EOPNOTSUPP) *states = ATTR_STATE_UNSUPPORTED; } - switch (asic_type) { - case CHIP_ARCTURUS: - case CHIP_ALDEBARAN: + switch (gc_ver) { + case IP_VERSION(9, 4, 1): + case IP_VERSION(9, 4, 2): /* the Mi series card does not support standalone mclk/socclk/fclk level setting */ if (DEVICE_ATTR_IS(pp_dpm_mclk) || DEVICE_ATTR_IS(pp_dpm_socclk) || @@ -2026,7 +2029,7 @@ static int default_attr_update(struct amdgpu_device *adev, struct amdgpu_device_ if (DEVICE_ATTR_IS(pp_dpm_dcefclk)) { /* SMU MP1 does not support dcefclk level setting */ - if (asic_type >= CHIP_NAVI10) { + if (gc_ver >= IP_VERSION(10, 0, 0)) { dev_attr->attr.mode &= ~S_IWUGO; dev_attr->store = NULL; } @@ -2864,8 +2867,9 @@ static ssize_t amdgpu_hwmon_show_power_label(struct device *dev, char *buf) { struct amdgpu_device *adev = dev_get_drvdata(dev); + uint32_t gc_ver = adev->ip_versions[GC_HWIP][0]; - if (adev->asic_type == CHIP_VANGOGH) + if (gc_ver == IP_VERSION(10, 3, 1)) return sysfs_emit(buf, "%s\n", to_sensor_dev_attr(attr)->index == PP_PWR_TYPE_FAST ? "fastPPT" : "slowPPT"); @@ -3177,6 +3181,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct device *dev = kobj_to_dev(kobj); struct amdgpu_device *adev = dev_get_drvdata(dev); umode_t effective_mode = attr->mode; + uint32_t gc_ver = adev->ip_versions[GC_HWIP][0]; /* under multi-vf mode, the hwmon attributes are all not supported */ if (amdgpu_sriov_vf(adev) && !amdgpu_sriov_is_pp_one_vf(adev)) @@ -3245,18 +3250,18 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_pwm1_enable.dev_attr.attr)) /* can't manage state */ effective_mode &= ~S_IWUSR; + /* not implemented yet for GC 10.3.1 APUs */ if (((adev->family == AMDGPU_FAMILY_SI) || - ((adev->flags & AMD_IS_APU) && - (adev->asic_type != CHIP_VANGOGH))) && /* not implemented yet */ + ((adev->flags & AMD_IS_APU) && (gc_ver != IP_VERSION(10, 3, 1)))) && (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr || - attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr|| + attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr || attr == &sensor_dev_attr_power1_cap.dev_attr.attr || attr == &sensor_dev_attr_power1_cap_default.dev_attr.attr)) return 0; + /* not implemented yet for APUs having <= GC 9.3.0 */ if (((adev->family == AMDGPU_FAMILY_SI) || - ((adev->flags & AMD_IS_APU) && - (adev->asic_type < CHIP_RENOIR))) && /* not implemented yet */ + ((adev->flags & AMD_IS_APU) && (gc_ver < IP_VERSION(9, 3, 0)))) && (attr == &sensor_dev_attr_power1_average.dev_attr.attr)) return 0; @@ -3294,8 +3299,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, return 0; /* only SOC15 dGPUs support hotspot and mem temperatures */ - if (((adev->flags & AMD_IS_APU) || - adev->asic_type < CHIP_VEGA10) && + if (((adev->flags & AMD_IS_APU) || gc_ver < IP_VERSION(9, 0, 0)) && (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr || attr == &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr || attr == &sensor_dev_attr_temp3_crit.dev_attr.attr || @@ -3310,13 +3314,13 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, return 0; /* only Vangogh has fast PPT limit and power labels */ - if (!(adev->asic_type == CHIP_VANGOGH) && + if (!(gc_ver == IP_VERSION(10, 3, 1)) && (attr == &sensor_dev_attr_power2_average.dev_attr.attr || - attr == &sensor_dev_attr_power2_cap_max.dev_attr.attr || + attr == &sensor_dev_attr_power2_cap_max.dev_attr.attr || attr == &sensor_dev_attr_power2_cap_min.dev_attr.attr || - attr == &sensor_dev_attr_power2_cap.dev_attr.attr || - attr == &sensor_dev_attr_power2_cap_default.dev_attr.attr || - attr == &sensor_dev_attr_power2_label.dev_attr.attr)) + attr == &sensor_dev_attr_power2_cap.dev_attr.attr || + attr == &sensor_dev_attr_power2_cap_default.dev_attr.attr || + attr == &sensor_dev_attr_power2_label.dev_attr.attr)) return 0; return effective_mode; @@ -3421,6 +3425,8 @@ static void amdgpu_debugfs_prints_cpu_info(struct seq_file *m, static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *adev) { + uint32_t mp1_ver = adev->ip_versions[MP1_HWIP][0]; + uint32_t gc_ver = adev->ip_versions[GC_HWIP][0]; uint32_t value; uint64_t value64 = 0; uint32_t query = 0; @@ -3467,7 +3473,8 @@ static int amdgpu_debugfs_pm_info_pp(struct seq_file *m, struct amdgpu_device *a if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_ENABLED_SMC_FEATURES_MASK, (void *)&value64, &size)) seq_printf(m, "SMC Feature Mask: 0x%016llx\n", value64); - if (adev->asic_type > CHIP_VEGA20) { + /* ASICs greater than CHIP_VEGA20 supports these sensors */ + if (gc_ver != IP_VERSION(9, 4, 0) && mp1_ver > IP_VERSION(9, 0, 0)) { /* VCN clocks */ if (!amdgpu_dpm_read_sensor(adev, AMDGPU_PP_SENSOR_VCN_POWER_STATE, (void *)&value, &size)) { if (!value) { From 9f07550b3c8a79cbb996a368f699c9eb619d8322 Mon Sep 17 00:00:00 2001 From: Sean Paul Date: Fri, 25 Mar 2022 00:06:19 +0000 Subject: [PATCH 00400/11454] drm/amdgpu: Re-classify some log messages in commit path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ATOMIC and DRIVER log categories do not typically contain per-frame log messages. This patch re-classifies some messages in amd to chattier categories to keep ATOMIC/DRIVER quiet. Acked-by: Christian König Reviewed-by: Harry Wentland Signed-off-by: Sean Paul Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_display.c | 5 +++-- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index ee21b242ccf6..787724166952 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -118,8 +118,9 @@ static void amdgpu_display_flip_work_func(struct work_struct *__work) spin_unlock_irqrestore(&crtc->dev->event_lock, flags); - DRM_DEBUG_DRIVER("crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: %p,\n", - amdgpu_crtc->crtc_id, amdgpu_crtc, work); + drm_dbg_vbl(adev_to_drm(adev), + "crtc:%d[%p], pflip_stat:AMDGPU_FLIP_SUBMITTED, work: %p,\n", + amdgpu_crtc->crtc_id, amdgpu_crtc, work); } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index b30656959fd8..45d130f86114 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -9248,7 +9248,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, &bundle->flip_addrs[planes_count].address, afb->tmz_surface, false); - DRM_DEBUG_ATOMIC("plane: id=%d dcc_en=%d\n", + drm_dbg_state(state->dev, "plane: id=%d dcc_en=%d\n", new_plane_state->plane->index, bundle->plane_infos[planes_count].dcc.enable); @@ -9282,7 +9282,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, dc_plane, bundle->flip_addrs[planes_count].flip_timestamp_in_us); - DRM_DEBUG_ATOMIC("%s Flipping to hi: 0x%x, low: 0x%x\n", + drm_dbg_state(state->dev, "%s Flipping to hi: 0x%x, low: 0x%x\n", __func__, bundle->flip_addrs[planes_count].address.grph.addr.high_part, bundle->flip_addrs[planes_count].address.grph.addr.low_part); @@ -9624,7 +9624,7 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state) dm_new_crtc_state = to_dm_crtc_state(new_crtc_state); dm_old_crtc_state = to_dm_crtc_state(old_crtc_state); - DRM_DEBUG_ATOMIC( + drm_dbg_state(state->dev, "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", @@ -10328,7 +10328,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, if (!drm_atomic_crtc_needs_modeset(new_crtc_state)) goto skip_modeset; - DRM_DEBUG_ATOMIC( + drm_dbg_state(state->dev, "amdgpu_crtc id:%d crtc_state_flags: enable:%d, active:%d, " "planes_changed:%d, mode_changed:%d,active_changed:%d," "connectors_changed:%d\n", From 425d7a87e54ee358f580eaf10cf28dc95f7121c1 Mon Sep 17 00:00:00 2001 From: tiancyin Date: Sun, 27 Mar 2022 19:07:13 +0800 Subject: [PATCH 00401/11454] drm/amd/vcn: fix an error msg on vcn 3.0 Some video card has more than one vcn instance, passing 0 to vcn_v3_0_pause_dpg_mode is incorrect. Error msg: Register(1) [mmUVD_POWER_STATUS] failed to reach value 0x00000001 != 0x00000002 Reviewed-by: James Zhu Signed-off-by: tiancyin Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c index e1cca0a10653..cb5f0a12333f 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c @@ -1488,7 +1488,7 @@ static int vcn_v3_0_stop_dpg_mode(struct amdgpu_device *adev, int inst_idx) struct dpg_pause_state state = {.fw_based = VCN_DPG_STATE__UNPAUSE}; uint32_t tmp; - vcn_v3_0_pause_dpg_mode(adev, 0, &state); + vcn_v3_0_pause_dpg_mode(adev, inst_idx, &state); /* Wait for power status to be 1 */ SOC15_WAIT_ON_RREG(VCN, inst_idx, mmUVD_POWER_STATUS, 1, From a3d63c62bdf06c5a3f8a71c207f13b26fc6030f5 Mon Sep 17 00:00:00 2001 From: Mohammad Zafar Ziya Date: Thu, 17 Mar 2022 09:45:42 +0800 Subject: [PATCH 00402/11454] drm/amdgpu: Add vcn and jpeg ras support flag Add vcn and jpeg ras support options V2: vcn and jpeg ras flag enabled for aldebaran asic only V3: vcn and jpeg ras flag disabled for error counter query Generic poison query interface added VCN and JPEG ras enabled based on IP version check V4: vcn and jpeg ras flag moved under ecc flag for dGPU Signed-off-by: Mohammad Zafar Ziya Reviewed-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c | 9 +++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c index 424c22a841f4..ec709997c9c7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c @@ -66,6 +66,8 @@ const char *ras_block_string[] = { "mp1", "fuse", "mca", + "vcn", + "jpeg", }; const char *ras_mca_block_string[] = { @@ -2205,6 +2207,13 @@ static void amdgpu_ras_check_supported(struct amdgpu_device *adev) dev_info(adev->dev, "SRAM ECC is active.\n"); adev->ras_hw_enabled |= ~(1 << AMDGPU_RAS_BLOCK__UMC | 1 << AMDGPU_RAS_BLOCK__DF); + + if (adev->ip_versions[VCN_HWIP][0] == IP_VERSION(2, 6, 0)) + adev->ras_hw_enabled |= (1 << AMDGPU_RAS_BLOCK__VCN | + 1 << AMDGPU_RAS_BLOCK__JPEG); + else + adev->ras_hw_enabled &= ~(1 << AMDGPU_RAS_BLOCK__VCN | + 1 << AMDGPU_RAS_BLOCK__JPEG); } else { dev_info(adev->dev, "SRAM ECC is not presented.\n"); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 9314fde81e68..1e1a3b736859 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -49,6 +49,8 @@ enum amdgpu_ras_block { AMDGPU_RAS_BLOCK__MP1, AMDGPU_RAS_BLOCK__FUSE, AMDGPU_RAS_BLOCK__MCA, + AMDGPU_RAS_BLOCK__VCN, + AMDGPU_RAS_BLOCK__JPEG, AMDGPU_RAS_BLOCK__LAST }; From 60fce7417fd6c0fef34ca1661bb17d63cf6db30b Mon Sep 17 00:00:00 2001 From: Mohammad Zafar Ziya Date: Thu, 17 Mar 2022 09:49:19 +0800 Subject: [PATCH 00403/11454] drm/amdgpu/vcn: Add vcn ras support VCN block ras feature support addition V2: default ras callback removed Signed-off-by: Mohammad Zafar Ziya Reviewed-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h index f06fb7f882e2..fb39065a96bd 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h @@ -24,6 +24,8 @@ #ifndef __AMDGPU_VCN_H__ #define __AMDGPU_VCN_H__ +#include "amdgpu_ras.h" + #define AMDGPU_VCN_STACK_SIZE (128*1024) #define AMDGPU_VCN_CONTEXT_SIZE (512*1024) @@ -233,6 +235,10 @@ struct amdgpu_vcn_inst { struct amdgpu_vcn_fw_shared fw_shared; }; +struct amdgpu_vcn_ras { + struct amdgpu_ras_block_object ras_block; +}; + struct amdgpu_vcn { unsigned fw_version; struct delayed_work idle_work; @@ -252,6 +258,9 @@ struct amdgpu_vcn { unsigned harvest_config; int (*pause_dpg_mode)(struct amdgpu_device *adev, int inst_idx, struct dpg_pause_state *new_state); + + struct ras_common_if *ras_if; + struct amdgpu_vcn_ras *ras; }; struct amdgpu_fw_shared_rb_ptrs_struct { From edd08fa137d39b1100296049c86c514682dbf378 Mon Sep 17 00:00:00 2001 From: Mohammad Zafar Ziya Date: Thu, 17 Mar 2022 09:53:03 +0800 Subject: [PATCH 00404/11454] drm/amdgpu/jpeg: Add jpeg block ras support Ras support addition for JPEG block V2: removed default callback Signed-off-by: Mohammad Zafar Ziya Reviewed-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h index 55fbff2be761..b6c7fb00e05a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.h @@ -24,6 +24,8 @@ #ifndef __AMDGPU_JPEG_H__ #define __AMDGPU_JPEG_H__ +#include "amdgpu_ras.h" + #define AMDGPU_MAX_JPEG_INSTANCES 2 #define AMDGPU_JPEG_HARVEST_JPEG0 (1 << 0) @@ -39,6 +41,10 @@ struct amdgpu_jpeg_inst { struct amdgpu_jpeg_reg external; }; +struct amdgpu_jpeg_ras { + struct amdgpu_ras_block_object ras_block; +}; + struct amdgpu_jpeg { uint8_t num_jpeg_inst; struct amdgpu_jpeg_inst inst[AMDGPU_MAX_JPEG_INSTANCES]; @@ -48,6 +54,8 @@ struct amdgpu_jpeg { enum amd_powergating_state cur_state; struct mutex jpeg_pg_lock; atomic_t total_submission_cnt; + struct ras_common_if *ras_if; + struct amdgpu_jpeg_ras *ras; }; int amdgpu_jpeg_sw_init(struct amdgpu_device *adev); From f0a339a8c0963abc80640975585df469e27ba3df Mon Sep 17 00:00:00 2001 From: Mohammad Zafar Ziya Date: Wed, 23 Mar 2022 10:54:15 +0800 Subject: [PATCH 00405/11454] drm/amdgpu/vcn: Add vcn and jpeg ver 2.6 ras register definition Adding vcn and jpeg ver 2.6 ras register definition Signed-off-by: Mohammad Zafar Ziya Reviewed-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- .../amd/include/asic_reg/vcn/vcn_2_5_offset.h | 13 ++++++++++ .../include/asic_reg/vcn/vcn_2_5_sh_mask.h | 24 +++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_offset.h b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_offset.h index 90350f46a0c4..363d2139cea2 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_offset.h +++ b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_offset.h @@ -988,4 +988,17 @@ #define mmMDM_WIG_PIPE_BUSY_BASE_IDX 1 +/* VCN 2_6_0 regs */ +#define mmUVD_RAS_VCPU_VCODEC_STATUS 0x0057 +#define mmUVD_RAS_VCPU_VCODEC_STATUS_BASE_IDX 1 +#define mmUVD_RAS_MMSCH_FATAL_ERROR 0x0058 +#define mmUVD_RAS_MMSCH_FATAL_ERROR_BASE_IDX 1 + + +/* JPEG 2_6_0 regs */ +#define mmUVD_RAS_JPEG0_STATUS 0x0059 +#define mmUVD_RAS_JPEG0_STATUS_BASE_IDX 1 +#define mmUVD_RAS_JPEG1_STATUS 0x005a +#define mmUVD_RAS_JPEG1_STATUS_BASE_IDX 1 + #endif diff --git a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_sh_mask.h index c41c59c30006..8de883b76d90 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_sh_mask.h +++ b/drivers/gpu/drm/amd/include/asic_reg/vcn/vcn_2_5_sh_mask.h @@ -3606,4 +3606,28 @@ #define UVD_LMI_CRC3__CRC32_MASK 0xFFFFFFFFL +/* VCN 2_6_0 UVD_RAS_VCPU_VCODEC_STATUS */ +#define UVD_RAS_VCPU_VCODEC_STATUS__POISONED_VF__SHIFT 0x0 +#define UVD_RAS_VCPU_VCODEC_STATUS__POISONED_PF__SHIFT 0x1f +#define UVD_RAS_VCPU_VCODEC_STATUS__POISONED_VF_MASK 0x7FFFFFFFL +#define UVD_RAS_VCPU_VCODEC_STATUS__POISONED_PF_MASK 0x80000000L + +/* VCN 2_6_0 UVD_RAS_MMSCH_FATAL_ERROR */ +#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_VF__SHIFT 0x0 +#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_PF__SHIFT 0x1f +#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_VF_MASK 0x7FFFFFFFL +#define UVD_RAS_MMSCH_FATAL_ERROR__POISONED_PF_MASK 0x80000000L + +/* JPEG 2_6_0 UVD_RAS_JPEG0_STATUS */ +#define UVD_RAS_JPEG0_STATUS__POISONED_VF__SHIFT 0x0 +#define UVD_RAS_JPEG0_STATUS__POISONED_PF__SHIFT 0x1f +#define UVD_RAS_JPEG0_STATUS__POISONED_VF_MASK 0x7FFFFFFFL +#define UVD_RAS_JPEG0_STATUS__POISONED_PF_MASK 0x80000000L + +/* JPEG 2_6_0 UVD_RAS_JPEG1_STATUS */ +#define UVD_RAS_JPEG1_STATUS__POISONED_VF__SHIFT 0x0 +#define UVD_RAS_JPEG1_STATUS__POISONED_PF__SHIFT 0x1f +#define UVD_RAS_JPEG1_STATUS__POISONED_VF_MASK 0x7FFFFFFFL +#define UVD_RAS_JPEG1_STATUS__POISONED_PF_MASK 0x80000000L + #endif From c543dcbe4237e03b23fa40e0fba979cfd8514954 Mon Sep 17 00:00:00 2001 From: Mohammad Zafar Ziya Date: Wed, 23 Mar 2022 12:06:49 +0800 Subject: [PATCH 00406/11454] drm/amdgpu/vcn: Add VCN ras error query support RAS error query support addition for VCN 2.6 V2: removed unused option and corrected comment format Moved the register definition under header file V3: poison query status check added. Removed error query interface V4: MMSCH poison check option removed, return true/false refactored. Signed-off-by: Mohammad Zafar Ziya Reviewed-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h | 1 + drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 71 +++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/vcn_v2_5.h | 6 +++ 3 files changed, 78 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h index 1e1a3b736859..606df8869b89 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.h @@ -508,6 +508,7 @@ struct amdgpu_ras_block_hw_ops { void (*query_ras_error_address)(struct amdgpu_device *adev, void *ras_error_status); void (*reset_ras_error_count)(struct amdgpu_device *adev); void (*reset_ras_error_status)(struct amdgpu_device *adev); + bool (*query_poison_status)(struct amdgpu_device *adev); }; /* work flow diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c index 1bf672966a62..3e1de8c8b372 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c @@ -31,6 +31,7 @@ #include "soc15d.h" #include "vcn_v2_0.h" #include "mmsch_v1_0.h" +#include "vcn_v2_5.h" #include "vcn/vcn_2_5_offset.h" #include "vcn/vcn_2_5_sh_mask.h" @@ -59,6 +60,7 @@ static int vcn_v2_5_set_powergating_state(void *handle, static int vcn_v2_5_pause_dpg_mode(struct amdgpu_device *adev, int inst_idx, struct dpg_pause_state *new_state); static int vcn_v2_5_sriov_start(struct amdgpu_device *adev); +static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev); static int amdgpu_ih_clientid_vcns[] = { SOC15_IH_CLIENTID_VCN, @@ -100,6 +102,7 @@ static int vcn_v2_5_early_init(void *handle) vcn_v2_5_set_dec_ring_funcs(adev); vcn_v2_5_set_enc_ring_funcs(adev); vcn_v2_5_set_irq_funcs(adev); + vcn_v2_5_set_ras_funcs(adev); return 0; } @@ -1932,3 +1935,71 @@ const struct amdgpu_ip_block_version vcn_v2_6_ip_block = .rev = 0, .funcs = &vcn_v2_6_ip_funcs, }; + +static uint32_t vcn_v2_6_query_poison_by_instance(struct amdgpu_device *adev, + uint32_t instance, uint32_t sub_block) +{ + uint32_t poison_stat = 0, reg_value = 0; + + switch (sub_block) { + case AMDGPU_VCN_V2_6_VCPU_VCODEC: + reg_value = RREG32_SOC15(VCN, instance, mmUVD_RAS_VCPU_VCODEC_STATUS); + poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_VCPU_VCODEC_STATUS, POISONED_PF); + break; + default: + break; + }; + + if (poison_stat) + dev_info(adev->dev, "Poison detected in VCN%d, sub_block%d\n", + instance, sub_block); + + return poison_stat; +} + +static bool vcn_v2_6_query_poison_status(struct amdgpu_device *adev) +{ + uint32_t inst, sub; + uint32_t poison_stat = 0; + + for (inst = 0; inst < adev->vcn.num_vcn_inst; inst++) + for (sub = 0; sub < AMDGPU_VCN_V2_6_MAX_SUB_BLOCK; sub++) + poison_stat += + vcn_v2_6_query_poison_by_instance(adev, inst, sub); + + return !!poison_stat; +} + +const struct amdgpu_ras_block_hw_ops vcn_v2_6_ras_hw_ops = { + .query_poison_status = vcn_v2_6_query_poison_status, +}; + +static struct amdgpu_vcn_ras vcn_v2_6_ras = { + .ras_block = { + .hw_ops = &vcn_v2_6_ras_hw_ops, + }, +}; + +static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev) +{ + switch (adev->ip_versions[VCN_HWIP][0]) { + case IP_VERSION(2, 6, 0): + adev->vcn.ras = &vcn_v2_6_ras; + break; + default: + break; + } + + if (adev->vcn.ras) { + amdgpu_ras_register_ras_block(adev, &adev->vcn.ras->ras_block); + + strcpy(adev->vcn.ras->ras_block.ras_comm.name, "vcn"); + adev->vcn.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__VCN; + adev->vcn.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON; + adev->vcn.ras_if = &adev->vcn.ras->ras_block.ras_comm; + + /* If don't define special ras_late_init function, use default ras_late_init */ + if (!adev->vcn.ras->ras_block.ras_late_init) + adev->vcn.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init; + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.h b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.h index e72f799ed0fd..1c19af74e4fd 100644 --- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.h +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.h @@ -24,6 +24,12 @@ #ifndef __VCN_V2_5_H__ #define __VCN_V2_5_H__ +enum amdgpu_vcn_v2_6_sub_block { + AMDGPU_VCN_V2_6_VCPU_VCODEC = 0, + + AMDGPU_VCN_V2_6_MAX_SUB_BLOCK, +}; + extern const struct amdgpu_ip_block_version vcn_v2_5_ip_block; extern const struct amdgpu_ip_block_version vcn_v2_6_ip_block; From 749831acb1f6bf5837aeeec93b96da1d91534775 Mon Sep 17 00:00:00 2001 From: Mohammad Zafar Ziya Date: Wed, 23 Mar 2022 12:10:00 +0800 Subject: [PATCH 00407/11454] drm/amdgpu/jpeg: Add jpeg ras error query support RAS error query support addition for JPEG 2.6 V2: removed unused options and corrected comment format. Moved register definition to header file. V3: poison query status check added. Removed the error query support V4: Return statement refactored. Signed-off-by: Mohammad Zafar Ziya Reviewed-by: Hawking Zhang Reviewed-by: Tao Zhou Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 74 ++++++++++++++++++++++++++ drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.h | 7 +++ 2 files changed, 81 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c index a29c86617fb5..8c3227d0b8b4 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c @@ -26,6 +26,7 @@ #include "soc15.h" #include "soc15d.h" #include "jpeg_v2_0.h" +#include "jpeg_v2_5.h" #include "vcn/vcn_2_5_offset.h" #include "vcn/vcn_2_5_sh_mask.h" @@ -39,6 +40,7 @@ static void jpeg_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev); static void jpeg_v2_5_set_irq_funcs(struct amdgpu_device *adev); static int jpeg_v2_5_set_powergating_state(void *handle, enum amd_powergating_state state); +static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev); static int amdgpu_ih_clientid_jpeg[] = { SOC15_IH_CLIENTID_VCN, @@ -70,6 +72,7 @@ static int jpeg_v2_5_early_init(void *handle) jpeg_v2_5_set_dec_ring_funcs(adev); jpeg_v2_5_set_irq_funcs(adev); + jpeg_v2_5_set_ras_funcs(adev); return 0; } @@ -730,3 +733,74 @@ const struct amdgpu_ip_block_version jpeg_v2_6_ip_block = .rev = 0, .funcs = &jpeg_v2_6_ip_funcs, }; + +static uint32_t jpeg_v2_6_query_poison_by_instance(struct amdgpu_device *adev, + uint32_t instance, uint32_t sub_block) +{ + uint32_t poison_stat = 0, reg_value = 0; + + switch (sub_block) { + case AMDGPU_JPEG_V2_6_JPEG0: + reg_value = RREG32_SOC15(JPEG, instance, mmUVD_RAS_JPEG0_STATUS); + poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG0_STATUS, POISONED_PF); + break; + case AMDGPU_JPEG_V2_6_JPEG1: + reg_value = RREG32_SOC15(JPEG, instance, mmUVD_RAS_JPEG1_STATUS); + poison_stat = REG_GET_FIELD(reg_value, UVD_RAS_JPEG1_STATUS, POISONED_PF); + break; + default: + break; + } + + if (poison_stat) + dev_info(adev->dev, "Poison detected in JPEG%d sub_block%d\n", + instance, sub_block); + + return poison_stat; +} + +static bool jpeg_v2_6_query_ras_poison_status(struct amdgpu_device *adev) +{ + uint32_t inst = 0, sub = 0, poison_stat = 0; + + for (inst = 0; inst < adev->jpeg.num_jpeg_inst; inst++) + for (sub = 0; sub < AMDGPU_JPEG_V2_6_MAX_SUB_BLOCK; sub++) + poison_stat += + jpeg_v2_6_query_poison_by_instance(adev, inst, sub); + + return !!poison_stat; +} + +const struct amdgpu_ras_block_hw_ops jpeg_v2_6_ras_hw_ops = { + .query_poison_status = jpeg_v2_6_query_ras_poison_status, +}; + +static struct amdgpu_jpeg_ras jpeg_v2_6_ras = { + .ras_block = { + .hw_ops = &jpeg_v2_6_ras_hw_ops, + }, +}; + +static void jpeg_v2_5_set_ras_funcs(struct amdgpu_device *adev) +{ + switch (adev->ip_versions[JPEG_HWIP][0]) { + case IP_VERSION(2, 6, 0): + adev->jpeg.ras = &jpeg_v2_6_ras; + break; + default: + break; + } + + if (adev->jpeg.ras) { + amdgpu_ras_register_ras_block(adev, &adev->jpeg.ras->ras_block); + + strcpy(adev->jpeg.ras->ras_block.ras_comm.name, "jpeg"); + adev->jpeg.ras->ras_block.ras_comm.block = AMDGPU_RAS_BLOCK__JPEG; + adev->jpeg.ras->ras_block.ras_comm.type = AMDGPU_RAS_ERROR__POISON; + adev->jpeg.ras_if = &adev->jpeg.ras->ras_block.ras_comm; + + /* If don't define special ras_late_init function, use default ras_late_init */ + if (!adev->jpeg.ras->ras_block.ras_late_init) + adev->jpeg.ras->ras_block.ras_late_init = amdgpu_ras_block_late_init; + } +} diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.h b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.h index 3b0aa29b9879..1e858c6cdf13 100644 --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.h +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.h @@ -24,6 +24,13 @@ #ifndef __JPEG_V2_5_H__ #define __JPEG_V2_5_H__ +enum amdgpu_jpeg_v2_6_sub_block { + AMDGPU_JPEG_V2_6_JPEG0 = 0, + AMDGPU_JPEG_V2_6_JPEG1, + + AMDGPU_JPEG_V2_6_MAX_SUB_BLOCK, +}; + extern const struct amdgpu_ip_block_version jpeg_v2_5_ip_block; extern const struct amdgpu_ip_block_version jpeg_v2_6_ip_block; From 6a9b028994025f5033f10d1da30b29dfdc713384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 16 Jul 2021 14:00:10 +0200 Subject: [PATCH 00408/11454] drm/ttm: move the LRU into resource handling v4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way we finally fix the problem that new resource are not immediately evict-able after allocation. That has caused numerous problems including OOM on GDS handling and not being able to use TTM as general resource manager. v2: stop assuming in ttm_resource_fini that res->bo is still valid. v3: cleanup kerneldoc, add more lockdep annotation v4: consistently use res->num_pages Signed-off-by: Christian König Tested-by: Bas Nieuwenhuizen Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220321132601.2161-1-christian.koenig@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 8 +- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 115 ++------------------- drivers/gpu/drm/ttm/ttm_bo_util.c | 1 - drivers/gpu/drm/ttm/ttm_device.c | 68 ++++++------- drivers/gpu/drm/ttm/ttm_resource.c | 126 ++++++++++++++++++++++-- include/drm/ttm/ttm_bo_api.h | 16 --- include/drm/ttm/ttm_bo_driver.h | 29 +----- include/drm/ttm/ttm_resource.h | 40 ++++++++ 9 files changed, 206 insertions(+), 199 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index b37fc7d7d2c7..f2ce5a0defd9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -683,12 +683,12 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev, if (vm->bulk_moveable) { spin_lock(&adev->mman.bdev.lru_lock); - ttm_bo_bulk_move_lru_tail(&vm->lru_bulk_move); + ttm_lru_bulk_move_tail(&vm->lru_bulk_move); spin_unlock(&adev->mman.bdev.lru_lock); return; } - memset(&vm->lru_bulk_move, 0, sizeof(vm->lru_bulk_move)); + ttm_lru_bulk_move_init(&vm->lru_bulk_move); spin_lock(&adev->mman.bdev.lru_lock); list_for_each_entry(bo_base, &vm->idle, vm_status) { @@ -698,11 +698,9 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev, if (!bo->parent) continue; - ttm_bo_move_to_lru_tail(&bo->tbo, bo->tbo.resource, - &vm->lru_bulk_move); + ttm_bo_move_to_lru_tail(&bo->tbo, &vm->lru_bulk_move); if (shadow) ttm_bo_move_to_lru_tail(&shadow->tbo, - shadow->tbo.resource, &vm->lru_bulk_move); } spin_unlock(&adev->mman.bdev.lru_lock); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index de3fe79b665a..582e8dc9bc8c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -849,7 +849,7 @@ void i915_ttm_adjust_lru(struct drm_i915_gem_object *obj) bo->priority = I915_TTM_PRIO_NO_PAGES; } - ttm_bo_move_to_lru_tail(bo, bo->resource, NULL); + ttm_bo_move_to_lru_tail(bo, NULL); spin_unlock(&bo->bdev->lru_lock); } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index db3dc7ef5382..cb0fa932d495 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -69,108 +69,16 @@ static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, } } -static inline void ttm_bo_move_to_pinned(struct ttm_buffer_object *bo) -{ - struct ttm_device *bdev = bo->bdev; - - list_move_tail(&bo->lru, &bdev->pinned); - - if (bdev->funcs->del_from_lru_notify) - bdev->funcs->del_from_lru_notify(bo); -} - -static inline void ttm_bo_del_from_lru(struct ttm_buffer_object *bo) -{ - struct ttm_device *bdev = bo->bdev; - - list_del_init(&bo->lru); - - if (bdev->funcs->del_from_lru_notify) - bdev->funcs->del_from_lru_notify(bo); -} - -static void ttm_bo_bulk_move_set_pos(struct ttm_lru_bulk_move_pos *pos, - struct ttm_buffer_object *bo) -{ - if (!pos->first) - pos->first = bo; - pos->last = bo; -} - void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo, - struct ttm_resource *mem, struct ttm_lru_bulk_move *bulk) { - struct ttm_device *bdev = bo->bdev; - struct ttm_resource_manager *man; + dma_resv_assert_held(bo->base.resv); - if (!bo->deleted) - dma_resv_assert_held(bo->base.resv); - - if (bo->pin_count) { - ttm_bo_move_to_pinned(bo); - return; - } - - if (!mem) - return; - - man = ttm_manager_type(bdev, mem->mem_type); - list_move_tail(&bo->lru, &man->lru[bo->priority]); - - if (bdev->funcs->del_from_lru_notify) - bdev->funcs->del_from_lru_notify(bo); - - if (bulk && !bo->pin_count) { - switch (bo->resource->mem_type) { - case TTM_PL_TT: - ttm_bo_bulk_move_set_pos(&bulk->tt[bo->priority], bo); - break; - - case TTM_PL_VRAM: - ttm_bo_bulk_move_set_pos(&bulk->vram[bo->priority], bo); - break; - } - } + if (bo->resource) + ttm_resource_move_to_lru_tail(bo->resource, bulk); } EXPORT_SYMBOL(ttm_bo_move_to_lru_tail); -void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) -{ - unsigned i; - - for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { - struct ttm_lru_bulk_move_pos *pos = &bulk->tt[i]; - struct ttm_resource_manager *man; - - if (!pos->first) - continue; - - dma_resv_assert_held(pos->first->base.resv); - dma_resv_assert_held(pos->last->base.resv); - - man = ttm_manager_type(pos->first->bdev, TTM_PL_TT); - list_bulk_move_tail(&man->lru[i], &pos->first->lru, - &pos->last->lru); - } - - for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { - struct ttm_lru_bulk_move_pos *pos = &bulk->vram[i]; - struct ttm_resource_manager *man; - - if (!pos->first) - continue; - - dma_resv_assert_held(pos->first->base.resv); - dma_resv_assert_held(pos->last->base.resv); - - man = ttm_manager_type(pos->first->bdev, TTM_PL_VRAM); - list_bulk_move_tail(&man->lru[i], &pos->first->lru, - &pos->last->lru); - } -} -EXPORT_SYMBOL(ttm_bo_bulk_move_lru_tail); - static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, struct ttm_resource *mem, bool evict, struct ttm_operation_ctx *ctx, @@ -344,7 +252,6 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, return ret; } - ttm_bo_move_to_pinned(bo); list_del_init(&bo->ddestroy); spin_unlock(&bo->bdev->lru_lock); ttm_bo_cleanup_memtype_use(bo); @@ -445,7 +352,7 @@ static void ttm_bo_release(struct kref *kref) */ if (bo->pin_count) { bo->pin_count = 0; - ttm_bo_move_to_lru_tail(bo, bo->resource, NULL); + ttm_resource_move_to_lru_tail(bo->resource, NULL); } kref_init(&bo->kref); @@ -458,7 +365,6 @@ static void ttm_bo_release(struct kref *kref) } spin_lock(&bo->bdev->lru_lock); - ttm_bo_del_from_lru(bo); list_del(&bo->ddestroy); spin_unlock(&bo->bdev->lru_lock); @@ -673,15 +579,17 @@ int ttm_mem_evict_first(struct ttm_device *bdev, struct ww_acquire_ctx *ticket) { struct ttm_buffer_object *bo = NULL, *busy_bo = NULL; + struct ttm_resource *res; bool locked = false; unsigned i; int ret; spin_lock(&bdev->lru_lock); for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { - list_for_each_entry(bo, &man->lru[i], lru) { + list_for_each_entry(res, &man->lru[i], lru) { bool busy; + bo = res->bo; if (!ttm_bo_evict_swapout_allowable(bo, ctx, place, &locked, &busy)) { if (busy && !busy_bo && ticket != @@ -699,7 +607,7 @@ int ttm_mem_evict_first(struct ttm_device *bdev, } /* If the inner loop terminated early, we have our candidate */ - if (&bo->lru != &man->lru[i]) + if (&res->lru != &man->lru[i]) break; bo = NULL; @@ -875,9 +783,6 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, } error: - if (bo->resource->mem_type == TTM_PL_SYSTEM && !bo->pin_count) - ttm_bo_move_to_lru_tail_unlocked(bo); - return ret; } EXPORT_SYMBOL(ttm_bo_mem_space); @@ -971,7 +876,6 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, bo->destroy = destroy ? destroy : ttm_bo_default_destroy; kref_init(&bo->kref); - INIT_LIST_HEAD(&bo->lru); INIT_LIST_HEAD(&bo->ddestroy); bo->bdev = bdev; bo->type = type; @@ -1021,8 +925,6 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, return ret; } - ttm_bo_move_to_lru_tail_unlocked(bo); - return ret; } EXPORT_SYMBOL(ttm_bo_init_reserved); @@ -1123,7 +1025,6 @@ int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, return ret == -EBUSY ? -ENOSPC : ret; } - ttm_bo_move_to_pinned(bo); /* TODO: Cleanup the locking */ spin_unlock(&bo->bdev->lru_lock); diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 544a84fa6589..0163e92b57af 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -231,7 +231,6 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, atomic_inc(&ttm_glob.bo_count); INIT_LIST_HEAD(&fbo->base.ddestroy); - INIT_LIST_HEAD(&fbo->base.lru); fbo->base.moving = NULL; drm_vma_node_reset(&fbo->base.base.vma_node); diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index be24bb6cefd0..ba35887147ba 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -144,6 +144,7 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, { struct ttm_resource_manager *man; struct ttm_buffer_object *bo; + struct ttm_resource *res; unsigned i, j; int ret; @@ -154,8 +155,11 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, continue; for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) { - list_for_each_entry(bo, &man->lru[j], lru) { - uint32_t num_pages = PFN_UP(bo->base.size); + list_for_each_entry(res, &man->lru[j], lru) { + uint32_t num_pages; + + bo = res->bo; + num_pages = PFN_UP(bo->base.size); ret = ttm_bo_swapout(bo, ctx, gfp_flags); /* ttm_bo_swapout has dropped the lru_lock */ @@ -259,49 +263,45 @@ void ttm_device_fini(struct ttm_device *bdev) } EXPORT_SYMBOL(ttm_device_fini); +static void ttm_device_clear_lru_dma_mappings(struct ttm_device *bdev, + struct list_head *list) +{ + struct ttm_resource *res; + + spin_lock(&bdev->lru_lock); + while ((res = list_first_entry_or_null(list, typeof(*res), lru))) { + struct ttm_buffer_object *bo = res->bo; + + /* Take ref against racing releases once lru_lock is unlocked */ + if (!ttm_bo_get_unless_zero(bo)) + continue; + + list_del_init(&res->lru); + spin_unlock(&bdev->lru_lock); + + if (bo->ttm) + ttm_tt_unpopulate(bo->bdev, bo->ttm); + + ttm_bo_put(bo); + spin_lock(&bdev->lru_lock); + } + spin_unlock(&bdev->lru_lock); +} + void ttm_device_clear_dma_mappings(struct ttm_device *bdev) { struct ttm_resource_manager *man; - struct ttm_buffer_object *bo; unsigned int i, j; - spin_lock(&bdev->lru_lock); - while (!list_empty(&bdev->pinned)) { - bo = list_first_entry(&bdev->pinned, struct ttm_buffer_object, lru); - /* Take ref against racing releases once lru_lock is unlocked */ - if (ttm_bo_get_unless_zero(bo)) { - list_del_init(&bo->lru); - spin_unlock(&bdev->lru_lock); - - if (bo->ttm) - ttm_tt_unpopulate(bo->bdev, bo->ttm); - - ttm_bo_put(bo); - spin_lock(&bdev->lru_lock); - } - } + ttm_device_clear_lru_dma_mappings(bdev, &bdev->pinned); for (i = TTM_PL_SYSTEM; i < TTM_NUM_MEM_TYPES; ++i) { man = ttm_manager_type(bdev, i); if (!man || !man->use_tt) continue; - for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) { - while (!list_empty(&man->lru[j])) { - bo = list_first_entry(&man->lru[j], struct ttm_buffer_object, lru); - if (ttm_bo_get_unless_zero(bo)) { - list_del_init(&bo->lru); - spin_unlock(&bdev->lru_lock); - - if (bo->ttm) - ttm_tt_unpopulate(bo->bdev, bo->ttm); - - ttm_bo_put(bo); - spin_lock(&bdev->lru_lock); - } - } - } + for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) + ttm_device_clear_lru_dma_mappings(bdev, &man->lru[j]); } - spin_unlock(&bdev->lru_lock); } EXPORT_SYMBOL(ttm_device_clear_dma_mappings); diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index cbd47a104962..2b76ecdf12e8 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -29,13 +29,117 @@ #include #include +/** + * ttm_lru_bulk_move_init - initialize a bulk move structure + * @bulk: the structure to init + * + * For now just memset the structure to zero. + */ +void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk) +{ + memset(bulk, 0, sizeof(*bulk)); +} +EXPORT_SYMBOL(ttm_lru_bulk_move_init); + +/** + * ttm_lru_bulk_move_tail - bulk move range of resources to the LRU tail. + * + * @bulk: bulk move structure + * + * Bulk move BOs to the LRU tail, only valid to use when driver makes sure that + * resource order never changes. Should be called with &ttm_device.lru_lock held. + */ +void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk) +{ + unsigned i; + + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { + struct ttm_lru_bulk_move_pos *pos = &bulk->tt[i]; + struct ttm_resource_manager *man; + + if (!pos->first) + continue; + + lockdep_assert_held(&pos->first->bo->bdev->lru_lock); + dma_resv_assert_held(pos->first->bo->base.resv); + dma_resv_assert_held(pos->last->bo->base.resv); + + man = ttm_manager_type(pos->first->bo->bdev, TTM_PL_TT); + list_bulk_move_tail(&man->lru[i], &pos->first->lru, + &pos->last->lru); + } + + for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { + struct ttm_lru_bulk_move_pos *pos = &bulk->vram[i]; + struct ttm_resource_manager *man; + + if (!pos->first) + continue; + + lockdep_assert_held(&pos->first->bo->bdev->lru_lock); + dma_resv_assert_held(pos->first->bo->base.resv); + dma_resv_assert_held(pos->last->bo->base.resv); + + man = ttm_manager_type(pos->first->bo->bdev, TTM_PL_VRAM); + list_bulk_move_tail(&man->lru[i], &pos->first->lru, + &pos->last->lru); + } +} +EXPORT_SYMBOL(ttm_lru_bulk_move_tail); + +/* Record a resource position in a bulk move structure */ +static void ttm_lru_bulk_move_set_pos(struct ttm_lru_bulk_move_pos *pos, + struct ttm_resource *res) +{ + if (!pos->first) + pos->first = res; + pos->last = res; +} + +/* Move a resource to the LRU tail and track the bulk position */ +void ttm_resource_move_to_lru_tail(struct ttm_resource *res, + struct ttm_lru_bulk_move *bulk) +{ + struct ttm_buffer_object *bo = res->bo; + struct ttm_device *bdev = bo->bdev; + struct ttm_resource_manager *man; + + lockdep_assert_held(&bo->bdev->lru_lock); + + if (bo->pin_count) { + list_move_tail(&res->lru, &bdev->pinned); + if (bdev->funcs->del_from_lru_notify) + bdev->funcs->del_from_lru_notify(res->bo); + return; + } + + man = ttm_manager_type(bdev, res->mem_type); + list_move_tail(&res->lru, &man->lru[bo->priority]); + + if (bdev->funcs->del_from_lru_notify) + bdev->funcs->del_from_lru_notify(bo); + + if (!bulk) + return; + + switch (res->mem_type) { + case TTM_PL_TT: + ttm_lru_bulk_move_set_pos(&bulk->tt[bo->priority], res); + break; + + case TTM_PL_VRAM: + ttm_lru_bulk_move_set_pos(&bulk->vram[bo->priority], res); + break; + } +} + /** * ttm_resource_init - resource object constructure * @bo: buffer object this resources is allocated for * @place: placement of the resource * @res: the resource object to inistilize * - * Initialize a new resource object. Counterpart of &ttm_resource_fini. + * Initialize a new resource object. Counterpart of ttm_resource_fini(). */ void ttm_resource_init(struct ttm_buffer_object *bo, const struct ttm_place *place, @@ -52,10 +156,12 @@ void ttm_resource_init(struct ttm_buffer_object *bo, res->bus.is_iomem = false; res->bus.caching = ttm_cached; res->bo = bo; + INIT_LIST_HEAD(&res->lru); man = ttm_manager_type(bo->bdev, place->mem_type); spin_lock(&bo->bdev->lru_lock); - man->usage += bo->base.size; + man->usage += res->num_pages << PAGE_SHIFT; + ttm_resource_move_to_lru_tail(res, NULL); spin_unlock(&bo->bdev->lru_lock); } EXPORT_SYMBOL(ttm_resource_init); @@ -66,15 +172,21 @@ EXPORT_SYMBOL(ttm_resource_init); * @res: the resource to clean up * * Should be used by resource manager backends to clean up the TTM resource - * objects before freeing the underlying structure. Counterpart of - * &ttm_resource_init + * objects before freeing the underlying structure. Makes sure the resource is + * removed from the LRU before destruction. + * Counterpart of ttm_resource_init(). */ void ttm_resource_fini(struct ttm_resource_manager *man, struct ttm_resource *res) { - spin_lock(&man->bdev->lru_lock); - man->usage -= res->bo->base.size; - spin_unlock(&man->bdev->lru_lock); + struct ttm_device *bdev = man->bdev; + + spin_lock(&bdev->lru_lock); + list_del_init(&res->lru); + if (res->bo && bdev->funcs->del_from_lru_notify) + bdev->funcs->del_from_lru_notify(res->bo); + man->usage -= res->num_pages << PAGE_SHIFT; + spin_unlock(&bdev->lru_lock); } EXPORT_SYMBOL(ttm_resource_fini); diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index c17b2df9178b..3da77fc54552 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -55,8 +55,6 @@ struct ttm_placement; struct ttm_place; -struct ttm_lru_bulk_move; - /** * enum ttm_bo_type * @@ -94,7 +92,6 @@ struct ttm_tt; * @ttm: TTM structure holding system pages. * @evicted: Whether the object was evicted without user-space knowing. * @deleted: True if the object is only a zombie and already deleted. - * @lru: List head for the lru list. * @ddestroy: List head for the delayed destroy list. * @swap: List head for swap LRU list. * @moving: Fence set when BO is moving @@ -143,7 +140,6 @@ struct ttm_buffer_object { * Members protected by the bdev::lru_lock. */ - struct list_head lru; struct list_head ddestroy; /** @@ -295,7 +291,6 @@ void ttm_bo_put(struct ttm_buffer_object *bo); * ttm_bo_move_to_lru_tail * * @bo: The buffer object. - * @mem: Resource object. * @bulk: optional bulk move structure to remember BO positions * * Move this BO to the tail of all lru lists used to lookup and reserve an @@ -303,19 +298,8 @@ void ttm_bo_put(struct ttm_buffer_object *bo); * held, and is used to make a BO less likely to be considered for eviction. */ void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo, - struct ttm_resource *mem, struct ttm_lru_bulk_move *bulk); -/** - * ttm_bo_bulk_move_lru_tail - * - * @bulk: bulk move structure - * - * Bulk move BOs to the LRU tail, only valid to use when driver makes sure that - * BO order never changes. Should be called with ttm_global::lru_lock held. - */ -void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk); - /** * ttm_bo_lock_delayed_workqueue * diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 5f087575194b..6c7352e13708 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -45,33 +45,6 @@ #include "ttm_tt.h" #include "ttm_pool.h" -/** - * struct ttm_lru_bulk_move_pos - * - * @first: first BO in the bulk move range - * @last: last BO in the bulk move range - * - * Positions for a lru bulk move. - */ -struct ttm_lru_bulk_move_pos { - struct ttm_buffer_object *first; - struct ttm_buffer_object *last; -}; - -/** - * struct ttm_lru_bulk_move - * - * @tt: first/last lru entry for BOs in the TT domain - * @vram: first/last lru entry for BOs in the VRAM domain - * @swap: first/last lru entry for BOs on the swap list - * - * Helper structure for bulk moves on the LRU list. - */ -struct ttm_lru_bulk_move { - struct ttm_lru_bulk_move_pos tt[TTM_MAX_BO_PRIORITY]; - struct ttm_lru_bulk_move_pos vram[TTM_MAX_BO_PRIORITY]; -}; - /* * ttm_bo.c */ @@ -182,7 +155,7 @@ static inline void ttm_bo_move_to_lru_tail_unlocked(struct ttm_buffer_object *bo) { spin_lock(&bo->bdev->lru_lock); - ttm_bo_move_to_lru_tail(bo, bo->resource, NULL); + ttm_bo_move_to_lru_tail(bo, NULL); spin_unlock(&bo->bdev->lru_lock); } diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 323c14a30c6b..f8f766b092a6 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -26,10 +26,12 @@ #define _TTM_RESOURCE_H_ #include +#include #include #include #include #include + #include #include #include @@ -179,6 +181,38 @@ struct ttm_resource { uint32_t placement; struct ttm_bus_placement bus; struct ttm_buffer_object *bo; + + /** + * @lru: Least recently used list, see &ttm_resource_manager.lru + */ + struct list_head lru; +}; + +/** + * struct ttm_lru_bulk_move_pos + * + * @first: first res in the bulk move range + * @last: last res in the bulk move range + * + * Positions for a lru bulk move. + */ +struct ttm_lru_bulk_move_pos { + struct ttm_resource *first; + struct ttm_resource *last; +}; + +/** + * struct ttm_lru_bulk_move + * + * @tt: first/last lru entry for resources in the TT domain + * @vram: first/last lru entry for resources in the VRAM domain + * + * Container for the current bulk move state. Should be used with + * ttm_lru_bulk_move_init() and ttm_bo_move_to_lru_tail(). + */ +struct ttm_lru_bulk_move { + struct ttm_lru_bulk_move_pos tt[TTM_MAX_BO_PRIORITY]; + struct ttm_lru_bulk_move_pos vram[TTM_MAX_BO_PRIORITY]; }; /** @@ -267,6 +301,12 @@ ttm_resource_manager_cleanup(struct ttm_resource_manager *man) man->move = NULL; } +void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk); +void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk); + +void ttm_resource_move_to_lru_tail(struct ttm_resource *res, + struct ttm_lru_bulk_move *bulk); + void ttm_resource_init(struct ttm_buffer_object *bo, const struct ttm_place *place, struct ttm_resource *res); From 5d05b988f1c0fddc4aaffa5fa3c3f5a9e7b84d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 8 Jun 2021 11:13:21 +0200 Subject: [PATCH 00409/11454] drm/ttm: add resource iterator v4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of duplicating that at different places add an iterator over all the resources in a resource manager. v2: add lockdep annotation and kerneldoc v3: fix various bugs pointed out by Felix v4: simplify the code a bit more Signed-off-by: Christian König Tested-by: Bas Nieuwenhuizen Reviewed-by: Daniel Vetter (v2) Reviewed-by: Felix Kuehling Link: https://patchwork.freedesktop.org/patch/msgid/20220321132601.2161-2-christian.koenig@amd.com --- drivers/gpu/drm/ttm/ttm_bo.c | 37 ++++++++-------------- drivers/gpu/drm/ttm/ttm_device.c | 26 +++++++-------- drivers/gpu/drm/ttm/ttm_resource.c | 51 ++++++++++++++++++++++++++++++ include/drm/ttm/ttm_resource.h | 23 ++++++++++++++ 4 files changed, 99 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index cb0fa932d495..b119af33e7d7 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -579,38 +579,29 @@ int ttm_mem_evict_first(struct ttm_device *bdev, struct ww_acquire_ctx *ticket) { struct ttm_buffer_object *bo = NULL, *busy_bo = NULL; + struct ttm_resource_cursor cursor; struct ttm_resource *res; bool locked = false; - unsigned i; int ret; spin_lock(&bdev->lru_lock); - for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { - list_for_each_entry(res, &man->lru[i], lru) { - bool busy; + ttm_resource_manager_for_each_res(man, &cursor, res) { + bool busy; - bo = res->bo; - if (!ttm_bo_evict_swapout_allowable(bo, ctx, place, - &locked, &busy)) { - if (busy && !busy_bo && ticket != - dma_resv_locking_ctx(bo->base.resv)) - busy_bo = bo; - continue; - } - - if (!ttm_bo_get_unless_zero(bo)) { - if (locked) - dma_resv_unlock(bo->base.resv); - continue; - } - break; + if (!ttm_bo_evict_swapout_allowable(res->bo, ctx, place, + &locked, &busy)) { + if (busy && !busy_bo && ticket != + dma_resv_locking_ctx(res->bo->base.resv)) + busy_bo = res->bo; + continue; } - /* If the inner loop terminated early, we have our candidate */ - if (&res->lru != &man->lru[i]) + if (ttm_bo_get_unless_zero(res->bo)) { + bo = res->bo; break; - - bo = NULL; + } + if (locked) + dma_resv_unlock(res->bo->base.resv); } if (!bo) { diff --git a/drivers/gpu/drm/ttm/ttm_device.c b/drivers/gpu/drm/ttm/ttm_device.c index ba35887147ba..a0562ab386f5 100644 --- a/drivers/gpu/drm/ttm/ttm_device.c +++ b/drivers/gpu/drm/ttm/ttm_device.c @@ -142,10 +142,10 @@ EXPORT_SYMBOL(ttm_global_swapout); int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, gfp_t gfp_flags) { + struct ttm_resource_cursor cursor; struct ttm_resource_manager *man; - struct ttm_buffer_object *bo; struct ttm_resource *res; - unsigned i, j; + unsigned i; int ret; spin_lock(&bdev->lru_lock); @@ -154,20 +154,16 @@ int ttm_device_swapout(struct ttm_device *bdev, struct ttm_operation_ctx *ctx, if (!man || !man->use_tt) continue; - for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) { - list_for_each_entry(res, &man->lru[j], lru) { - uint32_t num_pages; + ttm_resource_manager_for_each_res(man, &cursor, res) { + struct ttm_buffer_object *bo = res->bo; + uint32_t num_pages = PFN_UP(bo->base.size); - bo = res->bo; - num_pages = PFN_UP(bo->base.size); - - ret = ttm_bo_swapout(bo, ctx, gfp_flags); - /* ttm_bo_swapout has dropped the lru_lock */ - if (!ret) - return num_pages; - if (ret != -EBUSY) - return ret; - } + ret = ttm_bo_swapout(bo, ctx, gfp_flags); + /* ttm_bo_swapout has dropped the lru_lock */ + if (!ret) + return num_pages; + if (ret != -EBUSY) + return ret; } } spin_unlock(&bdev->lru_lock); diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 2b76ecdf12e8..e1d4130e6863 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -385,6 +385,57 @@ void ttm_resource_manager_debug(struct ttm_resource_manager *man, } EXPORT_SYMBOL(ttm_resource_manager_debug); +/** + * ttm_resource_manager_first + * + * @man: resource manager to iterate over + * @cursor: cursor to record the position + * + * Returns the first resource from the resource manager. + */ +struct ttm_resource * +ttm_resource_manager_first(struct ttm_resource_manager *man, + struct ttm_resource_cursor *cursor) +{ + struct ttm_resource *res; + + lockdep_assert_held(&man->bdev->lru_lock); + + for (cursor->priority = 0; cursor->priority < TTM_MAX_BO_PRIORITY; + ++cursor->priority) + list_for_each_entry(res, &man->lru[cursor->priority], lru) + return res; + + return NULL; +} + +/** + * ttm_resource_manager_next + * + * @man: resource manager to iterate over + * @cursor: cursor to record the position + * @res: the current resource pointer + * + * Returns the next resource from the resource manager. + */ +struct ttm_resource * +ttm_resource_manager_next(struct ttm_resource_manager *man, + struct ttm_resource_cursor *cursor, + struct ttm_resource *res) +{ + lockdep_assert_held(&man->bdev->lru_lock); + + list_for_each_entry_continue(res, &man->lru[cursor->priority], lru) + return res; + + for (++cursor->priority; cursor->priority < TTM_MAX_BO_PRIORITY; + ++cursor->priority) + list_for_each_entry(res, &man->lru[cursor->priority], lru) + return res; + + return NULL; +} + static void ttm_kmap_iter_iomap_map_local(struct ttm_kmap_iter *iter, struct dma_buf_map *dmap, pgoff_t i) diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index f8f766b092a6..d8e880110dc6 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -188,6 +188,17 @@ struct ttm_resource { struct list_head lru; }; +/** + * struct ttm_resource_cursor + * + * @priority: the current priority + * + * Cursor to iterate over the resources in a manager. + */ +struct ttm_resource_cursor { + unsigned int priority; +}; + /** * struct ttm_lru_bulk_move_pos * @@ -333,6 +344,18 @@ uint64_t ttm_resource_manager_usage(struct ttm_resource_manager *man); void ttm_resource_manager_debug(struct ttm_resource_manager *man, struct drm_printer *p); +struct ttm_resource * +ttm_resource_manager_first(struct ttm_resource_manager *man, + struct ttm_resource_cursor *cursor); +struct ttm_resource * +ttm_resource_manager_next(struct ttm_resource_manager *man, + struct ttm_resource_cursor *cursor, + struct ttm_resource *res); + +#define ttm_resource_manager_for_each_res(man, cursor, res) \ + for (res = ttm_resource_manager_first(man, cursor); res; \ + res = ttm_resource_manager_next(man, cursor, res)) + struct ttm_kmap_iter * ttm_kmap_iter_iomap_init(struct ttm_kmap_iter_iomap *iter_io, struct io_mapping *iomap, From b0e2c9ea5afc769476fd85a6a28cc370ddd44ee8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 24 Jan 2022 09:37:43 +0100 Subject: [PATCH 00410/11454] drm/ttm: allow bulk moves for all domains MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not just TT and VRAM. Signed-off-by: Christian König Reviewed-by: Daniel Vetter Tested-by: Bas Nieuwenhuizen Link: https://patchwork.freedesktop.org/patch/msgid/20220321132601.2161-3-christian.koenig@amd.com --- drivers/gpu/drm/ttm/ttm_resource.c | 52 +++++++++--------------------- include/drm/ttm/ttm_device.h | 2 -- include/drm/ttm/ttm_resource.h | 4 +-- 3 files changed, 17 insertions(+), 41 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index e1d4130e6863..19df7350de0f 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -51,38 +51,24 @@ EXPORT_SYMBOL(ttm_lru_bulk_move_init); */ void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk) { - unsigned i; + unsigned i, j; - for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { - struct ttm_lru_bulk_move_pos *pos = &bulk->tt[i]; - struct ttm_resource_manager *man; + for (i = 0; i < TTM_NUM_MEM_TYPES; ++i) { + for (j = 0; j < TTM_MAX_BO_PRIORITY; ++j) { + struct ttm_lru_bulk_move_pos *pos = &bulk->pos[i][j]; + struct ttm_resource_manager *man; - if (!pos->first) - continue; + if (!pos->first) + continue; - lockdep_assert_held(&pos->first->bo->bdev->lru_lock); - dma_resv_assert_held(pos->first->bo->base.resv); - dma_resv_assert_held(pos->last->bo->base.resv); + lockdep_assert_held(&pos->first->bo->bdev->lru_lock); + dma_resv_assert_held(pos->first->bo->base.resv); + dma_resv_assert_held(pos->last->bo->base.resv); - man = ttm_manager_type(pos->first->bo->bdev, TTM_PL_TT); - list_bulk_move_tail(&man->lru[i], &pos->first->lru, - &pos->last->lru); - } - - for (i = 0; i < TTM_MAX_BO_PRIORITY; ++i) { - struct ttm_lru_bulk_move_pos *pos = &bulk->vram[i]; - struct ttm_resource_manager *man; - - if (!pos->first) - continue; - - lockdep_assert_held(&pos->first->bo->bdev->lru_lock); - dma_resv_assert_held(pos->first->bo->base.resv); - dma_resv_assert_held(pos->last->bo->base.resv); - - man = ttm_manager_type(pos->first->bo->bdev, TTM_PL_VRAM); - list_bulk_move_tail(&man->lru[i], &pos->first->lru, - &pos->last->lru); + man = ttm_manager_type(pos->first->bo->bdev, i); + list_bulk_move_tail(&man->lru[j], &pos->first->lru, + &pos->last->lru); + } } } EXPORT_SYMBOL(ttm_lru_bulk_move_tail); @@ -122,15 +108,7 @@ void ttm_resource_move_to_lru_tail(struct ttm_resource *res, if (!bulk) return; - switch (res->mem_type) { - case TTM_PL_TT: - ttm_lru_bulk_move_set_pos(&bulk->tt[bo->priority], res); - break; - - case TTM_PL_VRAM: - ttm_lru_bulk_move_set_pos(&bulk->vram[bo->priority], res); - break; - } + ttm_lru_bulk_move_set_pos(&bulk->pos[res->mem_type][bo->priority], res); } /** diff --git a/include/drm/ttm/ttm_device.h b/include/drm/ttm/ttm_device.h index 0a4ddec78d8f..425150f35fbe 100644 --- a/include/drm/ttm/ttm_device.h +++ b/include/drm/ttm/ttm_device.h @@ -30,8 +30,6 @@ #include #include -#define TTM_NUM_MEM_TYPES 8 - struct ttm_device; struct ttm_placement; struct ttm_buffer_object; diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index d8e880110dc6..62e7bb782596 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -37,6 +37,7 @@ #include #define TTM_MAX_BO_PRIORITY 4U +#define TTM_NUM_MEM_TYPES 8 struct ttm_device; struct ttm_resource_manager; @@ -222,8 +223,7 @@ struct ttm_lru_bulk_move_pos { * ttm_lru_bulk_move_init() and ttm_bo_move_to_lru_tail(). */ struct ttm_lru_bulk_move { - struct ttm_lru_bulk_move_pos tt[TTM_MAX_BO_PRIORITY]; - struct ttm_lru_bulk_move_pos vram[TTM_MAX_BO_PRIORITY]; + struct ttm_lru_bulk_move_pos pos[TTM_NUM_MEM_TYPES][TTM_MAX_BO_PRIORITY]; }; /** From 6ce4431c7ba7954c4fa6a96ce16ca1b2943e1a83 Mon Sep 17 00:00:00 2001 From: Xiaomeng Tong Date: Sun, 27 Mar 2022 15:39:25 +0800 Subject: [PATCH 00411/11454] drm/nouveau/kms/nv50-: atom: fix an incorrect NULL check on list iterator The bug is here: return encoder; The list iterator value 'encoder' will *always* be set and non-NULL by drm_for_each_encoder_mask(), so it is incorrect to assume that the iterator value will be NULL if the list is empty or no element found. Otherwise it will bypass some NULL checks and lead to invalid memory access passing the check. To fix this bug, just return 'encoder' when found, otherwise return NULL. Cc: stable@vger.kernel.org Fixes: 12885ecbfe62d ("drm/nouveau/kms/nvd9-: Add CRC support") Signed-off-by: Xiaomeng Tong Reviewed-by: Lyude Paul [Changed commit title] Signed-off-by: Lyude Paul Link: https://patchwork.freedesktop.org/patch/msgid/20220327073925.11121-1-xiam0nd.tong@gmail.com --- drivers/gpu/drm/nouveau/dispnv50/atom.h | 6 +++--- drivers/gpu/drm/nouveau/dispnv50/crc.c | 27 ++++++++++++++++++++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/dispnv50/atom.h b/drivers/gpu/drm/nouveau/dispnv50/atom.h index 3d82b3c67dec..93f8f4f64578 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/atom.h +++ b/drivers/gpu/drm/nouveau/dispnv50/atom.h @@ -160,14 +160,14 @@ nv50_head_atom_get(struct drm_atomic_state *state, struct drm_crtc *crtc) static inline struct drm_encoder * nv50_head_atom_get_encoder(struct nv50_head_atom *atom) { - struct drm_encoder *encoder = NULL; + struct drm_encoder *encoder; /* We only ever have a single encoder */ drm_for_each_encoder_mask(encoder, atom->state.crtc->dev, atom->state.encoder_mask) - break; + return encoder; - return encoder; + return NULL; } #define nv50_wndw_atom(p) container_of((p), struct nv50_wndw_atom, state) diff --git a/drivers/gpu/drm/nouveau/dispnv50/crc.c b/drivers/gpu/drm/nouveau/dispnv50/crc.c index 29428e770f14..b834e8a9ae77 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/crc.c +++ b/drivers/gpu/drm/nouveau/dispnv50/crc.c @@ -390,9 +390,18 @@ void nv50_crc_atomic_check_outp(struct nv50_atom *atom) struct nv50_head_atom *armh = nv50_head_atom(old_crtc_state); struct nv50_head_atom *asyh = nv50_head_atom(new_crtc_state); struct nv50_outp_atom *outp_atom; - struct nouveau_encoder *outp = - nv50_real_outp(nv50_head_atom_get_encoder(armh)); - struct drm_encoder *encoder = &outp->base.base; + struct nouveau_encoder *outp; + struct drm_encoder *encoder, *enc; + + enc = nv50_head_atom_get_encoder(armh); + if (!enc) + continue; + + outp = nv50_real_outp(enc); + if (!outp) + continue; + + encoder = &outp->base.base; if (!asyh->clr.crc) continue; @@ -443,8 +452,16 @@ void nv50_crc_atomic_set(struct nv50_head *head, struct drm_device *dev = crtc->dev; struct nv50_crc *crc = &head->crc; const struct nv50_crc_func *func = nv50_disp(dev)->core->func->crc; - struct nouveau_encoder *outp = - nv50_real_outp(nv50_head_atom_get_encoder(asyh)); + struct nouveau_encoder *outp; + struct drm_encoder *encoder; + + encoder = nv50_head_atom_get_encoder(asyh); + if (!encoder) + return; + + outp = nv50_real_outp(encoder); + if (!outp) + return; func->set_src(head, outp->or, nv50_crc_source_type(outp, asyh->crc.src), &crc->ctx[crc->ctx_idx]); From d8b932014c4aa5a70bb6add0f14d9329e7c489c2 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Mon, 28 Mar 2022 10:16:50 -0700 Subject: [PATCH 00412/11454] drm/i915: avoid concurrent writes to aux_inv GPU hangs have been observed when multiple engines write to the same aux_inv register at the same time. To avoid this each engine should only invalidate its own auxiliary table. The function gen12_emit_flush_xcs() currently invalidate the auxiliary table for all engines because the rq->engine is not necessarily the engine eventually carrying out the request, and potentially the engine could even be a virtual one (with engine->instance being -1). With the MMIO remap feature, we can actually set bit 17 of MI_LRI instruction and let the hardware to figure out the local aux_inv register at runtime to avoid invalidating auxiliary table for all engines. Bspec: 45728 v2: Invalidate AUX table for indirect context as well. Cc: Stuart Summers Cc: Tvrtko Ursulin Signed-off-by: Chris Wilson Signed-off-by: Fei Yang Reviewed-by: Tvrtko Ursulin Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20220328171650.1900674-1-fei.yang@intel.com --- drivers/gpu/drm/i915/gt/gen8_engine_cs.c | 50 +++++--------------- drivers/gpu/drm/i915/gt/gen8_engine_cs.h | 4 +- drivers/gpu/drm/i915/gt/intel_gpu_commands.h | 1 + drivers/gpu/drm/i915/gt/intel_lrc.c | 12 +++++ 4 files changed, 27 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c index 36148887c699..047b5a710149 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.c +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.c @@ -6,7 +6,6 @@ #include "gen8_engine_cs.h" #include "i915_drv.h" #include "intel_gpu_commands.h" -#include "intel_gt_regs.h" #include "intel_lrc.h" #include "intel_ring.h" @@ -165,33 +164,9 @@ static u32 preparser_disable(bool state) return MI_ARB_CHECK | 1 << 8 | state; } -static i915_reg_t aux_inv_reg(const struct intel_engine_cs *engine) +u32 *gen12_emit_aux_table_inv(u32 *cs, const i915_reg_t inv_reg) { - static const i915_reg_t vd[] = { - GEN12_VD0_AUX_NV, - GEN12_VD1_AUX_NV, - GEN12_VD2_AUX_NV, - GEN12_VD3_AUX_NV, - }; - - static const i915_reg_t ve[] = { - GEN12_VE0_AUX_NV, - GEN12_VE1_AUX_NV, - }; - - if (engine->class == VIDEO_DECODE_CLASS) - return vd[engine->instance]; - - if (engine->class == VIDEO_ENHANCEMENT_CLASS) - return ve[engine->instance]; - - GEM_BUG_ON("unknown aux_inv reg\n"); - return INVALID_MMIO_REG; -} - -static u32 *gen12_emit_aux_table_inv(const i915_reg_t inv_reg, u32 *cs) -{ - *cs++ = MI_LOAD_REGISTER_IMM(1); + *cs++ = MI_LOAD_REGISTER_IMM(1) | MI_LRI_MMIO_REMAP_EN; *cs++ = i915_mmio_reg_offset(inv_reg); *cs++ = AUX_INV; *cs++ = MI_NOOP; @@ -274,7 +249,7 @@ int gen12_emit_flush_rcs(struct i915_request *rq, u32 mode) if (!HAS_FLAT_CCS(rq->engine->i915)) { /* hsdes: 1809175790 */ - cs = gen12_emit_aux_table_inv(GEN12_GFX_CCS_AUX_NV, cs); + cs = gen12_emit_aux_table_inv(cs, GEN12_GFX_CCS_AUX_NV); } *cs++ = preparser_disable(false); @@ -293,10 +268,12 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) if (mode & EMIT_INVALIDATE) { cmd += 2; - if (!HAS_FLAT_CCS(rq->engine->i915)) { + if (!HAS_FLAT_CCS(rq->engine->i915) && + (rq->engine->class == VIDEO_DECODE_CLASS || + rq->engine->class == VIDEO_ENHANCEMENT_CLASS)) { aux_inv = rq->engine->mask & ~BIT(BCS0); if (aux_inv) - cmd += 2 * hweight32(aux_inv) + 2; + cmd += 4; } } @@ -329,15 +306,10 @@ int gen12_emit_flush_xcs(struct i915_request *rq, u32 mode) *cs++ = 0; /* value */ if (aux_inv) { /* hsdes: 1809175790 */ - struct intel_engine_cs *engine; - unsigned int tmp; - - *cs++ = MI_LOAD_REGISTER_IMM(hweight32(aux_inv)); - for_each_engine_masked(engine, rq->engine->gt, aux_inv, tmp) { - *cs++ = i915_mmio_reg_offset(aux_inv_reg(engine)); - *cs++ = AUX_INV; - } - *cs++ = MI_NOOP; + if (rq->engine->class == VIDEO_DECODE_CLASS) + cs = gen12_emit_aux_table_inv(cs, GEN12_VD0_AUX_NV); + else + cs = gen12_emit_aux_table_inv(cs, GEN12_VE0_AUX_NV); } if (mode & EMIT_INVALIDATE) diff --git a/drivers/gpu/drm/i915/gt/gen8_engine_cs.h b/drivers/gpu/drm/i915/gt/gen8_engine_cs.h index cc6e21d3662a..107ab42539ab 100644 --- a/drivers/gpu/drm/i915/gt/gen8_engine_cs.h +++ b/drivers/gpu/drm/i915/gt/gen8_engine_cs.h @@ -10,7 +10,7 @@ #include #include "i915_gem.h" /* GEM_BUG_ON */ - +#include "intel_gt_regs.h" #include "intel_gpu_commands.h" struct i915_request; @@ -38,6 +38,8 @@ u32 *gen8_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); u32 *gen11_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); u32 *gen12_emit_fini_breadcrumb_rcs(struct i915_request *rq, u32 *cs); +u32 *gen12_emit_aux_table_inv(u32 *cs, const i915_reg_t inv_reg); + static inline u32 * __gen8_emit_pipe_control(u32 *batch, u32 flags0, u32 flags1, u32 offset) { diff --git a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h index d112ffd56418..4243be030bc1 100644 --- a/drivers/gpu/drm/i915/gt/intel_gpu_commands.h +++ b/drivers/gpu/drm/i915/gt/intel_gpu_commands.h @@ -144,6 +144,7 @@ #define MI_LOAD_REGISTER_IMM(x) MI_INSTR(0x22, 2*(x)-1) /* Gen11+. addr = base + (ctx_restore ? offset & GENMASK(12,2) : offset) */ #define MI_LRI_LRM_CS_MMIO REG_BIT(19) +#define MI_LRI_MMIO_REMAP_EN REG_BIT(17) #define MI_LRI_FORCE_POSTED (1<<12) #define MI_LOAD_REGISTER_IMM_MAX_REGS (126) #define MI_STORE_REGISTER_MEM MI_INSTR(0x24, 1) diff --git a/drivers/gpu/drm/i915/gt/intel_lrc.c b/drivers/gpu/drm/i915/gt/intel_lrc.c index 07bef7128fdb..dffef6ab4baf 100644 --- a/drivers/gpu/drm/i915/gt/intel_lrc.c +++ b/drivers/gpu/drm/i915/gt/intel_lrc.c @@ -1208,6 +1208,10 @@ gen12_emit_indirect_ctx_rcs(const struct intel_context *ce, u32 *cs) IS_DG2_G11(ce->engine->i915)) cs = gen8_emit_pipe_control(cs, PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, 0); + /* hsdes: 1809175790 */ + if (!HAS_FLAT_CCS(ce->engine->i915)) + cs = gen12_emit_aux_table_inv(cs, GEN12_GFX_CCS_AUX_NV); + return cs; } @@ -1225,6 +1229,14 @@ gen12_emit_indirect_ctx_xcs(const struct intel_context *ce, u32 *cs) PIPE_CONTROL_INSTRUCTION_CACHE_INVALIDATE, 0); + /* hsdes: 1809175790 */ + if (!HAS_FLAT_CCS(ce->engine->i915)) { + if (ce->engine->class == VIDEO_DECODE_CLASS) + cs = gen12_emit_aux_table_inv(cs, GEN12_VD0_AUX_NV); + else if (ce->engine->class == VIDEO_ENHANCEMENT_CLASS) + cs = gen12_emit_aux_table_inv(cs, GEN12_VE0_AUX_NV); + } + return cs; } From 66ddc69373a8d5a08fe4341d9e912bfdac602248 Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 24 Mar 2022 17:21:42 +0000 Subject: [PATCH 00413/11454] drm/i915/ttm: limit where we apply TTM_PL_FLAG_CONTIGUOUS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We only need this when allocating device local-memory, where this influences the drm_buddy. Currently there is some funny behaviour where an "in limbo" system memory object is lacking the relevant placement flags etc. before we first allocate the ttm_tt, leading to ttm performing a move when not needed, since the current placement is seen as not compatible. Suggested-by: Thomas Hellström Fixes: 2ed38cec5606 ("drm/i915: opportunistically apply ALLOC_CONTIGIOUS") Signed-off-by: Matthew Auld Cc: Nirmoy Das Reviewed-by: Thomas Hellström Acked-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220324172143.377104-1-matthew.auld@intel.com --- drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index e4a06fcf741a..97e648fa76bd 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -133,6 +133,9 @@ i915_ttm_place_from_region(const struct intel_memory_region *mr, memset(place, 0, sizeof(*place)); place->mem_type = intel_region_to_ttm_type(mr); + if (mr->type == INTEL_MEMORY_SYSTEM) + return; + if (flags & I915_BO_ALLOC_CONTIGUOUS) place->flags |= TTM_PL_FLAG_CONTIGUOUS; if (offset != I915_BO_INVALID_OFFSET) { From 552caa1fdbb8624d98964e3f0200fe78f4906a1a Mon Sep 17 00:00:00 2001 From: Matthew Auld Date: Thu, 24 Mar 2022 17:21:43 +0000 Subject: [PATCH 00414/11454] drm/i915/migrate: move the sanity check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the sanity check that both src and dst are never both system memory, which should never happen on discrete, and likely means we have a bug. The only exception is on integrated where we trigger this path in the selftests. Signed-off-by: Matthew Auld Cc: Thomas Hellström Cc: Nirmoy Das Reviewed-by: Thomas Hellström Reviewed-by: Nirmoy Das Link: https://patchwork.freedesktop.org/patch/msgid/20220324172143.377104-2-matthew.auld@intel.com --- drivers/gpu/drm/i915/gt/intel_migrate.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_migrate.c b/drivers/gpu/drm/i915/gt/intel_migrate.c index 20444d6ceb3c..950fd6da146c 100644 --- a/drivers/gpu/drm/i915/gt/intel_migrate.c +++ b/drivers/gpu/drm/i915/gt/intel_migrate.c @@ -530,6 +530,7 @@ intel_context_migrate_copy(struct intel_context *ce, int err; GEM_BUG_ON(ce->vm != ce->engine->gt->migrate.context->vm); + GEM_BUG_ON(IS_DGFX(ce->engine->i915) && (!src_is_lmem && !dst_is_lmem)); *out = NULL; GEM_BUG_ON(ce->ring->size < SZ_64K); @@ -566,8 +567,6 @@ intel_context_migrate_copy(struct intel_context *ce, src_offset = 0; dst_offset = CHUNK_SZ; if (HAS_64K_PAGES(ce->engine->i915)) { - GEM_BUG_ON(!src_is_lmem && !dst_is_lmem); - src_offset = 0; dst_offset = 0; if (src_is_lmem) From 7842cf65b0401814a9df518a86a41641255c84d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Tue, 15 Feb 2022 17:29:59 +0100 Subject: [PATCH 00415/11454] drm/ttm: de-inline ttm_bo_pin/unpin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Those functions are going to become more complex, don't inline them any more. Signed-off-by: Christian König Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220321132601.2161-4-christian.koenig@amd.com --- drivers/gpu/drm/ttm/ttm_bo.c | 32 ++++++++++++++++++++++++++++++++ include/drm/ttm/ttm_bo_api.h | 30 ++---------------------------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index b119af33e7d7..fe0fa5fb7945 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -633,6 +633,38 @@ int ttm_mem_evict_first(struct ttm_device *bdev, return ret; } +/** + * ttm_bo_pin - Pin the buffer object. + * @bo: The buffer object to pin + * + * Make sure the buffer is not evicted any more during memory pressure. + * @bo must be unpinned again by calling ttm_bo_unpin(). + */ +void ttm_bo_pin(struct ttm_buffer_object *bo) +{ + dma_resv_assert_held(bo->base.resv); + WARN_ON_ONCE(!kref_read(&bo->kref)); + ++bo->pin_count; +} +EXPORT_SYMBOL(ttm_bo_pin); + +/** + * ttm_bo_unpin - Unpin the buffer object. + * @bo: The buffer object to unpin + * + * Allows the buffer object to be evicted again during memory pressure. + */ +void ttm_bo_unpin(struct ttm_buffer_object *bo) +{ + dma_resv_assert_held(bo->base.resv); + WARN_ON_ONCE(!kref_read(&bo->kref)); + if (bo->pin_count) + --bo->pin_count; + else + WARN_ON_ONCE(true); +} +EXPORT_SYMBOL(ttm_bo_unpin); + /* * Add the last move fence to the BO and reserve a new shared slot. We only use * a shared slot to avoid unecessary sync and rely on the subsequent bo move to diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 3da77fc54552..885b7698fd65 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -524,34 +524,8 @@ ssize_t ttm_bo_io(struct ttm_device *bdev, struct file *filp, int ttm_bo_swapout(struct ttm_buffer_object *bo, struct ttm_operation_ctx *ctx, gfp_t gfp_flags); -/** - * ttm_bo_pin - Pin the buffer object. - * @bo: The buffer object to pin - * - * Make sure the buffer is not evicted any more during memory pressure. - */ -static inline void ttm_bo_pin(struct ttm_buffer_object *bo) -{ - dma_resv_assert_held(bo->base.resv); - WARN_ON_ONCE(!kref_read(&bo->kref)); - ++bo->pin_count; -} - -/** - * ttm_bo_unpin - Unpin the buffer object. - * @bo: The buffer object to unpin - * - * Allows the buffer object to be evicted again during memory pressure. - */ -static inline void ttm_bo_unpin(struct ttm_buffer_object *bo) -{ - dma_resv_assert_held(bo->base.resv); - WARN_ON_ONCE(!kref_read(&bo->kref)); - if (bo->pin_count) - --bo->pin_count; - else - WARN_ON_ONCE(true); -} +void ttm_bo_pin(struct ttm_buffer_object *bo); +void ttm_bo_unpin(struct ttm_buffer_object *bo); int ttm_mem_evict_first(struct ttm_device *bdev, struct ttm_resource_manager *man, From fee2ede155423b0f7a559050a39750b98fe9db69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Mon, 24 Jan 2022 11:07:15 +0100 Subject: [PATCH 00416/11454] drm/ttm: rework bulk move handling v5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of providing the bulk move structure for each LRU update set this as property of the BO. This should avoid costly bulk move rebuilds with some games under RADV. v2: some name polishing, add a few more kerneldoc words. v3: add some lockdep v4: fix bugs, handle pin/unpin as well v5: improve kerneldoc Signed-off-by: Christian König Tested-by: Bas Nieuwenhuizen Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20220321132601.2161-5-christian.koenig@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 1 - drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 72 +++---------------- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 3 - drivers/gpu/drm/i915/gem/i915_gem_ttm.c | 2 +- drivers/gpu/drm/ttm/ttm_bo.c | 61 +++++++++++++--- drivers/gpu/drm/ttm/ttm_resource.c | 96 ++++++++++++++++++------- include/drm/ttm/ttm_bo_api.h | 16 ++--- include/drm/ttm/ttm_bo_driver.h | 2 +- include/drm/ttm/ttm_device.h | 9 --- include/drm/ttm/ttm_resource.h | 11 +-- 10 files changed, 144 insertions(+), 129 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 5859ed0552a4..57ac118fc266 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -1498,7 +1498,6 @@ static struct ttm_device_funcs amdgpu_bo_driver = { .io_mem_reserve = &amdgpu_ttm_io_mem_reserve, .io_mem_pfn = amdgpu_ttm_io_mem_pfn, .access_memory = &amdgpu_ttm_access_memory, - .del_from_lru_notify = &amdgpu_vm_del_from_lru_notify }; /* diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index f2ce5a0defd9..28f5e8b21a99 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -375,7 +375,7 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, if (bo->tbo.base.resv != vm->root.bo->tbo.base.resv) return; - vm->bulk_moveable = false; + ttm_bo_set_bulk_move(&bo->tbo, &vm->lru_bulk_move); if (bo->tbo.type == ttm_bo_type_kernel && bo->parent) amdgpu_vm_bo_relocated(base); else @@ -637,36 +637,6 @@ void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, list_add(&entry->tv.head, validated); } -/** - * amdgpu_vm_del_from_lru_notify - update bulk_moveable flag - * - * @bo: BO which was removed from the LRU - * - * Make sure the bulk_moveable flag is updated when a BO is removed from the - * LRU. - */ -void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo) -{ - struct amdgpu_bo *abo; - struct amdgpu_vm_bo_base *bo_base; - - if (!amdgpu_bo_is_amdgpu_bo(bo)) - return; - - if (bo->pin_count) - return; - - abo = ttm_to_amdgpu_bo(bo); - if (!abo->parent) - return; - for (bo_base = abo->vm_bo; bo_base; bo_base = bo_base->next) { - struct amdgpu_vm *vm = bo_base->vm; - - if (abo->tbo.base.resv == vm->root.bo->tbo.base.resv) - vm->bulk_moveable = false; - } - -} /** * amdgpu_vm_move_to_lru_tail - move all BOs to the end of LRU * @@ -679,33 +649,9 @@ void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo) void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev, struct amdgpu_vm *vm) { - struct amdgpu_vm_bo_base *bo_base; - - if (vm->bulk_moveable) { - spin_lock(&adev->mman.bdev.lru_lock); - ttm_lru_bulk_move_tail(&vm->lru_bulk_move); - spin_unlock(&adev->mman.bdev.lru_lock); - return; - } - - ttm_lru_bulk_move_init(&vm->lru_bulk_move); - spin_lock(&adev->mman.bdev.lru_lock); - list_for_each_entry(bo_base, &vm->idle, vm_status) { - struct amdgpu_bo *bo = bo_base->bo; - struct amdgpu_bo *shadow = amdgpu_bo_shadowed(bo); - - if (!bo->parent) - continue; - - ttm_bo_move_to_lru_tail(&bo->tbo, &vm->lru_bulk_move); - if (shadow) - ttm_bo_move_to_lru_tail(&shadow->tbo, - &vm->lru_bulk_move); - } + ttm_lru_bulk_move_tail(&vm->lru_bulk_move); spin_unlock(&adev->mman.bdev.lru_lock); - - vm->bulk_moveable = true; } /** @@ -728,8 +674,6 @@ int amdgpu_vm_validate_pt_bos(struct amdgpu_device *adev, struct amdgpu_vm *vm, struct amdgpu_vm_bo_base *bo_base, *tmp; int r; - vm->bulk_moveable &= list_empty(&vm->evicted); - list_for_each_entry_safe(bo_base, tmp, &vm->evicted, vm_status) { struct amdgpu_bo *bo = bo_base->bo; struct amdgpu_bo *shadow = amdgpu_bo_shadowed(bo); @@ -1047,10 +991,16 @@ static void amdgpu_vm_free_table(struct amdgpu_vm_bo_base *entry) if (!entry->bo) return; + shadow = amdgpu_bo_shadowed(entry->bo); + if (shadow) { + ttm_bo_set_bulk_move(&shadow->tbo, NULL); + amdgpu_bo_unref(&shadow); + } + + ttm_bo_set_bulk_move(&entry->bo->tbo, NULL); entry->bo->vm_bo = NULL; list_del(&entry->vm_status); - amdgpu_bo_unref(&shadow); amdgpu_bo_unref(&entry->bo); } @@ -1070,8 +1020,6 @@ static void amdgpu_vm_free_pts(struct amdgpu_device *adev, struct amdgpu_vm_pt_cursor cursor; struct amdgpu_vm_bo_base *entry; - vm->bulk_moveable = false; - for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry) amdgpu_vm_free_table(entry); @@ -2651,7 +2599,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, if (bo) { if (bo->tbo.base.resv == vm->root.bo->tbo.base.resv) - vm->bulk_moveable = false; + ttm_bo_set_bulk_move(&bo->tbo, NULL); for (base = &bo_va->base.bo->vm_bo; *base; base = &(*base)->next) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h index 85fcfb8c5efd..4d236682a118 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h @@ -317,8 +317,6 @@ struct amdgpu_vm { /* Store positions of group of BOs */ struct ttm_lru_bulk_move lru_bulk_move; - /* mark whether can do the bulk move */ - bool bulk_moveable; /* Flag to indicate if VM is used for compute */ bool is_compute_context; }; @@ -454,7 +452,6 @@ void amdgpu_vm_set_task_info(struct amdgpu_vm *vm); void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev, struct amdgpu_vm *vm); -void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo); void amdgpu_vm_get_memory(struct amdgpu_vm *vm, uint64_t *vram_mem, uint64_t *gtt_mem, uint64_t *cpu_mem); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c index 582e8dc9bc8c..6fc192082d8c 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_ttm.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_ttm.c @@ -849,7 +849,7 @@ void i915_ttm_adjust_lru(struct drm_i915_gem_object *obj) bo->priority = I915_TTM_PRIO_NO_PAGES; } - ttm_bo_move_to_lru_tail(bo, NULL); + ttm_bo_move_to_lru_tail(bo); spin_unlock(&bo->bdev->lru_lock); } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index fe0fa5fb7945..e5fd0f2c0299 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -69,16 +69,55 @@ static void ttm_bo_mem_space_debug(struct ttm_buffer_object *bo, } } -void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo, - struct ttm_lru_bulk_move *bulk) +/** + * ttm_bo_move_to_lru_tail + * + * @bo: The buffer object. + * + * Move this BO to the tail of all lru lists used to lookup and reserve an + * object. This function must be called with struct ttm_global::lru_lock + * held, and is used to make a BO less likely to be considered for eviction. + */ +void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo) { dma_resv_assert_held(bo->base.resv); if (bo->resource) - ttm_resource_move_to_lru_tail(bo->resource, bulk); + ttm_resource_move_to_lru_tail(bo->resource); } EXPORT_SYMBOL(ttm_bo_move_to_lru_tail); +/** + * ttm_bo_set_bulk_move - update BOs bulk move object + * + * @bo: The buffer object. + * + * Update the BOs bulk move object, making sure that resources are added/removed + * as well. A bulk move allows to move many resource on the LRU at once, + * resulting in much less overhead of maintaining the LRU. + * The only requirement is that the resources stay together on the LRU and are + * never separated. This is enforces by setting the bulk_move structure on a BO. + * ttm_lru_bulk_move_tail() should be used to move all resources to the tail of + * their LRU list. + */ +void ttm_bo_set_bulk_move(struct ttm_buffer_object *bo, + struct ttm_lru_bulk_move *bulk) +{ + dma_resv_assert_held(bo->base.resv); + + if (bo->bulk_move == bulk) + return; + + spin_lock(&bo->bdev->lru_lock); + if (bo->bulk_move && bo->resource) + ttm_lru_bulk_move_del(bo->bulk_move, bo->resource); + bo->bulk_move = bulk; + if (bo->bulk_move && bo->resource) + ttm_lru_bulk_move_add(bo->bulk_move, bo->resource); + spin_unlock(&bo->bdev->lru_lock); +} +EXPORT_SYMBOL(ttm_bo_set_bulk_move); + static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, struct ttm_resource *mem, bool evict, struct ttm_operation_ctx *ctx, @@ -316,6 +355,7 @@ static void ttm_bo_release(struct kref *kref) int ret; WARN_ON_ONCE(bo->pin_count); + WARN_ON_ONCE(bo->bulk_move); if (!bo->deleted) { ret = ttm_bo_individualize_resv(bo); @@ -352,7 +392,7 @@ static void ttm_bo_release(struct kref *kref) */ if (bo->pin_count) { bo->pin_count = 0; - ttm_resource_move_to_lru_tail(bo->resource, NULL); + ttm_resource_move_to_lru_tail(bo->resource); } kref_init(&bo->kref); @@ -644,7 +684,8 @@ void ttm_bo_pin(struct ttm_buffer_object *bo) { dma_resv_assert_held(bo->base.resv); WARN_ON_ONCE(!kref_read(&bo->kref)); - ++bo->pin_count; + if (!(bo->pin_count++) && bo->bulk_move && bo->resource) + ttm_lru_bulk_move_del(bo->bulk_move, bo->resource); } EXPORT_SYMBOL(ttm_bo_pin); @@ -658,10 +699,11 @@ void ttm_bo_unpin(struct ttm_buffer_object *bo) { dma_resv_assert_held(bo->base.resv); WARN_ON_ONCE(!kref_read(&bo->kref)); - if (bo->pin_count) - --bo->pin_count; - else - WARN_ON_ONCE(true); + if (WARN_ON_ONCE(!bo->pin_count)) + return; + + if (!(--bo->pin_count) && bo->bulk_move && bo->resource) + ttm_lru_bulk_move_add(bo->bulk_move, bo->resource); } EXPORT_SYMBOL(ttm_bo_unpin); @@ -906,6 +948,7 @@ int ttm_bo_init_reserved(struct ttm_device *bdev, bo->moving = NULL; bo->pin_count = 0; bo->sg = sg; + bo->bulk_move = NULL; if (resv) { bo->base.resv = resv; dma_resv_assert_held(bo->base.resv); diff --git a/drivers/gpu/drm/ttm/ttm_resource.c b/drivers/gpu/drm/ttm/ttm_resource.c index 19df7350de0f..492ba3157e75 100644 --- a/drivers/gpu/drm/ttm/ttm_resource.c +++ b/drivers/gpu/drm/ttm/ttm_resource.c @@ -73,42 +73,77 @@ void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk) } EXPORT_SYMBOL(ttm_lru_bulk_move_tail); -/* Record a resource position in a bulk move structure */ -static void ttm_lru_bulk_move_set_pos(struct ttm_lru_bulk_move_pos *pos, - struct ttm_resource *res) +/* Return the bulk move pos object for this resource */ +static struct ttm_lru_bulk_move_pos * +ttm_lru_bulk_move_pos(struct ttm_lru_bulk_move *bulk, struct ttm_resource *res) { - if (!pos->first) - pos->first = res; - pos->last = res; + return &bulk->pos[res->mem_type][res->bo->priority]; } -/* Move a resource to the LRU tail and track the bulk position */ -void ttm_resource_move_to_lru_tail(struct ttm_resource *res, - struct ttm_lru_bulk_move *bulk) +/* Move the resource to the tail of the bulk move range */ +static void ttm_lru_bulk_move_pos_tail(struct ttm_lru_bulk_move_pos *pos, + struct ttm_resource *res) +{ + if (pos->last != res) { + list_move(&res->lru, &pos->last->lru); + pos->last = res; + } +} + +/* Add the resource to a bulk_move cursor */ +void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk, + struct ttm_resource *res) +{ + struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res); + + if (!pos->first) { + pos->first = res; + pos->last = res; + } else { + ttm_lru_bulk_move_pos_tail(pos, res); + } +} + +/* Remove the resource from a bulk_move range */ +void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk, + struct ttm_resource *res) +{ + struct ttm_lru_bulk_move_pos *pos = ttm_lru_bulk_move_pos(bulk, res); + + if (unlikely(pos->first == res && pos->last == res)) { + pos->first = NULL; + pos->last = NULL; + } else if (pos->first == res) { + pos->first = list_next_entry(res, lru); + } else if (pos->last == res) { + pos->last = list_prev_entry(res, lru); + } else { + list_move(&res->lru, &pos->last->lru); + } +} + +/* Move a resource to the LRU or bulk tail */ +void ttm_resource_move_to_lru_tail(struct ttm_resource *res) { struct ttm_buffer_object *bo = res->bo; struct ttm_device *bdev = bo->bdev; - struct ttm_resource_manager *man; lockdep_assert_held(&bo->bdev->lru_lock); if (bo->pin_count) { list_move_tail(&res->lru, &bdev->pinned); - if (bdev->funcs->del_from_lru_notify) - bdev->funcs->del_from_lru_notify(res->bo); - return; + + } else if (bo->bulk_move) { + struct ttm_lru_bulk_move_pos *pos = + ttm_lru_bulk_move_pos(bo->bulk_move, res); + + ttm_lru_bulk_move_pos_tail(pos, res); + } else { + struct ttm_resource_manager *man; + + man = ttm_manager_type(bdev, res->mem_type); + list_move_tail(&res->lru, &man->lru[bo->priority]); } - - man = ttm_manager_type(bdev, res->mem_type); - list_move_tail(&res->lru, &man->lru[bo->priority]); - - if (bdev->funcs->del_from_lru_notify) - bdev->funcs->del_from_lru_notify(bo); - - if (!bulk) - return; - - ttm_lru_bulk_move_set_pos(&bulk->pos[res->mem_type][bo->priority], res); } /** @@ -139,7 +174,10 @@ void ttm_resource_init(struct ttm_buffer_object *bo, man = ttm_manager_type(bo->bdev, place->mem_type); spin_lock(&bo->bdev->lru_lock); man->usage += res->num_pages << PAGE_SHIFT; - ttm_resource_move_to_lru_tail(res, NULL); + if (bo->bulk_move) + ttm_lru_bulk_move_add(bo->bulk_move, res); + else + ttm_resource_move_to_lru_tail(res); spin_unlock(&bo->bdev->lru_lock); } EXPORT_SYMBOL(ttm_resource_init); @@ -161,8 +199,6 @@ void ttm_resource_fini(struct ttm_resource_manager *man, spin_lock(&bdev->lru_lock); list_del_init(&res->lru); - if (res->bo && bdev->funcs->del_from_lru_notify) - bdev->funcs->del_from_lru_notify(res->bo); man->usage -= res->num_pages << PAGE_SHIFT; spin_unlock(&bdev->lru_lock); } @@ -185,6 +221,12 @@ void ttm_resource_free(struct ttm_buffer_object *bo, struct ttm_resource **res) if (!*res) return; + if (bo->bulk_move) { + spin_lock(&bo->bdev->lru_lock); + ttm_lru_bulk_move_del(bo->bulk_move, *res); + spin_unlock(&bo->bdev->lru_lock); + } + man = ttm_manager_type(bo->bdev, (*res)->mem_type); man->func->free(man, *res); *res = NULL; diff --git a/include/drm/ttm/ttm_bo_api.h b/include/drm/ttm/ttm_bo_api.h index 885b7698fd65..c61e1e5ceb83 100644 --- a/include/drm/ttm/ttm_bo_api.h +++ b/include/drm/ttm/ttm_bo_api.h @@ -135,6 +135,7 @@ struct ttm_buffer_object { struct ttm_resource *resource; struct ttm_tt *ttm; bool deleted; + struct ttm_lru_bulk_move *bulk_move; /** * Members protected by the bdev::lru_lock. @@ -287,18 +288,9 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, */ void ttm_bo_put(struct ttm_buffer_object *bo); -/** - * ttm_bo_move_to_lru_tail - * - * @bo: The buffer object. - * @bulk: optional bulk move structure to remember BO positions - * - * Move this BO to the tail of all lru lists used to lookup and reserve an - * object. This function must be called with struct ttm_global::lru_lock - * held, and is used to make a BO less likely to be considered for eviction. - */ -void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo, - struct ttm_lru_bulk_move *bulk); +void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo); +void ttm_bo_set_bulk_move(struct ttm_buffer_object *bo, + struct ttm_lru_bulk_move *bulk); /** * ttm_bo_lock_delayed_workqueue diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index 6c7352e13708..059a595e14e5 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h @@ -155,7 +155,7 @@ static inline void ttm_bo_move_to_lru_tail_unlocked(struct ttm_buffer_object *bo) { spin_lock(&bo->bdev->lru_lock); - ttm_bo_move_to_lru_tail(bo, NULL); + ttm_bo_move_to_lru_tail(bo); spin_unlock(&bo->bdev->lru_lock); } diff --git a/include/drm/ttm/ttm_device.h b/include/drm/ttm/ttm_device.h index 425150f35fbe..95b3c04b1ab9 100644 --- a/include/drm/ttm/ttm_device.h +++ b/include/drm/ttm/ttm_device.h @@ -198,15 +198,6 @@ struct ttm_device_funcs { int (*access_memory)(struct ttm_buffer_object *bo, unsigned long offset, void *buf, int len, int write); - /** - * struct ttm_bo_driver member del_from_lru_notify - * - * @bo: the buffer object deleted from lru - * - * notify driver that a BO was deleted from LRU. - */ - void (*del_from_lru_notify)(struct ttm_buffer_object *bo); - /** * Notify the driver that we're about to release a BO * diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 62e7bb782596..4ca960b5cde1 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -206,7 +206,7 @@ struct ttm_resource_cursor { * @first: first res in the bulk move range * @last: last res in the bulk move range * - * Positions for a lru bulk move. + * Range of resources for a lru bulk move. */ struct ttm_lru_bulk_move_pos { struct ttm_resource *first; @@ -220,7 +220,7 @@ struct ttm_lru_bulk_move_pos { * @vram: first/last lru entry for resources in the VRAM domain * * Container for the current bulk move state. Should be used with - * ttm_lru_bulk_move_init() and ttm_bo_move_to_lru_tail(). + * ttm_lru_bulk_move_init() and ttm_bo_set_bulk_move(). */ struct ttm_lru_bulk_move { struct ttm_lru_bulk_move_pos pos[TTM_NUM_MEM_TYPES][TTM_MAX_BO_PRIORITY]; @@ -313,10 +313,13 @@ ttm_resource_manager_cleanup(struct ttm_resource_manager *man) } void ttm_lru_bulk_move_init(struct ttm_lru_bulk_move *bulk); +void ttm_lru_bulk_move_add(struct ttm_lru_bulk_move *bulk, + struct ttm_resource *res); +void ttm_lru_bulk_move_del(struct ttm_lru_bulk_move *bulk, + struct ttm_resource *res); void ttm_lru_bulk_move_tail(struct ttm_lru_bulk_move *bulk); -void ttm_resource_move_to_lru_tail(struct ttm_resource *res, - struct ttm_lru_bulk_move *bulk); +void ttm_resource_move_to_lru_tail(struct ttm_resource *res); void ttm_resource_init(struct ttm_buffer_object *bo, const struct ttm_place *place, From 77ef271faee9c3be65fc5e5dcd66c45d4ffbe494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Fri, 16 Jul 2021 14:37:14 +0200 Subject: [PATCH 00417/11454] drm/amdgpu: drop amdgpu_gtt_node MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have the BO pointer in the base structure now as well. Signed-off-by: Christian König Reviewed-by: Daniel Vetter Tested-by: Bas Nieuwenhuizen Link: https://patchwork.freedesktop.org/patch/msgid/20220321132601.2161-6-christian.koenig@amd.com --- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 49 ++++++++------------- include/drm/ttm/ttm_resource.h | 8 ++++ 2 files changed, 26 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c index 3bcd27ae379d..68494b959116 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c @@ -26,23 +26,12 @@ #include "amdgpu.h" -struct amdgpu_gtt_node { - struct ttm_buffer_object *tbo; - struct ttm_range_mgr_node base; -}; - static inline struct amdgpu_gtt_mgr * to_gtt_mgr(struct ttm_resource_manager *man) { return container_of(man, struct amdgpu_gtt_mgr, manager); } -static inline struct amdgpu_gtt_node * -to_amdgpu_gtt_node(struct ttm_resource *res) -{ - return container_of(res, struct amdgpu_gtt_node, base.base); -} - /** * DOC: mem_info_gtt_total * @@ -106,9 +95,9 @@ const struct attribute_group amdgpu_gtt_mgr_attr_group = { */ bool amdgpu_gtt_mgr_has_gart_addr(struct ttm_resource *res) { - struct amdgpu_gtt_node *node = to_amdgpu_gtt_node(res); + struct ttm_range_mgr_node *node = to_ttm_range_mgr_node(res); - return drm_mm_node_allocated(&node->base.mm_nodes[0]); + return drm_mm_node_allocated(&node->mm_nodes[0]); } /** @@ -128,15 +117,14 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man, { struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); uint32_t num_pages = PFN_UP(tbo->base.size); - struct amdgpu_gtt_node *node; + struct ttm_range_mgr_node *node; int r; - node = kzalloc(struct_size(node, base.mm_nodes, 1), GFP_KERNEL); + node = kzalloc(struct_size(node, mm_nodes, 1), GFP_KERNEL); if (!node) return -ENOMEM; - node->tbo = tbo; - ttm_resource_init(tbo, place, &node->base.base); + ttm_resource_init(tbo, place, &node->base); if (!(place->flags & TTM_PL_FLAG_TEMPORARY) && ttm_resource_manager_usage(man) > man->size) { r = -ENOSPC; @@ -145,8 +133,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man, if (place->lpfn) { spin_lock(&mgr->lock); - r = drm_mm_insert_node_in_range(&mgr->mm, - &node->base.mm_nodes[0], + r = drm_mm_insert_node_in_range(&mgr->mm, &node->mm_nodes[0], num_pages, tbo->page_alignment, 0, place->fpfn, place->lpfn, DRM_MM_INSERT_BEST); @@ -154,18 +141,18 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man, if (unlikely(r)) goto err_free; - node->base.base.start = node->base.mm_nodes[0].start; + node->base.start = node->mm_nodes[0].start; } else { - node->base.mm_nodes[0].start = 0; - node->base.mm_nodes[0].size = node->base.base.num_pages; - node->base.base.start = AMDGPU_BO_INVALID_OFFSET; + node->mm_nodes[0].start = 0; + node->mm_nodes[0].size = node->base.num_pages; + node->base.start = AMDGPU_BO_INVALID_OFFSET; } - *res = &node->base.base; + *res = &node->base; return 0; err_free: - ttm_resource_fini(man, &node->base.base); + ttm_resource_fini(man, &node->base); kfree(node); return r; } @@ -181,12 +168,12 @@ err_free: static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man, struct ttm_resource *res) { - struct amdgpu_gtt_node *node = to_amdgpu_gtt_node(res); + struct ttm_range_mgr_node *node = to_ttm_range_mgr_node(res); struct amdgpu_gtt_mgr *mgr = to_gtt_mgr(man); spin_lock(&mgr->lock); - if (drm_mm_node_allocated(&node->base.mm_nodes[0])) - drm_mm_remove_node(&node->base.mm_nodes[0]); + if (drm_mm_node_allocated(&node->mm_nodes[0])) + drm_mm_remove_node(&node->mm_nodes[0]); spin_unlock(&mgr->lock); ttm_resource_fini(man, res); @@ -202,7 +189,7 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man, */ int amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr) { - struct amdgpu_gtt_node *node; + struct ttm_range_mgr_node *node; struct drm_mm_node *mm_node; struct amdgpu_device *adev; int r = 0; @@ -210,8 +197,8 @@ int amdgpu_gtt_mgr_recover(struct amdgpu_gtt_mgr *mgr) adev = container_of(mgr, typeof(*adev), mman.gtt_mgr); spin_lock(&mgr->lock); drm_mm_for_each_node(mm_node, &mgr->mm) { - node = container_of(mm_node, typeof(*node), base.mm_nodes[0]); - r = amdgpu_ttm_recover_gart(node->tbo); + node = container_of(mm_node, typeof(*node), mm_nodes[0]); + r = amdgpu_ttm_recover_gart(node->base.bo); if (r) break; } diff --git a/include/drm/ttm/ttm_resource.h b/include/drm/ttm/ttm_resource.h index 4ca960b5cde1..4428a62e5f0e 100644 --- a/include/drm/ttm/ttm_resource.h +++ b/include/drm/ttm/ttm_resource.h @@ -355,6 +355,14 @@ ttm_resource_manager_next(struct ttm_resource_manager *man, struct ttm_resource_cursor *cursor, struct ttm_resource *res); +/** + * ttm_resource_manager_for_each_res - iterate over all resources + * @man: the resource manager + * @cursor: struct ttm_resource_cursor for the current position + * @res: the current resource + * + * Iterate over all the evictable resources in a resource manager. + */ #define ttm_resource_manager_for_each_res(man, cursor, res) \ for (res = ttm_resource_manager_first(man, cursor); res; \ res = ttm_resource_manager_next(man, cursor, res)) From bdef417d84536715145f6dc9cc3275c46f26295a Mon Sep 17 00:00:00 2001 From: Xiaomeng Tong Date: Sun, 27 Mar 2022 13:20:28 +0800 Subject: [PATCH 00418/11454] gma500: fix an incorrect NULL check on list iterator The bug is here: return crtc; The list iterator value 'crtc' will *always* be set and non-NULL by list_for_each_entry(), so it is incorrect to assume that the iterator value will be NULL if the list is empty or no element is found. To fix the bug, return 'crtc' when found, otherwise return NULL. Cc: stable@vger.kernel.org fixes: 89c78134cc54d ("gma500: Add Poulsbo support") Signed-off-by: Xiaomeng Tong Signed-off-by: Patrik Jakobsson Link: https://patchwork.freedesktop.org/patch/msgid/20220327052028.2013-1-xiam0nd.tong@gmail.com --- drivers/gpu/drm/gma500/psb_intel_display.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/gma500/psb_intel_display.c b/drivers/gpu/drm/gma500/psb_intel_display.c index fb8234f4d128..dc467996cce4 100644 --- a/drivers/gpu/drm/gma500/psb_intel_display.c +++ b/drivers/gpu/drm/gma500/psb_intel_display.c @@ -524,14 +524,15 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe, struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) { - struct drm_crtc *crtc = NULL; + struct drm_crtc *crtc; list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { struct gma_crtc *gma_crtc = to_gma_crtc(crtc); + if (gma_crtc->pipe == pipe) - break; + return crtc; } - return crtc; + return NULL; } int gma_connector_clones(struct drm_device *dev, int type_mask) From 8b917cbe38e9b0d002492477a9fc2bfee2412ce4 Mon Sep 17 00:00:00 2001 From: Xiaomeng Tong Date: Sun, 27 Mar 2022 14:15:16 +0800 Subject: [PATCH 00419/11454] tilcdc: tilcdc_external: fix an incorrect NULL check on list iterator The bug is here: if (!encoder) { The list iterator value 'encoder' will *always* be set and non-NULL by list_for_each_entry(), so it is incorrect to assume that the iterator value will be NULL if the list is empty or no element is found. To fix the bug, use a new variable 'iter' as the list iterator, while use the original variable 'encoder' as a dedicated pointer to point to the found element. Cc: stable@vger.kernel.org Fixes: ec9eab097a500 ("drm/tilcdc: Add drm bridge support for attaching drm bridge drivers") Signed-off-by: Xiaomeng Tong Reviewed-by: Jyri Sarha Tested-by: Jyri Sarha Signed-off-by: Jyri Sarha Link: https://patchwork.freedesktop.org/patch/msgid/20220327061516.5076-1-xiam0nd.tong@gmail.com --- drivers/gpu/drm/tilcdc/tilcdc_external.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c index 7594cf6e186e..3b86d002ef62 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c @@ -60,11 +60,13 @@ struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev, int tilcdc_add_component_encoder(struct drm_device *ddev) { struct tilcdc_drm_private *priv = ddev->dev_private; - struct drm_encoder *encoder; + struct drm_encoder *encoder = NULL, *iter; - list_for_each_entry(encoder, &ddev->mode_config.encoder_list, head) - if (encoder->possible_crtcs & (1 << priv->crtc->index)) + list_for_each_entry(iter, &ddev->mode_config.encoder_list, head) + if (iter->possible_crtcs & (1 << priv->crtc->index)) { + encoder = iter; break; + } if (!encoder) { dev_err(ddev->dev, "%s: No suitable encoder found\n", __func__); From 657586e474bd025d534d4ea355ec3211d9883cd8 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 22 Mar 2022 16:38:44 +0200 Subject: [PATCH 00420/11454] drm/i915: Add a DP1.2 compatible way to read LTTPR capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit At least some DELL monitors (P2715Q) with DPCD_REV 1.2 return corrupted DPCD register values when reading from the 0xF0000- LTTPR range with an AUX transaction block size bigger than 1. The DP standard requires 0 to be returned - as for any other reserved/invalid addresses - but these monitors return the DPCD_REV register value repeated in each byte of the read buffer. This will in turn corrupt the values returned by the LTTPRs between the source and the monitor: LTTPRs must adjust the values they read from the downstream DPRX, for instance right-shift/init the downstream DP_PHY_REPEATER_CNT value. Since the value returned by the monitor's DPRX is non-zero the adjusted values will be corrupt. Reading the LTTPR registers one-by-one instead of reading all of them with a single AUX transfer works around the issue. According to the DP standard's 0xF0000 register description: "LTTPR-related registers at DPCD Addresses F0000h through F02FFh are valid only for DPCD r1.4 (or higher)." While it's unclear if DPCD r1.4 refers to the DPCD_REV or to the LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV register (tickets filed at the VESA site to clarify this haven't been addressed), one possibility is that it's a restriction due to non-compliant monitors described above. Disabling the non-transparent LTTPR mode for all such monitors is not a viable solution: the transparent LTTPR mode has its own issue causing link training failures and this would affect a lot of monitors in use with DPCD_REV < 1.4. Instead this patch works around the problem by reading the LTTPR common and PHY cap registers one-by-one for any monitor with a DPCD_REV < 1.4. The standard requires the DPCD capabilities to be read after the LTTPR common capabilities are read, so re-read the DPCD capabilities after the LTTPR common and PHY caps were read out. v2: - Use for instead of a while loop. (Ville) - Add to code comment the monitor model with the problem. Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/4531 Cc: Ville Syrjälä Signed-off-by: Imre Deak Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220322143844.42616-1-imre.deak@intel.com --- drivers/gpu/drm/dp/drm_dp.c | 58 ++++++++++++------- .../drm/i915/display/intel_dp_link_training.c | 31 +++++++--- include/drm/dp/drm_dp_helper.h | 2 + 3 files changed, 60 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/dp/drm_dp.c b/drivers/gpu/drm/dp/drm_dp.c index e159b81800d4..b9e5c0bd0d63 100644 --- a/drivers/gpu/drm/dp/drm_dp.c +++ b/drivers/gpu/drm/dp/drm_dp.c @@ -2400,9 +2400,36 @@ int drm_dp_dsc_sink_supported_input_bpcs(const u8 dsc_dpcd[DP_DSC_RECEIVER_CAP_S } EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs); +static int drm_dp_read_lttpr_regs(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], int address, + u8 *buf, int buf_size) +{ + /* + * At least the DELL P2715Q monitor with a DPCD_REV < 0x14 returns + * corrupted values when reading from the 0xF0000- range with a block + * size bigger than 1. + */ + int block_size = dpcd[DP_DPCD_REV] < 0x14 ? 1 : buf_size; + int offset; + int ret; + + for (offset = 0; offset < buf_size; offset += block_size) { + ret = drm_dp_dpcd_read(aux, + address + offset, + &buf[offset], block_size); + if (ret < 0) + return ret; + + WARN_ON(ret != block_size); + } + + return 0; +} + /** * drm_dp_read_lttpr_common_caps - read the LTTPR common capabilities * @aux: DisplayPort AUX channel + * @dpcd: DisplayPort configuration data * @caps: buffer to return the capability info in * * Read capabilities common to all LTTPRs. @@ -2410,25 +2437,19 @@ EXPORT_SYMBOL(drm_dp_dsc_sink_supported_input_bpcs); * Returns 0 on success or a negative error code on failure. */ int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], u8 caps[DP_LTTPR_COMMON_CAP_SIZE]) { - int ret; - - ret = drm_dp_dpcd_read(aux, - DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, - caps, DP_LTTPR_COMMON_CAP_SIZE); - if (ret < 0) - return ret; - - WARN_ON(ret != DP_LTTPR_COMMON_CAP_SIZE); - - return 0; + return drm_dp_read_lttpr_regs(aux, dpcd, + DP_LT_TUNABLE_PHY_REPEATER_FIELD_DATA_STRUCTURE_REV, + caps, DP_LTTPR_COMMON_CAP_SIZE); } EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps); /** * drm_dp_read_lttpr_phy_caps - read the capabilities for a given LTTPR PHY * @aux: DisplayPort AUX channel + * @dpcd: DisplayPort configuration data * @dp_phy: LTTPR PHY to read the capabilities for * @caps: buffer to return the capability info in * @@ -2437,20 +2458,13 @@ EXPORT_SYMBOL(drm_dp_read_lttpr_common_caps); * Returns 0 on success or a negative error code on failure. */ int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], enum drm_dp_phy dp_phy, u8 caps[DP_LTTPR_PHY_CAP_SIZE]) { - int ret; - - ret = drm_dp_dpcd_read(aux, - DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy), - caps, DP_LTTPR_PHY_CAP_SIZE); - if (ret < 0) - return ret; - - WARN_ON(ret != DP_LTTPR_PHY_CAP_SIZE); - - return 0; + return drm_dp_read_lttpr_regs(aux, dpcd, + DP_TRAINING_AUX_RD_INTERVAL_PHY_REPEATER(dp_phy), + caps, DP_LTTPR_PHY_CAP_SIZE); } EXPORT_SYMBOL(drm_dp_read_lttpr_phy_caps); diff --git a/drivers/gpu/drm/i915/display/intel_dp_link_training.c b/drivers/gpu/drm/i915/display/intel_dp_link_training.c index 5d98773efd1b..26f9e2b748e4 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/display/intel_dp_link_training.c @@ -55,6 +55,7 @@ static u8 *intel_dp_lttpr_phy_caps(struct intel_dp *intel_dp, } static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], enum drm_dp_phy dp_phy) { struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; @@ -63,7 +64,7 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp, intel_dp_phy_name(dp_phy, phy_name, sizeof(phy_name)); - if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dp_phy, phy_caps) < 0) { + if (drm_dp_read_lttpr_phy_caps(&intel_dp->aux, dpcd, dp_phy, phy_caps) < 0) { drm_dbg_kms(&dp_to_i915(intel_dp)->drm, "[ENCODER:%d:%s][%s] failed to read the PHY caps\n", encoder->base.base.id, encoder->base.name, phy_name); @@ -77,10 +78,12 @@ static void intel_dp_read_lttpr_phy_caps(struct intel_dp *intel_dp, phy_caps); } -static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp) +static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp, + const u8 dpcd[DP_RECEIVER_CAP_SIZE]) { struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; struct drm_i915_private *i915 = to_i915(encoder->base.dev); + int ret; if (intel_dp_is_edp(intel_dp)) return false; @@ -92,8 +95,9 @@ static bool intel_dp_read_lttpr_common_caps(struct intel_dp *intel_dp) if (DISPLAY_VER(i915) < 10 || IS_GEMINILAKE(i915)) return false; - if (drm_dp_read_lttpr_common_caps(&intel_dp->aux, - intel_dp->lttpr_common_caps) < 0) + ret = drm_dp_read_lttpr_common_caps(&intel_dp->aux, dpcd, + intel_dp->lttpr_common_caps); + if (ret < 0) goto reset_caps; drm_dbg_kms(&dp_to_i915(intel_dp)->drm, @@ -122,14 +126,14 @@ intel_dp_set_lttpr_transparent_mode(struct intel_dp *intel_dp, bool enable) return drm_dp_dpcd_write(&intel_dp->aux, DP_PHY_REPEATER_MODE, &val, 1) == 1; } -static int intel_dp_init_lttpr(struct intel_dp *intel_dp) +static int intel_dp_init_lttpr(struct intel_dp *intel_dp, const u8 dpcd[DP_RECEIVER_CAP_SIZE]) { struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; struct drm_i915_private *i915 = to_i915(encoder->base.dev); int lttpr_count; int i; - if (!intel_dp_read_lttpr_common_caps(intel_dp)) + if (!intel_dp_read_lttpr_common_caps(intel_dp, dpcd)) return 0; lttpr_count = drm_dp_lttpr_count(intel_dp->lttpr_common_caps); @@ -168,7 +172,7 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp) } for (i = 0; i < lttpr_count; i++) - intel_dp_read_lttpr_phy_caps(intel_dp, DP_PHY_LTTPR(i)); + intel_dp_read_lttpr_phy_caps(intel_dp, dpcd, DP_PHY_LTTPR(i)); return lttpr_count; } @@ -193,9 +197,18 @@ static int intel_dp_init_lttpr(struct intel_dp *intel_dp) */ int intel_dp_init_lttpr_and_dprx_caps(struct intel_dp *intel_dp) { - int lttpr_count = intel_dp_init_lttpr(intel_dp); + u8 dpcd[DP_RECEIVER_CAP_SIZE]; + int lttpr_count; - /* The DPTX shall read the DPRX caps after LTTPR detection. */ + if (drm_dp_read_dpcd_caps(&intel_dp->aux, dpcd)) + return -EIO; + + lttpr_count = intel_dp_init_lttpr(intel_dp, dpcd); + + /* + * The DPTX shall read the DPRX caps after LTTPR detection, so re-read + * it here. + */ if (drm_dp_read_dpcd_caps(&intel_dp->aux, intel_dp->dpcd)) { intel_dp_reset_lttpr_common_caps(intel_dp); return -EIO; diff --git a/include/drm/dp/drm_dp_helper.h b/include/drm/dp/drm_dp_helper.h index 69487bd8ed56..8c0d22faad9a 100644 --- a/include/drm/dp/drm_dp_helper.h +++ b/include/drm/dp/drm_dp_helper.h @@ -2150,8 +2150,10 @@ bool drm_dp_read_sink_count_cap(struct drm_connector *connector, int drm_dp_read_sink_count(struct drm_dp_aux *aux); int drm_dp_read_lttpr_common_caps(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], u8 caps[DP_LTTPR_COMMON_CAP_SIZE]); int drm_dp_read_lttpr_phy_caps(struct drm_dp_aux *aux, + const u8 dpcd[DP_RECEIVER_CAP_SIZE], enum drm_dp_phy dp_phy, u8 caps[DP_LTTPR_PHY_CAP_SIZE]); int drm_dp_lttpr_count(const u8 cap[DP_LTTPR_COMMON_CAP_SIZE]); From faacff8e6a5209b0b6a57fa58ba292742ab442d2 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:22 +0300 Subject: [PATCH 00421/11454] drm/edid: don't modify EDID while parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We'll want to keep the EDID immutable while parsing. Stop modifying the EDID because of the quirks. In theory, this does have userspace implications, but the userspace is supposed to use the modes exposed via KMS API, not by parsing the EDID directly. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/45d5cf067eaad49b321ac82836090d9de524374e.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index a7663f9a11d2..0e434ab7908c 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2740,9 +2740,9 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, return NULL; if (quirks & EDID_QUIRK_135_CLOCK_TOO_HIGH) - timing->pixel_clock = cpu_to_le16(1088); - - mode->clock = le16_to_cpu(timing->pixel_clock) * 10; + mode->clock = 1088 * 10; + else + mode->clock = le16_to_cpu(timing->pixel_clock) * 10; mode->hdisplay = hactive; mode->hsync_start = mode->hdisplay + hsync_offset; @@ -2763,14 +2763,14 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, drm_mode_do_interlace_quirk(mode, pt); if (quirks & EDID_QUIRK_DETAILED_SYNC_PP) { - pt->misc |= DRM_EDID_PT_HSYNC_POSITIVE | DRM_EDID_PT_VSYNC_POSITIVE; + mode->flags |= DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC; + } else { + mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? + DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; + mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? + DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; } - mode->flags |= (pt->misc & DRM_EDID_PT_HSYNC_POSITIVE) ? - DRM_MODE_FLAG_PHSYNC : DRM_MODE_FLAG_NHSYNC; - mode->flags |= (pt->misc & DRM_EDID_PT_VSYNC_POSITIVE) ? - DRM_MODE_FLAG_PVSYNC : DRM_MODE_FLAG_NVSYNC; - set_size: mode->width_mm = pt->width_mm_lo | (pt->width_height_mm_hi & 0xf0) << 4; mode->height_mm = pt->height_mm_lo | (pt->width_height_mm_hi & 0xf) << 8; From 73091e4fb78b5d88913593012ad74a1c0ff266da Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:23 +0300 Subject: [PATCH 00422/11454] drm/edid: fix reduced blanking support check MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reduced blanking bit is valid only for CVT, indicated by display range limits flags 0x04. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/5dea5ee24065450716bbc177dd6850d3193dbeec.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 0e434ab7908c..aa4ba35b40cf 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2408,7 +2408,7 @@ is_rb(struct detailed_timing *t, void *data) if (!is_display_descriptor(r, EDID_DETAIL_MONITOR_RANGE)) return; - if (r[15] & 0x10) + if (r[10] == DRM_EDID_CVT_SUPPORT_FLAG && r[15] & 0x10) *(bool *)data = true; } From e379814b5fb719b22c01c7a81f14b98cbaac3c42 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:24 +0300 Subject: [PATCH 00423/11454] drm/edid: pass a timing pointer to is_display_descriptor() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use struct member access instead of direct offsets to avoid lots of casts all over the place. Use BUILD_BUG_ON() for sanity check. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/ccc54b45ea628874c0290dd64114da6cefff1819.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index aa4ba35b40cf..f6b9b818aaf9 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2331,10 +2331,15 @@ struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, } EXPORT_SYMBOL(drm_mode_find_dmt); -static bool is_display_descriptor(const u8 d[18], u8 tag) +static bool is_display_descriptor(const struct detailed_timing *descriptor, u8 type) { - return d[0] == 0x00 && d[1] == 0x00 && - d[2] == 0x00 && d[3] == tag; + BUILD_BUG_ON(offsetof(typeof(*descriptor), pixel_clock) != 0); + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.pad1) != 2); + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.type) != 3); + + return descriptor->pixel_clock == 0 && + descriptor->data.other_data.pad1 == 0 && + descriptor->data.other_data.type == type; } static bool is_detailed_timing_descriptor(const u8 d[18]) @@ -2405,7 +2410,7 @@ is_rb(struct detailed_timing *t, void *data) { u8 *r = (u8 *)t; - if (!is_display_descriptor(r, EDID_DETAIL_MONITOR_RANGE)) + if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE)) return; if (r[10] == DRM_EDID_CVT_SUPPORT_FLAG && r[15] & 0x10) @@ -2431,7 +2436,7 @@ find_gtf2(struct detailed_timing *t, void *data) { u8 *r = (u8 *)t; - if (!is_display_descriptor(r, EDID_DETAIL_MONITOR_RANGE)) + if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE)) return; if (r[10] == 0x02) @@ -2987,7 +2992,7 @@ do_inferred_modes(struct detailed_timing *timing, void *c) struct detailed_non_pixel *data = &timing->data.other_data; struct detailed_data_monitor_range *range = &data->data.range; - if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_MONITOR_RANGE)) + if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE)) return; closure->modes += drm_dmt_modes_for_range(closure->connector, @@ -3067,7 +3072,7 @@ do_established_modes(struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; - if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_EST_TIMINGS)) + if (!is_display_descriptor(timing, EDID_DETAIL_EST_TIMINGS)) return; closure->modes += drm_est3_modes(closure->connector, timing); @@ -3122,7 +3127,7 @@ do_standard_modes(struct detailed_timing *timing, void *c) struct edid *edid = closure->edid; int i; - if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_STD_MODES)) + if (!is_display_descriptor(timing, EDID_DETAIL_STD_MODES)) return; for (i = 0; i < 6; i++) { @@ -3231,7 +3236,7 @@ do_cvt_mode(struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; - if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_CVT_3BYTE)) + if (!is_display_descriptor(timing, EDID_DETAIL_CVT_3BYTE)) return; closure->modes += drm_cvt_modes(closure->connector, timing); @@ -4491,7 +4496,7 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db) static void monitor_name(struct detailed_timing *t, void *data) { - if (!is_display_descriptor((const u8 *)t, EDID_DETAIL_MONITOR_NAME)) + if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_NAME)) return; *(u8 **)data = t->data.other_data.data.str.str; @@ -5221,7 +5226,7 @@ void get_monitor_range(struct detailed_timing *timing, const struct detailed_non_pixel *data = &timing->data.other_data; const struct detailed_data_monitor_range *range = &data->data.range; - if (!is_display_descriptor((const u8 *)timing, EDID_DETAIL_MONITOR_RANGE)) + if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE)) return; /* From a9b1f15f53313f967edd5088a60970cc829ab5a6 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:25 +0300 Subject: [PATCH 00424/11454] drm/edid: pass a timing pointer to is_detailed_timing_descriptor() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use struct member access instead of direct offsets to avoid a cast. Use BUILD_BUG_ON() for sanity check. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/0b5213383e14f11c6a505b10a7342fb2ff4f2a11.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index f6b9b818aaf9..1ebf434b2f0b 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2342,9 +2342,11 @@ static bool is_display_descriptor(const struct detailed_timing *descriptor, u8 t descriptor->data.other_data.type == type; } -static bool is_detailed_timing_descriptor(const u8 d[18]) +static bool is_detailed_timing_descriptor(const struct detailed_timing *descriptor) { - return d[0] != 0x00 || d[1] != 0x00; + BUILD_BUG_ON(offsetof(typeof(*descriptor), pixel_clock) != 0); + + return descriptor->pixel_clock != 0; } typedef void detailed_cb(struct detailed_timing *timing, void *closure); @@ -3266,7 +3268,7 @@ do_detailed_mode(struct detailed_timing *timing, void *c) struct detailed_mode_closure *closure = c; struct drm_display_mode *newmode; - if (!is_detailed_timing_descriptor((const u8 *)timing)) + if (!is_detailed_timing_descriptor(timing)) return; newmode = drm_mode_detailed(closure->connector->dev, From 90fd588f03a6392533c9e46c16dd4e50a12184ae Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:26 +0300 Subject: [PATCH 00425/11454] drm/edid: use struct detailed_timing member access in is_rb() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use struct detailed_timing member access instead of direct offsets to avoid casting. Use BUILD_BUG_ON() for sanity check. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/c069669c2fe8f9c3061c7d1a413c75a33ec48813.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 1ebf434b2f0b..d842d5fc0b81 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2408,15 +2408,19 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) } static void -is_rb(struct detailed_timing *t, void *data) +is_rb(struct detailed_timing *descriptor, void *data) { - u8 *r = (u8 *)t; + bool *res = data; - if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE)) + if (!is_display_descriptor(descriptor, EDID_DETAIL_MONITOR_RANGE)) return; - if (r[10] == DRM_EDID_CVT_SUPPORT_FLAG && r[15] & 0x10) - *(bool *)data = true; + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.flags) != 10); + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.cvt.flags) != 15); + + if (descriptor->data.other_data.data.range.flags == DRM_EDID_CVT_SUPPORT_FLAG && + descriptor->data.other_data.data.range.formula.cvt.flags & 0x10) + *res = true; } /* EDID 1.4 defines this explicitly. For EDID 1.3, we guess, badly. */ From c8a4beba19a56cb45cfc8b68f146eb63a25f7841 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:27 +0300 Subject: [PATCH 00426/11454] drm/edid: use struct detailed_timing member access in gtf2 functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use struct detailed_timing member access instead of direct offsets to avoid casting. Use BUILD_BUG_ON() for sanity check. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/9fe5f5c39039e585fecfffb390297d49262e5fd3.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 57 +++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index d842d5fc0b81..d188ac8ce2e2 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2438,61 +2438,78 @@ drm_monitor_supports_rb(struct edid *edid) } static void -find_gtf2(struct detailed_timing *t, void *data) +find_gtf2(struct detailed_timing *descriptor, void *data) { - u8 *r = (u8 *)t; + struct detailed_timing **res = data; - if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_RANGE)) + if (!is_display_descriptor(descriptor, EDID_DETAIL_MONITOR_RANGE)) return; - if (r[10] == 0x02) - *(u8 **)data = r; + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.flags) != 10); + + if (descriptor->data.other_data.data.range.flags == 0x02) + *res = descriptor; } /* Secondary GTF curve kicks in above some break frequency */ static int drm_gtf2_hbreak(struct edid *edid) { - u8 *r = NULL; + struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); - return r ? (r[12] * 2) : 0; + drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.hfreq_start_khz) != 12); + + return descriptor ? descriptor->data.other_data.data.range.formula.gtf2.hfreq_start_khz * 2 : 0; } static int drm_gtf2_2c(struct edid *edid) { - u8 *r = NULL; + struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); - return r ? r[13] : 0; + drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.c) != 13); + + return descriptor ? descriptor->data.other_data.data.range.formula.gtf2.c : 0; } static int drm_gtf2_m(struct edid *edid) { - u8 *r = NULL; + struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); - return r ? (r[15] << 8) + r[14] : 0; + drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.m) != 14); + + return descriptor ? le16_to_cpu(descriptor->data.other_data.data.range.formula.gtf2.m) : 0; } static int drm_gtf2_k(struct edid *edid) { - u8 *r = NULL; + struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); - return r ? r[16] : 0; + drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.k) != 16); + + return descriptor ? descriptor->data.other_data.data.range.formula.gtf2.k : 0; } static int drm_gtf2_2j(struct edid *edid) { - u8 *r = NULL; + struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &r); - return r ? r[17] : 0; + drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + + BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.j) != 17); + + return descriptor ? descriptor->data.other_data.data.range.formula.gtf2.j : 0; } /** From fcfb2ea19868f18065ba49add81cc10533d237da Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:28 +0300 Subject: [PATCH 00427/11454] drm/edid: constify struct detailed_timing in lower level parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Start constifying the struct detailed_timing pointers being passed around from bottom up. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/0b7fafcc7784db0003e454544916c273a9eb1250.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 40 +++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index d188ac8ce2e2..0d34d9906324 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2560,7 +2560,7 @@ static int drm_mode_hsync(const struct drm_display_mode *mode) */ static struct drm_display_mode * drm_mode_std(struct drm_connector *connector, struct edid *edid, - struct std_timing *t) + const struct std_timing *t) { struct drm_device *dev = connector->dev; struct drm_display_mode *m, *mode = NULL; @@ -2678,7 +2678,7 @@ drm_mode_std(struct drm_connector *connector, struct edid *edid, */ static void drm_mode_do_interlace_quirk(struct drm_display_mode *mode, - struct detailed_pixel_timing *pt) + const struct detailed_pixel_timing *pt) { int i; static const struct { @@ -2722,11 +2722,11 @@ drm_mode_do_interlace_quirk(struct drm_display_mode *mode, */ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, struct edid *edid, - struct detailed_timing *timing, + const struct detailed_timing *timing, u32 quirks) { struct drm_display_mode *mode; - struct detailed_pixel_timing *pt = &timing->data.pixel_data; + const struct detailed_pixel_timing *pt = &timing->data.pixel_data; unsigned hactive = (pt->hactive_hblank_hi & 0xf0) << 4 | pt->hactive_lo; unsigned vactive = (pt->vactive_vblank_hi & 0xf0) << 4 | pt->vactive_lo; unsigned hblank = (pt->hactive_hblank_hi & 0xf) << 8 | pt->hblank_lo; @@ -2821,7 +2821,7 @@ set_size: static bool mode_in_hsync_range(const struct drm_display_mode *mode, - struct edid *edid, u8 *t) + struct edid *edid, const u8 *t) { int hsync, hmin, hmax; @@ -2838,7 +2838,7 @@ mode_in_hsync_range(const struct drm_display_mode *mode, static bool mode_in_vsync_range(const struct drm_display_mode *mode, - struct edid *edid, u8 *t) + struct edid *edid, const u8 *t) { int vsync, vmin, vmax; @@ -2854,7 +2854,7 @@ mode_in_vsync_range(const struct drm_display_mode *mode, } static u32 -range_pixel_clock(struct edid *edid, u8 *t) +range_pixel_clock(struct edid *edid, const u8 *t) { /* unspecified */ if (t[9] == 0 || t[9] == 255) @@ -2870,10 +2870,10 @@ range_pixel_clock(struct edid *edid, u8 *t) static bool mode_in_range(const struct drm_display_mode *mode, struct edid *edid, - struct detailed_timing *timing) + const struct detailed_timing *timing) { u32 max_clock; - u8 *t = (u8 *)timing; + const u8 *t = (const u8 *)timing; if (!mode_in_hsync_range(mode, edid, t)) return false; @@ -2916,7 +2916,7 @@ static bool valid_inferred_mode(const struct drm_connector *connector, static int drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid, - struct detailed_timing *timing) + const struct detailed_timing *timing) { int i, modes = 0; struct drm_display_mode *newmode; @@ -2951,7 +2951,7 @@ void drm_mode_fixup_1366x768(struct drm_display_mode *mode) static int drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, - struct detailed_timing *timing) + const struct detailed_timing *timing) { int i, modes = 0; struct drm_display_mode *newmode; @@ -2980,7 +2980,7 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, static int drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid, - struct detailed_timing *timing) + const struct detailed_timing *timing) { int i, modes = 0; struct drm_display_mode *newmode; @@ -3012,8 +3012,8 @@ static void do_inferred_modes(struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; - struct detailed_non_pixel *data = &timing->data.other_data; - struct detailed_data_monitor_range *range = &data->data.range; + const struct detailed_non_pixel *data = &timing->data.other_data; + const struct detailed_data_monitor_range *range = &data->data.range; if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_RANGE)) return; @@ -3062,11 +3062,11 @@ add_inferred_modes(struct drm_connector *connector, struct edid *edid) } static int -drm_est3_modes(struct drm_connector *connector, struct detailed_timing *timing) +drm_est3_modes(struct drm_connector *connector, const struct detailed_timing *timing) { int i, j, m, modes = 0; struct drm_display_mode *mode; - u8 *est = ((u8 *)timing) + 6; + const u8 *est = ((const u8 *)timing) + 6; for (i = 0; i < 6; i++) { for (j = 7; j >= 0; j--) { @@ -3145,7 +3145,7 @@ static void do_standard_modes(struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; - struct detailed_non_pixel *data = &timing->data.other_data; + const struct detailed_non_pixel *data = &timing->data.other_data; struct drm_connector *connector = closure->connector; struct edid *edid = closure->edid; int i; @@ -3154,7 +3154,7 @@ do_standard_modes(struct detailed_timing *timing, void *c) return; for (i = 0; i < 6; i++) { - struct std_timing *std = &data->data.timings[i]; + const struct std_timing *std = &data->data.timings[i]; struct drm_display_mode *newmode; newmode = drm_mode_std(connector, edid, std); @@ -3203,12 +3203,12 @@ add_standard_modes(struct drm_connector *connector, struct edid *edid) } static int drm_cvt_modes(struct drm_connector *connector, - struct detailed_timing *timing) + const struct detailed_timing *timing) { int i, j, modes = 0; struct drm_display_mode *newmode; struct drm_device *dev = connector->dev; - struct cvt_timing *cvt; + const struct cvt_timing *cvt; const int rates[] = { 60, 85, 75, 60, 50 }; const u8 empty[3] = { 0, 0, 0 }; From 4194442daf053754cc6b726b3d624223dd5458d8 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:29 +0300 Subject: [PATCH 00428/11454] drm/edid: constify struct detailed_timing in parsing callbacks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moving one level higher, constify struct detailed_timing pointers in callbacks. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/9b617068d2349a574a837ad6207b1d45c4d79eb5.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 40 ++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 0d34d9906324..e90dc6ed3498 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2349,7 +2349,7 @@ static bool is_detailed_timing_descriptor(const struct detailed_timing *descript return descriptor->pixel_clock != 0; } -typedef void detailed_cb(struct detailed_timing *timing, void *closure); +typedef void detailed_cb(const struct detailed_timing *timing, void *closure); static void cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) @@ -2408,7 +2408,7 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) } static void -is_rb(struct detailed_timing *descriptor, void *data) +is_rb(const struct detailed_timing *descriptor, void *data) { bool *res = data; @@ -2438,9 +2438,9 @@ drm_monitor_supports_rb(struct edid *edid) } static void -find_gtf2(struct detailed_timing *descriptor, void *data) +find_gtf2(const struct detailed_timing *descriptor, void *data) { - struct detailed_timing **res = data; + const struct detailed_timing **res = data; if (!is_display_descriptor(descriptor, EDID_DETAIL_MONITOR_RANGE)) return; @@ -2455,7 +2455,7 @@ find_gtf2(struct detailed_timing *descriptor, void *data) static int drm_gtf2_hbreak(struct edid *edid) { - struct detailed_timing *descriptor = NULL; + const struct detailed_timing *descriptor = NULL; drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); @@ -2467,7 +2467,7 @@ drm_gtf2_hbreak(struct edid *edid) static int drm_gtf2_2c(struct edid *edid) { - struct detailed_timing *descriptor = NULL; + const struct detailed_timing *descriptor = NULL; drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); @@ -2479,7 +2479,7 @@ drm_gtf2_2c(struct edid *edid) static int drm_gtf2_m(struct edid *edid) { - struct detailed_timing *descriptor = NULL; + const struct detailed_timing *descriptor = NULL; drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); @@ -2491,7 +2491,7 @@ drm_gtf2_m(struct edid *edid) static int drm_gtf2_k(struct edid *edid) { - struct detailed_timing *descriptor = NULL; + const struct detailed_timing *descriptor = NULL; drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); @@ -2503,7 +2503,7 @@ drm_gtf2_k(struct edid *edid) static int drm_gtf2_2j(struct edid *edid) { - struct detailed_timing *descriptor = NULL; + const struct detailed_timing *descriptor = NULL; drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); @@ -3009,7 +3009,7 @@ drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid, } static void -do_inferred_modes(struct detailed_timing *timing, void *c) +do_inferred_modes(const struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; const struct detailed_non_pixel *data = &timing->data.other_data; @@ -3091,7 +3091,7 @@ drm_est3_modes(struct drm_connector *connector, const struct detailed_timing *ti } static void -do_established_modes(struct detailed_timing *timing, void *c) +do_established_modes(const struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; @@ -3142,7 +3142,7 @@ add_established_modes(struct drm_connector *connector, struct edid *edid) } static void -do_standard_modes(struct detailed_timing *timing, void *c) +do_standard_modes(const struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; const struct detailed_non_pixel *data = &timing->data.other_data; @@ -3255,7 +3255,7 @@ static int drm_cvt_modes(struct drm_connector *connector, } static void -do_cvt_mode(struct detailed_timing *timing, void *c) +do_cvt_mode(const struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; @@ -3284,7 +3284,7 @@ add_cvt_modes(struct drm_connector *connector, struct edid *edid) static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode); static void -do_detailed_mode(struct detailed_timing *timing, void *c) +do_detailed_mode(const struct detailed_timing *timing, void *c) { struct detailed_mode_closure *closure = c; struct drm_display_mode *newmode; @@ -4517,17 +4517,19 @@ drm_parse_hdmi_vsdb_audio(struct drm_connector *connector, const u8 *db) } static void -monitor_name(struct detailed_timing *t, void *data) +monitor_name(const struct detailed_timing *timing, void *data) { - if (!is_display_descriptor(t, EDID_DETAIL_MONITOR_NAME)) + const char **res = data; + + if (!is_display_descriptor(timing, EDID_DETAIL_MONITOR_NAME)) return; - *(u8 **)data = t->data.other_data.data.str.str; + *res = timing->data.other_data.data.str.str; } static int get_monitor_name(struct edid *edid, char name[13]) { - char *edid_name = NULL; + const char *edid_name = NULL; int mnl; if (!edid || !name) @@ -5242,7 +5244,7 @@ static void drm_parse_cea_ext(struct drm_connector *connector, } static -void get_monitor_range(struct detailed_timing *timing, +void get_monitor_range(const struct detailed_timing *timing, void *info_monitor_range) { struct drm_monitor_range_info *monitor_range = info_monitor_range; From eed628f116a7004f9ef751537d603f8b3d785298 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:30 +0300 Subject: [PATCH 00429/11454] drm/edid: constify struct edid passed to detailed blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Constify the first level of struct edid in detailed timing parsing. Also switch to struct edid instead of u8. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/ec7acb8a9ee0e2868bbb2afdfdd7db114ae180e1.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 48 ++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index e90dc6ed3498..f04e3d241c8d 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2352,38 +2352,37 @@ static bool is_detailed_timing_descriptor(const struct detailed_timing *descript typedef void detailed_cb(const struct detailed_timing *timing, void *closure); static void -cea_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) +cea_for_each_detailed_block(const u8 *ext, detailed_cb *cb, void *closure) { int i, n; u8 d = ext[0x02]; - u8 *det_base = ext + d; + const u8 *det_base = ext + d; if (d < 4 || d > 127) return; n = (127 - d) / 18; for (i = 0; i < n; i++) - cb((struct detailed_timing *)(det_base + 18 * i), closure); + cb((const struct detailed_timing *)(det_base + 18 * i), closure); } static void -vtb_for_each_detailed_block(u8 *ext, detailed_cb *cb, void *closure) +vtb_for_each_detailed_block(const u8 *ext, detailed_cb *cb, void *closure) { unsigned int i, n = min((int)ext[0x02], 6); - u8 *det_base = ext + 5; + const u8 *det_base = ext + 5; if (ext[0x01] != 1) return; /* unknown version */ for (i = 0; i < n; i++) - cb((struct detailed_timing *)(det_base + 18 * i), closure); + cb((const struct detailed_timing *)(det_base + 18 * i), closure); } static void -drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) +drm_for_each_detailed_block(const struct edid *edid, detailed_cb *cb, void *closure) { int i; - struct edid *edid = (struct edid *)raw_edid; if (edid == NULL) return; @@ -2391,8 +2390,8 @@ drm_for_each_detailed_block(u8 *raw_edid, detailed_cb *cb, void *closure) for (i = 0; i < EDID_DETAILED_TIMINGS; i++) cb(&(edid->detailed_timings[i]), closure); - for (i = 1; i <= raw_edid[0x7e]; i++) { - u8 *ext = raw_edid + (i * EDID_LENGTH); + for (i = 1; i <= edid->extensions; i++) { + const u8 *ext = (const u8 *)edid + (i * EDID_LENGTH); switch (*ext) { case CEA_EXT: @@ -2430,7 +2429,7 @@ drm_monitor_supports_rb(struct edid *edid) if (edid->revision >= 4) { bool ret = false; - drm_for_each_detailed_block((u8 *)edid, is_rb, &ret); + drm_for_each_detailed_block(edid, is_rb, &ret); return ret; } @@ -2457,7 +2456,7 @@ drm_gtf2_hbreak(struct edid *edid) { const struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(edid, find_gtf2, &descriptor); BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.hfreq_start_khz) != 12); @@ -2469,7 +2468,7 @@ drm_gtf2_2c(struct edid *edid) { const struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(edid, find_gtf2, &descriptor); BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.c) != 13); @@ -2481,7 +2480,7 @@ drm_gtf2_m(struct edid *edid) { const struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(edid, find_gtf2, &descriptor); BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.m) != 14); @@ -2493,7 +2492,7 @@ drm_gtf2_k(struct edid *edid) { const struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(edid, find_gtf2, &descriptor); BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.k) != 16); @@ -2505,7 +2504,7 @@ drm_gtf2_2j(struct edid *edid) { const struct detailed_timing *descriptor = NULL; - drm_for_each_detailed_block((u8 *)edid, find_gtf2, &descriptor); + drm_for_each_detailed_block(edid, find_gtf2, &descriptor); BUILD_BUG_ON(offsetof(typeof(*descriptor), data.other_data.data.range.formula.gtf2.j) != 17); @@ -3055,8 +3054,7 @@ add_inferred_modes(struct drm_connector *connector, struct edid *edid) }; if (version_greater(edid, 1, 0)) - drm_for_each_detailed_block((u8 *)edid, do_inferred_modes, - &closure); + drm_for_each_detailed_block(edid, do_inferred_modes, &closure); return closure.modes; } @@ -3135,8 +3133,8 @@ add_established_modes(struct drm_connector *connector, struct edid *edid) } if (version_greater(edid, 1, 0)) - drm_for_each_detailed_block((u8 *)edid, - do_established_modes, &closure); + drm_for_each_detailed_block(edid, do_established_modes, + &closure); return modes + closure.modes; } @@ -3194,7 +3192,7 @@ add_standard_modes(struct drm_connector *connector, struct edid *edid) } if (version_greater(edid, 1, 0)) - drm_for_each_detailed_block((u8 *)edid, do_standard_modes, + drm_for_each_detailed_block(edid, do_standard_modes, &closure); /* XXX should also look for standard codes in VTB blocks */ @@ -3274,7 +3272,7 @@ add_cvt_modes(struct drm_connector *connector, struct edid *edid) }; if (version_greater(edid, 1, 2)) - drm_for_each_detailed_block((u8 *)edid, do_cvt_mode, &closure); + drm_for_each_detailed_block(edid, do_cvt_mode, &closure); /* XXX should also look for CVT codes in VTB blocks */ @@ -3334,7 +3332,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, closure.preferred = (edid->features & DRM_EDID_FEATURE_PREFERRED_TIMING); - drm_for_each_detailed_block((u8 *)edid, do_detailed_mode, &closure); + drm_for_each_detailed_block(edid, do_detailed_mode, &closure); return closure.modes; } @@ -4535,7 +4533,7 @@ static int get_monitor_name(struct edid *edid, char name[13]) if (!edid || !name) return 0; - drm_for_each_detailed_block((u8 *)edid, monitor_name, &edid_name); + drm_for_each_detailed_block(edid, monitor_name, &edid_name); for (mnl = 0; edid_name && mnl < 13; mnl++) { if (edid_name[mnl] == 0x0a) break; @@ -5276,7 +5274,7 @@ void drm_get_monitor_range(struct drm_connector *connector, if (!version_greater(edid, 1, 1)) return; - drm_for_each_detailed_block((u8 *)edid, get_monitor_range, + drm_for_each_detailed_block(edid, get_monitor_range, &info->monitor_range); DRM_DEBUG_KMS("Supported Monitor Refresh rate range is %d Hz - %d Hz\n", From c14e724114fe0e90685297e6c10ebdb14d40a7ec Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:31 +0300 Subject: [PATCH 00430/11454] drm/edid: constify struct edid passed around in callbacks and closure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finalize detailed timing parsing constness by making struct edid also const in callbacks and closure. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/8229be49b5a7686856c17428aa9291b4c4cf1bd5.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 48 +++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index f04e3d241c8d..fee47ac1bdd8 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -97,7 +97,7 @@ static int oui(u8 first, u8 second, u8 third) struct detailed_mode_closure { struct drm_connector *connector; - struct edid *edid; + const struct edid *edid; bool preferred; u32 quirks; int modes; @@ -2424,7 +2424,7 @@ is_rb(const struct detailed_timing *descriptor, void *data) /* EDID 1.4 defines this explicitly. For EDID 1.3, we guess, badly. */ static bool -drm_monitor_supports_rb(struct edid *edid) +drm_monitor_supports_rb(const struct edid *edid) { if (edid->revision >= 4) { bool ret = false; @@ -2452,7 +2452,7 @@ find_gtf2(const struct detailed_timing *descriptor, void *data) /* Secondary GTF curve kicks in above some break frequency */ static int -drm_gtf2_hbreak(struct edid *edid) +drm_gtf2_hbreak(const struct edid *edid) { const struct detailed_timing *descriptor = NULL; @@ -2464,7 +2464,7 @@ drm_gtf2_hbreak(struct edid *edid) } static int -drm_gtf2_2c(struct edid *edid) +drm_gtf2_2c(const struct edid *edid) { const struct detailed_timing *descriptor = NULL; @@ -2476,7 +2476,7 @@ drm_gtf2_2c(struct edid *edid) } static int -drm_gtf2_m(struct edid *edid) +drm_gtf2_m(const struct edid *edid) { const struct detailed_timing *descriptor = NULL; @@ -2488,7 +2488,7 @@ drm_gtf2_m(struct edid *edid) } static int -drm_gtf2_k(struct edid *edid) +drm_gtf2_k(const struct edid *edid) { const struct detailed_timing *descriptor = NULL; @@ -2500,7 +2500,7 @@ drm_gtf2_k(struct edid *edid) } static int -drm_gtf2_2j(struct edid *edid) +drm_gtf2_2j(const struct edid *edid) { const struct detailed_timing *descriptor = NULL; @@ -2515,7 +2515,7 @@ drm_gtf2_2j(struct edid *edid) * standard_timing_level - get std. timing level(CVT/GTF/DMT) * @edid: EDID block to scan */ -static int standard_timing_level(struct edid *edid) +static int standard_timing_level(const struct edid *edid) { if (edid->revision >= 2) { if (edid->revision >= 4 && (edid->features & DRM_EDID_FEATURE_DEFAULT_GTF)) @@ -2558,7 +2558,7 @@ static int drm_mode_hsync(const struct drm_display_mode *mode) * and convert them into a real mode using CVT/GTF/DMT. */ static struct drm_display_mode * -drm_mode_std(struct drm_connector *connector, struct edid *edid, +drm_mode_std(struct drm_connector *connector, const struct edid *edid, const struct std_timing *t) { struct drm_device *dev = connector->dev; @@ -2720,7 +2720,7 @@ drm_mode_do_interlace_quirk(struct drm_display_mode *mode, * return a new struct drm_display_mode. */ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, - struct edid *edid, + const struct edid *edid, const struct detailed_timing *timing, u32 quirks) { @@ -2820,7 +2820,7 @@ set_size: static bool mode_in_hsync_range(const struct drm_display_mode *mode, - struct edid *edid, const u8 *t) + const struct edid *edid, const u8 *t) { int hsync, hmin, hmax; @@ -2837,7 +2837,7 @@ mode_in_hsync_range(const struct drm_display_mode *mode, static bool mode_in_vsync_range(const struct drm_display_mode *mode, - struct edid *edid, const u8 *t) + const struct edid *edid, const u8 *t) { int vsync, vmin, vmax; @@ -2853,7 +2853,7 @@ mode_in_vsync_range(const struct drm_display_mode *mode, } static u32 -range_pixel_clock(struct edid *edid, const u8 *t) +range_pixel_clock(const struct edid *edid, const u8 *t) { /* unspecified */ if (t[9] == 0 || t[9] == 255) @@ -2868,7 +2868,7 @@ range_pixel_clock(struct edid *edid, const u8 *t) } static bool -mode_in_range(const struct drm_display_mode *mode, struct edid *edid, +mode_in_range(const struct drm_display_mode *mode, const struct edid *edid, const struct detailed_timing *timing) { u32 max_clock; @@ -2914,7 +2914,7 @@ static bool valid_inferred_mode(const struct drm_connector *connector, } static int -drm_dmt_modes_for_range(struct drm_connector *connector, struct edid *edid, +drm_dmt_modes_for_range(struct drm_connector *connector, const struct edid *edid, const struct detailed_timing *timing) { int i, modes = 0; @@ -2949,7 +2949,7 @@ void drm_mode_fixup_1366x768(struct drm_display_mode *mode) } static int -drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, +drm_gtf_modes_for_range(struct drm_connector *connector, const struct edid *edid, const struct detailed_timing *timing) { int i, modes = 0; @@ -2978,7 +2978,7 @@ drm_gtf_modes_for_range(struct drm_connector *connector, struct edid *edid, } static int -drm_cvt_modes_for_range(struct drm_connector *connector, struct edid *edid, +drm_cvt_modes_for_range(struct drm_connector *connector, const struct edid *edid, const struct detailed_timing *timing) { int i, modes = 0; @@ -3046,7 +3046,7 @@ do_inferred_modes(const struct detailed_timing *timing, void *c) } static int -add_inferred_modes(struct drm_connector *connector, struct edid *edid) +add_inferred_modes(struct drm_connector *connector, const struct edid *edid) { struct detailed_mode_closure closure = { .connector = connector, @@ -3108,7 +3108,7 @@ do_established_modes(const struct detailed_timing *timing, void *c) * (defined above). Tease them out and add them to the global modes list. */ static int -add_established_modes(struct drm_connector *connector, struct edid *edid) +add_established_modes(struct drm_connector *connector, const struct edid *edid) { struct drm_device *dev = connector->dev; unsigned long est_bits = edid->established_timings.t1 | @@ -3145,7 +3145,7 @@ do_standard_modes(const struct detailed_timing *timing, void *c) struct detailed_mode_closure *closure = c; const struct detailed_non_pixel *data = &timing->data.other_data; struct drm_connector *connector = closure->connector; - struct edid *edid = closure->edid; + const struct edid *edid = closure->edid; int i; if (!is_display_descriptor(timing, EDID_DETAIL_STD_MODES)) @@ -3172,7 +3172,7 @@ do_standard_modes(const struct detailed_timing *timing, void *c) * GTF or CVT. Grab them from @edid and add them to the list. */ static int -add_standard_modes(struct drm_connector *connector, struct edid *edid) +add_standard_modes(struct drm_connector *connector, const struct edid *edid) { int i, modes = 0; struct detailed_mode_closure closure = { @@ -3264,7 +3264,7 @@ do_cvt_mode(const struct detailed_timing *timing, void *c) } static int -add_cvt_modes(struct drm_connector *connector, struct edid *edid) +add_cvt_modes(struct drm_connector *connector, const struct edid *edid) { struct detailed_mode_closure closure = { .connector = connector, @@ -3318,7 +3318,7 @@ do_detailed_mode(const struct detailed_timing *timing, void *c) * @quirks: quirks to apply */ static int -add_detailed_modes(struct drm_connector *connector, struct edid *edid, +add_detailed_modes(struct drm_connector *connector, const struct edid *edid, u32 quirks) { struct detailed_mode_closure closure = { @@ -4525,7 +4525,7 @@ monitor_name(const struct detailed_timing *timing, void *data) *res = timing->data.other_data.data.str.str; } -static int get_monitor_name(struct edid *edid, char name[13]) +static int get_monitor_name(const struct edid *edid, char name[13]) { const char *edid_name = NULL; int mnl; From f4e558ec9d9fb9484c30221a41cc5bfa73d33e6c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:32 +0300 Subject: [PATCH 00431/11454] drm/edid: add more general struct edid constness in the interfaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this, the remaining non-const parts are the ones that actually modify the EDID, for example to fix corrupt EDID. Cc: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/c7156f22494b585c55a00a6732462bde0cc19dbf.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 21 +++++++++++---------- include/drm/drm_edid.h | 10 +++++----- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index fee47ac1bdd8..2bdc0eef8f35 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2150,7 +2150,7 @@ static u32 edid_extract_panel_id(const struct edid *edid) u32 drm_edid_get_panel_id(struct i2c_adapter *adapter) { - struct edid *edid; + const struct edid *edid; u32 panel_id; edid = drm_do_get_edid_base_block(NULL, drm_do_probe_ddc_edid, adapter); @@ -3664,7 +3664,7 @@ static bool drm_valid_hdmi_vic(u8 vic) } static int -add_alternate_cea_modes(struct drm_connector *connector, struct edid *edid) +add_alternate_cea_modes(struct drm_connector *connector, const struct edid *edid) { struct drm_device *dev = connector->dev; struct drm_display_mode *mode, *tmp; @@ -4345,7 +4345,7 @@ static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector, } static int -add_cea_modes(struct drm_connector *connector, struct edid *edid) +add_cea_modes(struct drm_connector *connector, const struct edid *edid) { const u8 *cea = drm_find_cea_extension(edid); const u8 *db, *hdmi = NULL, *video = NULL; @@ -4551,7 +4551,7 @@ static int get_monitor_name(const struct edid *edid, char name[13]) * @bufsize: The size of the name buffer (should be at least 14 chars.) * */ -void drm_edid_get_monitor_name(struct edid *edid, char *name, int bufsize) +void drm_edid_get_monitor_name(const struct edid *edid, char *name, int bufsize) { int name_length; char buf[13]; @@ -4585,7 +4585,8 @@ static void clear_eld(struct drm_connector *connector) * Fill the ELD (EDID-Like Data) buffer for passing to the audio driver. The * HDCP and Port_ID ELD fields are left for the graphics driver to fill in. */ -static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) +static void drm_edid_to_eld(struct drm_connector *connector, + const struct edid *edid) { uint8_t *eld = connector->eld; const u8 *cea; @@ -4681,7 +4682,7 @@ static void drm_edid_to_eld(struct drm_connector *connector, struct edid *edid) * * Return: The number of found SADs or negative number on error. */ -int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads) +int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads) { int count = 0; int i, start, end, dbl; @@ -4743,7 +4744,7 @@ EXPORT_SYMBOL(drm_edid_to_sad); * Return: The number of found Speaker Allocation Blocks or negative number on * error. */ -int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb) +int drm_edid_to_speaker_allocation(const struct edid *edid, u8 **sadb) { int count = 0; int i, start, end, dbl; @@ -4838,7 +4839,7 @@ EXPORT_SYMBOL(drm_av_sync_delay); * * Return: True if the monitor is HDMI, false if not or unknown. */ -bool drm_detect_hdmi_monitor(struct edid *edid) +bool drm_detect_hdmi_monitor(const struct edid *edid) { const u8 *edid_ext; int i; @@ -4876,7 +4877,7 @@ EXPORT_SYMBOL(drm_detect_hdmi_monitor); * * Return: True if the monitor supports audio, false otherwise. */ -bool drm_detect_monitor_audio(struct edid *edid) +bool drm_detect_monitor_audio(const struct edid *edid) { const u8 *edid_ext; int i, j; @@ -5538,7 +5539,7 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector, } static int add_displayid_detailed_modes(struct drm_connector *connector, - struct edid *edid) + const struct edid *edid) { const struct displayid_block *block; struct displayid_iter iter; diff --git a/include/drm/drm_edid.h b/include/drm/drm_edid.h index 144c495b99c4..48b1bf9c315a 100644 --- a/include/drm/drm_edid.h +++ b/include/drm/drm_edid.h @@ -372,8 +372,8 @@ struct drm_connector; struct drm_connector_state; struct drm_display_mode; -int drm_edid_to_sad(struct edid *edid, struct cea_sad **sads); -int drm_edid_to_speaker_allocation(struct edid *edid, u8 **sadb); +int drm_edid_to_sad(const struct edid *edid, struct cea_sad **sads); +int drm_edid_to_speaker_allocation(const struct edid *edid, u8 **sadb); int drm_av_sync_delay(struct drm_connector *connector, const struct drm_display_mode *mode); @@ -569,8 +569,8 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid); int drm_add_override_edid_modes(struct drm_connector *connector); u8 drm_match_cea_mode(const struct drm_display_mode *to_match); -bool drm_detect_hdmi_monitor(struct edid *edid); -bool drm_detect_monitor_audio(struct edid *edid); +bool drm_detect_hdmi_monitor(const struct edid *edid); +bool drm_detect_monitor_audio(const struct edid *edid); enum hdmi_quantization_range drm_default_rgb_quant_range(const struct drm_display_mode *mode); int drm_add_modes_noedid(struct drm_connector *connector, @@ -582,7 +582,7 @@ int drm_edid_header_is_valid(const u8 *raw_edid); bool drm_edid_block_valid(u8 *raw_edid, int block, bool print_bad_edid, bool *edid_corrupt); bool drm_edid_is_valid(struct edid *edid); -void drm_edid_get_monitor_name(struct edid *edid, char *name, +void drm_edid_get_monitor_name(const struct edid *edid, char *name, int buflen); struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev, int hsize, int vsize, int fresh, From f40ab034b6aebb7ee9461d402915ca83e693d1bd Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 28 Mar 2022 17:34:33 +0300 Subject: [PATCH 00432/11454] drm/edid: split drm_add_edid_modes() to two MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce the size of the function that actually modifies the EDID. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Reviewed-by: Emil Velikov Link: https://patchwork.freedesktop.org/patch/msgid/437c3c79f68d1144444fb2dd18a678f3aa97272c.1648477901.git.jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 42 ++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 2bdc0eef8f35..359c52e5318a 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -5556,18 +5556,8 @@ static int add_displayid_detailed_modes(struct drm_connector *connector, return num_modes; } -/** - * drm_add_edid_modes - add modes from EDID data, if available - * @connector: connector we're probing - * @edid: EDID data - * - * Add the specified modes to the connector's mode list. Also fills out the - * &drm_display_info structure and ELD in @connector with any information which - * can be derived from the edid. - * - * Return: The number of modes added or 0 if we couldn't find any. - */ -int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) +static int drm_edid_connector_update(struct drm_connector *connector, + const struct edid *edid) { int num_modes = 0; u32 quirks; @@ -5576,12 +5566,6 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) clear_eld(connector); return 0; } - if (!drm_edid_is_valid(edid)) { - clear_eld(connector); - drm_warn(connector->dev, "%s: EDID invalid.\n", - connector->name); - return 0; - } drm_edid_to_eld(connector, edid); @@ -5633,6 +5617,28 @@ int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) return num_modes; } + +/** + * drm_add_edid_modes - add modes from EDID data, if available + * @connector: connector we're probing + * @edid: EDID data + * + * Add the specified modes to the connector's mode list. Also fills out the + * &drm_display_info structure and ELD in @connector with any information which + * can be derived from the edid. + * + * Return: The number of modes added or 0 if we couldn't find any. + */ +int drm_add_edid_modes(struct drm_connector *connector, struct edid *edid) +{ + if (edid && !drm_edid_is_valid(edid)) { + drm_warn(connector->dev, "%s: EDID invalid.\n", + connector->name); + edid = NULL; + } + + return drm_edid_connector_update(connector, edid); +} EXPORT_SYMBOL(drm_add_edid_modes); /** From fd04847372ba86347066c536ba99bc3c1f351334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Fri, 25 Mar 2022 11:38:32 -0700 Subject: [PATCH 00433/11454] docs: gpu: i915.rst: Fix DRRS documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_drrs_enable() and intel_drrs_disable() were renamed to intel_drrs_activate() and intel_drrs_deactivate() in commit 54903c7a6b40 ("drm/i915: s/enable/active/ for DRRS") and it is causing warnings when generating the kernel documentation. But as for a while DRRS has its own file, so here just let the tool generate the documentation for all exported and documented functions in intel_drrs.c. Cc: Ville Syrjälä Cc: Rodrigo Vivi Signed-off-by: José Roberto de Souza Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220325183832.146472-1-jose.souza@intel.com --- Documentation/gpu/i915.rst | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/Documentation/gpu/i915.rst b/Documentation/gpu/i915.rst index bcaefc952764..0f08693d05cd 100644 --- a/Documentation/gpu/i915.rst +++ b/Documentation/gpu/i915.rst @@ -187,19 +187,7 @@ Display Refresh Rate Switching (DRRS) :doc: Display Refresh Rate Switching (DRRS) .. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c - :functions: intel_drrs_enable - -.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c - :functions: intel_drrs_disable - -.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c - :functions: intel_drrs_invalidate - -.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c - :functions: intel_drrs_flush - -.. kernel-doc:: drivers/gpu/drm/i915/display/intel_drrs.c - :functions: intel_drrs_init + :internal: DPIO ---- From e0c603ef705019ae28d195a0faa5f568372f3bf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 24 Feb 2022 18:51:00 +0200 Subject: [PATCH 00434/11454] drm/i915: Remove locks around skl+ scaler programming MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the skl+ scaler registers are suitably confined to their own cachelines so we don't need the uncore.lock to globally serialize access to these registers. We actually already dropped some of this in commit 14ad15296d1f ("drm/i915: Make skl+ universal plane registers unlocked") as the plane scaler enabling/reconfiguration became lockless. So let's complete that and remove the rest of the locks from the scaler programming as well. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220224165103.15682-2-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/skl_scaler.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/skl_scaler.c b/drivers/gpu/drm/i915/display/skl_scaler.c index 998128bac8c0..4092679be21e 100644 --- a/drivers/gpu/drm/i915/display/skl_scaler.c +++ b/drivers/gpu/drm/i915/display/skl_scaler.c @@ -409,7 +409,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) int x = dst->x1; int y = dst->y1; int hscale, vscale; - unsigned long irqflags; struct drm_rect src; int id; u32 ps_ctrl; @@ -436,8 +435,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) ps_ctrl = skl_scaler_get_filter_select(crtc_state->hw.scaling_filter, 0); ps_ctrl |= PS_SCALER_EN | scaler_state->scalers[id].mode; - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); - skl_scaler_setup_filter(dev_priv, pipe, id, 0, crtc_state->hw.scaling_filter); @@ -451,8 +448,6 @@ void skl_pfit_enable(const struct intel_crtc_state *crtc_state) x << 16 | y); intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(pipe, id), width << 16 | height); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } void @@ -521,15 +516,10 @@ static void skl_detach_scaler(struct intel_crtc *crtc, int id) { struct drm_device *dev = crtc->base.dev; struct drm_i915_private *dev_priv = to_i915(dev); - unsigned long irqflags; - - spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); intel_de_write_fw(dev_priv, SKL_PS_CTRL(crtc->pipe, id), 0); intel_de_write_fw(dev_priv, SKL_PS_WIN_POS(crtc->pipe, id), 0); intel_de_write_fw(dev_priv, SKL_PS_WIN_SZ(crtc->pipe, id), 0); - - spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); } /* From 46fc66be60e806c90d5ca3c85887dfb12857ba47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 24 Feb 2022 18:51:01 +0200 Subject: [PATCH 00435/11454] drm/i915: Make ilk+ pfit regiser unlocked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ilk+ panel fitter register are sitting nicely on their own cacheline, so no need for global serialization via uncore.lock. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220224165103.15682-3-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_display.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 3d2ff258f0a9..6d4a038edaed 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1117,13 +1117,13 @@ static void ilk_pfit_enable(const struct intel_crtc_state *crtc_state) * e.g. x201. */ if (IS_IVYBRIDGE(dev_priv) || IS_HASWELL(dev_priv)) - intel_de_write(dev_priv, PF_CTL(pipe), PF_ENABLE | - PF_FILTER_MED_3x3 | PF_PIPE_SEL_IVB(pipe)); + intel_de_write_fw(dev_priv, PF_CTL(pipe), PF_ENABLE | + PF_FILTER_MED_3x3 | PF_PIPE_SEL_IVB(pipe)); else - intel_de_write(dev_priv, PF_CTL(pipe), PF_ENABLE | - PF_FILTER_MED_3x3); - intel_de_write(dev_priv, PF_WIN_POS(pipe), x << 16 | y); - intel_de_write(dev_priv, PF_WIN_SZ(pipe), width << 16 | height); + intel_de_write_fw(dev_priv, PF_CTL(pipe), PF_ENABLE | + PF_FILTER_MED_3x3); + intel_de_write_fw(dev_priv, PF_WIN_POS(pipe), x << 16 | y); + intel_de_write_fw(dev_priv, PF_WIN_SZ(pipe), width << 16 | height); } static void intel_crtc_dpms_overlay_disable(struct intel_crtc *crtc) @@ -2023,9 +2023,9 @@ void ilk_pfit_disable(const struct intel_crtc_state *old_crtc_state) if (!old_crtc_state->pch_pfit.enabled) return; - intel_de_write(dev_priv, PF_CTL(pipe), 0); - intel_de_write(dev_priv, PF_WIN_POS(pipe), 0); - intel_de_write(dev_priv, PF_WIN_SZ(pipe), 0); + intel_de_write_fw(dev_priv, PF_CTL(pipe), 0); + intel_de_write_fw(dev_priv, PF_WIN_POS(pipe), 0); + intel_de_write_fw(dev_priv, PF_WIN_SZ(pipe), 0); } static void ilk_crtc_disable(struct intel_atomic_state *state, From e9b14658d51950d5ab6ef219fb3c9483c70a18ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 24 Feb 2022 18:51:02 +0200 Subject: [PATCH 00436/11454] drm/i915: Split color_commit() into noarm+arm pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To reduce the amount of registers written during the vblank evade critical section let's also split the .color_commit() hook to noarm+arm pair. The noarm hook runs before the vblank evasion with the arm hook staying inside the critical section. Just the framework here, actually moving stuff out into the noarm hook will follow. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220224165103.15682-4-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_color.c | 59 +++++++++++++------- drivers/gpu/drm/i915/display/intel_color.h | 3 +- drivers/gpu/drm/i915/display/intel_display.c | 22 ++++++-- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index e94ec57260f1..df775c6179b2 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -31,12 +31,21 @@ struct intel_color_funcs { int (*color_check)(struct intel_crtc_state *crtc_state); /* - * Program double buffered color management registers during - * vblank evasion. The registers should then latch during the - * next vblank start, alongside any other double buffered registers - * involved with the same commit. + * Program non-arming double buffered color management registers + * before vblank evasion. The registers should then latch after + * the arming register is written (by color_commit_arm()) during + * the next vblank start, alongside any other double buffered + * registers involved with the same commit. This hook is optional. */ - void (*color_commit)(const struct intel_crtc_state *crtc_state); + void (*color_commit_noarm)(const struct intel_crtc_state *crtc_state); + /* + * Program arming double buffered color management registers + * during vblank evasion. The registers (and whatever other registers + * they arm that were written by color_commit_noarm) should then latch + * during the next vblank start, alongside any other double buffered + * registers involved with the same commit. + */ + void (*color_commit_arm)(const struct intel_crtc_state *crtc_state); /* * Load LUTs (and other single buffered color management * registers). Will (hopefully) be called during the vblank @@ -491,7 +500,7 @@ static void icl_lut_multi_seg_pack(struct drm_color_lut *entry, u32 ldw, u32 udw REG_FIELD_GET(PAL_PREC_MULTI_SEG_BLUE_LDW_MASK, ldw); } -static void i9xx_color_commit(const struct intel_crtc_state *crtc_state) +static void i9xx_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -504,7 +513,7 @@ static void i9xx_color_commit(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, PIPECONF(pipe), val); } -static void ilk_color_commit(const struct intel_crtc_state *crtc_state) +static void ilk_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -519,7 +528,7 @@ static void ilk_color_commit(const struct intel_crtc_state *crtc_state) ilk_load_csc_matrix(crtc_state); } -static void hsw_color_commit(const struct intel_crtc_state *crtc_state) +static void hsw_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -530,7 +539,7 @@ static void hsw_color_commit(const struct intel_crtc_state *crtc_state) ilk_load_csc_matrix(crtc_state); } -static void skl_color_commit(const struct intel_crtc_state *crtc_state) +static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); @@ -1169,11 +1178,19 @@ void intel_color_load_luts(const struct intel_crtc_state *crtc_state) dev_priv->color_funcs->load_luts(crtc_state); } -void intel_color_commit(const struct intel_crtc_state *crtc_state) +void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); - dev_priv->color_funcs->color_commit(crtc_state); + if (dev_priv->color_funcs->color_commit_noarm) + dev_priv->color_funcs->color_commit_noarm(crtc_state); +} + +void intel_color_commit_arm(const struct intel_crtc_state *crtc_state) +{ + struct drm_i915_private *dev_priv = to_i915(crtc_state->uapi.crtc->dev); + + dev_priv->color_funcs->color_commit_arm(crtc_state); } static bool intel_can_preload_luts(const struct intel_crtc_state *new_crtc_state) @@ -2132,70 +2149,70 @@ static void icl_read_luts(struct intel_crtc_state *crtc_state) static const struct intel_color_funcs chv_color_funcs = { .color_check = chv_color_check, - .color_commit = i9xx_color_commit, + .color_commit_arm = i9xx_color_commit_arm, .load_luts = chv_load_luts, .read_luts = chv_read_luts, }; static const struct intel_color_funcs i965_color_funcs = { .color_check = i9xx_color_check, - .color_commit = i9xx_color_commit, + .color_commit_arm = i9xx_color_commit_arm, .load_luts = i965_load_luts, .read_luts = i965_read_luts, }; static const struct intel_color_funcs i9xx_color_funcs = { .color_check = i9xx_color_check, - .color_commit = i9xx_color_commit, + .color_commit_arm = i9xx_color_commit_arm, .load_luts = i9xx_load_luts, .read_luts = i9xx_read_luts, }; static const struct intel_color_funcs icl_color_funcs = { .color_check = icl_color_check, - .color_commit = skl_color_commit, + .color_commit_arm = skl_color_commit_arm, .load_luts = icl_load_luts, .read_luts = icl_read_luts, }; static const struct intel_color_funcs glk_color_funcs = { .color_check = glk_color_check, - .color_commit = skl_color_commit, + .color_commit_arm = skl_color_commit_arm, .load_luts = glk_load_luts, .read_luts = glk_read_luts, }; static const struct intel_color_funcs skl_color_funcs = { .color_check = ivb_color_check, - .color_commit = skl_color_commit, + .color_commit_arm = skl_color_commit_arm, .load_luts = bdw_load_luts, .read_luts = NULL, }; static const struct intel_color_funcs bdw_color_funcs = { .color_check = ivb_color_check, - .color_commit = hsw_color_commit, + .color_commit_arm = hsw_color_commit_arm, .load_luts = bdw_load_luts, .read_luts = NULL, }; static const struct intel_color_funcs hsw_color_funcs = { .color_check = ivb_color_check, - .color_commit = hsw_color_commit, + .color_commit_arm = hsw_color_commit_arm, .load_luts = ivb_load_luts, .read_luts = NULL, }; static const struct intel_color_funcs ivb_color_funcs = { .color_check = ivb_color_check, - .color_commit = ilk_color_commit, + .color_commit_arm = ilk_color_commit_arm, .load_luts = ivb_load_luts, .read_luts = NULL, }; static const struct intel_color_funcs ilk_color_funcs = { .color_check = ilk_color_check, - .color_commit = ilk_color_commit, + .color_commit_arm = ilk_color_commit_arm, .load_luts = ilk_load_luts, .read_luts = ilk_read_luts, }; diff --git a/drivers/gpu/drm/i915/display/intel_color.h b/drivers/gpu/drm/i915/display/intel_color.h index 173727aaa24d..fd873425e082 100644 --- a/drivers/gpu/drm/i915/display/intel_color.h +++ b/drivers/gpu/drm/i915/display/intel_color.h @@ -14,7 +14,8 @@ struct drm_property_blob; void intel_color_init(struct intel_crtc *crtc); int intel_color_check(struct intel_crtc_state *crtc_state); -void intel_color_commit(const struct intel_crtc_state *crtc_state); +void intel_color_commit_noarm(const struct intel_crtc_state *crtc_state); +void intel_color_commit_arm(const struct intel_crtc_state *crtc_state); void intel_color_load_luts(const struct intel_crtc_state *crtc_state); void intel_color_get_config(struct intel_crtc_state *crtc_state); int intel_color_get_gamma_bit_precision(const struct intel_crtc_state *crtc_state); diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 6d4a038edaed..24e76afb050d 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1779,7 +1779,8 @@ static void ilk_crtc_enable(struct intel_atomic_state *state, * clocks enabled */ intel_color_load_luts(new_crtc_state); - intel_color_commit(new_crtc_state); + intel_color_commit_noarm(new_crtc_state); + intel_color_commit_arm(new_crtc_state); /* update DSPCNTR to configure gamma for pipe bottom color */ intel_disable_primary_plane(new_crtc_state); @@ -1970,7 +1971,8 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, * clocks enabled */ intel_color_load_luts(new_crtc_state); - intel_color_commit(new_crtc_state); + intel_color_commit_noarm(new_crtc_state); + intel_color_commit_arm(new_crtc_state); /* update DSPCNTR to configure gamma/csc for pipe bottom color */ if (DISPLAY_VER(dev_priv) < 9) intel_disable_primary_plane(new_crtc_state); @@ -2390,7 +2392,8 @@ static void valleyview_crtc_enable(struct intel_atomic_state *state, i9xx_pfit_enable(new_crtc_state); intel_color_load_luts(new_crtc_state); - intel_color_commit(new_crtc_state); + intel_color_commit_noarm(new_crtc_state); + intel_color_commit_arm(new_crtc_state); /* update DSPCNTR to configure gamma for pipe bottom color */ intel_disable_primary_plane(new_crtc_state); @@ -2429,7 +2432,8 @@ static void i9xx_crtc_enable(struct intel_atomic_state *state, i9xx_pfit_enable(new_crtc_state); intel_color_load_luts(new_crtc_state); - intel_color_commit(new_crtc_state); + intel_color_commit_noarm(new_crtc_state); + intel_color_commit_arm(new_crtc_state); /* update DSPCNTR to configure gamma for pipe bottom color */ intel_disable_primary_plane(new_crtc_state); @@ -8083,7 +8087,7 @@ static void commit_pipe_pre_planes(struct intel_atomic_state *state, if (!modeset) { if (new_crtc_state->uapi.color_mgmt_changed || new_crtc_state->update_pipe) - intel_color_commit(new_crtc_state); + intel_color_commit_arm(new_crtc_state); if (DISPLAY_VER(dev_priv) >= 9 || IS_BROADWELL(dev_priv)) bdw_set_pipemisc(new_crtc_state); @@ -8163,6 +8167,11 @@ static void intel_update_crtc(struct intel_atomic_state *state, intel_fbc_update(state, crtc); + if (!modeset && + (new_crtc_state->uapi.color_mgmt_changed || + new_crtc_state->update_pipe)) + intel_color_commit_noarm(new_crtc_state); + intel_crtc_planes_update_noarm(state, crtc); /* Perform vblank evasion around commit operation */ @@ -10003,7 +10012,8 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc, } /* Disable any background color/etc. set by the BIOS */ - intel_color_commit(crtc_state); + intel_color_commit_noarm(crtc_state); + intel_color_commit_arm(crtc_state); } /* Adjust the state of the output pipe according to whether we From d13dde4495800c4e7b98d81eab9472ae248ff49e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 24 Feb 2022 18:51:03 +0200 Subject: [PATCH 00437/11454] drm/i915: Split pipe+output CSC programming to noarm+arm pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move most of the pipe+output CSC programming to the .color_commit_noarm() hook which runs before vblank evasion. Only PIPE_CSC_MODE (the arming register) needs to remain in inside the critical section. A test case that just updates the CTM in a loop produces the following i915_update_info numbers on ilk (w/o lockdep): old new Updates: 10012 Updates: 10008 | | 1us |** 1us |********** |************* |************* 4us |********* 4us |* |* |** 16us | 16us | | | 66us | 66us | | | 262us | 262us | | | 1ms | 1ms | | | 4ms | 4ms | | | 17ms | 17ms | | | Min update: 1345ns Min update: 1268ns Max update: 16672ns Max update: 15656ns Average update: 3914ns Average update: 2185ns Overruns > 100us: 0 Overruns > 100us: 0 And here is tgl (forced to update both pipe CSC and output CSC, and with lockdep enabled): old new Updates: 10012 Updates: 10012 | | 1us | 1us | | | 4us |* 4us |** |** |********** 16us |************* 16us |************* |* | 66us | 66us | | | 262us | 262us | | | 1ms | 1ms | | | 4ms | 4ms | | | 17ms | 17ms | | | Min update: 5204ns Min update: 5176ns Max update: 176038ns Max update: 186685ns Average update: 23931ns Average update: 16654ns Overruns > 250us: 0 Overruns > 250us: 0 Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220224165103.15682-5-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy --- drivers/gpu/drm/i915/display/intel_color.c | 36 ++++++++++++++-------- 1 file changed, 23 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c index df775c6179b2..34128c9c635c 100644 --- a/drivers/gpu/drm/i915/display/intel_color.c +++ b/drivers/gpu/drm/i915/display/intel_color.c @@ -346,15 +346,11 @@ static void ilk_load_csc_matrix(const struct intel_crtc_state *crtc_state) ilk_csc_coeff_identity, ilk_csc_off_zero); } - - intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe), - crtc_state->csc_mode); } static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); if (crtc_state->hw.ctm) { u16 coeff[9]; @@ -373,9 +369,6 @@ static void icl_load_csc_matrix(const struct intel_crtc_state *crtc_state) ilk_csc_coeff_limited_range, ilk_csc_postoff_limited_range); } - - intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe), - crtc_state->csc_mode); } static void chv_load_cgm_csc(struct intel_crtc *crtc, @@ -500,6 +493,16 @@ static void icl_lut_multi_seg_pack(struct drm_color_lut *entry, u32 ldw, u32 udw REG_FIELD_GET(PAL_PREC_MULTI_SEG_BLUE_LDW_MASK, ldw); } +static void icl_color_commit_noarm(const struct intel_crtc_state *crtc_state) +{ + icl_load_csc_matrix(crtc_state); +} + +static void ilk_color_commit_noarm(const struct intel_crtc_state *crtc_state) +{ + ilk_load_csc_matrix(crtc_state); +} + static void i9xx_color_commit_arm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -525,7 +528,8 @@ static void ilk_color_commit_arm(const struct intel_crtc_state *crtc_state) val |= PIPECONF_GAMMA_MODE(crtc_state->gamma_mode); intel_de_write(dev_priv, PIPECONF(pipe), val); - ilk_load_csc_matrix(crtc_state); + intel_de_write_fw(dev_priv, PIPE_CSC_MODE(pipe), + crtc_state->csc_mode); } static void hsw_color_commit_arm(const struct intel_crtc_state *crtc_state) @@ -536,7 +540,8 @@ static void hsw_color_commit_arm(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode); - ilk_load_csc_matrix(crtc_state); + intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe), + crtc_state->csc_mode); } static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state) @@ -560,10 +565,8 @@ static void skl_color_commit_arm(const struct intel_crtc_state *crtc_state) intel_de_write(dev_priv, GAMMA_MODE(crtc->pipe), crtc_state->gamma_mode); - if (DISPLAY_VER(dev_priv) >= 11) - icl_load_csc_matrix(crtc_state); - else - ilk_load_csc_matrix(crtc_state); + intel_de_write_fw(dev_priv, PIPE_CSC_MODE(crtc->pipe), + crtc_state->csc_mode); } static void i9xx_load_lut_8(struct intel_crtc *crtc, @@ -2170,6 +2173,7 @@ static const struct intel_color_funcs i9xx_color_funcs = { static const struct intel_color_funcs icl_color_funcs = { .color_check = icl_color_check, + .color_commit_noarm = icl_color_commit_noarm, .color_commit_arm = skl_color_commit_arm, .load_luts = icl_load_luts, .read_luts = icl_read_luts, @@ -2177,6 +2181,7 @@ static const struct intel_color_funcs icl_color_funcs = { static const struct intel_color_funcs glk_color_funcs = { .color_check = glk_color_check, + .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = skl_color_commit_arm, .load_luts = glk_load_luts, .read_luts = glk_read_luts, @@ -2184,6 +2189,7 @@ static const struct intel_color_funcs glk_color_funcs = { static const struct intel_color_funcs skl_color_funcs = { .color_check = ivb_color_check, + .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = skl_color_commit_arm, .load_luts = bdw_load_luts, .read_luts = NULL, @@ -2191,6 +2197,7 @@ static const struct intel_color_funcs skl_color_funcs = { static const struct intel_color_funcs bdw_color_funcs = { .color_check = ivb_color_check, + .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = hsw_color_commit_arm, .load_luts = bdw_load_luts, .read_luts = NULL, @@ -2198,6 +2205,7 @@ static const struct intel_color_funcs bdw_color_funcs = { static const struct intel_color_funcs hsw_color_funcs = { .color_check = ivb_color_check, + .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = hsw_color_commit_arm, .load_luts = ivb_load_luts, .read_luts = NULL, @@ -2205,6 +2213,7 @@ static const struct intel_color_funcs hsw_color_funcs = { static const struct intel_color_funcs ivb_color_funcs = { .color_check = ivb_color_check, + .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = ilk_color_commit_arm, .load_luts = ivb_load_luts, .read_luts = NULL, @@ -2212,6 +2221,7 @@ static const struct intel_color_funcs ivb_color_funcs = { static const struct intel_color_funcs ilk_color_funcs = { .color_check = ilk_color_check, + .color_commit_noarm = ilk_color_commit_noarm, .color_commit_arm = ilk_color_commit_arm, .load_luts = ilk_load_luts, .read_luts = ilk_read_luts, From 5d2fd49db9b48c37041d0f9565b1c6fad2c09ce3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Mar 2022 20:29:27 +0200 Subject: [PATCH 00438/11454] drm/i915: Pass intel_connector to intel_panel_{init,fini}() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the other intel_panel functions take struct intel_connector, so might as well make init()/fini() take one as well. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220323182935.4701-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/icl_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_connector.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_dvo.c | 2 +- drivers/gpu/drm/i915/display/intel_lvds.c | 2 +- drivers/gpu/drm/i915/display/intel_panel.c | 11 ++++++----- drivers/gpu/drm/i915/display/intel_panel.h | 5 ++--- drivers/gpu/drm/i915/display/intel_sdvo.c | 2 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 00cae5d26637..c7a6c2cce297 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -2057,7 +2057,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) goto err; } - intel_panel_init(&intel_connector->panel, fixed_mode, NULL); + intel_panel_init(intel_connector, fixed_mode, NULL); intel_backlight_setup(intel_connector, INVALID_PIPE); if (dev_priv->vbt.dsi.config->dual_link) diff --git a/drivers/gpu/drm/i915/display/intel_connector.c b/drivers/gpu/drm/i915/display/intel_connector.c index a5f5dd55b0cb..1dcc268927a2 100644 --- a/drivers/gpu/drm/i915/display/intel_connector.c +++ b/drivers/gpu/drm/i915/display/intel_connector.c @@ -102,7 +102,7 @@ void intel_connector_destroy(struct drm_connector *connector) if (!IS_ERR_OR_NULL(intel_connector->edid)) kfree(intel_connector->edid); - intel_panel_fini(&intel_connector->panel); + intel_panel_fini(intel_connector); drm_connector_cleanup(connector); diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 6b6dc382be56..cfe88c4cfa29 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5053,7 +5053,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, pipe_name(pipe)); } - intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode); + intel_panel_init(intel_connector, fixed_mode, downclock_mode); if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) intel_connector->panel.backlight.power = intel_pps_backlight_power; intel_backlight_setup(intel_connector, pipe); diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index d4670889d26c..d4dc16a9c0dd 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -549,7 +549,7 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) * headers, likely), so for now, just get the current * mode being output through DVO. */ - intel_panel_init(&intel_connector->panel, + intel_panel_init(intel_connector, intel_dvo_get_current_mode(intel_encoder), NULL); intel_dvo->panel_wants_dither = true; diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 5449d69fbae5..cd685dbf324b 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -996,7 +996,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) out: mutex_unlock(&dev->mode_config.mutex); - intel_panel_init(&intel_connector->panel, fixed_mode, downclock_mode); + intel_panel_init(intel_connector, fixed_mode, downclock_mode); intel_backlight_setup(intel_connector, INVALID_PIPE); lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder, fixed_mode); diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index f428d0457c17..8c9e26539cc5 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -599,10 +599,12 @@ intel_panel_mode_valid(struct intel_connector *connector, return MODE_OK; } -int intel_panel_init(struct intel_panel *panel, +int intel_panel_init(struct intel_connector *connector, struct drm_display_mode *fixed_mode, struct drm_display_mode *downclock_mode) { + struct intel_panel *panel = &connector->panel; + intel_backlight_init_funcs(panel); if (fixed_mode) @@ -613,16 +615,15 @@ int intel_panel_init(struct intel_panel *panel, return 0; } -void intel_panel_fini(struct intel_panel *panel) +void intel_panel_fini(struct intel_connector *connector) { - struct intel_connector *intel_connector = - container_of(panel, struct intel_connector, panel); + struct intel_panel *panel = &connector->panel; struct drm_display_mode *fixed_mode, *next; intel_backlight_destroy(panel); list_for_each_entry_safe(fixed_mode, next, &panel->fixed_modes, head) { list_del(&fixed_mode->head); - drm_mode_destroy(intel_connector->base.dev, fixed_mode); + drm_mode_destroy(connector->base.dev, fixed_mode); } } diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index e86100903f9e..579200270825 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -16,12 +16,11 @@ struct drm_display_mode; struct drm_i915_private; struct intel_connector; struct intel_crtc_state; -struct intel_panel; -int intel_panel_init(struct intel_panel *panel, +int intel_panel_init(struct intel_connector *connector, struct drm_display_mode *fixed_mode, struct drm_display_mode *downclock_mode); -void intel_panel_fini(struct intel_panel *panel); +void intel_panel_fini(struct intel_connector *connector); enum drm_connector_status intel_panel_detect(struct drm_connector *connector, bool force); bool intel_panel_use_ssc(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 328a8f20c63b..a2061b132107 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2928,7 +2928,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) struct drm_display_mode *fixed_mode = drm_mode_duplicate(connector->dev, mode); - intel_panel_init(&intel_connector->panel, + intel_panel_init(intel_connector, fixed_mode, NULL); break; } diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index c87a6e729a3c..32f5b115c2c2 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1987,7 +1987,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) goto err_cleanup_connector; } - intel_panel_init(&intel_connector->panel, fixed_mode, NULL); + intel_panel_init(intel_connector, fixed_mode, NULL); intel_backlight_setup(intel_connector, INVALID_PIPE); vlv_dsi_add_properties(intel_connector, fixed_mode); From f01bae2dca3ec54fc607b8879dd4558e8a336dde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Mar 2022 20:29:28 +0200 Subject: [PATCH 00439/11454] drm/i915: Use DRM_MODE_FMT+DRM_MODE_ARG() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace all drm_mode_debug_printmodeline() calls with DRM_MODE_FMT+DRM_MODE_ARG(). Makes the debug output a bit more terse in places where we previously had a newline in the precedeing drm_dbg_kms(), and avoids anything else sneaking in between the two printk()s in all cases. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220323182935.4701-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_bios.c | 12 +++++----- drivers/gpu/drm/i915/display/intel_display.c | 12 +++++----- drivers/gpu/drm/i915/display/intel_dp.c | 6 ++--- drivers/gpu/drm/i915/display/intel_dvo.c | 4 ++-- drivers/gpu/drm/i915/display/intel_lvds.c | 4 ++-- drivers/gpu/drm/i915/display/intel_panel.c | 24 ++++++++++---------- drivers/gpu/drm/i915/display/intel_tv.c | 12 +++++----- 7 files changed, 37 insertions(+), 37 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c index c7afe19dd44a..3f3e8ccd9026 100644 --- a/drivers/gpu/drm/i915/display/intel_bios.c +++ b/drivers/gpu/drm/i915/display/intel_bios.c @@ -306,8 +306,8 @@ parse_lfp_panel_dtd(struct drm_i915_private *i915, i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; drm_dbg_kms(&i915->drm, - "Found panel mode in BIOS VBT legacy lfp table:\n"); - drm_mode_debug_printmodeline(panel_fixed_mode); + "Found panel mode in BIOS VBT legacy lfp table: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(panel_fixed_mode)); fp_timing = get_lvds_fp_timing(bdb, lvds_lfp_data, lvds_lfp_data_ptrs, @@ -397,8 +397,8 @@ parse_generic_dtd(struct drm_i915_private *i915, panel_fixed_mode->flags |= DRM_MODE_FLAG_NVSYNC; drm_dbg_kms(&i915->drm, - "Found panel mode in BIOS VBT generic dtd table:\n"); - drm_mode_debug_printmodeline(panel_fixed_mode); + "Found panel mode in BIOS VBT generic dtd table: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(panel_fixed_mode)); i915->vbt.lfp_lvds_vbt_mode = panel_fixed_mode; } @@ -551,8 +551,8 @@ parse_sdvo_panel_data(struct drm_i915_private *i915, i915->vbt.sdvo_lvds_vbt_mode = panel_fixed_mode; drm_dbg_kms(&i915->drm, - "Found SDVO panel mode in BIOS VBT tables:\n"); - drm_mode_debug_printmodeline(panel_fixed_mode); + "Found SDVO panel mode in BIOS VBT tables: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(panel_fixed_mode)); } static int intel_bios_ssc_frequency(struct drm_i915_private *i915, diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 24e76afb050d..84501d00653a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -5421,13 +5421,13 @@ static void intel_dump_pipe_config(const struct intel_crtc_state *pipe_config, intel_vrr_vmin_vblank_start(pipe_config), intel_vrr_vmax_vblank_start(pipe_config)); - drm_dbg_kms(&dev_priv->drm, "requested mode:\n"); - drm_mode_debug_printmodeline(&pipe_config->hw.mode); - drm_dbg_kms(&dev_priv->drm, "adjusted mode:\n"); - drm_mode_debug_printmodeline(&pipe_config->hw.adjusted_mode); + drm_dbg_kms(&dev_priv->drm, "requested mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&pipe_config->hw.mode)); + drm_dbg_kms(&dev_priv->drm, "adjusted mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&pipe_config->hw.adjusted_mode)); intel_dump_crtc_timings(dev_priv, &pipe_config->hw.adjusted_mode); - drm_dbg_kms(&dev_priv->drm, "pipe mode:\n"); - drm_mode_debug_printmodeline(&pipe_config->hw.pipe_mode); + drm_dbg_kms(&dev_priv->drm, "pipe mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&pipe_config->hw.pipe_mode)); intel_dump_crtc_timings(dev_priv, &pipe_config->hw.pipe_mode); drm_dbg_kms(&dev_priv->drm, "port clock: %d, pipe src: " DRM_RECT_FMT ", pixel rate %d\n", diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index cfe88c4cfa29..595e34fdd1e0 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -2553,9 +2553,9 @@ static void intel_edp_mso_mode_fixup(struct intel_connector *connector, drm_mode_set_name(mode); drm_dbg_kms(&i915->drm, - "[CONNECTOR:%d:%s] using generated MSO mode: ", - connector->base.base.id, connector->base.name); - drm_mode_debug_printmodeline(mode); + "[CONNECTOR:%d:%s] using generated MSO mode: " DRM_MODE_FMT "\n", + connector->base.base.id, connector->base.name, + DRM_MODE_ARG(mode)); } static void intel_edp_mso_init(struct intel_dp *intel_dp) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index d4dc16a9c0dd..90e026cef6ee 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -391,8 +391,8 @@ intel_dvo_get_current_mode(struct intel_encoder *encoder) mode = intel_encoder_current_mode(encoder); if (mode) { - DRM_DEBUG_KMS("using current (BIOS) mode: "); - drm_mode_debug_printmodeline(mode); + DRM_DEBUG_KMS("using current (BIOS) mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(mode)); mode->type |= DRM_MODE_TYPE_PREFERRED; } diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index cd685dbf324b..b57e76b4ef04 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -984,8 +984,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) */ fixed_mode = intel_encoder_current_mode(intel_encoder); if (fixed_mode) { - drm_dbg_kms(&dev_priv->drm, "using current (BIOS) mode: "); - drm_mode_debug_printmodeline(fixed_mode); + drm_dbg_kms(&dev_priv->drm, "using current (BIOS) mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(fixed_mode)); fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; } diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 8c9e26539cc5..2ba51222d156 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -194,9 +194,9 @@ intel_panel_edid_downclock_mode(struct intel_connector *connector, return NULL; drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] using downclock mode from EDID: ", - connector->base.base.id, connector->base.name); - drm_mode_debug_printmodeline(downclock_mode); + "[CONNECTOR:%d:%s] using downclock mode from EDID: " DRM_MODE_FMT "\n", + connector->base.base.id, connector->base.name, + DRM_MODE_ARG(downclock_mode)); return downclock_mode; } @@ -221,9 +221,9 @@ intel_panel_edid_fixed_mode(struct intel_connector *connector) return NULL; drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] using preferred mode from EDID: ", - connector->base.base.id, connector->base.name); - drm_mode_debug_printmodeline(fixed_mode); + "[CONNECTOR:%d:%s] using preferred mode from EDID: " DRM_MODE_FMT "\n", + connector->base.base.id, connector->base.name, + DRM_MODE_ARG(fixed_mode)); return fixed_mode; } @@ -238,9 +238,9 @@ intel_panel_edid_fixed_mode(struct intel_connector *connector) fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] using first mode from EDID: ", - connector->base.base.id, connector->base.name); - drm_mode_debug_printmodeline(fixed_mode); + "[CONNECTOR:%d:%s] using first mode from EDID: " DRM_MODE_FMT "\n", + connector->base.base.id, connector->base.name, + DRM_MODE_ARG(fixed_mode)); return fixed_mode; } @@ -262,9 +262,9 @@ intel_panel_vbt_fixed_mode(struct intel_connector *connector) fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; - drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using mode from VBT: ", - connector->base.base.id, connector->base.name); - drm_mode_debug_printmodeline(fixed_mode); + drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using mode from VBT: " DRM_MODE_FMT "\n", + connector->base.base.id, connector->base.name, + DRM_MODE_ARG(fixed_mode)); info->width_mm = fixed_mode->width_mm; info->height_mm = fixed_mode->height_mm; diff --git a/drivers/gpu/drm/i915/display/intel_tv.c b/drivers/gpu/drm/i915/display/intel_tv.c index 8a39989b87ad..9379f3463344 100644 --- a/drivers/gpu/drm/i915/display/intel_tv.c +++ b/drivers/gpu/drm/i915/display/intel_tv.c @@ -1145,8 +1145,8 @@ intel_tv_get_config(struct intel_encoder *encoder, intel_tv_mode_to_mode(&mode, &tv_mode); - drm_dbg_kms(&dev_priv->drm, "TV mode:\n"); - drm_mode_debug_printmodeline(&mode); + drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(&mode)); intel_tv_scale_mode_horiz(&mode, hdisplay, xpos, mode.hdisplay - xsize - xpos); @@ -1250,8 +1250,8 @@ intel_tv_compute_config(struct intel_encoder *encoder, tv_conn_state->bypass_vfilter = false; } - drm_dbg_kms(&dev_priv->drm, "TV mode:\n"); - drm_mode_debug_printmodeline(adjusted_mode); + drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(adjusted_mode)); /* * The pipe scanline counter behaviour looks as follows when @@ -1806,8 +1806,8 @@ intel_tv_get_modes(struct drm_connector *connector) */ intel_tv_mode_to_mode(mode, tv_mode); if (count == 0) { - drm_dbg_kms(&dev_priv->drm, "TV mode:\n"); - drm_mode_debug_printmodeline(mode); + drm_dbg_kms(&dev_priv->drm, "TV mode: " DRM_MODE_FMT "\n", + DRM_MODE_ARG(mode)); } intel_tv_scale_mode_horiz(mode, input->w, 0, 0); intel_tv_scale_mode_vert(mode, input->h, 0, 0); From e9ebf1359514ab6cfe972cddf87a9cb8ad859214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Mar 2022 20:29:29 +0200 Subject: [PATCH 00440/11454] drm/i915: Extract intel_edp_add_properties() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull the drm_connector_set_panel_orientation_with_quirk() into intel_edp_add_properties() to match how the DSI encoders do it. Less clutter in intel_edp_init_connector() overall. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220323182935.4701-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 595e34fdd1e0..8a998f9a3c74 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4954,6 +4954,22 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect drm_connector_attach_vrr_capable_property(connector); } +static void +intel_edp_add_properties(struct intel_dp *intel_dp, + const struct drm_display_mode *fixed_mode) +{ + struct intel_connector *connector = intel_dp->attached_connector; + struct drm_i915_private *i915 = to_i915(connector->base.dev); + + if (!fixed_mode) + return; + + drm_connector_set_panel_orientation_with_quirk(&connector->base, + i915->vbt.orientation, + fixed_mode->hdisplay, + fixed_mode->vdisplay); +} + static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct intel_connector *intel_connector) { @@ -5058,11 +5074,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_connector->panel.backlight.power = intel_pps_backlight_power; intel_backlight_setup(intel_connector, pipe); - if (fixed_mode) { - drm_connector_set_panel_orientation_with_quirk(connector, - dev_priv->vbt.orientation, - fixed_mode->hdisplay, fixed_mode->vdisplay); - } + intel_edp_add_properties(intel_dp, fixed_mode); return true; From f6d39f563cf73f3e2608d0f171babe24c0394c9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Mar 2022 20:29:30 +0200 Subject: [PATCH 00441/11454] drm/i915: Use intel_panel_preferred_fixed_mode() more MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use intel_panel_preferred_fixed_mode() for all the orientation quirk setup and compute_is_dual_link_lvds()). All of these happen after intel_panel_init() so the panel fixed_mode list is already in place. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220323182935.4701-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/icl_dsi.c | 7 ++++--- drivers/gpu/drm/i915/display/intel_dp.c | 7 ++++--- drivers/gpu/drm/i915/display/intel_lvds.c | 11 ++++++----- drivers/gpu/drm/i915/display/vlv_dsi.c | 7 ++++--- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index c7a6c2cce297..b4fda29b04b5 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1965,9 +1965,10 @@ static void icl_dphy_param_init(struct intel_dsi *intel_dsi) intel_dsi_log_params(intel_dsi); } -static void icl_dsi_add_properties(struct intel_connector *connector, - const struct drm_display_mode *fixed_mode) +static void icl_dsi_add_properties(struct intel_connector *connector) { + const struct drm_display_mode *fixed_mode = + intel_panel_preferred_fixed_mode(connector); u32 allowed_scalers; allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | @@ -2085,7 +2086,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) icl_dphy_param_init(intel_dsi); - icl_dsi_add_properties(intel_connector, fixed_mode); + icl_dsi_add_properties(intel_connector); return; err: diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 8a998f9a3c74..a5ad9ee96cac 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4955,11 +4955,12 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect } static void -intel_edp_add_properties(struct intel_dp *intel_dp, - const struct drm_display_mode *fixed_mode) +intel_edp_add_properties(struct intel_dp *intel_dp) { struct intel_connector *connector = intel_dp->attached_connector; struct drm_i915_private *i915 = to_i915(connector->base.dev); + const struct drm_display_mode *fixed_mode = + intel_panel_preferred_fixed_mode(connector); if (!fixed_mode) return; @@ -5074,7 +5075,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_connector->panel.backlight.power = intel_pps_backlight_power; intel_backlight_setup(intel_connector, pipe); - intel_edp_add_properties(intel_dp, fixed_mode); + intel_edp_add_properties(intel_dp); return true; diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index b57e76b4ef04..d068e0607153 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -778,12 +778,13 @@ bool intel_is_dual_link_lvds(struct drm_i915_private *dev_priv) return encoder && to_lvds_encoder(&encoder->base)->is_dual_link; } -static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder, - const struct drm_display_mode *fixed_mode) +static bool compute_is_dual_link_lvds(struct intel_lvds_encoder *lvds_encoder) { - struct drm_device *dev = lvds_encoder->base.base.dev; + struct drm_i915_private *dev_priv = to_i915(lvds_encoder->base.base.dev); + struct intel_connector *connector = lvds_encoder->attached_connector; + const struct drm_display_mode *fixed_mode = + intel_panel_preferred_fixed_mode(connector); unsigned int val; - struct drm_i915_private *dev_priv = to_i915(dev); /* use the module option value if specified */ if (dev_priv->params.lvds_channel_mode > 0) @@ -999,7 +1000,7 @@ out: intel_panel_init(intel_connector, fixed_mode, downclock_mode); intel_backlight_setup(intel_connector, INVALID_PIPE); - lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder, fixed_mode); + lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder); drm_dbg_kms(&dev_priv->drm, "detected %s-link lvds configuration\n", lvds_encoder->is_dual_link ? "dual" : "single"); diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index 32f5b115c2c2..da0af425ed94 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1657,10 +1657,11 @@ static const struct drm_connector_funcs intel_dsi_connector_funcs = { .atomic_duplicate_state = intel_digital_connector_duplicate_state, }; -static void vlv_dsi_add_properties(struct intel_connector *connector, - const struct drm_display_mode *fixed_mode) +static void vlv_dsi_add_properties(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + const struct drm_display_mode *fixed_mode = + intel_panel_preferred_fixed_mode(connector); u32 allowed_scalers; allowed_scalers = BIT(DRM_MODE_SCALE_ASPECT) | BIT(DRM_MODE_SCALE_FULLSCREEN); @@ -1990,7 +1991,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) intel_panel_init(intel_connector, fixed_mode, NULL); intel_backlight_setup(intel_connector, INVALID_PIPE); - vlv_dsi_add_properties(intel_connector, fixed_mode); + vlv_dsi_add_properties(intel_connector); return; From 688a9bbccb9034952c40b442f0f03a6a0c07d36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Mar 2022 20:29:31 +0200 Subject: [PATCH 00442/11454] drm/i915: Rename intel_panel_vbt_fixed_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rename intel_panel_vbt_fixed_mode() to intel_panel_vbt_lfp_fixed_mode() to be more descriptive. We'll have another VBT fixed mode function soon and we don't want to confuse the two. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220323182935.4701-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/icl_dsi.c | 2 +- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_lvds.c | 2 +- drivers/gpu/drm/i915/display/intel_panel.c | 2 +- drivers/gpu/drm/i915/display/intel_panel.h | 2 +- drivers/gpu/drm/i915/display/vlv_dsi.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index b4fda29b04b5..44f4c65522b9 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -2050,7 +2050,7 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) intel_connector_attach_encoder(intel_connector, encoder); mutex_lock(&dev->mode_config.mutex); - fixed_mode = intel_panel_vbt_fixed_mode(intel_connector); + fixed_mode = intel_panel_vbt_lfp_fixed_mode(intel_connector); mutex_unlock(&dev->mode_config.mutex); if (!fixed_mode) { diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index a5ad9ee96cac..c7f8fc654857 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5048,7 +5048,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, /* fallback to VBT if available for eDP */ if (!fixed_mode) - fixed_mode = intel_panel_vbt_fixed_mode(intel_connector); + fixed_mode = intel_panel_vbt_lfp_fixed_mode(intel_connector); mutex_unlock(&dev->mode_config.mutex); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index d068e0607153..c3f017c3740c 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -974,7 +974,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) goto out; /* Failed to get EDID, what about VBT? */ - fixed_mode = intel_panel_vbt_fixed_mode(intel_connector); + fixed_mode = intel_panel_vbt_lfp_fixed_mode(intel_connector); if (fixed_mode) goto out; diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 2ba51222d156..bd606d0b1c24 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -246,7 +246,7 @@ intel_panel_edid_fixed_mode(struct intel_connector *connector) } struct drm_display_mode * -intel_panel_vbt_fixed_mode(struct intel_connector *connector) +intel_panel_vbt_lfp_fixed_mode(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct drm_display_info *info = &connector->base.display_info; diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 579200270825..9704ac81fe3e 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -47,6 +47,6 @@ intel_panel_edid_downclock_mode(struct intel_connector *connector, struct drm_display_mode * intel_panel_edid_fixed_mode(struct intel_connector *connector); struct drm_display_mode * -intel_panel_vbt_fixed_mode(struct intel_connector *connector); +intel_panel_vbt_lfp_fixed_mode(struct intel_connector *connector); #endif /* __INTEL_PANEL_H__ */ diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index da0af425ed94..dc43cb8ecb86 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1980,7 +1980,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) intel_connector_attach_encoder(intel_connector, intel_encoder); mutex_lock(&dev->mode_config.mutex); - fixed_mode = intel_panel_vbt_fixed_mode(intel_connector); + fixed_mode = intel_panel_vbt_lfp_fixed_mode(intel_connector); mutex_unlock(&dev->mode_config.mutex); if (!fixed_mode) { From 14daee248f0102359898e21706f570c274c11948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Mar 2022 20:29:32 +0200 Subject: [PATCH 00443/11454] drm/i915: Extract intel_panel_vbt_sdvo_fixed_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We have a function for duplicating the VBT LFP mode. Add the same for the VBT SDVO mode. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220323182935.4701-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_panel.c | 20 ++++++++++++++++++++ drivers/gpu/drm/i915/display/intel_panel.h | 2 ++ drivers/gpu/drm/i915/display/intel_sdvo.c | 14 ++++---------- 3 files changed, 26 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index bd606d0b1c24..7f59db8b9ede 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -272,6 +272,26 @@ intel_panel_vbt_lfp_fixed_mode(struct intel_connector *connector) return fixed_mode; } +struct drm_display_mode * +intel_panel_vbt_sdvo_fixed_mode(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct drm_display_mode *fixed_mode; + + if (!i915->vbt.sdvo_lvds_vbt_mode) + return NULL; + + fixed_mode = drm_mode_duplicate(&i915->drm, + i915->vbt.sdvo_lvds_vbt_mode); + if (!fixed_mode) + return NULL; + + /* Guarantee the mode is preferred */ + fixed_mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; + + return fixed_mode; +} + /* adjusted_mode has been preset to be the panel's fixed mode */ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 9704ac81fe3e..7e32c903a1e6 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -48,5 +48,7 @@ struct drm_display_mode * intel_panel_edid_fixed_mode(struct intel_connector *connector); struct drm_display_mode * intel_panel_vbt_lfp_fixed_mode(struct intel_connector *connector); +struct drm_display_mode * +intel_panel_vbt_sdvo_fixed_mode(struct intel_connector *connector); #endif /* __INTEL_PANEL_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index a2061b132107..27b3d3a79989 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2301,16 +2301,10 @@ static int intel_sdvo_get_lvds_modes(struct drm_connector *connector) * Fetch modes from VBT. For SDVO prefer the VBT mode since some * SDVO->LVDS transcoders can't cope with the EDID mode. */ - if (dev_priv->vbt.sdvo_lvds_vbt_mode != NULL) { - newmode = drm_mode_duplicate(connector->dev, - dev_priv->vbt.sdvo_lvds_vbt_mode); - if (newmode != NULL) { - /* Guarantee the mode is preferred */ - newmode->type = (DRM_MODE_TYPE_PREFERRED | - DRM_MODE_TYPE_DRIVER); - drm_mode_probed_add(connector, newmode); - num_modes++; - } + newmode = intel_panel_vbt_sdvo_fixed_mode(to_intel_connector(connector)); + if (newmode) { + drm_mode_probed_add(connector, newmode); + num_modes++; } /* From 5248cc781d2f4a087cf20ee3c806e2945af03725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Mar 2022 20:29:33 +0200 Subject: [PATCH 00444/11454] drm/i915: Extract intel_panel_encoder_fixed_mode() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apart from the EDID and VBT based mechanism we also sometimes use the encoder's current mode as the panel fixed mode. We currently have the same code for that duplicated in two places. Let's unify. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220323182935.4701-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dvo.c | 30 +++++----------------- drivers/gpu/drm/i915/display/intel_lvds.c | 7 +---- drivers/gpu/drm/i915/display/intel_panel.c | 20 +++++++++++++++ drivers/gpu/drm/i915/display/intel_panel.h | 4 +++ 4 files changed, 31 insertions(+), 30 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 90e026cef6ee..8c98897d8313 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -378,27 +378,6 @@ static const struct drm_encoder_funcs intel_dvo_enc_funcs = { .destroy = intel_dvo_enc_destroy, }; -/* - * Attempts to get a fixed panel timing for LVDS (currently only the i830). - * - * Other chips with DVO LVDS will need to extend this to deal with the LVDS - * chip being on DVOB/C and having multiple pipes. - */ -static struct drm_display_mode * -intel_dvo_get_current_mode(struct intel_encoder *encoder) -{ - struct drm_display_mode *mode; - - mode = intel_encoder_current_mode(encoder); - if (mode) { - DRM_DEBUG_KMS("using current (BIOS) mode: " DRM_MODE_FMT "\n", - DRM_MODE_ARG(mode)); - mode->type |= DRM_MODE_TYPE_PREFERRED; - } - - return mode; -} - static enum port intel_dvo_port(i915_reg_t dvo_reg) { if (i915_mmio_reg_equal(dvo_reg, DVOA)) @@ -541,6 +520,8 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_connector_attach_encoder(intel_connector, intel_encoder); if (dvo->type == INTEL_DVO_CHIP_LVDS) { + struct drm_display_mode *fixed_mode; + /* * For our LVDS chipsets, we should hopefully be able * to dig the fixed panel mode out of the BIOS data. @@ -549,9 +530,10 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) * headers, likely), so for now, just get the current * mode being output through DVO. */ - intel_panel_init(intel_connector, - intel_dvo_get_current_mode(intel_encoder), - NULL); + fixed_mode = intel_panel_encoder_fixed_mode(intel_connector, + intel_encoder); + + intel_panel_init(intel_connector, fixed_mode, NULL); intel_dvo->panel_wants_dither = true; } diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index c3f017c3740c..5b2367bc3cd2 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -983,12 +983,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) * on. If so, assume that whatever is currently programmed is the * correct mode. */ - fixed_mode = intel_encoder_current_mode(intel_encoder); - if (fixed_mode) { - drm_dbg_kms(&dev_priv->drm, "using current (BIOS) mode: " DRM_MODE_FMT "\n", - DRM_MODE_ARG(fixed_mode)); - fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; - } + fixed_mode = intel_panel_encoder_fixed_mode(intel_connector, intel_encoder); /* If we still don't have a mode after all that, give up. */ if (!fixed_mode) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 7f59db8b9ede..882e424973d4 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -292,6 +292,26 @@ intel_panel_vbt_sdvo_fixed_mode(struct intel_connector *connector) return fixed_mode; } +struct drm_display_mode * +intel_panel_encoder_fixed_mode(struct intel_connector *connector, + struct intel_encoder *encoder) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct drm_display_mode *fixed_mode; + + fixed_mode = intel_encoder_current_mode(encoder); + if (!fixed_mode) + return NULL; + + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using current (BIOS) mode: " DRM_MODE_FMT "\n", + connector->base.base.id, connector->base.name, + DRM_MODE_ARG(fixed_mode)); + + fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; + + return fixed_mode; +} + /* adjusted_mode has been preset to be the panel's fixed mode */ static int pch_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 7e32c903a1e6..6a6ac338e9aa 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -16,6 +16,7 @@ struct drm_display_mode; struct drm_i915_private; struct intel_connector; struct intel_crtc_state; +struct intel_encoder; int intel_panel_init(struct intel_connector *connector, struct drm_display_mode *fixed_mode, @@ -50,5 +51,8 @@ struct drm_display_mode * intel_panel_vbt_lfp_fixed_mode(struct intel_connector *connector); struct drm_display_mode * intel_panel_vbt_sdvo_fixed_mode(struct intel_connector *connector); +struct drm_display_mode * +intel_panel_encoder_fixed_mode(struct intel_connector *connector, + struct intel_encoder *encoder); #endif /* __INTEL_PANEL_H__ */ From 7a36980cd2360141b5a6930236399a33c7cbbbb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Mar 2022 20:29:34 +0200 Subject: [PATCH 00445/11454] drm/i915: Use intel_panel_edid_fixed_mode() for sdvo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Despite the name intel_panel_edid_fixed_mode() doesn't actually look in the EDID. All it does is dig out the preferred mode from the connector's probed_modes list. That is also what the SDVO LVDS code is doing by hand. Let's just call intel_panel_edid_fixed_mode(). The slight difference in behaviour is that the SDVO code currently bails if it can't find the preferred mode, whereas intel_panel_edid_fixed_mode() will fall back to just returning the first mode from the probed_modes list. Can't imagine why such an LVDS panel would even exist, and also why would you have a panel and be expected to not use it? So I'm going to assume this is a total non-issue. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220323182935.4701-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_sdvo.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 27b3d3a79989..62e2e8b4358c 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2886,7 +2886,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) struct drm_connector *connector; struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - struct drm_display_mode *mode; + struct drm_display_mode *fixed_mode; DRM_DEBUG_KMS("initialising LVDS device %d\n", device); @@ -2917,16 +2917,9 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) intel_sdvo_get_lvds_modes(connector); - list_for_each_entry(mode, &connector->probed_modes, head) { - if (mode->type & DRM_MODE_TYPE_PREFERRED) { - struct drm_display_mode *fixed_mode = - drm_mode_duplicate(connector->dev, mode); + fixed_mode = intel_panel_edid_fixed_mode(intel_connector); - intel_panel_init(intel_connector, - fixed_mode, NULL); - break; - } - } + intel_panel_init(intel_connector, fixed_mode, NULL); if (!intel_panel_preferred_fixed_mode(intel_connector)) goto err; From 50203b943b4f8522e6991e38e0f11594cd6845f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Wed, 23 Mar 2022 20:29:35 +0200 Subject: [PATCH 00446/11454] drm/i915: Change SDVO fixed mode handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SDVO is the only connector type currently returning the VBT fixed mode directly from .get_modes(), everyone else just adds it to the fixed_modes list and then returns that from .get_modes(). Adjust SDVO to follow the common behaviour. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220323182935.4701-10-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_sdvo.c | 29 ++++++++--------------- 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 62e2e8b4358c..c9c3f71818d9 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2291,27 +2291,12 @@ static int intel_sdvo_get_lvds_modes(struct drm_connector *connector) { struct intel_sdvo *intel_sdvo = intel_attached_sdvo(to_intel_connector(connector)); struct drm_i915_private *dev_priv = to_i915(connector->dev); - struct drm_display_mode *newmode; int num_modes = 0; drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s]\n", connector->base.id, connector->name); - /* - * Fetch modes from VBT. For SDVO prefer the VBT mode since some - * SDVO->LVDS transcoders can't cope with the EDID mode. - */ - newmode = intel_panel_vbt_sdvo_fixed_mode(to_intel_connector(connector)); - if (newmode) { - drm_mode_probed_add(connector, newmode); - num_modes++; - } - - /* - * Attempt to get the mode list from DDC. - * Assume that the preferred modes are - * arranged in priority order. - */ + num_modes += intel_panel_get_modes(to_intel_connector(connector)); num_modes += intel_ddc_get_modes(connector, &intel_sdvo->ddc); return num_modes; @@ -2915,9 +2900,15 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) if (!intel_sdvo_create_enhance_property(intel_sdvo, intel_sdvo_connector)) goto err; - intel_sdvo_get_lvds_modes(connector); - - fixed_mode = intel_panel_edid_fixed_mode(intel_connector); + /* + * Fetch modes from VBT. For SDVO prefer the VBT mode since some + * SDVO->LVDS transcoders can't cope with the EDID mode. + */ + fixed_mode = intel_panel_vbt_sdvo_fixed_mode(intel_connector); + if (!fixed_mode) { + intel_ddc_get_modes(connector, &intel_sdvo->ddc); + fixed_mode = intel_panel_edid_fixed_mode(intel_connector); + } intel_panel_init(intel_connector, fixed_mode, NULL); From 756b807f6a3e01d238c346925006cdfd6a59e341 Mon Sep 17 00:00:00 2001 From: Tejas Upadhyay Date: Tue, 22 Mar 2022 09:36:16 +0530 Subject: [PATCH 00447/11454] drm/i915: Add RPL-S PCI IDs Add couple of RPL-S device ids Bspec : 53655 Cc: Matt Roper Signed-off-by: Tejas Upadhyay Reviewed-by: Anshuman Gupta Signed-off-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220322040616.1078009-1-tejaskumarx.surendrakumar.upadhyay@intel.com --- include/drm/i915_pciids.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/drm/i915_pciids.h b/include/drm/i915_pciids.h index 533890dc9da1..0800dc8b98b3 100644 --- a/include/drm/i915_pciids.h +++ b/include/drm/i915_pciids.h @@ -679,6 +679,8 @@ INTEL_VGA_DEVICE(0xA782, info), \ INTEL_VGA_DEVICE(0xA783, info), \ INTEL_VGA_DEVICE(0xA788, info), \ - INTEL_VGA_DEVICE(0xA789, info) + INTEL_VGA_DEVICE(0xA789, info), \ + INTEL_VGA_DEVICE(0xA78A, info), \ + INTEL_VGA_DEVICE(0xA78B, info) #endif /* _I915_PCIIDS_H */ From ec57376fba5abc0e571617ff88e2ade7970c2e4b Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Thu, 24 Mar 2022 13:48:25 -0700 Subject: [PATCH 00448/11454] drm/panel-edp: Add AUO B133UAN01 Add support for the AUO B133UAN01 13.3" WUXGA panel. Signed-off-by: Matthias Kaehlcke Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20220324134819.v2.1.I816014b6c62da5a33af5021f3cc35cea66552c00@changeid --- drivers/gpu/drm/panel/panel-edp.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index e15e62f235d8..db4eea1d7f67 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1847,6 +1847,7 @@ static const struct panel_delay delay_100_500_e200 = { static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x8495, &delay_200_500_e50, "B133UAN01.0"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0786, &delay_200_500_p2e80, "NV116WHM-T01"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d1, &boe_nv133fhm_n61.delay, "NV133FHM-N61"), From 412c942bdfae114bd3e1570936cef59d5aeb4f54 Mon Sep 17 00:00:00 2001 From: Matt Roper Date: Mon, 28 Mar 2022 17:08:21 -0700 Subject: [PATCH 00449/11454] drm/i915/ats-m: add ATS-M platform info ATS-M is a server platform based on Xe_HPG and Xe_HPM, but without display support. From a driver point of view, it's easiest to just handle it as DG2 (including identifying as PLATFORM_DG2), but with the display disabled in the device info. Signed-off-by: Matt Roper Reviewed-by: Balasubramani Vivekanandan Link: https://patchwork.freedesktop.org/patch/msgid/20220329000822.1323195-1-matthew.d.roper@intel.com --- drivers/gpu/drm/i915/i915_pci.c | 38 +++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index a95ae08b071c..8e321d300e0c 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -1038,25 +1038,35 @@ static const struct intel_device_info xehpsdv_info = { .require_force_probe = 1, }; +#define DG2_FEATURES \ + XE_HP_FEATURES, \ + XE_HPM_FEATURES, \ + DGFX_FEATURES, \ + .graphics.rel = 55, \ + .media.rel = 55, \ + PLATFORM(INTEL_DG2), \ + .has_4tile = 1, \ + .has_64k_pages = 1, \ + .has_guc_deprivilege = 1, \ + .platform_engine_mask = \ + BIT(RCS0) | BIT(BCS0) | \ + BIT(VECS0) | BIT(VECS1) | \ + BIT(VCS0) | BIT(VCS2) + __maybe_unused static const struct intel_device_info dg2_info = { - XE_HP_FEATURES, - XE_HPM_FEATURES, + DG2_FEATURES, XE_LPD_FEATURES, - DGFX_FEATURES, - .graphics.rel = 55, - .media.rel = 55, - .has_4tile = 1, - PLATFORM(INTEL_DG2), - .has_guc_deprivilege = 1, - .has_64k_pages = 1, - .platform_engine_mask = - BIT(RCS0) | BIT(BCS0) | - BIT(VECS0) | BIT(VECS1) | - BIT(VCS0) | BIT(VCS2), - .require_force_probe = 1, .display.cpu_transcoder_mask = BIT(TRANSCODER_A) | BIT(TRANSCODER_B) | BIT(TRANSCODER_C) | BIT(TRANSCODER_D), + .require_force_probe = 1, +}; + +__maybe_unused +static const struct intel_device_info ats_m_info = { + DG2_FEATURES, + .display = { 0 }, + .require_force_probe = 1, }; #undef PLATFORM From 1216c4d30723f5ed5b7576a2b96dafc4c5a8cbf9 Mon Sep 17 00:00:00 2001 From: Edmond Gagnon Date: Fri, 25 Mar 2022 17:42:12 -0500 Subject: [PATCH 00450/11454] wcn36xx: Implement tx_rate reporting Currently, the driver reports a tx_rate of 6.0 MBit/s no matter the true rate: root@linaro-developer:~# iw wlan0 link Connected to 6c:f3:7f:eb:9b:92 (on wlan0) SSID: SQ-DEVICETEST freq: 5200 RX: 4141 bytes (32 packets) TX: 2082 bytes (15 packets) signal: -77 dBm rx bitrate: 135.0 MBit/s MCS 6 40MHz short GI tx bitrate: 6.0 MBit/s bss flags: short-slot-time dtim period: 1 beacon int: 100 This patch requests HAL_GLOBAL_CLASS_A_STATS_INFO via a hal_get_stats firmware message and reports it via ieee80211_ops::sta_statistics. root@linaro-developer:~# iw wlan0 link Connected to 6c:f3:7f:eb:73:b2 (on wlan0) SSID: SQ-DEVICETEST freq: 5700 RX: 26788094 bytes (19859 packets) TX: 1101376 bytes (12119 packets) signal: -75 dBm rx bitrate: 135.0 MBit/s MCS 6 40MHz short GI tx bitrate: 108.0 MBit/s VHT-MCS 5 40MHz VHT-NSS 1 bss flags: short-slot-time dtim period: 1 beacon int: 100 Tested on MSM8939 with WCN3680B running firmware CNSS-PR-2-0-1-2-c1-00083, and verified by sniffing frames over the air with Wireshark to ensure the MCS indices match. Signed-off-by: Edmond Gagnon Reviewed-by: Benjamin Li Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220325224212.159690-1-egagnon@squareup.com --- drivers/net/wireless/ath/wcn36xx/hal.h | 7 ++- drivers/net/wireless/ath/wcn36xx/main.c | 16 +++++++ drivers/net/wireless/ath/wcn36xx/smd.c | 57 +++++++++++++++++++++++++ drivers/net/wireless/ath/wcn36xx/smd.h | 2 + drivers/net/wireless/ath/wcn36xx/txrx.c | 29 +++++++++++++ drivers/net/wireless/ath/wcn36xx/txrx.h | 1 + 6 files changed, 111 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ath/wcn36xx/hal.h b/drivers/net/wireless/ath/wcn36xx/hal.h index 2a1db9756fd5..46a49f0a51b3 100644 --- a/drivers/net/wireless/ath/wcn36xx/hal.h +++ b/drivers/net/wireless/ath/wcn36xx/hal.h @@ -2626,7 +2626,12 @@ enum tx_rate_info { HAL_TX_RATE_SGI = 0x8, /* Rate with Long guard interval */ - HAL_TX_RATE_LGI = 0x10 + HAL_TX_RATE_LGI = 0x10, + + /* VHT rates */ + HAL_TX_RATE_VHT20 = 0x20, + HAL_TX_RATE_VHT40 = 0x40, + HAL_TX_RATE_VHT80 = 0x80, }; struct ani_global_class_a_stats_info { diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index 95ea7d040d8c..864d1547e6f8 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c @@ -1400,6 +1400,21 @@ static int wcn36xx_get_survey(struct ieee80211_hw *hw, int idx, return 0; } +static void wcn36xx_sta_statistics(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct station_info *sinfo) +{ + struct wcn36xx *wcn; + u8 sta_index; + int status; + + wcn = hw->priv; + sta_index = get_sta_index(vif, wcn36xx_sta_to_priv(sta)); + status = wcn36xx_smd_get_stats(wcn, sta_index, HAL_GLOBAL_CLASS_A_STATS_INFO, sinfo); + + if (status) + wcn36xx_err("wcn36xx_smd_get_stats failed\n"); +} + static const struct ieee80211_ops wcn36xx_ops = { .start = wcn36xx_start, .stop = wcn36xx_stop, @@ -1423,6 +1438,7 @@ static const struct ieee80211_ops wcn36xx_ops = { .set_rts_threshold = wcn36xx_set_rts_threshold, .sta_add = wcn36xx_sta_add, .sta_remove = wcn36xx_sta_remove, + .sta_statistics = wcn36xx_sta_statistics, .ampdu_action = wcn36xx_ampdu_action, #if IS_ENABLED(CONFIG_IPV6) .ipv6_addr_change = wcn36xx_ipv6_addr_change, diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c index 59ad332156ae..872b37875c57 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.c +++ b/drivers/net/wireless/ath/wcn36xx/smd.c @@ -2627,6 +2627,62 @@ out: return ret; } +int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask, + struct station_info *sinfo) +{ + struct wcn36xx_hal_stats_req_msg msg_body; + struct wcn36xx_hal_stats_rsp_msg *rsp; + void *rsp_body; + int ret; + + if (stats_mask & ~HAL_GLOBAL_CLASS_A_STATS_INFO) { + wcn36xx_err("stats_mask 0x%x contains unimplemented types\n", + stats_mask); + return -EINVAL; + } + + mutex_lock(&wcn->hal_mutex); + INIT_HAL_MSG(msg_body, WCN36XX_HAL_GET_STATS_REQ); + + msg_body.sta_id = sta_index; + msg_body.stats_mask = stats_mask; + + PREPARE_HAL_BUF(wcn->hal_buf, msg_body); + + ret = wcn36xx_smd_send_and_wait(wcn, msg_body.header.len); + if (ret) { + wcn36xx_err("sending hal_get_stats failed\n"); + goto out; + } + + ret = wcn36xx_smd_rsp_status_check(wcn->hal_buf, wcn->hal_rsp_len); + if (ret) { + wcn36xx_err("hal_get_stats response failed err=%d\n", ret); + goto out; + } + + rsp = (struct wcn36xx_hal_stats_rsp_msg *)wcn->hal_buf; + rsp_body = (wcn->hal_buf + sizeof(struct wcn36xx_hal_stats_rsp_msg)); + + if (rsp->stats_mask != stats_mask) { + wcn36xx_err("stats_mask 0x%x differs from requested 0x%x\n", + rsp->stats_mask, stats_mask); + goto out; + } + + if (rsp->stats_mask & HAL_GLOBAL_CLASS_A_STATS_INFO) { + struct ani_global_class_a_stats_info *stats_info = rsp_body; + + wcn36xx_process_tx_rate(stats_info, &sinfo->txrate); + sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_BITRATE); + rsp_body += sizeof(struct ani_global_class_a_stats_info); + } +out: + mutex_unlock(&wcn->hal_mutex); + + return ret; +} + static int wcn36xx_smd_trigger_ba_rsp(void *buf, int len, struct add_ba_info *ba_info) { struct wcn36xx_hal_trigger_ba_rsp_candidate *candidate; @@ -3316,6 +3372,7 @@ int wcn36xx_smd_rsp_process(struct rpmsg_device *rpdev, case WCN36XX_HAL_ADD_BA_SESSION_RSP: case WCN36XX_HAL_ADD_BA_RSP: case WCN36XX_HAL_DEL_BA_RSP: + case WCN36XX_HAL_GET_STATS_RSP: case WCN36XX_HAL_TRIGGER_BA_RSP: case WCN36XX_HAL_UPDATE_CFG_RSP: case WCN36XX_HAL_JOIN_RSP: diff --git a/drivers/net/wireless/ath/wcn36xx/smd.h b/drivers/net/wireless/ath/wcn36xx/smd.h index 957cfa87fbde..3fd598ac2a27 100644 --- a/drivers/net/wireless/ath/wcn36xx/smd.h +++ b/drivers/net/wireless/ath/wcn36xx/smd.h @@ -138,6 +138,8 @@ int wcn36xx_smd_add_ba_session(struct wcn36xx *wcn, int wcn36xx_smd_add_ba(struct wcn36xx *wcn, u8 session_id); int wcn36xx_smd_del_ba(struct wcn36xx *wcn, u16 tid, u8 direction, u8 sta_index); int wcn36xx_smd_trigger_ba(struct wcn36xx *wcn, u8 sta_index, u16 tid, u16 *ssn); +int wcn36xx_smd_get_stats(struct wcn36xx *wcn, u8 sta_index, u32 stats_mask, + struct station_info *sinfo); int wcn36xx_smd_update_cfg(struct wcn36xx *wcn, u32 cfg_id, u32 value); diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.c b/drivers/net/wireless/ath/wcn36xx/txrx.c index df749b114568..8da3955995b6 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.c +++ b/drivers/net/wireless/ath/wcn36xx/txrx.c @@ -699,3 +699,32 @@ int wcn36xx_start_tx(struct wcn36xx *wcn, return ret; } + +void wcn36xx_process_tx_rate(struct ani_global_class_a_stats_info *stats, struct rate_info *info) +{ + /* tx_rate is in units of 500kbps; mac80211 wants them in 100kbps */ + if (stats->tx_rate_flags & HAL_TX_RATE_LEGACY) + info->legacy = stats->tx_rate * 5; + + info->flags = 0; + info->mcs = stats->mcs_index; + info->nss = 1; + + if (stats->tx_rate_flags & (HAL_TX_RATE_HT20 | HAL_TX_RATE_HT40)) + info->flags |= RATE_INFO_FLAGS_MCS; + + if (stats->tx_rate_flags & (HAL_TX_RATE_VHT20 | HAL_TX_RATE_VHT40 | HAL_TX_RATE_VHT80)) + info->flags |= RATE_INFO_FLAGS_VHT_MCS; + + if (stats->tx_rate_flags & HAL_TX_RATE_SGI) + info->flags |= RATE_INFO_FLAGS_SHORT_GI; + + if (stats->tx_rate_flags & (HAL_TX_RATE_HT20 | HAL_TX_RATE_VHT20)) + info->bw = RATE_INFO_BW_20; + + if (stats->tx_rate_flags & (HAL_TX_RATE_HT40 | HAL_TX_RATE_VHT40)) + info->bw = RATE_INFO_BW_40; + + if (stats->tx_rate_flags & HAL_TX_RATE_VHT80) + info->bw = RATE_INFO_BW_80; +} diff --git a/drivers/net/wireless/ath/wcn36xx/txrx.h b/drivers/net/wireless/ath/wcn36xx/txrx.h index b54311ffde9c..fb0d6cabd52b 100644 --- a/drivers/net/wireless/ath/wcn36xx/txrx.h +++ b/drivers/net/wireless/ath/wcn36xx/txrx.h @@ -164,5 +164,6 @@ int wcn36xx_rx_skb(struct wcn36xx *wcn, struct sk_buff *skb); int wcn36xx_start_tx(struct wcn36xx *wcn, struct wcn36xx_sta *sta_priv, struct sk_buff *skb); +void wcn36xx_process_tx_rate(struct ani_global_class_a_stats_info *stats, struct rate_info *info); #endif /* _TXRX_H_ */ From 801cb1d234288d9bc2afeaa98c7e98f8038b7a6c Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Mon, 28 Mar 2022 14:57:19 +0300 Subject: [PATCH 00451/11454] ath11k: add support to search regdb data in board-2.bin for WCN6855 Currently ath11k only download the same regdb.bin file for all WCN6855 chips, actually ath11k needs to distinguish all different WCN6855 chips. This is to re-use the string type which include bus, chip id, board id, vendor, device, subsystem-vendor, subsystem-device and variant for WCN6855 to distinguish different regdb in board-2.bin. ath11k will first load board-2.bin and search in it for the regdb data with the above parameters, if matched one regdb data, then download it to firmware, if not matched any one, then ath11k will download the file regdb.bin to firmware. Add enum value ATH11K_BD_IE_REGDB and enum type ath11k_bd_ie_regdb_type to distinguish regdb data and board data since they are in the same file board-2.bin. This only take effect for WCN6855 which supports regdb in hardware parameters. Test log: [ 3833.091948] ath11k_pci 0000:05:00.0: boot using board name 'bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262' [ 3833.092072] ath11k_pci 0000:05:00.0: boot firmware request ath11k/WCN6855/hw2.0/board-2.bin size 205316 [ 3833.092079] ath11k_pci 0000:05:00.0: board name [ 3833.092083] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 71 6d 69 2d 63 68 69 70 bus=pci,qmi-chip [ 3833.092088] ath11k_pci 0000:05:00.0: 00000010: 2d 69 64 3d 31 -id=1 [ 3833.092091] ath11k_pci 0000:05:00.0: board name [ 3833.092095] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 71 6d 69 2d 63 68 69 70 bus=pci,qmi-chip [ 3833.092099] ath11k_pci 0000:05:00.0: 00000010: 2d 69 64 3d 32 -id=2 [ 3833.092102] ath11k_pci 0000:05:00.0: board name [ 3833.092105] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 71 6d 69 2d 63 68 69 70 bus=pci,qmi-chip [ 3833.092109] ath11k_pci 0000:05:00.0: 00000010: 2d 69 64 3d 33 -id=3 [ 3833.092112] ath11k_pci 0000:05:00.0: board name [ 3833.092116] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 76 65 6e 64 6f 72 3d 31 bus=pci,vendor=1 [ 3833.092119] ath11k_pci 0000:05:00.0: 00000010: 37 63 62 2c 64 65 76 69 63 65 3d 31 31 30 33 2c 7cb,device=1103, [ 3833.092123] ath11k_pci 0000:05:00.0: 00000020: 73 75 62 73 79 73 74 65 6d 2d 76 65 6e 64 6f 72 subsystem-vendor [ 3833.092126] ath11k_pci 0000:05:00.0: 00000030: 3d 31 37 63 62 2c 73 75 62 73 79 73 74 65 6d 2d =17cb,subsystem- [ 3833.092130] ath11k_pci 0000:05:00.0: 00000040: 64 65 76 69 63 65 3d 33 33 37 34 2c 71 6d 69 2d device=3374,qmi- [ 3833.092133] ath11k_pci 0000:05:00.0: 00000050: 63 68 69 70 2d 69 64 3d 32 2c 71 6d 69 2d 62 6f chip-id=2,qmi-bo [ 3833.092137] ath11k_pci 0000:05:00.0: 00000060: 61 72 64 2d 69 64 3d 32 36 36 2c 76 61 72 69 61 ard-id=266,varia [ 3833.092140] ath11k_pci 0000:05:00.0: 00000070: 6e 74 3d 48 50 5f 47 38 5f 4c 61 6e 63 69 61 31 nt=HP_G8_Lancia1 [ 3833.092144] ath11k_pci 0000:05:00.0: 00000080: 35 5 [ 3833.092147] ath11k_pci 0000:05:00.0: board name [ 3833.092150] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 76 65 6e 64 6f 72 3d 31 bus=pci,vendor=1 [ 3833.092154] ath11k_pci 0000:05:00.0: 00000010: 37 63 62 2c 64 65 76 69 63 65 3d 31 31 30 33 2c 7cb,device=1103, [ 3833.092157] ath11k_pci 0000:05:00.0: 00000020: 73 75 62 73 79 73 74 65 6d 2d 76 65 6e 64 6f 72 subsystem-vendor [ 3833.092161] ath11k_pci 0000:05:00.0: 00000030: 3d 31 37 63 62 2c 73 75 62 73 79 73 74 65 6d 2d =17cb,subsystem- [ 3833.092165] ath11k_pci 0000:05:00.0: 00000040: 64 65 76 69 63 65 3d 33 33 37 34 2c 71 6d 69 2d device=3374,qmi- [ 3833.092168] ath11k_pci 0000:05:00.0: 00000050: 63 68 69 70 2d 69 64 3d 32 2c 71 6d 69 2d 62 6f chip-id=2,qmi-bo [ 3833.092172] ath11k_pci 0000:05:00.0: 00000060: 61 72 64 2d 69 64 3d 32 36 36 ard-id=266 [ 3833.092206] ath11k_pci 0000:05:00.0: board name [ 3833.092209] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 76 65 6e 64 6f 72 3d 31 bus=pci,vendor=1 [ 3833.092213] ath11k_pci 0000:05:00.0: 00000010: 37 63 62 2c 64 65 76 69 63 65 3d 31 31 30 33 2c 7cb,device=1103, [ 3833.092216] ath11k_pci 0000:05:00.0: 00000020: 73 75 62 73 79 73 74 65 6d 2d 76 65 6e 64 6f 72 subsystem-vendor [ 3833.092220] ath11k_pci 0000:05:00.0: 00000030: 3d 31 37 63 62 2c 73 75 62 73 79 73 74 65 6d 2d =17cb,subsystem- [ 3833.092223] ath11k_pci 0000:05:00.0: 00000040: 64 65 76 69 63 65 3d 33 33 37 34 2c 71 6d 69 2d device=3374,qmi- [ 3833.092227] ath11k_pci 0000:05:00.0: 00000050: 63 68 69 70 2d 69 64 3d 32 2c 71 6d 69 2d 62 6f chip-id=2,qmi-bo [ 3833.092230] ath11k_pci 0000:05:00.0: 00000060: 61 72 64 2d 69 64 3d 32 36 32 ard-id=262 [ 3833.092234] ath11k_pci 0000:05:00.0: boot found match regdb data for name 'bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262' [ 3833.092238] ath11k_pci 0000:05:00.0: board name [ 3833.092241] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 71 6d 69 2d 63 68 69 70 bus=pci,qmi-chip [ 3833.092245] ath11k_pci 0000:05:00.0: 00000010: 2d 69 64 3d 31 31 -id=11 [ 3833.092248] ath11k_pci 0000:05:00.0: board name [ 3833.092251] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 71 6d 69 2d 63 68 69 70 bus=pci,qmi-chip [ 3833.092255] ath11k_pci 0000:05:00.0: 00000010: 2d 69 64 3d 32 32 -id=22 [ 3833.092258] ath11k_pci 0000:05:00.0: board name [ 3833.092261] ath11k_pci 0000:05:00.0: 00000000: 62 75 73 3d 70 63 69 2c 71 6d 69 2d 63 68 69 70 bus=pci,qmi-chip [ 3833.092265] ath11k_pci 0000:05:00.0: 00000010: 2d 69 64 3d 33 33 -id=33 [ 3833.092268] ath11k_pci 0000:05:00.0: boot found regdb data for 'bus=pci,vendor=17cb,device=1103,subsystem-vendor=17cb,subsystem-device=3374,qmi-chip-id=2,qmi-board-id=262' [ 3833.092272] ath11k_pci 0000:05:00.0: fetched regdb Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220319023543.14288-4-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 84 ++++++++++++++++++-------- drivers/net/wireless/ath/ath11k/hw.h | 19 ++++++ 2 files changed, 78 insertions(+), 25 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index 9395a5a271f1..d1d8a2f99196 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -723,7 +723,9 @@ static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab, struct ath11k_board_data *bd, const void *buf, size_t buf_len, const char *boardname, - int bd_ie_type) + int ie_id, + int name_id, + int data_id) { const struct ath11k_fw_ie *hdr; bool name_match_found; @@ -733,7 +735,7 @@ static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab, name_match_found = false; - /* go through ATH11K_BD_IE_BOARD_ elements */ + /* go through ATH11K_BD_IE_BOARD_/ATH11K_BD_IE_REGDB_ elements */ while (buf_len > sizeof(struct ath11k_fw_ie)) { hdr = buf; board_ie_id = le32_to_cpu(hdr->id); @@ -744,48 +746,50 @@ static int ath11k_core_parse_bd_ie_board(struct ath11k_base *ab, buf += sizeof(*hdr); if (buf_len < ALIGN(board_ie_len, 4)) { - ath11k_err(ab, "invalid ATH11K_BD_IE_BOARD length: %zu < %zu\n", + ath11k_err(ab, "invalid %s length: %zu < %zu\n", + ath11k_bd_ie_type_str(ie_id), buf_len, ALIGN(board_ie_len, 4)); ret = -EINVAL; goto out; } - switch (board_ie_id) { - case ATH11K_BD_IE_BOARD_NAME: + if (board_ie_id == name_id) { ath11k_dbg_dump(ab, ATH11K_DBG_BOOT, "board name", "", board_ie_data, board_ie_len); if (board_ie_len != strlen(boardname)) - break; + goto next; ret = memcmp(board_ie_data, boardname, strlen(boardname)); if (ret) - break; + goto next; name_match_found = true; ath11k_dbg(ab, ATH11K_DBG_BOOT, - "boot found match for name '%s'", + "boot found match %s for name '%s'", + ath11k_bd_ie_type_str(ie_id), boardname); - break; - case ATH11K_BD_IE_BOARD_DATA: + } else if (board_ie_id == data_id) { if (!name_match_found) /* no match found */ - break; + goto next; ath11k_dbg(ab, ATH11K_DBG_BOOT, - "boot found board data for '%s'", boardname); + "boot found %s for '%s'", + ath11k_bd_ie_type_str(ie_id), + boardname); bd->data = board_ie_data; bd->len = board_ie_len; ret = 0; goto out; - default: - ath11k_warn(ab, "unknown ATH11K_BD_IE_BOARD found: %d\n", + } else { + ath11k_warn(ab, "unknown %s id found: %d\n", + ath11k_bd_ie_type_str(ie_id), board_ie_id); - break; } - +next: /* jump over the padding */ board_ie_len = ALIGN(board_ie_len, 4); @@ -802,7 +806,10 @@ out: static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, struct ath11k_board_data *bd, - const char *boardname) + const char *boardname, + int ie_id_match, + int name_id, + int data_id) { size_t len, magic_len; const u8 *data; @@ -867,22 +874,23 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, goto err; } - switch (ie_id) { - case ATH11K_BD_IE_BOARD: + if (ie_id == ie_id_match) { ret = ath11k_core_parse_bd_ie_board(ab, bd, data, ie_len, boardname, - ATH11K_BD_IE_BOARD); + ie_id_match, + name_id, + data_id); if (ret == -ENOENT) /* no match found, continue */ - break; + goto next; else if (ret) /* there was an error, bail out */ goto err; /* either found or error, so stop searching */ goto out; } - +next: /* jump over the padding */ ie_len = ALIGN(ie_len, 4); @@ -893,7 +901,8 @@ static int ath11k_core_fetch_board_data_api_n(struct ath11k_base *ab, out: if (!bd->data || !bd->len) { ath11k_dbg(ab, ATH11K_DBG_BOOT, - "failed to fetch board data for %s from %s\n", + "failed to fetch %s for %s from %s\n", + ath11k_bd_ie_type_str(ie_id_match), boardname, filepath); ret = -ENODATA; goto err; @@ -937,7 +946,10 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) } ab->bd_api = 2; - ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname); + ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname, + ATH11K_BD_IE_BOARD, + ATH11K_BD_IE_BOARD_NAME, + ATH11K_BD_IE_BOARD_DATA); if (!ret) goto success; @@ -948,7 +960,10 @@ int ath11k_core_fetch_bdf(struct ath11k_base *ab, struct ath11k_board_data *bd) return ret; } - ret = ath11k_core_fetch_board_data_api_n(ab, bd, fallback_boardname); + ret = ath11k_core_fetch_board_data_api_n(ab, bd, fallback_boardname, + ATH11K_BD_IE_BOARD, + ATH11K_BD_IE_BOARD_NAME, + ATH11K_BD_IE_BOARD_DATA); if (!ret) goto success; @@ -975,13 +990,32 @@ success: int ath11k_core_fetch_regdb(struct ath11k_base *ab, struct ath11k_board_data *bd) { + char boardname[BOARD_NAME_SIZE]; int ret; + ret = ath11k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE); + if (ret) { + ath11k_dbg(ab, ATH11K_DBG_BOOT, + "failed to create board name for regdb: %d", ret); + goto exit; + } + + ret = ath11k_core_fetch_board_data_api_n(ab, bd, boardname, + ATH11K_BD_IE_REGDB, + ATH11K_BD_IE_REGDB_NAME, + ATH11K_BD_IE_REGDB_DATA); + if (!ret) + goto exit; + ret = ath11k_core_fetch_board_data_api_1(ab, bd, ATH11K_REGDB_FILE_NAME); if (ret) ath11k_dbg(ab, ATH11K_DBG_BOOT, "failed to fetch %s from %s\n", ATH11K_REGDB_FILE_NAME, ab->hw_params.fw.dir); +exit: + if (!ret) + ath11k_dbg(ab, ATH11K_DBG_BOOT, "fetched regdb\n"); + return ret; } diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h index 5955c6f5da24..44025bc5d082 100644 --- a/drivers/net/wireless/ath/ath11k/hw.h +++ b/drivers/net/wireless/ath/ath11k/hw.h @@ -291,9 +291,16 @@ enum ath11k_bd_ie_board_type { ATH11K_BD_IE_BOARD_DATA = 1, }; +enum ath11k_bd_ie_regdb_type { + ATH11K_BD_IE_REGDB_NAME = 0, + ATH11K_BD_IE_REGDB_DATA = 1, +}; + enum ath11k_bd_ie_type { /* contains sub IEs of enum ath11k_bd_ie_board_type */ ATH11K_BD_IE_BOARD = 0, + /* contains sub IEs of enum ath11k_bd_ie_regdb_type */ + ATH11K_BD_IE_REGDB = 1, }; struct ath11k_hw_regs { @@ -361,4 +368,16 @@ extern const struct ath11k_hw_regs qca6390_regs; extern const struct ath11k_hw_regs qcn9074_regs; extern const struct ath11k_hw_regs wcn6855_regs; +static inline const char *ath11k_bd_ie_type_str(enum ath11k_bd_ie_type type) +{ + switch (type) { + case ATH11K_BD_IE_BOARD: + return "board data"; + case ATH11K_BD_IE_REGDB: + return "regdb data"; + } + + return "unknown"; +} + #endif From 1f682dc9fb3790aa7ec27d3d122ff32b1eda1365 Mon Sep 17 00:00:00 2001 From: Wen Gong Date: Sun, 27 Mar 2022 23:58:32 -0400 Subject: [PATCH 00452/11454] ath11k: reduce the wait time of 11d scan and hw scan while add interface Currently ath11k will wait 11d scan complete while add interface in ath11k_mac_op_add_interface(), when system resume without enable wowlan, ath11k_mac_op_add_interface() is called for each resume, thus it increase the resume time of system. And ath11k_mac_op_hw_scan() after ath11k_mac_op_add_interface() also needs some time cost because the previous 11d scan need more than 5 seconds when 6 GHz is enabled, then the scan started event will indicated to ath11k after the 11d scan completed. While 11d scan/hw scan is running in firmware, if ath11k update channel list to firmware by WMI_SCAN_CHAN_LIST_CMDID, then firmware will cancel the current scan which is running, it lead the scan failed. The patch commit 9dcf6808b253 ("ath11k: add 11d scan offload support") used finish_11d_scan/finish_11d_ch_list/pending_11d to synchronize the 11d scan/hw scan/channel list between ath11k/firmware/mac80211 and to avoid the scan fail. Add wait operation before ath11k update channel list, function ath11k_reg_update_chan_list() will wait until the current 11d scan/hw scan completed. And remove the wait operation of start 11d scan and waiting channel list complete in hw scan. After these changes, resume time cost reduce about 5 seconds and also hw scan time cost reduced obviously, and scan failed not seen. The 11d scan is sent to firmware only one time for each interface added in mac.c, and it is moved after the 1st hw scan because 11d scan will cost some time and thus leads the AP scan result update to UI delay. Currently priority of ath11k's hw scan is WMI_SCAN_PRIORITY_LOW, and priority of 11d scan in firmware is WMI_SCAN_PRIORITY_MEDIUM, then the 11d scan which sent after hw scan will cancel the hw scan in firmware, so change the priority to WMI_SCAN_PRIORITY_MEDIUM for the hw scan which is in front of the 11d scan, thus it will not happen scan cancel in firmware. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 Fixes: 9dcf6808b253 ("ath11k: add 11d scan offload support") Signed-off-by: Wen Gong Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20220328035832.14122-1-quic_wgong@quicinc.com --- drivers/net/wireless/ath/ath11k/core.c | 1 + drivers/net/wireless/ath/ath11k/core.h | 13 +++-- drivers/net/wireless/ath/ath11k/mac.c | 71 +++++++++++--------------- drivers/net/wireless/ath/ath11k/mac.h | 2 +- drivers/net/wireless/ath/ath11k/reg.c | 43 ++++++++++------ drivers/net/wireless/ath/ath11k/reg.h | 2 +- drivers/net/wireless/ath/ath11k/wmi.c | 16 +++++- 7 files changed, 84 insertions(+), 64 deletions(-) diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index d1d8a2f99196..7f4462cf5787 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1465,6 +1465,7 @@ static void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) ieee80211_stop_queues(ar->hw); ath11k_mac_drain_tx(ar); + complete(&ar->completed_11d_scan); complete(&ar->scan.started); complete(&ar->scan.completed); complete(&ar->peer_assoc_done); diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h index b4d58e01fffa..17a61d0d684e 100644 --- a/drivers/net/wireless/ath/ath11k/core.h +++ b/drivers/net/wireless/ath/ath11k/core.h @@ -52,6 +52,8 @@ extern unsigned int ath11k_frame_mode; +#define ATH11K_SCAN_TIMEOUT_HZ (20 * HZ) + #define ATH11K_MON_TIMER_INTERVAL 10 #define ATH11K_RESET_TIMEOUT_HZ (20 * HZ) #define ATH11K_RESET_MAX_FAIL_COUNT_FIRST 3 @@ -216,6 +218,12 @@ enum ath11k_scan_state { ATH11K_SCAN_ABORTING, }; +enum ath11k_11d_state { + ATH11K_11D_IDLE, + ATH11K_11D_PREPARING, + ATH11K_11D_RUNNING, +}; + enum ath11k_dev_flags { ATH11K_CAC_RUNNING, ATH11K_FLAG_CORE_REGISTERED, @@ -664,9 +672,8 @@ struct ath11k { bool dfs_block_radar_events; struct ath11k_thermal thermal; u32 vdev_id_11d_scan; - struct completion finish_11d_scan; - struct completion finish_11d_ch_list; - bool pending_11d; + struct completion completed_11d_scan; + enum ath11k_11d_state state_11d; bool regdom_set_by_user; int hw_rate_code; u8 twt_enabled; diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index 9caa8b87c313..175a4ae752f3 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -3621,26 +3621,6 @@ static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw, if (ret) goto exit; - /* Currently the pending_11d=true only happened 1 time while - * wlan interface up in ath11k_mac_11d_scan_start(), it is called by - * ath11k_mac_op_add_interface(), after wlan interface up, - * pending_11d=false always. - * If remove below wait, it always happened scan fail and lead connect - * fail while wlan interface up, because it has a 11d scan which is running - * in firmware, and lead this scan failed. - */ - if (ar->pending_11d) { - long time_left; - unsigned long timeout = 5 * HZ; - - if (ar->supports_6ghz) - timeout += 5 * HZ; - - time_left = wait_for_completion_timeout(&ar->finish_11d_ch_list, timeout); - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac wait 11d channel list time left %ld\n", time_left); - } - memset(&arg, 0, sizeof(arg)); ath11k_wmi_start_scan_init(ar, &arg); arg.vdev_id = arvif->vdev_id; @@ -3706,6 +3686,10 @@ exit: kfree(arg.extraie.ptr); mutex_unlock(&ar->conf_mutex); + + if (ar->state_11d == ATH11K_11D_PREPARING) + ath11k_mac_11d_scan_start(ar, arvif->vdev_id); + return ret; } @@ -5859,7 +5843,7 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw) /* TODO: Do we need to enable ANI? */ - ath11k_reg_update_chan_list(ar); + ath11k_reg_update_chan_list(ar, false); ar->num_started_vdevs = 0; ar->num_created_vdevs = 0; @@ -5926,6 +5910,11 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw) cancel_work_sync(&ar->ab->update_11d_work); cancel_work_sync(&ar->ab->rfkill_work); + if (ar->state_11d == ATH11K_11D_PREPARING) { + ar->state_11d = ATH11K_11D_IDLE; + complete(&ar->completed_11d_scan); + } + spin_lock_bh(&ar->data_lock); list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) { list_del(&ppdu_stats->list); @@ -6096,7 +6085,7 @@ static bool ath11k_mac_vif_ap_active_any(struct ath11k_base *ab) return false; } -void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait) +void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id) { struct wmi_11d_scan_start_params param; int ret; @@ -6124,28 +6113,22 @@ void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait) ath11k_dbg(ar->ab, ATH11K_DBG_MAC, "mac start 11d scan\n"); - if (wait) - reinit_completion(&ar->finish_11d_scan); - ret = ath11k_wmi_send_11d_scan_start_cmd(ar, ¶m); if (ret) { ath11k_warn(ar->ab, "failed to start 11d scan vdev %d ret: %d\n", vdev_id, ret); } else { ar->vdev_id_11d_scan = vdev_id; - if (wait) { - ar->pending_11d = true; - ret = wait_for_completion_timeout(&ar->finish_11d_scan, - 5 * HZ); - ath11k_dbg(ar->ab, ATH11K_DBG_MAC, - "mac 11d scan left time %d\n", ret); - - if (!ret) - ar->pending_11d = false; - } + if (ar->state_11d == ATH11K_11D_PREPARING) + ar->state_11d = ATH11K_11D_RUNNING; } fin: + if (ar->state_11d == ATH11K_11D_PREPARING) { + ar->state_11d = ATH11K_11D_IDLE; + complete(&ar->completed_11d_scan); + } + mutex_unlock(&ar->ab->vdev_id_11d_lock); } @@ -6168,12 +6151,15 @@ void ath11k_mac_11d_scan_stop(struct ath11k *ar) vdev_id = ar->vdev_id_11d_scan; ret = ath11k_wmi_send_11d_scan_stop_cmd(ar, vdev_id); - if (ret) + if (ret) { ath11k_warn(ar->ab, "failed to stopt 11d scan vdev %d ret: %d\n", vdev_id, ret); - else + } else { ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID; + ar->state_11d = ATH11K_11D_IDLE; + complete(&ar->completed_11d_scan); + } } mutex_unlock(&ar->ab->vdev_id_11d_lock); } @@ -6369,8 +6355,10 @@ static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw, goto err_peer_del; } - ath11k_mac_11d_scan_start(ar, arvif->vdev_id, true); - + if (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab->wmi_ab.svc_map)) { + reinit_completion(&ar->completed_11d_scan); + ar->state_11d = ATH11K_11D_PREPARING; + } break; case WMI_VDEV_TYPE_MONITOR: set_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); @@ -7230,7 +7218,7 @@ ath11k_mac_op_unassign_vif_chanctx(struct ieee80211_hw *hw, } if (arvif->vdev_type == WMI_VDEV_TYPE_STA) - ath11k_mac_11d_scan_start(ar, arvif->vdev_id, false); + ath11k_mac_11d_scan_start(ar, arvif->vdev_id); mutex_unlock(&ar->conf_mutex); } @@ -8920,8 +8908,7 @@ int ath11k_mac_allocate(struct ath11k_base *ab) ar->monitor_vdev_id = -1; clear_bit(ATH11K_FLAG_MONITOR_VDEV_CREATED, &ar->monitor_flags); ar->vdev_id_11d_scan = ATH11K_11D_INVALID_VDEV_ID; - init_completion(&ar->finish_11d_scan); - init_completion(&ar->finish_11d_ch_list); + init_completion(&ar->completed_11d_scan); } return 0; diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index 045bf4fe1706..7f93e3a9ca23 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -130,7 +130,7 @@ extern const struct htt_rx_ring_tlv_filter ath11k_mac_mon_status_filter_default; #define ATH11K_SCAN_11D_INTERVAL 600000 #define ATH11K_11D_INVALID_VDEV_ID 0xFFFF -void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id, bool wait); +void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id); void ath11k_mac_11d_scan_stop(struct ath11k *ar); void ath11k_mac_11d_scan_stop_all(struct ath11k_base *ab); diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c index 35eb1a0c04dc..79ac2142317a 100644 --- a/drivers/net/wireless/ath/ath11k/reg.c +++ b/drivers/net/wireless/ath/ath11k/reg.c @@ -103,7 +103,7 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) ar->regdom_set_by_user = true; } -int ath11k_reg_update_chan_list(struct ath11k *ar) +int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait) { struct ieee80211_supported_band **bands; struct scan_chan_list_params *params; @@ -112,7 +112,32 @@ int ath11k_reg_update_chan_list(struct ath11k *ar) struct channel_param *ch; enum nl80211_band band; int num_channels = 0; - int i, ret; + int i, ret, left; + + if (wait && ar->state_11d != ATH11K_11D_IDLE) { + left = wait_for_completion_timeout(&ar->completed_11d_scan, + ATH11K_SCAN_TIMEOUT_HZ); + if (!left) { + ath11k_dbg(ar->ab, ATH11K_DBG_REG, + "failed to receive 11d scan complete: timed out\n"); + ar->state_11d = ATH11K_11D_IDLE; + } + ath11k_dbg(ar->ab, ATH11K_DBG_REG, + "reg 11d scan wait left time %d\n", left); + } + + if (wait && + (ar->scan.state == ATH11K_SCAN_STARTING || + ar->scan.state == ATH11K_SCAN_RUNNING)) { + left = wait_for_completion_timeout(&ar->scan.completed, + ATH11K_SCAN_TIMEOUT_HZ); + if (!left) + ath11k_dbg(ar->ab, ATH11K_DBG_REG, + "failed to receive hw scan complete: timed out\n"); + + ath11k_dbg(ar->ab, ATH11K_DBG_REG, + "reg hw scan wait left time %d\n", left); + } bands = hw->wiphy->bands; for (band = 0; band < NUM_NL80211_BANDS; band++) { @@ -194,11 +219,6 @@ int ath11k_reg_update_chan_list(struct ath11k *ar) ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params); kfree(params); - if (ar->pending_11d) { - complete(&ar->finish_11d_ch_list); - ar->pending_11d = false; - } - return ret; } @@ -264,15 +284,8 @@ int ath11k_regd_update(struct ath11k *ar) goto err; } - if (ar->pending_11d) - complete(&ar->finish_11d_scan); - rtnl_lock(); wiphy_lock(ar->hw->wiphy); - - if (ar->pending_11d) - reinit_completion(&ar->finish_11d_ch_list); - ret = regulatory_set_wiphy_regd_sync(ar->hw->wiphy, regd_copy); wiphy_unlock(ar->hw->wiphy); rtnl_unlock(); @@ -283,7 +296,7 @@ int ath11k_regd_update(struct ath11k *ar) goto err; if (ar->state == ATH11K_STATE_ON) { - ret = ath11k_reg_update_chan_list(ar); + ret = ath11k_reg_update_chan_list(ar, true); if (ret) goto err; } diff --git a/drivers/net/wireless/ath/ath11k/reg.h b/drivers/net/wireless/ath/ath11k/reg.h index 5fb9dc03a74e..2f284f26378d 100644 --- a/drivers/net/wireless/ath/ath11k/reg.h +++ b/drivers/net/wireless/ath/ath11k/reg.h @@ -32,5 +32,5 @@ struct ieee80211_regdomain * ath11k_reg_build_regd(struct ath11k_base *ab, struct cur_regulatory_info *reg_info, bool intersect); int ath11k_regd_update(struct ath11k *ar); -int ath11k_reg_update_chan_list(struct ath11k *ar); +int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait); #endif diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c index 7f97c26bffd9..3af24b18204e 100644 --- a/drivers/net/wireless/ath/ath11k/wmi.c +++ b/drivers/net/wireless/ath/ath11k/wmi.c @@ -2015,7 +2015,10 @@ void ath11k_wmi_start_scan_init(struct ath11k *ar, { /* setup commonly used values */ arg->scan_req_id = 1; - arg->scan_priority = WMI_SCAN_PRIORITY_LOW; + if (ar->state_11d == ATH11K_11D_PREPARING) + arg->scan_priority = WMI_SCAN_PRIORITY_MEDIUM; + else + arg->scan_priority = WMI_SCAN_PRIORITY_LOW; arg->dwell_time_active = 50; arg->dwell_time_active_2g = 0; arg->dwell_time_passive = 150; @@ -6350,8 +6353,10 @@ static void ath11k_wmi_op_ep_tx_credits(struct ath11k_base *ab) static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *skb) { const struct wmi_11d_new_cc_ev *ev; + struct ath11k *ar; + struct ath11k_pdev *pdev; const void **tb; - int ret; + int ret, i; tb = ath11k_wmi_tlv_parse_alloc(ab, skb->data, skb->len, GFP_ATOMIC); if (IS_ERR(tb)) { @@ -6377,6 +6382,13 @@ static int ath11k_reg_11d_new_cc_event(struct ath11k_base *ab, struct sk_buff *s kfree(tb); + for (i = 0; i < ab->num_radios; i++) { + pdev = &ab->pdevs[i]; + ar = pdev->ar; + ar->state_11d = ATH11K_11D_IDLE; + complete(&ar->completed_11d_scan); + } + queue_work(ab->workqueue, &ab->update_11d_work); return 0; From 78a574deef7f4addf3eb6f90ddf209ef21788d76 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Mar 2022 15:50:29 +0200 Subject: [PATCH 00453/11454] drm/i915/dmc: simplify intel_dmc_load_program() conditions intel_dmc_load_program() is only ever called when intel_dmc_has_payload() is true. Move the condition within intel_dmc_load_program() to let it be called directly. Also note that intel_dmc_has_payload() will always return false when HAS_DMC() is false. Remove the redundant check. Signed-off-by: Jani Nikula Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/c8ec46a44071f80b9c97617391b30e0c61ebc3e6.1647870374.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 6 +++--- drivers/gpu/drm/i915/display/intel_dmc.c | 11 +---------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index 3dc859032bac..b3efe345567f 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -5387,7 +5387,7 @@ static void skl_display_core_init(struct drm_i915_private *dev_priv, gen9_dbuf_enable(dev_priv); - if (resume && intel_dmc_has_payload(dev_priv)) + if (resume) intel_dmc_load_program(dev_priv); } @@ -5454,7 +5454,7 @@ static void bxt_display_core_init(struct drm_i915_private *dev_priv, bool resume gen9_dbuf_enable(dev_priv); - if (resume && intel_dmc_has_payload(dev_priv)) + if (resume) intel_dmc_load_program(dev_priv); } @@ -5618,7 +5618,7 @@ static void icl_display_core_init(struct drm_i915_private *dev_priv, if (IS_DG2(dev_priv)) intel_snps_phy_wait_for_calibration(dev_priv); - if (resume && intel_dmc_has_payload(dev_priv)) + if (resume) intel_dmc_load_program(dev_priv); /* Wa_14011508470:tgl,dg1,rkl,adl-s,adl-p */ diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index a719c0f379ba..66fd69259e73 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -276,17 +276,8 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv) struct intel_dmc *dmc = &dev_priv->dmc; u32 id, i; - if (!HAS_DMC(dev_priv)) { - drm_err(&dev_priv->drm, - "No DMC support available for this platform\n"); + if (!intel_dmc_has_payload(dev_priv)) return; - } - - if (!dev_priv->dmc.dmc_info[DMC_FW_MAIN].payload) { - drm_err(&dev_priv->drm, - "Tried to program CSR with empty payload\n"); - return; - } assert_rpm_wakelock_held(&dev_priv->runtime_pm); From 790daf744ea8edf4cf8df0c1d24154af294da3f9 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Mar 2022 15:50:30 +0200 Subject: [PATCH 00454/11454] drm/i915/dmc: move assert_dmc_loaded() to intel_dmc.c Start localizing DMC register and data access to intel_dmc.c. Signed-off-by: Jani Nikula Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/4b96fe56c9c01bc671992dd6fe619638b157878f.1647870374.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_display_power.c | 12 ------------ drivers/gpu/drm/i915/display/intel_dmc.c | 11 +++++++++++ drivers/gpu/drm/i915/display/intel_dmc.h | 2 ++ 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_power.c b/drivers/gpu/drm/i915/display/intel_display_power.c index b3efe345567f..6a5695008f7c 100644 --- a/drivers/gpu/drm/i915/display/intel_display_power.c +++ b/drivers/gpu/drm/i915/display/intel_display_power.c @@ -905,18 +905,6 @@ static void bxt_disable_dc9(struct drm_i915_private *dev_priv) intel_pps_unlock_regs_wa(dev_priv); } -static void assert_dmc_loaded(struct drm_i915_private *dev_priv) -{ - drm_WARN_ONCE(&dev_priv->drm, - !intel_de_read(dev_priv, - DMC_PROGRAM(dev_priv->dmc.dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)), - "DMC program storage start is NULL\n"); - drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, DMC_SSP_BASE), - "DMC SSP Base Not fine\n"); - drm_WARN_ONCE(&dev_priv->drm, !intel_de_read(dev_priv, DMC_HTP_SKL), - "DMC HTP Not fine\n"); -} - /** * intel_display_power_set_target_dc_state - Set target dc state. * @dev_priv: i915 device diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 66fd69259e73..63ae16622c3e 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -305,6 +305,17 @@ void intel_dmc_load_program(struct drm_i915_private *dev_priv) gen9_set_dc_state_debugmask(dev_priv); } +void assert_dmc_loaded(struct drm_i915_private *i915) +{ + drm_WARN_ONCE(&i915->drm, + !intel_de_read(i915, DMC_PROGRAM(i915->dmc.dmc_info[DMC_FW_MAIN].start_mmioaddr, 0)), + "DMC program storage start is NULL\n"); + drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_SSP_BASE), + "DMC SSP Base Not fine\n"); + drm_WARN_ONCE(&i915->drm, !intel_de_read(i915, DMC_HTP_SKL), + "DMC HTP Not fine\n"); +} + static bool fw_info_matches_stepping(const struct intel_fw_info *fw_info, const struct stepping_info *si) { diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index 7c590309a3a9..326f80ad0f31 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -55,4 +55,6 @@ void intel_dmc_ucode_suspend(struct drm_i915_private *i915); void intel_dmc_ucode_resume(struct drm_i915_private *i915); bool intel_dmc_has_payload(struct drm_i915_private *i915); +void assert_dmc_loaded(struct drm_i915_private *i915); + #endif /* __INTEL_DMC_H__ */ From f0147745f78685350e027c430449e242bdc2ec1e Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Mar 2022 15:50:31 +0200 Subject: [PATCH 00455/11454] drm/i915/dmc: move dmc debugfs to intel_dmc.c Continue localizing DMC register and data access to intel_dmc.c. Signed-off-by: Jani Nikula Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/3b7bc0fc117b030d59dd74891af104c165bf9b39.1647870374.git.jani.nikula@intel.com --- .../drm/i915/display/intel_display_debugfs.c | 75 +---------------- drivers/gpu/drm/i915/display/intel_dmc.c | 83 +++++++++++++++++++ drivers/gpu/drm/i915/display/intel_dmc.h | 1 + 3 files changed, 85 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c index c1e74a13a082..452d773fd4e3 100644 --- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c +++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c @@ -436,79 +436,6 @@ static int i915_power_domain_info(struct seq_file *m, void *unused) return 0; } -static int i915_dmc_info(struct seq_file *m, void *unused) -{ - struct drm_i915_private *dev_priv = node_to_i915(m->private); - intel_wakeref_t wakeref; - struct intel_dmc *dmc; - i915_reg_t dc5_reg, dc6_reg = {}; - - if (!HAS_DMC(dev_priv)) - return -ENODEV; - - dmc = &dev_priv->dmc; - - wakeref = intel_runtime_pm_get(&dev_priv->runtime_pm); - - seq_printf(m, "fw loaded: %s\n", - str_yes_no(intel_dmc_has_payload(dev_priv))); - seq_printf(m, "path: %s\n", dmc->fw_path); - seq_printf(m, "Pipe A fw support: %s\n", - str_yes_no(GRAPHICS_VER(dev_priv) >= 12)); - seq_printf(m, "Pipe A fw loaded: %s\n", - str_yes_no(dmc->dmc_info[DMC_FW_PIPEA].payload)); - seq_printf(m, "Pipe B fw support: %s\n", - str_yes_no(IS_ALDERLAKE_P(dev_priv))); - seq_printf(m, "Pipe B fw loaded: %s\n", - str_yes_no(dmc->dmc_info[DMC_FW_PIPEB].payload)); - - if (!intel_dmc_has_payload(dev_priv)) - goto out; - - seq_printf(m, "version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version), - DMC_VERSION_MINOR(dmc->version)); - - if (DISPLAY_VER(dev_priv) >= 12) { - if (IS_DGFX(dev_priv)) { - dc5_reg = DG1_DMC_DEBUG_DC5_COUNT; - } else { - dc5_reg = TGL_DMC_DEBUG_DC5_COUNT; - dc6_reg = TGL_DMC_DEBUG_DC6_COUNT; - } - - /* - * NOTE: DMC_DEBUG3 is a general purpose reg. - * According to B.Specs:49196 DMC f/w reuses DC5/6 counter - * reg for DC3CO debugging and validation, - * but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter. - */ - seq_printf(m, "DC3CO count: %d\n", intel_de_read(dev_priv, IS_DGFX(dev_priv) ? - DG1_DMC_DEBUG3 : TGL_DMC_DEBUG3)); - } else { - dc5_reg = IS_BROXTON(dev_priv) ? BXT_DMC_DC3_DC5_COUNT : - SKL_DMC_DC3_DC5_COUNT; - if (!IS_GEMINILAKE(dev_priv) && !IS_BROXTON(dev_priv)) - dc6_reg = SKL_DMC_DC5_DC6_COUNT; - } - - seq_printf(m, "DC3 -> DC5 count: %d\n", - intel_de_read(dev_priv, dc5_reg)); - if (dc6_reg.reg) - seq_printf(m, "DC5 -> DC6 count: %d\n", - intel_de_read(dev_priv, dc6_reg)); - -out: - seq_printf(m, "program base: 0x%08x\n", - intel_de_read(dev_priv, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0))); - seq_printf(m, "ssp base: 0x%08x\n", - intel_de_read(dev_priv, DMC_SSP_BASE)); - seq_printf(m, "htp: 0x%08x\n", intel_de_read(dev_priv, DMC_HTP_SKL)); - - intel_runtime_pm_put(&dev_priv->runtime_pm, wakeref); - - return 0; -} - static void intel_seq_print_mode(struct seq_file *m, int tabs, const struct drm_display_mode *mode) { @@ -1957,7 +1884,6 @@ static const struct drm_info_list intel_display_debugfs_list[] = { {"i915_gem_framebuffer", i915_gem_framebuffer_info, 0}, {"i915_edp_psr_status", i915_edp_psr_status, 0}, {"i915_power_domain_info", i915_power_domain_info, 0}, - {"i915_dmc_info", i915_dmc_info, 0}, {"i915_display_info", i915_display_info, 0}, {"i915_shared_dplls_info", i915_shared_dplls_info, 0}, {"i915_dp_mst_info", i915_dp_mst_info, 0}, @@ -2001,6 +1927,7 @@ void intel_display_debugfs_register(struct drm_i915_private *i915) ARRAY_SIZE(intel_display_debugfs_list), minor->debugfs_root, minor); + intel_dmc_debugfs_register(i915); intel_fbc_debugfs_register(i915); } diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 63ae16622c3e..2e11725a0828 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -810,3 +810,86 @@ void intel_dmc_ucode_fini(struct drm_i915_private *dev_priv) for (id = 0; id < DMC_FW_MAX; id++) kfree(dev_priv->dmc.dmc_info[id].payload); } + +static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused) +{ + struct drm_i915_private *i915 = m->private; + intel_wakeref_t wakeref; + struct intel_dmc *dmc; + i915_reg_t dc5_reg, dc6_reg = {}; + + if (!HAS_DMC(i915)) + return -ENODEV; + + dmc = &i915->dmc; + + wakeref = intel_runtime_pm_get(&i915->runtime_pm); + + seq_printf(m, "fw loaded: %s\n", + str_yes_no(intel_dmc_has_payload(i915))); + seq_printf(m, "path: %s\n", dmc->fw_path); + seq_printf(m, "Pipe A fw support: %s\n", + str_yes_no(GRAPHICS_VER(i915) >= 12)); + seq_printf(m, "Pipe A fw loaded: %s\n", + str_yes_no(dmc->dmc_info[DMC_FW_PIPEA].payload)); + seq_printf(m, "Pipe B fw support: %s\n", + str_yes_no(IS_ALDERLAKE_P(i915))); + seq_printf(m, "Pipe B fw loaded: %s\n", + str_yes_no(dmc->dmc_info[DMC_FW_PIPEB].payload)); + + if (!intel_dmc_has_payload(i915)) + goto out; + + seq_printf(m, "version: %d.%d\n", DMC_VERSION_MAJOR(dmc->version), + DMC_VERSION_MINOR(dmc->version)); + + if (DISPLAY_VER(i915) >= 12) { + if (IS_DGFX(i915)) { + dc5_reg = DG1_DMC_DEBUG_DC5_COUNT; + } else { + dc5_reg = TGL_DMC_DEBUG_DC5_COUNT; + dc6_reg = TGL_DMC_DEBUG_DC6_COUNT; + } + + /* + * NOTE: DMC_DEBUG3 is a general purpose reg. + * According to B.Specs:49196 DMC f/w reuses DC5/6 counter + * reg for DC3CO debugging and validation, + * but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter. + */ + seq_printf(m, "DC3CO count: %d\n", + intel_de_read(i915, IS_DGFX(i915) ? + DG1_DMC_DEBUG3 : TGL_DMC_DEBUG3)); + } else { + dc5_reg = IS_BROXTON(i915) ? BXT_DMC_DC3_DC5_COUNT : + SKL_DMC_DC3_DC5_COUNT; + if (!IS_GEMINILAKE(i915) && !IS_BROXTON(i915)) + dc6_reg = SKL_DMC_DC5_DC6_COUNT; + } + + seq_printf(m, "DC3 -> DC5 count: %d\n", intel_de_read(i915, dc5_reg)); + if (dc6_reg.reg) + seq_printf(m, "DC5 -> DC6 count: %d\n", + intel_de_read(i915, dc6_reg)); + +out: + seq_printf(m, "program base: 0x%08x\n", + intel_de_read(i915, DMC_PROGRAM(dmc->dmc_info[DMC_FW_MAIN].start_mmioaddr, 0))); + seq_printf(m, "ssp base: 0x%08x\n", + intel_de_read(i915, DMC_SSP_BASE)); + seq_printf(m, "htp: 0x%08x\n", intel_de_read(i915, DMC_HTP_SKL)); + + intel_runtime_pm_put(&i915->runtime_pm, wakeref); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(intel_dmc_debugfs_status); + +void intel_dmc_debugfs_register(struct drm_i915_private *i915) +{ + struct drm_minor *minor = i915->drm.primary; + + debugfs_create_file("i915_dmc_info", 0444, minor->debugfs_root, + i915, &intel_dmc_debugfs_status_fops); +} diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index 326f80ad0f31..b9f608057700 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -54,6 +54,7 @@ void intel_dmc_ucode_fini(struct drm_i915_private *i915); void intel_dmc_ucode_suspend(struct drm_i915_private *i915); void intel_dmc_ucode_resume(struct drm_i915_private *i915); bool intel_dmc_has_payload(struct drm_i915_private *i915); +void intel_dmc_debugfs_register(struct drm_i915_private *i915); void assert_dmc_loaded(struct drm_i915_private *i915); From ca2cae9a48dd09b90b7c33d20f12ec718ef0b571 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Mon, 21 Mar 2022 15:50:32 +0200 Subject: [PATCH 00456/11454] drm/i915/dmc: fix i915_reg_t usage i915_reg_t is supposed to be a somewhat opaque data type, not to be looked inside. Signed-off-by: Jani Nikula Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/b813d0cf1b800386742eb3f919b0ba8d5c182a2a.1647870374.git.jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 2e11725a0828..5de13f978e57 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -816,7 +816,7 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused) struct drm_i915_private *i915 = m->private; intel_wakeref_t wakeref; struct intel_dmc *dmc; - i915_reg_t dc5_reg, dc6_reg = {}; + i915_reg_t dc5_reg, dc6_reg = INVALID_MMIO_REG; if (!HAS_DMC(i915)) return -ENODEV; @@ -868,7 +868,7 @@ static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused) } seq_printf(m, "DC3 -> DC5 count: %d\n", intel_de_read(i915, dc5_reg)); - if (dc6_reg.reg) + if (i915_mmio_reg_valid(dc6_reg)) seq_printf(m, "DC5 -> DC6 count: %d\n", intel_de_read(i915, dc6_reg)); From a7f46d5b91a5eb005e9719cae55eb08774f59201 Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 29 Mar 2022 10:02:04 +0100 Subject: [PATCH 00457/11454] drm/i915: Move intel_vtd_active and run_as_guest to i915_utils Continuation of the effort to declutter i915_drv.h. Also, component specific helpers which consult the iommu/virtualization helpers moved to respective component source/header files as appropriate. v2: * s/dev_priv/i915/ in intel_scanout_needs_vtd_wa. (Lucas) Signed-off-by: Tvrtko Ursulin Cc: Jani Nikula Cc: Lucas De Marchi Acked-by: Jani Nikula Reviewed-by: Lucas De Marchi Signed-off-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20220329090204.2324499-1-tvrtko.ursulin@linux.intel.com [tursulin: fixup conflict in i915_drv.h] --- drivers/gpu/drm/i915/display/intel_bw.c | 3 +- drivers/gpu/drm/i915/display/intel_display.c | 8 ++++- drivers/gpu/drm/i915/display/intel_display.h | 2 ++ drivers/gpu/drm/i915/display/intel_fbc.c | 3 +- drivers/gpu/drm/i915/gem/i915_gem_stolen.c | 3 +- drivers/gpu/drm/i915/gem/i915_gemfs.c | 3 +- drivers/gpu/drm/i915/gt/intel_ggtt.c | 5 +-- drivers/gpu/drm/i915/gt/intel_gtt.c | 12 +++++++ drivers/gpu/drm/i915/gt/intel_gtt.h | 2 ++ drivers/gpu/drm/i915/i915_debugfs.c | 1 + drivers/gpu/drm/i915/i915_driver.c | 3 +- drivers/gpu/drm/i915/i915_driver.h | 4 +++ drivers/gpu/drm/i915/i915_drv.h | 37 -------------------- drivers/gpu/drm/i915/i915_gpu_error.c | 3 +- drivers/gpu/drm/i915/i915_utils.c | 11 ++++++ drivers/gpu/drm/i915/i915_utils.h | 8 +++++ drivers/gpu/drm/i915/intel_device_info.c | 3 +- drivers/gpu/drm/i915/intel_pch.c | 3 +- 18 files changed, 66 insertions(+), 48 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index ac11ff19e47d..c93454f46d30 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -6,6 +6,7 @@ #include #include "i915_reg.h" +#include "i915_utils.h" #include "intel_atomic.h" #include "intel_bw.h" #include "intel_cdclk.h" @@ -649,7 +650,7 @@ static unsigned int intel_bw_data_rate(struct drm_i915_private *dev_priv, for_each_pipe(dev_priv, pipe) data_rate += bw_state->data_rate[pipe]; - if (DISPLAY_VER(dev_priv) >= 13 && intel_vtd_active(dev_priv)) + if (DISPLAY_VER(dev_priv) >= 13 && i915_vtd_active(dev_priv)) data_rate = DIV_ROUND_UP(data_rate * 105, 100); return data_rate; diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 84501d00653a..7a147f224fb6 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -77,6 +77,7 @@ #include "g4x_hdmi.h" #include "hsw_ips.h" #include "i915_drv.h" +#include "i915_utils.h" #include "icl_dsi.h" #include "intel_acpi.h" #include "intel_atomic.h" @@ -1197,7 +1198,7 @@ static bool needs_async_flip_vtd_wa(const struct intel_crtc_state *crtc_state) { struct drm_i915_private *i915 = to_i915(crtc_state->uapi.crtc->dev); - return crtc_state->uapi.async_flip && intel_vtd_active(i915) && + return crtc_state->uapi.async_flip && i915_vtd_active(i915) && (DISPLAY_VER(i915) == 9 || IS_BROADWELL(i915) || IS_HASWELL(i915)); } @@ -10696,3 +10697,8 @@ void intel_display_driver_unregister(struct drm_i915_private *i915) acpi_video_unregister(); intel_opregion_unregister(i915); } + +bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915) +{ + return DISPLAY_VER(i915) >= 6 && i915_vtd_active(i915); +} diff --git a/drivers/gpu/drm/i915/display/intel_display.h b/drivers/gpu/drm/i915/display/intel_display.h index 8513703086b7..867fa248f042 100644 --- a/drivers/gpu/drm/i915/display/intel_display.h +++ b/drivers/gpu/drm/i915/display/intel_display.h @@ -694,4 +694,6 @@ void assert_transcoder(struct drm_i915_private *dev_priv, #define I915_STATE_WARN_ON(x) \ I915_STATE_WARN((x), "%s", "WARN_ON(" __stringify(x) ")") +bool intel_scanout_needs_vtd_wa(struct drm_i915_private *i915); + #endif diff --git a/drivers/gpu/drm/i915/display/intel_fbc.c b/drivers/gpu/drm/i915/display/intel_fbc.c index 142280b6ce6d..b653f3ba7c66 100644 --- a/drivers/gpu/drm/i915/display/intel_fbc.c +++ b/drivers/gpu/drm/i915/display/intel_fbc.c @@ -43,6 +43,7 @@ #include #include "i915_drv.h" +#include "i915_utils.h" #include "i915_vgpu.h" #include "intel_cdclk.h" #include "intel_de.h" @@ -1643,7 +1644,7 @@ static int intel_sanitize_fbc_option(struct drm_i915_private *i915) static bool need_fbc_vtd_wa(struct drm_i915_private *i915) { /* WaFbcTurnOffFbcWhenHyperVisorIsUsed:skl,bxt */ - if (intel_vtd_active(i915) && + if (i915_vtd_active(i915) && (IS_SKYLAKE(i915) || IS_BROXTON(i915))) { drm_info(&i915->drm, "Disabling framebuffer compression (FBC) to prevent screen flicker with VT-d enabled\n"); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c index b9c3196b91ca..f1011a80d4c3 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_stolen.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_stolen.c @@ -15,6 +15,7 @@ #include "i915_drv.h" #include "i915_gem_stolen.h" #include "i915_reg.h" +#include "i915_utils.h" #include "i915_vgpu.h" #include "intel_mchbar_regs.h" @@ -401,7 +402,7 @@ static int i915_gem_init_stolen(struct intel_memory_region *mem) return 0; } - if (intel_vtd_active(i915) && GRAPHICS_VER(i915) < 8) { + if (i915_vtd_active(i915) && GRAPHICS_VER(i915) < 8) { drm_notice(&i915->drm, "%s, disabling use of stolen memory\n", "DMAR active"); diff --git a/drivers/gpu/drm/i915/gem/i915_gemfs.c b/drivers/gpu/drm/i915/gem/i915_gemfs.c index 7271fbf813fa..ee87874e59dc 100644 --- a/drivers/gpu/drm/i915/gem/i915_gemfs.c +++ b/drivers/gpu/drm/i915/gem/i915_gemfs.c @@ -9,6 +9,7 @@ #include "i915_drv.h" #include "i915_gemfs.h" +#include "i915_utils.h" int i915_gemfs_init(struct drm_i915_private *i915) { @@ -32,7 +33,7 @@ int i915_gemfs_init(struct drm_i915_private *i915) */ opts = NULL; - if (intel_vtd_active(i915)) { + if (i915_vtd_active(i915)) { if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) { opts = huge_opt; drm_info(&i915->drm, diff --git a/drivers/gpu/drm/i915/gt/intel_ggtt.c b/drivers/gpu/drm/i915/gt/intel_ggtt.c index 8850d4e0f9cc..e164f30a900d 100644 --- a/drivers/gpu/drm/i915/gt/intel_ggtt.c +++ b/drivers/gpu/drm/i915/gt/intel_ggtt.c @@ -18,6 +18,7 @@ #include "intel_gt_regs.h" #include "i915_drv.h" #include "i915_scatterlist.h" +#include "i915_utils.h" #include "i915_vgpu.h" #include "intel_gtt.h" @@ -104,7 +105,7 @@ static bool needs_idle_maps(struct drm_i915_private *i915) * Query intel_iommu to see if we need the workaround. Presumably that * was loaded first. */ - if (!intel_vtd_active(i915)) + if (!i915_vtd_active(i915)) return false; if (GRAPHICS_VER(i915) == 5 && IS_MOBILE(i915)) @@ -1256,7 +1257,7 @@ int i915_ggtt_probe_hw(struct drm_i915_private *i915) if (ret) return ret; - if (intel_vtd_active(i915)) + if (i915_vtd_active(i915)) drm_info(&i915->drm, "VT-d active for gfx access\n"); return 0; diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 49a8fb63e6e5..2f9b6694ebdd 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -13,10 +13,22 @@ #include "gem/i915_gem_internal.h" #include "gem/i915_gem_lmem.h" #include "i915_trace.h" +#include "i915_utils.h" #include "intel_gt.h" #include "intel_gt_regs.h" #include "intel_gtt.h" + +static bool intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *i915) +{ + return IS_BROXTON(i915) && i915_vtd_active(i915); +} + +bool intel_vm_no_concurrent_access_wa(struct drm_i915_private *i915) +{ + return IS_CHERRYVIEW(i915) || intel_ggtt_update_needs_vtd_wa(i915); +} + struct drm_i915_gem_object *alloc_pt_lmem(struct i915_address_space *vm, int sz) { struct drm_i915_gem_object *obj; diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.h b/drivers/gpu/drm/i915/gt/intel_gtt.h index 8073438b67c8..b12ecee49de0 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.h +++ b/drivers/gpu/drm/i915/gt/intel_gtt.h @@ -369,6 +369,8 @@ struct i915_ppgtt { #define i915_is_dpt(vm) ((vm)->is_dpt) #define i915_is_ggtt_or_dpt(vm) (i915_is_ggtt(vm) || i915_is_dpt(vm)) +bool intel_vm_no_concurrent_access_wa(struct drm_i915_private *i915); + int __must_check i915_vm_lock_objects(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww); diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 747fe9f41e1f..02239395ce81 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -48,6 +48,7 @@ #include "i915_debugfs.h" #include "i915_debugfs_params.h" +#include "i915_driver.h" #include "i915_irq.h" #include "i915_scheduler.h" #include "intel_mchbar_regs.h" diff --git a/drivers/gpu/drm/i915/i915_driver.c b/drivers/gpu/drm/i915/i915_driver.c index 13e6530a3227..3b8850bb3152 100644 --- a/drivers/gpu/drm/i915/i915_driver.c +++ b/drivers/gpu/drm/i915/i915_driver.c @@ -88,6 +88,7 @@ #include "i915_suspend.h" #include "i915_switcheroo.h" #include "i915_sysfs.h" +#include "i915_utils.h" #include "i915_vgpu.h" #include "intel_dram.h" #include "intel_gvt.h" @@ -754,7 +755,7 @@ void i915_print_iommu_status(struct drm_i915_private *i915, struct drm_printer *p) { drm_printf(p, "iommu: %s\n", - str_enabled_disabled(intel_vtd_active(i915))); + str_enabled_disabled(i915_vtd_active(i915))); } static void i915_welcome_messages(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/i915_driver.h b/drivers/gpu/drm/i915/i915_driver.h index 9d11de65daaf..44ec543d92cb 100644 --- a/drivers/gpu/drm/i915/i915_driver.h +++ b/drivers/gpu/drm/i915/i915_driver.h @@ -11,6 +11,7 @@ struct pci_dev; struct pci_device_id; struct drm_i915_private; +struct drm_printer; #define DRIVER_NAME "i915" #define DRIVER_DESC "Intel Graphics" @@ -26,4 +27,7 @@ void i915_driver_shutdown(struct drm_i915_private *i915); int i915_driver_resume_switcheroo(struct drm_i915_private *i915); int i915_driver_suspend_switcheroo(struct drm_i915_private *i915, pm_message_t state); +void +i915_print_iommu_status(struct drm_i915_private *i915, struct drm_printer *p); + #endif /* __I915_DRIVER_H__ */ diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3c85dc8c1f04..600afdadd755 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -32,9 +32,6 @@ #include -#include - -#include #include #include @@ -1364,43 +1361,9 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_GUC_DEPRIVILEGE(dev_priv) \ (INTEL_INFO(dev_priv)->has_guc_deprivilege) -static inline bool run_as_guest(void) -{ - return !hypervisor_is_type(X86_HYPER_NATIVE); -} - #define HAS_D12_PLANE_MINIMIZATION(dev_priv) (IS_ROCKETLAKE(dev_priv) || \ IS_ALDERLAKE_S(dev_priv)) -static inline bool intel_vtd_active(struct drm_i915_private *i915) -{ - if (device_iommu_mapped(i915->drm.dev)) - return true; - - /* Running as a guest, we assume the host is enforcing VT'd */ - return run_as_guest(); -} - -void -i915_print_iommu_status(struct drm_i915_private *i915, struct drm_printer *p); - -static inline bool intel_scanout_needs_vtd_wa(struct drm_i915_private *dev_priv) -{ - return DISPLAY_VER(dev_priv) >= 6 && intel_vtd_active(dev_priv); -} - -static inline bool -intel_ggtt_update_needs_vtd_wa(struct drm_i915_private *i915) -{ - return IS_BROXTON(i915) && intel_vtd_active(i915); -} - -static inline bool -intel_vm_no_concurrent_access_wa(struct drm_i915_private *i915) -{ - return IS_CHERRYVIEW(i915) || intel_ggtt_update_needs_vtd_wa(i915); -} - /* i915_gem.c */ void i915_gem_init_early(struct drm_i915_private *dev_priv); void i915_gem_cleanup_early(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 5e09a4e4b01a..04289cc22741 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -54,6 +54,7 @@ #include "i915_gpu_error.h" #include "i915_memcpy.h" #include "i915_scatterlist.h" +#include "i915_utils.h" #define ALLOW_FAIL (__GFP_KSWAPD_RECLAIM | __GFP_RETRY_MAYFAIL | __GFP_NOWARN) #define ATOMIC_MAYFAIL (GFP_ATOMIC | __GFP_NOWARN) @@ -1814,7 +1815,7 @@ static void capture_gen(struct i915_gpu_coredump *error) error->wakelock = atomic_read(&i915->runtime_pm.wakeref_count); error->suspended = i915->runtime_pm.suspended; - error->iommu = intel_vtd_active(i915); + error->iommu = i915_vtd_active(i915); error->reset_count = i915_reset_count(&i915->gpu_error); error->suspend_count = i915->suspend_count; diff --git a/drivers/gpu/drm/i915/i915_utils.c b/drivers/gpu/drm/i915/i915_utils.c index f9e780dee9de..29fd02bf5ea8 100644 --- a/drivers/gpu/drm/i915/i915_utils.c +++ b/drivers/gpu/drm/i915/i915_utils.c @@ -3,6 +3,8 @@ * Copyright © 2019 Intel Corporation */ +#include + #include #include "i915_drv.h" @@ -114,3 +116,12 @@ void set_timer_ms(struct timer_list *t, unsigned long timeout) /* Keep t->expires = 0 reserved to indicate a canceled timer. */ mod_timer(t, jiffies + timeout ?: 1); } + +bool i915_vtd_active(struct drm_i915_private *i915) +{ + if (device_iommu_mapped(i915->drm.dev)) + return true; + + /* Running as a guest, we assume the host is enforcing VT'd */ + return i915_run_as_guest(); +} diff --git a/drivers/gpu/drm/i915/i915_utils.h b/drivers/gpu/drm/i915/i915_utils.h index 3ff9611ff81c..b2d89c43f24d 100644 --- a/drivers/gpu/drm/i915/i915_utils.h +++ b/drivers/gpu/drm/i915/i915_utils.h @@ -32,6 +32,7 @@ #include #include #include +#include struct drm_i915_private; struct timer_list; @@ -425,4 +426,11 @@ static inline bool timer_expired(const struct timer_list *t) return timer_active(t) && !timer_pending(t); } +static inline bool i915_run_as_guest(void) +{ + return !hypervisor_is_type(X86_HYPER_NATIVE); +} + +bool i915_vtd_active(struct drm_i915_private *i915); + #endif /* !__I915_UTILS_H */ diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 88f29ac11ddd..98861642e275 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -31,6 +31,7 @@ #include "display/intel_de.h" #include "intel_device_info.h" #include "i915_drv.h" +#include "i915_utils.h" #define PLATFORM_NAME(x) [INTEL_##x] = #x static const char * const platform_names[] = { @@ -380,7 +381,7 @@ void intel_device_info_runtime_init(struct drm_i915_private *dev_priv) info->display.has_dsc = 0; } - if (GRAPHICS_VER(dev_priv) == 6 && intel_vtd_active(dev_priv)) { + if (GRAPHICS_VER(dev_priv) == 6 && i915_vtd_active(dev_priv)) { drm_info(&dev_priv->drm, "Disabling ppGTT for VT-d support\n"); info->ppgtt_type = INTEL_PPGTT_NONE; diff --git a/drivers/gpu/drm/i915/intel_pch.c b/drivers/gpu/drm/i915/intel_pch.c index 4cce044efde2..e2b2bbdc0714 100644 --- a/drivers/gpu/drm/i915/intel_pch.c +++ b/drivers/gpu/drm/i915/intel_pch.c @@ -4,6 +4,7 @@ */ #include "i915_drv.h" +#include "i915_utils.h" #include "intel_pch.h" /* Map PCH device id to PCH type, or PCH_NONE if unknown. */ @@ -256,7 +257,7 @@ void intel_detect_pch(struct drm_i915_private *dev_priv) dev_priv->pch_type = PCH_NOP; dev_priv->pch_id = 0; } else if (!pch) { - if (run_as_guest() && HAS_DISPLAY(dev_priv)) { + if (i915_run_as_guest() && HAS_DISPLAY(dev_priv)) { intel_virt_detect_pch(dev_priv, &id, &pch_type); dev_priv->pch_type = pch_type; dev_priv->pch_id = id; From 1f31e35f2e88d7e222f8246d2a34db02aa035c60 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Mar 2022 12:41:08 +0300 Subject: [PATCH 00458/11454] drm/i915/audio: unify audio codec enable/disable debug logging MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The audio codec enable/disable debug logging is spread around in callers and the platform specific hooks. Put them all together in one place on both the enable and disable paths. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220330094109.4164326-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/g4x_dp.c | 7 +--- drivers/gpu/drm/i915/display/g4x_hdmi.c | 3 -- drivers/gpu/drm/i915/display/intel_audio.c | 39 ++++++---------------- 3 files changed, 11 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 8e1338678d91..55fefc950f41 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -658,9 +658,7 @@ static void intel_enable_dp(struct intel_atomic_state *state, { struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct intel_dp *intel_dp = enc_to_intel_dp(encoder); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); u32 dp_reg = intel_de_read(dev_priv, intel_dp->output_reg); - enum pipe pipe = crtc->pipe; intel_wakeref_t wakeref; if (drm_WARN_ON(&dev_priv->drm, dp_reg & DP_PORT_EN)) @@ -694,11 +692,8 @@ static void intel_enable_dp(struct intel_atomic_state *state, intel_dp_start_link_train(intel_dp, pipe_config); intel_dp_stop_link_train(intel_dp, pipe_config); - if (pipe_config->has_audio) { - drm_dbg(&dev_priv->drm, "Enabling DP audio on pipe %c\n", - pipe_name(pipe)); + if (pipe_config->has_audio) intel_audio_codec_enable(encoder, pipe_config, conn_state); - } } static void g4x_enable_dp(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index 06e00b1eaa7c..39ba5dc51f8e 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -148,11 +148,8 @@ static void intel_enable_hdmi_audio(struct intel_encoder *encoder, const struct drm_connector_state *conn_state) { struct drm_i915_private *i915 = to_i915(encoder->base.dev); - struct intel_crtc *crtc = to_intel_crtc(pipe_config->uapi.crtc); drm_WARN_ON(&i915->drm, !pipe_config->has_hdmi_sink); - drm_dbg_kms(&i915->drm, "Enabling HDMI audio on pipe %c\n", - pipe_name(crtc->pipe)); intel_audio_codec_enable(encoder, pipe_config, conn_state); } diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 3bdca0fe2cee..24d20817a5e5 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -337,8 +337,6 @@ static void g4x_audio_codec_disable(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); u32 eldv, tmp; - drm_dbg_kms(&dev_priv->drm, "Disable audio codec\n"); - tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID); if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL) eldv = G4X_ELDV_DEVCL_DEVBLC; @@ -362,9 +360,6 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder, u32 tmp; int len, i; - drm_dbg_kms(&dev_priv->drm, "Enable audio codec, %u bytes ELD\n", - drm_eld_size(eld)); - tmp = intel_de_read(dev_priv, G4X_AUD_VID_DID); if (tmp == INTEL_AUDIO_DEVBLC || tmp == INTEL_AUDIO_DEVCL) eldv = G4X_ELDV_DEVCL_DEVBLC; @@ -383,7 +378,6 @@ static void g4x_audio_codec_enable(struct intel_encoder *encoder, intel_de_write(dev_priv, G4X_AUD_CNTL_ST, tmp); len = min(drm_eld_size(eld) / 4, len); - drm_dbg(&dev_priv->drm, "ELD size %d\n", len); for (i = 0; i < len; i++) intel_de_write(dev_priv, G4X_HDMIW_HDMIEDID, *((const u32 *)eld + i)); @@ -501,9 +495,6 @@ static void hsw_audio_codec_disable(struct intel_encoder *encoder, enum transcoder cpu_transcoder = old_crtc_state->cpu_transcoder; u32 tmp; - drm_dbg_kms(&dev_priv->drm, "Disable audio codec on transcoder %s\n", - transcoder_name(cpu_transcoder)); - mutex_lock(&dev_priv->audio.mutex); /* Disable timestamps */ @@ -647,10 +638,6 @@ static void hsw_audio_codec_enable(struct intel_encoder *encoder, u32 tmp; int len, i; - drm_dbg_kms(&dev_priv->drm, - "Enable audio codec on transcoder %s, %u bytes ELD\n", - transcoder_name(cpu_transcoder), drm_eld_size(eld)); - mutex_lock(&dev_priv->audio.mutex); /* Enable Audio WA for 4k DSC usecases */ @@ -703,11 +690,6 @@ static void ilk_audio_codec_disable(struct intel_encoder *encoder, u32 tmp, eldv; i915_reg_t aud_config, aud_cntrl_st2; - drm_dbg_kms(&dev_priv->drm, - "Disable audio codec on [ENCODER:%d:%s], pipe %c\n", - encoder->base.base.id, encoder->base.name, - pipe_name(pipe)); - if (drm_WARN_ON(&dev_priv->drm, port == PORT_A)) return; @@ -754,11 +736,6 @@ static void ilk_audio_codec_enable(struct intel_encoder *encoder, int len, i; i915_reg_t hdmiw_hdmiedid, aud_config, aud_cntl_st, aud_cntrl_st2; - drm_dbg_kms(&dev_priv->drm, - "Enable audio codec on [ENCODER:%d:%s], pipe %c, %u bytes ELD\n", - encoder->base.base.id, encoder->base.name, - pipe_name(pipe), drm_eld_size(eld)); - if (drm_WARN_ON(&dev_priv->drm, port == PORT_A)) return; @@ -844,18 +821,17 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, enum port port = encoder->port; enum pipe pipe = crtc->pipe; + drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n", + connector->base.id, connector->name, + encoder->base.base.id, encoder->base.name, + pipe, drm_eld_size(connector->eld)); + /* FIXME precompute the ELD in .compute_config() */ if (!connector->eld[0]) drm_dbg_kms(&dev_priv->drm, "Bogus ELD on [CONNECTOR:%d:%s]\n", connector->base.id, connector->name); - drm_dbg(&dev_priv->drm, "ELD on [CONNECTOR:%d:%s], [ENCODER:%d:%s]\n", - connector->base.id, - connector->name, - encoder->base.base.id, - encoder->base.name); - connector->eld[6] = drm_av_sync_delay(connector, adjusted_mode) / 2; if (dev_priv->audio.funcs) @@ -900,9 +876,14 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, struct drm_i915_private *dev_priv = to_i915(encoder->base.dev); struct i915_audio_component *acomp = dev_priv->audio.component; struct intel_crtc *crtc = to_intel_crtc(old_crtc_state->uapi.crtc); + struct drm_connector *connector = old_conn_state->connector; enum port port = encoder->port; enum pipe pipe = crtc->pipe; + drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n", + connector->base.id, connector->name, + encoder->base.base.id, encoder->base.name, pipe); + if (dev_priv->audio.funcs) dev_priv->audio.funcs->audio_codec_disable(encoder, old_crtc_state, From 179db7c1be5c09aa1b1493d45e6f88aebd525b96 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Mar 2022 12:41:09 +0300 Subject: [PATCH 00459/11454] drm/i915/audio: move has_audio checks to within codec enable/disable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduce duplication. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220330094109.4164326-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/g4x_dp.c | 7 ++--- drivers/gpu/drm/i915/display/g4x_hdmi.c | 33 +++++++-------------- drivers/gpu/drm/i915/display/intel_audio.c | 6 ++++ drivers/gpu/drm/i915/display/intel_ddi.c | 14 +++------ drivers/gpu/drm/i915/display/intel_dp_mst.c | 8 ++--- 5 files changed, 26 insertions(+), 42 deletions(-) diff --git a/drivers/gpu/drm/i915/display/g4x_dp.c b/drivers/gpu/drm/i915/display/g4x_dp.c index 55fefc950f41..16bb21ad898b 100644 --- a/drivers/gpu/drm/i915/display/g4x_dp.c +++ b/drivers/gpu/drm/i915/display/g4x_dp.c @@ -495,9 +495,7 @@ static void intel_disable_dp(struct intel_atomic_state *state, intel_dp->link_trained = false; - if (old_crtc_state->has_audio) - intel_audio_codec_disable(encoder, - old_crtc_state, old_conn_state); + intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); /* * Make sure the panel is off before trying to change the mode. @@ -692,8 +690,7 @@ static void intel_enable_dp(struct intel_atomic_state *state, intel_dp_start_link_train(intel_dp, pipe_config); intel_dp_stop_link_train(intel_dp, pipe_config); - if (pipe_config->has_audio) - intel_audio_codec_enable(encoder, pipe_config, conn_state); + intel_audio_codec_enable(encoder, pipe_config, conn_state); } static void g4x_enable_dp(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/g4x_hdmi.c b/drivers/gpu/drm/i915/display/g4x_hdmi.c index 39ba5dc51f8e..8bfef08b7c43 100644 --- a/drivers/gpu/drm/i915/display/g4x_hdmi.c +++ b/drivers/gpu/drm/i915/display/g4x_hdmi.c @@ -143,16 +143,6 @@ static void intel_hdmi_get_config(struct intel_encoder *encoder, &pipe_config->infoframes.hdmi); } -static void intel_enable_hdmi_audio(struct intel_encoder *encoder, - const struct intel_crtc_state *pipe_config, - const struct drm_connector_state *conn_state) -{ - struct drm_i915_private *i915 = to_i915(encoder->base.dev); - - drm_WARN_ON(&i915->drm, !pipe_config->has_hdmi_sink); - intel_audio_codec_enable(encoder, pipe_config, conn_state); -} - static void g4x_enable_hdmi(struct intel_atomic_state *state, struct intel_encoder *encoder, const struct intel_crtc_state *pipe_config, @@ -172,8 +162,9 @@ static void g4x_enable_hdmi(struct intel_atomic_state *state, intel_de_write(dev_priv, intel_hdmi->hdmi_reg, temp); intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg); - if (pipe_config->has_audio) - intel_enable_hdmi_audio(encoder, pipe_config, conn_state); + drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio && + !pipe_config->has_hdmi_sink); + intel_audio_codec_enable(encoder, pipe_config, conn_state); } static void ibx_enable_hdmi(struct intel_atomic_state *state, @@ -224,8 +215,9 @@ static void ibx_enable_hdmi(struct intel_atomic_state *state, intel_de_posting_read(dev_priv, intel_hdmi->hdmi_reg); } - if (pipe_config->has_audio) - intel_enable_hdmi_audio(encoder, pipe_config, conn_state); + drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio && + !pipe_config->has_hdmi_sink); + intel_audio_codec_enable(encoder, pipe_config, conn_state); } static void cpt_enable_hdmi(struct intel_atomic_state *state, @@ -278,8 +270,9 @@ static void cpt_enable_hdmi(struct intel_atomic_state *state, intel_de_read(dev_priv, TRANS_CHICKEN1(pipe)) & ~TRANS_CHICKEN1_HDMIUNIT_GC_DISABLE); } - if (pipe_config->has_audio) - intel_enable_hdmi_audio(encoder, pipe_config, conn_state); + drm_WARN_ON(&dev_priv->drm, pipe_config->has_audio && + !pipe_config->has_hdmi_sink); + intel_audio_codec_enable(encoder, pipe_config, conn_state); } static void vlv_enable_hdmi(struct intel_atomic_state *state, @@ -353,9 +346,7 @@ static void g4x_disable_hdmi(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - if (old_crtc_state->has_audio) - intel_audio_codec_disable(encoder, - old_crtc_state, old_conn_state); + intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); intel_disable_hdmi(state, encoder, old_crtc_state, old_conn_state); } @@ -365,9 +356,7 @@ static void pch_disable_hdmi(struct intel_atomic_state *state, const struct intel_crtc_state *old_crtc_state, const struct drm_connector_state *old_conn_state) { - if (old_crtc_state->has_audio) - intel_audio_codec_disable(encoder, - old_crtc_state, old_conn_state); + intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); } static void pch_post_disable_hdmi(struct intel_atomic_state *state, diff --git a/drivers/gpu/drm/i915/display/intel_audio.c b/drivers/gpu/drm/i915/display/intel_audio.c index 24d20817a5e5..1c87bf66b092 100644 --- a/drivers/gpu/drm/i915/display/intel_audio.c +++ b/drivers/gpu/drm/i915/display/intel_audio.c @@ -821,6 +821,9 @@ void intel_audio_codec_enable(struct intel_encoder *encoder, enum port port = encoder->port; enum pipe pipe = crtc->pipe; + if (!crtc_state->has_audio) + return; + drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Enable audio codec on pipe %c, %u bytes ELD\n", connector->base.id, connector->name, encoder->base.base.id, encoder->base.name, @@ -880,6 +883,9 @@ void intel_audio_codec_disable(struct intel_encoder *encoder, enum port port = encoder->port; enum pipe pipe = crtc->pipe; + if (!old_crtc_state->has_audio) + return; + drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s][ENCODER:%d:%s] Disable audio codec on pipe %c\n", connector->base.id, connector->name, encoder->base.base.id, encoder->base.name, pipe); diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index dc208df829f1..cec578efc4bd 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -2819,8 +2819,7 @@ static void intel_enable_ddi_dp(struct intel_atomic_state *state, if (!dig_port->lspcon.active || dig_port->dp.has_hdmi_sink) intel_dp_set_infoframes(encoder, true, crtc_state, conn_state); - if (crtc_state->has_audio) - intel_audio_codec_enable(encoder, crtc_state, conn_state); + intel_audio_codec_enable(encoder, crtc_state, conn_state); trans_port_sync_stop_link_train(state, encoder, crtc_state); } @@ -2914,8 +2913,7 @@ static void intel_enable_ddi_hdmi(struct intel_atomic_state *state, intel_de_write(dev_priv, DDI_BUF_CTL(port), dig_port->saved_port_bits | DDI_BUF_CTL_ENABLE); - if (crtc_state->has_audio) - intel_audio_codec_enable(encoder, crtc_state, conn_state); + intel_audio_codec_enable(encoder, crtc_state, conn_state); } static void intel_enable_ddi(struct intel_atomic_state *state, @@ -2956,9 +2954,7 @@ static void intel_disable_ddi_dp(struct intel_atomic_state *state, intel_dp->link_trained = false; - if (old_crtc_state->has_audio) - intel_audio_codec_disable(encoder, - old_crtc_state, old_conn_state); + intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); intel_psr_disable(intel_dp, old_crtc_state); intel_edp_backlight_off(old_conn_state); @@ -2978,9 +2974,7 @@ static void intel_disable_ddi_hdmi(struct intel_atomic_state *state, struct drm_i915_private *i915 = to_i915(encoder->base.dev); struct drm_connector *connector = old_conn_state->connector; - if (old_crtc_state->has_audio) - intel_audio_codec_disable(encoder, - old_crtc_state, old_conn_state); + intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); if (!intel_hdmi_handle_sink_scrambling(encoder, connector, false, false)) diff --git a/drivers/gpu/drm/i915/display/intel_dp_mst.c b/drivers/gpu/drm/i915/display/intel_dp_mst.c index e30e698aa684..061b277e5ce7 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/display/intel_dp_mst.c @@ -398,9 +398,8 @@ static void intel_mst_disable_dp(struct intel_atomic_state *state, if (ret) { drm_dbg_kms(&i915->drm, "failed to update payload %d\n", ret); } - if (old_crtc_state->has_audio) - intel_audio_codec_disable(encoder, - old_crtc_state, old_conn_state); + + intel_audio_codec_disable(encoder, old_crtc_state, old_conn_state); } static void intel_mst_post_disable_dp(struct intel_atomic_state *state, @@ -599,8 +598,7 @@ static void intel_mst_enable_dp(struct intel_atomic_state *state, intel_crtc_vblank_on(pipe_config); - if (pipe_config->has_audio) - intel_audio_codec_enable(encoder, pipe_config, conn_state); + intel_audio_codec_enable(encoder, pipe_config, conn_state); /* Enable hdcp if it's desired */ if (conn_state->content_protection == From 1dedcdd0336c356e7ac8eb9b3bc3fe3b4faeac8d Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Mar 2022 12:30:19 +0300 Subject: [PATCH 00460/11454] drm/i915/dp: make DSC usage logging actually useful MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Debug log when DSC is going to be used, and why, instead of unconditionally logging the rarely used debug option setting, which might not have any bearing on whether DSC is going to be used or not. Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220330093019.4150386-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dp.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index c7f8fc654857..56c36c9ef173 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1483,6 +1483,7 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, &pipe_config->hw.adjusted_mode; struct intel_dp *intel_dp = enc_to_intel_dp(encoder); struct link_config_limits limits; + bool joiner_needs_dsc = false; int ret; limits.min_rate = intel_dp_common_rate(intel_dp, 0); @@ -1518,19 +1519,23 @@ intel_dp_compute_link_config(struct intel_encoder *encoder, adjusted_mode->crtc_clock)) pipe_config->bigjoiner_pipes = GENMASK(crtc->pipe + 1, crtc->pipe); + /* + * Pipe joiner needs compression up to display 12 due to bandwidth + * limitation. DG2 onwards pipe joiner can be enabled without + * compression. + */ + joiner_needs_dsc = DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes; + /* * Optimize for slow and wide for everything, because there are some * eDP 1.3 and 1.4 panels don't work well with fast and narrow. */ ret = intel_dp_compute_link_config_wide(intel_dp, pipe_config, &limits); - /* - * Pipe joiner needs compression upto display12 due to BW limitation. DG2 - * onwards pipe joiner can be enabled without compression. - */ - drm_dbg_kms(&i915->drm, "Force DSC en = %d\n", intel_dp->force_dsc_en); - if (ret || intel_dp->force_dsc_en || - (DISPLAY_VER(i915) < 13 && pipe_config->bigjoiner_pipes)) { + if (ret || joiner_needs_dsc || intel_dp->force_dsc_en) { + drm_dbg_kms(&i915->drm, "Try DSC (fallback=%s, joiner=%s, force=%s)\n", + str_yes_no(ret), str_yes_no(joiner_needs_dsc), + str_yes_no(intel_dp->force_dsc_en)); ret = intel_dp_dsc_compute_config(intel_dp, pipe_config, conn_state, &limits); if (ret < 0) From 3f654e14825effb1d68ea481f96dc027e404365a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Fri, 25 Mar 2022 07:22:49 -0700 Subject: [PATCH 00461/11454] drm/i915/dg2: Add Wa_22014226127 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New DG2 workaround added to specification. BSpec: 54077 BSpec: 66622 BSpec: 54833 Cc: Matt Roper Signed-off-by: José Roberto de Souza Reviewed-by: Matt Roper Link: https://patchwork.freedesktop.org/patch/msgid/20220325142249.81443-1-jose.souza@intel.com --- drivers/gpu/drm/i915/gt/intel_gt_regs.h | 1 + drivers/gpu/drm/i915/gt/intel_workarounds.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/gt/intel_gt_regs.h b/drivers/gpu/drm/i915/gt/intel_gt_regs.h index 62e0f075b1de..17432b075d97 100644 --- a/drivers/gpu/drm/i915/gt/intel_gt_regs.h +++ b/drivers/gpu/drm/i915/gt/intel_gt_regs.h @@ -1088,6 +1088,7 @@ #define EU_PERF_CNTL3 _MMIO(0xe758) #define LSC_CHICKEN_BIT_0 _MMIO(0xe7c8) +#define DISABLE_D8_D16_COASLESCE REG_BIT(30) #define FORCE_1_SUB_MESSAGE_PER_FRAGMENT REG_BIT(15) #define LSC_CHICKEN_BIT_0_UDW _MMIO(0xe7c8 + 4) #define DIS_CHAIN_2XSIMD8 REG_BIT(55 - 32) diff --git a/drivers/gpu/drm/i915/gt/intel_workarounds.c b/drivers/gpu/drm/i915/gt/intel_workarounds.c index dc0ffff6f655..29c8cd0a81b6 100644 --- a/drivers/gpu/drm/i915/gt/intel_workarounds.c +++ b/drivers/gpu/drm/i915/gt/intel_workarounds.c @@ -2624,6 +2624,11 @@ general_render_compute_wa_init(struct intel_engine_cs *engine, struct i915_wa_li wa_write_or(wal, GEN12_GAMCNTRL_CTRL, INVALIDATION_BROADCAST_MODE_DIS | GLOBAL_INVALIDATION_MODE); } + + if (IS_DG2(i915)) { + /* Wa_22014226127:dg2 */ + wa_write_or(wal, LSC_CHICKEN_BIT_0, DISABLE_D8_D16_COASLESCE); + } } static void From d7ade5f20e5319a2104e22c47fc414619453ca93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Wed, 30 Mar 2022 08:57:22 -0700 Subject: [PATCH 00462/11454] drm/i915/display/tgl+: Set default values for all registers in PIPE_MBUS_DBOX_CTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit MBUS_DBOX_B2B_TRANSACTIONS_MAX, MBUS_DBOX_B2B_TRANSACTIONS_DELAY and MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN were being programmed with zeros while specification has different default values for this registers in display 12 and newer. While at it also converting all MBUS_DBOX macros to use REG_* macros. BSpec: 50343 BSpec: 20231 Reviewed-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Stanislav Lisovskiy Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220330155724.255226-1-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 13 +++++++--- drivers/gpu/drm/i915/i915_reg.h | 25 ++++++++++++-------- 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 7a147f224fb6..8501929bca3a 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1830,13 +1830,20 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc, bool joined_mbus) { struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); enum pipe pipe = crtc->pipe; - u32 val; + u32 val = 0; + + if (DISPLAY_VER(dev_priv) >= 12) { + val |= MBUS_DBOX_B2B_TRANSACTIONS_MAX(16); + val |= MBUS_DBOX_B2B_TRANSACTIONS_DELAY(1); + val |= MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN; + } /* Wa_22010947358:adl-p */ if (IS_ALDERLAKE_P(dev_priv)) - val = joined_mbus ? MBUS_DBOX_A_CREDIT(6) : MBUS_DBOX_A_CREDIT(4); + val |= joined_mbus ? MBUS_DBOX_A_CREDIT(6) : + MBUS_DBOX_A_CREDIT(4); else - val = MBUS_DBOX_A_CREDIT(2); + val |= MBUS_DBOX_A_CREDIT(2); if (DISPLAY_VER(dev_priv) >= 12) { val |= MBUS_DBOX_BW_CREDIT(2); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 77c6f259eda1..0cf21db6143b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1099,16 +1099,21 @@ #define MBUS_ABOX_BT_CREDIT_POOL1_MASK (0x1F << 0) #define MBUS_ABOX_BT_CREDIT_POOL1(x) ((x) << 0) -#define _PIPEA_MBUS_DBOX_CTL 0x7003C -#define _PIPEB_MBUS_DBOX_CTL 0x7103C -#define PIPE_MBUS_DBOX_CTL(pipe) _MMIO_PIPE(pipe, _PIPEA_MBUS_DBOX_CTL, \ - _PIPEB_MBUS_DBOX_CTL) -#define MBUS_DBOX_BW_CREDIT_MASK (3 << 14) -#define MBUS_DBOX_BW_CREDIT(x) ((x) << 14) -#define MBUS_DBOX_B_CREDIT_MASK (0x1F << 8) -#define MBUS_DBOX_B_CREDIT(x) ((x) << 8) -#define MBUS_DBOX_A_CREDIT_MASK (0xF << 0) -#define MBUS_DBOX_A_CREDIT(x) ((x) << 0) +#define _PIPEA_MBUS_DBOX_CTL 0x7003C +#define _PIPEB_MBUS_DBOX_CTL 0x7103C +#define PIPE_MBUS_DBOX_CTL(pipe) _MMIO_PIPE(pipe, _PIPEA_MBUS_DBOX_CTL, \ + _PIPEB_MBUS_DBOX_CTL) +#define MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASK REG_GENMASK(24, 20) /* tgl+ */ +#define MBUS_DBOX_B2B_TRANSACTIONS_MAX(x) REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_MAX_MASK, x) +#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK REG_GENMASK(19, 17) /* tgl+ */ +#define MBUS_DBOX_B2B_TRANSACTIONS_DELAY(x) REG_FIELD_PREP(MBUS_DBOX_B2B_TRANSACTIONS_DELAY_MASK, x) +#define MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN REG_BIT(16) /* tgl+ */ +#define MBUS_DBOX_BW_CREDIT_MASK REG_GENMASK(15, 14) +#define MBUS_DBOX_BW_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_BW_CREDIT_MASK, x) +#define MBUS_DBOX_B_CREDIT_MASK REG_GENMASK(12, 8) +#define MBUS_DBOX_B_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_B_CREDIT_MASK, x) +#define MBUS_DBOX_A_CREDIT_MASK REG_GENMASK(3, 0) +#define MBUS_DBOX_A_CREDIT(x) REG_FIELD_PREP(MBUS_DBOX_A_CREDIT_MASK, x) #define MBUS_UBOX_CTL _MMIO(0x4503C) #define MBUS_BBOX_CTL_S1 _MMIO(0x45040) From 291f63e72e56a6433910d80e23da384c62077538 Mon Sep 17 00:00:00 2001 From: Caz Yokoyama Date: Wed, 30 Mar 2022 08:57:23 -0700 Subject: [PATCH 00463/11454] drm/i915/display/adlp: Adjust MBUS DBOX BW and B credits MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Alderlake-P has different MBUS DBOX BW and B credits than other platforms, so here setting it properly. BSpec: 49213 BSpec: 50343 Cc: Matt Roper Cc: Stanislav Lisovskiy Cc: Jani Nikula Cc: Ville Syrjälä Reviewed-by: Ville Syrjälä Signed-off-by: Caz Yokoyama Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220330155724.255226-2-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index 8501929bca3a..e5f12f2040af 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1845,7 +1845,10 @@ static void icl_pipe_mbus_enable(struct intel_crtc *crtc, bool joined_mbus) else val |= MBUS_DBOX_A_CREDIT(2); - if (DISPLAY_VER(dev_priv) >= 12) { + if (IS_ALDERLAKE_P(dev_priv)) { + val |= MBUS_DBOX_BW_CREDIT(2); + val |= MBUS_DBOX_B_CREDIT(8); + } else if (DISPLAY_VER(dev_priv) >= 12) { val |= MBUS_DBOX_BW_CREDIT(2); val |= MBUS_DBOX_B_CREDIT(12); } else { From 47e794d69c0d8a4a1ff91fcb6e3d69bc38fcfef2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Wed, 30 Mar 2022 08:57:24 -0700 Subject: [PATCH 00464/11454] drm/i915/display/adlp: Fix programing of PIPE_MBUS_DBOX_CTL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PIPE_MBUS_DBOX_CTL was only being programmed when a pipe is being enabled but that could potentially cause issues as it could have mismatching values while pipes are being enabled. So here moving the PIPE_MBUS_DBOX_CTL programming of all pipes to be executed before the function that enables all pipes, leaving all pipes with a matching A_CREDIT value. While at it, also moving it to intel_pm.c as we are trying to reduce the gigantic size of intel_display.c and intel_pm.c have other MBUS programing sequences. v2: - do not program PIPE_MBUS_DBOX_CTL if pipe will not be active or when it do not needs modeset - remove the checks to wait a vblank v3: - checking if dbuf state is present in state before using it v4: - removing redundant checks - calling intel_atomic_get_new_dbuf_state instead of intel_atomic_get_dbuf_state BSpec: 49213 BSpec: 50343 Reviewed-by: Ville Syrjälä Cc: Ville Syrjälä Cc: Stanislav Lisovskiy Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220330155724.255226-3-jose.souza@intel.com --- drivers/gpu/drm/i915/display/intel_display.c | 41 +-------------- drivers/gpu/drm/i915/intel_pm.c | 52 ++++++++++++++++++++ drivers/gpu/drm/i915/intel_pm.h | 1 + 3 files changed, 54 insertions(+), 40 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_display.c b/drivers/gpu/drm/i915/display/intel_display.c index e5f12f2040af..eee185ed41c3 100644 --- a/drivers/gpu/drm/i915/display/intel_display.c +++ b/drivers/gpu/drm/i915/display/intel_display.c @@ -1826,39 +1826,6 @@ static void glk_pipe_scaler_clock_gating_wa(struct drm_i915_private *dev_priv, intel_de_write(dev_priv, CLKGATE_DIS_PSL(pipe), val); } -static void icl_pipe_mbus_enable(struct intel_crtc *crtc, bool joined_mbus) -{ - struct drm_i915_private *dev_priv = to_i915(crtc->base.dev); - enum pipe pipe = crtc->pipe; - u32 val = 0; - - if (DISPLAY_VER(dev_priv) >= 12) { - val |= MBUS_DBOX_B2B_TRANSACTIONS_MAX(16); - val |= MBUS_DBOX_B2B_TRANSACTIONS_DELAY(1); - val |= MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN; - } - - /* Wa_22010947358:adl-p */ - if (IS_ALDERLAKE_P(dev_priv)) - val |= joined_mbus ? MBUS_DBOX_A_CREDIT(6) : - MBUS_DBOX_A_CREDIT(4); - else - val |= MBUS_DBOX_A_CREDIT(2); - - if (IS_ALDERLAKE_P(dev_priv)) { - val |= MBUS_DBOX_BW_CREDIT(2); - val |= MBUS_DBOX_B_CREDIT(8); - } else if (DISPLAY_VER(dev_priv) >= 12) { - val |= MBUS_DBOX_BW_CREDIT(2); - val |= MBUS_DBOX_B_CREDIT(12); - } else { - val |= MBUS_DBOX_BW_CREDIT(1); - val |= MBUS_DBOX_B_CREDIT(8); - } - - intel_de_write(dev_priv, PIPE_MBUS_DBOX_CTL(pipe), val); -} - static void hsw_set_linetime_wm(const struct intel_crtc_state *crtc_state) { struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); @@ -1995,13 +1962,6 @@ static void hsw_crtc_enable(struct intel_atomic_state *state, intel_initial_watermarks(state, crtc); - if (DISPLAY_VER(dev_priv) >= 11) { - const struct intel_dbuf_state *dbuf_state = - intel_atomic_get_new_dbuf_state(state); - - icl_pipe_mbus_enable(crtc, dbuf_state->joined_mbus); - } - if (intel_crtc_is_bigjoiner_slave(new_crtc_state)) intel_crtc_vblank_on(new_crtc_state); @@ -8600,6 +8560,7 @@ static void intel_atomic_commit_tail(struct intel_atomic_state *state) intel_encoders_update_prepare(state); intel_dbuf_pre_plane_update(state); + intel_mbus_dbox_update(state); for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { if (new_crtc_state->do_async_flip) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 2c3cd4d775da..641616135955 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -8258,3 +8258,55 @@ void intel_dbuf_post_plane_update(struct intel_atomic_state *state) gen9_dbuf_slices_update(dev_priv, new_dbuf_state->enabled_slices); } + +void intel_mbus_dbox_update(struct intel_atomic_state *state) +{ + struct drm_i915_private *i915 = to_i915(state->base.dev); + const struct intel_dbuf_state *new_dbuf_state, *old_dbuf_state; + const struct intel_crtc_state *new_crtc_state; + const struct intel_crtc *crtc; + u32 val = 0; + int i; + + if (DISPLAY_VER(i915) < 11) + return; + + new_dbuf_state = intel_atomic_get_new_dbuf_state(state); + old_dbuf_state = intel_atomic_get_old_dbuf_state(state); + if (!new_dbuf_state || + (new_dbuf_state->joined_mbus == old_dbuf_state->joined_mbus && + new_dbuf_state->active_pipes == old_dbuf_state->active_pipes)) + return; + + if (DISPLAY_VER(i915) >= 12) { + val |= MBUS_DBOX_B2B_TRANSACTIONS_MAX(16); + val |= MBUS_DBOX_B2B_TRANSACTIONS_DELAY(1); + val |= MBUS_DBOX_REGULATE_B2B_TRANSACTIONS_EN; + } + + /* Wa_22010947358:adl-p */ + if (IS_ALDERLAKE_P(i915)) + val |= new_dbuf_state->joined_mbus ? MBUS_DBOX_A_CREDIT(6) : + MBUS_DBOX_A_CREDIT(4); + else + val |= MBUS_DBOX_A_CREDIT(2); + + if (IS_ALDERLAKE_P(i915)) { + val |= MBUS_DBOX_BW_CREDIT(2); + val |= MBUS_DBOX_B_CREDIT(8); + } else if (DISPLAY_VER(i915) >= 12) { + val |= MBUS_DBOX_BW_CREDIT(2); + val |= MBUS_DBOX_B_CREDIT(12); + } else { + val |= MBUS_DBOX_BW_CREDIT(1); + val |= MBUS_DBOX_B_CREDIT(8); + } + + for_each_new_intel_crtc_in_state(state, crtc, new_crtc_state, i) { + if (!new_crtc_state->hw.active || + !intel_crtc_needs_modeset(new_crtc_state)) + continue; + + intel_de_write(i915, PIPE_MBUS_DBOX_CTL(crtc->pipe), val); + } +} diff --git a/drivers/gpu/drm/i915/intel_pm.h b/drivers/gpu/drm/i915/intel_pm.h index 51705151b842..50604cf7398c 100644 --- a/drivers/gpu/drm/i915/intel_pm.h +++ b/drivers/gpu/drm/i915/intel_pm.h @@ -94,5 +94,6 @@ intel_atomic_get_dbuf_state(struct intel_atomic_state *state); int intel_dbuf_init(struct drm_i915_private *dev_priv); void intel_dbuf_pre_plane_update(struct intel_atomic_state *state); void intel_dbuf_post_plane_update(struct intel_atomic_state *state); +void intel_mbus_dbox_update(struct intel_atomic_state *state); #endif /* __INTEL_PM_H__ */ From d049a24b15d8c1c90461933f0526b582a8cdf9b4 Mon Sep 17 00:00:00 2001 From: Matthias Kaehlcke Date: Wed, 30 Mar 2022 09:04:44 -0700 Subject: [PATCH 00465/11454] drm/panel-edp: Fix AUO B133UAN01 panel id Two digits are swapped in the AUO B133UAN01 panel id (0x8495 instead of 0x8594). This went initially unnoticed because the panel is still detected, though it is set up with a conservative default timing. Fix the digit swap. Fixes: ec57376fba5a ("drm/panel-edp: Add AUO B133UAN01") Signed-off-by: Matthias Kaehlcke Reviewed-by: Douglas Anderson Signed-off-by: Douglas Anderson Link: https://patchwork.freedesktop.org/patch/msgid/20220330090435.1.Id1522250dd07a6b574c1cc7826023fc6acd141b4@changeid --- drivers/gpu/drm/panel/panel-edp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c index db4eea1d7f67..1732b4f56e38 100644 --- a/drivers/gpu/drm/panel/panel-edp.c +++ b/drivers/gpu/drm/panel/panel-edp.c @@ -1847,7 +1847,7 @@ static const struct panel_delay delay_100_500_e200 = { static const struct edp_panel_entry edp_panels[] = { EDP_PANEL_ENTRY('A', 'U', 'O', 0x405c, &auo_b116xak01.delay, "B116XAK01"), EDP_PANEL_ENTRY('A', 'U', 'O', 0x615c, &delay_200_500_e50, "B116XAN06.1"), - EDP_PANEL_ENTRY('A', 'U', 'O', 0x8495, &delay_200_500_e50, "B133UAN01.0"), + EDP_PANEL_ENTRY('A', 'U', 'O', 0x8594, &delay_200_500_e50, "B133UAN01.0"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x0786, &delay_200_500_p2e80, "NV116WHM-T01"), EDP_PANEL_ENTRY('B', 'O', 'E', 0x07d1, &boe_nv133fhm_n61.delay, "NV133FHM-N61"), From 018ad18f6ab062a198627ec1bd5fd9d797c90238 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 28 Mar 2022 14:43:01 +0200 Subject: [PATCH 00466/11454] drm/atomic: Print the state every non-blocking commit The DRM_UT_STATE controls whether we're calling drm_atomic_print_new_state() whenever a new state is committed. However, that call is made in the drm_mode_atomic_ioctl(), whereas we have multiple users of the drm_atomic_commit() function in the kernel (framebuffer emulation, drm_atomic_helper_dirtyfb, etc.). This leads to multiple states being committed but never actually displayed even though we asked to have verbose atomic state debugging. Let's move the call to drm_atomic_print_new_state() to drm_atomic_commit() to make sure we don't miss any. Non-blocking commits were never logged though, and it would create too much churn in the logs to do so, so leave them out for now. Signed-off-by: Maxime Ripard Reviewed-by: Daniel Vetter Link: https://lore.kernel.org/r/20220328124304.2309418-2-maxime@cerno.tech --- drivers/gpu/drm/drm_atomic.c | 4 ++++ drivers/gpu/drm/drm_atomic_uapi.c | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 88cd992df356..637df126c2d9 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -1423,8 +1423,12 @@ EXPORT_SYMBOL(drm_atomic_check_only); int drm_atomic_commit(struct drm_atomic_state *state) { struct drm_mode_config *config = &state->dev->mode_config; + struct drm_printer p = drm_info_printer(state->dev->dev); int ret; + if (drm_debug_enabled(DRM_UT_STATE)) + drm_atomic_print_new_state(state, &p); + ret = drm_atomic_check_only(state); if (ret) return ret; diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index 9781722519c3..45e6d3c62a9a 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -1326,7 +1326,6 @@ int drm_mode_atomic_ioctl(struct drm_device *dev, struct drm_out_fence_state *fence_state; int ret = 0; unsigned int i, j, num_fences; - struct drm_printer p = drm_info_printer(dev->dev); /* disallow for drivers not supporting atomic: */ if (!drm_core_check_feature(dev, DRIVER_ATOMIC)) @@ -1458,9 +1457,6 @@ retry: } else if (arg->flags & DRM_MODE_ATOMIC_NONBLOCK) { ret = drm_atomic_nonblocking_commit(state); } else { - if (drm_debug_enabled(DRM_UT_STATE)) - drm_atomic_print_new_state(state, &p); - ret = drm_atomic_commit(state); } From 97a1f01b3f2f734bd3982aa5639b2b54632f8f7d Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 28 Mar 2022 14:43:02 +0200 Subject: [PATCH 00467/11454] drm/atomic: Add atomic_print_state to private objects A number of drivers (amdgpu, komeda, vc4, etc.) leverage the drm_private_state structure, but we don't have any infrastructure to provide debugging like we do for the other components state. Let's add an atomic_print_state hook to be consistent. Reviewed-by: Daniel Vetter Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220328124304.2309418-3-maxime@cerno.tech --- drivers/gpu/drm/drm_atomic.c | 16 ++++++++++++++++ include/drm/drm_atomic.h | 27 +++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_atomic.c b/drivers/gpu/drm/drm_atomic.c index 637df126c2d9..58c0283fb6b0 100644 --- a/drivers/gpu/drm/drm_atomic.c +++ b/drivers/gpu/drm/drm_atomic.c @@ -789,6 +789,8 @@ drm_atomic_private_obj_init(struct drm_device *dev, obj->state = state; obj->funcs = funcs; list_add_tail(&obj->head, &dev->mode_config.privobj_list); + + state->obj = obj; } EXPORT_SYMBOL(drm_atomic_private_obj_init); @@ -1636,6 +1638,15 @@ commit: } EXPORT_SYMBOL(__drm_atomic_helper_set_config); +static void drm_atomic_private_obj_print_state(struct drm_printer *p, + const struct drm_private_state *state) +{ + struct drm_private_obj *obj = state->obj; + + if (obj->funcs->atomic_print_state) + obj->funcs->atomic_print_state(p, state); +} + /** * drm_atomic_print_new_state - prints drm atomic state * @state: atomic configuration to check @@ -1656,6 +1667,8 @@ void drm_atomic_print_new_state(const struct drm_atomic_state *state, struct drm_crtc_state *crtc_state; struct drm_connector *connector; struct drm_connector_state *connector_state; + struct drm_private_obj *obj; + struct drm_private_state *obj_state; int i; if (!p) { @@ -1673,6 +1686,9 @@ void drm_atomic_print_new_state(const struct drm_atomic_state *state, for_each_new_connector_in_state(state, connector, connector_state, i) drm_atomic_connector_print_state(p, connector_state); + + for_each_new_private_obj_in_state(state, obj, obj_state, i) + drm_atomic_private_obj_print_state(p, obj_state); } EXPORT_SYMBOL(drm_atomic_print_new_state); diff --git a/include/drm/drm_atomic.h b/include/drm/drm_atomic.h index 1701c2128a5c..0777725085df 100644 --- a/include/drm/drm_atomic.h +++ b/include/drm/drm_atomic.h @@ -227,6 +227,18 @@ struct drm_private_state_funcs { */ void (*atomic_destroy_state)(struct drm_private_obj *obj, struct drm_private_state *state); + + /** + * @atomic_print_state: + * + * If driver subclasses &struct drm_private_state, it should implement + * this optional hook for printing additional driver specific state. + * + * Do not call this directly, use drm_atomic_private_obj_print_state() + * instead. + */ + void (*atomic_print_state)(struct drm_printer *p, + const struct drm_private_state *state); }; /** @@ -311,14 +323,21 @@ struct drm_private_obj { /** * struct drm_private_state - base struct for driver private object state - * @state: backpointer to global drm_atomic_state * - * Currently only contains a backpointer to the overall atomic update, but in - * the future also might hold synchronization information similar to e.g. - * &drm_crtc.commit. + * Currently only contains a backpointer to the overall atomic update, + * and the relevant private object but in the future also might hold + * synchronization information similar to e.g. &drm_crtc.commit. */ struct drm_private_state { + /** + * @state: backpointer to global drm_atomic_state + */ struct drm_atomic_state *state; + + /** + * @obj: backpointer to the private object + */ + struct drm_private_obj *obj; }; struct __drm_private_objs_state { From 220f125cd5153f570022b11a89d2f96b0e0979cf Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 28 Mar 2022 14:43:03 +0200 Subject: [PATCH 00468/11454] drm/vc4: Constify private state accessors None of those helpers modify the pointed data, let's make them const. Acked-by: Daniel Vetter Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220328124304.2309418-4-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_kms.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 24de29bc1cda..26b771c919b1 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -32,7 +32,8 @@ struct vc4_ctm_state { int fifo; }; -static struct vc4_ctm_state *to_vc4_ctm_state(struct drm_private_state *priv) +static struct vc4_ctm_state * +to_vc4_ctm_state(const struct drm_private_state *priv) { return container_of(priv, struct vc4_ctm_state, base); } @@ -49,7 +50,7 @@ struct vc4_hvs_state { }; static struct vc4_hvs_state * -to_vc4_hvs_state(struct drm_private_state *priv) +to_vc4_hvs_state(const struct drm_private_state *priv) { return container_of(priv, struct vc4_hvs_state, base); } @@ -61,7 +62,7 @@ struct vc4_load_tracker_state { }; static struct vc4_load_tracker_state * -to_vc4_load_tracker_state(struct drm_private_state *priv) +to_vc4_load_tracker_state(const struct drm_private_state *priv) { return container_of(priv, struct vc4_load_tracker_state, base); } From 66bfe59dd307b0b601ef721d348d850c8bf2396e Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Mon, 28 Mar 2022 14:43:04 +0200 Subject: [PATCH 00469/11454] drm/vc4: Implement atomic_print_state for HVS channel state The HVS state configuration is useful when debugging what's going on in the vc4 hardware pipeline. Add an implementation of .atomic_print_state. Acked-by: Daniel Vetter Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20220328124304.2309418-5-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_kms.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 26b771c919b1..bffd81d4bfcf 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -701,9 +701,26 @@ static void vc4_hvs_channels_destroy_state(struct drm_private_obj *obj, kfree(hvs_state); } +static void vc4_hvs_channels_print_state(struct drm_printer *p, + const struct drm_private_state *state) +{ + struct vc4_hvs_state *hvs_state = to_vc4_hvs_state(state); + unsigned int i; + + drm_printf(p, "HVS State\n"); + drm_printf(p, "\tCore Clock Rate: %lu\n", hvs_state->core_clock_rate); + + for (i = 0; i < HVS_NUM_CHANNELS; i++) { + drm_printf(p, "\tChannel %d\n", i); + drm_printf(p, "\t\tin use=%d\n", hvs_state->fifo_state[i].in_use); + drm_printf(p, "\t\tload=%lu\n", hvs_state->fifo_state[i].fifo_load); + } +} + static const struct drm_private_state_funcs vc4_hvs_state_funcs = { .atomic_duplicate_state = vc4_hvs_channels_duplicate_state, .atomic_destroy_state = vc4_hvs_channels_destroy_state, + .atomic_print_state = vc4_hvs_channels_print_state, }; static void vc4_hvs_channels_obj_fini(struct drm_device *dev, void *unused) From 3aefc722ff52076407203b6af9713de567993adf Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Mar 2022 20:04:26 +0300 Subject: [PATCH 00470/11454] drm/edid: fix invalid EDID extension block filtering MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The invalid EDID block filtering uses the number of valid EDID extensions instead of all EDID extensions for looping the extensions in the copy. This is fine, by coincidence, if all the invalid blocks are at the end of the EDID. However, it's completely broken if there are invalid extensions in the middle; the invalid blocks are included and valid blocks are excluded. Fix it by modifying the base block after, not before, the copy. Fixes: 14544d0937bf ("drm/edid: Only print the bad edid when aborting") Reported-by: Ville Syrjälä Signed-off-by: Jani Nikula Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220330170426.349248-1-jani.nikula@intel.com --- drivers/gpu/drm/drm_edid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 359c52e5318a..18e1b88cd894 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -2031,9 +2031,6 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, connector_bad_edid(connector, edid, edid[0x7e] + 1); - edid[EDID_LENGTH-1] += edid[0x7e] - valid_extensions; - edid[0x7e] = valid_extensions; - new = kmalloc_array(valid_extensions + 1, EDID_LENGTH, GFP_KERNEL); if (!new) @@ -2050,6 +2047,9 @@ struct edid *drm_do_get_edid(struct drm_connector *connector, base += EDID_LENGTH; } + new[EDID_LENGTH - 1] += new[0x7e] - valid_extensions; + new[0x7e] = valid_extensions; + kfree(edid); edid = new; } From bc58192a9b59fa75d5666bed9cc1b45fa49c6e0b Mon Sep 17 00:00:00 2001 From: Vinod Govindapillai Date: Tue, 29 Mar 2022 02:00:00 +0300 Subject: [PATCH 00471/11454] drm/i915: Handle the DG2 max bw properly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update DG2 init bw info similar to other platforms even though DG2 has constant bandwidh. This will avoid branching out DG2 specific max bw calls. V3: Fix dg2_get_bw_info() and avoid handle special cases for DG2 (Ville Syrjälä) cc: Ville Syrjälä cc: Stanislav Lisovskiy Signed-off-by: Vinod Govindapillai Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220328230000.215094-1-vinod.govindapillai@intel.com --- drivers/gpu/drm/i915/display/intel_bw.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_bw.c b/drivers/gpu/drm/i915/display/intel_bw.c index c93454f46d30..37bd7b17f3d0 100644 --- a/drivers/gpu/drm/i915/display/intel_bw.c +++ b/drivers/gpu/drm/i915/display/intel_bw.c @@ -465,20 +465,25 @@ static int tgl_get_bw_info(struct drm_i915_private *dev_priv, const struct intel static void dg2_get_bw_info(struct drm_i915_private *i915) { - struct intel_bw_info *bi = &i915->max_bw[0]; + unsigned int deratedbw = IS_DG2_G11(i915) ? 38000 : 50000; + int num_groups = ARRAY_SIZE(i915->max_bw); + int i; /* * DG2 doesn't have SAGV or QGV points, just a constant max bandwidth - * that doesn't depend on the number of planes enabled. Create a - * single dummy QGV point to reflect that. DG2-G10 platforms have a - * constant 50 GB/s bandwidth, whereas DG2-G11 platforms have 38 GB/s. + * that doesn't depend on the number of planes enabled. So fill all the + * plane group with constant bw information for uniformity with other + * platforms. DG2-G10 platforms have a constant 50 GB/s bandwidth, + * whereas DG2-G11 platforms have 38 GB/s. */ - bi->num_planes = 1; - bi->num_qgv_points = 1; - if (IS_DG2_G11(i915)) - bi->deratedbw[0] = 38000; - else - bi->deratedbw[0] = 50000; + for (i = 0; i < num_groups; i++) { + struct intel_bw_info *bi = &i915->max_bw[i]; + + bi->num_planes = 1; + /* Need only one dummy QGV point per group */ + bi->num_qgv_points = 1; + bi->deratedbw[0] = deratedbw; + } i915->sagv_status = I915_SAGV_NOT_CONTROLLED; } From 5efde05f6af1c5dd1abf63cd26c004bdfb4bbb5c Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Mar 2022 14:34:15 +0300 Subject: [PATCH 00472/11454] drm/i915/dmc: abstract GPU error state dump Only intel_dmc.c should be accessing dmc details directly. Need to add an i915_error_printf() stub for CONFIG_DRM_I915_CAPTURE_ERROR=n. v2: Add the stub (kernel test robot ) Signed-off-by: Jani Nikula Reviewed-by: Lucas De Marchi # v1 Link: https://patchwork.freedesktop.org/patch/msgid/20220330113417.220964-1-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 15 +++++++++++++++ drivers/gpu/drm/i915/display/intel_dmc.h | 3 +++ drivers/gpu/drm/i915/i915_gpu_error.c | 10 +--------- drivers/gpu/drm/i915/i915_gpu_error.h | 6 ++++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index 5de13f978e57..f0eb3de8de60 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -811,6 +811,21 @@ void intel_dmc_ucode_fini(struct drm_i915_private *dev_priv) kfree(dev_priv->dmc.dmc_info[id].payload); } +void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m, + struct drm_i915_private *i915) +{ + struct intel_dmc *dmc = &i915->dmc; + + if (!HAS_DMC(i915)) + return; + + i915_error_printf(m, "DMC loaded: %s\n", + str_yes_no(intel_dmc_has_payload(i915))); + i915_error_printf(m, "DMC fw version: %d.%d\n", + DMC_VERSION_MAJOR(dmc->version), + DMC_VERSION_MINOR(dmc->version)); +} + static int intel_dmc_debugfs_status_show(struct seq_file *m, void *unused) { struct drm_i915_private *i915 = m->private; diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index b9f608057700..dd8880d2cbed 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -10,6 +10,7 @@ #include "intel_wakeref.h" #include +struct drm_i915_error_state_buf; struct drm_i915_private; #define DMC_VERSION(major, minor) ((major) << 16 | (minor)) @@ -55,6 +56,8 @@ void intel_dmc_ucode_suspend(struct drm_i915_private *i915); void intel_dmc_ucode_resume(struct drm_i915_private *i915); bool intel_dmc_has_payload(struct drm_i915_private *i915); void intel_dmc_debugfs_register(struct drm_i915_private *i915); +void intel_dmc_print_error_state(struct drm_i915_error_state_buf *m, + struct drm_i915_private *i915); void assert_dmc_loaded(struct drm_i915_private *i915); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 04289cc22741..d0e7ee7b07df 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -826,15 +826,7 @@ static void __err_print_to_sgl(struct drm_i915_error_state_buf *m, err_printf(m, "IOMMU enabled?: %d\n", error->iommu); - if (HAS_DMC(m->i915)) { - struct intel_dmc *dmc = &m->i915->dmc; - - err_printf(m, "DMC loaded: %s\n", - str_yes_no(intel_dmc_has_payload(m->i915) != 0)); - err_printf(m, "DMC fw version: %d.%d\n", - DMC_VERSION_MAJOR(dmc->version), - DMC_VERSION_MINOR(dmc->version)); - } + intel_dmc_print_error_state(m, m->i915); err_printf(m, "RPM wakelock: %s\n", str_yes_no(error->wakelock)); err_printf(m, "PM suspended: %s\n", str_yes_no(error->suspended)); diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index 903d838e2e63..88ce3a08f555 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -281,6 +281,12 @@ void i915_disable_error_state(struct drm_i915_private *i915, int err); #else +__printf(2, 3) +static inline void +i915_error_printf(struct drm_i915_error_state_buf *e, const char *f, ...) +{ +} + static inline void i915_capture_error_state(struct intel_gt *gt, intel_engine_mask_t engine_mask) { From fe1295e628c911bf33ce7ecd2b2caae67065c639 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Mar 2022 14:34:16 +0300 Subject: [PATCH 00473/11454] drm/i915/dmc: hide DMC version macros The macros are now only needed within intel_dmc.c, so move them there. Signed-off-by: Jani Nikula Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220330113417.220964-2-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 4 ++++ drivers/gpu/drm/i915/display/intel_dmc.h | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index f0eb3de8de60..a204b60a061f 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -37,6 +37,10 @@ * low-power state and comes back to normal. */ +#define DMC_VERSION(major, minor) ((major) << 16 | (minor)) +#define DMC_VERSION_MAJOR(version) ((version) >> 16) +#define DMC_VERSION_MINOR(version) ((version) & 0xffff) + #define DMC_PATH(platform, major, minor) \ "i915/" \ __stringify(platform) "_dmc_ver" \ diff --git a/drivers/gpu/drm/i915/display/intel_dmc.h b/drivers/gpu/drm/i915/display/intel_dmc.h index dd8880d2cbed..41091aee3b47 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.h +++ b/drivers/gpu/drm/i915/display/intel_dmc.h @@ -13,10 +13,6 @@ struct drm_i915_error_state_buf; struct drm_i915_private; -#define DMC_VERSION(major, minor) ((major) << 16 | (minor)) -#define DMC_VERSION_MAJOR(version) ((version) >> 16) -#define DMC_VERSION_MINOR(version) ((version) & 0xffff) - enum { DMC_FW_MAIN = 0, DMC_FW_PIPEA, From 9c67d9e84c7d4a3a2371a54ee2dddc4699002000 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Wed, 30 Mar 2022 14:34:17 +0300 Subject: [PATCH 00474/11454] drm/i915/dmc: split out dmc registers to a separate file Clean up the massive i915_reg.h a bit with this isolated set of registers. v2: Remove stale comment (Lucas) Signed-off-by: Jani Nikula Reviewed-by: Lucas De Marchi Link: https://patchwork.freedesktop.org/patch/msgid/20220330113417.220964-3-jani.nikula@intel.com --- drivers/gpu/drm/i915/display/intel_dmc.c | 1 + drivers/gpu/drm/i915/display/intel_dmc_regs.h | 30 +++++++++++++++++++ drivers/gpu/drm/i915/gvt/handlers.c | 1 + drivers/gpu/drm/i915/i915_reg.h | 21 ------------- 4 files changed, 32 insertions(+), 21 deletions(-) create mode 100644 drivers/gpu/drm/i915/display/intel_dmc_regs.h diff --git a/drivers/gpu/drm/i915/display/intel_dmc.c b/drivers/gpu/drm/i915/display/intel_dmc.c index a204b60a061f..257cf662f9f4 100644 --- a/drivers/gpu/drm/i915/display/intel_dmc.c +++ b/drivers/gpu/drm/i915/display/intel_dmc.c @@ -28,6 +28,7 @@ #include "i915_reg.h" #include "intel_de.h" #include "intel_dmc.h" +#include "intel_dmc_regs.h" /** * DOC: DMC Firmware Support diff --git a/drivers/gpu/drm/i915/display/intel_dmc_regs.h b/drivers/gpu/drm/i915/display/intel_dmc_regs.h new file mode 100644 index 000000000000..d65e698832eb --- /dev/null +++ b/drivers/gpu/drm/i915/display/intel_dmc_regs.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: MIT */ +/* + * Copyright © 2022 Intel Corporation + */ + +#ifndef __INTEL_DMC_REGS_H__ +#define __INTEL_DMC_REGS_H__ + +#include "i915_reg_defs.h" + +#define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4) +#define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0 +#define DMC_HTP_ADDR_SKL 0x00500034 +#define DMC_SSP_BASE _MMIO(0x8F074) +#define DMC_HTP_SKL _MMIO(0x8F004) +#define DMC_LAST_WRITE _MMIO(0x8F034) +#define DMC_LAST_WRITE_VALUE 0xc003b400 +#define DMC_MMIO_START_RANGE 0x80000 +#define DMC_MMIO_END_RANGE 0x8FFFF +#define SKL_DMC_DC3_DC5_COUNT _MMIO(0x80030) +#define SKL_DMC_DC5_DC6_COUNT _MMIO(0x8002C) +#define BXT_DMC_DC3_DC5_COUNT _MMIO(0x80038) +#define TGL_DMC_DEBUG_DC5_COUNT _MMIO(0x101084) +#define TGL_DMC_DEBUG_DC6_COUNT _MMIO(0x101088) +#define DG1_DMC_DEBUG_DC5_COUNT _MMIO(0x134154) + +#define TGL_DMC_DEBUG3 _MMIO(0x101090) +#define DG1_DMC_DEBUG3 _MMIO(0x13415c) + +#endif /* __INTEL_DMC_REGS_H__ */ diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 0ee3ecc83234..57b0f4977760 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -42,6 +42,7 @@ #include "i915_pvinfo.h" #include "intel_mchbar_regs.h" #include "display/intel_display_types.h" +#include "display/intel_dmc_regs.h" #include "display/intel_fbc.h" #include "display/vlv_dsi_pll_regs.h" #include "gt/intel_gt_regs.h" diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0cf21db6143b..0ad04132ca8d 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -5494,27 +5494,6 @@ #define GAMMA_MODE_MODE_SPLIT (3 << 0) /* ivb-bdw */ #define GAMMA_MODE_MODE_12BIT_MULTI_SEGMENTED (3 << 0) /* icl + */ -/* DMC */ -#define DMC_PROGRAM(addr, i) _MMIO((addr) + (i) * 4) -#define DMC_SSP_BASE_ADDR_GEN9 0x00002FC0 -#define DMC_HTP_ADDR_SKL 0x00500034 -#define DMC_SSP_BASE _MMIO(0x8F074) -#define DMC_HTP_SKL _MMIO(0x8F004) -#define DMC_LAST_WRITE _MMIO(0x8F034) -#define DMC_LAST_WRITE_VALUE 0xc003b400 -/* MMIO address range for DMC program (0x80000 - 0x82FFF) */ -#define DMC_MMIO_START_RANGE 0x80000 -#define DMC_MMIO_END_RANGE 0x8FFFF -#define SKL_DMC_DC3_DC5_COUNT _MMIO(0x80030) -#define SKL_DMC_DC5_DC6_COUNT _MMIO(0x8002C) -#define BXT_DMC_DC3_DC5_COUNT _MMIO(0x80038) -#define TGL_DMC_DEBUG_DC5_COUNT _MMIO(0x101084) -#define TGL_DMC_DEBUG_DC6_COUNT _MMIO(0x101088) -#define DG1_DMC_DEBUG_DC5_COUNT _MMIO(0x134154) - -#define TGL_DMC_DEBUG3 _MMIO(0x101090) -#define DG1_DMC_DEBUG3 _MMIO(0x13415c) - /* Display Internal Timeout Register */ #define RM_TIMEOUT _MMIO(0x42060) #define MMIO_TIMEOUT_US(us) ((us) << 0) From aeb9f0a4a3dc001b2ce382820d26fdf805cf0f9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Thu, 31 Mar 2022 11:41:52 -0700 Subject: [PATCH 00475/11454] drm/i915/display: Add HAS_MBUS_JOINING MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will make easy to extend MBUS joining support to future platforms that also supports this feature. Reviewed-by: Ville Syrjälä Signed-off-by: José Roberto de Souza Link: https://patchwork.freedesktop.org/patch/msgid/20220331184152.1086943-1-jose.souza@intel.com --- drivers/gpu/drm/i915/i915_drv.h | 2 ++ drivers/gpu/drm/i915/intel_pm.c | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 600afdadd755..d36ad4ded337 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1364,6 +1364,8 @@ IS_SUBPLATFORM(const struct drm_i915_private *i915, #define HAS_D12_PLANE_MINIMIZATION(dev_priv) (IS_ROCKETLAKE(dev_priv) || \ IS_ALDERLAKE_S(dev_priv)) +#define HAS_MBUS_JOINING(i915) (IS_ALDERLAKE_P(i915)) + /* i915_gem.c */ void i915_gem_init_early(struct drm_i915_private *dev_priv); void i915_gem_cleanup_early(struct drm_i915_private *dev_priv); diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 641616135955..8824f269e5f5 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -6038,7 +6038,7 @@ skl_compute_ddb(struct intel_atomic_state *state) return ret; } - if (IS_ALDERLAKE_P(dev_priv)) + if (HAS_MBUS_JOINING(dev_priv)) new_dbuf_state->joined_mbus = adlp_check_mbus_joined(new_dbuf_state->active_pipes); @@ -6530,7 +6530,7 @@ void skl_wm_get_hw_state(struct drm_i915_private *dev_priv) to_intel_dbuf_state(dev_priv->dbuf.obj.state); struct intel_crtc *crtc; - if (IS_ALDERLAKE_P(dev_priv)) + if (HAS_MBUS_JOINING(dev_priv)) dbuf_state->joined_mbus = intel_de_read(dev_priv, MBUS_CTL) & MBUS_JOIN; for_each_intel_crtc(&dev_priv->drm, crtc) { @@ -8192,7 +8192,7 @@ static void update_mbus_pre_enable(struct intel_atomic_state *state) const struct intel_dbuf_state *dbuf_state = intel_atomic_get_new_dbuf_state(state); - if (!IS_ALDERLAKE_P(dev_priv)) + if (!HAS_MBUS_JOINING(dev_priv)) return; /* From 1c05183a3709fbef6aea66cd50002e718aec2e95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:12 +0300 Subject: [PATCH 00476/11454] drm/i915: Extract intel_edp_has_drrs() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pull all the eDP specific platform/port checks out from intel_drrs_init() into intel_edp_has_drrs(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-2-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 35 ++++++++++++++++++++++- drivers/gpu/drm/i915/display/intel_drrs.c | 24 ---------------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 56c36c9ef173..2c23ec0a880a 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -4976,6 +4976,39 @@ intel_edp_add_properties(struct intel_dp *intel_dp) fixed_mode->vdisplay); } +static bool +intel_edp_has_drrs(struct intel_dp *intel_dp) +{ + struct intel_connector *connector = intel_dp->attached_connector; + struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; + struct drm_i915_private *i915 = to_i915(connector->base.dev); + + if (DISPLAY_VER(i915) < 5) { + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] DRRS not supported on platform\n", + connector->base.base.id, connector->base.name); + return false; + } + + if ((DISPLAY_VER(i915) < 8 && !HAS_GMCH(i915)) && + encoder->port != PORT_A) { + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] DRRS not supported on [ENCODER:%d:%s]\n", + connector->base.base.id, connector->base.name, + encoder->base.base.id, encoder->base.name); + return false; + } + + if (i915->vbt.drrs_type == DRRS_TYPE_NONE) { + drm_dbg_kms(&i915->drm, + "[CONNECTOR:%d:%s] DRRS not supported according to VBT\n", + connector->base.base.id, connector->base.name); + return false; + } + + return true; +} + static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct intel_connector *intel_connector) { @@ -5041,7 +5074,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_connector->edid = edid; fixed_mode = intel_panel_edid_fixed_mode(intel_connector); - if (fixed_mode) + if (fixed_mode && intel_edp_has_drrs(intel_dp)) downclock_mode = intel_drrs_init(intel_connector, fixed_mode); /* MSO requires information from the EDID */ diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index a5c7d58b36e0..1448c3029b8e 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -373,32 +373,8 @@ intel_drrs_init(struct intel_connector *connector, const struct drm_display_mode *fixed_mode) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct intel_encoder *encoder = connector->encoder; struct drm_display_mode *downclock_mode; - if (DISPLAY_VER(dev_priv) < 5) { - drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] DRRS not supported on platform\n", - connector->base.base.id, connector->base.name); - return NULL; - } - - if ((DISPLAY_VER(dev_priv) < 8 && !HAS_GMCH(dev_priv)) && - encoder->port != PORT_A) { - drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] DRRS not supported on [ENCODER:%d:%s]\n", - connector->base.base.id, connector->base.name, - encoder->base.base.id, encoder->base.name); - return NULL; - } - - if (dev_priv->vbt.drrs_type == DRRS_TYPE_NONE) { - drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] DRRS not supported according to VBT\n", - connector->base.base.id, connector->base.name); - return NULL; - } - downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode); if (!downclock_mode) { drm_dbg_kms(&dev_priv->drm, From db10c14a2523071369e87c24af854928d52dad34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:13 +0300 Subject: [PATCH 00477/11454] drm/i915: Put fixed modes directly onto the panel's fixed_modes list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than having the connector init get the fixed mode back from intel_panel and then feed it straight back into intel_panel_init() let's just make the fixed mode lookup put the mode directly onto the panel's fixed_modes list. Avoids the pointless round trip and opens the door for further enhancements to the fixed mode handling. v2: Make the debug message correct by using intel_panel_drrs_type() (Jani) Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-3-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/icl_dsi.c | 8 +-- drivers/gpu/drm/i915/display/intel_dp.c | 22 ++++---- drivers/gpu/drm/i915/display/intel_drrs.c | 20 ++----- drivers/gpu/drm/i915/display/intel_drrs.h | 3 +- drivers/gpu/drm/i915/display/intel_dvo.c | 9 ++- drivers/gpu/drm/i915/display/intel_lvds.c | 35 +++++------- drivers/gpu/drm/i915/display/intel_panel.c | 64 +++++++++------------- drivers/gpu/drm/i915/display/intel_panel.h | 22 +++----- drivers/gpu/drm/i915/display/intel_sdvo.c | 10 ++-- drivers/gpu/drm/i915/display/vlv_dsi.c | 9 +-- 10 files changed, 83 insertions(+), 119 deletions(-) diff --git a/drivers/gpu/drm/i915/display/icl_dsi.c b/drivers/gpu/drm/i915/display/icl_dsi.c index 44f4c65522b9..084cc51d1c41 100644 --- a/drivers/gpu/drm/i915/display/icl_dsi.c +++ b/drivers/gpu/drm/i915/display/icl_dsi.c @@ -1993,7 +1993,6 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) struct intel_encoder *encoder; struct intel_connector *intel_connector; struct drm_connector *connector; - struct drm_display_mode *fixed_mode; enum port port; if (!intel_bios_is_dsi_present(dev_priv, &port)) @@ -2050,15 +2049,16 @@ void icl_dsi_init(struct drm_i915_private *dev_priv) intel_connector_attach_encoder(intel_connector, encoder); mutex_lock(&dev->mode_config.mutex); - fixed_mode = intel_panel_vbt_lfp_fixed_mode(intel_connector); + intel_panel_add_vbt_lfp_fixed_mode(intel_connector); mutex_unlock(&dev->mode_config.mutex); - if (!fixed_mode) { + if (!intel_panel_preferred_fixed_mode(intel_connector)) { drm_err(&dev_priv->drm, "DSI fixed mode info missing\n"); goto err; } - intel_panel_init(intel_connector, fixed_mode, NULL); + intel_panel_init(intel_connector); + intel_backlight_setup(intel_connector, INVALID_PIPE); if (dev_priv->vbt.dsi.config->dual_link) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 2c23ec0a880a..67472555211d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5015,8 +5015,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct drm_i915_private *dev_priv = dp_to_i915(intel_dp); struct drm_device *dev = &dev_priv->drm; struct drm_connector *connector = &intel_connector->base; - struct drm_display_mode *fixed_mode = NULL; - struct drm_display_mode *downclock_mode = NULL; + struct drm_display_mode *fixed_mode; bool has_dpcd; enum pipe pipe = INVALID_PIPE; struct edid *edid; @@ -5073,20 +5072,22 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } intel_connector->edid = edid; - fixed_mode = intel_panel_edid_fixed_mode(intel_connector); - if (fixed_mode && intel_edp_has_drrs(intel_dp)) - downclock_mode = intel_drrs_init(intel_connector, fixed_mode); + intel_panel_add_edid_fixed_mode(intel_connector); + if (intel_panel_preferred_fixed_mode(intel_connector) && + intel_edp_has_drrs(intel_dp)) + intel_drrs_init(intel_connector); /* MSO requires information from the EDID */ intel_edp_mso_init(intel_dp); /* multiply the mode clock and horizontal timings for MSO */ - intel_edp_mso_mode_fixup(intel_connector, fixed_mode); - intel_edp_mso_mode_fixup(intel_connector, downclock_mode); + list_for_each_entry(fixed_mode, &intel_connector->panel.fixed_modes, head) + intel_edp_mso_mode_fixup(intel_connector, fixed_mode); /* fallback to VBT if available for eDP */ - if (!fixed_mode) - fixed_mode = intel_panel_vbt_lfp_fixed_mode(intel_connector); + if (!intel_panel_preferred_fixed_mode(intel_connector)) + intel_panel_add_vbt_lfp_fixed_mode(intel_connector); + mutex_unlock(&dev->mode_config.mutex); if (IS_VALLEYVIEW(dev_priv) || IS_CHERRYVIEW(dev_priv)) { @@ -5108,7 +5109,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, pipe_name(pipe)); } - intel_panel_init(intel_connector, fixed_mode, downclock_mode); + intel_panel_init(intel_connector); + if (!(dev_priv->quirks & QUIRK_NO_PPS_BACKLIGHT_POWER_HOOK)) intel_connector->panel.backlight.power = intel_pps_backlight_power; intel_backlight_setup(intel_connector, pipe); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 1448c3029b8e..d04a9ff9e813 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -358,7 +358,6 @@ void intel_crtc_drrs_init(struct intel_crtc *crtc) /** * intel_drrs_init - Init DRRS for eDP connector * @connector: eDP connector - * @fixed_mode: preferred mode of panel * * This function is called only once at driver load to initialize * DRRS support for the connector. @@ -368,25 +367,14 @@ void intel_crtc_drrs_init(struct intel_crtc *crtc) * DRRS support is determined by the presence of downclock mode (apart * from VBT setting). */ -struct drm_display_mode * -intel_drrs_init(struct intel_connector *connector, - const struct drm_display_mode *fixed_mode) +void intel_drrs_init(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - struct drm_display_mode *downclock_mode; - downclock_mode = intel_panel_edid_downclock_mode(connector, fixed_mode); - if (!downclock_mode) { - drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] DRRS not supported due to lack of downclock mode\n", - connector->base.base.id, connector->base.name); - return NULL; - } + intel_panel_add_edid_downclock_mode(connector); drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] %s DRRS supported\n", + "[CONNECTOR:%d:%s] DRRS type: %s\n", connector->base.base.id, connector->base.name, - intel_drrs_type_str(dev_priv->vbt.drrs_type)); - - return downclock_mode; + intel_drrs_type_str(intel_panel_drrs_type(connector))); } diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index e2f78cc10061..3ea52220cd69 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -27,7 +27,6 @@ void intel_drrs_compute_config(struct intel_connector *connector, struct intel_crtc_state *pipe_config, int output_bpp, bool constant_n); void intel_crtc_drrs_init(struct intel_crtc *crtc); -struct drm_display_mode *intel_drrs_init(struct intel_connector *connector, - const struct drm_display_mode *fixed_mode); +void intel_drrs_init(struct intel_connector *connector); #endif /* __INTEL_DRRS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_dvo.c b/drivers/gpu/drm/i915/display/intel_dvo.c index 8c98897d8313..5572e43026e4 100644 --- a/drivers/gpu/drm/i915/display/intel_dvo.c +++ b/drivers/gpu/drm/i915/display/intel_dvo.c @@ -520,8 +520,6 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) intel_connector_attach_encoder(intel_connector, intel_encoder); if (dvo->type == INTEL_DVO_CHIP_LVDS) { - struct drm_display_mode *fixed_mode; - /* * For our LVDS chipsets, we should hopefully be able * to dig the fixed panel mode out of the BIOS data. @@ -530,10 +528,11 @@ void intel_dvo_init(struct drm_i915_private *dev_priv) * headers, likely), so for now, just get the current * mode being output through DVO. */ - fixed_mode = intel_panel_encoder_fixed_mode(intel_connector, - intel_encoder); + intel_panel_add_encoder_fixed_mode(intel_connector, + intel_encoder); + + intel_panel_init(intel_connector); - intel_panel_init(intel_connector, fixed_mode, NULL); intel_dvo->panel_wants_dither = true; } diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 5b2367bc3cd2..193daffadc90 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -829,8 +829,6 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) struct intel_connector *intel_connector; struct drm_connector *connector; struct drm_encoder *encoder; - struct drm_display_mode *fixed_mode = NULL; - struct drm_display_mode *downclock_mode = NULL; struct edid *edid; i915_reg_t lvds_reg; u32 lvds; @@ -969,30 +967,29 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) } intel_connector->edid = edid; - fixed_mode = intel_panel_edid_fixed_mode(intel_connector); - if (fixed_mode) - goto out; + /* Try EDID first */ + intel_panel_add_edid_fixed_mode(intel_connector); /* Failed to get EDID, what about VBT? */ - fixed_mode = intel_panel_vbt_lfp_fixed_mode(intel_connector); - if (fixed_mode) - goto out; + if (!intel_panel_preferred_fixed_mode(intel_connector)) + intel_panel_add_vbt_lfp_fixed_mode(intel_connector); /* - * If we didn't get EDID, try checking if the panel is already turned - * on. If so, assume that whatever is currently programmed is the - * correct mode. + * If we didn't get a fixed mode from EDID or VBT, try checking + * if the panel is already turned on. If so, assume that + * whatever is currently programmed is the correct mode. */ - fixed_mode = intel_panel_encoder_fixed_mode(intel_connector, intel_encoder); + if (!intel_panel_preferred_fixed_mode(intel_connector)) + intel_panel_add_encoder_fixed_mode(intel_connector, intel_encoder); - /* If we still don't have a mode after all that, give up. */ - if (!fixed_mode) - goto failed; - -out: mutex_unlock(&dev->mode_config.mutex); - intel_panel_init(intel_connector, fixed_mode, downclock_mode); + /* If we still don't have a mode after all that, give up. */ + if (!intel_panel_preferred_fixed_mode(intel_connector)) + goto failed; + + intel_panel_init(intel_connector); + intel_backlight_setup(intel_connector, INVALID_PIPE); lvds_encoder->is_dual_link = compute_is_dual_link_lvds(lvds_encoder); @@ -1004,8 +1001,6 @@ out: return; failed: - mutex_unlock(&dev->mode_config.mutex); - drm_dbg_kms(&dev_priv->drm, "No LVDS modes found, disabling.\n"); drm_connector_cleanup(connector); drm_encoder_cleanup(encoder); diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 882e424973d4..415aa381f732 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -158,11 +158,11 @@ static bool is_downclock_mode(const struct drm_display_mode *downclock_mode, downclock_mode->clock < fixed_mode->clock; } -struct drm_display_mode * -intel_panel_edid_downclock_mode(struct intel_connector *connector, - const struct drm_display_mode *fixed_mode) +void intel_panel_add_edid_downclock_mode(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + const struct drm_display_mode *fixed_mode = + intel_panel_preferred_fixed_mode(connector); const struct drm_display_mode *scan, *best_mode = NULL; struct drm_display_mode *downclock_mode; int best_clock = fixed_mode->clock; @@ -187,29 +187,28 @@ intel_panel_edid_downclock_mode(struct intel_connector *connector, } if (!best_mode) - return NULL; + return; downclock_mode = drm_mode_duplicate(&dev_priv->drm, best_mode); if (!downclock_mode) - return NULL; + return; drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using downclock mode from EDID: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, DRM_MODE_ARG(downclock_mode)); - return downclock_mode; + list_add_tail(&downclock_mode->head, &connector->panel.fixed_modes); } -struct drm_display_mode * -intel_panel_edid_fixed_mode(struct intel_connector *connector) +void intel_panel_add_edid_fixed_mode(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); const struct drm_display_mode *scan; struct drm_display_mode *fixed_mode; if (list_empty(&connector->base.probed_modes)) - return NULL; + return; /* prefer fixed mode from EDID if available */ list_for_each_entry(scan, &connector->base.probed_modes, head) { @@ -218,47 +217,45 @@ intel_panel_edid_fixed_mode(struct intel_connector *connector) fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan); if (!fixed_mode) - return NULL; + return; drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using preferred mode from EDID: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, DRM_MODE_ARG(fixed_mode)); - return fixed_mode; + list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); + return; } scan = list_first_entry(&connector->base.probed_modes, typeof(*scan), head); - fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan); if (!fixed_mode) - return NULL; + return; fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; - drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using first mode from EDID: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, DRM_MODE_ARG(fixed_mode)); - return fixed_mode; + list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); } -struct drm_display_mode * -intel_panel_vbt_lfp_fixed_mode(struct intel_connector *connector) +void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct drm_display_info *info = &connector->base.display_info; struct drm_display_mode *fixed_mode; if (!dev_priv->vbt.lfp_lvds_vbt_mode) - return NULL; + return; fixed_mode = drm_mode_duplicate(&dev_priv->drm, dev_priv->vbt.lfp_lvds_vbt_mode); if (!fixed_mode) - return NULL; + return; fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; @@ -269,39 +266,37 @@ intel_panel_vbt_lfp_fixed_mode(struct intel_connector *connector) info->width_mm = fixed_mode->width_mm; info->height_mm = fixed_mode->height_mm; - return fixed_mode; + list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); } -struct drm_display_mode * -intel_panel_vbt_sdvo_fixed_mode(struct intel_connector *connector) +void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct drm_display_mode *fixed_mode; if (!i915->vbt.sdvo_lvds_vbt_mode) - return NULL; + return; fixed_mode = drm_mode_duplicate(&i915->drm, i915->vbt.sdvo_lvds_vbt_mode); if (!fixed_mode) - return NULL; + return; /* Guarantee the mode is preferred */ fixed_mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; - return fixed_mode; + list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); } -struct drm_display_mode * -intel_panel_encoder_fixed_mode(struct intel_connector *connector, - struct intel_encoder *encoder) +void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, + struct intel_encoder *encoder) { struct drm_i915_private *i915 = to_i915(connector->base.dev); struct drm_display_mode *fixed_mode; fixed_mode = intel_encoder_current_mode(encoder); if (!fixed_mode) - return NULL; + return; drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using current (BIOS) mode: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, @@ -309,7 +304,7 @@ intel_panel_encoder_fixed_mode(struct intel_connector *connector, fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; - return fixed_mode; + list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); } /* adjusted_mode has been preset to be the panel's fixed mode */ @@ -639,19 +634,12 @@ intel_panel_mode_valid(struct intel_connector *connector, return MODE_OK; } -int intel_panel_init(struct intel_connector *connector, - struct drm_display_mode *fixed_mode, - struct drm_display_mode *downclock_mode) +int intel_panel_init(struct intel_connector *connector) { struct intel_panel *panel = &connector->panel; intel_backlight_init_funcs(panel); - if (fixed_mode) - list_add_tail(&fixed_mode->head, &panel->fixed_modes); - if (downclock_mode) - list_add_tail(&downclock_mode->head, &panel->fixed_modes); - return 0; } diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 6a6ac338e9aa..5eaa2a1c2337 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -18,9 +18,7 @@ struct intel_connector; struct intel_crtc_state; struct intel_encoder; -int intel_panel_init(struct intel_connector *connector, - struct drm_display_mode *fixed_mode, - struct drm_display_mode *downclock_mode); +int intel_panel_init(struct intel_connector *connector); void intel_panel_fini(struct intel_connector *connector); enum drm_connector_status intel_panel_detect(struct drm_connector *connector, bool force); @@ -42,17 +40,11 @@ int intel_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); int intel_panel_compute_config(struct intel_connector *connector, struct drm_display_mode *adjusted_mode); -struct drm_display_mode * -intel_panel_edid_downclock_mode(struct intel_connector *connector, - const struct drm_display_mode *fixed_mode); -struct drm_display_mode * -intel_panel_edid_fixed_mode(struct intel_connector *connector); -struct drm_display_mode * -intel_panel_vbt_lfp_fixed_mode(struct intel_connector *connector); -struct drm_display_mode * -intel_panel_vbt_sdvo_fixed_mode(struct intel_connector *connector); -struct drm_display_mode * -intel_panel_encoder_fixed_mode(struct intel_connector *connector, - struct intel_encoder *encoder); +void intel_panel_add_edid_fixed_mode(struct intel_connector *connector); +void intel_panel_add_edid_downclock_mode(struct intel_connector *connector); +void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector); +void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector); +void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, + struct intel_encoder *encoder); #endif /* __INTEL_PANEL_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index c9c3f71818d9..866e05c1a49d 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2871,7 +2871,6 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) struct drm_connector *connector; struct intel_connector *intel_connector; struct intel_sdvo_connector *intel_sdvo_connector; - struct drm_display_mode *fixed_mode; DRM_DEBUG_KMS("initialising LVDS device %d\n", device); @@ -2904,13 +2903,14 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) * Fetch modes from VBT. For SDVO prefer the VBT mode since some * SDVO->LVDS transcoders can't cope with the EDID mode. */ - fixed_mode = intel_panel_vbt_sdvo_fixed_mode(intel_connector); - if (!fixed_mode) { + intel_panel_add_vbt_sdvo_fixed_mode(intel_connector); + + if (!intel_panel_preferred_fixed_mode(intel_connector)) { intel_ddc_get_modes(connector, &intel_sdvo->ddc); - fixed_mode = intel_panel_edid_fixed_mode(intel_connector); + intel_panel_add_edid_fixed_mode(intel_connector); } - intel_panel_init(intel_connector, fixed_mode, NULL); + intel_panel_init(intel_connector); if (!intel_panel_preferred_fixed_mode(intel_connector)) goto err; diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index dc43cb8ecb86..1954f07f0d3e 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -1859,7 +1859,7 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) struct drm_encoder *encoder; struct intel_connector *intel_connector; struct drm_connector *connector; - struct drm_display_mode *current_mode, *fixed_mode; + struct drm_display_mode *current_mode; enum port port; enum pipe pipe; @@ -1980,15 +1980,16 @@ void vlv_dsi_init(struct drm_i915_private *dev_priv) intel_connector_attach_encoder(intel_connector, intel_encoder); mutex_lock(&dev->mode_config.mutex); - fixed_mode = intel_panel_vbt_lfp_fixed_mode(intel_connector); + intel_panel_add_vbt_lfp_fixed_mode(intel_connector); mutex_unlock(&dev->mode_config.mutex); - if (!fixed_mode) { + if (!intel_panel_preferred_fixed_mode(intel_connector)) { drm_dbg_kms(&dev_priv->drm, "no fixed mode\n"); goto err_cleanup_connector; } - intel_panel_init(intel_connector, fixed_mode, NULL); + intel_panel_init(intel_connector); + intel_backlight_setup(intel_connector, INVALID_PIPE); vlv_dsi_add_properties(intel_connector); From 54746f57f08959c68986c335b3156da6846d0ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:14 +0300 Subject: [PATCH 00478/11454] drm/i915: Refactor non-EDID fixed mode duplication MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All the non-EDID fixed mode functions basically do the exact same thing. Let's refactor the common bits into a shared function. There are minor differences on how the mode types are populated, whether the display info physical size is updated, and the debug print. The differences are purely accidental, so unifying them is actually a good thing. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-4-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_panel.c | 70 ++++++++++------------ 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 415aa381f732..1e56ca9033e0 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -243,68 +243,62 @@ void intel_panel_add_edid_fixed_mode(struct intel_connector *connector) list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); } -void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector) +static void intel_panel_add_fixed_mode(struct intel_connector *connector, + struct drm_display_mode *fixed_mode, + const char *type) { - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); + struct drm_i915_private *i915 = to_i915(connector->base.dev); struct drm_display_info *info = &connector->base.display_info; - struct drm_display_mode *fixed_mode; - if (!dev_priv->vbt.lfp_lvds_vbt_mode) - return; - - fixed_mode = drm_mode_duplicate(&dev_priv->drm, - dev_priv->vbt.lfp_lvds_vbt_mode); if (!fixed_mode) return; - fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; - - drm_dbg_kms(&dev_priv->drm, "[CONNECTOR:%d:%s] using mode from VBT: " DRM_MODE_FMT "\n", - connector->base.base.id, connector->base.name, - DRM_MODE_ARG(fixed_mode)); + fixed_mode->type |= DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; info->width_mm = fixed_mode->width_mm; info->height_mm = fixed_mode->height_mm; + drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using %s fixed mode: " DRM_MODE_FMT "\n", + connector->base.base.id, connector->base.name, type, + DRM_MODE_ARG(fixed_mode)); + list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); } +void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + const struct drm_display_mode *mode; + + mode = i915->vbt.lfp_lvds_vbt_mode; + if (!mode) + return; + + intel_panel_add_fixed_mode(connector, + drm_mode_duplicate(&i915->drm, mode), + "VBT LFP"); +} + void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector) { struct drm_i915_private *i915 = to_i915(connector->base.dev); - struct drm_display_mode *fixed_mode; + const struct drm_display_mode *mode; - if (!i915->vbt.sdvo_lvds_vbt_mode) + mode = i915->vbt.sdvo_lvds_vbt_mode; + if (!mode) return; - fixed_mode = drm_mode_duplicate(&i915->drm, - i915->vbt.sdvo_lvds_vbt_mode); - if (!fixed_mode) - return; - - /* Guarantee the mode is preferred */ - fixed_mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER; - - list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); + intel_panel_add_fixed_mode(connector, + drm_mode_duplicate(&i915->drm, mode), + "VBT SDVO"); } void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, struct intel_encoder *encoder) { - struct drm_i915_private *i915 = to_i915(connector->base.dev); - struct drm_display_mode *fixed_mode; - - fixed_mode = intel_encoder_current_mode(encoder); - if (!fixed_mode) - return; - - drm_dbg_kms(&i915->drm, "[CONNECTOR:%d:%s] using current (BIOS) mode: " DRM_MODE_FMT "\n", - connector->base.base.id, connector->base.name, - DRM_MODE_ARG(fixed_mode)); - - fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; - - list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); + intel_panel_add_fixed_mode(connector, + intel_encoder_current_mode(encoder), + "current (BIOS)"); } /* adjusted_mode has been preset to be the panel's fixed mode */ From 05d2d45e8736e91dfb7da28c2f51aa8e5cdc7d1f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:15 +0300 Subject: [PATCH 00479/11454] drm/i915: Nuke intel_drrs_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_drrs_init() is a mostly pointless wrapper around intel_panel_add_edid_downclock_mode(), get rid of it. The only really useful thing left in there is the debug print regarding the DRRS type supported by the connector. Let's just move that into intel_panel_init(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-5-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 2 +- drivers/gpu/drm/i915/display/intel_drrs.c | 24 ---------------------- drivers/gpu/drm/i915/display/intel_drrs.h | 1 - drivers/gpu/drm/i915/display/intel_panel.c | 6 ++++++ 4 files changed, 7 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index 67472555211d..e539bc315d7b 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5075,7 +5075,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_panel_add_edid_fixed_mode(intel_connector); if (intel_panel_preferred_fixed_mode(intel_connector) && intel_edp_has_drrs(intel_dp)) - intel_drrs_init(intel_connector); + intel_panel_add_edid_downclock_mode(intel_connector); /* MSO requires information from the EDID */ intel_edp_mso_init(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index d04a9ff9e813..3ebea697f77a 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -354,27 +354,3 @@ void intel_crtc_drrs_init(struct intel_crtc *crtc) mutex_init(&crtc->drrs.mutex); crtc->drrs.cpu_transcoder = INVALID_TRANSCODER; } - -/** - * intel_drrs_init - Init DRRS for eDP connector - * @connector: eDP connector - * - * This function is called only once at driver load to initialize - * DRRS support for the connector. - * - * Returns: - * Downclock mode if panel supports it, else return NULL. - * DRRS support is determined by the presence of downclock mode (apart - * from VBT setting). - */ -void intel_drrs_init(struct intel_connector *connector) -{ - struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - - intel_panel_add_edid_downclock_mode(connector); - - drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] DRRS type: %s\n", - connector->base.base.id, connector->base.name, - intel_drrs_type_str(intel_panel_drrs_type(connector))); -} diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index 3ea52220cd69..084c3f4f8403 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -27,6 +27,5 @@ void intel_drrs_compute_config(struct intel_connector *connector, struct intel_crtc_state *pipe_config, int output_bpp, bool constant_n); void intel_crtc_drrs_init(struct intel_crtc *crtc); -void intel_drrs_init(struct intel_connector *connector); #endif /* __INTEL_DRRS_H__ */ diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 1e56ca9033e0..5ecc6fc80588 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -35,6 +35,7 @@ #include "intel_connector.h" #include "intel_de.h" #include "intel_display_types.h" +#include "intel_drrs.h" #include "intel_panel.h" bool intel_panel_use_ssc(struct drm_i915_private *i915) @@ -634,6 +635,11 @@ int intel_panel_init(struct intel_connector *connector) intel_backlight_init_funcs(panel); + drm_dbg_kms(connector->base.dev, + "[CONNECTOR:%d:%s] DRRS type: %s\n", + connector->base.base.id, connector->base.name, + intel_drrs_type_str(intel_panel_drrs_type(connector))); + return 0; } From 3a3c4ce92962a42d5ee9b1db435b4b3ffa5a4fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:16 +0300 Subject: [PATCH 00480/11454] drm/i915: Combine the EDID fixed_mode+downclock_mode lookup into one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The intel_panel_add_edid_fixed_mode() vs. intel_panel_add_edid_downclock_mode() split is not really helpful. Let's just roll those into a single function so that the connector init code doesn't have to care too much about this. All we need to know is whether DRRS should be allowed or not. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-6-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 6 ++---- drivers/gpu/drm/i915/display/intel_lvds.c | 2 +- drivers/gpu/drm/i915/display/intel_panel.c | 11 +++++++++-- drivers/gpu/drm/i915/display/intel_panel.h | 3 +-- drivers/gpu/drm/i915/display/intel_sdvo.c | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index e539bc315d7b..abfdaa0c7382 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -5072,10 +5072,8 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, } intel_connector->edid = edid; - intel_panel_add_edid_fixed_mode(intel_connector); - if (intel_panel_preferred_fixed_mode(intel_connector) && - intel_edp_has_drrs(intel_dp)) - intel_panel_add_edid_downclock_mode(intel_connector); + intel_panel_add_edid_fixed_modes(intel_connector, + intel_edp_has_drrs(intel_dp)); /* MSO requires information from the EDID */ intel_edp_mso_init(intel_dp); diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 193daffadc90..73129d21f5e5 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -968,7 +968,7 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) intel_connector->edid = edid; /* Try EDID first */ - intel_panel_add_edid_fixed_mode(intel_connector); + intel_panel_add_edid_fixed_modes(intel_connector, false); /* Failed to get EDID, what about VBT? */ if (!intel_panel_preferred_fixed_mode(intel_connector)) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 5ecc6fc80588..3b1da9aa023f 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -159,7 +159,7 @@ static bool is_downclock_mode(const struct drm_display_mode *downclock_mode, downclock_mode->clock < fixed_mode->clock; } -void intel_panel_add_edid_downclock_mode(struct intel_connector *connector) +static void intel_panel_add_edid_downclock_mode(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); const struct drm_display_mode *fixed_mode = @@ -202,7 +202,7 @@ void intel_panel_add_edid_downclock_mode(struct intel_connector *connector) list_add_tail(&downclock_mode->head, &connector->panel.fixed_modes); } -void intel_panel_add_edid_fixed_mode(struct intel_connector *connector) +static void intel_panel_add_edid_fixed_mode(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); const struct drm_display_mode *scan; @@ -244,6 +244,13 @@ void intel_panel_add_edid_fixed_mode(struct intel_connector *connector) list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); } +void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs) +{ + intel_panel_add_edid_fixed_mode(connector); + if (intel_panel_preferred_fixed_mode(connector) && has_drrs) + intel_panel_add_edid_downclock_mode(connector); +} + static void intel_panel_add_fixed_mode(struct intel_connector *connector, struct drm_display_mode *fixed_mode, const char *type) diff --git a/drivers/gpu/drm/i915/display/intel_panel.h b/drivers/gpu/drm/i915/display/intel_panel.h index 5eaa2a1c2337..2e32bb728beb 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.h +++ b/drivers/gpu/drm/i915/display/intel_panel.h @@ -40,8 +40,7 @@ int intel_panel_fitting(struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state); int intel_panel_compute_config(struct intel_connector *connector, struct drm_display_mode *adjusted_mode); -void intel_panel_add_edid_fixed_mode(struct intel_connector *connector); -void intel_panel_add_edid_downclock_mode(struct intel_connector *connector); +void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs); void intel_panel_add_vbt_lfp_fixed_mode(struct intel_connector *connector); void intel_panel_add_vbt_sdvo_fixed_mode(struct intel_connector *connector); void intel_panel_add_encoder_fixed_mode(struct intel_connector *connector, diff --git a/drivers/gpu/drm/i915/display/intel_sdvo.c b/drivers/gpu/drm/i915/display/intel_sdvo.c index 866e05c1a49d..ab88d8b783e6 100644 --- a/drivers/gpu/drm/i915/display/intel_sdvo.c +++ b/drivers/gpu/drm/i915/display/intel_sdvo.c @@ -2907,7 +2907,7 @@ intel_sdvo_lvds_init(struct intel_sdvo *intel_sdvo, int device) if (!intel_panel_preferred_fixed_mode(intel_connector)) { intel_ddc_get_modes(connector, &intel_sdvo->ddc); - intel_panel_add_edid_fixed_mode(intel_connector); + intel_panel_add_edid_fixed_modes(intel_connector, false); } intel_panel_init(intel_connector); From ccaa910128c52547102ba2e769cbadda5675df57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:17 +0300 Subject: [PATCH 00481/11454] drm/i915: Stop duplicating the EDID fixed/downclock modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of duplicating the fixed/downclock modes we can just grab the originals straight from the probed_modes list and keep them. The next .get_modes() is going to repopulate the probed_modes list anyway so whatever we leave there is just going to sit around until that time wasting memory. In fact let's clear out the probed modes list entirely to make sure we get 100% consistent behaviour starting already from the very first real .get_modes(). Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-7-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_panel.c | 62 ++++++++++------------ 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 3b1da9aa023f..5d08b2bf27ec 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -164,8 +164,7 @@ static void intel_panel_add_edid_downclock_mode(struct intel_connector *connecto struct drm_i915_private *dev_priv = to_i915(connector->base.dev); const struct drm_display_mode *fixed_mode = intel_panel_preferred_fixed_mode(connector); - const struct drm_display_mode *scan, *best_mode = NULL; - struct drm_display_mode *downclock_mode; + struct drm_display_mode *scan, *best_mode = NULL; int best_clock = fixed_mode->clock; list_for_each_entry(scan, &connector->base.probed_modes, head) { @@ -190,58 +189,54 @@ static void intel_panel_add_edid_downclock_mode(struct intel_connector *connecto if (!best_mode) return; - downclock_mode = drm_mode_duplicate(&dev_priv->drm, best_mode); - if (!downclock_mode) - return; - drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] using downclock mode from EDID: " DRM_MODE_FMT "\n", + "[CONNECTOR:%d:%s] using EDID downclock mode: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, - DRM_MODE_ARG(downclock_mode)); + DRM_MODE_ARG(best_mode)); - list_add_tail(&downclock_mode->head, &connector->panel.fixed_modes); + list_move_tail(&best_mode->head, &connector->panel.fixed_modes); } static void intel_panel_add_edid_fixed_mode(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - const struct drm_display_mode *scan; - struct drm_display_mode *fixed_mode; + struct drm_display_mode *scan, *fixed_mode = NULL; if (list_empty(&connector->base.probed_modes)) return; - /* prefer fixed mode from EDID if available */ + /* make sure the preferred mode is first */ list_for_each_entry(scan, &connector->base.probed_modes, head) { - if ((scan->type & DRM_MODE_TYPE_PREFERRED) == 0) - continue; - - fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan); - if (!fixed_mode) - return; - - drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] using preferred mode from EDID: " DRM_MODE_FMT "\n", - connector->base.base.id, connector->base.name, - DRM_MODE_ARG(fixed_mode)); - - list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); - return; + if (scan->type & DRM_MODE_TYPE_PREFERRED) { + fixed_mode = scan; + break; + } } - scan = list_first_entry(&connector->base.probed_modes, - typeof(*scan), head); - fixed_mode = drm_mode_duplicate(&dev_priv->drm, scan); if (!fixed_mode) - return; + fixed_mode = list_first_entry(&connector->base.probed_modes, + typeof(*fixed_mode), head); - fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] using first mode from EDID: " DRM_MODE_FMT "\n", + "[CONNECTOR:%d:%s] using %s EDID fixed mode: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, + fixed_mode->type & DRM_MODE_TYPE_PREFERRED ? "preferred" : "first", DRM_MODE_ARG(fixed_mode)); - list_add_tail(&fixed_mode->head, &connector->panel.fixed_modes); + fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; + + list_move_tail(&fixed_mode->head, &connector->panel.fixed_modes); +} + +static void intel_panel_destroy_probed_modes(struct intel_connector *connector) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + struct drm_display_mode *mode, *next; + + list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) { + list_del(&mode->head); + drm_mode_destroy(&i915->drm, mode); + } } void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs) @@ -249,6 +244,7 @@ void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool ha intel_panel_add_edid_fixed_mode(connector); if (intel_panel_preferred_fixed_mode(connector) && has_drrs) intel_panel_add_edid_downclock_mode(connector); + intel_panel_destroy_probed_modes(connector); } static void intel_panel_add_fixed_mode(struct intel_connector *connector, From 7634bef123bcf42e64acb694d545ba93b79d5b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:18 +0300 Subject: [PATCH 00482/11454] drm/i915: Allow an arbitrary number of downclock modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the "two fixed modes only" limit and grab as many downclock modes from the EDID as we can find. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-8-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_panel.c | 44 +++++++--------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index 5d08b2bf27ec..d359c8050fdc 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -159,42 +159,24 @@ static bool is_downclock_mode(const struct drm_display_mode *downclock_mode, downclock_mode->clock < fixed_mode->clock; } -static void intel_panel_add_edid_downclock_mode(struct intel_connector *connector) +static void intel_panel_add_edid_downclock_modes(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); const struct drm_display_mode *fixed_mode = intel_panel_preferred_fixed_mode(connector); - struct drm_display_mode *scan, *best_mode = NULL; - int best_clock = fixed_mode->clock; + struct drm_display_mode *mode, *next; - list_for_each_entry(scan, &connector->base.probed_modes, head) { - /* - * If one mode has the same resolution with the fixed_panel - * mode while they have the different refresh rate, it means - * that the reduced downclock is found. In such - * case we can set the different FPx0/1 to dynamically select - * between low and high frequency. - */ - if (is_downclock_mode(scan, fixed_mode) && - scan->clock < best_clock) { - /* - * The downclock is already found. But we - * expect to find the lower downclock. - */ - best_clock = scan->clock; - best_mode = scan; - } + list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) { + if (!is_downclock_mode(mode, fixed_mode)) + continue; + + drm_dbg_kms(&dev_priv->drm, + "[CONNECTOR:%d:%s] using EDID downclock mode: " DRM_MODE_FMT "\n", + connector->base.base.id, connector->base.name, + DRM_MODE_ARG(mode)); + + list_move_tail(&mode->head, &connector->panel.fixed_modes); } - - if (!best_mode) - return; - - drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] using EDID downclock mode: " DRM_MODE_FMT "\n", - connector->base.base.id, connector->base.name, - DRM_MODE_ARG(best_mode)); - - list_move_tail(&best_mode->head, &connector->panel.fixed_modes); } static void intel_panel_add_edid_fixed_mode(struct intel_connector *connector) @@ -243,7 +225,7 @@ void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool ha { intel_panel_add_edid_fixed_mode(connector); if (intel_panel_preferred_fixed_mode(connector) && has_drrs) - intel_panel_add_edid_downclock_mode(connector); + intel_panel_add_edid_downclock_modes(connector); intel_panel_destroy_probed_modes(connector); } From c19909d037b640a5e3580c68f420e7ba058c68e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:19 +0300 Subject: [PATCH 00483/11454] drm/i915: Allow higher refresh rate alternate fixed modes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We shouldn't restrict ourselves to just downclock modes with lower refresh rate than the preferred mode. Laptops these days can offer higher refresh rate modes as well. Remove the arbitrary limit and allow all modes that, apart from the clock, match the preferred mode. v2: s/add_edid_downclock_modes/add_edid_alt_fixed_modes/ (Jani) Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-9-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_panel.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_panel.c b/drivers/gpu/drm/i915/display/intel_panel.c index d359c8050fdc..03398feb6676 100644 --- a/drivers/gpu/drm/i915/display/intel_panel.c +++ b/drivers/gpu/drm/i915/display/intel_panel.c @@ -149,29 +149,29 @@ int intel_panel_compute_config(struct intel_connector *connector, return 0; } -static bool is_downclock_mode(const struct drm_display_mode *downclock_mode, - const struct drm_display_mode *fixed_mode) +static bool is_alt_fixed_mode(const struct drm_display_mode *mode, + const struct drm_display_mode *preferred_mode) { - return drm_mode_match(downclock_mode, fixed_mode, + return drm_mode_match(mode, preferred_mode, DRM_MODE_MATCH_TIMINGS | DRM_MODE_MATCH_FLAGS | DRM_MODE_MATCH_3D_FLAGS) && - downclock_mode->clock < fixed_mode->clock; + mode->clock != preferred_mode->clock; } -static void intel_panel_add_edid_downclock_modes(struct intel_connector *connector) +static void intel_panel_add_edid_alt_fixed_modes(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); - const struct drm_display_mode *fixed_mode = + const struct drm_display_mode *preferred_mode = intel_panel_preferred_fixed_mode(connector); struct drm_display_mode *mode, *next; list_for_each_entry_safe(mode, next, &connector->base.probed_modes, head) { - if (!is_downclock_mode(mode, fixed_mode)) + if (!is_alt_fixed_mode(mode, preferred_mode)) continue; drm_dbg_kms(&dev_priv->drm, - "[CONNECTOR:%d:%s] using EDID downclock mode: " DRM_MODE_FMT "\n", + "[CONNECTOR:%d:%s] using alternate EDID fixed mode: " DRM_MODE_FMT "\n", connector->base.base.id, connector->base.name, DRM_MODE_ARG(mode)); @@ -179,7 +179,7 @@ static void intel_panel_add_edid_downclock_modes(struct intel_connector *connect } } -static void intel_panel_add_edid_fixed_mode(struct intel_connector *connector) +static void intel_panel_add_edid_preferred_mode(struct intel_connector *connector) { struct drm_i915_private *dev_priv = to_i915(connector->base.dev); struct drm_display_mode *scan, *fixed_mode = NULL; @@ -223,9 +223,9 @@ static void intel_panel_destroy_probed_modes(struct intel_connector *connector) void intel_panel_add_edid_fixed_modes(struct intel_connector *connector, bool has_drrs) { - intel_panel_add_edid_fixed_mode(connector); + intel_panel_add_edid_preferred_mode(connector); if (intel_panel_preferred_fixed_mode(connector) && has_drrs) - intel_panel_add_edid_downclock_modes(connector); + intel_panel_add_edid_alt_fixed_modes(connector); intel_panel_destroy_probed_modes(connector); } From f244cdfa72b828d775f24251dac85b04ad1c4829 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:20 +0300 Subject: [PATCH 00484/11454] drm/i915: Move intel_drrs_compute_config() into intel_dp.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_drrs_compute_config() is 100% DP specific. DRRS on other types of encoders wouldn't do any of these M2/N2 calculations etc. So let's move this into intel_dp.c so all the DP state calculation is more concentrated into one place. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-10-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 59 +++++++++++++++++++++-- drivers/gpu/drm/i915/display/intel_drrs.c | 54 --------------------- drivers/gpu/drm/i915/display/intel_drrs.h | 3 -- 3 files changed, 56 insertions(+), 60 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index abfdaa0c7382..da1fd626c3fb 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -60,7 +60,6 @@ #include "intel_dp_mst.h" #include "intel_dpio_phy.h" #include "intel_dpll.h" -#include "intel_drrs.h" #include "intel_fifo_underrun.h" #include "intel_hdcp.h" #include "intel_hdmi.h" @@ -1770,6 +1769,60 @@ intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp, intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA); } +static bool can_enable_drrs(struct intel_connector *connector, + const struct intel_crtc_state *pipe_config, + const struct drm_display_mode *downclock_mode) +{ + if (pipe_config->vrr.enable) + return false; + + /* + * DRRS and PSR can't be enable together, so giving preference to PSR + * as it allows more power-savings by complete shutting down display, + * so to guarantee this, intel_drrs_compute_config() must be called + * after intel_psr_compute_config(). + */ + if (pipe_config->has_psr) + return false; + + return downclock_mode && + intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; +} + +static void +intel_dp_drrs_compute_config(struct intel_connector *connector, + struct intel_crtc_state *pipe_config, + int output_bpp, bool constant_n) +{ + struct drm_i915_private *i915 = to_i915(connector->base.dev); + const struct drm_display_mode *downclock_mode = + intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); + int pixel_clock; + + if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { + if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder)) + intel_zero_m_n(&pipe_config->dp_m2_n2); + return; + } + + if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) + pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay; + + pipe_config->has_drrs = true; + + pixel_clock = downclock_mode->clock; + if (pipe_config->splitter.enable) + pixel_clock /= pipe_config->splitter.link_count; + + intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock, + pipe_config->port_clock, &pipe_config->dp_m2_n2, + constant_n, pipe_config->fec_enable); + + /* FIXME: abstract this better */ + if (pipe_config->splitter.enable) + pipe_config->dp_m2_n2.data_m *= pipe_config->splitter.link_count; +} + int intel_dp_compute_config(struct intel_encoder *encoder, struct intel_crtc_state *pipe_config, @@ -1878,8 +1931,8 @@ intel_dp_compute_config(struct intel_encoder *encoder, intel_vrr_compute_config(pipe_config, conn_state); intel_psr_compute_config(intel_dp, pipe_config, conn_state); - intel_drrs_compute_config(intel_connector, pipe_config, - output_bpp, constant_n); + intel_dp_drrs_compute_config(intel_connector, pipe_config, + output_bpp, constant_n); intel_dp_compute_vsc_sdp(intel_dp, pipe_config, conn_state); intel_dp_compute_hdr_metadata_infoframe_sdp(intel_dp, pipe_config, conn_state); diff --git a/drivers/gpu/drm/i915/display/intel_drrs.c b/drivers/gpu/drm/i915/display/intel_drrs.c index 3ebea697f77a..166caf293f7b 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.c +++ b/drivers/gpu/drm/i915/display/intel_drrs.c @@ -61,60 +61,6 @@ const char *intel_drrs_type_str(enum drrs_type drrs_type) return str[drrs_type]; } -static bool can_enable_drrs(struct intel_connector *connector, - const struct intel_crtc_state *pipe_config, - const struct drm_display_mode *downclock_mode) -{ - if (pipe_config->vrr.enable) - return false; - - /* - * DRRS and PSR can't be enable together, so giving preference to PSR - * as it allows more power-savings by complete shutting down display, - * so to guarantee this, intel_drrs_compute_config() must be called - * after intel_psr_compute_config(). - */ - if (pipe_config->has_psr) - return false; - - return downclock_mode && - intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; -} - -void -intel_drrs_compute_config(struct intel_connector *connector, - struct intel_crtc_state *pipe_config, - int output_bpp, bool constant_n) -{ - struct drm_i915_private *i915 = to_i915(connector->base.dev); - const struct drm_display_mode *downclock_mode = - intel_panel_downclock_mode(connector, &pipe_config->hw.adjusted_mode); - int pixel_clock; - - if (!can_enable_drrs(connector, pipe_config, downclock_mode)) { - if (intel_cpu_transcoder_has_m2_n2(i915, pipe_config->cpu_transcoder)) - intel_zero_m_n(&pipe_config->dp_m2_n2); - return; - } - - if (IS_IRONLAKE(i915) || IS_SANDYBRIDGE(i915) || IS_IVYBRIDGE(i915)) - pipe_config->msa_timing_delay = i915->vbt.edp.drrs_msa_timing_delay; - - pipe_config->has_drrs = true; - - pixel_clock = downclock_mode->clock; - if (pipe_config->splitter.enable) - pixel_clock /= pipe_config->splitter.link_count; - - intel_link_compute_m_n(output_bpp, pipe_config->lane_count, pixel_clock, - pipe_config->port_clock, &pipe_config->dp_m2_n2, - constant_n, pipe_config->fec_enable); - - /* FIXME: abstract this better */ - if (pipe_config->splitter.enable) - pipe_config->dp_m2_n2.data_m *= pipe_config->splitter.link_count; -} - static void intel_drrs_set_refresh_rate_pipeconf(struct intel_crtc *crtc, enum drrs_refresh_rate refresh_rate) diff --git a/drivers/gpu/drm/i915/display/intel_drrs.h b/drivers/gpu/drm/i915/display/intel_drrs.h index 084c3f4f8403..3ad1be1ad9c1 100644 --- a/drivers/gpu/drm/i915/display/intel_drrs.h +++ b/drivers/gpu/drm/i915/display/intel_drrs.h @@ -23,9 +23,6 @@ void intel_drrs_invalidate(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); void intel_drrs_flush(struct drm_i915_private *dev_priv, unsigned int frontbuffer_bits); -void intel_drrs_compute_config(struct intel_connector *connector, - struct intel_crtc_state *pipe_config, - int output_bpp, bool constant_n); void intel_crtc_drrs_init(struct intel_crtc *crtc); #endif /* __INTEL_DRRS_H__ */ From 1159c83392787d9f7ad6dc443025b8eeed14085b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:21 +0300 Subject: [PATCH 00485/11454] drm/i915: Allow static DRRS on all eDP ports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only seamless DRRS has specific hardware requirements so we can allow static DRRS on any eDP port. And we can replace these port checks and whatnot with a simple check to make sure the transcoder(s) we're about to use are capable of seamless DRRS. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-11-ville.syrjala@linux.intel.com Acked-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_dp.c | 54 +++++++++---------------- 1 file changed, 20 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp.c b/drivers/gpu/drm/i915/display/intel_dp.c index da1fd626c3fb..b0b4bdaf3b9d 100644 --- a/drivers/gpu/drm/i915/display/intel_dp.c +++ b/drivers/gpu/drm/i915/display/intel_dp.c @@ -1769,10 +1769,22 @@ intel_dp_compute_hdr_metadata_infoframe_sdp(struct intel_dp *intel_dp, intel_hdmi_infoframe_enable(HDMI_PACKET_TYPE_GAMUT_METADATA); } +static bool cpu_transcoder_has_drrs(struct drm_i915_private *i915, + enum transcoder cpu_transcoder) +{ + /* M1/N1 is double buffered */ + if (DISPLAY_VER(i915) >= 9 || IS_BROADWELL(i915)) + return true; + + return intel_cpu_transcoder_has_m2_n2(i915, cpu_transcoder); +} + static bool can_enable_drrs(struct intel_connector *connector, const struct intel_crtc_state *pipe_config, const struct drm_display_mode *downclock_mode) { + struct drm_i915_private *i915 = to_i915(connector->base.dev); + if (pipe_config->vrr.enable) return false; @@ -1785,6 +1797,13 @@ static bool can_enable_drrs(struct intel_connector *connector, if (pipe_config->has_psr) return false; + /* FIXME missing FDI M2/N2 etc. */ + if (pipe_config->has_pch_encoder) + return false; + + if (!cpu_transcoder_has_drrs(i915, pipe_config->cpu_transcoder)) + return false; + return downclock_mode && intel_panel_drrs_type(connector) == DRRS_TYPE_SEAMLESS; } @@ -5029,39 +5048,6 @@ intel_edp_add_properties(struct intel_dp *intel_dp) fixed_mode->vdisplay); } -static bool -intel_edp_has_drrs(struct intel_dp *intel_dp) -{ - struct intel_connector *connector = intel_dp->attached_connector; - struct intel_encoder *encoder = &dp_to_dig_port(intel_dp)->base; - struct drm_i915_private *i915 = to_i915(connector->base.dev); - - if (DISPLAY_VER(i915) < 5) { - drm_dbg_kms(&i915->drm, - "[CONNECTOR:%d:%s] DRRS not supported on platform\n", - connector->base.base.id, connector->base.name); - return false; - } - - if ((DISPLAY_VER(i915) < 8 && !HAS_GMCH(i915)) && - encoder->port != PORT_A) { - drm_dbg_kms(&i915->drm, - "[CONNECTOR:%d:%s] DRRS not supported on [ENCODER:%d:%s]\n", - connector->base.base.id, connector->base.name, - encoder->base.base.id, encoder->base.name); - return false; - } - - if (i915->vbt.drrs_type == DRRS_TYPE_NONE) { - drm_dbg_kms(&i915->drm, - "[CONNECTOR:%d:%s] DRRS not supported according to VBT\n", - connector->base.base.id, connector->base.name); - return false; - } - - return true; -} - static bool intel_edp_init_connector(struct intel_dp *intel_dp, struct intel_connector *intel_connector) { @@ -5126,7 +5112,7 @@ static bool intel_edp_init_connector(struct intel_dp *intel_dp, intel_connector->edid = edid; intel_panel_add_edid_fixed_modes(intel_connector, - intel_edp_has_drrs(intel_dp)); + dev_priv->vbt.drrs_type != DRRS_TYPE_NONE); /* MSO requires information from the EDID */ intel_edp_mso_init(intel_dp); From 001b6169a9204d9b4013c4c0ff24fca08bf1ad16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Thu, 31 Mar 2022 14:28:22 +0300 Subject: [PATCH 00486/11454] drm/i915: Allow static DRRS on LVDS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing special about static DRRS on LVDS, it's just your bog standard modeset. Let's allow it. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20220331112822.11462-12-ville.syrjala@linux.intel.com Reviewed-by: Jani Nikula --- drivers/gpu/drm/i915/display/intel_lvds.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_lvds.c b/drivers/gpu/drm/i915/display/intel_lvds.c index 73129d21f5e5..e8478161f8b9 100644 --- a/drivers/gpu/drm/i915/display/intel_lvds.c +++ b/drivers/gpu/drm/i915/display/intel_lvds.c @@ -968,7 +968,8 @@ void intel_lvds_init(struct drm_i915_private *dev_priv) intel_connector->edid = edid; /* Try EDID first */ - intel_panel_add_edid_fixed_modes(intel_connector, false); + intel_panel_add_edid_fixed_modes(intel_connector, + dev_priv->vbt.drrs_type != DRRS_TYPE_NONE); /* Failed to get EDID, what about VBT? */ if (!intel_panel_preferred_fixed_mode(intel_connector)) From 6f5efd118efafa22139e8670a4e4b506ba757dfd Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Sat, 26 Mar 2022 15:33:26 +0800 Subject: [PATCH 00487/11454] drm/bridge: anx7625: add missing destroy_workqueue() in anx7625_i2c_probe() Add the missing destroy_workqueue() before return from anx7625_i2c_probe() in the error handling case. Fixes: adca62ec370c ("drm/bridge: anx7625: Support reading edid through aux channel") Signed-off-by: Yang Yingliang Reviewed-by: Hsin-Yi Wang Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220326073326.3389347-1-yangyingliang@huawei.com --- drivers/gpu/drm/bridge/analogix/anx7625.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/anx7625.c b/drivers/gpu/drm/bridge/analogix/anx7625.c index dcf3275a00fe..6516f9570b86 100644 --- a/drivers/gpu/drm/bridge/analogix/anx7625.c +++ b/drivers/gpu/drm/bridge/analogix/anx7625.c @@ -2660,7 +2660,7 @@ static int anx7625_i2c_probe(struct i2c_client *client, if (ret) { if (ret != -EPROBE_DEFER) DRM_DEV_ERROR(dev, "fail to parse DT : %d\n", ret); - return ret; + goto free_wq; } if (anx7625_register_i2c_dummy_clients(platform, client) != 0) { @@ -2675,7 +2675,7 @@ static int anx7625_i2c_probe(struct i2c_client *client, pm_suspend_ignore_children(dev, true); ret = devm_add_action_or_reset(dev, anx7625_runtime_disable, dev); if (ret) - return ret; + goto free_wq; if (!platform->pdata.low_power_mode) { anx7625_disable_pd_protocol(platform); From 7ed2b0dabf7a22874cb30f8878df239ef638eb53 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 21 Mar 2022 11:47:05 +0100 Subject: [PATCH 00488/11454] drm/bridge: adv7511: clean up CEC adapter when probe fails When the probe routine fails we also need to clean up the CEC adapter registered in adv7511_cec_init(). Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support") Signed-off-by: Lucas Stach Reviewed-by: Robert Foss Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220321104705.2804423-1-l.stach@pengutronix.de --- drivers/gpu/drm/bridge/adv7511/adv7511_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index 005bf18682ff..668dcefbae17 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -1313,6 +1313,7 @@ err_unregister_audio: adv7511_audio_exit(adv7511); drm_bridge_remove(&adv7511->bridge); err_unregister_cec: + cec_unregister_adapter(adv7511->cec_adap); i2c_unregister_device(adv7511->i2c_cec); clk_disable_unprepare(adv7511->cec_clk); err_i2c_unregister_packet: From dd550c7cdbe3087adfd51360931938db4de8e832 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:05 +0200 Subject: [PATCH 00489/11454] dt-bindings: display: bridge: tc358867: Document DPI output support The TC358767/TC358867/TC9595 are all capable of operating in multiple modes, DPI-to-(e)DP, DSI-to-(e)DP, DSI-to-DPI. Document support for the DPI output port, which can now be connected both as input and output. Acked-by: Rob Herring Reviewed-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Rob Herring Cc: Sam Ravnborg Cc: devicetree@vger.kernel.org To: dri-devel@lists.freedesktop.org Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-2-marex@denx.de --- .../devicetree/bindings/display/bridge/toshiba,tc358767.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml index f1541cc05297..5cfda6f2ba69 100644 --- a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml +++ b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml @@ -61,8 +61,8 @@ properties: port@1: $ref: /schemas/graph.yaml#/properties/port description: | - DPI input port. The remote endpoint phandle should be a - reference to a valid DPI output endpoint node + DPI input/output port. The remote endpoint phandle should be a + reference to a valid DPI output or input endpoint node. port@2: $ref: /schemas/graph.yaml#/properties/port From 9ba328035e68a2eae973f0c9fbb5df15f160612c Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:06 +0200 Subject: [PATCH 00490/11454] dt-bindings: display: bridge: tc358867: Document DSI data-lanes property It is necessary to specify the number of connected/used DSI data lanes when using the DSI input port of this bridge. Document the 'data-lanes' property of the DSI input port. Reviewed-by: Rob Herring Acked-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Rob Herring Cc: Sam Ravnborg Cc: devicetree@vger.kernel.org To: dri-devel@lists.freedesktop.org Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-3-marex@denx.de --- .../display/bridge/toshiba,tc358767.yaml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml index 5cfda6f2ba69..ed280053ec62 100644 --- a/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml +++ b/Documentation/devicetree/bindings/display/bridge/toshiba,tc358767.yaml @@ -53,11 +53,27 @@ properties: properties: port@0: - $ref: /schemas/graph.yaml#/properties/port + $ref: /schemas/graph.yaml#/$defs/port-base + unevaluatedProperties: false description: | DSI input port. The remote endpoint phandle should be a reference to a valid DSI output endpoint node + properties: + endpoint: + $ref: /schemas/media/video-interfaces.yaml# + unevaluatedProperties: false + + properties: + data-lanes: + description: array of physical DSI data lane indexes. + minItems: 1 + items: + - const: 1 + - const: 2 + - const: 3 + - const: 4 + port@1: $ref: /schemas/graph.yaml#/properties/port description: | From a219062b9a87fd0a1591266413e62596d9bd8316 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:07 +0200 Subject: [PATCH 00491/11454] drm/bridge: tc358767: Change tc_ prefix to tc_edp_ for (e)DP specific functions These functions are specific to (e)DP output initialization and operation, add specific tc_edp_ prefix to those functions to discern them from DPI output functions that will be added later in this series. No functional change. Reviewed-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Sam Ravnborg Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-4-marex@denx.de --- drivers/gpu/drm/bridge/tc358767.c | 39 ++++++++++++++++--------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 7f9574b17caa..79691cd3b18c 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1164,7 +1164,7 @@ static int tc_main_link_disable(struct tc_data *tc) return regmap_write(tc->regmap, DP0CTL, 0); } -static int tc_stream_enable(struct tc_data *tc) +static int tc_edp_stream_enable(struct tc_data *tc) { int ret; u32 value; @@ -1219,7 +1219,7 @@ static int tc_stream_enable(struct tc_data *tc) return 0; } -static int tc_stream_disable(struct tc_data *tc) +static int tc_edp_stream_disable(struct tc_data *tc) { int ret; @@ -1234,7 +1234,7 @@ static int tc_stream_disable(struct tc_data *tc) return 0; } -static void tc_bridge_enable(struct drm_bridge *bridge) +static void tc_edp_bridge_enable(struct drm_bridge *bridge) { struct tc_data *tc = bridge_to_tc(bridge); int ret; @@ -1251,7 +1251,7 @@ static void tc_bridge_enable(struct drm_bridge *bridge) return; } - ret = tc_stream_enable(tc); + ret = tc_edp_stream_enable(tc); if (ret < 0) { dev_err(tc->dev, "main link stream start error: %d\n", ret); tc_main_link_disable(tc); @@ -1259,12 +1259,12 @@ static void tc_bridge_enable(struct drm_bridge *bridge) } } -static void tc_bridge_disable(struct drm_bridge *bridge) +static void tc_edp_bridge_disable(struct drm_bridge *bridge) { struct tc_data *tc = bridge_to_tc(bridge); int ret; - ret = tc_stream_disable(tc); + ret = tc_edp_stream_disable(tc); if (ret < 0) dev_err(tc->dev, "main link stream stop error: %d\n", ret); @@ -1285,9 +1285,10 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, return true; } -static enum drm_mode_status tc_mode_valid(struct drm_bridge *bridge, - const struct drm_display_info *info, - const struct drm_display_mode *mode) +static enum drm_mode_status +tc_edp_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) { struct tc_data *tc = bridge_to_tc(bridge); u32 req, avail; @@ -1395,8 +1396,8 @@ static const struct drm_connector_funcs tc_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; -static int tc_bridge_attach(struct drm_bridge *bridge, - enum drm_bridge_attach_flags flags) +static int tc_edp_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) { u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; struct tc_data *tc = bridge_to_tc(bridge); @@ -1448,18 +1449,18 @@ aux_unregister: return ret; } -static void tc_bridge_detach(struct drm_bridge *bridge) +static void tc_edp_bridge_detach(struct drm_bridge *bridge) { drm_dp_aux_unregister(&bridge_to_tc(bridge)->aux); } -static const struct drm_bridge_funcs tc_bridge_funcs = { - .attach = tc_bridge_attach, - .detach = tc_bridge_detach, - .mode_valid = tc_mode_valid, +static const struct drm_bridge_funcs tc_edp_bridge_funcs = { + .attach = tc_edp_bridge_attach, + .detach = tc_edp_bridge_detach, + .mode_valid = tc_edp_mode_valid, .mode_set = tc_bridge_mode_set, - .enable = tc_bridge_enable, - .disable = tc_bridge_disable, + .enable = tc_edp_bridge_enable, + .disable = tc_edp_bridge_disable, .mode_fixup = tc_bridge_mode_fixup, .detect = tc_bridge_detect, .get_edid = tc_get_edid, @@ -1696,7 +1697,7 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->aux.transfer = tc_aux_transfer; drm_dp_aux_init(&tc->aux); - tc->bridge.funcs = &tc_bridge_funcs; + tc->bridge.funcs = &tc_edp_bridge_funcs; if (tc->hpd_pin >= 0) tc->bridge.ops |= DRM_BRIDGE_OP_DETECT; tc->bridge.ops |= DRM_BRIDGE_OP_EDID; From f5be62394dec1d05ba662c2068b0e512c29e1c36 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:08 +0200 Subject: [PATCH 00492/11454] drm/bridge: tc358767: Convert to atomic ops Use the atomic version of the enable/disable operations to continue the transition to the atomic API. This will be needed to access the mode from the atomic state. Reviewed-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Sam Ravnborg Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-5-marex@denx.de --- drivers/gpu/drm/bridge/tc358767.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 79691cd3b18c..780fb94609f1 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1234,7 +1234,9 @@ static int tc_edp_stream_disable(struct tc_data *tc) return 0; } -static void tc_edp_bridge_enable(struct drm_bridge *bridge) +static void +tc_edp_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct tc_data *tc = bridge_to_tc(bridge); int ret; @@ -1259,7 +1261,9 @@ static void tc_edp_bridge_enable(struct drm_bridge *bridge) } } -static void tc_edp_bridge_disable(struct drm_bridge *bridge) +static void +tc_edp_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct tc_data *tc = bridge_to_tc(bridge); int ret; @@ -1459,11 +1463,14 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = { .detach = tc_edp_bridge_detach, .mode_valid = tc_edp_mode_valid, .mode_set = tc_bridge_mode_set, - .enable = tc_edp_bridge_enable, - .disable = tc_edp_bridge_disable, + .atomic_enable = tc_edp_bridge_atomic_enable, + .atomic_disable = tc_edp_bridge_atomic_disable, .mode_fixup = tc_bridge_mode_fixup, .detect = tc_bridge_detect, .get_edid = tc_get_edid, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, }; static bool tc_readable_reg(struct device *dev, unsigned int reg) From 65fdbb714d7f5764b6571b86f0617782cbe28ab1 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:09 +0200 Subject: [PATCH 00493/11454] drm/bridge: tc358767: Implement atomic_check callback Implement .atomic_check callback which prevents user space from setting unsupported mode. The tc_edp_common_atomic_check() variant is already prepared for DSI-to-DPI mode addition, which has different frequency limits. Reviewed-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Sam Ravnborg Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-6-marex@denx.de --- drivers/gpu/drm/bridge/tc358767.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 780fb94609f1..59cba91554b4 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1289,6 +1289,31 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge, return true; } +static int tc_common_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + const unsigned int max_khz) +{ + tc_bridge_mode_fixup(bridge, &crtc_state->mode, + &crtc_state->adjusted_mode); + + if (crtc_state->adjusted_mode.clock > max_khz) + return -EINVAL; + + return 0; +} + +static int tc_edp_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + /* DPI->(e)DP interface clock limitation: upto 154 MHz */ + return tc_common_atomic_check(bridge, bridge_state, crtc_state, + conn_state, 154000); +} + static enum drm_mode_status tc_edp_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, @@ -1463,6 +1488,7 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = { .detach = tc_edp_bridge_detach, .mode_valid = tc_edp_mode_valid, .mode_set = tc_bridge_mode_set, + .atomic_check = tc_edp_atomic_check, .atomic_enable = tc_edp_bridge_atomic_enable, .atomic_disable = tc_edp_bridge_atomic_disable, .mode_fixup = tc_bridge_mode_fixup, From 8478095a8c4bcea3c83b0767d6c9127434160761 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:10 +0200 Subject: [PATCH 00494/11454] drm/bridge: tc358767: Move (e)DP bridge endpoint parsing into dedicated function The TC358767/TC358867/TC9595 are all capable of operating in multiple modes, DPI-to-(e)DP, DSI-to-(e)DP, DSI-to-DPI. Only the first mode is currently supported. In order to support the rest of the modes without making the tc_probe() overly long, split the bridge endpoint parsing into dedicated function, where the necessary logic to detect the bridge mode based on which endpoints are connected, can be implemented. Reviewed-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Sam Ravnborg Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-7-marex@denx.de --- drivers/gpu/drm/bridge/tc358767.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 59cba91554b4..1a7755396282 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1583,19 +1583,12 @@ static irqreturn_t tc_irq_handler(int irq, void *arg) return IRQ_HANDLED; } -static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) +static int tc_probe_edp_bridge_endpoint(struct tc_data *tc) { - struct device *dev = &client->dev; + struct device *dev = tc->dev; struct drm_panel *panel; - struct tc_data *tc; int ret; - tc = devm_kzalloc(dev, sizeof(*tc), GFP_KERNEL); - if (!tc) - return -ENOMEM; - - tc->dev = dev; - /* port@2 is the output port */ ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, NULL); if (ret && ret != -ENODEV) @@ -1614,6 +1607,25 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; } + return ret; +} + +static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct tc_data *tc; + int ret; + + tc = devm_kzalloc(dev, sizeof(*tc), GFP_KERNEL); + if (!tc) + return -ENOMEM; + + tc->dev = dev; + + ret = tc_probe_edp_bridge_endpoint(tc); + if (ret) + return ret; + /* Shut down GPIO is optional */ tc->sd_gpio = devm_gpiod_get_optional(dev, "shutdown", GPIOD_OUT_HIGH); if (IS_ERR(tc->sd_gpio)) From 824c7bb46c9c2b5fbdc910425357fe863db93c26 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:11 +0200 Subject: [PATCH 00495/11454] drm/bridge: tc358767: Wrap (e)DP aux I2C registration into tc_aux_link_setup() This bit of code is (e)DP and aux I2C link specific, move it into tc_aux_link_setup() to permit cleaner addition of DSI-to-DPI mode. No functional change. Reviewed-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Sam Ravnborg Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-8-marex@denx.de --- drivers/gpu/drm/bridge/tc358767.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 1a7755396282..1f4b962502c7 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -656,6 +656,12 @@ static int tc_aux_link_setup(struct tc_data *tc) if (ret) goto err; + /* Register DP AUX channel */ + tc->aux.name = "TC358767 AUX i2c adapter"; + tc->aux.dev = tc->dev; + tc->aux.transfer = tc_aux_transfer; + drm_dp_aux_init(&tc->aux); + return 0; err: dev_err(tc->dev, "tc_aux_link_setup failed: %d\n", ret); @@ -1736,12 +1742,6 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) if (ret) return ret; - /* Register DP AUX channel */ - tc->aux.name = "TC358767 AUX i2c adapter"; - tc->aux.dev = tc->dev; - tc->aux.transfer = tc_aux_transfer; - drm_dp_aux_init(&tc->aux); - tc->bridge.funcs = &tc_edp_bridge_funcs; if (tc->hpd_pin >= 0) tc->bridge.ops |= DRM_BRIDGE_OP_DETECT; From dd1fd5ab7cd6dca15af6553b936a08cfc354e406 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:12 +0200 Subject: [PATCH 00496/11454] drm/bridge: tc358767: Move bridge ops setup into tc_probe_edp_bridge_endpoint() The bridge ops are specific to the bridge configuration, move them into tc_probe_edp_bridge_endpoint() to permit cleaner addition of DSI-to-DPI mode. No functional change. Reviewed-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Sam Ravnborg Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-9-marex@denx.de --- drivers/gpu/drm/bridge/tc358767.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 1f4b962502c7..470f3e9c76fc 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1613,6 +1613,11 @@ static int tc_probe_edp_bridge_endpoint(struct tc_data *tc) tc->bridge.type = DRM_MODE_CONNECTOR_DisplayPort; } + tc->bridge.funcs = &tc_edp_bridge_funcs; + if (tc->hpd_pin >= 0) + tc->bridge.ops |= DRM_BRIDGE_OP_DETECT; + tc->bridge.ops |= DRM_BRIDGE_OP_EDID; + return ret; } @@ -1742,11 +1747,6 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) if (ret) return ret; - tc->bridge.funcs = &tc_edp_bridge_funcs; - if (tc->hpd_pin >= 0) - tc->bridge.ops |= DRM_BRIDGE_OP_DETECT; - tc->bridge.ops |= DRM_BRIDGE_OP_EDID; - tc->bridge.of_node = dev->of_node; drm_bridge_add(&tc->bridge); From 71f7d9c03118fc98c487e7ecd3a039da9c1cc513 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:13 +0200 Subject: [PATCH 00497/11454] drm/bridge: tc358767: Detect bridge mode from connected endpoints in DT The TC358767/TC358867/TC9595 are all capable of operating in multiple modes, DPI-to-(e)DP, DSI-to-(e)DP, DSI-to-DPI. Only the first mode is currently supported. It is possible to find out the mode in which the bridge should be operated by testing connected endpoints in DT. Port allocation: port@0 - DSI input port@1 - DPI input/output port@2 - eDP output Possible connections: DPI -> port@1 -> port@2 -> eDP :: [port@0 is not connected] DSI -> port@0 -> port@2 -> eDP :: [port@1 is not connected] DSI -> port@0 -> port@1 -> DPI :: [port@2 is not connected] Add function to determine the bridge mode based on connected endpoints. Reviewed-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Sam Ravnborg Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-10-marex@denx.de --- drivers/gpu/drm/bridge/tc358767.c | 46 ++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 470f3e9c76fc..074efe24ac61 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1621,6 +1621,50 @@ static int tc_probe_edp_bridge_endpoint(struct tc_data *tc) return ret; } +static int tc_probe_bridge_endpoint(struct tc_data *tc) +{ + struct device *dev = tc->dev; + struct of_endpoint endpoint; + struct device_node *node = NULL; + const u8 mode_dpi_to_edp = BIT(1) | BIT(2); + const u8 mode_dsi_to_edp = BIT(0) | BIT(2); + const u8 mode_dsi_to_dpi = BIT(0) | BIT(1); + u8 mode = 0; + + /* + * Determine bridge configuration. + * + * Port allocation: + * port@0 - DSI input + * port@1 - DPI input/output + * port@2 - eDP output + * + * Possible connections: + * DPI -> port@1 -> port@2 -> eDP :: [port@0 is not connected] + * DSI -> port@0 -> port@2 -> eDP :: [port@1 is not connected] + * DSI -> port@0 -> port@1 -> DPI :: [port@2 is not connected] + */ + + for_each_endpoint_of_node(dev->of_node, node) { + of_graph_parse_endpoint(node, &endpoint); + if (endpoint.port > 2) + return -EINVAL; + + mode |= BIT(endpoint.port); + } + + if (mode == mode_dpi_to_edp) + return tc_probe_edp_bridge_endpoint(tc); + else if (mode == mode_dsi_to_dpi) + dev_warn(dev, "The mode DSI-to-DPI is not supported!\n"); + else if (mode == mode_dsi_to_edp) + dev_warn(dev, "The mode DSI-to-(e)DP is not supported!\n"); + else + dev_warn(dev, "Invalid mode (0x%x) is not supported!\n", mode); + + return -EINVAL; +} + static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; @@ -1633,7 +1677,7 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->dev = dev; - ret = tc_probe_edp_bridge_endpoint(tc); + ret = tc_probe_bridge_endpoint(tc); if (ret) return ret; From aebe58a7af42d2126dc8ca39825cb5a624649115 Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:14 +0200 Subject: [PATCH 00498/11454] drm/bridge: tc358767: Split tc_set_video_mode() into common and (e)DP part The tc_set_video_mode() sets up both common and (e)DP video mode settings of the bridge chip. Split the function into tc_set_common_video_mode() to set the common settings and tc_set_edp_video_mode() to set the (e)DP specific settings. No functional change. Reviewed-by: Lucas Stach Tested-by: Lucas Stach # In both DPI to eDP and DSI to DPI mode. Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Sam Ravnborg Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-11-marex@denx.de --- drivers/gpu/drm/bridge/tc358767.c | 65 ++++++++++++++++++------------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 074efe24ac61..ba4e75c22030 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -734,33 +734,16 @@ err_dpcd_read: return ret; } -static int tc_set_video_mode(struct tc_data *tc, - const struct drm_display_mode *mode) +static int tc_set_common_video_mode(struct tc_data *tc, + const struct drm_display_mode *mode) { - int ret; - int vid_sync_dly; - int max_tu_symbol; - int left_margin = mode->htotal - mode->hsync_end; int right_margin = mode->hsync_start - mode->hdisplay; int hsync_len = mode->hsync_end - mode->hsync_start; int upper_margin = mode->vtotal - mode->vsync_end; int lower_margin = mode->vsync_start - mode->vdisplay; int vsync_len = mode->vsync_end - mode->vsync_start; - u32 dp0_syncval; - u32 bits_per_pixel = 24; - u32 in_bw, out_bw; - - /* - * Recommended maximum number of symbols transferred in a transfer unit: - * DIV_ROUND_UP((input active video bandwidth in bytes) * tu_size, - * (output active video bandwidth in bytes)) - * Must be less than tu_size. - */ - - in_bw = mode->clock * bits_per_pixel / 8; - out_bw = tc->link.num_lanes * tc->link.rate; - max_tu_symbol = DIV_ROUND_UP(in_bw * TU_SIZE_RECOMMENDED, out_bw); + int ret; dev_dbg(tc->dev, "set mode %dx%d\n", mode->hdisplay, mode->vdisplay); @@ -818,8 +801,35 @@ static int tc_set_video_mode(struct tc_data *tc, FIELD_PREP(COLOR_B, 99) | ENI2CFILTER | FIELD_PREP(COLOR_BAR_MODE, COLOR_BAR_MODE_BARS)); - if (ret) - return ret; + + return ret; +} + +static int tc_set_edp_video_mode(struct tc_data *tc, + const struct drm_display_mode *mode) +{ + int ret; + int vid_sync_dly; + int max_tu_symbol; + + int left_margin = mode->htotal - mode->hsync_end; + int hsync_len = mode->hsync_end - mode->hsync_start; + int upper_margin = mode->vtotal - mode->vsync_end; + int vsync_len = mode->vsync_end - mode->vsync_start; + u32 dp0_syncval; + u32 bits_per_pixel = 24; + u32 in_bw, out_bw; + + /* + * Recommended maximum number of symbols transferred in a transfer unit: + * DIV_ROUND_UP((input active video bandwidth in bytes) * tu_size, + * (output active video bandwidth in bytes)) + * Must be less than tu_size. + */ + + in_bw = mode->clock * bits_per_pixel / 8; + out_bw = tc->link.num_lanes * tc->link.rate; + max_tu_symbol = DIV_ROUND_UP(in_bw * TU_SIZE_RECOMMENDED, out_bw); /* DP Main Stream Attributes */ vid_sync_dly = hsync_len + left_margin + mode->hdisplay; @@ -869,10 +879,7 @@ static int tc_set_video_mode(struct tc_data *tc, FIELD_PREP(MAX_TU_SYMBOL, max_tu_symbol) | FIELD_PREP(TU_SIZE, TU_SIZE_RECOMMENDED) | BPC_8); - if (ret) - return ret; - - return 0; + return ret; } static int tc_wait_link_training(struct tc_data *tc) @@ -1185,7 +1192,11 @@ static int tc_edp_stream_enable(struct tc_data *tc) return ret; } - ret = tc_set_video_mode(tc, &tc->mode); + ret = tc_set_common_video_mode(tc, &tc->mode); + if (ret) + return ret; + + ret = tc_set_edp_video_mode(tc, &tc->mode); if (ret) return ret; From bbfd3190b65629117ae1535499e3de9791499ddc Mon Sep 17 00:00:00 2001 From: Marek Vasut Date: Tue, 29 Mar 2022 10:50:15 +0200 Subject: [PATCH 00499/11454] drm/bridge: tc358767: Add DSI-to-DPI mode support The TC358767/TC358867/TC9595 are all capable of operating in multiple modes, DPI-to-(e)DP, DSI-to-(e)DP, DSI-to-DPI. Add support for the DSI-to-DPI mode. This requires skipping most of the (e)DP initialization code, which is currently a large part of this driver, hence it is better to have far simpler separate tc_dpi_bridge_funcs and their implementation. The configuration of DPI output is also much simpler. The configuration of the DSI input is rather similar to the other TC bridge chips. The Pixel PLL in DPI output mode does not have the 65..150 MHz limitation imposed on the (e)DP output mode, so this limitation is skipped to permit operating panels with far slower pixel clock, even below 9 MHz. This mode of operation of the PLL is valid and tested. The detection of bridge mode is now added into tc_probe_bridge_mode(), where in case a DPI panel is found on port@1 endpoint@1, the mode is assumed to be DSI-to-DPI. If (e)DP is detected on port@2, the mode is assumed to be DPI-to-(e)DP. The DSI-to-(e)DP mode is not supported due to lack of proper hardware, but this would be some sort of mix between the two aforementioned modes. Reviewed-by: Lucas Stach Signed-off-by: Marek Vasut Cc: Jonas Karlman Cc: Laurent Pinchart Cc: Maxime Ripard Cc: Neil Armstrong Cc: Sam Ravnborg Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220329085015.39159-12-marex@denx.de --- drivers/gpu/drm/bridge/Kconfig | 1 + drivers/gpu/drm/bridge/tc358767.c | 358 +++++++++++++++++++++++++++++- 2 files changed, 348 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index 1b8721a7a6df..e4cbf31797c5 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -267,6 +267,7 @@ config DRM_TOSHIBA_TC358767 select DRM_DP_HELPER select DRM_KMS_HELPER select REGMAP_I2C + select DRM_MIPI_DSI select DRM_PANEL help Toshiba TC358767 eDP bridge chip driver. diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index ba4e75c22030..12355daf45ef 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -1,6 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * tc358767 eDP bridge driver + * TC358767/TC358867/TC9595 DSI/DPI-to-DPI/(e)DP bridge driver + * + * The TC358767/TC358867/TC9595 can operate in multiple modes. + * The following modes are supported: + * DPI->(e)DP -- supported + * DSI->DPI .... supported + * DSI->(e)DP .. NOT supported * * Copyright (C) 2016 CogentEmbedded Inc * Author: Andrey Gusakov @@ -29,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -36,7 +43,35 @@ /* Registers */ -/* Display Parallel Interface */ +/* PPI layer registers */ +#define PPI_STARTPPI 0x0104 /* START control bit */ +#define PPI_LPTXTIMECNT 0x0114 /* LPTX timing signal */ +#define LPX_PERIOD 3 +#define PPI_LANEENABLE 0x0134 +#define PPI_TX_RX_TA 0x013c +#define TTA_GET 0x40000 +#define TTA_SURE 6 +#define PPI_D0S_ATMR 0x0144 +#define PPI_D1S_ATMR 0x0148 +#define PPI_D0S_CLRSIPOCOUNT 0x0164 /* Assertion timer for Lane 0 */ +#define PPI_D1S_CLRSIPOCOUNT 0x0168 /* Assertion timer for Lane 1 */ +#define PPI_D2S_CLRSIPOCOUNT 0x016c /* Assertion timer for Lane 2 */ +#define PPI_D3S_CLRSIPOCOUNT 0x0170 /* Assertion timer for Lane 3 */ +#define PPI_START_FUNCTION BIT(0) + +/* DSI layer registers */ +#define DSI_STARTDSI 0x0204 /* START control bit of DSI-TX */ +#define DSI_LANEENABLE 0x0210 /* Enables each lane */ +#define DSI_RX_START BIT(0) + +/* Lane enable PPI and DSI register bits */ +#define LANEENABLE_CLEN BIT(0) +#define LANEENABLE_L0EN BIT(1) +#define LANEENABLE_L1EN BIT(2) +#define LANEENABLE_L2EN BIT(1) +#define LANEENABLE_L3EN BIT(2) + +/* Display Parallel Input Interface */ #define DPIPXLFMT 0x0440 #define VS_POL_ACTIVE_LOW (1 << 10) #define HS_POL_ACTIVE_LOW (1 << 9) @@ -48,6 +83,14 @@ #define DPI_BPP_RGB666 (1 << 0) #define DPI_BPP_RGB565 (2 << 0) +/* Display Parallel Output Interface */ +#define POCTRL 0x0448 +#define POCTRL_S2P BIT(7) +#define POCTRL_PCLK_POL BIT(3) +#define POCTRL_VS_POL BIT(2) +#define POCTRL_HS_POL BIT(1) +#define POCTRL_DE_POL BIT(0) + /* Video Path */ #define VPCTRL0 0x0450 #define VSDELAY GENMASK(31, 20) @@ -247,6 +290,9 @@ struct tc_data { struct drm_bridge *panel_bridge; struct drm_connector connector; + struct mipi_dsi_device *dsi; + u8 dsi_lanes; + /* link settings */ struct tc_edp_link link; @@ -469,10 +515,24 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) int mul, best_mul = 1; int delta, best_delta; int ext_div[] = {1, 2, 3, 5, 7}; + int clk_min, clk_max; int best_pixelclock = 0; int vco_hi = 0; u32 pxl_pllparam; + /* + * refclk * mul / (ext_pre_div * pre_div) should be in range: + * - DPI ..... 0 to 100 MHz + * - (e)DP ... 150 to 650 MHz + */ + if (tc->bridge.type == DRM_MODE_CONNECTOR_DPI) { + clk_min = 0; + clk_max = 100000000; + } else { + clk_min = 150000000; + clk_max = 650000000; + } + dev_dbg(tc->dev, "PLL: requested %d pixelclock, ref %d\n", pixelclock, refclk); best_delta = pixelclock; @@ -499,11 +559,7 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) continue; clk = (refclk / ext_div[i_pre] / div) * mul; - /* - * refclk * mul / (ext_pre_div * pre_div) - * should be in the 150 to 650 MHz range - */ - if ((clk > 650000000) || (clk < 150000000)) + if ((clk > clk_max) || (clk < clk_min)) continue; clk = clk / ext_div[i_post]; @@ -805,6 +861,20 @@ static int tc_set_common_video_mode(struct tc_data *tc, return ret; } +static int tc_set_dpi_video_mode(struct tc_data *tc, + const struct drm_display_mode *mode) +{ + u32 value = POCTRL_S2P; + + if (tc->mode.flags & DRM_MODE_FLAG_NHSYNC) + value |= POCTRL_HS_POL; + + if (tc->mode.flags & DRM_MODE_FLAG_NVSYNC) + value |= POCTRL_VS_POL; + + return regmap_write(tc->regmap, POCTRL, value); +} + static int tc_set_edp_video_mode(struct tc_data *tc, const struct drm_display_mode *mode) { @@ -1177,6 +1247,85 @@ static int tc_main_link_disable(struct tc_data *tc) return regmap_write(tc->regmap, DP0CTL, 0); } +static int tc_dpi_stream_enable(struct tc_data *tc) +{ + int ret; + u32 value; + + dev_dbg(tc->dev, "enable video stream\n"); + + /* Setup PLL */ + ret = tc_set_syspllparam(tc); + if (ret) + return ret; + + /* + * Initially PLLs are in bypass. Force PLL parameter update, + * disable PLL bypass, enable PLL + */ + ret = tc_pllupdate(tc, DP0_PLLCTRL); + if (ret) + return ret; + + ret = tc_pllupdate(tc, DP1_PLLCTRL); + if (ret) + return ret; + + /* Pixel PLL must always be enabled for DPI mode */ + ret = tc_pxl_pll_en(tc, clk_get_rate(tc->refclk), + 1000 * tc->mode.clock); + if (ret) + return ret; + + regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 3); + regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 3); + regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 3); + regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 3); + regmap_write(tc->regmap, PPI_D0S_ATMR, 0); + regmap_write(tc->regmap, PPI_D1S_ATMR, 0); + regmap_write(tc->regmap, PPI_TX_RX_TA, TTA_GET | TTA_SURE); + regmap_write(tc->regmap, PPI_LPTXTIMECNT, LPX_PERIOD); + + value = ((LANEENABLE_L0EN << tc->dsi_lanes) - LANEENABLE_L0EN) | + LANEENABLE_CLEN; + regmap_write(tc->regmap, PPI_LANEENABLE, value); + regmap_write(tc->regmap, DSI_LANEENABLE, value); + + ret = tc_set_common_video_mode(tc, &tc->mode); + if (ret) + return ret; + + ret = tc_set_dpi_video_mode(tc, &tc->mode); + if (ret) + return ret; + + /* Set input interface */ + value = DP0_AUDSRC_NO_INPUT; + if (tc_test_pattern) + value |= DP0_VIDSRC_COLOR_BAR; + else + value |= DP0_VIDSRC_DSI_RX; + ret = regmap_write(tc->regmap, SYSCTRL, value); + if (ret) + return ret; + + usleep_range(120, 150); + + regmap_write(tc->regmap, PPI_STARTPPI, PPI_START_FUNCTION); + regmap_write(tc->regmap, DSI_STARTDSI, DSI_RX_START); + + return 0; +} + +static int tc_dpi_stream_disable(struct tc_data *tc) +{ + dev_dbg(tc->dev, "disable video stream\n"); + + tc_pxl_pll_dis(tc); + + return 0; +} + static int tc_edp_stream_enable(struct tc_data *tc) { int ret; @@ -1251,6 +1400,34 @@ static int tc_edp_stream_disable(struct tc_data *tc) return 0; } +static void +tc_dpi_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) + +{ + struct tc_data *tc = bridge_to_tc(bridge); + int ret; + + ret = tc_dpi_stream_enable(tc); + if (ret < 0) { + dev_err(tc->dev, "main link stream start error: %d\n", ret); + tc_main_link_disable(tc); + return; + } +} + +static void +tc_dpi_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) +{ + struct tc_data *tc = bridge_to_tc(bridge); + int ret; + + ret = tc_dpi_stream_disable(tc); + if (ret < 0) + dev_err(tc->dev, "main link stream stop error: %d\n", ret); +} + static void tc_edp_bridge_atomic_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) @@ -1321,6 +1498,16 @@ static int tc_common_atomic_check(struct drm_bridge *bridge, return 0; } +static int tc_dpi_atomic_check(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state) +{ + /* DSI->DPI interface clock limitation: upto 100 MHz */ + return tc_common_atomic_check(bridge, bridge_state, crtc_state, + conn_state, 100000); +} + static int tc_edp_atomic_check(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, @@ -1331,6 +1518,18 @@ static int tc_edp_atomic_check(struct drm_bridge *bridge, conn_state, 154000); } +static enum drm_mode_status +tc_dpi_mode_valid(struct drm_bridge *bridge, + const struct drm_display_info *info, + const struct drm_display_mode *mode) +{ + /* DPI interface clock limitation: upto 100 MHz */ + if (mode->clock > 100000) + return MODE_CLOCK_HIGH; + + return MODE_OK; +} + static enum drm_mode_status tc_edp_mode_valid(struct drm_bridge *bridge, const struct drm_display_info *info, @@ -1442,6 +1641,18 @@ static const struct drm_connector_funcs tc_connector_funcs = { .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, }; +static int tc_dpi_bridge_attach(struct drm_bridge *bridge, + enum drm_bridge_attach_flags flags) +{ + struct tc_data *tc = bridge_to_tc(bridge); + + if (!tc->panel_bridge) + return 0; + + return drm_bridge_attach(tc->bridge.encoder, tc->panel_bridge, + &tc->bridge, flags); +} + static int tc_edp_bridge_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags) { @@ -1500,6 +1711,45 @@ static void tc_edp_bridge_detach(struct drm_bridge *bridge) drm_dp_aux_unregister(&bridge_to_tc(bridge)->aux); } +#define MAX_INPUT_SEL_FORMATS 1 + +static u32 * +tc_dpi_atomic_get_input_bus_fmts(struct drm_bridge *bridge, + struct drm_bridge_state *bridge_state, + struct drm_crtc_state *crtc_state, + struct drm_connector_state *conn_state, + u32 output_fmt, + unsigned int *num_input_fmts) +{ + u32 *input_fmts; + + *num_input_fmts = 0; + + input_fmts = kcalloc(MAX_INPUT_SEL_FORMATS, sizeof(*input_fmts), + GFP_KERNEL); + if (!input_fmts) + return NULL; + + /* This is the DSI-end bus format */ + input_fmts[0] = MEDIA_BUS_FMT_RGB888_1X24; + *num_input_fmts = 1; + + return input_fmts; +} + +static const struct drm_bridge_funcs tc_dpi_bridge_funcs = { + .attach = tc_dpi_bridge_attach, + .mode_valid = tc_dpi_mode_valid, + .mode_set = tc_bridge_mode_set, + .atomic_check = tc_dpi_atomic_check, + .atomic_enable = tc_dpi_bridge_atomic_enable, + .atomic_disable = tc_dpi_bridge_atomic_disable, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + .atomic_get_input_bus_fmts = tc_dpi_atomic_get_input_bus_fmts, +}; + static const struct drm_bridge_funcs tc_edp_bridge_funcs = { .attach = tc_edp_bridge_attach, .detach = tc_edp_bridge_detach, @@ -1600,6 +1850,82 @@ static irqreturn_t tc_irq_handler(int irq, void *arg) return IRQ_HANDLED; } +static int tc_mipi_dsi_host_attach(struct tc_data *tc) +{ + struct device *dev = tc->dev; + struct device_node *host_node; + struct device_node *endpoint; + struct mipi_dsi_device *dsi; + struct mipi_dsi_host *host; + const struct mipi_dsi_device_info info = { + .type = "tc358767", + .channel = 0, + .node = NULL, + }; + int dsi_lanes, ret; + + endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 0, -1); + dsi_lanes = of_property_count_u32_elems(endpoint, "data-lanes"); + host_node = of_graph_get_remote_port_parent(endpoint); + host = of_find_mipi_dsi_host_by_node(host_node); + of_node_put(host_node); + of_node_put(endpoint); + + if (dsi_lanes < 0 || dsi_lanes > 4) + return -EINVAL; + + if (!host) + return -EPROBE_DEFER; + + dsi = mipi_dsi_device_register_full(host, &info); + if (IS_ERR(dsi)) + return dev_err_probe(dev, PTR_ERR(dsi), + "failed to create dsi device\n"); + + tc->dsi = dsi; + + tc->dsi_lanes = dsi_lanes; + dsi->lanes = tc->dsi_lanes; + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + + ret = mipi_dsi_attach(dsi); + if (ret < 0) { + dev_err(dev, "failed to attach dsi to host: %d\n", ret); + return ret; + } + + return 0; +} + +static int tc_probe_dpi_bridge_endpoint(struct tc_data *tc) +{ + struct device *dev = tc->dev; + struct drm_panel *panel; + int ret; + + /* port@1 is the DPI input/output port */ + ret = drm_of_find_panel_or_bridge(dev->of_node, 1, 0, &panel, NULL); + if (ret && ret != -ENODEV) + return ret; + + if (panel) { + struct drm_bridge *panel_bridge; + + panel_bridge = devm_drm_panel_bridge_add(dev, panel); + if (IS_ERR(panel_bridge)) + return PTR_ERR(panel_bridge); + + tc->panel_bridge = panel_bridge; + tc->bridge.type = DRM_MODE_CONNECTOR_DPI; + tc->bridge.funcs = &tc_dpi_bridge_funcs; + + return 0; + } + + return ret; +} + static int tc_probe_edp_bridge_endpoint(struct tc_data *tc) { struct device *dev = tc->dev; @@ -1667,7 +1993,7 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc) if (mode == mode_dpi_to_edp) return tc_probe_edp_bridge_endpoint(tc); else if (mode == mode_dsi_to_dpi) - dev_warn(dev, "The mode DSI-to-DPI is not supported!\n"); + return tc_probe_dpi_bridge_endpoint(tc); else if (mode == mode_dsi_to_edp) dev_warn(dev, "The mode DSI-to-(e)DP is not supported!\n"); else @@ -1798,15 +2124,25 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) } } - ret = tc_aux_link_setup(tc); - if (ret) - return ret; + if (tc->bridge.type != DRM_MODE_CONNECTOR_DPI) { /* (e)DP output */ + ret = tc_aux_link_setup(tc); + if (ret) + return ret; + } tc->bridge.of_node = dev->of_node; drm_bridge_add(&tc->bridge); i2c_set_clientdata(client, tc); + if (tc->bridge.type == DRM_MODE_CONNECTOR_DPI) { /* DPI output */ + ret = tc_mipi_dsi_host_attach(tc); + if (ret) { + drm_bridge_remove(&tc->bridge); + return ret; + } + } + return 0; } From b2831dd4be4e98c6f62976a821d7e852f0c9c08b Mon Sep 17 00:00:00 2001 From: Jagan Teki Date: Thu, 3 Mar 2022 22:06:49 +0530 Subject: [PATCH 00500/11454] drm: bridge: tc358764: Use drm panel_bridge API Replace the manual panel handling code by a drm panel_bridge via devm_drm_of_get_bridge(). Adding panel_bridge handling, - Drops drm_connector and related operations as drm_bridge_attach creates connector during attachment. - Drops panel pointer and panel healpers. This simplifies the driver and allows all components in the display pipeline to be treated as bridges. Signed-off-by: Jagan Teki Acked-by: Marek Szyprowski Tested-by: Marek Szyprowski Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20220303163654.3381470-2-jagan@amarulasolutions.com --- drivers/gpu/drm/bridge/tc358764.c | 104 ++---------------------------- 1 file changed, 6 insertions(+), 98 deletions(-) diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index c1e35bdf9232..dca41ed32f8a 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -16,14 +16,9 @@ #include