From mauricex.r.petallo at intel.com Tue Jul 22 12:04:24 2014 From: mauricex.r.petallo at intel.com (Petallo, MauriceX R) Date: Tue, 22 Jul 2014 12:04:24 +0000 Subject: [LTSI-dev] Preset Value disabling and DDR50 mode enabling for BayTrail eMMC in 3.10-LTSI Message-ID: Hi Greg-KH, Please consider to pull-in the following commits which are currently (still) in linux-next to LTSI kernel 3.10: d61b59461b0cd0106f03e566d537b9072029e059 mmc: sdhci: Preset value not supported in Baytrail eMMC f25c33724d1512a72554c0ad4cb70b43ba15374e mmc: sdhci: add DDR50 1.8V mode support for BayTrail eMMC Controller These patches are required for Intel Baytrail Platform to: (1) Declare SDHCI_QUIRK2_PRESET_VALUE_BROKEN for PCI mode and ACPI mode Baytrail eMMC controller as it doesn't support Preset Value feature. (2) Enable DDR50 1.8V mode support for PCI and ACPI mode BayTrail eMMC controller I cherry-picked these patches from linux-next and it apply smoothly with LTSI kernel 3.10. With these patches, the kernel builds successfully and boots on Intel Baytrail Platforms. Tests are also conducted from our end. Thanks and best regards, Maurice Petallo From dhobsong at igel.co.jp Thu Jul 31 03:26:34 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:34 +0900 Subject: [LTSI-dev] [PATCH 00/16] Backport of additional SMACK features for Tizen 3.0 Message-ID: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> This patch series adds some SMACK features/fixes that are used by the Tizen 3.0 security policy. All of these patches have been backported from the mainline kernel. The most recent is from v3.16-rc1. Casey Schaufler (8): Smack: Local IPv6 port based controls Smack: Improve access check performance Smack: Add smkfstransmute mount option Smack: network label match fix Smack: IPv6 casting error fix for 3.11 Smack: Implement lock security mode Smack: Ptrace access check mode Smack: Label cgroup files for systemd David Quigley (1): Security: Add Hook to test if the particular xattr is part of a MAC model. Passion,Zhao (1): Smack: Fix the bug smackcipso can't set CIPSO correctly Rafal Krypa (1): Smack: parse multiple rules per write to load2, up to PAGE_SIZE-1 bytes Tetsuo Handa (3): Smack: Fix possible NULL pointer dereference at smk_netlbl_mls() xattr: Constify ->name member of "struct xattr". ocfs2: fix panic on kfree(xattr->name) Tomasz Stanislawski (2): security: smack: fix memleak in smk_write_rules_list() security: smack: add a hash table to quicken smk_find_entry() fs/ocfs2/namei.c | 2 - fs/ocfs2/xattr.h | 2 +- include/linux/security.h | 22 +- include/linux/xattr.h | 2 +- include/uapi/linux/reiserfs_xattr.h | 2 +- security/capability.c | 8 +- security/integrity/evm/evm_main.c | 2 +- security/security.c | 14 +- security/selinux/hooks.c | 23 +- security/smack/smack.h | 135 +++--- security/smack/smack_access.c | 82 ++-- security/smack/smack_lsm.c | 781 +++++++++++++++++++++++++---------- security/smack/smackfs.c | 239 ++++++----- 13 files changed, 870 insertions(+), 444 deletions(-) -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:35 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:35 +0900 Subject: [LTSI-dev] [PATCH 01/16] Smack: Local IPv6 port based controls In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-2-git-send-email-dhobsong@igel.co.jp> From: Casey Schaufler Smack does not provide access controls on IPv6 communications. This patch introduces a mechanism for maintaining Smack lables for local IPv6 communications. It is based on labeling local ports. The behavior should be compatible with any future "real" IPv6 support as it provides no interfaces for users to manipulate the labeling. Remote IPv6 connections use the ambient label the same way that unlabeled IPv4 packets are treated. Targeted for git://git.gitorious.org/smack-next/kernel.git Signed-off-by: Casey Schaufler (cherry picked from commit c673944347edfd4362b10eea11ac384a582b1cf5) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smack.h | 11 ++ security/smack/smack_lsm.c | 348 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 319 insertions(+), 40 deletions(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index 8ad3095..bb28e09 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -94,6 +94,17 @@ struct smk_netlbladdr { }; /* + * An entry in the table identifying ports. + */ +struct smk_port_label { + struct list_head list; + struct sock *smk_sock; /* socket initialized on */ + unsigned short smk_port; /* the port number */ + char *smk_in; /* incoming label */ + char *smk_out; /* outgoing label */ +}; + +/* * This is the repository for labels seen so that it is * not necessary to keep allocating tiny chuncks of memory * and so that they can be shared. diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index d52c780..609e89d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -27,10 +27,13 @@ #include #include #include +#include #include #include #include #include +#include +#include #include #include #include @@ -45,6 +48,12 @@ #define TRANS_TRUE "TRUE" #define TRANS_TRUE_SIZE 4 +#define SMK_CONNECTING 0 +#define SMK_RECEIVING 1 +#define SMK_SENDING 2 + +LIST_HEAD(smk_ipv6_port_list); + /** * smk_fetch - Fetch the smack label from a file. * @ip: a pointer to the inode @@ -1878,6 +1887,155 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) } /** + * smk_ipv6_port_label - Smack port access table management + * @sock: socket + * @address: address + * + * Create or update the port list entry + */ +static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address) +{ + struct sock *sk = sock->sk; + struct sockaddr_in6 *addr6; + struct socket_smack *ssp = sock->sk->sk_security; + struct smk_port_label *spp; + unsigned short port = 0; + + if (address == NULL) { + /* + * This operation is changing the Smack information + * on the bound socket. Take the changes to the port + * as well. + */ + list_for_each_entry(spp, &smk_ipv6_port_list, list) { + if (sk != spp->smk_sock) + continue; + spp->smk_in = ssp->smk_in; + spp->smk_out = ssp->smk_out; + return; + } + /* + * A NULL address is only used for updating existing + * bound entries. If there isn't one, it's OK. + */ + return; + } + + addr6 = (struct sockaddr_in6 *)address; + port = ntohs(addr6->sin6_port); + /* + * This is a special case that is safely ignored. + */ + if (port == 0) + return; + + /* + * Look for an existing port list entry. + * This is an indication that a port is getting reused. + */ + list_for_each_entry(spp, &smk_ipv6_port_list, list) { + if (spp->smk_port != port) + continue; + spp->smk_port = port; + spp->smk_sock = sk; + spp->smk_in = ssp->smk_in; + spp->smk_out = ssp->smk_out; + return; + } + + /* + * A new port entry is required. + */ + spp = kzalloc(sizeof(*spp), GFP_KERNEL); + if (spp == NULL) + return; + + spp->smk_port = port; + spp->smk_sock = sk; + spp->smk_in = ssp->smk_in; + spp->smk_out = ssp->smk_out; + + list_add(&spp->list, &smk_ipv6_port_list); + return; +} + +/** + * smk_ipv6_port_check - check Smack port access + * @sock: socket + * @address: address + * + * Create or update the port list entry + */ +static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, + int act) +{ + __be16 *bep; + __be32 *be32p; + struct sockaddr_in6 *addr6; + struct smk_port_label *spp; + struct socket_smack *ssp = sk->sk_security; + unsigned short port = 0; + char *subject; + char *object; + struct smk_audit_info ad; +#ifdef CONFIG_AUDIT + struct lsm_network_audit net; +#endif + + if (act == SMK_RECEIVING) { + subject = smack_net_ambient; + object = ssp->smk_in; + } else { + subject = ssp->smk_out; + object = smack_net_ambient; + } + + /* + * Get the IP address and port from the address. + */ + addr6 = (struct sockaddr_in6 *)address; + port = ntohs(addr6->sin6_port); + bep = (__be16 *)(&addr6->sin6_addr); + be32p = (__be32 *)(&addr6->sin6_addr); + + /* + * It's remote, so port lookup does no good. + */ + if (be32p[0] || be32p[1] || be32p[2] || bep[6] || ntohs(bep[7]) != 1) + goto auditout; + + /* + * It's local so the send check has to have passed. + */ + if (act == SMK_RECEIVING) { + subject = smack_known_web.smk_known; + goto auditout; + } + + list_for_each_entry(spp, &smk_ipv6_port_list, list) { + if (spp->smk_port != port) + continue; + object = spp->smk_in; + if (act == SMK_CONNECTING) + ssp->smk_packet = spp->smk_out; + break; + } + +auditout: + +#ifdef CONFIG_AUDIT + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); + ad.a.u.net->family = sk->sk_family; + ad.a.u.net->dport = port; + if (act == SMK_RECEIVING) + ad.a.u.net->v6info.saddr = addr6->sin6_addr; + else + ad.a.u.net->v6info.daddr = addr6->sin6_addr; +#endif + return smk_access(subject, object, MAY_WRITE, &ad); +} + +/** * smack_inode_setsecurity - set smack xattrs * @inode: the object * @name: attribute name @@ -1926,7 +2084,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, ssp->smk_in = sp; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { ssp->smk_out = sp; - if (sock->sk->sk_family != PF_UNIX) { + if (sock->sk->sk_family == PF_INET) { rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); if (rc != 0) printk(KERN_WARNING @@ -1936,6 +2094,9 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, } else return -EOPNOTSUPP; + if (sock->sk->sk_family == PF_INET6) + smk_ipv6_port_label(sock, NULL); + return 0; } @@ -1963,6 +2124,25 @@ static int smack_socket_post_create(struct socket *sock, int family, } /** + * smack_socket_bind - record port binding information. + * @sock: the socket + * @address: the port address + * @addrlen: size of the address + * + * Records the label bound to a port. + * + * Returns 0 + */ +static int smack_socket_bind(struct socket *sock, struct sockaddr *address, + int addrlen) +{ + if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) + smk_ipv6_port_label(sock, address); + + return 0; +} + +/** * smack_socket_connect - connect access check * @sock: the socket * @sap: the other end @@ -1975,12 +2155,24 @@ static int smack_socket_post_create(struct socket *sock, int family, static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, int addrlen) { - if (sock->sk == NULL || sock->sk->sk_family != PF_INET) + int rc = 0; + + if (sock->sk == NULL) return 0; - if (addrlen < sizeof(struct sockaddr_in)) - return -EINVAL; - return smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap); + switch (sock->sk->sk_family) { + case PF_INET: + if (addrlen < sizeof(struct sockaddr_in)) + return -EINVAL; + rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap); + break; + case PF_INET6: + if (addrlen < sizeof(struct sockaddr_in6)) + return -EINVAL; + rc = smk_ipv6_port_check(sock->sk, sap, SMK_CONNECTING); + break; + } + return rc; } /** @@ -2792,22 +2984,32 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) * @msg: the message * @size: the size of the message * - * Return 0 if the current subject can write to the destination - * host. This is only a question if the destination is a single - * label host. + * Return 0 if the current subject can write to the destination host. + * For IPv4 this is only a question if the destination is a single label host. + * For IPv6 this is a check against the label of the port. */ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; + struct sockaddr *sap = (struct sockaddr *) msg->msg_name; + int rc = 0; /* * Perfectly reasonable for this to be NULL */ - if (sip == NULL || sip->sin_family != AF_INET) + if (sip == NULL) return 0; - return smack_netlabel_send(sock->sk, sip); + switch (sip->sin_family) { + case AF_INET: + rc = smack_netlabel_send(sock->sk, sip); + break; + case AF_INET6: + rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING); + break; + } + return rc; } /** @@ -2878,6 +3080,54 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, return smack_net_ambient; } +static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr *sap) +{ + struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; + u8 nexthdr; + int offset; + int proto = -EINVAL; + struct ipv6hdr _ipv6h; + struct ipv6hdr *ip6; + __be16 frag_off; + struct tcphdr _tcph, *th; + struct udphdr _udph, *uh; + struct dccp_hdr _dccph, *dh; + + sip->sin6_port = 0; + + offset = skb_network_offset(skb); + ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h); + if (ip6 == NULL) + return -EINVAL; + sip->sin6_addr = ip6->saddr; + + nexthdr = ip6->nexthdr; + offset += sizeof(_ipv6h); + offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off); + if (offset < 0) + return -EINVAL; + + proto = nexthdr; + switch (proto) { + case IPPROTO_TCP: + th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); + if (th != NULL) + sip->sin6_port = th->source; + break; + case IPPROTO_UDP: + uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); + if (uh != NULL) + sip->sin6_port = uh->source; + break; + case IPPROTO_DCCP: + dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph); + if (dh != NULL) + sip->sin6_port = dh->dccph_sport; + break; + } + return proto; +} + /** * smack_socket_sock_rcv_skb - Smack packet delivery access check * @sk: socket @@ -2889,43 +3139,52 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { struct netlbl_lsm_secattr secattr; struct socket_smack *ssp = sk->sk_security; + struct sockaddr sadd; char *csp; - int rc; + int rc = 0; struct smk_audit_info ad; #ifdef CONFIG_AUDIT struct lsm_network_audit net; #endif - if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) - return 0; - - /* - * Translate what netlabel gave us. - */ - netlbl_secattr_init(&secattr); + switch (sk->sk_family) { + case PF_INET: + /* + * Translate what netlabel gave us. + */ + netlbl_secattr_init(&secattr); - rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); - if (rc == 0) - csp = smack_from_secattr(&secattr, ssp); - else - csp = smack_net_ambient; + rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); + if (rc == 0) + csp = smack_from_secattr(&secattr, ssp); + else + csp = smack_net_ambient; - netlbl_secattr_destroy(&secattr); + netlbl_secattr_destroy(&secattr); #ifdef CONFIG_AUDIT - smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); - ad.a.u.net->family = sk->sk_family; - ad.a.u.net->netif = skb->skb_iif; - ipv4_skb_to_auditdata(skb, &ad.a, NULL); + smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); + ad.a.u.net->family = sk->sk_family; + ad.a.u.net->netif = skb->skb_iif; + ipv4_skb_to_auditdata(skb, &ad.a, NULL); #endif - /* - * Receiving a packet requires that the other end - * be able to write here. Read access is not required. - * This is the simplist possible security model - * for networking. - */ - rc = smk_access(csp, ssp->smk_in, MAY_WRITE, &ad); - if (rc != 0) - netlbl_skbuff_err(skb, rc, 0); + /* + * Receiving a packet requires that the other end + * be able to write here. Read access is not required. + * This is the simplist possible security model + * for networking. + */ + rc = smk_access(csp, ssp->smk_in, MAY_WRITE, &ad); + if (rc != 0) + netlbl_skbuff_err(skb, rc, 0); + break; + case PF_INET6: + rc = smk_skb_to_addr_ipv6(skb, &sadd); + if (rc == IPPROTO_UDP || rc == IPPROTO_TCP) + rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); + else + rc = 0; + break; + } return rc; } @@ -3063,9 +3322,17 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct lsm_network_audit net; #endif - /* handle mapped IPv4 packets arriving via IPv6 sockets */ - if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) - family = PF_INET; + if (family == PF_INET6) { + /* + * Handle mapped IPv4 packets arriving + * via IPv6 sockets. Don't set up netlabel + * processing on IPv6. + */ + if (skb->protocol == htons(ETH_P_IP)) + family = PF_INET; + else + return 0; + } netlbl_secattr_init(&secattr); rc = netlbl_skbuff_getattr(skb, family, &secattr); @@ -3498,6 +3765,7 @@ struct security_operations smack_ops = { .unix_may_send = smack_unix_may_send, .socket_post_create = smack_socket_post_create, + .socket_bind = smack_socket_bind, .socket_connect = smack_socket_connect, .socket_sendmsg = smack_socket_sendmsg, .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:37 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:37 +0900 Subject: [LTSI-dev] [PATCH 03/16] Smack: Add smkfstransmute mount option In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-4-git-send-email-dhobsong@igel.co.jp> From: Casey Schaufler Suppliment the smkfsroot mount option with another, smkfstransmute, that does the same thing but also marks the root inode as transmutting. This allows a freshly created filesystem to be mounted with a transmutting heirarchy. Targeted for git://git.gitorious.org/smack-next/kernel.git Signed-off-by: Casey Schaufler (cherry picked from commit e830b39412ca2bbedd7508243f21c04d57ad543c) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smack.h | 1 + security/smack/smack_lsm.c | 25 ++++++++++++++++++++----- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index 159f25b..339614c 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -143,6 +143,7 @@ struct smk_port_label { #define SMK_FSFLOOR "smackfsfloor=" #define SMK_FSHAT "smackfshat=" #define SMK_FSROOT "smackfsroot=" +#define SMK_FSTRANS "smackfstransmute=" #define SMACK_CIPSO_OPTION "-CIPSO" diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 3669d9f..6a08330 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -261,8 +261,9 @@ static int smack_sb_alloc_security(struct super_block *sb) sbsp->smk_default = smack_known_floor.smk_known; sbsp->smk_floor = smack_known_floor.smk_known; sbsp->smk_hat = smack_known_hat.smk_known; - sbsp->smk_initialized = 0; - + /* + * smk_initialized will be zero from kzalloc. + */ sb->s_security = sbsp; return 0; @@ -306,6 +307,8 @@ static int smack_sb_copy_data(char *orig, char *smackopts) dp = smackopts; else if (strstr(cp, SMK_FSROOT) == cp) dp = smackopts; + else if (strstr(cp, SMK_FSTRANS) == cp) + dp = smackopts; else dp = otheropts; @@ -341,8 +344,9 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) char *op; char *commap; char *nsp; + int transmute = 0; - if (sp->smk_initialized != 0) + if (sp->smk_initialized) return 0; sp->smk_initialized = 1; @@ -373,6 +377,13 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) nsp = smk_import(op, 0); if (nsp != NULL) sp->smk_root = nsp; + } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { + op += strlen(SMK_FSTRANS); + nsp = smk_import(op, 0); + if (nsp != NULL) { + sp->smk_root = nsp; + transmute = 1; + } } } @@ -380,11 +391,15 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) * Initialize the root inode. */ isp = inode->i_security; - if (isp == NULL) + if (inode->i_security == NULL) { inode->i_security = new_inode_smack(sp->smk_root); - else + isp = inode->i_security; + } else isp->smk_inode = sp->smk_root; + if (transmute) + isp->smk_flags |= SMK_INODE_TRANSMUTE; + return 0; } -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:38 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:38 +0900 Subject: [LTSI-dev] [PATCH 04/16] Smack: Fix possible NULL pointer dereference at smk_netlbl_mls() In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-5-git-send-email-dhobsong@igel.co.jp> From: Tetsuo Handa netlbl_secattr_catmap_alloc(GFP_ATOMIC) can return NULL. Signed-off-by: Tetsuo Handa (cherry picked from commit 8cd77a0bd4b4a7d02c2a6926a69585d8088ee721) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smack_access.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 53f2327..6a0377f 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -403,6 +403,8 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, sap->flags |= NETLBL_SECATTR_MLS_CAT; sap->attr.mls.lvl = level; sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); + if (!sap->attr.mls.cat) + return -ENOMEM; sap->attr.mls.cat->startbit = 0; for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++) -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:36 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:36 +0900 Subject: [LTSI-dev] [PATCH 02/16] Smack: Improve access check performance In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-3-git-send-email-dhobsong@igel.co.jp> From: Casey Schaufler Each Smack label that the kernel has seen is added to a list of labels. The list of access rules for a given subject label hangs off of the label list entry for the label. This patch changes the structures that contain subject labels to point at the label list entry rather that the label itself. Doing so removes a label list lookup in smk_access() that was accounting for the largest single chunk of Smack overhead. Targeted for git://git.gitorious.org/smack-next/kernel.git Signed-off-by: Casey Schaufler (cherry picked from commit 2f823ff8bec03a1e6f9e11fd0c4d54e4c7d09532) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smack.h | 108 +++++++------- security/smack/smack_access.c | 41 ++--- security/smack/smack_lsm.c | 331 ++++++++++++++++++++++------------------- security/smack/smackfs.c | 51 +++---- 4 files changed, 282 insertions(+), 249 deletions(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index bb28e09..159f25b 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -29,6 +29,38 @@ #define SMK_LONGLABEL 256 /* + * This is the repository for labels seen so that it is + * not necessary to keep allocating tiny chuncks of memory + * and so that they can be shared. + * + * Labels are never modified in place. Anytime a label + * is imported (e.g. xattrset on a file) the list is checked + * for it and it is added if it doesn't exist. The address + * is passed out in either case. Entries are added, but + * never deleted. + * + * Since labels are hanging around anyway it doesn't + * hurt to maintain a secid for those awkward situations + * where kernel components that ought to use LSM independent + * interfaces don't. The secid should go away when all of + * these components have been repaired. + * + * The cipso value associated with the label gets stored here, too. + * + * Keep the access rules for this subject label here so that + * the entire set of rules does not need to be examined every + * time. + */ +struct smack_known { + struct list_head list; + char *smk_known; + u32 smk_secid; + struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */ + struct list_head smk_rules; /* access rules */ + struct mutex smk_rules_lock; /* lock for rules */ +}; + +/* * Maximum number of bytes for the levels in a CIPSO IP option. * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is * bigger than can be used, and 24 is the next lower multiple @@ -46,25 +78,25 @@ struct superblock_smack { }; struct socket_smack { - char *smk_out; /* outbound label */ - char *smk_in; /* inbound label */ - char *smk_packet; /* TCP peer label */ + struct smack_known *smk_out; /* outbound label */ + char *smk_in; /* inbound label */ + char *smk_packet; /* TCP peer label */ }; /* * Inode smack data */ struct inode_smack { - char *smk_inode; /* label of the fso */ - char *smk_task; /* label of the task */ - char *smk_mmap; /* label of the mmap domain */ - struct mutex smk_lock; /* initialization lock */ - int smk_flags; /* smack inode flags */ + char *smk_inode; /* label of the fso */ + struct smack_known *smk_task; /* label of the task */ + struct smack_known *smk_mmap; /* label of the mmap domain */ + struct mutex smk_lock; /* initialization lock */ + int smk_flags; /* smack inode flags */ }; struct task_smack { - char *smk_task; /* label for access control */ - char *smk_forked; /* label when forked */ + struct smack_known *smk_task; /* label for access control */ + struct smack_known *smk_forked; /* label when forked */ struct list_head smk_rules; /* per task access rules */ struct mutex smk_rules_lock; /* lock for the rules */ }; @@ -78,7 +110,7 @@ struct task_smack { */ struct smack_rule { struct list_head list; - char *smk_subject; + struct smack_known *smk_subject; char *smk_object; int smk_access; }; @@ -101,39 +133,7 @@ struct smk_port_label { struct sock *smk_sock; /* socket initialized on */ unsigned short smk_port; /* the port number */ char *smk_in; /* incoming label */ - char *smk_out; /* outgoing label */ -}; - -/* - * This is the repository for labels seen so that it is - * not necessary to keep allocating tiny chuncks of memory - * and so that they can be shared. - * - * Labels are never modified in place. Anytime a label - * is imported (e.g. xattrset on a file) the list is checked - * for it and it is added if it doesn't exist. The address - * is passed out in either case. Entries are added, but - * never deleted. - * - * Since labels are hanging around anyway it doesn't - * hurt to maintain a secid for those awkward situations - * where kernel components that ought to use LSM independent - * interfaces don't. The secid should go away when all of - * these components have been repaired. - * - * The cipso value associated with the label gets stored here, too. - * - * Keep the access rules for this subject label here so that - * the entire set of rules does not need to be examined every - * time. - */ -struct smack_known { - struct list_head list; - char *smk_known; - u32 smk_secid; - struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */ - struct list_head smk_rules; /* access rules */ - struct mutex smk_rules_lock; /* lock for rules */ + struct smack_known *smk_out; /* outgoing label */ }; /* @@ -214,9 +214,9 @@ struct inode_smack *new_inode_smack(char *); * These functions are in smack_access.c */ int smk_access_entry(char *, char *, struct list_head *); -int smk_access(char *, char *, int, struct smk_audit_info *); +int smk_access(struct smack_known *, char *, int, struct smk_audit_info *); int smk_curacc(char *, u32, struct smk_audit_info *); -char *smack_from_secid(const u32); +struct smack_known *smack_from_secid(const u32); char *smk_parse_smack(const char *string, int len); int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); char *smk_import(const char *, int); @@ -229,7 +229,7 @@ u32 smack_to_secid(const char *); */ extern int smack_cipso_direct; extern int smack_cipso_mapped; -extern char *smack_net_ambient; +extern struct smack_known *smack_net_ambient; extern char *smack_onlycap; extern const char *smack_cipso_option; @@ -265,17 +265,17 @@ static inline char *smk_of_inode(const struct inode *isp) } /* - * Present a pointer to the smack label in an task blob. + * Present a pointer to the smack label entry in an task blob. */ -static inline char *smk_of_task(const struct task_smack *tsp) +static inline struct smack_known *smk_of_task(const struct task_smack *tsp) { return tsp->smk_task; } /* - * Present a pointer to the forked smack label in an task blob. + * Present a pointer to the forked smack label entry in an task blob. */ -static inline char *smk_of_forked(const struct task_smack *tsp) +static inline struct smack_known *smk_of_forked(const struct task_smack *tsp) { return tsp->smk_forked; } @@ -283,7 +283,7 @@ static inline char *smk_of_forked(const struct task_smack *tsp) /* * Present a pointer to the smack label in the current task blob. */ -static inline char *smk_of_current(void) +static inline struct smack_known *smk_of_current(void) { return smk_of_task(current_security()); } @@ -294,9 +294,11 @@ static inline char *smk_of_current(void) */ static inline int smack_privileged(int cap) { + struct smack_known *skp = smk_of_current(); + if (!capable(cap)) return 0; - if (smack_onlycap == NULL || smack_onlycap == smk_of_current()) + if (smack_onlycap == NULL || smack_onlycap == skp->smk_known) return 1; return 0; } diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 2e397a8..53f2327 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -93,7 +93,7 @@ int smk_access_entry(char *subject_label, char *object_label, list_for_each_entry_rcu(srp, rule_list, list) { if (srp->smk_object == object_label && - srp->smk_subject == subject_label) { + srp->smk_subject->smk_known == subject_label) { may = srp->smk_access; break; } @@ -104,7 +104,7 @@ int smk_access_entry(char *subject_label, char *object_label, /** * smk_access - determine if a subject has a specific access to an object - * @subject_label: a pointer to the subject's Smack label + * @subject_known: a pointer to the subject's Smack label entry * @object_label: a pointer to the object's Smack label * @request: the access requested, in "MAY" format * @a : a pointer to the audit data @@ -115,10 +115,9 @@ int smk_access_entry(char *subject_label, char *object_label, * * Smack labels are shared on smack_list */ -int smk_access(char *subject_label, char *object_label, int request, - struct smk_audit_info *a) +int smk_access(struct smack_known *subject_known, char *object_label, + int request, struct smk_audit_info *a) { - struct smack_known *skp; int may = MAY_NOT; int rc = 0; @@ -127,7 +126,7 @@ int smk_access(char *subject_label, char *object_label, int request, * * A star subject can't access any object. */ - if (subject_label == smack_known_star.smk_known) { + if (subject_known == &smack_known_star) { rc = -EACCES; goto out_audit; } @@ -137,7 +136,7 @@ int smk_access(char *subject_label, char *object_label, int request, * An internet subject can access any object. */ if (object_label == smack_known_web.smk_known || - subject_label == smack_known_web.smk_known) + subject_known == &smack_known_web) goto out_audit; /* * A star object can be accessed by any subject. @@ -148,7 +147,7 @@ int smk_access(char *subject_label, char *object_label, int request, * An object can be accessed in any way by a subject * with the same label. */ - if (subject_label == object_label) + if (subject_known->smk_known == object_label) goto out_audit; /* * A hat subject can read any object. @@ -157,7 +156,7 @@ int smk_access(char *subject_label, char *object_label, int request, if ((request & MAY_ANYREAD) == request) { if (object_label == smack_known_floor.smk_known) goto out_audit; - if (subject_label == smack_known_hat.smk_known) + if (subject_known == &smack_known_hat) goto out_audit; } /* @@ -167,9 +166,9 @@ int smk_access(char *subject_label, char *object_label, int request, * good. A negative response from smk_access_entry() * indicates there is no entry for this pair. */ - skp = smk_find_entry(subject_label); rcu_read_lock(); - may = smk_access_entry(subject_label, object_label, &skp->smk_rules); + may = smk_access_entry(subject_known->smk_known, object_label, + &subject_known->smk_rules); rcu_read_unlock(); if (may > 0 && (request & may) == request) @@ -179,7 +178,8 @@ int smk_access(char *subject_label, char *object_label, int request, out_audit: #ifdef CONFIG_AUDIT if (a) - smack_log(subject_label, object_label, request, rc, a); + smack_log(subject_known->smk_known, object_label, request, + rc, a); #endif return rc; } @@ -198,20 +198,21 @@ out_audit: int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) { struct task_smack *tsp = current_security(); - char *sp = smk_of_task(tsp); + struct smack_known *skp = smk_of_task(tsp); int may; int rc; /* * Check the global rule list */ - rc = smk_access(sp, obj_label, mode, NULL); + rc = smk_access(skp, obj_label, mode, NULL); if (rc == 0) { /* * If there is an entry in the task's rule list * it can further restrict access. */ - may = smk_access_entry(sp, obj_label, &tsp->smk_rules); + may = smk_access_entry(skp->smk_known, obj_label, + &tsp->smk_rules); if (may < 0) goto out_audit; if ((mode & may) == mode) @@ -228,7 +229,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) out_audit: #ifdef CONFIG_AUDIT if (a) - smack_log(sp, obj_label, mode, rc, a); + smack_log(skp->smk_known, obj_label, mode, rc, a); #endif return rc; } @@ -513,10 +514,10 @@ char *smk_import(const char *string, int len) * smack_from_secid - find the Smack label associated with a secid * @secid: an integer that might be associated with a Smack label * - * Returns a pointer to the appropriate Smack label if there is one, + * Returns a pointer to the appropriate Smack label entry if there is one, * otherwise a pointer to the invalid Smack label. */ -char *smack_from_secid(const u32 secid) +struct smack_known *smack_from_secid(const u32 secid) { struct smack_known *skp; @@ -524,7 +525,7 @@ char *smack_from_secid(const u32 secid) list_for_each_entry_rcu(skp, &smack_known_list, list) { if (skp->smk_secid == secid) { rcu_read_unlock(); - return skp->smk_known; + return skp; } } @@ -533,7 +534,7 @@ char *smack_from_secid(const u32 secid) * of a secid that is not on the list. */ rcu_read_unlock(); - return smack_known_invalid.smk_known; + return &smack_known_invalid; } /** diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 609e89d..3669d9f 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -62,11 +62,12 @@ LIST_HEAD(smk_ipv6_port_list); * Returns a pointer to the master list entry for the Smack label * or NULL if there was no label to fetch. */ -static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) +static struct smack_known *smk_fetch(const char *name, struct inode *ip, + struct dentry *dp) { int rc; char *buffer; - char *result = NULL; + struct smack_known *skp = NULL; if (ip->i_op->getxattr == NULL) return NULL; @@ -77,11 +78,11 @@ static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL); if (rc > 0) - result = smk_import(buffer, rc); + skp = smk_import_entry(buffer, rc); kfree(buffer); - return result; + return skp; } /** @@ -111,7 +112,8 @@ struct inode_smack *new_inode_smack(char *smack) * * Returns the new blob or NULL if there's no memory available */ -static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp) +static struct task_smack *new_task_smack(struct smack_known *task, + struct smack_known *forked, gfp_t gfp) { struct task_smack *tsp; @@ -173,17 +175,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) { int rc; struct smk_audit_info ad; - char *tsp; + struct smack_known *skp; rc = cap_ptrace_access_check(ctp, mode); if (rc != 0) return rc; - tsp = smk_of_task(task_security(ctp)); + skp = smk_of_task(task_security(ctp)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ctp); - rc = smk_curacc(tsp, MAY_READWRITE, &ad); + rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); return rc; } @@ -199,17 +201,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp) { int rc; struct smk_audit_info ad; - char *tsp; + struct smack_known *skp; rc = cap_ptrace_traceme(ptp); if (rc != 0) return rc; - tsp = smk_of_task(task_security(ptp)); + skp = smk_of_task(task_security(ptp)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ptp); - rc = smk_curacc(tsp, MAY_READWRITE, &ad); + rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); return rc; } @@ -224,12 +226,12 @@ static int smack_ptrace_traceme(struct task_struct *ptp) static int smack_syslog(int typefrom_file) { int rc = 0; - char *sp = smk_of_current(); + struct smack_known *skp = smk_of_current(); if (smack_privileged(CAP_MAC_OVERRIDE)) return 0; - if (sp != smack_known_floor.smk_known) + if (skp != &smack_known_floor) rc = -EACCES; return rc; @@ -533,7 +535,9 @@ static int smack_bprm_secureexec(struct linux_binprm *bprm) */ static int smack_inode_alloc_security(struct inode *inode) { - inode->i_security = new_inode_smack(smk_of_current()); + struct smack_known *skp = smk_of_current(); + + inode->i_security = new_inode_smack(skp->smk_known); if (inode->i_security == NULL) return -ENOMEM; return 0; @@ -566,9 +570,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, char **name, void **value, size_t *len) { - struct smack_known *skp; struct inode_smack *issp = inode->i_security; - char *csp = smk_of_current(); + struct smack_known *skp = smk_of_current(); char *isp = smk_of_inode(inode); char *dsp = smk_of_inode(dir); int may; @@ -580,9 +583,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, } if (value) { - skp = smk_find_entry(csp); rcu_read_lock(); - may = smk_access_entry(csp, dsp, &skp->smk_rules); + may = smk_access_entry(skp->smk_known, dsp, &skp->smk_rules); rcu_read_unlock(); /* @@ -871,29 +873,31 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { - char *nsp; + struct smack_known *skp; struct inode_smack *isp = dentry->d_inode->i_security; + if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { + isp->smk_flags |= SMK_INODE_TRANSMUTE; + return; + } + + skp = smk_import_entry(value, size); if (strcmp(name, XATTR_NAME_SMACK) == 0) { - nsp = smk_import(value, size); - if (nsp != NULL) - isp->smk_inode = nsp; + if (skp != NULL) + isp->smk_inode = skp->smk_known; else isp->smk_inode = smack_known_invalid.smk_known; } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { - nsp = smk_import(value, size); - if (nsp != NULL) - isp->smk_task = nsp; + if (skp != NULL) + isp->smk_task = skp; else - isp->smk_task = smack_known_invalid.smk_known; + isp->smk_task = &smack_known_invalid; } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { - nsp = smk_import(value, size); - if (nsp != NULL) - isp->smk_mmap = nsp; + if (skp != NULL) + isp->smk_mmap = skp; else - isp->smk_mmap = smack_known_invalid.smk_known; - } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) - isp->smk_flags |= SMK_INODE_TRANSMUTE; + isp->smk_mmap = &smack_known_invalid; + } return; } @@ -999,7 +1003,7 @@ static int smack_inode_getsecurity(const struct inode *inode, if (strcmp(name, XATTR_SMACK_IPIN) == 0) isp = ssp->smk_in; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) - isp = ssp->smk_out; + isp = ssp->smk_out->smk_known; else return -EOPNOTSUPP; @@ -1079,7 +1083,9 @@ static int smack_file_permission(struct file *file, int mask) */ static int smack_file_alloc_security(struct file *file) { - file->f_security = smk_of_current(); + struct smack_known *skp = smk_of_current(); + + file->f_security = skp->smk_known; return 0; } @@ -1190,10 +1196,9 @@ static int smack_mmap_file(struct file *file, unsigned long flags) { struct smack_known *skp; + struct smack_known *mkp; struct smack_rule *srp; struct task_smack *tsp; - char *sp; - char *msmack; char *osmack; struct inode_smack *isp; int may; @@ -1207,11 +1212,10 @@ static int smack_mmap_file(struct file *file, isp = file_inode(file)->i_security; if (isp->smk_mmap == NULL) return 0; - msmack = isp->smk_mmap; + mkp = isp->smk_mmap; tsp = current_security(); - sp = smk_of_current(); - skp = smk_find_entry(sp); + skp = smk_of_current(); rc = 0; rcu_read_lock(); @@ -1225,13 +1229,13 @@ static int smack_mmap_file(struct file *file, /* * Matching labels always allows access. */ - if (msmack == osmack) + if (mkp->smk_known == osmack) continue; /* * If there is a matching local rule take * that into account as well. */ - may = smk_access_entry(srp->smk_subject, osmack, + may = smk_access_entry(srp->smk_subject->smk_known, osmack, &tsp->smk_rules); if (may == -ENOENT) may = srp->smk_access; @@ -1249,8 +1253,8 @@ static int smack_mmap_file(struct file *file, * If there isn't one a SMACK64MMAP subject * can't have as much access as current. */ - skp = smk_find_entry(msmack); - mmay = smk_access_entry(msmack, osmack, &skp->smk_rules); + mmay = smk_access_entry(mkp->smk_known, osmack, + &mkp->smk_rules); if (mmay == -ENOENT) { rc = -EACCES; break; @@ -1259,7 +1263,8 @@ static int smack_mmap_file(struct file *file, * If there is a local entry it modifies the * potential access, too. */ - tmay = smk_access_entry(msmack, osmack, &tsp->smk_rules); + tmay = smk_access_entry(mkp->smk_known, osmack, + &tsp->smk_rules); if (tmay != -ENOENT) mmay &= tmay; @@ -1288,7 +1293,9 @@ static int smack_mmap_file(struct file *file, */ static int smack_file_set_fowner(struct file *file) { - file->f_security = smk_of_current(); + struct smack_known *skp = smk_of_current(); + + file->f_security = skp->smk_known; return 0; } @@ -1306,9 +1313,10 @@ static int smack_file_set_fowner(struct file *file) static int smack_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int signum) { + struct smack_known *skp; + struct smack_known *tkp = smk_of_task(tsk->cred->security); struct file *file; int rc; - char *tsp = smk_of_task(tsk->cred->security); struct smk_audit_info ad; /* @@ -1317,13 +1325,14 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, file = container_of(fown, struct file, f_owner); /* we don't log here as rc can be overriden */ - rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); + skp = smk_find_entry(file->f_security); + rc = smk_access(skp, tkp->smk_known, MAY_WRITE, NULL); if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) rc = 0; smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, tsk); - smack_log(file->f_security, tsp, MAY_WRITE, rc, &ad); + smack_log(file->f_security, tkp->smk_known, MAY_WRITE, rc, &ad); return rc; } @@ -1478,12 +1487,12 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) static int smack_kernel_act_as(struct cred *new, u32 secid) { struct task_smack *new_tsp = new->security; - char *smack = smack_from_secid(secid); + struct smack_known *skp = smack_from_secid(secid); - if (smack == NULL) + if (skp == NULL) return -EINVAL; - new_tsp->smk_task = smack; + new_tsp->smk_task = skp; return 0; } @@ -1501,8 +1510,8 @@ static int smack_kernel_create_files_as(struct cred *new, struct inode_smack *isp = inode->i_security; struct task_smack *tsp = new->security; - tsp->smk_forked = isp->smk_inode; - tsp->smk_task = isp->smk_inode; + tsp->smk_forked = smk_find_entry(isp->smk_inode); + tsp->smk_task = tsp->smk_forked; return 0; } @@ -1518,10 +1527,11 @@ static int smk_curacc_on_task(struct task_struct *p, int access, const char *caller) { struct smk_audit_info ad; + struct smack_known *skp = smk_of_task(task_security(p)); smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, p); - return smk_curacc(smk_of_task(task_security(p)), access, &ad); + return smk_curacc(skp->smk_known, access, &ad); } /** @@ -1567,7 +1577,9 @@ static int smack_task_getsid(struct task_struct *p) */ static void smack_task_getsecid(struct task_struct *p, u32 *secid) { - *secid = smack_to_secid(smk_of_task(task_security(p))); + struct smack_known *skp = smk_of_task(task_security(p)); + + *secid = skp->smk_secid; } /** @@ -1671,6 +1683,8 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, int sig, u32 secid) { struct smk_audit_info ad; + struct smack_known *skp; + struct smack_known *tkp = smk_of_task(task_security(p)); smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, p); @@ -1679,15 +1693,14 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, * can write the receiver. */ if (secid == 0) - return smk_curacc(smk_of_task(task_security(p)), MAY_WRITE, - &ad); + return smk_curacc(tkp->smk_known, MAY_WRITE, &ad); /* * If the secid isn't 0 we're dealing with some USB IO * specific behavior. This is not clean. For one thing * we can't take privilege into account. */ - return smk_access(smack_from_secid(secid), - smk_of_task(task_security(p)), MAY_WRITE, &ad); + skp = smack_from_secid(secid); + return smk_access(skp, tkp->smk_known, MAY_WRITE, &ad); } /** @@ -1719,7 +1732,9 @@ static int smack_task_wait(struct task_struct *p) static void smack_task_to_inode(struct task_struct *p, struct inode *inode) { struct inode_smack *isp = inode->i_security; - isp->smk_inode = smk_of_task(task_security(p)); + struct smack_known *skp = smk_of_task(task_security(p)); + + isp->smk_inode = skp->smk_known; } /* @@ -1738,15 +1753,15 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) */ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) { - char *csp = smk_of_current(); + struct smack_known *skp = smk_of_current(); struct socket_smack *ssp; ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); if (ssp == NULL) return -ENOMEM; - ssp->smk_in = csp; - ssp->smk_out = csp; + ssp->smk_in = skp->smk_known; + ssp->smk_out = skp; ssp->smk_packet = NULL; sk->sk_security = ssp; @@ -1833,7 +1848,7 @@ static int smack_netlabel(struct sock *sk, int labeled) labeled == SMACK_UNLABELED_SOCKET) netlbl_sock_delattr(sk); else { - skp = smk_find_entry(ssp->smk_out); + skp = ssp->smk_out; rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel); } @@ -1856,6 +1871,7 @@ static int smack_netlabel(struct sock *sk, int labeled) */ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) { + struct smack_known *skp; int rc; int sk_lbl; char *hostsp; @@ -1874,7 +1890,8 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr; #endif sk_lbl = SMACK_UNLABELED_SOCKET; - rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad); + skp = ssp->smk_out; + rc = smk_access(skp, hostsp, MAY_WRITE, &ad); } else { sk_lbl = SMACK_CIPSO_SOCKET; rc = 0; @@ -1974,8 +1991,8 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, struct sockaddr_in6 *addr6; struct smk_port_label *spp; struct socket_smack *ssp = sk->sk_security; + struct smack_known *skp; unsigned short port = 0; - char *subject; char *object; struct smk_audit_info ad; #ifdef CONFIG_AUDIT @@ -1983,11 +2000,11 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, #endif if (act == SMK_RECEIVING) { - subject = smack_net_ambient; + skp = smack_net_ambient; object = ssp->smk_in; } else { - subject = ssp->smk_out; - object = smack_net_ambient; + skp = ssp->smk_out; + object = smack_net_ambient->smk_known; } /* @@ -2008,7 +2025,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, * It's local so the send check has to have passed. */ if (act == SMK_RECEIVING) { - subject = smack_known_web.smk_known; + skp = &smack_known_web; goto auditout; } @@ -2017,7 +2034,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, continue; object = spp->smk_in; if (act == SMK_CONNECTING) - ssp->smk_packet = spp->smk_out; + ssp->smk_packet = spp->smk_out->smk_known; break; } @@ -2032,7 +2049,7 @@ auditout: else ad.a.u.net->v6info.daddr = addr6->sin6_addr; #endif - return smk_access(subject, object, MAY_WRITE, &ad); + return smk_access(skp, object, MAY_WRITE, &ad); } /** @@ -2050,7 +2067,7 @@ auditout: static int smack_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) { - char *sp; + struct smack_known *skp; struct inode_smack *nsp = inode->i_security; struct socket_smack *ssp; struct socket *sock; @@ -2059,12 +2076,12 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, if (value == NULL || size > SMK_LONGLABEL || size == 0) return -EACCES; - sp = smk_import(value, size); - if (sp == NULL) + skp = smk_import_entry(value, size); + if (skp == NULL) return -EINVAL; if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { - nsp->smk_inode = sp; + nsp->smk_inode = skp->smk_known; nsp->smk_flags |= SMK_INODE_INSTANT; return 0; } @@ -2081,9 +2098,9 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, ssp = sock->sk->sk_security; if (strcmp(name, XATTR_SMACK_IPIN) == 0) - ssp->smk_in = sp; + ssp->smk_in = skp->smk_known; else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { - ssp->smk_out = sp; + ssp->smk_out = skp; if (sock->sk->sk_family == PF_INET) { rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); if (rc != 0) @@ -2203,7 +2220,9 @@ static int smack_flags_to_may(int flags) */ static int smack_msg_msg_alloc_security(struct msg_msg *msg) { - msg->security = smk_of_current(); + struct smack_known *skp = smk_of_current(); + + msg->security = skp->smk_known; return 0; } @@ -2238,8 +2257,9 @@ static char *smack_of_shm(struct shmid_kernel *shp) static int smack_shm_alloc_security(struct shmid_kernel *shp) { struct kern_ipc_perm *isp = &shp->shm_perm; + struct smack_known *skp = smk_of_current(); - isp->security = smk_of_current(); + isp->security = skp->smk_known; return 0; } @@ -2361,8 +2381,9 @@ static char *smack_of_sem(struct sem_array *sma) static int smack_sem_alloc_security(struct sem_array *sma) { struct kern_ipc_perm *isp = &sma->sem_perm; + struct smack_known *skp = smk_of_current(); - isp->security = smk_of_current(); + isp->security = skp->smk_known; return 0; } @@ -2479,8 +2500,9 @@ static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops, static int smack_msg_queue_alloc_security(struct msg_queue *msq) { struct kern_ipc_perm *kisp = &msq->q_perm; + struct smack_known *skp = smk_of_current(); - kisp->security = smk_of_current(); + kisp->security = skp->smk_known; return 0; } @@ -2652,8 +2674,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) struct super_block *sbp; struct superblock_smack *sbsp; struct inode_smack *isp; - char *csp = smk_of_current(); - char *fetched; + struct smack_known *skp; + struct smack_known *ckp = smk_of_current(); char *final; char trattr[TRANS_TRUE_SIZE]; int transflag = 0; @@ -2720,7 +2742,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * Programs that change smack have to treat the * pty with respect. */ - final = csp; + final = ckp->smk_known; break; case SOCKFS_MAGIC: /* @@ -2775,9 +2797,9 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * Get the dentry for xattr. */ dp = dget(opt_dentry); - fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); - if (fetched != NULL) - final = fetched; + skp = smk_fetch(XATTR_NAME_SMACK, inode, dp); + if (skp != NULL) + final = skp->smk_known; /* * Transmuting directory @@ -2817,7 +2839,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) } if (final == NULL) - isp->smk_inode = csp; + isp->smk_inode = ckp->smk_known; else isp->smk_inode = final; @@ -2840,13 +2862,14 @@ unlockandout: */ static int smack_getprocattr(struct task_struct *p, char *name, char **value) { + struct smack_known *skp = smk_of_task(task_security(p)); char *cp; int slen; if (strcmp(name, "current") != 0) return -EINVAL; - cp = kstrdup(smk_of_task(task_security(p)), GFP_KERNEL); + cp = kstrdup(skp->smk_known, GFP_KERNEL); if (cp == NULL) return -ENOMEM; @@ -2872,7 +2895,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, { struct task_smack *tsp; struct cred *new; - char *newsmack; + struct smack_known *skp; /* * Changing another process' Smack value is too dangerous @@ -2890,14 +2913,14 @@ static int smack_setprocattr(struct task_struct *p, char *name, if (strcmp(name, "current") != 0) return -EINVAL; - newsmack = smk_import(value, size); - if (newsmack == NULL) + skp = smk_import_entry(value, size); + if (skp == NULL) return -EINVAL; /* * No process is ever allowed the web ("@") label. */ - if (newsmack == smack_known_web.smk_known) + if (skp == &smack_known_web) return -EPERM; new = prepare_creds(); @@ -2905,7 +2928,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, return -ENOMEM; tsp = new->security; - tsp->smk_task = newsmack; + tsp->smk_task = skp; commit_creds(new); return size; @@ -2923,6 +2946,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, static int smack_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { + struct smack_known *skp; struct socket_smack *ssp = sock->sk_security; struct socket_smack *osp = other->sk_security; struct socket_smack *nsp = newsk->sk_security; @@ -2936,15 +2960,17 @@ static int smack_unix_stream_connect(struct sock *sock, smk_ad_setfield_u_net_sk(&ad, other); #endif - if (!smack_privileged(CAP_MAC_OVERRIDE)) - rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); + if (!smack_privileged(CAP_MAC_OVERRIDE)) { + skp = ssp->smk_out; + rc = smk_access(skp, osp->smk_in, MAY_WRITE, &ad); + } /* * Cross reference the peer labels for SO_PEERSEC. */ if (rc == 0) { - nsp->smk_packet = ssp->smk_out; - ssp->smk_packet = osp->smk_out; + nsp->smk_packet = ssp->smk_out->smk_known; + ssp->smk_packet = osp->smk_out->smk_known; } return rc; @@ -2962,8 +2988,8 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) { struct socket_smack *ssp = sock->sk->sk_security; struct socket_smack *osp = other->sk->sk_security; + struct smack_known *skp; struct smk_audit_info ad; - int rc = 0; #ifdef CONFIG_AUDIT struct lsm_network_audit net; @@ -2972,10 +2998,11 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) smk_ad_setfield_u_net_sk(&ad, other->sk); #endif - if (!smack_privileged(CAP_MAC_OVERRIDE)) - rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); + if (smack_privileged(CAP_MAC_OVERRIDE)) + return 0; - return rc; + skp = ssp->smk_out; + return smk_access(skp, osp->smk_in, MAY_WRITE, &ad); } /** @@ -3017,13 +3044,12 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, * @sap: netlabel secattr * @ssp: socket security information * - * Returns a pointer to a Smack label found on the label list. + * Returns a pointer to a Smack label entry found on the label list. */ -static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, - struct socket_smack *ssp) +static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, + struct socket_smack *ssp) { - struct smack_known *kp; - char *sp; + struct smack_known *skp; int found = 0; if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { @@ -3038,11 +3064,11 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, * ambient value. */ rcu_read_lock(); - list_for_each_entry(kp, &smack_known_list, list) { - if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl) + list_for_each_entry(skp, &smack_known_list, list) { + if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl) continue; if (memcmp(sap->attr.mls.cat, - kp->smk_netlabel.attr.mls.cat, + skp->smk_netlabel.attr.mls.cat, SMK_CIPSOLEN) != 0) continue; found = 1; @@ -3051,17 +3077,17 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, rcu_read_unlock(); if (found) - return kp->smk_known; + return skp; if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) - return smack_known_web.smk_known; - return smack_known_star.smk_known; + return &smack_known_web; + return &smack_known_star; } if ((sap->flags & NETLBL_SECATTR_SECID) != 0) { /* * Looks like a fallback, which gives us a secid. */ - sp = smack_from_secid(sap->attr.secid); + skp = smack_from_secid(sap->attr.secid); /* * This has got to be a bug because it is * impossible to specify a fallback without @@ -3069,8 +3095,8 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, * it has a secid, and the only way to get a * secid is from a fallback. */ - BUG_ON(sp == NULL); - return sp; + BUG_ON(skp == NULL); + return skp; } /* * Without guidance regarding the smack value @@ -3139,8 +3165,8 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { struct netlbl_lsm_secattr secattr; struct socket_smack *ssp = sk->sk_security; + struct smack_known *skp; struct sockaddr sadd; - char *csp; int rc = 0; struct smk_audit_info ad; #ifdef CONFIG_AUDIT @@ -3155,9 +3181,9 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); if (rc == 0) - csp = smack_from_secattr(&secattr, ssp); + skp = smack_from_secattr(&secattr, ssp); else - csp = smack_net_ambient; + skp = smack_net_ambient; netlbl_secattr_destroy(&secattr); @@ -3173,7 +3199,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) * This is the simplist possible security model * for networking. */ - rc = smk_access(csp, ssp->smk_in, MAY_WRITE, &ad); + rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); if (rc != 0) netlbl_skbuff_err(skb, rc, 0); break; @@ -3238,7 +3264,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, { struct netlbl_lsm_secattr secattr; struct socket_smack *ssp = NULL; - char *sp; + struct smack_known *skp; int family = PF_UNSPEC; u32 s = 0; /* 0 is the invalid secid */ int rc; @@ -3254,7 +3280,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, if (family == PF_UNIX) { ssp = sock->sk->sk_security; - s = smack_to_secid(ssp->smk_out); + s = ssp->smk_out->smk_secid; } else if (family == PF_INET || family == PF_INET6) { /* * Translate what netlabel gave us. @@ -3264,8 +3290,8 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, netlbl_secattr_init(&secattr); rc = netlbl_skbuff_getattr(skb, family, &secattr); if (rc == 0) { - sp = smack_from_secattr(&secattr, ssp); - s = smack_to_secid(sp); + skp = smack_from_secattr(&secattr, ssp); + s = skp->smk_secid; } netlbl_secattr_destroy(&secattr); } @@ -3286,13 +3312,15 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, static void smack_sock_graft(struct sock *sk, struct socket *parent) { struct socket_smack *ssp; + struct smack_known *skp = smk_of_current(); if (sk == NULL || (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)) return; ssp = sk->sk_security; - ssp->smk_in = ssp->smk_out = smk_of_current(); + ssp->smk_in = skp->smk_known; + ssp->smk_out = skp; /* cssp->smk_packet is already set in smack_inet_csk_clone() */ } @@ -3314,7 +3342,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, struct netlbl_lsm_secattr secattr; struct sockaddr_in addr; struct iphdr *hdr; - char *sp; char *hsp; int rc; struct smk_audit_info ad; @@ -3337,9 +3364,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, netlbl_secattr_init(&secattr); rc = netlbl_skbuff_getattr(skb, family, &secattr); if (rc == 0) - sp = smack_from_secattr(&secattr, ssp); + skp = smack_from_secattr(&secattr, ssp); else - sp = smack_known_huh.smk_known; + skp = &smack_known_huh; netlbl_secattr_destroy(&secattr); #ifdef CONFIG_AUDIT @@ -3352,7 +3379,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, * Receiving a packet requires that the other end be able to write * here. Read access is not required. */ - rc = smk_access(sp, ssp->smk_in, MAY_WRITE, &ad); + rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); if (rc != 0) return rc; @@ -3360,7 +3387,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, * Save the peer's label in the request_sock so we can later setup * smk_packet in the child socket so that SO_PEERCRED can report it. */ - req->peer_secid = smack_to_secid(sp); + req->peer_secid = skp->smk_secid; /* * We need to decide if we want to label the incoming connection here @@ -3373,10 +3400,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, hsp = smack_host_label(&addr); rcu_read_unlock(); - if (hsp == NULL) { - skp = smk_find_entry(sp); + if (hsp == NULL) rc = netlbl_req_setattr(req, &skp->smk_netlabel); - } else + else netlbl_req_delattr(req); return rc; @@ -3393,10 +3419,12 @@ static void smack_inet_csk_clone(struct sock *sk, const struct request_sock *req) { struct socket_smack *ssp = sk->sk_security; + struct smack_known *skp; - if (req->peer_secid != 0) - ssp->smk_packet = smack_from_secid(req->peer_secid); - else + if (req->peer_secid != 0) { + skp = smack_from_secid(req->peer_secid); + ssp->smk_packet = skp->smk_known; + } else ssp->smk_packet = NULL; } @@ -3422,7 +3450,9 @@ static void smack_inet_csk_clone(struct sock *sk, static int smack_key_alloc(struct key *key, const struct cred *cred, unsigned long flags) { - key->security = smk_of_task(cred->security); + struct smack_known *skp = smk_of_task(cred->security); + + key->security = skp->smk_known; return 0; } @@ -3451,7 +3481,7 @@ static int smack_key_permission(key_ref_t key_ref, { struct key *keyp; struct smk_audit_info ad; - char *tsp = smk_of_task(cred->security); + struct smack_known *tkp = smk_of_task(cred->security); keyp = key_ref_to_ptr(key_ref); if (keyp == NULL) @@ -3465,15 +3495,14 @@ static int smack_key_permission(key_ref_t key_ref, /* * This should not occur */ - if (tsp == NULL) + if (tkp == NULL) return -EACCES; #ifdef CONFIG_AUDIT smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); ad.a.u.key_struct.key = keyp->serial; ad.a.u.key_struct.key_desc = keyp->description; #endif - return smk_access(tsp, keyp->security, - MAY_READWRITE, &ad); + return smk_access(tkp, keyp->security, MAY_READWRITE, &ad); } #endif /* CONFIG_KEYS */ @@ -3555,7 +3584,7 @@ static int smack_audit_rule_known(struct audit_krule *krule) static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, struct audit_context *actx) { - char *smack; + struct smack_known *skp; char *rule = vrule; if (!rule) { @@ -3567,7 +3596,7 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER) return 0; - smack = smack_from_secid(secid); + skp = smack_from_secid(secid); /* * No need to do string comparisons. If a match occurs, @@ -3575,9 +3604,9 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, * label. */ if (op == Audit_equal) - return (rule == smack); + return (rule == skp->smk_known); if (op == Audit_not_equal) - return (rule != smack); + return (rule != skp->smk_known); return 0; } @@ -3605,11 +3634,11 @@ static void smack_audit_rule_free(void *vrule) */ static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { - char *sp = smack_from_secid(secid); + struct smack_known *skp = smack_from_secid(secid); if (secdata) - *secdata = sp; - *seclen = strlen(sp); + *secdata = skp->smk_known; + *seclen = strlen(skp->smk_known); return 0; } @@ -3845,8 +3874,8 @@ static __init int smack_init(void) if (!security_module_enable(&smack_ops)) return 0; - tsp = new_task_smack(smack_known_floor.smk_known, - smack_known_floor.smk_known, GFP_KERNEL); + tsp = new_task_smack(&smack_known_floor, &smack_known_floor, + GFP_KERNEL); if (tsp == NULL) return -ENOMEM; diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 53a08b8..3c79cba 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -66,7 +66,7 @@ static DEFINE_MUTEX(smk_netlbladdr_lock); * If it isn't somehow marked, use this. * It can be reset via smackfs/ambient */ -char *smack_net_ambient; +struct smack_known *smack_net_ambient; /* * This is the level in a CIPSO header that indicates a @@ -112,7 +112,7 @@ struct smack_master_list { LIST_HEAD(smack_rule_list); struct smack_parsed_rule { - char *smk_subject; + struct smack_known *smk_subject; char *smk_object; int smk_access1; int smk_access2; @@ -163,9 +163,11 @@ static inline void smack_catset_bit(unsigned int cat, char *catsetp) */ static void smk_netlabel_audit_set(struct netlbl_audit *nap) { + struct smack_known *skp = smk_of_current(); + nap->loginuid = audit_get_loginuid(current); nap->sessionid = audit_get_sessionid(current); - nap->secid = smack_to_secid(smk_of_current()); + nap->secid = skp->smk_secid; } /* @@ -306,7 +308,7 @@ static int smk_fill_rule(const char *subject, const char *object, struct smack_known *skp; if (import) { - rule->smk_subject = smk_import(subject, len); + rule->smk_subject = smk_import_entry(subject, len); if (rule->smk_subject == NULL) return -1; @@ -321,7 +323,7 @@ static int smk_fill_rule(const char *subject, const char *object, kfree(cp); if (skp == NULL) return -1; - rule->smk_subject = skp->smk_known; + rule->smk_subject = skp; cp = smk_parse_smack(object, len); if (cp == NULL) @@ -445,7 +447,6 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, struct list_head *rule_list, struct mutex *rule_lock, int format) { - struct smack_known *skp; struct smack_parsed_rule *rule; char *data; int datalen; @@ -505,12 +506,10 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, goto out_free_rule; } - if (rule_list == NULL) { load = 1; - skp = smk_find_entry(rule->smk_subject); - rule_list = &skp->smk_rules; - rule_lock = &skp->smk_rules_lock; + rule_list = &rule->smk_subject->smk_rules; + rule_lock = &rule->smk_subject->smk_rules_lock; } rc = smk_set_access(rule, rule_list, rule_lock, load); @@ -579,13 +578,14 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) * because you should expect to be able to write * anything you read back. */ - if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max) + if (strlen(srp->smk_subject->smk_known) >= max || + strlen(srp->smk_object) >= max) return; if (srp->smk_access == 0) return; - seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object); + seq_printf(s, "%s %s", srp->smk_subject->smk_known, srp->smk_object); seq_putc(s, ' '); @@ -738,9 +738,9 @@ static void smk_unlbl_ambient(char *oldambient) __func__, __LINE__, rc); } if (smack_net_ambient == NULL) - smack_net_ambient = smack_known_floor.smk_known; + smack_net_ambient = &smack_known_floor; - rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET, + rc = netlbl_cfg_unlbl_map_add(smack_net_ambient->smk_known, PF_INET, NULL, NULL, &nai); if (rc != 0) printk(KERN_WARNING "%s:%d add rc = %d\n", @@ -1535,11 +1535,12 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, */ mutex_lock(&smack_ambient_lock); - asize = strlen(smack_net_ambient) + 1; + asize = strlen(smack_net_ambient->smk_known) + 1; if (cn >= asize) rc = simple_read_from_buffer(buf, cn, ppos, - smack_net_ambient, asize); + smack_net_ambient->smk_known, + asize); else rc = -EINVAL; @@ -1560,8 +1561,8 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, static ssize_t smk_write_ambient(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { + struct smack_known *skp; char *oldambient; - char *smack = NULL; char *data; int rc = count; @@ -1577,16 +1578,16 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, goto out; } - smack = smk_import(data, count); - if (smack == NULL) { + skp = smk_import_entry(data, count); + if (skp == NULL) { rc = -EINVAL; goto out; } mutex_lock(&smack_ambient_lock); - oldambient = smack_net_ambient; - smack_net_ambient = smack; + oldambient = smack_net_ambient->smk_known; + smack_net_ambient = skp; smk_unlbl_ambient(oldambient); mutex_unlock(&smack_ambient_lock); @@ -1645,7 +1646,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { char *data; - char *sp = smk_of_task(current->cred->security); + struct smack_known *skp = smk_of_task(current->cred->security); int rc = count; if (!smack_privileged(CAP_MAC_ADMIN)) @@ -1656,7 +1657,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, * explicitly for clarity. The smk_access() implementation * would use smk_access(smack_onlycap, MAY_WRITE) */ - if (smack_onlycap != NULL && smack_onlycap != sp) + if (smack_onlycap != NULL && smack_onlycap != skp->smk_known) return -EPERM; data = kzalloc(count, GFP_KERNEL); @@ -1866,8 +1867,8 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, if (res) return -EINVAL; - res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access1, - NULL); + res = smk_access(rule.smk_subject, rule.smk_object, + rule.smk_access1, NULL); data[0] = res == 0 ? '1' : '0'; data[1] = '\0'; -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:39 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:39 +0900 Subject: [LTSI-dev] [PATCH 05/16] Smack: Fix the bug smackcipso can't set CIPSO correctly In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-6-git-send-email-dhobsong@igel.co.jp> From: "Passion,Zhao" Bug report: https://tizendev.org/bugs/browse/TDIS-3891 The reason is userspace libsmack only use "smackfs/cipso2" long-label interface, but the code's logical is still for orginal fixed length label. Now update smack_cipso_apply() to support flexible label (<=256 including tailing '\0') There is also a bug in kernel/security/smack/smackfs.c: When smk_set_cipso() parsing the CIPSO setting from userspace, the offset of CIPSO level should be "strlen(label)+1" instead of "strlen(label)" Signed-off-by: Passion,Zhao (cherry picked from commit 0fcfee61d63b82c1eefb5b1a914240480f17d63f) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smackfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 3c79cba..ab16703 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -881,7 +881,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, if (format == SMK_FIXED24_FMT) rule += SMK_LABELLEN; else - rule += strlen(skp->smk_known); + rule += strlen(skp->smk_known) + 1; ret = sscanf(rule, "%d", &maplevel); if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:40 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:40 +0900 Subject: [LTSI-dev] [PATCH 06/16] Security: Add Hook to test if the particular xattr is part of a MAC model. In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-7-git-send-email-dhobsong@igel.co.jp> From: David Quigley The interface to request security labels from user space is the xattr interface. When requesting the security label from an NFS server it is important to make sure the requested xattr actually is a MAC label. This allows us to make sure that we get the desired semantics from the attribute instead of something else such as capabilities or a time based LSM. Acked-by: Eric Paris Acked-by: James Morris Signed-off-by: Matthew N. Dodd Signed-off-by: Miguel Rodel Felipe Signed-off-by: Phua Eu Gene Signed-off-by: Khin Mi Mi Aung Signed-off-by: Trond Myklebust (cherry picked from commit 746df9b59c8a5f162c907796c7295d3c4c0d8995) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- include/linux/security.h | 14 ++++++++++++++ security/capability.c | 6 ++++++ security/security.c | 6 ++++++ security/selinux/hooks.c | 6 ++++++ security/smack/smack_lsm.c | 11 +++++++++++ 5 files changed, 43 insertions(+) diff --git a/include/linux/security.h b/include/linux/security.h index 4686491..1d8fe3c 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1313,6 +1313,13 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) * @pages contains the number of pages. * Return 0 if permission is granted. * + * @ismaclabel: + * Check if the extended attribute specified by @name + * represents a MAC label. Returns 1 if name is a MAC + * attribute otherwise returns 0. + * @name full extended attribute name to check against + * LSM as a MAC label. + * * @secid_to_secctx: * Convert secid to security context. If secdata is NULL the length of * the result will be returned in seclen, but no secdata will be returned. @@ -1590,6 +1597,7 @@ struct security_operations { int (*getprocattr) (struct task_struct *p, char *name, char **value); int (*setprocattr) (struct task_struct *p, char *name, void *value, size_t size); + int (*ismaclabel) (const char *name); int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen); int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); void (*release_secctx) (char *secdata, u32 seclen); @@ -1840,6 +1848,7 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode); int security_getprocattr(struct task_struct *p, char *name, char **value); int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size); int security_netlink_send(struct sock *sk, struct sk_buff *skb); +int security_ismaclabel(const char *name); int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen); int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); void security_release_secctx(char *secdata, u32 seclen); @@ -2520,6 +2529,11 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb) return cap_netlink_send(sk, skb); } +static inline int security_ismaclabel(const char *name) +{ + return 0; +} + static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { return -EOPNOTSUPP; diff --git a/security/capability.c b/security/capability.c index 1728d4e..26e0d3d 100644 --- a/security/capability.c +++ b/security/capability.c @@ -816,6 +816,11 @@ static int cap_setprocattr(struct task_struct *p, char *name, void *value, return -EINVAL; } +static int cap_ismaclabel(const char *name) +{ + return 0; +} + static int cap_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { return -EOPNOTSUPP; @@ -1034,6 +1039,7 @@ void __init security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, d_instantiate); set_to_cap_if_null(ops, getprocattr); set_to_cap_if_null(ops, setprocattr); + set_to_cap_if_null(ops, ismaclabel); set_to_cap_if_null(ops, secid_to_secctx); set_to_cap_if_null(ops, secctx_to_secid); set_to_cap_if_null(ops, release_secctx); diff --git a/security/security.c b/security/security.c index a3dce87..bf919ce 100644 --- a/security/security.c +++ b/security/security.c @@ -1047,6 +1047,12 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb) return security_ops->netlink_send(sk, skb); } +int security_ismaclabel(const char *name) +{ + return security_ops->ismaclabel(name); +} +EXPORT_SYMBOL(security_ismaclabel); + int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { return security_ops->secid_to_secctx(secid, secdata, seclen); diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a7096e1..d2f4381 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5526,6 +5526,11 @@ abort_change: return error; } +static int selinux_ismaclabel(const char *name) +{ + return (strcmp(name, XATTR_SELINUX_SUFFIX) == 0); +} + static int selinux_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { return security_sid_to_context(secid, secdata, seclen); @@ -5763,6 +5768,7 @@ static struct security_operations selinux_ops = { .getprocattr = selinux_getprocattr, .setprocattr = selinux_setprocattr, + .ismaclabel = selinux_ismaclabel, .secid_to_secctx = selinux_secid_to_secctx, .secctx_to_secid = selinux_secctx_to_secid, .release_secctx = selinux_release_secctx, diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 6a08330..3f7682a 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3640,6 +3640,16 @@ static void smack_audit_rule_free(void *vrule) #endif /* CONFIG_AUDIT */ /** + * smack_ismaclabel - check if xattr @name references a smack MAC label + * @name: Full xattr name to check. + */ +static int smack_ismaclabel(const char *name) +{ + return (strcmp(name, XATTR_SMACK_SUFFIX) == 0); +} + + +/** * smack_secid_to_secctx - return the smack label for a secid * @secid: incoming integer * @secdata: destination @@ -3836,6 +3846,7 @@ struct security_operations smack_ops = { .audit_rule_free = smack_audit_rule_free, #endif /* CONFIG_AUDIT */ + .ismaclabel = smack_ismaclabel, .secid_to_secctx = smack_secid_to_secctx, .secctx_to_secid = smack_secctx_to_secid, .release_secctx = smack_release_secctx, -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:41 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:41 +0900 Subject: [LTSI-dev] [PATCH 07/16] xattr: Constify ->name member of "struct xattr". In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-8-git-send-email-dhobsong@igel.co.jp> From: Tetsuo Handa Since everybody sets kstrdup()ed constant string to "struct xattr"->name but nobody modifies "struct xattr"->name , we can omit kstrdup() and its failure checking by constifying ->name member of "struct xattr". Signed-off-by: Tetsuo Handa Reviewed-by: Joel Becker [ocfs2] Acked-by: Serge E. Hallyn Acked-by: Casey Schaufler Acked-by: Mimi Zohar Reviewed-by: Paul Moore Tested-by: Paul Moore Acked-by: Eric Paris Signed-off-by: James Morris (cherry picked from commit 9548906b2bb7ff09e12c013a55d669bef2c8e121) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- fs/ocfs2/xattr.h | 2 +- include/linux/security.h | 8 ++++---- include/linux/xattr.h | 2 +- include/uapi/linux/reiserfs_xattr.h | 2 +- security/capability.c | 2 +- security/integrity/evm/evm_main.c | 2 +- security/security.c | 8 +++----- security/selinux/hooks.c | 17 ++++++----------- security/smack/smack_lsm.c | 9 +++------ 9 files changed, 21 insertions(+), 31 deletions(-) diff --git a/fs/ocfs2/xattr.h b/fs/ocfs2/xattr.h index e5c7f15..19f134e 100644 --- a/fs/ocfs2/xattr.h +++ b/fs/ocfs2/xattr.h @@ -32,7 +32,7 @@ enum ocfs2_xattr_type { struct ocfs2_security_xattr_info { int enable; - char *name; + const char *name; void *value; size_t value_len; }; diff --git a/include/linux/security.h b/include/linux/security.h index 1d8fe3c..0f246d4 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -1472,7 +1472,7 @@ struct security_operations { int (*inode_alloc_security) (struct inode *inode); void (*inode_free_security) (struct inode *inode); int (*inode_init_security) (struct inode *inode, struct inode *dir, - const struct qstr *qstr, char **name, + const struct qstr *qstr, const char **name, void **value, size_t *len); int (*inode_create) (struct inode *dir, struct dentry *dentry, umode_t mode); @@ -1744,7 +1744,7 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, initxattrs initxattrs, void *fs_data); int security_old_inode_init_security(struct inode *inode, struct inode *dir, - const struct qstr *qstr, char **name, + const struct qstr *qstr, const char **name, void **value, size_t *len); int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode); int security_inode_link(struct dentry *old_dentry, struct inode *dir, @@ -2056,8 +2056,8 @@ static inline int security_inode_init_security(struct inode *inode, static inline int security_old_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, - char **name, void **value, - size_t *len) + const char **name, + void **value, size_t *len) { return -EOPNOTSUPP; } diff --git a/include/linux/xattr.h b/include/linux/xattr.h index fdbafc6..91b0a68 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -31,7 +31,7 @@ struct xattr_handler { }; struct xattr { - char *name; + const char *name; void *value; size_t value_len; }; diff --git a/include/uapi/linux/reiserfs_xattr.h b/include/uapi/linux/reiserfs_xattr.h index d8ce17c..38fdd64 100644 --- a/include/uapi/linux/reiserfs_xattr.h +++ b/include/uapi/linux/reiserfs_xattr.h @@ -16,7 +16,7 @@ struct reiserfs_xattr_header { }; struct reiserfs_security_handle { - char *name; + const char *name; void *value; size_t length; }; diff --git a/security/capability.c b/security/capability.c index 26e0d3d..432e8af 100644 --- a/security/capability.c +++ b/security/capability.c @@ -119,7 +119,7 @@ static void cap_inode_free_security(struct inode *inode) } static int cap_inode_init_security(struct inode *inode, struct inode *dir, - const struct qstr *qstr, char **name, + const struct qstr *qstr, const char **name, void **value, size_t *len) { return -EOPNOTSUPP; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index cdbde17..2787080 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -405,7 +405,7 @@ int evm_inode_init_security(struct inode *inode, evm_xattr->value = xattr_data; evm_xattr->value_len = sizeof(*xattr_data); - evm_xattr->name = kstrdup(XATTR_EVM_SUFFIX, GFP_NOFS); + evm_xattr->name = XATTR_EVM_SUFFIX; return 0; out: kfree(xattr_data); diff --git a/security/security.c b/security/security.c index bf919ce..7813fd8 100644 --- a/security/security.c +++ b/security/security.c @@ -335,10 +335,10 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, if (unlikely(IS_PRIVATE(inode))) return 0; - memset(new_xattrs, 0, sizeof new_xattrs); if (!initxattrs) return security_ops->inode_init_security(inode, dir, qstr, NULL, NULL, NULL); + memset(new_xattrs, 0, sizeof(new_xattrs)); lsm_xattr = new_xattrs; ret = security_ops->inode_init_security(inode, dir, qstr, &lsm_xattr->name, @@ -353,16 +353,14 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, goto out; ret = initxattrs(inode, new_xattrs, fs_data); out: - for (xattr = new_xattrs; xattr->name != NULL; xattr++) { - kfree(xattr->name); + for (xattr = new_xattrs; xattr->value != NULL; xattr++) kfree(xattr->value); - } return (ret == -EOPNOTSUPP) ? 0 : ret; } EXPORT_SYMBOL(security_inode_init_security); int security_old_inode_init_security(struct inode *inode, struct inode *dir, - const struct qstr *qstr, char **name, + const struct qstr *qstr, const char **name, void **value, size_t *len) { if (unlikely(IS_PRIVATE(inode))) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d2f4381..0c47e2c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -2533,7 +2533,8 @@ static void selinux_inode_free_security(struct inode *inode) } static int selinux_inode_init_security(struct inode *inode, struct inode *dir, - const struct qstr *qstr, char **name, + const struct qstr *qstr, + const char **name, void **value, size_t *len) { const struct task_security_struct *tsec = current_security(); @@ -2541,7 +2542,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, struct superblock_security_struct *sbsec; u32 sid, newsid, clen; int rc; - char *namep = NULL, *context; + char *context; dsec = dir->i_security; sbsec = dir->i_sb->s_security; @@ -2577,19 +2578,13 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir, if (!ss_initialized || !(sbsec->flags & SE_SBLABELSUPP)) return -EOPNOTSUPP; - if (name) { - namep = kstrdup(XATTR_SELINUX_SUFFIX, GFP_NOFS); - if (!namep) - return -ENOMEM; - *name = namep; - } + if (name) + *name = XATTR_SELINUX_SUFFIX; if (value && len) { rc = security_sid_to_context_force(newsid, &context, &clen); - if (rc) { - kfree(namep); + if (rc) return rc; - } *value = context; *len = clen; } diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 3f7682a..a113a77 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -582,7 +582,7 @@ static void smack_inode_free_security(struct inode *inode) * Returns 0 if it all works out, -ENOMEM if there's no memory */ static int smack_inode_init_security(struct inode *inode, struct inode *dir, - const struct qstr *qstr, char **name, + const struct qstr *qstr, const char **name, void **value, size_t *len) { struct inode_smack *issp = inode->i_security; @@ -591,11 +591,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, char *dsp = smk_of_inode(dir); int may; - if (name) { - *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_NOFS); - if (*name == NULL) - return -ENOMEM; - } + if (name) + *name = XATTR_SMACK_SUFFIX; if (value) { rcu_read_lock(); -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:42 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:42 +0900 Subject: [LTSI-dev] [PATCH 08/16] ocfs2: fix panic on kfree(xattr->name) In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-9-git-send-email-dhobsong@igel.co.jp> From: Tetsuo Handa Commit 9548906b2bb7 ('xattr: Constify ->name member of "struct xattr"') missed that ocfs2 is calling kfree(xattr->name). As a result, kernel panic occurs upon calling kfree(xattr->name) because xattr->name refers static constant names. This patch removes kfree(xattr->name) from ocfs2_mknod() and ocfs2_symlink(). Signed-off-by: Tetsuo Handa Reported-by: Tariq Saeed Tested-by: Tariq Saeed Reviewed-by: Srinivas Eeda Cc: Joel Becker Cc: Mark Fasheh Cc: [3.12+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds (cherry picked from commit f81c20158f8d5f7938d5eb86ecc42ecc09273ce6) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- fs/ocfs2/namei.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c index b4a5cdf..64bf0f4 100644 --- a/fs/ocfs2/namei.c +++ b/fs/ocfs2/namei.c @@ -430,7 +430,6 @@ leave: brelse(new_fe_bh); brelse(parent_fe_bh); - kfree(si.name); kfree(si.value); ocfs2_free_dir_lookup_result(&lookup); @@ -1817,7 +1816,6 @@ bail: brelse(new_fe_bh); brelse(parent_fe_bh); - kfree(si.name); kfree(si.value); ocfs2_free_dir_lookup_result(&lookup); if (inode_ac) -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:43 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:43 +0900 Subject: [LTSI-dev] [PATCH 09/16] security: smack: fix memleak in smk_write_rules_list() In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-10-git-send-email-dhobsong@igel.co.jp> From: Tomasz Stanislawski The smack_parsed_rule structure is allocated. If a rule is successfully installed then the last reference to the object is lost. This patch fixes this leak. Moreover smack_parsed_rule is allocated on stack because it no longer needed ofter smk_write_rules_list() is finished. Signed-off-by: Tomasz Stanislawski (cherry picked from commit 470043ba995a79a274a5db306856975002a06f19) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smackfs.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index ab16703..269b270 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -447,7 +447,7 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, struct list_head *rule_list, struct mutex *rule_lock, int format) { - struct smack_parsed_rule *rule; + struct smack_parsed_rule rule; char *data; int datalen; int rc = -EINVAL; @@ -479,47 +479,36 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, goto out; } - rule = kzalloc(sizeof(*rule), GFP_KERNEL); - if (rule == NULL) { - rc = -ENOMEM; - goto out; - } - if (format == SMK_LONG_FMT) { /* * Be sure the data string is terminated. */ data[count] = '\0'; - if (smk_parse_long_rule(data, rule, 1, 0)) - goto out_free_rule; + if (smk_parse_long_rule(data, &rule, 1, 0)) + goto out; } else if (format == SMK_CHANGE_FMT) { data[count] = '\0'; - if (smk_parse_long_rule(data, rule, 1, 1)) - goto out_free_rule; + if (smk_parse_long_rule(data, &rule, 1, 1)) + goto out; } else { /* * More on the minor hack for backward compatibility */ if (count == (SMK_OLOADLEN)) data[SMK_OLOADLEN] = '-'; - if (smk_parse_rule(data, rule, 1)) - goto out_free_rule; + if (smk_parse_rule(data, &rule, 1)) + goto out; } if (rule_list == NULL) { load = 1; - rule_list = &rule->smk_subject->smk_rules; - rule_lock = &rule->smk_subject->smk_rules_lock; + rule_list = &rule.smk_subject->smk_rules; + rule_lock = &rule.smk_subject->smk_rules_lock; } - rc = smk_set_access(rule, rule_list, rule_lock, load); - if (rc == 0) { + rc = smk_set_access(&rule, rule_list, rule_lock, load); + if (rc == 0) rc = count; - goto out; - } - -out_free_rule: - kfree(rule); out: kfree(data); return rc; -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:44 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:44 +0900 Subject: [LTSI-dev] [PATCH 10/16] security: smack: add a hash table to quicken smk_find_entry() In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-11-git-send-email-dhobsong@igel.co.jp> From: Tomasz Stanislawski Accepted for the smack-next tree after changing the number of slots from 128 to 16. This patch adds a hash table to quicken searching of a smack label by its name. Basically, the patch improves performance of SMACK initialization. Parsing of rules involves translation from a string to a smack_known (aka label) entity which is done in smk_find_entry(). The current implementation of the function iterates over a global list of smack_known resulting in O(N) complexity for smk_find_entry(). The total complexity of SMACK initialization becomes O(rules * labels). Therefore it scales quadratically with a complexity of a system. Applying the patch reduced the complexity of smk_find_entry() to O(1) as long as number of label is in hundreds. If the number of labels is increased please update SMACK_HASH_SLOTS constant defined in security/smack/smack.h. Introducing the configuration of this constant with Kconfig or cmdline might be a good idea. The size of the hash table was adjusted experimentally. The rule set used by TIZEN contains circa 17K rules for 500 labels. The table above contains results of SMACK initialization using 'time smackctl apply' bash command. The 'Ref' is a kernel without this patch applied. The consecutive values refers to value of SMACK_HASH_SLOTS. Every measurement was repeated three times to reduce noise. | Ref | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 -------------------------------------------------------------------------------------------- Run1 | 1.156 | 1.096 | 0.883 | 0.764 | 0.692 | 0.667 | 0.649 | 0.633 | 0.634 | 0.629 | 0.620 Run2 | 1.156 | 1.111 | 0.885 | 0.764 | 0.694 | 0.661 | 0.649 | 0.651 | 0.634 | 0.638 | 0.623 Run3 | 1.160 | 1.107 | 0.886 | 0.764 | 0.694 | 0.671 | 0.661 | 0.638 | 0.631 | 0.624 | 0.638 AVG | 1.157 | 1.105 | 0.885 | 0.764 | 0.693 | 0.666 | 0.653 | 0.641 | 0.633 | 0.630 | 0.627 Surprisingly, a single hlist is slightly faster than a double-linked list. The speed-up saturates near 64 slots. Therefore I chose value 128 to provide some margin if more labels were used. It looks that IO becomes a new bottleneck. Signed-off-by: Tomasz Stanislawski (cherry picked from commit 4d7cf4a1f49f76f4069114ee08be75cd68c37c5a) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smack.h | 5 +++++ security/smack/smack_access.c | 29 ++++++++++++++++++++++++++--- security/smack/smack_lsm.c | 12 ++++++------ 3 files changed, 37 insertions(+), 9 deletions(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index 339614c..e80597a 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -53,6 +53,7 @@ */ struct smack_known { struct list_head list; + struct hlist_node smk_hashed; char *smk_known; u32 smk_secid; struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */ @@ -222,6 +223,7 @@ char *smk_parse_smack(const char *string, int len); int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); char *smk_import(const char *, int); struct smack_known *smk_import_entry(const char *, int); +void smk_insert_entry(struct smack_known *skp); struct smack_known *smk_find_entry(const char *); u32 smack_to_secid(const char *); @@ -247,6 +249,9 @@ extern struct list_head smk_netlbladdr_list; extern struct security_operations smack_ops; +#define SMACK_HASH_SLOTS 16 +extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS]; + /* * Is the directory transmuting? */ diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 6a0377f..b3b59b1 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -325,6 +325,25 @@ void smack_log(char *subject_label, char *object_label, int request, DEFINE_MUTEX(smack_known_lock); +struct hlist_head smack_known_hash[SMACK_HASH_SLOTS]; + +/** + * smk_insert_entry - insert a smack label into a hash map, + * + * this function must be called under smack_known_lock + */ +void smk_insert_entry(struct smack_known *skp) +{ + unsigned int hash; + struct hlist_head *head; + + hash = full_name_hash(skp->smk_known, strlen(skp->smk_known)); + head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)]; + + hlist_add_head_rcu(&skp->smk_hashed, head); + list_add_rcu(&skp->list, &smack_known_list); +} + /** * smk_find_entry - find a label on the list, return the list entry * @string: a text string that might be a Smack label @@ -334,12 +353,16 @@ DEFINE_MUTEX(smack_known_lock); */ struct smack_known *smk_find_entry(const char *string) { + unsigned int hash; + struct hlist_head *head; struct smack_known *skp; - list_for_each_entry_rcu(skp, &smack_known_list, list) { + hash = full_name_hash(string, strlen(string)); + head = &smack_known_hash[hash & (SMACK_HASH_SLOTS - 1)]; + + hlist_for_each_entry_rcu(skp, head, smk_hashed) if (strcmp(skp->smk_known, string) == 0) return skp; - } return NULL; } @@ -475,7 +498,7 @@ struct smack_known *smk_import_entry(const char *string, int len) * Make sure that the entry is actually * filled before putting it on the list. */ - list_add_rcu(&skp->list, &smack_known_list); + smk_insert_entry(skp); goto unlockout; } /* diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index a113a77..f70a0fa 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3876,12 +3876,12 @@ static __init void init_smack_known_list(void) /* * Create the known labels list */ - list_add(&smack_known_huh.list, &smack_known_list); - list_add(&smack_known_hat.list, &smack_known_list); - list_add(&smack_known_star.list, &smack_known_list); - list_add(&smack_known_floor.list, &smack_known_list); - list_add(&smack_known_invalid.list, &smack_known_list); - list_add(&smack_known_web.list, &smack_known_list); + smk_insert_entry(&smack_known_huh); + smk_insert_entry(&smack_known_hat); + smk_insert_entry(&smack_known_star); + smk_insert_entry(&smack_known_floor); + smk_insert_entry(&smack_known_invalid); + smk_insert_entry(&smack_known_web); } /** -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:45 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:45 +0900 Subject: [LTSI-dev] [PATCH 11/16] Smack: network label match fix In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-12-git-send-email-dhobsong@igel.co.jp> From: Casey Schaufler The Smack code that matches incoming CIPSO tags with Smack labels reaches through the NetLabel interfaces and compares the network data with the CIPSO header associated with a Smack label. This was done in a ill advised attempt to optimize performance. It works so long as the categories fit in a single capset, but this isn't always the case. This patch changes the Smack code to use the appropriate NetLabel interfaces to compare the incoming CIPSO header with the CIPSO header associated with a label. It will always match the CIPSO headers correctly. Targeted for git://git.gitorious.org/smack-next/kernel.git Signed-off-by: Casey Schaufler (cherry picked from commit 677264e8fb73ea35a508700e19ce76c527576d1c) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smack.h | 8 ++++++-- security/smack/smack_lsm.c | 30 ++++++++++++++++++++++++------ security/smack/smackfs.c | 2 +- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index e80597a..076b8e8 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -168,9 +168,13 @@ struct smk_port_label { #define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */ #define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ #define SMACK_CIPSO_MAPPED_DEFAULT 251 /* Also arbitrary */ -#define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ #define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ -#define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ +/* + * CIPSO 2.2 standard is 239, but Smack wants to use the + * categories in a structured way that limits the value to + * the bits in 23 bytes, hence the unusual number. + */ +#define SMACK_CIPSO_MAXCATNUM 184 /* 23 * 8 */ /* * Flag for transmute access diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index f70a0fa..19de5e2 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -3063,6 +3063,8 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, { struct smack_known *skp; int found = 0; + int acat; + int kcat; if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { /* @@ -3079,12 +3081,28 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, list_for_each_entry(skp, &smack_known_list, list) { if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl) continue; - if (memcmp(sap->attr.mls.cat, - skp->smk_netlabel.attr.mls.cat, - SMK_CIPSOLEN) != 0) - continue; - found = 1; - break; + /* + * Compare the catsets. Use the netlbl APIs. + */ + if ((sap->flags & NETLBL_SECATTR_MLS_CAT) == 0) { + if ((skp->smk_netlabel.flags & + NETLBL_SECATTR_MLS_CAT) == 0) + found = 1; + break; + } + for (acat = -1, kcat = -1; acat == kcat; ) { + acat = netlbl_secattr_catmap_walk( + sap->attr.mls.cat, acat + 1); + kcat = netlbl_secattr_catmap_walk( + skp->smk_netlabel.attr.mls.cat, + kcat + 1); + if (acat < 0 || kcat < 0) + break; + } + if (acat == kcat) { + found = 1; + break; + } } rcu_read_unlock(); diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 269b270..a07e93f 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -890,7 +890,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, for (i = 0; i < catlen; i++) { rule += SMK_DIGITLEN; ret = sscanf(rule, "%u", &cat); - if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL) + if (ret != 1 || cat > SMACK_CIPSO_MAXCATNUM) goto out; smack_catset_bit(cat, mapcatset); -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:46 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:46 +0900 Subject: [LTSI-dev] [PATCH 12/16] Smack: IPv6 casting error fix for 3.11 In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-13-git-send-email-dhobsong@igel.co.jp> From: Casey Schaufler The original implementation of the Smack IPv6 port based local controls works most of the time using a sockaddr as a temporary variable, but not always as it overflows in some circumstances. The correct data is a sockaddr_in6. A struct sockaddr isn't as large as a struct sockaddr_in6. There would need to be casting one way or the other. This patch gets it the right way. Signed-off-by: Casey Schaufler Signed-off-by: James Morris (cherry picked from commit 6ea062475a9a2ea6e1394487fa0e51b3459957d1) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smack_lsm.c | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 19de5e2..8825375 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1995,12 +1995,11 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address) * * Create or update the port list entry */ -static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, +static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, int act) { __be16 *bep; __be32 *be32p; - struct sockaddr_in6 *addr6; struct smk_port_label *spp; struct socket_smack *ssp = sk->sk_security; struct smack_known *skp; @@ -2022,10 +2021,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, /* * Get the IP address and port from the address. */ - addr6 = (struct sockaddr_in6 *)address; - port = ntohs(addr6->sin6_port); - bep = (__be16 *)(&addr6->sin6_addr); - be32p = (__be32 *)(&addr6->sin6_addr); + port = ntohs(address->sin6_port); + bep = (__be16 *)(&address->sin6_addr); + be32p = (__be32 *)(&address->sin6_addr); /* * It's remote, so port lookup does no good. @@ -2057,9 +2055,9 @@ auditout: ad.a.u.net->family = sk->sk_family; ad.a.u.net->dport = port; if (act == SMK_RECEIVING) - ad.a.u.net->v6info.saddr = addr6->sin6_addr; + ad.a.u.net->v6info.saddr = address->sin6_addr; else - ad.a.u.net->v6info.daddr = addr6->sin6_addr; + ad.a.u.net->v6info.daddr = address->sin6_addr; #endif return smk_access(skp, object, MAY_WRITE, &ad); } @@ -2198,7 +2196,8 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, case PF_INET6: if (addrlen < sizeof(struct sockaddr_in6)) return -EINVAL; - rc = smk_ipv6_port_check(sock->sk, sap, SMK_CONNECTING); + rc = smk_ipv6_port_check(sock->sk, (struct sockaddr_in6 *)sap, + SMK_CONNECTING); break; } return rc; @@ -3031,7 +3030,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; - struct sockaddr *sap = (struct sockaddr *) msg->msg_name; + struct sockaddr_in6 *sap = (struct sockaddr_in6 *) msg->msg_name; int rc = 0; /* @@ -3136,9 +3135,8 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, return smack_net_ambient; } -static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr *sap) +static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) { - struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; u8 nexthdr; int offset; int proto = -EINVAL; @@ -3196,7 +3194,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) struct netlbl_lsm_secattr secattr; struct socket_smack *ssp = sk->sk_security; struct smack_known *skp; - struct sockaddr sadd; + struct sockaddr_in6 sadd; int rc = 0; struct smk_audit_info ad; #ifdef CONFIG_AUDIT -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:47 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:47 +0900 Subject: [LTSI-dev] [PATCH 13/16] Smack: parse multiple rules per write to load2, up to PAGE_SIZE-1 bytes In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-14-git-send-email-dhobsong@igel.co.jp> From: Rafal Krypa Smack interface for loading rules has always parsed only single rule from data written to it. This requires user program to call one write() per each rule it wants to load. This change makes it possible to write multiple rules, separated by new line character. Smack will load at most PAGE_SIZE-1 characters and properly return number of processed bytes. In case when user buffer is larger, it will be additionally truncated. All characters after last \n will not get parsed to avoid partial rule near input buffer boundary. Signed-off-by: Rafal Krypa (cherry picked from commit 10289b0f738e8b301969f2288c4942455f1b1e59) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smackfs.c | 167 +++++++++++++++++++++++----------------------- 1 file changed, 82 insertions(+), 85 deletions(-) diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index a07e93f..80f4b4a 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -368,56 +368,43 @@ static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule, * @data: string to be parsed, null terminated * @rule: Will be filled with Smack parsed rule * @import: if non-zero, import labels - * @change: if non-zero, data is from /smack/change-rule + * @tokens: numer of substrings expected in data * - * Returns 0 on success, -1 on failure + * Returns number of processed bytes on success, -1 on failure. */ -static int smk_parse_long_rule(const char *data, struct smack_parsed_rule *rule, - int import, int change) +static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule, + int import, int tokens) { - char *subject; - char *object; - char *access1; - char *access2; - int datalen; - int rc = -1; + ssize_t cnt = 0; + char *tok[4]; + int i; - /* This is inefficient */ - datalen = strlen(data); + /* + * Parsing the rule in-place, filling all white-spaces with '\0' + */ + for (i = 0; i < tokens; ++i) { + while (isspace(data[cnt])) + data[cnt++] = '\0'; - /* Our first element can be 64 + \0 with no spaces */ - subject = kzalloc(datalen + 1, GFP_KERNEL); - if (subject == NULL) - return -1; - object = kzalloc(datalen, GFP_KERNEL); - if (object == NULL) - goto free_out_s; - access1 = kzalloc(datalen, GFP_KERNEL); - if (access1 == NULL) - goto free_out_o; - access2 = kzalloc(datalen, GFP_KERNEL); - if (access2 == NULL) - goto free_out_a; - - if (change) { - if (sscanf(data, "%s %s %s %s", - subject, object, access1, access2) == 4) - rc = smk_fill_rule(subject, object, access1, access2, - rule, import, 0); - } else { - if (sscanf(data, "%s %s %s", subject, object, access1) == 3) - rc = smk_fill_rule(subject, object, access1, NULL, - rule, import, 0); + if (data[cnt] == '\0') + /* Unexpected end of data */ + return -1; + + tok[i] = data + cnt; + + while (data[cnt] && !isspace(data[cnt])) + ++cnt; } + while (isspace(data[cnt])) + data[cnt++] = '\0'; - kfree(access2); -free_out_a: - kfree(access1); -free_out_o: - kfree(object); -free_out_s: - kfree(subject); - return rc; + while (i < 4) + tok[i++] = NULL; + + if (smk_fill_rule(tok[0], tok[1], tok[2], tok[3], rule, import, 0)) + return -1; + + return cnt; } #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ @@ -449,9 +436,10 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, { struct smack_parsed_rule rule; char *data; - int datalen; - int rc = -EINVAL; - int load = 0; + int rc; + int trunc = 0; + int tokens; + ssize_t cnt = 0; /* * No partial writes. @@ -466,11 +454,14 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, */ if (count != SMK_OLOADLEN && count != SMK_LOADLEN) return -EINVAL; - datalen = SMK_LOADLEN; - } else - datalen = count + 1; + } else { + if (count >= PAGE_SIZE) { + count = PAGE_SIZE - 1; + trunc = 1; + } + } - data = kzalloc(datalen, GFP_KERNEL); + data = kmalloc(count + 1, GFP_KERNEL); if (data == NULL) return -ENOMEM; @@ -479,36 +470,49 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, goto out; } - if (format == SMK_LONG_FMT) { - /* - * Be sure the data string is terminated. - */ - data[count] = '\0'; - if (smk_parse_long_rule(data, &rule, 1, 0)) - goto out; - } else if (format == SMK_CHANGE_FMT) { - data[count] = '\0'; - if (smk_parse_long_rule(data, &rule, 1, 1)) - goto out; - } else { - /* - * More on the minor hack for backward compatibility - */ - if (count == (SMK_OLOADLEN)) - data[SMK_OLOADLEN] = '-'; - if (smk_parse_rule(data, &rule, 1)) + /* + * In case of parsing only part of user buf, + * avoid having partial rule at the data buffer + */ + if (trunc) { + while (count > 0 && (data[count - 1] != '\n')) + --count; + if (count == 0) { + rc = -EINVAL; goto out; + } } - if (rule_list == NULL) { - load = 1; - rule_list = &rule.smk_subject->smk_rules; - rule_lock = &rule.smk_subject->smk_rules_lock; + data[count] = '\0'; + tokens = (format == SMK_CHANGE_FMT ? 4 : 3); + while (cnt < count) { + if (format == SMK_FIXED24_FMT) { + rc = smk_parse_rule(data, &rule, 1); + if (rc != 0) { + rc = -EINVAL; + goto out; + } + cnt = count; + } else { + rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens); + if (rc <= 0) { + rc = -EINVAL; + goto out; + } + cnt += rc; + } + + if (rule_list == NULL) + rc = smk_set_access(&rule, &rule.smk_subject->smk_rules, + &rule.smk_subject->smk_rules_lock, 1); + else + rc = smk_set_access(&rule, rule_list, rule_lock, 0); + + if (rc) + goto out; } - rc = smk_set_access(&rule, rule_list, rule_lock, load); - if (rc == 0) - rc = count; + rc = cnt; out: kfree(data); return rc; @@ -1829,7 +1833,6 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, { struct smack_parsed_rule rule; char *data; - char *cod; int res; data = simple_transaction_get(file, buf, count); @@ -1842,18 +1845,12 @@ static ssize_t smk_user_access(struct file *file, const char __user *buf, res = smk_parse_rule(data, &rule, 0); } else { /* - * Copy the data to make sure the string is terminated. + * simple_transaction_get() returns null-terminated data */ - cod = kzalloc(count + 1, GFP_KERNEL); - if (cod == NULL) - return -ENOMEM; - memcpy(cod, data, count); - cod[count] = '\0'; - res = smk_parse_long_rule(cod, &rule, 0, 0); - kfree(cod); + res = smk_parse_long_rule(data, &rule, 0, 3); } - if (res) + if (res < 0) return -EINVAL; res = smk_access(rule.smk_subject, rule.smk_object, -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:48 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:48 +0900 Subject: [LTSI-dev] [PATCH 14/16] Smack: Implement lock security mode In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-15-git-send-email-dhobsong@igel.co.jp> From: Casey Schaufler Linux file locking does not follow the same rules as other mechanisms. Even though it is a write operation a process can set a read lock on files which it has open only for read access. Two programs with read access to a file can use read locks to communicate. This is not acceptable in a Mandatory Access Control environment. Smack treats setting a read lock as the write operation that it is. Unfortunately, many programs assume that setting a read lock is a read operation. These programs are unhappy in the Smack environment. This patch introduces a new access mode (lock) to address this problem. A process with lock access to a file can set a read lock. A process with write access to a file can set a read lock or a write lock. This prevents a situation where processes are granted write access just so they can set read locks. Targeted for git://git.gitorious.org/smack-next/kernel.git Signed-off-by: Casey Schaufler (cherry picked from commit c0ab6e56dcb7ca9903d460247cb464e769ae6e77) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smack.h | 12 ++++++++---- security/smack/smack_access.c | 10 ++++++++++ security/smack/smack_lsm.c | 9 +++++++-- security/smack/smackfs.c | 10 ++++++++-- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/security/smack/smack.h b/security/smack/smack.h index 076b8e8..364cc64 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -177,9 +177,13 @@ struct smk_port_label { #define SMACK_CIPSO_MAXCATNUM 184 /* 23 * 8 */ /* - * Flag for transmute access + * Flags for untraditional access modes. + * It shouldn't be necessary to avoid conflicts with definitions + * in fs.h, but do so anyway. */ -#define MAY_TRANSMUTE 64 +#define MAY_TRANSMUTE 0x00001000 /* Controls directory labeling */ +#define MAY_LOCK 0x00002000 /* Locks should be writes, but ... */ + /* * Just to make the common cases easier to deal with */ @@ -188,9 +192,9 @@ struct smk_port_label { #define MAY_NOT 0 /* - * Number of access types used by Smack (rwxat) + * Number of access types used by Smack (rwxatl) */ -#define SMK_NUM_ACCESS_TYPE 5 +#define SMK_NUM_ACCESS_TYPE 6 /* SMACK data */ struct smack_audit_data { diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index b3b59b1..14293cd 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c @@ -84,6 +84,8 @@ int log_policy = SMACK_AUDIT_DENIED; * * Do the object check first because that is more * likely to differ. + * + * Allowing write access implies allowing locking. */ int smk_access_entry(char *subject_label, char *object_label, struct list_head *rule_list) @@ -99,6 +101,11 @@ int smk_access_entry(char *subject_label, char *object_label, } } + /* + * MAY_WRITE implies MAY_LOCK. + */ + if ((may & MAY_WRITE) == MAY_WRITE) + may |= MAY_LOCK; return may; } @@ -245,6 +252,7 @@ out_audit: static inline void smack_str_from_perm(char *string, int access) { int i = 0; + if (access & MAY_READ) string[i++] = 'r'; if (access & MAY_WRITE) @@ -255,6 +263,8 @@ static inline void smack_str_from_perm(char *string, int access) string[i++] = 'a'; if (access & MAY_TRANSMUTE) string[i++] = 't'; + if (access & MAY_LOCK) + string[i++] = 'l'; string[i] = '\0'; } /** diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 8825375..88d366e5 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1146,7 +1146,7 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd, * @file: the object * @cmd: unused * - * Returns 0 if current has write access, error code otherwise + * Returns 0 if current has lock access, error code otherwise */ static int smack_file_lock(struct file *file, unsigned int cmd) { @@ -1154,7 +1154,7 @@ static int smack_file_lock(struct file *file, unsigned int cmd) smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); smk_ad_setfield_u_fs_path(&ad, file->f_path); - return smk_curacc(file->f_security, MAY_WRITE, &ad); + return smk_curacc(file->f_security, MAY_LOCK, &ad); } /** @@ -1178,8 +1178,13 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, switch (cmd) { case F_GETLK: + break; case F_SETLK: case F_SETLKW: + smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); + smk_ad_setfield_u_fs_path(&ad, file->f_path); + rc = smk_curacc(file->f_security, MAY_LOCK, &ad); + break; case F_SETOWN: case F_SETSIG: smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 80f4b4a..160aa08 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -139,7 +139,7 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION; * SMK_LOADLEN: Smack rule length */ #define SMK_OACCESS "rwxa" -#define SMK_ACCESS "rwxat" +#define SMK_ACCESS "rwxatl" #define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1) #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) @@ -282,6 +282,10 @@ static int smk_perm_from_str(const char *string) case 'T': perm |= MAY_TRANSMUTE; break; + case 'l': + case 'L': + perm |= MAY_LOCK; + break; default: return perm; } @@ -452,7 +456,7 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, /* * Minor hack for backward compatibility */ - if (count != SMK_OLOADLEN && count != SMK_LOADLEN) + if (count < SMK_OLOADLEN || count > SMK_LOADLEN) return -EINVAL; } else { if (count >= PAGE_SIZE) { @@ -592,6 +596,8 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) seq_putc(s, 'a'); if (srp->smk_access & MAY_TRANSMUTE) seq_putc(s, 't'); + if (srp->smk_access & MAY_LOCK) + seq_putc(s, 'l'); seq_putc(s, '\n'); } -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:49 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:49 +0900 Subject: [LTSI-dev] [PATCH 15/16] Smack: Ptrace access check mode In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-16-git-send-email-dhobsong@igel.co.jp> From: Casey Schaufler When the ptrace security hooks were split the addition of a mode parameter was not taken advantage of in the Smack ptrace access check. This changes the access check from always looking for read and write access to using the passed mode. This will make use of /proc much happier. Targeted for git://git.gitorious.org/smack-next/kernel.git Signed-off-by: Casey Schaufler (cherry picked from commit b5dfd8075bc26636d11c3d8888940198afbf5112) Signed-off-by: Damian Hobson-Garcia Signed-off-by: Tomohito Esaki --- security/smack/smack_lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 88d366e5..b0be893 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -185,7 +185,7 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); smk_ad_setfield_u_tsk(&ad, ctp); - rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); + rc = smk_curacc(skp->smk_known, mode, &ad); return rc; } -- 1.7.9.5 From dhobsong at igel.co.jp Thu Jul 31 03:26:50 2014 From: dhobsong at igel.co.jp (Damian Hobson-Garcia) Date: Thu, 31 Jul 2014 12:26:50 +0900 Subject: [LTSI-dev] [PATCH 16/16] Smack: Label cgroup files for systemd In-Reply-To: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> References: <1406777210-28425-1-git-send-email-dhobsong@igel.co.jp> Message-ID: <1406777210-28425-17-git-send-email-dhobsong@igel.co.jp> From: Casey Schaufler The cgroup filesystem isn't ready for an LSM to properly use extented attributes. This patch makes files created in the cgroup filesystem usable by a system running Smack and systemd. Targeted for git://git.gitorious.org/smack-next/kernel.git Signed-off-by: Casey Schaufler (cherry picked from commit 36ea735b522d09826ae0dac0e540f294436c52f3) Signed-off-by: Damian Hobson-Garcia --- security/smack/smack_lsm.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index b0be893..3f01cf5 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2726,6 +2726,15 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) * of the superblock. */ if (opt_dentry->d_parent == opt_dentry) { + if (sbp->s_magic == CGROUP_SUPER_MAGIC) { + /* + * The cgroup filesystem is never mounted, + * so there's no opportunity to set the mount + * options. + */ + sbsp->smk_root = smack_known_star.smk_known; + sbsp->smk_default = smack_known_star.smk_known; + } isp->smk_inode = sbsp->smk_root; isp->smk_flags |= SMK_INODE_INSTANT; goto unlockandout; @@ -2739,16 +2748,20 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) */ switch (sbp->s_magic) { case SMACK_MAGIC: + case PIPEFS_MAGIC: + case SOCKFS_MAGIC: + case CGROUP_SUPER_MAGIC: /* * Casey says that it's a little embarrassing * that the smack file system doesn't do * extended attributes. - */ - final = smack_known_star.smk_known; - break; - case PIPEFS_MAGIC: - /* + * * Casey says pipes are easy (?) + * + * Socket access is controlled by the socket + * structures associated with the task involved. + * + * Cgroupfs is special */ final = smack_known_star.smk_known; break; @@ -2760,13 +2773,6 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) */ final = ckp->smk_known; break; - case SOCKFS_MAGIC: - /* - * Socket access is controlled by the socket - * structures associated with the task involved. - */ - final = smack_known_star.smk_known; - break; case PROC_SUPER_MAGIC: /* * Casey says procfs appears not to care. -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:24:21 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:24:21 -0000 Subject: [LTSI-dev] [PATCH 00/50] Baytrail Backport Patches from mainline 3.13 to LTSI 3.10 Message-ID: <1406258864-18901-1-git-send-email-dheerajx.s.jamwal@intel.com> Hi Greg, Please consider the following Baytrail i915 backport patches for LTSI 3.10 from mainline 3.13 kernel. we have kept all the commit information intact by using cherry pick options. we have tested the patches by creating a yocto image, booted it on Baytrail Platform and verified the below scenarios Analog Display Passed 1280x1024 at 60Hz 1280x1024 at 75Hz HDMI Display Passed 1920x1080 at 60Hz 1600x1200 at 60Hz Dual Display Passed Clone Mode Passed Extended Mode Passed 3D Rendering Passed Open GL Rendering String Passed Glxgears Running Passed Video PlayBack(verifed with the mp4, png,avi files) Passed Restart/shutdown/standby Passed Thanks, Dheeraj Artem Bityutskiy (1): drm/i915: preserve dispaly init order on ByT Ben Widawsky (6): drm/i915: Do a fuller init after reset drm/i915: cleanup context fini drm/i915: Replace has_bsd/blt/vebox with a mask drm/i915: Make PTE valid encoding optional drm/i915: Disable GGTT PTEs on GEN6+ suspend drm/i915: Print RC6 info less often Chon Ming Lee (1): drm/i915: Move some hdmi enable function name to vlv specific. Chris Wilson (2): drm/i915: Disable all GEM timers and work on unload drm/i915: Whitespace alignment fix for block header in display error state Damien Lespiau (15): drm/i915: Keep the CRC values into a circular buffer drm/i915: Sample the frame counter instead of a timestamp for CRCs drm/i915: Make switching to the same CRC source a no-op drm/i915: Enforce going back to none before changing CRC source drm/i915: Empty the circular buffer when asked for a new source drm/i915: Dynamically allocate the CRC circular buffer drm/i915: Generalize the CRC command format for future work drm/i915: Rename i915_pipe_crc_ctl to i915_display_crc_ctl drm/i915: Warn if we receive an interrupt after freeing the buffer drm/i915: Add log messages when CRCs collection is started/stopped drm/i915: Move drm_add_fake_info_node() higher in the file drm/i915: Implement blocking read for pipe CRC files drm/i915: Only one open() allowed on pipe CRC result files drm/i915: Enable pipe CRCs drm/i915: Use pipe_name() instead of the pipe number Daniel Vetter (19): drm/i915: Add a control file for pipe CRCs drm/i915: static inline for dummy crc functions drm/i915: constify harder drm/i915: grab dev->struct_mutex around framebuffer_init drm/i915: prevent tiling changes on framebuffer backing storage drm/i915: Use unsigned long for obj->user_pin_count drm/i915: check gem bo size when creating framebuffers drm/i915: don't Oops in debugfs for I915_FBDEV=n drm/i915: extract display_pipe_crc_update drm/i915: add CRC #defines for ilk/snb drm/i915: wire up CRC interrupt for ilk/snb drm/i915: use ->get_vblank_counter for the crc frame counter drm/i915: wait one vblank when disabling CRCs drm/i915: fix CRC debugfs setup drm/i915: crc support for hsw drm/i915: remove dead code in ironlake_crtc_mode_set drm/i915: Adjust CRC capture for pre-gen5/vlv drm/i915: CRC source selection #defines for gmch/vlv chips drm/i915: Wire up CRC interrupts for pre-gen5/vlv Imre Deak (1): drm/i915: vlv: fix VGA hotplug after modeset Jani Nikula (3): drm/i915: pass mode to ELD write vfuncs drm/i915: set HDMI pixel clock in audio configuration drm/i915/dp: don't mention eDP bpp clamping if it doesn't affect bpp Paulo Zanoni (1): drm/i915: fix open-coded DIV_ROUND_UP Shuang He (1): drm/i915: Expose latest 200 CRC value for pipe through debugfs drivers/gpu/drm/i915/i915_debugfs.c | 546 +++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_dma.c | 10 +- drivers/gpu/drm/i915/i915_drv.c | 70 ++-- drivers/gpu/drm/i915/i915_drv.h | 85 +++-- drivers/gpu/drm/i915/i915_gem.c | 54 +-- drivers/gpu/drm/i915/i915_gem_context.c | 17 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 109 ++++-- drivers/gpu/drm/i915/i915_gem_tiling.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 147 ++++++++- drivers/gpu/drm/i915/i915_reg.h | 101 +++++- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 119 +++++-- drivers/gpu/drm/i915/intel_dp.c | 5 +- drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_fbdev.c | 4 +- drivers/gpu/drm/i915/intel_hdmi.c | 12 +- drivers/gpu/drm/i915/intel_panel.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 54 ++- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 +- 19 files changed, 1110 insertions(+), 235 deletions(-) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:34 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:34 -0000 Subject: [LTSI-dev] [PATCH 01/50] drm/i915: Do a fuller init after reset In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-2-git-send-email-dheerajx.s.jamwal@intel.com> From: Ben Widawsky I had this lying around from he original PPGTT series, and thought we might try to get it in by itself. It's convenient to just call i915_gem_init_hw at reset because we'll be adding new things to that function, and having just one function to call instead of reimplementing it in two places is nice. In order to accommodate we cleanup ringbuffers in order to bring them back up cleanly. Optionally, we could also teardown/re initialize the default context but this was causing some problems on reset which I wasn't able to fully debug, and is unnecessary with the previous context init/enable split. This essentially reverts: commit 8e88a2bd5987178d16d53686197404e149e996d9 Author: Daniel Vetter Date: Tue Jun 19 18:40:00 2012 +0200 drm/i915: don't call modeset_init_hw in i915_reset It seems to work for me on ILK now. Perhaps it's due to: commit 8a5c2ae753c588bcb2a4e38d1c6a39865dbf1ff3 Author: Jesse Barnes Date: Thu Mar 28 13:57:19 2013 -0700 drm/i915: fix ILK GPU reset for render Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter (cherry picked from commit 3d57e5bd1284f44e325f3a52d966259ed42f9e05) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_drv.c | 29 ++++++++--------------------- drivers/gpu/drm/i915/i915_gem.c | 2 ++ drivers/gpu/drm/i915/intel_ringbuffer.c | 4 +++- 3 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 8ac8e81..837813b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -744,30 +744,17 @@ int i915_reset(struct drm_device *dev) */ if (drm_core_check_feature(dev, DRIVER_MODESET) || !dev_priv->ums.mm_suspended) { - struct intel_ring_buffer *ring; - int i; - + bool hw_contexts_disabled = dev_priv->hw_contexts_disabled; dev_priv->ums.mm_suspended = 0; - i915_gem_init_swizzling(dev); - - for_each_ring(ring, dev_priv, i) - ring->init(ring); - - i915_gem_context_init(dev); - if (dev_priv->mm.aliasing_ppgtt) { - ret = dev_priv->mm.aliasing_ppgtt->enable(dev); - if (ret) - i915_gem_cleanup_aliasing_ppgtt(dev); - } - - /* - * It would make sense to re-init all the other hw state, at - * least the rps/rc6/emon init done within modeset_init_hw. For - * some unknown reason, this blows up my ilk, so don't. - */ - + ret = i915_gem_init_hw(dev); + if (!hw_contexts_disabled && dev_priv->hw_contexts_disabled) + DRM_ERROR("HW contexts didn't survive reset\n"); mutex_unlock(&dev->struct_mutex); + if (ret) { + DRM_ERROR("Failed hw init on reset %d\n", ret); + return ret; + } drm_irq_uninstall(dev); drm_irq_install(dev); diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 729e5c3..cf2bafa 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2400,6 +2400,8 @@ void i915_gem_reset(struct drm_device *dev) for_each_ring(ring, dev_priv, i) i915_gem_reset_ring_lists(dev_priv, ring); + i915_gem_cleanup_ringbuffer(dev); + i915_gem_restore_fences(dev); } diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 213a8b4..d03424e 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -1324,7 +1324,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) /* Disable the ring buffer. The ring must be idle at this point */ dev_priv = ring->dev->dev_private; ret = intel_ring_idle(ring); - if (ret) + if (ret && !i915_reset_in_progress(&dev_priv->gpu_error)) DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n", ring->name, ret); @@ -1335,6 +1335,8 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring) i915_gem_object_unpin(ring->obj); drm_gem_object_unreference(&ring->obj->base); ring->obj = NULL; + ring->preallocated_lazy_request = NULL; + ring->outstanding_lazy_seqno = 0; if (ring->cleanup) ring->cleanup(ring); -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:35 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:35 -0000 Subject: [LTSI-dev] [PATCH 00/50] Baytrail Backport Patches from mainline 3.13 to LTSI 3.10 Message-ID: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Hi Greg, Please consider the following Baytrail i915 backport patches for LTSI 3.10 from mainline 3.13 kernel. we have kept all the commit information intact by using cherry pick options. we have tested the patches by creating a yocto image, booted it on Baytrail Platform and verified the below scenarios Analog Display Passed 1280x1024 at 60Hz 1280x1024 at 75Hz HDMI Display Passed 1920x1080 at 60Hz 1600x1200 at 60Hz Dual Display Passed Clone Mode Passed Extended Mode Passed 3D Rendering Passed Open GL Rendering String Passed Glxgears Running Passed Video PlayBack(verifed with the mp4, png,avi files) Passed Restart/shutdown/standby Passed Thanks, Dheeraj Artem Bityutskiy (1): drm/i915: preserve dispaly init order on ByT Ben Widawsky (6): drm/i915: Do a fuller init after reset drm/i915: cleanup context fini drm/i915: Replace has_bsd/blt/vebox with a mask drm/i915: Make PTE valid encoding optional drm/i915: Disable GGTT PTEs on GEN6+ suspend drm/i915: Print RC6 info less often Chon Ming Lee (1): drm/i915: Move some hdmi enable function name to vlv specific. Chris Wilson (2): drm/i915: Disable all GEM timers and work on unload drm/i915: Whitespace alignment fix for block header in display error state Damien Lespiau (15): drm/i915: Keep the CRC values into a circular buffer drm/i915: Sample the frame counter instead of a timestamp for CRCs drm/i915: Make switching to the same CRC source a no-op drm/i915: Enforce going back to none before changing CRC source drm/i915: Empty the circular buffer when asked for a new source drm/i915: Dynamically allocate the CRC circular buffer drm/i915: Generalize the CRC command format for future work drm/i915: Rename i915_pipe_crc_ctl to i915_display_crc_ctl drm/i915: Warn if we receive an interrupt after freeing the buffer drm/i915: Add log messages when CRCs collection is started/stopped drm/i915: Move drm_add_fake_info_node() higher in the file drm/i915: Implement blocking read for pipe CRC files drm/i915: Only one open() allowed on pipe CRC result files drm/i915: Enable pipe CRCs drm/i915: Use pipe_name() instead of the pipe number Daniel Vetter (19): drm/i915: Add a control file for pipe CRCs drm/i915: static inline for dummy crc functions drm/i915: constify harder drm/i915: grab dev->struct_mutex around framebuffer_init drm/i915: prevent tiling changes on framebuffer backing storage drm/i915: Use unsigned long for obj->user_pin_count drm/i915: check gem bo size when creating framebuffers drm/i915: don't Oops in debugfs for I915_FBDEV=n drm/i915: extract display_pipe_crc_update drm/i915: add CRC #defines for ilk/snb drm/i915: wire up CRC interrupt for ilk/snb drm/i915: use ->get_vblank_counter for the crc frame counter drm/i915: wait one vblank when disabling CRCs drm/i915: fix CRC debugfs setup drm/i915: crc support for hsw drm/i915: remove dead code in ironlake_crtc_mode_set drm/i915: Adjust CRC capture for pre-gen5/vlv drm/i915: CRC source selection #defines for gmch/vlv chips drm/i915: Wire up CRC interrupts for pre-gen5/vlv Imre Deak (1): drm/i915: vlv: fix VGA hotplug after modeset Jani Nikula (3): drm/i915: pass mode to ELD write vfuncs drm/i915: set HDMI pixel clock in audio configuration drm/i915/dp: don't mention eDP bpp clamping if it doesn't affect bpp Paulo Zanoni (1): drm/i915: fix open-coded DIV_ROUND_UP Shuang He (1): drm/i915: Expose latest 200 CRC value for pipe through debugfs drivers/gpu/drm/i915/i915_debugfs.c | 546 +++++++++++++++++++++++++++++-- drivers/gpu/drm/i915/i915_dma.c | 10 +- drivers/gpu/drm/i915/i915_drv.c | 70 ++-- drivers/gpu/drm/i915/i915_drv.h | 85 +++-- drivers/gpu/drm/i915/i915_gem.c | 54 +-- drivers/gpu/drm/i915/i915_gem_context.c | 17 +- drivers/gpu/drm/i915/i915_gem_gtt.c | 109 ++++-- drivers/gpu/drm/i915/i915_gem_tiling.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 147 ++++++++- drivers/gpu/drm/i915/i915_reg.h | 101 +++++- drivers/gpu/drm/i915/intel_crt.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 119 +++++-- drivers/gpu/drm/i915/intel_dp.c | 5 +- drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_fbdev.c | 4 +- drivers/gpu/drm/i915/intel_hdmi.c | 12 +- drivers/gpu/drm/i915/intel_panel.c | 2 +- drivers/gpu/drm/i915/intel_pm.c | 54 ++- drivers/gpu/drm/i915/intel_ringbuffer.c | 4 +- 19 files changed, 1110 insertions(+), 235 deletions(-) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:36 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:36 -0000 Subject: [LTSI-dev] [PATCH 02/50] drm/i915: cleanup context fini In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-3-git-send-email-dheerajx.s.jamwal@intel.com> From: Ben Widawsky I had this lying around from he original PPGTT series, and thought we might try to get it in by itself. With the introduction of context refcounting we never explicitly ref/unref the backing object. As such, the previous fix was a bit wonky. Aside from fixing the above, this patch also puts us in good shape for an upcoming patch which allows a failure to occur in between context_init and the first do_switch. CC: Mika Kuoppala Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter (cherry picked from commit 71b76d004f48b4b217a3895bfe058e2e5eefed39) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_gem_context.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index e41dce0..a613380 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c @@ -220,7 +220,6 @@ static int create_default_context(struct drm_i915_private *dev_priv) * may not be available. To avoid this we always pin the * default context. */ - dev_priv->ring[RCS].default_context = ctx; ret = i915_gem_obj_ggtt_pin(ctx->obj, CONTEXT_ALIGN, false, false); if (ret) { DRM_DEBUG_DRIVER("Couldn't pin %d\n", ret); @@ -233,6 +232,8 @@ static int create_default_context(struct drm_i915_private *dev_priv) goto err_unpin; } + dev_priv->ring[RCS].default_context = ctx; + DRM_DEBUG_DRIVER("Default HW context loaded\n"); return 0; @@ -288,16 +289,24 @@ void i915_gem_context_fini(struct drm_device *dev) * other code, leading to spurious errors. */ intel_gpu_reset(dev); - i915_gem_object_unpin(dctx->obj); - /* When default context is created and switched to, base object refcount * will be 2 (+1 from object creation and +1 from do_switch()). * i915_gem_context_fini() will be called after gpu_idle() has switched * to default context. So we need to unreference the base object once * to offset the do_switch part, so that i915_gem_context_unreference() * can then free the base object correctly. */ - drm_gem_object_unreference(&dctx->obj->base); + WARN_ON(!dev_priv->ring[RCS].last_context); + if (dev_priv->ring[RCS].last_context == dctx) { + /* Fake switch to NULL context */ + WARN_ON(dctx->obj->active); + i915_gem_object_unpin(dctx->obj); + i915_gem_context_unreference(dctx); + } + + i915_gem_object_unpin(dctx->obj); i915_gem_context_unreference(dctx); + dev_priv->ring[RCS].default_context = NULL; + dev_priv->ring[RCS].last_context = NULL; } static int context_idr_cleanup(int id, void *p, void *data) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:38 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:38 -0000 Subject: [LTSI-dev] [PATCH 03/50] drm/i915: Replace has_bsd/blt/vebox with a mask In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-4-git-send-email-dheerajx.s.jamwal@intel.com> From: Ben Widawsky I've sent this patch several times for various reasons. It essentially cleans up a lot of code where we need to do something per ring, and want to query whether or not the ring exists on that hardware. It has various uses coming up, but for now it shouldn't be too offensive. v2: Big conflict resolution on Damien's DEV_INFO_FOR_EACH stuff v3: Resolved vebox addition v4: Rebased after months of disuse. Also made failed ringbuffer init cleaner. v5: Remove the init cleaner from v4. There is a better way to do it. (Chris) Reviewed-by: Chris Wilson Signed-off-by: Ben Widawsky Signed-off-by: Daniel Vetter (cherry picked from commit 73ae478cdf6ab886b107f39269cbbf6d33ad2abe) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_drv.c | 32 ++++++++++++++++++++------------ drivers/gpu/drm/i915/i915_drv.h | 14 ++++++++------ 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 837813b..bc83851 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -160,49 +160,58 @@ extern int intel_agp_enabled; static const struct intel_device_info intel_i830_info = { .gen = 2, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, .has_overlay = 1, .overlay_needs_physical = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_845g_info = { .gen = 2, .num_pipes = 1, .has_overlay = 1, .overlay_needs_physical = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i85x_info = { .gen = 2, .is_i85x = 1, .is_mobile = 1, .num_pipes = 2, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i865g_info = { .gen = 2, .num_pipes = 1, .has_overlay = 1, .overlay_needs_physical = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i915g_info = { .gen = 3, .is_i915g = 1, .cursor_needs_physical = 1, .num_pipes = 2, .has_overlay = 1, .overlay_needs_physical = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i915gm_info = { .gen = 3, .is_mobile = 1, .num_pipes = 2, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i945g_info = { .gen = 3, .has_hotplug = 1, .cursor_needs_physical = 1, .num_pipes = 2, .has_overlay = 1, .overlay_needs_physical = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i945gm_info = { .gen = 3, .is_i945gm = 1, .is_mobile = 1, .num_pipes = 2, .has_hotplug = 1, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, .supports_tv = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i965g_info = { .gen = 4, .is_broadwater = 1, .num_pipes = 2, .has_hotplug = 1, .has_overlay = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_i965gm_info = { @@ -210,18 +219,20 @@ static const struct intel_device_info intel_i965gm_info = { .is_mobile = 1, .has_fbc = 1, .has_hotplug = 1, .has_overlay = 1, .supports_tv = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_g33_info = { .gen = 3, .is_g33 = 1, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, .has_overlay = 1, + .ring_mask = RENDER_RING, }; static const struct intel_device_info intel_g45_info = { .gen = 4, .is_g4x = 1, .need_gfx_hws = 1, .num_pipes = 2, .has_pipe_cxsr = 1, .has_hotplug = 1, - .has_bsd_ring = 1, + .ring_mask = RENDER_RING | BSD_RING, }; static const struct intel_device_info intel_gm45_info = { @@ -229,7 +240,7 @@ static const struct intel_device_info intel_gm45_info = { .is_mobile = 1, .need_gfx_hws = 1, .has_fbc = 1, .has_pipe_cxsr = 1, .has_hotplug = 1, .supports_tv = 1, - .has_bsd_ring = 1, + .ring_mask = RENDER_RING | BSD_RING, }; static const struct intel_device_info intel_pineview_info = { @@ -241,21 +252,20 @@ static const struct intel_device_info intel_pineview_info = { static const struct intel_device_info intel_ironlake_d_info = { .gen = 5, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, - .has_bsd_ring = 1, + .ring_mask = RENDER_RING | BSD_RING, }; static const struct intel_device_info intel_ironlake_m_info = { .gen = 5, .is_mobile = 1, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, .has_fbc = 1, - .has_bsd_ring = 1, + .ring_mask = RENDER_RING | BSD_RING, }; static const struct intel_device_info intel_sandybridge_d_info = { .gen = 6, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, - .has_bsd_ring = 1, - .has_blt_ring = 1, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING, .has_llc = 1, }; @@ -263,16 +273,14 @@ static const struct intel_device_info intel_sandybridge_m_info = { .gen = 6, .is_mobile = 1, .num_pipes = 2, .need_gfx_hws = 1, .has_hotplug = 1, .has_fbc = 1, - .has_bsd_ring = 1, - .has_blt_ring = 1, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING, .has_llc = 1, }; #define GEN7_FEATURES \ .gen = 7, .num_pipes = 3, \ .need_gfx_hws = 1, .has_hotplug = 1, \ - .has_bsd_ring = 1, \ - .has_blt_ring = 1, \ + .ring_mask = RENDER_RING | BSD_RING | BLT_RING, \ .has_llc = 1 static const struct intel_device_info intel_ivybridge_d_info = { @@ -315,7 +323,7 @@ static const struct intel_device_info intel_haswell_d_info = { .is_haswell = 1, .has_ddi = 1, .has_fpga_dbg = 1, - .has_vebox_ring = 1, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, }; static const struct intel_device_info intel_haswell_m_info = { @@ -325,7 +333,7 @@ static const struct intel_device_info intel_haswell_m_info = { .has_ddi = 1, .has_fpga_dbg = 1, .has_fbc = 1, - .has_vebox_ring = 1, + .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING, }; /* diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index fc7e4db..32a3be3 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -448,9 +448,6 @@ struct intel_uncore { func(has_overlay) sep \ func(overlay_needs_physical) sep \ func(supports_tv) sep \ - func(has_bsd_ring) sep \ - func(has_blt_ring) sep \ - func(has_vebox_ring) sep \ func(has_llc) sep \ func(has_ddi) sep \ func(has_fpga_dbg) @@ -462,6 +459,7 @@ struct intel_device_info { u32 display_mmio_offset; u8 num_pipes:3; u8 gen; + u8 ring_mask; /* Rings supported by the HW */ DEV_INFO_FOR_EACH_FLAG(DEFINE_FLAG, SEP_SEMICOLON); }; @@ -1691,9 +1689,13 @@ struct drm_i915_file_private { #define IS_GEN6(dev) (INTEL_INFO(dev)->gen == 6) #define IS_GEN7(dev) (INTEL_INFO(dev)->gen == 7) -#define HAS_BSD(dev) (INTEL_INFO(dev)->has_bsd_ring) -#define HAS_BLT(dev) (INTEL_INFO(dev)->has_blt_ring) -#define HAS_VEBOX(dev) (INTEL_INFO(dev)->has_vebox_ring) +#define RENDER_RING (1<ring_mask & BSD_RING) +#define HAS_BLT(dev) (INTEL_INFO(dev)->ring_mask & BLT_RING) +#define HAS_VEBOX(dev) (INTEL_INFO(dev)->ring_mask & VEBOX_RING) #define HAS_LLC(dev) (INTEL_INFO(dev)->has_llc) #define HAS_WT(dev) (IS_HASWELL(dev) && to_i915(dev)->ellc_size) #define I915_NEED_GFX_HWS(dev) (INTEL_INFO(dev)->need_gfx_hws) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:38 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:38 -0000 Subject: [LTSI-dev] [PATCH 04/50] drm/i915: Expose latest 200 CRC value for pipe through debugfs In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-5-git-send-email-dheerajx.s.jamwal@intel.com> From: Shuang He There are several points in the display pipeline where CRCs can be computed on the bits flowing there. For instance, it's usually possible to compute the CRCs of the primary plane, the sprite plane or the CRCs of the bits after the panel fitter (collectively called pipe CRCs). v2: Quite a bit of rework here and there (Damien) Signed-off-by: Shuang He Signed-off-by: Damien Lespiau [danvet: Fix intermediate compile file reported by Wu Fengguang's kernel builder.] Signed-off-by: Daniel Vetter (cherry picked from commit 8bf1e9f1d2aa1fafd2b262683a13cbb7f934c6d0) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 33 ++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 15 +++++++++++++++ drivers/gpu/drm/i915/i915_irq.c | 35 ++++++++++++++++++++++++++++++++++ drivers/gpu/drm/i915/i915_reg.h | 36 ++++++++++++++++++++++++++++++++++- 4 files changed, 118 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 72d0458..e1d45aa 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1732,6 +1732,36 @@ static int i915_pc8_status(struct seq_file *m, void *unused) return 0; } +static int i915_pipe_crc(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + enum pipe pipe = (enum pipe)node->info_ent->data; + const struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; + int i; + int start; + + if (!IS_IVYBRIDGE(dev)) { + seq_puts(m, "unsupported\n"); + return 0; + } + + start = atomic_read(&pipe_crc->slot) + 1; + seq_puts(m, " timestamp CRC1 CRC2 CRC3 CRC4 CRC5\n"); + for (i = 0; i < INTEL_PIPE_CRC_ENTRIES_NR; i++) { + const struct intel_pipe_crc_entry *entry = + &pipe_crc->entries[(start + i) % + INTEL_PIPE_CRC_ENTRIES_NR]; + + seq_printf(m, "%12u %8x %8x %8x %8x %8x\n", entry->timestamp, + entry->crc[0], entry->crc[1], entry->crc[2], + entry->crc[3], entry->crc[4]); + } + + return 0; +} + static int i915_wedged_get(void *data, u64 *val) { @@ -2247,6 +2277,9 @@ static struct drm_info_list i915_debugfs_list[] = { {"i915_edp_psr_status", i915_edp_psr_status, 0}, {"i915_energy_uJ", i915_energy_uJ, 0}, {"i915_pc8_status", i915_pc8_status, 0}, + {"i915_pipe_A_crc", i915_pipe_crc, 0, (void *)PIPE_A}, + {"i915_pipe_B_crc", i915_pipe_crc, 0, (void *)PIPE_B}, + {"i915_pipe_C_crc", i915_pipe_crc, 0, (void *)PIPE_C}, }; #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 32a3be3..6ec44c2 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1217,6 +1217,17 @@ struct i915_package_c8 { } regsave; }; +struct intel_pipe_crc_entry { + uint32_t timestamp; + uint32_t crc[5]; +}; + +#define INTEL_PIPE_CRC_ENTRIES_NR 200 +struct intel_pipe_crc { + struct intel_pipe_crc_entry entries[INTEL_PIPE_CRC_ENTRIES_NR]; + atomic_t slot; +}; + typedef struct drm_i915_private { struct drm_device *dev; struct kmem_cache *slab; @@ -1421,6 +1432,10 @@ typedef struct drm_i915_private { struct i915_dri1_state dri1; /* Old ums support infrastructure, same warning applies. */ struct i915_ums_state ums; + +#ifdef CONFIG_DEBUG_FS + struct intel_pipe_crc pipe_crc[I915_MAX_PIPES]; +#endif } drm_i915_private_t; static inline struct drm_i915_private *to_i915(const struct drm_device *dev) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 26753b6..d2074f1 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1188,6 +1188,32 @@ static void dp_aux_irq_handler(struct drm_device *dev) wake_up_all(&dev_priv->gmbus_wait_queue); } +#if defined(CONFIG_DEBUG_FS) +static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; + struct intel_pipe_crc_entry *entry; + ktime_t now; + int ts, slot; + + now = ktime_get(); + ts = ktime_to_us(now); + + slot = (atomic_read(&pipe_crc->slot) + 1) % INTEL_PIPE_CRC_ENTRIES_NR; + entry = &pipe_crc->entries[slot]; + entry->timestamp = ts; + entry->crc[0] = I915_READ(PIPE_CRC_RES_1_IVB(pipe)); + entry->crc[1] = I915_READ(PIPE_CRC_RES_2_IVB(pipe)); + entry->crc[2] = I915_READ(PIPE_CRC_RES_3_IVB(pipe)); + entry->crc[3] = I915_READ(PIPE_CRC_RES_4_IVB(pipe)); + entry->crc[4] = I915_READ(PIPE_CRC_RES_5_IVB(pipe)); + atomic_set(&dev_priv->pipe_crc[pipe].slot, slot); +} +#else +static void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} +#endif + /* The RPS events need forcewake, so we add them to a work queue and mask their * IMR bits until the work is done. Other interrupts can be processed without * the work queue. */ @@ -1366,6 +1392,15 @@ static void ivb_err_int_handler(struct drm_device *dev) if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, false)) DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n"); + if (err_int & ERR_INT_PIPE_CRC_DONE_A) + ivb_pipe_crc_update(dev, PIPE_A); + + if (err_int & ERR_INT_PIPE_CRC_DONE_B) + ivb_pipe_crc_update(dev, PIPE_B); + + if (err_int & ERR_INT_PIPE_CRC_DONE_C) + ivb_pipe_crc_update(dev, PIPE_C); + I915_WRITE(GEN7_ERR_INT, err_int); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b334751..e4775dd 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -722,8 +722,11 @@ #define GEN7_ERR_INT 0x44040 #define ERR_INT_POISON (1<<31) #define ERR_INT_MMIO_UNCLAIMED (1<<13) +#define ERR_INT_PIPE_CRC_DONE_C (1<<8) #define ERR_INT_FIFO_UNDERRUN_C (1<<6) +#define ERR_INT_PIPE_CRC_DONE_B (1<<5) #define ERR_INT_FIFO_UNDERRUN_B (1<<3) +#define ERR_INT_PIPE_CRC_DONE_A (1<<2) #define ERR_INT_FIFO_UNDERRUN_A (1<<0) #define ERR_INT_FIFO_UNDERRUN(pipe) (1<<(pipe*3)) @@ -1835,6 +1838,38 @@ * Display engine regs */ +/* Pipe A CRC regs */ +#define _PIPE_CRC_CTL_A (dev_priv->info->display_mmio_offset + 0x60050) +#define PIPE_CRC_ENABLE (1 << 31) +#define PIPE_CRC_SOURCE_PRIMARY_IVB (0 << 29) +#define PIPE_CRC_SOURCE_SPRITE_IVB (1 << 29) +#define PIPE_CRC_SOURCE_PF_IVB (2 << 29) +#define _PIPE_CRC_RES_1_A_IVB (dev_priv->info->display_mmio_offset + 0x60064) +#define _PIPE_CRC_RES_2_A_IVB (dev_priv->info->display_mmio_offset + 0x60068) +#define _PIPE_CRC_RES_3_A_IVB (dev_priv->info->display_mmio_offset + 0x6006c) +#define _PIPE_CRC_RES_4_A_IVB (dev_priv->info->display_mmio_offset + 0x60070) +#define _PIPE_CRC_RES_5_A_IVB (dev_priv->info->display_mmio_offset + 0x60074) + +/* Pipe B CRC regs */ +#define _PIPE_CRC_CTL_B (dev_priv->info->display_mmio_offset + 0x61050) +#define _PIPE_CRC_RES_1_B_IVB (dev_priv->info->display_mmio_offset + 0x61064) +#define _PIPE_CRC_RES_2_B_IVB (dev_priv->info->display_mmio_offset + 0x61068) +#define _PIPE_CRC_RES_3_B_IVB (dev_priv->info->display_mmio_offset + 0x6106c) +#define _PIPE_CRC_RES_4_B_IVB (dev_priv->info->display_mmio_offset + 0x61070) +#define _PIPE_CRC_RES_5_B_IVB (dev_priv->info->display_mmio_offset + 0x61074) + +#define PIPE_CRC_CTL(pipe) _PIPE(pipe, _PIPE_CRC_CTL_A, _PIPE_CRC_CTL_B) +#define PIPE_CRC_RES_1_IVB(pipe) \ + _PIPE(pipe, _PIPE_CRC_RES_1_A_IVB, _PIPE_CRC_RES_1_B_IVB) +#define PIPE_CRC_RES_2_IVB(pipe) \ + _PIPE(pipe, _PIPE_CRC_RES_2_A_IVB, _PIPE_CRC_RES_2_B_IVB) +#define PIPE_CRC_RES_3_IVB(pipe) \ + _PIPE(pipe, _PIPE_CRC_RES_3_A_IVB, _PIPE_CRC_RES_3_B_IVB) +#define PIPE_CRC_RES_4_IVB(pipe) \ + _PIPE(pipe, _PIPE_CRC_RES_4_A_IVB, _PIPE_CRC_RES_4_B_IVB) +#define PIPE_CRC_RES_5_IVB(pipe) \ + _PIPE(pipe, _PIPE_CRC_RES_5_A_IVB, _PIPE_CRC_RES_5_B_IVB) + /* Pipe A timing regs */ #define _HTOTAL_A (dev_priv->info->display_mmio_offset + 0x60000) #define _HBLANK_A (dev_priv->info->display_mmio_offset + 0x60004) @@ -1857,7 +1892,6 @@ #define _BCLRPAT_B (dev_priv->info->display_mmio_offset + 0x61020) #define _VSYNCSHIFT_B (dev_priv->info->display_mmio_offset + 0x61028) - #define HTOTAL(trans) _TRANSCODER(trans, _HTOTAL_A, _HTOTAL_B) #define HBLANK(trans) _TRANSCODER(trans, _HBLANK_A, _HBLANK_B) #define HSYNC(trans) _TRANSCODER(trans, _HSYNC_A, _HSYNC_B) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:38 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:38 -0000 Subject: [LTSI-dev] [PATCH 05/50] drm/i915: Add a control file for pipe CRCs In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-6-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter Note the "return -ENODEV;" in pipe_crc_set_source(). The ctl file is disabled until the end of the series to be able to do incremental improvements. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 926321d503406d1fefb2fae9651beca14160529a) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 217 ++++++++++++++++++++++++++++++++++- drivers/gpu/drm/i915/i915_drv.h | 9 ++ 2 files changed, 224 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e1d45aa..0d8a9a3 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -27,6 +27,7 @@ */ #include +#include #include #include #include @@ -1742,8 +1743,8 @@ static int i915_pipe_crc(struct seq_file *m, void *data) int i; int start; - if (!IS_IVYBRIDGE(dev)) { - seq_puts(m, "unsupported\n"); + if (dev_priv->pipe_crc[pipe].source == INTEL_PIPE_CRC_SOURCE_NONE) { + seq_puts(m, "none\n"); return 0; } @@ -1762,6 +1763,217 @@ static int i915_pipe_crc(struct seq_file *m, void *data) return 0; } +static const char *pipe_crc_sources[] = { + "none", + "plane1", + "plane2", + "pf", +}; + +static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) +{ + BUILD_BUG_ON(ARRAY_SIZE(pipe_crc_sources) != INTEL_PIPE_CRC_SOURCE_MAX); + return pipe_crc_sources[source]; +} + +static int pipe_crc_ctl_show(struct seq_file *m, void *data) +{ + struct drm_device *dev = m->private; + struct drm_i915_private *dev_priv = dev->dev_private; + int i; + + for (i = 0; i < I915_MAX_PIPES; i++) + seq_printf(m, "%c %s\n", pipe_name(i), + pipe_crc_source_name(dev_priv->pipe_crc[i].source)); + + return 0; +} + +static int pipe_crc_ctl_open(struct inode *inode, struct file *file) +{ + struct drm_device *dev = inode->i_private; + + return single_open(file, pipe_crc_ctl_show, dev); +} + +static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, + enum intel_pipe_crc_source source) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + u32 val; + + + return -ENODEV; + + if (!IS_IVYBRIDGE(dev)) + return -ENODEV; + + dev_priv->pipe_crc[pipe].source = source; + + switch (source) { + case INTEL_PIPE_CRC_SOURCE_PLANE1: + val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_IVB; + break; + case INTEL_PIPE_CRC_SOURCE_PLANE2: + val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; + break; + case INTEL_PIPE_CRC_SOURCE_PF: + val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB; + break; + case INTEL_PIPE_CRC_SOURCE_NONE: + default: + val = 0; + break; + } + + I915_WRITE(PIPE_CRC_CTL(pipe), val); + POSTING_READ(PIPE_CRC_CTL(pipe)); + + return 0; +} + +/* + * Parse pipe CRC command strings: + * command: wsp* pipe wsp+ source wsp* + * pipe: (A | B | C) + * source: (none | plane1 | plane2 | pf) + * wsp: (#0x20 | #0x9 | #0xA)+ + * + * eg.: + * "A plane1" -> Start CRC computations on plane1 of pipe A + * "A none" -> Stop CRC + */ +static int pipe_crc_ctl_tokenize(char *buf, char *words[], int max_words) +{ + int n_words = 0; + + while (*buf) { + char *end; + + /* skip leading white space */ + buf = skip_spaces(buf); + if (!*buf) + break; /* end of buffer */ + + /* find end of word */ + for (end = buf; *end && !isspace(*end); end++) + ; + + if (n_words == max_words) { + DRM_DEBUG_DRIVER("too many words, allowed <= %d\n", + max_words); + return -EINVAL; /* ran out of words[] before bytes */ + } + + if (*end) + *end++ = '\0'; + words[n_words++] = buf; + buf = end; + } + + return n_words; +} + +static int pipe_crc_ctl_parse_pipe(const char *buf, enum pipe *pipe) +{ + const char name = buf[0]; + + if (name < 'A' || name >= pipe_name(I915_MAX_PIPES)) + return -EINVAL; + + *pipe = name - 'A'; + + return 0; +} + +static int +pipe_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *source) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pipe_crc_sources); i++) + if (!strcmp(buf, pipe_crc_sources[i])) { + *source = i; + return 0; + } + + return -EINVAL; +} + +static int pipe_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len) +{ +#define MAX_WORDS 2 + int n_words; + char *words[MAX_WORDS]; + enum pipe pipe; + enum intel_pipe_crc_source source; + + n_words = pipe_crc_ctl_tokenize(buf, words, MAX_WORDS); + if (n_words != 2) { + DRM_DEBUG_DRIVER("tokenize failed, a command is 2 words\n"); + return -EINVAL; + } + + if (pipe_crc_ctl_parse_pipe(words[0], &pipe) < 0) { + DRM_DEBUG_DRIVER("unknown pipe %s\n", words[0]); + return -EINVAL; + } + + if (pipe_crc_ctl_parse_source(words[1], &source) < 0) { + DRM_DEBUG_DRIVER("unknown source %s\n", words[1]); + return -EINVAL; + } + + return pipe_crc_set_source(dev, pipe, source); +} + +static ssize_t pipe_crc_ctl_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) +{ + struct seq_file *m = file->private_data; + struct drm_device *dev = m->private; + char *tmpbuf; + int ret; + + if (len == 0) + return 0; + + if (len > PAGE_SIZE - 1) { + DRM_DEBUG_DRIVER("expected <%lu bytes into pipe crc control\n", + PAGE_SIZE); + return -E2BIG; + } + + tmpbuf = kmalloc(len + 1, GFP_KERNEL); + if (!tmpbuf) + return -ENOMEM; + + if (copy_from_user(tmpbuf, ubuf, len)) { + ret = -EFAULT; + goto out; + } + tmpbuf[len] = '\0'; + + ret = pipe_crc_ctl_parse(dev, tmpbuf, len); + +out: + kfree(tmpbuf); + if (ret < 0) + return ret; + + *offp += len; + return len; +} + +static const struct file_operations i915_pipe_crc_ctl_fops = { + .owner = THIS_MODULE, + .open = pipe_crc_ctl_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = pipe_crc_ctl_write +}; + static int i915_wedged_get(void *data, u64 *val) { @@ -2297,6 +2509,7 @@ static struct i915_debugfs_files { {"i915_gem_drop_caches", &i915_drop_caches_fops}, {"i915_error_state", &i915_error_state_fops}, {"i915_next_seqno", &i915_next_seqno_fops}, + {"i915_pipe_crc_ctl", &i915_pipe_crc_ctl_fops}, }; int i915_debugfs_init(struct drm_minor *minor) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 6ec44c2..c57972d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1217,6 +1217,14 @@ struct i915_package_c8 { } regsave; }; +enum intel_pipe_crc_source { + INTEL_PIPE_CRC_SOURCE_NONE, + INTEL_PIPE_CRC_SOURCE_PLANE1, + INTEL_PIPE_CRC_SOURCE_PLANE2, + INTEL_PIPE_CRC_SOURCE_PF, + INTEL_PIPE_CRC_SOURCE_MAX, +}; + struct intel_pipe_crc_entry { uint32_t timestamp; uint32_t crc[5]; @@ -1225,6 +1233,7 @@ struct intel_pipe_crc_entry { #define INTEL_PIPE_CRC_ENTRIES_NR 200 struct intel_pipe_crc { struct intel_pipe_crc_entry entries[INTEL_PIPE_CRC_ENTRIES_NR]; + enum intel_pipe_crc_source source; atomic_t slot; }; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:39 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:39 -0000 Subject: [LTSI-dev] [PATCH 06/50] drm/i915: Keep the CRC values into a circular buffer In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-7-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau There are a few good properties to a circular buffer, for instance it has a number of entries (before we were always dumping the full buffer). Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit b2c88f5b1dea77b57759387728917a124eb1c098) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 20 ++++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_irq.c | 19 +++++++++++++++---- 3 files changed, 29 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 0d8a9a3..991abff 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -27,6 +27,7 @@ */ #include +#include #include #include #include @@ -1739,25 +1740,28 @@ static int i915_pipe_crc(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct drm_i915_private *dev_priv = dev->dev_private; enum pipe pipe = (enum pipe)node->info_ent->data; - const struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; - int i; - int start; + struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; + int head, tail; if (dev_priv->pipe_crc[pipe].source == INTEL_PIPE_CRC_SOURCE_NONE) { seq_puts(m, "none\n"); return 0; } - start = atomic_read(&pipe_crc->slot) + 1; seq_puts(m, " timestamp CRC1 CRC2 CRC3 CRC4 CRC5\n"); - for (i = 0; i < INTEL_PIPE_CRC_ENTRIES_NR; i++) { - const struct intel_pipe_crc_entry *entry = - &pipe_crc->entries[(start + i) % - INTEL_PIPE_CRC_ENTRIES_NR]; + head = atomic_read(&pipe_crc->head); + tail = atomic_read(&pipe_crc->tail); + + while (CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) >= 1) { + struct intel_pipe_crc_entry *entry = &pipe_crc->entries[tail]; seq_printf(m, "%12u %8x %8x %8x %8x %8x\n", entry->timestamp, entry->crc[0], entry->crc[1], entry->crc[2], entry->crc[3], entry->crc[4]); + + BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); + tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); + atomic_set(&pipe_crc->tail, tail); } return 0; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c57972d..a0fd931 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1230,11 +1230,11 @@ struct intel_pipe_crc_entry { uint32_t crc[5]; }; -#define INTEL_PIPE_CRC_ENTRIES_NR 200 +#define INTEL_PIPE_CRC_ENTRIES_NR 128 struct intel_pipe_crc { struct intel_pipe_crc_entry entries[INTEL_PIPE_CRC_ENTRIES_NR]; enum intel_pipe_crc_source source; - atomic_t slot; + atomic_t head, tail; }; typedef struct drm_i915_private { diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index d2074f1..73d76af 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -30,6 +30,7 @@ #include #include +#include #include #include #include "i915_drv.h" @@ -1195,20 +1196,30 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; struct intel_pipe_crc_entry *entry; ktime_t now; - int ts, slot; + int ts, head, tail; + + head = atomic_read(&pipe_crc->head); + tail = atomic_read(&pipe_crc->tail); + + if (CIRC_SPACE(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) < 1) { + DRM_ERROR("CRC buffer overflowing\n"); + return; + } + + entry = &pipe_crc->entries[head]; now = ktime_get(); ts = ktime_to_us(now); - slot = (atomic_read(&pipe_crc->slot) + 1) % INTEL_PIPE_CRC_ENTRIES_NR; - entry = &pipe_crc->entries[slot]; entry->timestamp = ts; entry->crc[0] = I915_READ(PIPE_CRC_RES_1_IVB(pipe)); entry->crc[1] = I915_READ(PIPE_CRC_RES_2_IVB(pipe)); entry->crc[2] = I915_READ(PIPE_CRC_RES_3_IVB(pipe)); entry->crc[3] = I915_READ(PIPE_CRC_RES_4_IVB(pipe)); entry->crc[4] = I915_READ(PIPE_CRC_RES_5_IVB(pipe)); - atomic_set(&dev_priv->pipe_crc[pipe].slot, slot); + + head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); + atomic_set(&pipe_crc->head, head); } #else static void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:39 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:39 -0000 Subject: [LTSI-dev] [PATCH 07/50] drm/i915: Sample the frame counter instead of a timestamp for CRCs In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-8-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit ac2300d4d5c2e9e4d82361a582cf1df3ec22fec7) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_irq.c | 8 ++------ 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 991abff..58c6fd4 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1748,14 +1748,14 @@ static int i915_pipe_crc(struct seq_file *m, void *data) return 0; } - seq_puts(m, " timestamp CRC1 CRC2 CRC3 CRC4 CRC5\n"); + seq_puts(m, " frame CRC1 CRC2 CRC3 CRC4 CRC5\n"); head = atomic_read(&pipe_crc->head); tail = atomic_read(&pipe_crc->tail); while (CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) >= 1) { struct intel_pipe_crc_entry *entry = &pipe_crc->entries[tail]; - seq_printf(m, "%12u %8x %8x %8x %8x %8x\n", entry->timestamp, + seq_printf(m, "%8u %8x %8x %8x %8x %8x\n", entry->frame, entry->crc[0], entry->crc[1], entry->crc[2], entry->crc[3], entry->crc[4]); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index a0fd931..879e044 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1226,7 +1226,7 @@ enum intel_pipe_crc_source { }; struct intel_pipe_crc_entry { - uint32_t timestamp; + uint32_t frame; uint32_t crc[5]; }; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 73d76af..0b21828 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1195,8 +1195,7 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) struct drm_i915_private *dev_priv = dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; struct intel_pipe_crc_entry *entry; - ktime_t now; - int ts, head, tail; + int head, tail; head = atomic_read(&pipe_crc->head); tail = atomic_read(&pipe_crc->tail); @@ -1208,10 +1207,7 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) entry = &pipe_crc->entries[head]; - now = ktime_get(); - ts = ktime_to_us(now); - - entry->timestamp = ts; + entry->frame = I915_READ(PIPEFRAME(pipe)); entry->crc[0] = I915_READ(PIPE_CRC_RES_1_IVB(pipe)); entry->crc[1] = I915_READ(PIPE_CRC_RES_2_IVB(pipe)); entry->crc[2] = I915_READ(PIPE_CRC_RES_3_IVB(pipe)); -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:41 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:41 -0000 Subject: [LTSI-dev] [PATCH 08/50] drm/i915: Make switching to the same CRC source a no-op In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-9-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit cc3da175b0807a3e15f0fb3dad2bc9c7ff071440) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 58c6fd4..8c750d5 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1804,6 +1804,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, enum intel_pipe_crc_source source) { struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; u32 val; @@ -1812,7 +1813,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (!IS_IVYBRIDGE(dev)) return -ENODEV; - dev_priv->pipe_crc[pipe].source = source; + if (pipe_crc->source == source) + return 0; + + pipe_crc->source = source; switch (source) { case INTEL_PIPE_CRC_SOURCE_PLANE1: -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:41 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:41 -0000 Subject: [LTSI-dev] [PATCH 09/50] drm/i915: Enforce going back to none before changing CRC source In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-10-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau This way we can have some init/fini code on those transitions. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit ae676fcd2a93bf1809cddbd79e37b37609791dc2) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 8c750d5..787c50d 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1816,6 +1816,10 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (pipe_crc->source == source) return 0; + /* forbid changing the source without going back to 'none' */ + if (pipe_crc->source && source) + return -EINVAL; + pipe_crc->source = source; switch (source) { -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:42 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:42 -0000 Subject: [LTSI-dev] [PATCH 10/50] drm/i915: Empty the circular buffer when asked for a new source In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-11-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau So we don't read out stale CRCs from a previous run left in the buffer. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 4b584369c6d6b75c9dbfeeb0896853874d031897) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 787c50d..ec9151a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1820,6 +1820,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (pipe_crc->source && source) return -EINVAL; + /* none -> real source transition */ + if (source) { + atomic_set(&pipe_crc->head, 0); + atomic_set(&pipe_crc->tail, 0); + } + pipe_crc->source = source; switch (source) { -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:44 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:44 -0000 Subject: [LTSI-dev] [PATCH 11/50] drm/i915: Dynamically allocate the CRC circular buffer In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-12-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau So we don't eat that memory when not needed. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit e5f75aca193837c57a886c3fb83442fda88142e9) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 12 ++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index ec9151a..53a3f22 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1822,6 +1822,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, /* none -> real source transition */ if (source) { + pipe_crc->entries = kzalloc(sizeof(*pipe_crc->entries) * + INTEL_PIPE_CRC_ENTRIES_NR, + GFP_KERNEL); + if (!pipe_crc->entries) + return -ENOMEM; + atomic_set(&pipe_crc->head, 0); atomic_set(&pipe_crc->tail, 0); } @@ -1847,6 +1853,12 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, I915_WRITE(PIPE_CRC_CTL(pipe), val); POSTING_READ(PIPE_CRC_CTL(pipe)); + /* real source -> none transition */ + if (source == INTEL_PIPE_CRC_SOURCE_NONE) { + kfree(pipe_crc->entries); + pipe_crc->entries = NULL; + } + return 0; } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 879e044..99c8e42 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1232,7 +1232,7 @@ struct intel_pipe_crc_entry { #define INTEL_PIPE_CRC_ENTRIES_NR 128 struct intel_pipe_crc { - struct intel_pipe_crc_entry entries[INTEL_PIPE_CRC_ENTRIES_NR]; + struct intel_pipe_crc_entry *entries; enum intel_pipe_crc_source source; atomic_t head, tail; }; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:44 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:44 -0000 Subject: [LTSI-dev] [PATCH 12/50] drm/i915: Generalize the CRC command format for future work In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-13-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau Let's move from writing 'A plane1' to 'pipe A plane1' to i915_pipe_crc_ctl. This will allow us to extend the interface to transcoders or DDIs in the future. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit b94dec877f97d22a27096d0c3d399c1427157aa2) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 56 +++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 53a3f22..c609783 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1864,14 +1864,15 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, /* * Parse pipe CRC command strings: - * command: wsp* pipe wsp+ source wsp* - * pipe: (A | B | C) + * command: wsp* object wsp+ name wsp+ source wsp* + * object: 'pipe' + * name: (A | B | C) * source: (none | plane1 | plane2 | pf) * wsp: (#0x20 | #0x9 | #0xA)+ * * eg.: - * "A plane1" -> Start CRC computations on plane1 of pipe A - * "A none" -> Stop CRC + * "pipe A plane1" -> Start CRC computations on plane1 of pipe A + * "pipe A none" -> Stop CRC */ static int pipe_crc_ctl_tokenize(char *buf, char *words[], int max_words) { @@ -1904,6 +1905,28 @@ static int pipe_crc_ctl_tokenize(char *buf, char *words[], int max_words) return n_words; } +enum intel_pipe_crc_object { + PIPE_CRC_OBJECT_PIPE, +}; + +static const char *pipe_crc_objects[] = { + "pipe", +}; + +static int +pipe_crc_ctl_parse_object(const char *buf, enum intel_pipe_crc_object *object) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(pipe_crc_objects); i++) + if (!strcmp(buf, pipe_crc_objects[i])) { + *object = i; + return 0; + } + + return -EINVAL; +} + static int pipe_crc_ctl_parse_pipe(const char *buf, enum pipe *pipe) { const char name = buf[0]; @@ -1932,25 +1955,32 @@ pipe_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *source) static int pipe_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len) { -#define MAX_WORDS 2 +#define N_WORDS 3 int n_words; - char *words[MAX_WORDS]; + char *words[N_WORDS]; enum pipe pipe; + enum intel_pipe_crc_object object; enum intel_pipe_crc_source source; - n_words = pipe_crc_ctl_tokenize(buf, words, MAX_WORDS); - if (n_words != 2) { - DRM_DEBUG_DRIVER("tokenize failed, a command is 2 words\n"); + n_words = pipe_crc_ctl_tokenize(buf, words, N_WORDS); + if (n_words != N_WORDS) { + DRM_DEBUG_DRIVER("tokenize failed, a command is %d words\n", + N_WORDS); + return -EINVAL; + } + + if (pipe_crc_ctl_parse_object(words[0], &object) < 0) { + DRM_DEBUG_DRIVER("unknown object %s\n", words[0]); return -EINVAL; } - if (pipe_crc_ctl_parse_pipe(words[0], &pipe) < 0) { - DRM_DEBUG_DRIVER("unknown pipe %s\n", words[0]); + if (pipe_crc_ctl_parse_pipe(words[1], &pipe) < 0) { + DRM_DEBUG_DRIVER("unknown pipe %s\n", words[1]); return -EINVAL; } - if (pipe_crc_ctl_parse_source(words[1], &source) < 0) { - DRM_DEBUG_DRIVER("unknown source %s\n", words[1]); + if (pipe_crc_ctl_parse_source(words[2], &source) < 0) { + DRM_DEBUG_DRIVER("unknown source %s\n", words[2]); return -EINVAL; } -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:45 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:45 -0000 Subject: [LTSI-dev] [PATCH 13/50] drm/i915: Rename i915_pipe_crc_ctl to i915_display_crc_ctl In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-14-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau In the same spirit than: drm/i915: Generalize the CRC command format for future work Let's move from writing 'A plane1' to 'pipe A plane1' to i915_pipe_crc_ctl. This will allow us to extend the interface to transcoders or DDIs in the future. Let's rename the CRC control file to be more generic. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit bd9db02ffcf33348f3fb5d33b8623e78d7831d66) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index c609783..471c258 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1780,7 +1780,7 @@ static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) return pipe_crc_sources[source]; } -static int pipe_crc_ctl_show(struct seq_file *m, void *data) +static int display_crc_ctl_show(struct seq_file *m, void *data) { struct drm_device *dev = m->private; struct drm_i915_private *dev_priv = dev->dev_private; @@ -1793,11 +1793,11 @@ static int pipe_crc_ctl_show(struct seq_file *m, void *data) return 0; } -static int pipe_crc_ctl_open(struct inode *inode, struct file *file) +static int display_crc_ctl_open(struct inode *inode, struct file *file) { struct drm_device *dev = inode->i_private; - return single_open(file, pipe_crc_ctl_show, dev); + return single_open(file, display_crc_ctl_show, dev); } static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, @@ -1874,7 +1874,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, * "pipe A plane1" -> Start CRC computations on plane1 of pipe A * "pipe A none" -> Stop CRC */ -static int pipe_crc_ctl_tokenize(char *buf, char *words[], int max_words) +static int display_crc_ctl_tokenize(char *buf, char *words[], int max_words) { int n_words = 0; @@ -1914,20 +1914,20 @@ static const char *pipe_crc_objects[] = { }; static int -pipe_crc_ctl_parse_object(const char *buf, enum intel_pipe_crc_object *object) +display_crc_ctl_parse_object(const char *buf, enum intel_pipe_crc_object *o) { int i; for (i = 0; i < ARRAY_SIZE(pipe_crc_objects); i++) if (!strcmp(buf, pipe_crc_objects[i])) { - *object = i; + *o = i; return 0; } return -EINVAL; } -static int pipe_crc_ctl_parse_pipe(const char *buf, enum pipe *pipe) +static int display_crc_ctl_parse_pipe(const char *buf, enum pipe *pipe) { const char name = buf[0]; @@ -1940,20 +1940,20 @@ static int pipe_crc_ctl_parse_pipe(const char *buf, enum pipe *pipe) } static int -pipe_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *source) +display_crc_ctl_parse_source(const char *buf, enum intel_pipe_crc_source *s) { int i; for (i = 0; i < ARRAY_SIZE(pipe_crc_sources); i++) if (!strcmp(buf, pipe_crc_sources[i])) { - *source = i; + *s = i; return 0; } return -EINVAL; } -static int pipe_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len) +static int display_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len) { #define N_WORDS 3 int n_words; @@ -1962,24 +1962,24 @@ static int pipe_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len) enum intel_pipe_crc_object object; enum intel_pipe_crc_source source; - n_words = pipe_crc_ctl_tokenize(buf, words, N_WORDS); + n_words = display_crc_ctl_tokenize(buf, words, N_WORDS); if (n_words != N_WORDS) { DRM_DEBUG_DRIVER("tokenize failed, a command is %d words\n", N_WORDS); return -EINVAL; } - if (pipe_crc_ctl_parse_object(words[0], &object) < 0) { + if (display_crc_ctl_parse_object(words[0], &object) < 0) { DRM_DEBUG_DRIVER("unknown object %s\n", words[0]); return -EINVAL; } - if (pipe_crc_ctl_parse_pipe(words[1], &pipe) < 0) { + if (display_crc_ctl_parse_pipe(words[1], &pipe) < 0) { DRM_DEBUG_DRIVER("unknown pipe %s\n", words[1]); return -EINVAL; } - if (pipe_crc_ctl_parse_source(words[2], &source) < 0) { + if (display_crc_ctl_parse_source(words[2], &source) < 0) { DRM_DEBUG_DRIVER("unknown source %s\n", words[2]); return -EINVAL; } @@ -1987,8 +1987,8 @@ static int pipe_crc_ctl_parse(struct drm_device *dev, char *buf, size_t len) return pipe_crc_set_source(dev, pipe, source); } -static ssize_t pipe_crc_ctl_write(struct file *file, const char __user *ubuf, - size_t len, loff_t *offp) +static ssize_t display_crc_ctl_write(struct file *file, const char __user *ubuf, + size_t len, loff_t *offp) { struct seq_file *m = file->private_data; struct drm_device *dev = m->private; @@ -2014,7 +2014,7 @@ static ssize_t pipe_crc_ctl_write(struct file *file, const char __user *ubuf, } tmpbuf[len] = '\0'; - ret = pipe_crc_ctl_parse(dev, tmpbuf, len); + ret = display_crc_ctl_parse(dev, tmpbuf, len); out: kfree(tmpbuf); @@ -2025,13 +2025,13 @@ out: return len; } -static const struct file_operations i915_pipe_crc_ctl_fops = { +static const struct file_operations i915_display_crc_ctl_fops = { .owner = THIS_MODULE, - .open = pipe_crc_ctl_open, + .open = display_crc_ctl_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, - .write = pipe_crc_ctl_write + .write = display_crc_ctl_write }; static int @@ -2569,7 +2569,7 @@ static struct i915_debugfs_files { {"i915_gem_drop_caches", &i915_drop_caches_fops}, {"i915_error_state", &i915_error_state_fops}, {"i915_next_seqno", &i915_next_seqno_fops}, - {"i915_pipe_crc_ctl", &i915_pipe_crc_ctl_fops}, + {"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, }; int i915_debugfs_init(struct drm_minor *minor) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:45 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:45 -0000 Subject: [LTSI-dev] [PATCH 14/50] drm/i915: Warn if we receive an interrupt after freeing the buffer In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-15-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau This shouldn't happen as the buffer is freed after disable pipe CRCs, but better be safe than sorry. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 0c912c79eede0ba3dcc717a6e13de8766404c736) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_irq.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 0b21828..b201a21 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1197,6 +1197,11 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) struct intel_pipe_crc_entry *entry; int head, tail; + if (!pipe_crc->entries) { + DRM_ERROR("spurious interrupt\n"); + return; + } + head = atomic_read(&pipe_crc->head); tail = atomic_read(&pipe_crc->tail); -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:46 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:46 -0000 Subject: [LTSI-dev] [PATCH 15/50] drm/i915: Add log messages when CRCs collection is started/stopped In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-16-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 7cd6ccff85a13a8e5755cffa50129032d83c7c72) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 471c258..dee85d7 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1822,6 +1822,9 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, /* none -> real source transition */ if (source) { + DRM_DEBUG_DRIVER("collecting CRCs for pipe %c, %s\n", + pipe_name(pipe), pipe_crc_source_name(source)); + pipe_crc->entries = kzalloc(sizeof(*pipe_crc->entries) * INTEL_PIPE_CRC_ENTRIES_NR, GFP_KERNEL); @@ -1855,6 +1858,9 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, /* real source -> none transition */ if (source == INTEL_PIPE_CRC_SOURCE_NONE) { + DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n", + pipe_name(pipe)); + kfree(pipe_crc->entries); pipe_crc->entries = NULL; } -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:48 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:48 -0000 Subject: [LTSI-dev] [PATCH 16/50] drm/i915: Move drm_add_fake_info_node() higher in the file In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-17-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau Following commit needs drm_add_fake_info_node() higher in the file to avoid having a forward declaration. Move this helper near the top of the file. This also makes the next commit diff a bit easier to review. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 497666d80587933fc65dbe40d8fe6b6cc89ac9ad) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 52 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index dee85d7..baa2e43 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -53,6 +53,32 @@ static const char *yesno(int v) return v ? "yes" : "no"; } +/* As the drm_debugfs_init() routines are called before dev->dev_private is + * allocated we need to hook into the minor for release. */ +static int +drm_add_fake_info_node(struct drm_minor *minor, + struct dentry *ent, + const void *key) +{ + struct drm_info_node *node; + + node = kmalloc(sizeof(*node), GFP_KERNEL); + if (node == NULL) { + debugfs_remove(ent); + return -ENOMEM; + } + + node->minor = minor; + node->dent = ent; + node->info_ent = (void *) key; + + mutex_lock(&minor->debugfs_lock); + list_add(&node->list, &minor->debugfs_list); + mutex_unlock(&minor->debugfs_lock); + + return 0; +} + static int i915_capabilities(struct seq_file *m, void *data) { struct drm_info_node *node = (struct drm_info_node *) m->private; @@ -2425,32 +2451,6 @@ DEFINE_SIMPLE_ATTRIBUTE(i915_cache_sharing_fops, i915_cache_sharing_get, i915_cache_sharing_set, "%llu\n"); -/* As the drm_debugfs_init() routines are called before dev->dev_private is - * allocated we need to hook into the minor for release. */ -static int -drm_add_fake_info_node(struct drm_minor *minor, - struct dentry *ent, - const void *key) -{ - struct drm_info_node *node; - - node = kmalloc(sizeof(*node), GFP_KERNEL); - if (node == NULL) { - debugfs_remove(ent); - return -ENOMEM; - } - - node->minor = minor; - node->dent = ent; - node->info_ent = (void *) key; - - mutex_lock(&minor->debugfs_lock); - list_add(&node->list, &minor->debugfs_list); - mutex_unlock(&minor->debugfs_lock); - - return 0; -} - static int i915_forcewake_open(struct inode *inode, struct file *file) { struct drm_device *dev = inode->i_private; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:52 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:52 -0000 Subject: [LTSI-dev] [PATCH 18/50] drm/i915: Only one open() allowed on pipe CRC result files In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-19-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau It doesn't really make sense to have two processes dequeueing the CRC values at the same time. Forbid that usage. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit be5c7a90753fb9f74c867f74489abe822ffb4b26) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 16 ++++++++++++++++ drivers/gpu/drm/i915/i915_drv.h | 1 + 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5137f8f..826ebce 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1768,6 +1768,15 @@ struct pipe_crc_info { static int i915_pipe_crc_open(struct inode *inode, struct file *filep) { + struct pipe_crc_info *info = inode->i_private; + struct drm_i915_private *dev_priv = info->dev->dev_private; + struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; + + if (!atomic_dec_and_test(&pipe_crc->available)) { + atomic_inc(&pipe_crc->available); + return -EBUSY; /* already open */ + } + filep->private_data = inode->i_private; return 0; @@ -1775,6 +1784,12 @@ static int i915_pipe_crc_open(struct inode *inode, struct file *filep) static int i915_pipe_crc_release(struct inode *inode, struct file *filep) { + struct pipe_crc_info *info = inode->i_private; + struct drm_i915_private *dev_priv = info->dev->dev_private; + struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; + + atomic_inc(&pipe_crc->available); /* release the device */ + return 0; } @@ -2684,6 +2699,7 @@ void intel_display_crc_init(struct drm_device *dev) for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i]; + atomic_set(&pipe_crc->available, 1); init_waitqueue_head(&pipe_crc->wq); } } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 5cb9122..b4205b5 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1232,6 +1232,7 @@ struct intel_pipe_crc_entry { #define INTEL_PIPE_CRC_ENTRIES_NR 128 struct intel_pipe_crc { + atomic_t available; /* exclusive access to the device */ struct intel_pipe_crc_entry *entries; enum intel_pipe_crc_source source; atomic_t head, tail; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:52 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:52 -0000 Subject: [LTSI-dev] [PATCH 19/50] drm/i915: Enable pipe CRCs In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-20-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau It's time to declare them ready. Unleash the beast. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit d8882ac707f1536615d676fd6338d2a27d3911ed) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 826ebce..d1674b6 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1949,9 +1949,6 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; u32 val; - - return -ENODEV; - if (!IS_IVYBRIDGE(dev)) return -ENODEV; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:53 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:53 -0000 Subject: [LTSI-dev] [PATCH 17/50] drm/i915: Implement blocking read for pipe CRC files In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-18-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau seq_file is not quite the right interface for these ones. We have a circular buffer with a new entry per vblank on one side and a process wanting to dequeue the CRC with a read(). It's quite racy to wait for vblank in user land and then try to read a pipe_crc file, sometimes the CRC interrupt hasn't been fired and we end up with an EOF. So, let's have the read on the pipe_crc file block until the interrupt gives us a new entry. At that point we can wake the reading process. Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 071444280bcbb96ec38a1fb1ee3924ca7860844a) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 164 +++++++++++++++++++++++++++++++---- drivers/gpu/drm/i915/i915_dma.c | 2 + drivers/gpu/drm/i915/i915_drv.h | 6 ++ drivers/gpu/drm/i915/i915_irq.c | 2 + 4 files changed, 155 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index baa2e43..5137f8f 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1760,37 +1760,138 @@ static int i915_pc8_status(struct seq_file *m, void *unused) return 0; } -static int i915_pipe_crc(struct seq_file *m, void *data) +struct pipe_crc_info { + const char *name; + struct drm_device *dev; + enum pipe pipe; +}; + +static int i915_pipe_crc_open(struct inode *inode, struct file *filep) +{ + filep->private_data = inode->i_private; + + return 0; +} + +static int i915_pipe_crc_release(struct inode *inode, struct file *filep) +{ + return 0; +} + +/* (6 fields, 8 chars each, space separated (5) + '\n') */ +#define PIPE_CRC_LINE_LEN (6 * 8 + 5 + 1) +/* account for \'0' */ +#define PIPE_CRC_BUFFER_LEN (PIPE_CRC_LINE_LEN + 1) + +static int pipe_crc_data_count(struct intel_pipe_crc *pipe_crc) { - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct drm_i915_private *dev_priv = dev->dev_private; - enum pipe pipe = (enum pipe)node->info_ent->data; - struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; int head, tail; - if (dev_priv->pipe_crc[pipe].source == INTEL_PIPE_CRC_SOURCE_NONE) { - seq_puts(m, "none\n"); + head = atomic_read(&pipe_crc->head); + tail = atomic_read(&pipe_crc->tail); + + return CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR); +} + +static ssize_t +i915_pipe_crc_read(struct file *filep, char __user *user_buf, size_t count, + loff_t *pos) +{ + struct pipe_crc_info *info = filep->private_data; + struct drm_device *dev = info->dev; + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[info->pipe]; + char buf[PIPE_CRC_BUFFER_LEN]; + int head, tail, n_entries, n; + ssize_t bytes_read; + + /* + * Don't allow user space to provide buffers not big enough to hold + * a line of data. + */ + if (count < PIPE_CRC_LINE_LEN) + return -EINVAL; + + if (pipe_crc->source == INTEL_PIPE_CRC_SOURCE_NONE) return 0; + + /* nothing to read */ + while (pipe_crc_data_count(pipe_crc) == 0) { + if (filep->f_flags & O_NONBLOCK) + return -EAGAIN; + + if (wait_event_interruptible(pipe_crc->wq, + pipe_crc_data_count(pipe_crc))) + return -ERESTARTSYS; } - seq_puts(m, " frame CRC1 CRC2 CRC3 CRC4 CRC5\n"); + /* We now have one or more entries to read */ head = atomic_read(&pipe_crc->head); tail = atomic_read(&pipe_crc->tail); - - while (CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR) >= 1) { + n_entries = min((size_t)CIRC_CNT(head, tail, INTEL_PIPE_CRC_ENTRIES_NR), + count / PIPE_CRC_LINE_LEN); + bytes_read = 0; + n = 0; + do { struct intel_pipe_crc_entry *entry = &pipe_crc->entries[tail]; + int ret; - seq_printf(m, "%8u %8x %8x %8x %8x %8x\n", entry->frame, - entry->crc[0], entry->crc[1], entry->crc[2], - entry->crc[3], entry->crc[4]); + bytes_read += snprintf(buf, PIPE_CRC_BUFFER_LEN, + "%8u %8x %8x %8x %8x %8x\n", + entry->frame, entry->crc[0], + entry->crc[1], entry->crc[2], + entry->crc[3], entry->crc[4]); + + ret = copy_to_user(user_buf + n * PIPE_CRC_LINE_LEN, + buf, PIPE_CRC_LINE_LEN); + if (ret == PIPE_CRC_LINE_LEN) + return -EFAULT; BUILD_BUG_ON_NOT_POWER_OF_2(INTEL_PIPE_CRC_ENTRIES_NR); tail = (tail + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); atomic_set(&pipe_crc->tail, tail); - } + n++; + } while (--n_entries); - return 0; + return bytes_read; +} + +static const struct file_operations i915_pipe_crc_fops = { + .owner = THIS_MODULE, + .open = i915_pipe_crc_open, + .read = i915_pipe_crc_read, + .release = i915_pipe_crc_release, +}; + +static struct pipe_crc_info i915_pipe_crc_data[I915_MAX_PIPES] = { + { + .name = "i915_pipe_A_crc", + .pipe = PIPE_A, + }, + { + .name = "i915_pipe_B_crc", + .pipe = PIPE_B, + }, + { + .name = "i915_pipe_C_crc", + .pipe = PIPE_C, + }, +}; + +static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor, + enum pipe pipe) +{ + struct drm_device *dev = minor->dev; + struct dentry *ent; + struct pipe_crc_info *info = &i915_pipe_crc_data[pipe]; + + info->dev = dev; + ent = debugfs_create_file(info->name, S_IRUGO, root, info, + &i915_pipe_crc_fops); + if (IS_ERR(ent)) + return PTR_ERR(ent); + + return drm_add_fake_info_node(minor, ent, info); } static const char *pipe_crc_sources[] = { @@ -2555,9 +2656,6 @@ static struct drm_info_list i915_debugfs_list[] = { {"i915_edp_psr_status", i915_edp_psr_status, 0}, {"i915_energy_uJ", i915_energy_uJ, 0}, {"i915_pc8_status", i915_pc8_status, 0}, - {"i915_pipe_A_crc", i915_pipe_crc, 0, (void *)PIPE_A}, - {"i915_pipe_B_crc", i915_pipe_crc, 0, (void *)PIPE_B}, - {"i915_pipe_C_crc", i915_pipe_crc, 0, (void *)PIPE_C}, }; #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list) @@ -2578,6 +2676,18 @@ static struct i915_debugfs_files { {"i915_display_crc_ctl", &i915_display_crc_ctl_fops}, }; +void intel_display_crc_init(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + int i; + + for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { + struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[i]; + + init_waitqueue_head(&pipe_crc->wq); + } +} + int i915_debugfs_init(struct drm_minor *minor) { int ret, i; @@ -2586,6 +2696,12 @@ int i915_debugfs_init(struct drm_minor *minor) if (ret) return ret; + for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) { + ret = i915_pipe_crc_create(minor->debugfs_root, minor, i); + if (ret) + return ret; + } + for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) { ret = i915_debugfs_create(minor->debugfs_root, minor, i915_debugfs_files[i].name, @@ -2601,12 +2717,22 @@ int i915_debugfs_init(struct drm_minor *minor) void i915_debugfs_cleanup(struct drm_minor *minor) { + struct drm_device *dev = minor->dev; int i; drm_debugfs_remove_files(i915_debugfs_list, I915_DEBUGFS_ENTRIES, minor); + drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops, 1, minor); + + for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { + struct drm_info_list *info_list = + (struct drm_info_list *)&i915_pipe_crc_data[i]; + + drm_debugfs_remove_files(info_list, 1, minor); + } + for (i = 0; i < ARRAY_SIZE(i915_debugfs_files); i++) { struct drm_info_list *info_list = (struct drm_info_list *) i915_debugfs_files[i].fops; diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 43f54cf..1dd3c09 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1522,6 +1522,8 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev_priv->pc8.disable_count = 2; /* requirements_met + gpu_idle */ INIT_DELAYED_WORK(&dev_priv->pc8.enable_work, hsw_enable_pc8_work); + intel_display_crc_init(dev); + i915_dump_device_info(dev_priv); /* Not all pre-production machines fall into this category, only the diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 99c8e42..5cb9122 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1235,6 +1235,7 @@ struct intel_pipe_crc { struct intel_pipe_crc_entry *entries; enum intel_pipe_crc_source source; atomic_t head, tail; + wait_queue_head_t wq; }; typedef struct drm_i915_private { @@ -2234,6 +2235,11 @@ int i915_verify_lists(struct drm_device *dev); /* i915_debugfs.c */ int i915_debugfs_init(struct drm_minor *minor); void i915_debugfs_cleanup(struct drm_minor *minor); +#if defined(CONFIG_DEBUG_FS) +void intel_display_crc_init(struct drm_device *dev); +#else +void intel_display_crc_init(struct drm_device *dev) {} +#endif /* i915_gpu_error.c */ __printf(2, 3) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b201a21..b2be057 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1221,6 +1221,8 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); atomic_set(&pipe_crc->head, head); + + wake_up_interruptible(&pipe_crc->wq); } #else static void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:54 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:54 -0000 Subject: [LTSI-dev] [PATCH 20/50] drm/i915: static inline for dummy crc functions In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-21-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter Also use #ifdef to keep consistent with all other such cases. Cc: Damien Lespiau Acked-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit f8c168fa45b8bbb3ad67768c0f0b6f8054743648) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_drv.h | 4 ++-- drivers/gpu/drm/i915/i915_irq.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index b4205b5..388223d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2236,10 +2236,10 @@ int i915_verify_lists(struct drm_device *dev); /* i915_debugfs.c */ int i915_debugfs_init(struct drm_minor *minor); void i915_debugfs_cleanup(struct drm_minor *minor); -#if defined(CONFIG_DEBUG_FS) +#ifdef CONFIG_DEBUG_FS void intel_display_crc_init(struct drm_device *dev); #else -void intel_display_crc_init(struct drm_device *dev) {} +static inline void intel_display_crc_init(struct drm_device *dev) {} #endif /* i915_gpu_error.c */ diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b2be057..8c9148c 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1225,7 +1225,7 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) wake_up_interruptible(&pipe_crc->wq); } #else -static void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} +static inline void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} #endif /* The RPS events need forcewake, so we add them to a work queue and mask their -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:56 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:56 -0000 Subject: [LTSI-dev] [PATCH 21/50] drm/i915: constify harder In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-22-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter We not only want const strings, but a const array of them. Reported by checkpatch.pl Cc: Damien Lespiau Acked-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit e8dfcf789591965abf3ad72856137c35abe3edc2) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index d1674b6..5fce5d8 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1909,7 +1909,7 @@ static int i915_pipe_crc_create(struct dentry *root, struct drm_minor *minor, return drm_add_fake_info_node(minor, ent, info); } -static const char *pipe_crc_sources[] = { +static const char * const pipe_crc_sources[] = { "none", "plane1", "plane2", @@ -2054,7 +2054,7 @@ enum intel_pipe_crc_object { PIPE_CRC_OBJECT_PIPE, }; -static const char *pipe_crc_objects[] = { +static const char * const pipe_crc_objects[] = { "pipe", }; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:57 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:57 -0000 Subject: [LTSI-dev] [PATCH 22/50] drm/i915: Move some hdmi enable function name to vlv specific. In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-23-git-send-email-dheerajx.s.jamwal@intel.com> From: Chon Ming Lee There is no functional change on this patch. Only rename several hdmi encoder function name which suppose to use only by valleyview from intel_hdmi_pre_pll_enable to vlv_hdmi_pre_pll_enable, and etc. Signed-off-by: Chon Ming Lee Signed-off-by: Daniel Vetter (cherry picked from commit 9514ac6e7a55328b1fad4b7fc7227d3beb01d7ad) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_hdmi.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index 4f4d346..51a8336 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1074,7 +1074,7 @@ done: return 0; } -static void intel_hdmi_pre_enable(struct intel_encoder *encoder) +static void vlv_hdmi_pre_enable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_device *dev = encoder->base.dev; @@ -1127,7 +1127,7 @@ static void intel_hdmi_pre_enable(struct intel_encoder *encoder) vlv_wait_port_ready(dev_priv, port); } -static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder) +static void vlv_hdmi_pre_pll_enable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_device *dev = encoder->base.dev; @@ -1163,7 +1163,7 @@ static void intel_hdmi_pre_pll_enable(struct intel_encoder *encoder) mutex_unlock(&dev_priv->dpio_lock); } -static void intel_hdmi_post_disable(struct intel_encoder *encoder) +static void vlv_hdmi_post_disable(struct intel_encoder *encoder) { struct intel_digital_port *dport = enc_to_dig_port(&encoder->base); struct drm_i915_private *dev_priv = encoder->base.dev->dev_private; @@ -1313,10 +1313,10 @@ void intel_hdmi_init(struct drm_device *dev, int hdmi_reg, enum port port) intel_encoder->get_hw_state = intel_hdmi_get_hw_state; intel_encoder->get_config = intel_hdmi_get_config; if (IS_VALLEYVIEW(dev)) { - intel_encoder->pre_pll_enable = intel_hdmi_pre_pll_enable; - intel_encoder->pre_enable = intel_hdmi_pre_enable; + intel_encoder->pre_pll_enable = vlv_hdmi_pre_pll_enable; + intel_encoder->pre_enable = vlv_hdmi_pre_enable; intel_encoder->enable = vlv_enable_hdmi; - intel_encoder->post_disable = intel_hdmi_post_disable; + intel_encoder->post_disable = vlv_hdmi_post_disable; } else { intel_encoder->enable = intel_enable_hdmi; } -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:59 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:59 -0000 Subject: [LTSI-dev] [PATCH 23/50] drm/i915: Disable all GEM timers and work on unload In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-24-git-send-email-dheerajx.s.jamwal@intel.com> From: Chris Wilson We have two once very similar functions, i915_gpu_idle() and i915_gem_idle(). The former is used as the lower level operation to flush work on the GPU, whereas the latter is the high level interface to flush the GEM bookkeeping in addition to flushing the GPU. As such i915_gem_idle() also clears out the request and activity lists and cancels the delayed work. This is what we need for unloading the driver, unfortunately we called i915_gpu_idle() instead. In the process, make sure that when cancelling the delayed work and timer, which is synchronous, that we do not hold any locks to prevent a deadlock if the work item is already waiting upon the mutex. This requires us to push the mutex down from the caller to i915_gem_idle(). v2: s/i915_gem_idle/i915_gem_suspend/ Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70334 Signed-off-by: Chris Wilson Tested-by: xunx.fang at intel.com [danvet: Only set ums.suspended for !kms as discussed earlier. Chris noticed that this slipped through.] Signed-off-by: Daniel Vetter (cherry picked from commit 45c5f2022c798b2938d4c0d1c14795787f610ccd) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_dma.c | 8 +------ drivers/gpu/drm/i915/i915_drv.c | 4 +--- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 45 +++++++++++++++++---------------------- 4 files changed, 23 insertions(+), 36 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 1dd3c09..f59c2b4 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1741,15 +1741,9 @@ int i915_driver_unload(struct drm_device *dev) if (dev_priv->mm.inactive_shrinker.shrink) unregister_shrinker(&dev_priv->mm.inactive_shrinker); - mutex_lock(&dev->struct_mutex); - ret = i915_gpu_idle(dev); + ret = i915_gem_suspend(dev); if (ret) DRM_ERROR("failed to idle hardware: %d\n", ret); - i915_gem_retire_requests(dev); - mutex_unlock(&dev->struct_mutex); - - /* Cancel the retire work handler, which should be idle now. */ - cancel_delayed_work_sync(&dev_priv->mm.retire_work); io_mapping_free(dev_priv->gtt.mappable); arch_phys_wc_del(dev_priv->gtt.mtrr); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index bc83851..c0b2a0f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -487,9 +487,7 @@ static int i915_drm_freeze(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) { int error; - mutex_lock(&dev->struct_mutex); - error = i915_gem_idle(dev); - mutex_unlock(&dev->struct_mutex); + error = i915_gem_suspend(dev); if (error) { dev_err(&dev->pdev->dev, "GEM idle failed, resume might fail\n"); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 388223d..0e9042f 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2038,7 +2038,7 @@ int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice); void i915_gem_init_swizzling(struct drm_device *dev); void i915_gem_cleanup_ringbuffer(struct drm_device *dev); int __must_check i915_gpu_idle(struct drm_device *dev); -int __must_check i915_gem_idle(struct drm_device *dev); +int __must_check i915_gem_suspend(struct drm_device *dev); int __i915_add_request(struct intel_ring_buffer *ring, struct drm_file *file, struct drm_i915_gem_object *batch_obj, diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index cf2bafa..dbf5aef 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -4266,17 +4266,18 @@ void i915_gem_vma_destroy(struct i915_vma *vma) } int -i915_gem_idle(struct drm_device *dev) +i915_gem_suspend(struct drm_device *dev) { drm_i915_private_t *dev_priv = dev->dev_private; - int ret; + int ret = 0; + mutex_lock(&dev->struct_mutex); if (dev_priv->ums.mm_suspended) - return 0; + goto err; ret = i915_gpu_idle(dev); if (ret) - return ret; + goto err; i915_gem_retire_requests(dev); @@ -4284,16 +4285,26 @@ i915_gem_idle(struct drm_device *dev) if (!drm_core_check_feature(dev, DRIVER_MODESET)) i915_gem_evict_everything(dev); - del_timer_sync(&dev_priv->gpu_error.hangcheck_timer); - i915_kernel_lost_context(dev); i915_gem_cleanup_ringbuffer(dev); - /* Cancel the retire work handler, which should be idle now. */ + /* Hack! Don't let anybody do execbuf while we don't control the chip. + * We need to replace this with a semaphore, or something. + * And not confound ums.mm_suspended! + */ + dev_priv->ums.mm_suspended = !drm_core_check_feature(dev, + DRIVER_MODESET); + mutex_unlock(&dev->struct_mutex); + + del_timer_sync(&dev_priv->gpu_error.hangcheck_timer); cancel_delayed_work_sync(&dev_priv->mm.retire_work); cancel_delayed_work_sync(&dev_priv->mm.idle_work); return 0; + +err: + mutex_unlock(&dev->struct_mutex); + return ret; } int i915_gem_l3_remap(struct intel_ring_buffer *ring, int slice) @@ -4546,26 +4557,12 @@ int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_i915_private *dev_priv = dev->dev_private; - int ret; - if (drm_core_check_feature(dev, DRIVER_MODESET)) return 0; drm_irq_uninstall(dev); - mutex_lock(&dev->struct_mutex); - ret = i915_gem_idle(dev); - - /* Hack! Don't let anybody do execbuf while we don't control the chip. - * We need to replace this with a semaphore, or something. - * And not confound ums.mm_suspended! - */ - if (ret != 0) - dev_priv->ums.mm_suspended = 1; - mutex_unlock(&dev->struct_mutex); - - return ret; + return i915_gem_suspend(dev); } void @@ -4576,11 +4573,9 @@ i915_gem_lastclose(struct drm_device *dev) if (drm_core_check_feature(dev, DRIVER_MODESET)) return; - mutex_lock(&dev->struct_mutex); - ret = i915_gem_idle(dev); + ret = i915_gem_suspend(dev); if (ret) DRM_ERROR("failed to idle hardware: %d\n", ret); - mutex_unlock(&dev->struct_mutex); } static void -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:25:59 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:25:59 -0000 Subject: [LTSI-dev] [PATCH 24/50] drm/i915: Use pipe_name() instead of the pipe number In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-25-git-send-email-dheerajx.s.jamwal@intel.com> From: Damien Lespiau Yet other direct usages of the pipe number instead of pipe_name(). We've been tracking them lately but managed to miss these last ones. v2: Catch them all! (Ville) Reviewed-by: Ville Syrj?l? (v1) Signed-off-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 6f2bcceb27b6120af6b76a865a72eafa50323d41) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_display.c | 4 ++-- drivers/gpu/drm/i915/intel_dsi.c | 2 +- drivers/gpu/drm/i915/intel_panel.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 081a7dd..436cb5b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -10762,11 +10762,11 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev) } encoder->connectors_active = false; - DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe=%i\n", + DRM_DEBUG_KMS("[ENCODER:%d:%s] hw state readout: %s, pipe %c\n", encoder->base.base.id, drm_get_encoder_name(&encoder->base), encoder->base.crtc ? "enabled" : "disabled", - pipe); + pipe_name(pipe)); } list_for_each_entry(connector, &dev->mode_config.connector_list, diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 9a2fdd2..d257b09 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c @@ -350,7 +350,7 @@ static void intel_dsi_mode_set(struct intel_encoder *intel_encoder) unsigned int bpp = intel_crtc->config.pipe_bpp; u32 val, tmp; - DRM_DEBUG_KMS("pipe %d\n", pipe); + DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); /* Update the DSI PLL */ vlv_enable_dsi_pll(intel_encoder); diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index 1f29960..de15186 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c @@ -574,7 +574,7 @@ void intel_panel_enable_backlight(struct drm_device *dev, intel_pipe_to_cpu_transcoder(dev_priv, pipe); unsigned long flags; - DRM_DEBUG_KMS("pipe=%d\n", pipe); + DRM_DEBUG_KMS("pipe %c\n", pipe_name(pipe)); spin_lock_irqsave(&dev_priv->backlight.lock, flags); -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:01 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:01 -0000 Subject: [LTSI-dev] [PATCH 25/50] drm/i915: preserve dispaly init order on ByT In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-26-git-send-email-dheerajx.s.jamwal@intel.com> From: Artem Bityutskiy This patch changes HDMI port registration order for the BayTrail platform. The story is that in kernel version 3.11 i915 supported only one HDMI port - the HDMIB port. So this port ended up being HDMI-1 in user-space. But commit '6f6005a drm/i915: expose HDMI connectors on port C on BYT' introduced HDMIC port support. And added HDMIC registration prior to HDMIB, so HDMIB became HDMI-2 and HDMIC became HDMI-1. Well, this is fine as far as the kernel is concerned. i915 does not give any guarantees to the numbering, and has never given them. However, this breaks wayland setup in Tizen IVI. We have only one single HDMI port on our hardware, and it is connected to HDMIB. Our configuration relies on the fact that it is HDMI-1. Well, certainly this is user-space problem which was exposed with Jesse's patch. However, there is a reason why we have to do this assumption - we use touchscreen monitors and we have to associate event devices with the monitors, and this is not easy to do dynamically, so we just have a static setup. Anyway, while the user-space setup will have to be fixed regardless, let's chane the HDMI port registration order so that HDMIB stays HDMI-1, just like it was in 3.11. Simply because there is no strong reason for changing the order in the kernel, and it'll help setups like ours in sense that we'll have more time for fixing the issue properly. Also amend the commentary which looks a bit out-of-date. Signed-off-by: Artem Bityutskiy [danvet: Drop the commment, SDVOC is gone and we have a proper HDMIC define now.] Signed-off-by: Daniel Vetter (cherry picked from commit 585a94b80ec2393fbb09739a355fb8ba9e7c27c4) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_display.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 436cb5b..f12748e 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9884,7 +9884,13 @@ static void intel_setup_outputs(struct drm_device *dev) if (I915_READ(PCH_DP_D) & DP_DETECTED) intel_dp_init(dev, PCH_DP_D, PORT_D); } else if (IS_VALLEYVIEW(dev)) { - /* Check for built-in panel first. Shares lanes with HDMI on SDVOC */ + if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) { + intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB, + PORT_B); + if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED) + intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B); + } + if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIC) & SDVO_DETECTED) { intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIC, PORT_C); @@ -9893,13 +9899,6 @@ static void intel_setup_outputs(struct drm_device *dev) PORT_C); } - if (I915_READ(VLV_DISPLAY_BASE + GEN4_HDMIB) & SDVO_DETECTED) { - intel_hdmi_init(dev, VLV_DISPLAY_BASE + GEN4_HDMIB, - PORT_B); - if (I915_READ(VLV_DISPLAY_BASE + DP_B) & DP_DETECTED) - intel_dp_init(dev, VLV_DISPLAY_BASE + DP_B, PORT_B); - } - intel_dsi_init(dev); } else if (SUPPORTS_DIGITAL_OUTPUTS(dev)) { bool found = false; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:02 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:02 -0000 Subject: [LTSI-dev] [PATCH 26/50] drm/i915: vlv: fix VGA hotplug after modeset In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-27-git-send-email-dheerajx.s.jamwal@intel.com> From: Imre Deak Since commit 912d812e84cea8689a2bf3dd13b11dfe191f0f1e Author: Daniel Vetter Date: Thu Oct 11 20:08:23 2012 +0200 drm/i915/crt: don't set HOTPLUG bits on !PCH on VLV we don't detect any VGA unplug event after a modeset, since there we reset the ADPA hotplug bits. Fix it by preserving the hotplug bits on VLV as well. Signed-off-by: Imre Deak [danvet: For consistency use gen >= 5 like in Chris' exact same fix in intel_crt_reset.] Signed-off-by: Daniel Vetter (cherry picked from commit 533df0fecdeda3e116ee8ffc8bfef96216e814bc) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_crt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 942b9ac..2e01bd3 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -274,7 +274,7 @@ static void intel_crt_mode_set(struct intel_encoder *encoder) struct drm_display_mode *adjusted_mode = &crtc->config.adjusted_mode; u32 adpa; - if (HAS_PCH_SPLIT(dev)) + if (INTEL_INFO(dev)->gen >= 5) adpa = ADPA_HOTPLUG_BITS; else adpa = 0; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:04 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:04 -0000 Subject: [LTSI-dev] [PATCH 27/50] drm/i915: grab dev->struct_mutex around framebuffer_init In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-28-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter We look at gem state (like obj->tiling/obj->stride), we better have the relevant locks. Right now this doesn't matter much since most of these checks are a curtesy to safe buggy userspace, but I'd like to freeze the tiling once we have framebuffer objects attached. And then locking matters. Cc: Ville Syrj?l? Reviewed-by: Ville Syrj?l? Signed-off-by: Daniel Vetter (cherry picked from commit dd4916c55aa4bacb26c343d0f0faa64e7aaef918) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_display.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index f12748e..249a6cf 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -7285,14 +7285,21 @@ intel_framebuffer_create(struct drm_device *dev, return ERR_PTR(-ENOMEM); } + ret = i915_mutex_lock_interruptible(dev); + if (ret) + goto err; + ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj); - if (ret) { - drm_gem_object_unreference_unlocked(&obj->base); - kfree(intel_fb); - return ERR_PTR(ret); - } + mutex_unlock(&dev->struct_mutex); + if (ret) + goto err; return &intel_fb->base; +err: + drm_gem_object_unreference_unlocked(&obj->base); + kfree(intel_fb); + + return ERR_PTR(ret); } static u32 @@ -9989,6 +9996,8 @@ int intel_framebuffer_init(struct drm_device *dev, int pitch_limit; int ret; + WARN_ON(!mutex_is_locked(&dev->struct_mutex)); + if (obj->tiling_mode == I915_TILING_Y) { DRM_DEBUG("hardware does not support tiling Y\n"); return -EINVAL; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:07 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:07 -0000 Subject: [LTSI-dev] [PATCH 28/50] drm/i915: prevent tiling changes on framebuffer backing storage In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-29-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter Assuming that all framebuffer related metadata is invariant simplifies our userspace input data checking. And current userspace always first updates the tiling of an object before creating a framebuffer with it. This allows us to upconvert a check in pin_and_fence to a WARN. In the future it should also be helpful to know which buffer objects are potential scanout targets for e.g. frontbuffer rendering tracking and similar things. Note that SNA shipped for one prerelease with code which will be broken through this patch. But users shouldn't notice since it's purely an optimization and will transparently fall back to allocating a new fb. i-g-t also had offending code (now fixed), but we don't really care about breaking the test-suite. Cc: Ville Syrj?l? Reviewed-by: Ville Syrj?l? Grumpily-reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter (cherry picked from commit 80075d492f8773209e26d11d6bb13ba624ef95a4) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_drv.h | 3 +++ drivers/gpu/drm/i915/i915_gem_tiling.c | 2 +- drivers/gpu/drm/i915/intel_display.c | 7 +++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0e9042f..558cbe1 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1597,6 +1597,9 @@ struct drm_i915_gem_object { /** Current tiling stride for the object, if it's tiled. */ uint32_t stride; + /** References from framebuffers, locks out tiling changes. */ + unsigned long framebuffer_references; + /** Record of address bit 17 of each page at last unbind. */ unsigned long *bit_17; diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index ac9ebe9..b139053 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c @@ -308,7 +308,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data, return -EINVAL; } - if (obj->pin_count) { + if (obj->pin_count || obj->framebuffer_references) { drm_gem_object_unreference_unlocked(&obj->base); return -EBUSY; } diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 249a6cf..e302c0d 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -1921,10 +1921,7 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, alignment = 0; break; case I915_TILING_Y: - /* Despite that we check this in framebuffer_init userspace can - * screw us over and change the tiling after the fact. Only - * pinned buffers can't change their tiling. */ - DRM_DEBUG_DRIVER("Y tiled not allowed for scan out buffers\n"); + WARN(1, "Y tiled bo slipped through, driver bug!\n"); return -EINVAL; default: BUG(); @@ -9962,6 +9959,7 @@ static void intel_setup_outputs(struct drm_device *dev) void intel_framebuffer_fini(struct intel_framebuffer *fb) { drm_framebuffer_cleanup(&fb->base); + WARN_ON(!fb->obj->framebuffer_references--); drm_gem_object_unreference_unlocked(&fb->obj->base); } @@ -10088,6 +10086,7 @@ int intel_framebuffer_init(struct drm_device *dev, drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); intel_fb->obj = obj; + intel_fb->obj->framebuffer_references++; ret = drm_framebuffer_init(dev, &intel_fb->base, &intel_fb_funcs); if (ret) { -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:07 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:07 -0000 Subject: [LTSI-dev] [PATCH 29/50] drm/i915: Use unsigned long for obj->user_pin_count In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-30-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter At least on linux sizeof(long) == sizeof(void*) and the thinking is that you can grab about as many references as there's memory. Doesn't really matter, just a bit of OCD since the fixed size data type in a pure in-kernel datastructure look off. v2: Ville asked for an overflow check since no one prevents userspace from incrementing the pin count forever. v3: s/INT/LONG/, noticed by Chris. Cc: Chris Wilson Cc: Ville Syrj?l? Reviewed-by: Ville Syrj?l? Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter (cherry picked from commit aa5f8021811aede2e40aa715c55fbd87d945a443) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_drv.h | 2 +- drivers/gpu/drm/i915/i915_gem.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 558cbe1..1fe6e63 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1604,7 +1604,7 @@ struct drm_i915_gem_object { unsigned long *bit_17; /** User space pin count and filp owning the pin */ - uint32_t user_pin_count; + unsigned long user_pin_count; struct drm_file *pin_filp; /** for phy allocated objects */ diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index dbf5aef..32784ff 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3925,6 +3925,11 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, goto out; } + if (obj->user_pin_count == ULONG_MAX) { + ret = -EBUSY; + goto out; + } + if (obj->user_pin_count == 0) { ret = i915_gem_obj_ggtt_pin(obj, args->alignment, true, false); if (ret) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:09 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:09 -0000 Subject: [LTSI-dev] [PATCH 30/50] drm/i915: check gem bo size when creating framebuffers In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-31-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter It's better to catch such fallout early, and this way we can rely on the checking done by the drm core on fb->heigh/width at modeset time. If we ever support planar formats on intel we might want to look into a common helper to do all this, but for now this is good enough. v2: Take tiling into account, requested by Ville. v3: Fix tile height on gen2, spotted by Ville. Cc: Ville Syrj?l? Requested-by: Chris Wilson Cc: Chris Wilson Reviewed-by: Ville Syrj?l? Signed-off-by: Daniel Vetter (cherry picked from commit 53155c0a5949d5cc3bd434d838e5b0c6e0542f9b) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_display.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index e302c0d..6383f57 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -9991,6 +9991,7 @@ int intel_framebuffer_init(struct drm_device *dev, struct drm_mode_fb_cmd2 *mode_cmd, struct drm_i915_gem_object *obj) { + int aligned_height, tile_height; int pitch_limit; int ret; @@ -10084,6 +10085,13 @@ int intel_framebuffer_init(struct drm_device *dev, if (mode_cmd->offsets[0] != 0) return -EINVAL; + tile_height = IS_GEN2(dev) ? 16 : 8; + aligned_height = ALIGN(mode_cmd->height, + obj->tiling_mode ? tile_height : 1); + /* FIXME drm helper for size checks (especially planar formats)? */ + if (obj->base.size < aligned_height * mode_cmd->pitches[0]) + return -EINVAL; + drm_helper_mode_fill_fb_struct(&intel_fb->base, mode_cmd); intel_fb->obj = obj; intel_fb->obj->framebuffer_references++; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:10 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:10 -0000 Subject: [LTSI-dev] [PATCH 31/50] drm/i915: pass mode to ELD write vfuncs In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-32-git-send-email-dheerajx.s.jamwal@intel.com> From: Jani Nikula This will be needed for setting the HDMI pixel clock for audio config. No functional changes. v2: Now with a commit message. Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter (cherry picked from commit 34427052ebb450cbf1d0f2851436fbe216f56417) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/intel_display.c | 11 +++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 1fe6e63..c119a01 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -379,7 +379,8 @@ struct drm_i915_display_funcs { void (*crtc_disable)(struct drm_crtc *crtc); void (*off)(struct drm_crtc *crtc); void (*write_eld)(struct drm_connector *connector, - struct drm_crtc *crtc); + struct drm_crtc *crtc, + struct drm_display_mode *mode); void (*fdi_link_train)(struct drm_crtc *crtc); void (*init_clock_gating)(struct drm_device *dev); int (*queue_flip)(struct drm_device *dev, struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 6383f57..fcf276b 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6749,7 +6749,8 @@ static bool intel_eld_uptodate(struct drm_connector *connector, } static void g4x_write_eld(struct drm_connector *connector, - struct drm_crtc *crtc) + struct drm_crtc *crtc, + struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; @@ -6789,7 +6790,8 @@ static void g4x_write_eld(struct drm_connector *connector, } static void haswell_write_eld(struct drm_connector *connector, - struct drm_crtc *crtc) + struct drm_crtc *crtc, + struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; @@ -6876,7 +6878,8 @@ static void haswell_write_eld(struct drm_connector *connector, } static void ironlake_write_eld(struct drm_connector *connector, - struct drm_crtc *crtc) + struct drm_crtc *crtc, + struct drm_display_mode *mode) { struct drm_i915_private *dev_priv = connector->dev->dev_private; uint8_t *eld = connector->eld; @@ -6971,7 +6974,7 @@ void intel_write_eld(struct drm_encoder *encoder, connector->eld[6] = drm_av_sync_delay(connector, mode) / 2; if (dev_priv->display.write_eld) - dev_priv->display.write_eld(connector, crtc); + dev_priv->display.write_eld(connector, crtc, mode); } static void i845_update_cursor(struct drm_crtc *crtc, u32 base) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:15 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:15 -0000 Subject: [LTSI-dev] [PATCH 33/50] drm/i915: don't Oops in debugfs for I915_FBDEV=n In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-34-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter Failed to properly test this. Reported-by: Chris Wilson Cc: Chris Wilson Tested-by: Chris Wilson Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter (cherry picked from commit 131a56dc41b8c026f97466341167d86deb25357b) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 5fce5d8..7811bf4 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1456,7 +1456,7 @@ static int i915_gem_framebuffer_info(struct seq_file *m, void *data) mutex_lock(&dev->mode_config.fb_lock); list_for_each_entry(fb, &dev->mode_config.fb_list, base.head) { - if (&fb->base == ifbdev->helper.fb) + if (ifbdev && &fb->base == ifbdev->helper.fb) continue; seq_printf(m, "user size: %d x %d, depth %d, %d bpp, refcount %d, obj ", -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:15 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:15 -0000 Subject: [LTSI-dev] [PATCH 32/50] drm/i915: set HDMI pixel clock in audio configuration In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-33-git-send-email-dheerajx.s.jamwal@intel.com> From: Jani Nikula The HDMI audio expects HDMI pixel clock to be set in the audio configuration. We've currently just set 0, using 25.2 / 1.001 kHz frequency, which fails with some modes. v2: Now with a commit message. Reference: http://mid.gmane.org/CAGpEb3Ep1LRZETPxHGRfBDqr5Ts2tAc8gCukWwugUf1U5NYv1g at mail.gmail.com Reference: http://mid.gmane.org/20130206213533.GA16367 at hardeman.nu Reported-by: David H?rdeman Reported-by: Jasper Smet Tested-by: Jasper Smet Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Daniel Vetter (cherry picked from commit 1a91510dc3b8098930ebda3018f5cd72e8428243) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_reg.h | 12 ++++++++- drivers/gpu/drm/i915/intel_display.c | 48 +++++++++++++++++++++++++++++++--- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index e4775dd..0ee9411 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -4905,7 +4905,17 @@ #define AUD_CONFIG_LOWER_N_SHIFT 4 #define AUD_CONFIG_LOWER_N_VALUE (0xfff << 4) #define AUD_CONFIG_PIXEL_CLOCK_HDMI_SHIFT 16 -#define AUD_CONFIG_PIXEL_CLOCK_HDMI (0xf << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_MASK (0xf << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 (0 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 (1 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 (2 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 (3 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 (4 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 (5 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 (6 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 (7 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 (8 << 16) +#define AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 (9 << 16) #define AUD_CONFIG_DISABLE_NCTS (1 << 3) /* HSW Audio */ diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index fcf276b..1b48257 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6719,6 +6719,44 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, return 0; } +static struct { + int clock; + u32 config; +} hdmi_audio_clock[] = { + { DIV_ROUND_UP(25200 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_25175 }, + { 25200, AUD_CONFIG_PIXEL_CLOCK_HDMI_25200 }, /* default per bspec */ + { 27000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27000 }, + { 27000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_27027 }, + { 54000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54000 }, + { 54000 * 1001 / 1000, AUD_CONFIG_PIXEL_CLOCK_HDMI_54054 }, + { DIV_ROUND_UP(74250 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_74176 }, + { 74250, AUD_CONFIG_PIXEL_CLOCK_HDMI_74250 }, + { DIV_ROUND_UP(148500 * 1000, 1001), AUD_CONFIG_PIXEL_CLOCK_HDMI_148352 }, + { 148500, AUD_CONFIG_PIXEL_CLOCK_HDMI_148500 }, +}; + +/* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ +static u32 audio_config_hdmi_pixel_clock(struct drm_display_mode *mode) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(hdmi_audio_clock); i++) { + if (mode->clock == hdmi_audio_clock[i].clock) + break; + } + + if (i == ARRAY_SIZE(hdmi_audio_clock)) { + DRM_DEBUG_KMS("HDMI audio pixel clock setting for %d not found, falling back to defaults\n", mode->clock); + i = 1; + } + + DRM_DEBUG_KMS("Configuring HDMI audio for pixel clock %d (0x%08x)\n", + hdmi_audio_clock[i].clock, + hdmi_audio_clock[i].config); + + return hdmi_audio_clock[i].config; +} + static bool intel_eld_uptodate(struct drm_connector *connector, int reg_eldv, uint32_t bits_eldv, int reg_elda, uint32_t bits_elda, @@ -6844,8 +6882,9 @@ static void haswell_write_eld(struct drm_connector *connector, DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ - } else - I915_WRITE(aud_config, 0); + } else { + I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); + } if (intel_eld_uptodate(connector, aud_cntrl_st2, eldv, @@ -6923,8 +6962,9 @@ static void ironlake_write_eld(struct drm_connector *connector, DRM_DEBUG_DRIVER("ELD: DisplayPort detected\n"); eld[5] |= (1 << 2); /* Conn_Type, 0x1 = DisplayPort */ I915_WRITE(aud_config, AUD_CONFIG_N_VALUE_INDEX); /* 0x1 = DP */ - } else - I915_WRITE(aud_config, 0); + } else { + I915_WRITE(aud_config, audio_config_hdmi_pixel_clock(mode)); + } if (intel_eld_uptodate(connector, aud_cntrl_st2, eldv, -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:15 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:15 -0000 Subject: [LTSI-dev] [PATCH 34/50] drm/i915: extract display_pipe_crc_update In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-35-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter The ringbuffer update logic should always be the same, but different platforms have different amounts of CRC registers. Hence extract it. Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit eba94eb90138caf0b22797dc5fd802e28d253dcf) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_irq.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 8c9148c..df031bb 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1190,7 +1190,10 @@ static void dp_aux_irq_handler(struct drm_device *dev) } #if defined(CONFIG_DEBUG_FS) -static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +static void display_pipe_crc_update(struct drm_device *dev, enum pipe pipe, + uint32_t crc0, uint32_t crc1, + uint32_t crc2, uint32_t crc3, + uint32_t crc4, uint32_t frame) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; @@ -1212,18 +1215,31 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) entry = &pipe_crc->entries[head]; - entry->frame = I915_READ(PIPEFRAME(pipe)); - entry->crc[0] = I915_READ(PIPE_CRC_RES_1_IVB(pipe)); - entry->crc[1] = I915_READ(PIPE_CRC_RES_2_IVB(pipe)); - entry->crc[2] = I915_READ(PIPE_CRC_RES_3_IVB(pipe)); - entry->crc[3] = I915_READ(PIPE_CRC_RES_4_IVB(pipe)); - entry->crc[4] = I915_READ(PIPE_CRC_RES_5_IVB(pipe)); + entry->frame = frame; + entry->crc[0] = crc0; + entry->crc[1] = crc1; + entry->crc[2] = crc2; + entry->crc[3] = crc3; + entry->crc[4] = crc4; head = (head + 1) & (INTEL_PIPE_CRC_ENTRIES_NR - 1); atomic_set(&pipe_crc->head, head); wake_up_interruptible(&pipe_crc->wq); } + +static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + display_pipe_crc_update(dev, pipe, + I915_READ(PIPE_CRC_RES_1_IVB(pipe)), + I915_READ(PIPE_CRC_RES_2_IVB(pipe)), + I915_READ(PIPE_CRC_RES_3_IVB(pipe)), + I915_READ(PIPE_CRC_RES_4_IVB(pipe)), + I915_READ(PIPE_CRC_RES_5_IVB(pipe)), + I915_READ(PIPEFRAME(pipe))); +} #else static inline void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} #endif -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:16 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:16 -0000 Subject: [LTSI-dev] [PATCH 35/50] drm/i915: add CRC #defines for ilk/snb In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-36-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter Also add a new _PIPE_INC macro which takes an base plus increment. Much less likely to botch the job by missing an s/A/B/ somewhere. v2: They've moved the bitfield. Argh! Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 5a6b5c84e494336935a32909a640c2da267fda0d) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_reg.h | 46 +++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 0ee9411..c376572 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -26,6 +26,7 @@ #define _I915_REG_H_ #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) +#define _PIPE_INC(pipe, base, inc) ((base) + (pipe)*(inc)) #define _TRANSCODER(tran, a, b) ((a) + (tran)*((b)-(a))) #define _PORT(port, a, b) ((a) + (port)*((b)-(a))) @@ -1844,19 +1845,31 @@ #define PIPE_CRC_SOURCE_PRIMARY_IVB (0 << 29) #define PIPE_CRC_SOURCE_SPRITE_IVB (1 << 29) #define PIPE_CRC_SOURCE_PF_IVB (2 << 29) -#define _PIPE_CRC_RES_1_A_IVB (dev_priv->info->display_mmio_offset + 0x60064) -#define _PIPE_CRC_RES_2_A_IVB (dev_priv->info->display_mmio_offset + 0x60068) -#define _PIPE_CRC_RES_3_A_IVB (dev_priv->info->display_mmio_offset + 0x6006c) -#define _PIPE_CRC_RES_4_A_IVB (dev_priv->info->display_mmio_offset + 0x60070) -#define _PIPE_CRC_RES_5_A_IVB (dev_priv->info->display_mmio_offset + 0x60074) +#define PIPE_CRC_SOURCE_PRIMARY_ILK (0 << 28) +#define PIPE_CRC_SOURCE_SPRITE_ILK (1 << 28) +#define PIPE_CRC_SOURCE_PIPE_ILK (2 << 28) +/* embedded DP port on the north display block, reserved on ivb */ +#define PIPE_CRC_SOURCE_PORT_A_ILK (4 << 28) +#define PIPE_CRC_SOURCE_FDI_ILK (5 << 28) /* reserved on ivb */ +#define _PIPE_CRC_RES_1_A_IVB 0x60064 +#define _PIPE_CRC_RES_2_A_IVB 0x60068 +#define _PIPE_CRC_RES_3_A_IVB 0x6006c +#define _PIPE_CRC_RES_4_A_IVB 0x60070 +#define _PIPE_CRC_RES_5_A_IVB 0x60074 + +#define _PIPE_CRC_RES_RED_A_ILK 0x60060 +#define _PIPE_CRC_RES_GREEN_A_ILK 0x60064 +#define _PIPE_CRC_RES_BLUE_A_ILK 0x60068 +#define _PIPE_CRC_RES_RES1_A_ILK 0x6006c +#define _PIPE_CRC_RES_RES2_A_ILK 0x60080 /* Pipe B CRC regs */ -#define _PIPE_CRC_CTL_B (dev_priv->info->display_mmio_offset + 0x61050) -#define _PIPE_CRC_RES_1_B_IVB (dev_priv->info->display_mmio_offset + 0x61064) -#define _PIPE_CRC_RES_2_B_IVB (dev_priv->info->display_mmio_offset + 0x61068) -#define _PIPE_CRC_RES_3_B_IVB (dev_priv->info->display_mmio_offset + 0x6106c) -#define _PIPE_CRC_RES_4_B_IVB (dev_priv->info->display_mmio_offset + 0x61070) -#define _PIPE_CRC_RES_5_B_IVB (dev_priv->info->display_mmio_offset + 0x61074) +#define _PIPE_CRC_CTL_B 0x61050 +#define _PIPE_CRC_RES_1_B_IVB 0x61064 +#define _PIPE_CRC_RES_2_B_IVB 0x61068 +#define _PIPE_CRC_RES_3_B_IVB 0x6106c +#define _PIPE_CRC_RES_4_B_IVB 0x61070 +#define _PIPE_CRC_RES_5_B_IVB 0x61074 #define PIPE_CRC_CTL(pipe) _PIPE(pipe, _PIPE_CRC_CTL_A, _PIPE_CRC_CTL_B) #define PIPE_CRC_RES_1_IVB(pipe) \ @@ -1870,6 +1883,17 @@ #define PIPE_CRC_RES_5_IVB(pipe) \ _PIPE(pipe, _PIPE_CRC_RES_5_A_IVB, _PIPE_CRC_RES_5_B_IVB) +#define PIPE_CRC_RES_RED_ILK(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_RED_A_ILK, 0x01000) +#define PIPE_CRC_RES_GREEN_ILK(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_GREEN_A_ILK, 0x01000) +#define PIPE_CRC_RES_BLUE_ILK(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_BLUE_A_ILK, 0x01000) +#define PIPE_CRC_RES_RES1_ILK(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_RES1_A_ILK, 0x01000) +#define PIPE_CRC_RES_RES2_ILK(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_RES2_A_ILK, 0x01000) + /* Pipe A timing regs */ #define _HTOTAL_A (dev_priv->info->display_mmio_offset + 0x60000) #define _HBLANK_A (dev_priv->info->display_mmio_offset + 0x60004) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:18 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:18 -0000 Subject: [LTSI-dev] [PATCH 36/50] drm/i915: wire up CRC interrupt for ilk/snb In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-37-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter We enable the interrupt unconditionally and only control it through the enable bit in the CRC control register. v2: Extract per-platform helpers to compute the register values. Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 5b3a856bcfa3d24496035a77ab086548773a633d) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 74 +++++++++++++++++++++++++++-------- drivers/gpu/drm/i915/i915_drv.h | 1 + drivers/gpu/drm/i915/i915_irq.c | 26 +++++++++++- drivers/gpu/drm/i915/i915_reg.h | 2 + 4 files changed, 84 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 7811bf4..baa5272 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1914,6 +1914,7 @@ static const char * const pipe_crc_sources[] = { "plane1", "plane2", "pf", + "pipe", }; static const char *pipe_crc_source_name(enum intel_pipe_crc_source source) @@ -1942,14 +1943,61 @@ static int display_crc_ctl_open(struct inode *inode, struct file *file) return single_open(file, display_crc_ctl_show, dev); } +static int ilk_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, + uint32_t *val) +{ + switch (source) { + case INTEL_PIPE_CRC_SOURCE_PLANE1: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_ILK; + break; + case INTEL_PIPE_CRC_SOURCE_PLANE2: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_ILK; + break; + case INTEL_PIPE_CRC_SOURCE_PF: + return -EINVAL; + case INTEL_PIPE_CRC_SOURCE_PIPE: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PIPE_ILK; + break; + default: + *val = 0; + break; + } + + return 0; +} + +static int ivb_pipe_crc_ctl_reg(enum intel_pipe_crc_source source, + uint32_t *val) +{ + switch (source) { + case INTEL_PIPE_CRC_SOURCE_PLANE1: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_IVB; + break; + case INTEL_PIPE_CRC_SOURCE_PLANE2: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; + break; + case INTEL_PIPE_CRC_SOURCE_PF: + *val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB; + break; + case INTEL_PIPE_CRC_SOURCE_PIPE: + return -EINVAL; + default: + *val = 0; + break; + } + + return 0; +} + static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, enum intel_pipe_crc_source source) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; u32 val; + int ret; - if (!IS_IVYBRIDGE(dev)) + if (!(IS_IVYBRIDGE(dev) || IS_GEN5(dev) || IS_GEN6(dev))) return -ENODEV; if (pipe_crc->source == source) @@ -1959,6 +2007,14 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, if (pipe_crc->source && source) return -EINVAL; + if (IS_GEN5(dev) || IS_GEN6(dev)) + ret = ilk_pipe_crc_ctl_reg(source, &val); + else + ret = ivb_pipe_crc_ctl_reg(source, &val); + + if (ret != 0) + return ret; + /* none -> real source transition */ if (source) { DRM_DEBUG_DRIVER("collecting CRCs for pipe %c, %s\n", @@ -1976,22 +2032,6 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, pipe_crc->source = source; - switch (source) { - case INTEL_PIPE_CRC_SOURCE_PLANE1: - val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PRIMARY_IVB; - break; - case INTEL_PIPE_CRC_SOURCE_PLANE2: - val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_SPRITE_IVB; - break; - case INTEL_PIPE_CRC_SOURCE_PF: - val = PIPE_CRC_ENABLE | PIPE_CRC_SOURCE_PF_IVB; - break; - case INTEL_PIPE_CRC_SOURCE_NONE: - default: - val = 0; - break; - } - I915_WRITE(PIPE_CRC_CTL(pipe), val); POSTING_READ(PIPE_CRC_CTL(pipe)); diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index c119a01..8a2a474 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1223,6 +1223,7 @@ enum intel_pipe_crc_source { INTEL_PIPE_CRC_SOURCE_PLANE1, INTEL_PIPE_CRC_SOURCE_PLANE2, INTEL_PIPE_CRC_SOURCE_PF, + INTEL_PIPE_CRC_SOURCE_PIPE, INTEL_PIPE_CRC_SOURCE_MAX, }; diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index df031bb..36465ef 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1240,8 +1240,22 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) I915_READ(PIPE_CRC_RES_5_IVB(pipe)), I915_READ(PIPEFRAME(pipe))); } + +static void ilk_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + display_pipe_crc_update(dev, pipe, + I915_READ(PIPE_CRC_RES_RED_ILK(pipe)), + I915_READ(PIPE_CRC_RES_GREEN_ILK(pipe)), + I915_READ(PIPE_CRC_RES_BLUE_ILK(pipe)), + I915_READ(PIPE_CRC_RES_RES1_ILK(pipe)), + I915_READ(PIPE_CRC_RES_RES2_ILK(pipe)), + I915_READ(PIPEFRAME(pipe))); +} #else static inline void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} +static inline void ilk_pipe_crc_update(struct drm_device *dev, int pipe) {} #endif /* The RPS events need forcewake, so we add them to a work queue and mask their @@ -1524,6 +1538,12 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false)) DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); + if (de_iir & DE_PIPEA_CRC_DONE) + ilk_pipe_crc_update(dev, PIPE_A); + + if (de_iir & DE_PIPEB_CRC_DONE) + ilk_pipe_crc_update(dev, PIPE_B); + if (de_iir & DE_PLANEA_FLIP_DONE) { intel_prepare_page_flip(dev, 0); intel_finish_page_flip_plane(dev, 0); @@ -2500,8 +2520,10 @@ static int ironlake_irq_postinstall(struct drm_device *dev) } else { display_mask = (DE_MASTER_IRQ_CONTROL | DE_GSE | DE_PCH_EVENT | DE_PLANEA_FLIP_DONE | DE_PLANEB_FLIP_DONE | - DE_AUX_CHANNEL_A | DE_PIPEB_FIFO_UNDERRUN | - DE_PIPEA_FIFO_UNDERRUN | DE_POISON); + DE_AUX_CHANNEL_A | + DE_PIPEB_FIFO_UNDERRUN | DE_PIPEA_FIFO_UNDERRUN | + DE_PIPEB_CRC_DONE | DE_PIPEA_CRC_DONE | + DE_POISON); extra_mask = DE_PIPEA_VBLANK | DE_PIPEB_VBLANK | DE_PCU_EVENT; } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index c376572..3388105 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -3922,12 +3922,14 @@ #define DE_PIPEB_ODD_FIELD (1 << 13) #define DE_PIPEB_LINE_COMPARE (1 << 12) #define DE_PIPEB_VSYNC (1 << 11) +#define DE_PIPEB_CRC_DONE (1 << 10) #define DE_PIPEB_FIFO_UNDERRUN (1 << 8) #define DE_PIPEA_VBLANK (1 << 7) #define DE_PIPEA_EVEN_FIELD (1 << 6) #define DE_PIPEA_ODD_FIELD (1 << 5) #define DE_PIPEA_LINE_COMPARE (1 << 4) #define DE_PIPEA_VSYNC (1 << 3) +#define DE_PIPEA_CRC_DONE (1 << 2) #define DE_PIPEA_FIFO_UNDERRUN (1 << 0) /* More Ivybridge lolz */ -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:19 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:19 -0000 Subject: [LTSI-dev] [PATCH 37/50] drm/i915: use ->get_vblank_counter for the crc frame counter In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-38-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter Suggested by Ville. Cc: Ville Syrj?l? Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 8bc5e955f4819331ed470b251043bbfd5e2aab71) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_irq.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 36465ef..eaf1268 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1193,7 +1193,7 @@ static void dp_aux_irq_handler(struct drm_device *dev) static void display_pipe_crc_update(struct drm_device *dev, enum pipe pipe, uint32_t crc0, uint32_t crc1, uint32_t crc2, uint32_t crc3, - uint32_t crc4, uint32_t frame) + uint32_t crc4) { struct drm_i915_private *dev_priv = dev->dev_private; struct intel_pipe_crc *pipe_crc = &dev_priv->pipe_crc[pipe]; @@ -1215,7 +1215,7 @@ static void display_pipe_crc_update(struct drm_device *dev, enum pipe pipe, entry = &pipe_crc->entries[head]; - entry->frame = frame; + entry->frame = dev->driver->get_vblank_counter(dev, pipe); entry->crc[0] = crc0; entry->crc[1] = crc1; entry->crc[2] = crc2; @@ -1237,8 +1237,7 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) I915_READ(PIPE_CRC_RES_2_IVB(pipe)), I915_READ(PIPE_CRC_RES_3_IVB(pipe)), I915_READ(PIPE_CRC_RES_4_IVB(pipe)), - I915_READ(PIPE_CRC_RES_5_IVB(pipe)), - I915_READ(PIPEFRAME(pipe))); + I915_READ(PIPE_CRC_RES_5_IVB(pipe))); } static void ilk_pipe_crc_update(struct drm_device *dev, enum pipe pipe) @@ -1250,8 +1249,7 @@ static void ilk_pipe_crc_update(struct drm_device *dev, enum pipe pipe) I915_READ(PIPE_CRC_RES_GREEN_ILK(pipe)), I915_READ(PIPE_CRC_RES_BLUE_ILK(pipe)), I915_READ(PIPE_CRC_RES_RES1_ILK(pipe)), - I915_READ(PIPE_CRC_RES_RES2_ILK(pipe)), - I915_READ(PIPEFRAME(pipe))); + I915_READ(PIPE_CRC_RES_RES2_ILK(pipe))); } #else static inline void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:20 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:20 -0000 Subject: [LTSI-dev] [PATCH 38/50] drm/i915: wait one vblank when disabling CRCs In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-39-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter This avoids a spurious spurious interrupt warning. Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit bcf17ab2e9a9b15abdfce83461d4f98e0d11aa1a) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index baa5272..e85507b 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2040,6 +2040,8 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, DRM_DEBUG_DRIVER("stopping CRCs for pipe %c\n", pipe_name(pipe)); + intel_wait_for_vblank(dev, pipe); + kfree(pipe_crc->entries); pipe_crc->entries = NULL; } -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:22 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:22 -0000 Subject: [LTSI-dev] [PATCH 39/50] drm/i915: fix CRC debugfs setup In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-40-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter We've set up all files, but removed only those for which we have a pipe. Which leaves the one for pipe C on machines with less than 2 pipes, breaking module reload. v2: We can't get at the drm device this early (wtf), so just register all the files and also remove them all again. Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit e309a9977087fa0f2cb16d0a0790f7c05ccb5171) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e85507b..649c00e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -2772,7 +2772,6 @@ int i915_debugfs_init(struct drm_minor *minor) void i915_debugfs_cleanup(struct drm_minor *minor) { - struct drm_device *dev = minor->dev; int i; drm_debugfs_remove_files(i915_debugfs_list, @@ -2781,7 +2780,7 @@ void i915_debugfs_cleanup(struct drm_minor *minor) drm_debugfs_remove_files((struct drm_info_list *) &i915_forcewake_fops, 1, minor); - for (i = 0; i < INTEL_INFO(dev)->num_pipes; i++) { + for (i = 0; i < ARRAY_SIZE(i915_pipe_crc_data); i++) { struct drm_info_list *info_list = (struct drm_info_list *)&i915_pipe_crc_data[i]; -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:23 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:23 -0000 Subject: [LTSI-dev] [PATCH 40/50] drm/i915: crc support for hsw In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-41-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter hw designers decided to change the CRC registers and coalesce them all into one. Otherwise nothing changed. I've opted for a new hsw_ version to grab the crc sample since hsw+1 will have the same crc registers, but different interrupt source registers. So this little helper function will come handy there. Also refactor the display error handler with a neat pipe loop. v2: Use for_each_pipe. Reviewed-by: Damien Lespiau Signed-off-by: Daniel Vetter (cherry picked from commit 5a69b89f853fb35adf51b8b45c026bad0934bf97) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_debugfs.c | 2 +- drivers/gpu/drm/i915/i915_irq.c | 44 ++++++++++++++++++++--------------- drivers/gpu/drm/i915/i915_reg.h | 1 + 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index 649c00e..061182a 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c @@ -1997,7 +1997,7 @@ static int pipe_crc_set_source(struct drm_device *dev, enum pipe pipe, u32 val; int ret; - if (!(IS_IVYBRIDGE(dev) || IS_GEN5(dev) || IS_GEN6(dev))) + if (!(INTEL_INFO(dev)->gen >= 5 && !IS_VALLEYVIEW(dev))) return -ENODEV; if (pipe_crc->source == source) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index eaf1268..156a1a4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1228,6 +1228,15 @@ static void display_pipe_crc_update(struct drm_device *dev, enum pipe pipe, wake_up_interruptible(&pipe_crc->wq); } +static void hsw_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + display_pipe_crc_update(dev, pipe, + I915_READ(PIPE_CRC_RES_1_IVB(pipe)), + 0, 0, 0, 0); +} + static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; @@ -1252,6 +1261,7 @@ static void ilk_pipe_crc_update(struct drm_device *dev, enum pipe pipe) I915_READ(PIPE_CRC_RES_RES2_ILK(pipe))); } #else +static inline void hsw_pipe_crc_update(struct drm_device *dev, int pipe) {} static inline void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} static inline void ilk_pipe_crc_update(struct drm_device *dev, int pipe) {} #endif @@ -1418,30 +1428,26 @@ static void ivb_err_int_handler(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; u32 err_int = I915_READ(GEN7_ERR_INT); + enum pipe pipe; if (err_int & ERR_INT_POISON) DRM_ERROR("Poison interrupt\n"); - if (err_int & ERR_INT_FIFO_UNDERRUN_A) - if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_A, false)) - DRM_DEBUG_DRIVER("Pipe A FIFO underrun\n"); - - if (err_int & ERR_INT_FIFO_UNDERRUN_B) - if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_B, false)) - DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); - - if (err_int & ERR_INT_FIFO_UNDERRUN_C) - if (intel_set_cpu_fifo_underrun_reporting(dev, PIPE_C, false)) - DRM_DEBUG_DRIVER("Pipe C FIFO underrun\n"); - - if (err_int & ERR_INT_PIPE_CRC_DONE_A) - ivb_pipe_crc_update(dev, PIPE_A); - - if (err_int & ERR_INT_PIPE_CRC_DONE_B) - ivb_pipe_crc_update(dev, PIPE_B); + for_each_pipe(pipe) { + if (err_int & ERR_INT_FIFO_UNDERRUN(pipe)) { + if (intel_set_cpu_fifo_underrun_reporting(dev, pipe, + false)) + DRM_DEBUG_DRIVER("Pipe %c FIFO underrun\n", + pipe_name(pipe)); + } - if (err_int & ERR_INT_PIPE_CRC_DONE_C) - ivb_pipe_crc_update(dev, PIPE_C); + if (err_int & ERR_INT_PIPE_CRC_DONE(pipe)) { + if (IS_IVYBRIDGE(dev)) + ivb_pipe_crc_update(dev, pipe); + else + hsw_pipe_crc_update(dev, pipe); + } + } I915_WRITE(GEN7_ERR_INT, err_int); } diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 3388105..89aeae7c 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -728,6 +728,7 @@ #define ERR_INT_PIPE_CRC_DONE_B (1<<5) #define ERR_INT_FIFO_UNDERRUN_B (1<<3) #define ERR_INT_PIPE_CRC_DONE_A (1<<2) +#define ERR_INT_PIPE_CRC_DONE(pipe) (1<<(2 + pipe*3)) #define ERR_INT_FIFO_UNDERRUN_A (1<<0) #define ERR_INT_FIFO_UNDERRUN(pipe) (1<<(pipe*3)) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:24 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:24 -0000 Subject: [LTSI-dev] [PATCH 41/50] drm/i915: remove dead code in ironlake_crtc_mode_set In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-42-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter In Author: Daniel Vetter Date: Wed Jun 5 13:34:23 2013 +0200 drm/i915: consolidate pch pll enable sequence I've removed all the code from this if block, but somehow forgotten to kill the block itself. Reviewed-by: Ville Syrj?l? Signed-off-by: Daniel Vetter (cherry picked from commit 3c9d87e3acb6d2e5a3c3f42ab42f206cbac13807) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_display.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 1b48257..a35bb19 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -6068,11 +6068,6 @@ static int ironlake_crtc_mode_set(struct drm_crtc *crtc, else intel_crtc->lowfreq_avail = false; - if (intel_crtc->config.has_pch_encoder) { - pll = intel_crtc_to_shared_dpll(intel_crtc); - - } - intel_set_pipe_timings(intel_crtc); if (intel_crtc->config.has_pch_encoder) { -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:26 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:26 -0000 Subject: [LTSI-dev] [PATCH 42/50] drm/i915: Make PTE valid encoding optional In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-43-git-send-email-dheerajx.s.jamwal@intel.com> From: Ben Widawsky We need this to work around a corruption when the boot kernel image loads the hibernated kernel image from swap on Haswell systems - somehow not everything is properly shut off. This is just the prep work, the next patch will implement the actual workaround. Signed-off-by: Ben Widawsky [danvet: Add a commit message suitable for -fixes and add cc: stable] Cc: stable at vger.kernel.org Signed-off-by: Daniel Vetter (cherry picked from commit b35b380ed46bb01726bec1795e6443e625306757) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_drv.h | 3 ++- drivers/gpu/drm/i915/i915_gem_gtt.c | 35 ++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8a2a474..86bdcee 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -516,7 +516,8 @@ struct i915_address_space { /* FIXME: Need a more generic return type */ gen6_gtt_pte_t (*pte_encode)(dma_addr_t addr, - enum i915_cache_level level); + enum i915_cache_level level, + bool valid); /* Create a valid PTE */ void (*clear_range)(struct i915_address_space *vm, unsigned int first_entry, unsigned int num_entries); diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index e999496..81dce29 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -58,9 +58,10 @@ #define HSW_WT_ELLC_LLC_AGE0 HSW_CACHEABILITY_CONTROL(0x6) static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= GEN6_PTE_ADDR_ENCODE(addr); switch (level) { @@ -79,9 +80,10 @@ static gen6_gtt_pte_t snb_pte_encode(dma_addr_t addr, } static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= GEN6_PTE_ADDR_ENCODE(addr); switch (level) { @@ -105,9 +107,10 @@ static gen6_gtt_pte_t ivb_pte_encode(dma_addr_t addr, #define BYT_PTE_SNOOPED_BY_CPU_CACHES (1 << 2) static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= GEN6_PTE_ADDR_ENCODE(addr); /* Mark the page as writeable. Other platforms don't have a @@ -122,9 +125,10 @@ static gen6_gtt_pte_t byt_pte_encode(dma_addr_t addr, } static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= HSW_PTE_ADDR_ENCODE(addr); if (level != I915_CACHE_NONE) @@ -134,9 +138,10 @@ static gen6_gtt_pte_t hsw_pte_encode(dma_addr_t addr, } static gen6_gtt_pte_t iris_pte_encode(dma_addr_t addr, - enum i915_cache_level level) + enum i915_cache_level level, + bool valid) { - gen6_gtt_pte_t pte = GEN6_PTE_VALID; + gen6_gtt_pte_t pte = valid ? GEN6_PTE_VALID : 0; pte |= HSW_PTE_ADDR_ENCODE(addr); switch (level) { @@ -245,7 +250,7 @@ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, unsigned first_pte = first_entry % I915_PPGTT_PT_ENTRIES; unsigned last_pte, i; - scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); + scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true); while (num_entries) { last_pte = first_pte + num_entries; @@ -282,7 +287,7 @@ static void gen6_ppgtt_insert_entries(struct i915_address_space *vm, dma_addr_t page_addr; page_addr = sg_page_iter_dma_address(&sg_iter); - pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level); + pt_vaddr[act_pte] = vm->pte_encode(page_addr, cache_level, true); if (++act_pte == I915_PPGTT_PT_ENTRIES) { kunmap_atomic(pt_vaddr); act_pt++; @@ -536,7 +541,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, for_each_sg_page(st->sgl, &sg_iter, st->nents, 0) { addr = sg_page_iter_dma_address(&sg_iter); - iowrite32(vm->pte_encode(addr, level), >t_entries[i]); + iowrite32(vm->pte_encode(addr, level, true), >t_entries[i]); i++; } @@ -548,7 +553,7 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, */ if (i != 0) WARN_ON(readl(>t_entries[i-1]) != - vm->pte_encode(addr, level)); + vm->pte_encode(addr, level, true)); /* This next bit makes the above posting read even more important. We * want to flush the TLBs only after we're certain all the PTE updates @@ -573,7 +578,7 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, first_entry, num_entries, max_entries)) num_entries = max_entries; - scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC); + scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true); for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); readl(gtt_base); -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:28 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:28 -0000 Subject: [LTSI-dev] [PATCH 43/50] drm/i915: Disable GGTT PTEs on GEN6+ suspend In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-44-git-send-email-dheerajx.s.jamwal@intel.com> From: Ben Widawsky Once the machine gets to a certain point in the suspend process, we expect the GPU to be idle. If it is not, we might corrupt memory. Empirically (with an early version of this patch) we have seen this is not the case. We cannot currently explain why the latent GPU writes occur. In the technical sense, this patch is a workaround in that we have an issue we can't explain, and the patch indirectly solves the issue. However, it's really better than a workaround because we understand why it works, and it really should be a safe thing to do in all cases. The noticeable effect other than the debug messages would be an increase in the suspend time. I have not measure how expensive it actually is. I think it would be good to spend further time to root cause why we're seeing these latent writes, but it shouldn't preclude preventing the fallout. NOTE: It should be safe (and makes some sense IMO) to also keep the VALID bit unset on resume when we clear_range(). I've opted not to do this as properly clearing those bits at some later point would be extra work. v2: Fix bugzilla link Bugzilla: http://bugs.freedesktop.org/show_bug.cgi?id=65496 Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=59321 Tested-by: Takashi Iwai Tested-by: Paulo Zanoni Signed-off-by: Ben Widawsky Tested-By: Todd Previte Cc: stable at vger.kernel.org Signed-off-by: Daniel Vetter (cherry picked from commit 828c79087cec61eaf4c76bb32c222fbe35ac3930) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_drv.c | 5 +++ drivers/gpu/drm/i915/i915_drv.h | 5 ++- drivers/gpu/drm/i915/i915_gem_gtt.c | 76 ++++++++++++++++++++++++++++++----- drivers/gpu/drm/i915/i915_reg.h | 4 ++ 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c0b2a0f..7e70c8c 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -508,6 +508,8 @@ static int i915_drm_freeze(struct drm_device *dev) intel_modeset_suspend_hw(dev); } + i915_gem_suspend_gtt_mappings(dev); + i915_save_state(dev); intel_opregion_fini(dev); @@ -656,6 +658,9 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) static int i915_drm_thaw(struct drm_device *dev) { + if (drm_core_check_feature(dev, DRIVER_MODESET)) + i915_check_and_clear_faults(dev); + return __i915_drm_thaw(dev, true); } diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 86bdcee..3a15cde 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -520,7 +520,8 @@ struct i915_address_space { bool valid); /* Create a valid PTE */ void (*clear_range)(struct i915_address_space *vm, unsigned int first_entry, - unsigned int num_entries); + unsigned int num_entries, + bool use_scratch); void (*insert_entries)(struct i915_address_space *vm, struct sg_table *st, unsigned int first_entry, @@ -2177,6 +2178,8 @@ void i915_ppgtt_bind_object(struct i915_hw_ppgtt *ppgtt, void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, struct drm_i915_gem_object *obj); +void i915_check_and_clear_faults(struct drm_device *dev); +void i915_gem_suspend_gtt_mappings(struct drm_device *dev); void i915_gem_restore_gtt_mappings(struct drm_device *dev); int __must_check i915_gem_gtt_prepare_object(struct drm_i915_gem_object *obj); void i915_gem_gtt_bind_object(struct drm_i915_gem_object *obj, diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 81dce29..c4c42e7 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -241,7 +241,8 @@ static int gen6_ppgtt_enable(struct drm_device *dev) /* PPGTT support for Sandybdrige/Gen6 and later */ static void gen6_ppgtt_clear_range(struct i915_address_space *vm, unsigned first_entry, - unsigned num_entries) + unsigned num_entries, + bool use_scratch) { struct i915_hw_ppgtt *ppgtt = container_of(vm, struct i915_hw_ppgtt, base); @@ -372,7 +373,7 @@ static int gen6_ppgtt_init(struct i915_hw_ppgtt *ppgtt) } ppgtt->base.clear_range(&ppgtt->base, 0, - ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES); + ppgtt->num_pd_entries * I915_PPGTT_PT_ENTRIES, true); ppgtt->pd_offset = first_pd_entry_in_global_pt * sizeof(gen6_gtt_pte_t); @@ -449,7 +450,8 @@ void i915_ppgtt_unbind_object(struct i915_hw_ppgtt *ppgtt, { ppgtt->base.clear_range(&ppgtt->base, i915_gem_obj_ggtt_offset(obj) >> PAGE_SHIFT, - obj->base.size >> PAGE_SHIFT); + obj->base.size >> PAGE_SHIFT, + true); } extern int intel_iommu_gfx_mapped; @@ -490,15 +492,65 @@ static void undo_idling(struct drm_i915_private *dev_priv, bool interruptible) dev_priv->mm.interruptible = interruptible; } +void i915_check_and_clear_faults(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + struct intel_ring_buffer *ring; + int i; + + if (INTEL_INFO(dev)->gen < 6) + return; + + for_each_ring(ring, dev_priv, i) { + u32 fault_reg; + fault_reg = I915_READ(RING_FAULT_REG(ring)); + if (fault_reg & RING_FAULT_VALID) { + DRM_DEBUG_DRIVER("Unexpected fault\n" + "\tAddr: 0x%08lx\\n" + "\tAddress space: %s\n" + "\tSource ID: %d\n" + "\tType: %d\n", + fault_reg & PAGE_MASK, + fault_reg & RING_FAULT_GTTSEL_MASK ? "GGTT" : "PPGTT", + RING_FAULT_SRCID(fault_reg), + RING_FAULT_FAULT_TYPE(fault_reg)); + I915_WRITE(RING_FAULT_REG(ring), + fault_reg & ~RING_FAULT_VALID); + } + } + POSTING_READ(RING_FAULT_REG(&dev_priv->ring[RCS])); +} + +void i915_gem_suspend_gtt_mappings(struct drm_device *dev) +{ + struct drm_i915_private *dev_priv = dev->dev_private; + + /* Don't bother messing with faults pre GEN6 as we have little + * documentation supporting that it's a good idea. + */ + if (INTEL_INFO(dev)->gen < 6) + return; + + i915_check_and_clear_faults(dev); + + dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, + dev_priv->gtt.base.start / PAGE_SIZE, + dev_priv->gtt.base.total / PAGE_SIZE, + false); +} + void i915_gem_restore_gtt_mappings(struct drm_device *dev) { struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj; + i915_check_and_clear_faults(dev); + /* First fill our portion of the GTT with scratch pages */ dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, dev_priv->gtt.base.start / PAGE_SIZE, - dev_priv->gtt.base.total / PAGE_SIZE); + dev_priv->gtt.base.total / PAGE_SIZE, + true); list_for_each_entry(obj, &dev_priv->mm.bound_list, global_list) { i915_gem_clflush_object(obj, obj->pin_display); @@ -565,7 +617,8 @@ static void gen6_ggtt_insert_entries(struct i915_address_space *vm, static void gen6_ggtt_clear_range(struct i915_address_space *vm, unsigned int first_entry, - unsigned int num_entries) + unsigned int num_entries, + bool use_scratch) { struct drm_i915_private *dev_priv = vm->dev->dev_private; gen6_gtt_pte_t scratch_pte, __iomem *gtt_base = @@ -578,7 +631,8 @@ static void gen6_ggtt_clear_range(struct i915_address_space *vm, first_entry, num_entries, max_entries)) num_entries = max_entries; - scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, true); + scratch_pte = vm->pte_encode(vm->scratch.addr, I915_CACHE_LLC, use_scratch); + for (i = 0; i < num_entries; i++) iowrite32(scratch_pte, >t_base[i]); readl(gtt_base); @@ -599,7 +653,8 @@ static void i915_ggtt_insert_entries(struct i915_address_space *vm, static void i915_ggtt_clear_range(struct i915_address_space *vm, unsigned int first_entry, - unsigned int num_entries) + unsigned int num_entries, + bool unused) { intel_gtt_clear_range(first_entry, num_entries); } @@ -627,7 +682,8 @@ void i915_gem_gtt_unbind_object(struct drm_i915_gem_object *obj) dev_priv->gtt.base.clear_range(&dev_priv->gtt.base, entry, - obj->base.size >> PAGE_SHIFT); + obj->base.size >> PAGE_SHIFT, + true); obj->has_global_gtt_mapping = 0; } @@ -714,11 +770,11 @@ void i915_gem_setup_global_gtt(struct drm_device *dev, const unsigned long count = (hole_end - hole_start) / PAGE_SIZE; DRM_DEBUG_KMS("clearing unused GTT space: [%lx, %lx]\n", hole_start, hole_end); - ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count); + ggtt_vm->clear_range(ggtt_vm, hole_start / PAGE_SIZE, count, true); } /* And finally clear the reserved guard page */ - ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1); + ggtt_vm->clear_range(ggtt_vm, end / PAGE_SIZE - 1, 1, true); } static bool diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 89aeae7c..5d4b97b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -657,6 +657,10 @@ #define ARB_MODE_SWIZZLE_IVB (1<<5) #define RENDER_HWS_PGA_GEN7 (0x04080) #define RING_FAULT_REG(ring) (0x4094 + 0x100*(ring)->id) +#define RING_FAULT_GTTSEL_MASK (1<<11) +#define RING_FAULT_SRCID(x) ((x >> 3) & 0xff) +#define RING_FAULT_FAULT_TYPE(x) ((x >> 1) & 0x3) +#define RING_FAULT_VALID (1<<0) #define DONE_REG 0x40b0 #define BSD_HWS_PGA_GEN7 (0x04180) #define BLT_HWS_PGA_GEN7 (0x04280) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:28 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:28 -0000 Subject: [LTSI-dev] [PATCH 44/50] drm/i915/dp: don't mention eDP bpp clamping if it doesn't affect bpp In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-45-git-send-email-dheerajx.s.jamwal@intel.com> From: Jani Nikula This is useful with the follow-up patch that frobs dev_priv->vbt.edp_bpp, and the value no longer comes directly from VBT. Signed-off-by: Jani Nikula Signed-off-by: Daniel Vetter (cherry picked from commit 6da7f10d296f4ac625f96b39eef22c41398727e3) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_dp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 68a50fe..fad4320 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c @@ -822,10 +822,11 @@ intel_dp_compute_config(struct intel_encoder *encoder, /* Walk through all bpp values. Luckily they're all nicely spaced with 2 * bpc in between. */ bpp = pipe_config->pipe_bpp; - if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp) { + if (is_edp(intel_dp) && dev_priv->vbt.edp_bpp && + dev_priv->vbt.edp_bpp < bpp) { DRM_DEBUG_KMS("clamping bpp for eDP panel to BIOS-provided %i\n", dev_priv->vbt.edp_bpp); - bpp = min_t(int, bpp, dev_priv->vbt.edp_bpp); + bpp = dev_priv->vbt.edp_bpp; } for (; bpp >= 6*3; bpp -= 2*3) { -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:30 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:30 -0000 Subject: [LTSI-dev] [PATCH 45/50] drm/i915: Print RC6 info less often In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-46-git-send-email-dheerajx.s.jamwal@intel.com> From: Ben Widawsky Since we use intel_enable_rc6() now for more than just when we're enabling RC6, we'll see this message many times, and it is just confusing. As an example, calc_residency calls this function whenever poked via sysfs. This leaves the impression in dmesg that we're constantly re-enabling RC6. While at it, move the defines and description from drv.h to intel_pm.c, since these are only ever used in that code. Signed-off-by: Ben Widawsky Reviewed-by: Chris Wilson Signed-off-by: Daniel Vetter (cherry picked from commit dc39fff7229c01550cad1ee8fa0309dfafdcd2e7) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_drv.h | 21 --------------- drivers/gpu/drm/i915/intel_pm.c | 54 +++++++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 3a15cde..51d0998 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1786,27 +1786,6 @@ struct drm_i915_file_private { #include "i915_trace.h" -/** - * RC6 is a special power stage which allows the GPU to enter an very - * low-voltage mode when idle, using down to 0V while at this stage. This - * stage is entered automatically when the GPU is idle when RC6 support is - * enabled, and as soon as new workload arises GPU wakes up automatically as well. - * - * There are different RC6 modes available in Intel GPU, which differentiate - * among each other with the latency required to enter and leave RC6 and - * voltage consumed by the GPU in different states. - * - * The combination of the following flags define which states GPU is allowed - * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and - * RC6pp is deepest RC6. Their support by hardware varies according to the - * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one - * which brings the most power savings; deeper states save more power, but - * require higher latency to switch to and wake up. - */ -#define INTEL_RC6_ENABLE (1<<0) -#define INTEL_RC6p_ENABLE (1<<1) -#define INTEL_RC6pp_ENABLE (1<<2) - extern const struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; extern unsigned int i915_fbpercrtc __always_unused; diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8064ff9..bff5fa3 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -32,6 +32,27 @@ #include #include +/** + * RC6 is a special power stage which allows the GPU to enter an very + * low-voltage mode when idle, using down to 0V while at this stage. This + * stage is entered automatically when the GPU is idle when RC6 support is + * enabled, and as soon as new workload arises GPU wakes up automatically as well. + * + * There are different RC6 modes available in Intel GPU, which differentiate + * among each other with the latency required to enter and leave RC6 and + * voltage consumed by the GPU in different states. + * + * The combination of the following flags define which states GPU is allowed + * to enter, while RC6 is the normal RC6 state, RC6p is the deep RC6, and + * RC6pp is deepest RC6. Their support by hardware varies according to the + * GPU, BIOS, chipset and platform. RC6 is usually the safest one and the one + * which brings the most power savings; deeper states save more power, but + * require higher latency to switch to and wake up. + */ +#define INTEL_RC6_ENABLE (1<<0) +#define INTEL_RC6p_ENABLE (1<<1) +#define INTEL_RC6pp_ENABLE (1<<2) + /* FBC, or Frame Buffer Compression, is a technique employed to compress the * framebuffer contents in-memory, aiming at reducing the required bandwidth * during in-memory transfers and, therefore, reduce the power packet. @@ -3685,6 +3706,20 @@ static void valleyview_disable_rps(struct drm_device *dev) } } +static void intel_print_rc6_info(struct drm_device *dev, u32 mode) +{ + if (IS_GEN6(dev)) + DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); + + if (IS_HASWELL(dev)) + DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); + + DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", + (mode & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", + (mode & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", + (mode & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); +} + int intel_enable_rc6(const struct drm_device *dev) { /* No RC6 before Ironlake */ @@ -3699,18 +3734,13 @@ int intel_enable_rc6(const struct drm_device *dev) if (INTEL_INFO(dev)->gen == 5) return 0; - if (IS_HASWELL(dev)) { - DRM_DEBUG_DRIVER("Haswell: only RC6 available\n"); + if (IS_HASWELL(dev)) return INTEL_RC6_ENABLE; - } /* snb/ivb have more than one rc6 state. */ - if (INTEL_INFO(dev)->gen == 6) { - DRM_DEBUG_DRIVER("Sandybridge: deep RC6 disabled\n"); + if (INTEL_INFO(dev)->gen == 6) return INTEL_RC6_ENABLE; - } - DRM_DEBUG_DRIVER("RC6 and deep RC6 enabled\n"); return (INTEL_RC6_ENABLE | INTEL_RC6p_ENABLE); } @@ -3812,10 +3842,7 @@ static void gen6_enable_rps(struct drm_device *dev) rc6_mask |= GEN6_RC_CTL_RC6pp_ENABLE; } - DRM_INFO("Enabling RC6 states: RC6 %s, RC6p %s, RC6pp %s\n", - (rc6_mask & GEN6_RC_CTL_RC6_ENABLE) ? "on" : "off", - (rc6_mask & GEN6_RC_CTL_RC6p_ENABLE) ? "on" : "off", - (rc6_mask & GEN6_RC_CTL_RC6pp_ENABLE) ? "on" : "off"); + intel_print_rc6_info(dev, rc6_mask); I915_WRITE(GEN6_RC_CONTROL, rc6_mask | @@ -4051,6 +4078,9 @@ static void valleyview_enable_rps(struct drm_device *dev) VLV_RENDER_RC6_COUNT_EN)); if (intel_enable_rc6(dev) & INTEL_RC6_ENABLE) rc6_mode = GEN7_RC_CTL_TO_MODE; + + intel_print_rc6_info(dev, rc6_mode); + I915_WRITE(GEN6_RC_CONTROL, rc6_mode); val = vlv_punit_read(dev_priv, PUNIT_REG_GPU_FREQ_STS); @@ -4222,6 +4252,8 @@ static void ironlake_enable_rc6(struct drm_device *dev) I915_WRITE(PWRCTXA, i915_gem_obj_ggtt_offset(dev_priv->ips.pwrctx) | PWRCTX_EN); I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); + + intel_print_rc6_info(dev, INTEL_RC6_ENABLE); } static unsigned long intel_pxfreq(u32 vidfreq) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:31 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:31 -0000 Subject: [LTSI-dev] [PATCH 46/50] drm/i915: fix open-coded DIV_ROUND_UP In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-47-git-send-email-dheerajx.s.jamwal@intel.com> From: Paulo Zanoni Use the nice Kernel macro, it makes the code much more readable. Signed-off-by: Paulo Zanoni Reviewed-by: Jani Nikula Signed-off-by: Daniel Vetter (cherry picked from commit de45eaf7b9530b6137d3ce370b12b199fae01419) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_gem.c | 2 +- drivers/gpu/drm/i915/intel_fbdev.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 32784ff..87235b7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -259,7 +259,7 @@ i915_gem_dumb_create(struct drm_file *file, struct drm_mode_create_dumb *args) { /* have to work out size/pitch and return them */ - args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); + args->pitch = ALIGN(args->width * DIV_ROUND_UP(args->bpp, 8), 64); args->size = args->pitch * args->height; return i915_gem_create(file, dev, args->size, &args->handle); diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c index acc8395..895fcb4 100644 --- a/drivers/gpu/drm/i915/intel_fbdev.c +++ b/drivers/gpu/drm/i915/intel_fbdev.c @@ -78,8 +78,8 @@ static int intelfb_create(struct drm_fb_helper *helper, mode_cmd.width = sizes->surface_width; mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((sizes->surface_bpp + 7) / - 8), 64); + mode_cmd.pitches[0] = ALIGN(mode_cmd.width * + DIV_ROUND_UP(sizes->surface_bpp, 8), 64); mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:32 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:32 -0000 Subject: [LTSI-dev] [PATCH 47/50] drm/i915: Whitespace alignment fix for block header in display error state In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-48-git-send-email-dheerajx.s.jamwal@intel.com> From: Chris Wilson The current output looks like: Num Pipes: 2 Pipe [0]: SRC: 027f01df Plane [0]: CNTR: d9000000 STRIDE: 00001400 SIZE: 031f04ff POS: 00000000 ADDR: 00020000 Cursor [0]: CNTR: 00000000 POS: 00000000 BASE: 00000000 Pipe [1]: SRC: 04ff031f Plane [1]: CNTR: 01000000 STRIDE: 00000000 SIZE: 018f02cf POS: 00000000 ADDR: 00000000 Cursor [1]: CNTR: 00000000 POS: 00000000 BASE: 00000000 CPU transcoder: A CONF: 00000000 HTOTAL: 031f027f HBLANK: 03170287 HSYNC: 02ef028f VTOTAL: 020c01df VBLANK: 020401e7 VSYNC: 01eb01e9 CPU transcoder: B CONF: 80000000 HTOTAL: 059f04ff HBLANK: 059f04ff HSYNC: 054f052f VTOTAL: 0336031f VBLANK: 0336031f VSYNC: 03280322 which lacks the important visual clue to demarque the transcoder blocks from the last cursor. Signed-off-by: Chris Wilson Cc: Daniel Vetter Signed-off-by: Daniel Vetter (cherry picked from commit 1cf84bb6ae2d49ce06ffa93c6293edfff70bed55) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/intel_display.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a35bb19..a89c295 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -11178,7 +11178,7 @@ intel_display_print_error_state(struct drm_i915_error_state_buf *m, } for (i = 0; i < error->num_transcoders; i++) { - err_printf(m, " CPU transcoder: %c\n", + err_printf(m, "CPU transcoder: %c\n", transcoder_name(error->transcoder[i].cpu_transcoder)); err_printf(m, " CONF: %08x\n", error->transcoder[i].conf); err_printf(m, " HTOTAL: %08x\n", error->transcoder[i].htotal); -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:33 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:33 -0000 Subject: [LTSI-dev] [PATCH 48/50] drm/i915: Adjust CRC capture for pre-gen5/vlv In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-49-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter Should work down to gen2. The #defines for the interrupt sources are already there in PIPESTAT and are the same on all gmch platforms for gen2 up to vlv. Reviewed-by: Ville Syrj?l? Signed-off-by: Daniel Vetter (cherry picked from commit 0b5c5ed072b8e0de8dc4e085dbd855e440c58bf4) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_irq.c | 28 +++++++++++++++++++--------- drivers/gpu/drm/i915/i915_reg.h | 30 +++++++++++++++--------------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 156a1a4..98f5ac3 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1249,21 +1249,31 @@ static void ivb_pipe_crc_update(struct drm_device *dev, enum pipe pipe) I915_READ(PIPE_CRC_RES_5_IVB(pipe))); } -static void ilk_pipe_crc_update(struct drm_device *dev, enum pipe pipe) +static void i9xx_pipe_crc_update(struct drm_device *dev, enum pipe pipe) { struct drm_i915_private *dev_priv = dev->dev_private; + uint32_t res1, res2; + + if (INTEL_INFO(dev)->gen >= 3) + res1 = I915_READ(PIPE_CRC_RES_RES1_I915(pipe)); + else + res1 = 0; + + if (INTEL_INFO(dev)->gen >= 5 || IS_G4X(dev)) + res2 = I915_READ(PIPE_CRC_RES_RES2_G4X(pipe)); + else + res2 = 0; display_pipe_crc_update(dev, pipe, - I915_READ(PIPE_CRC_RES_RED_ILK(pipe)), - I915_READ(PIPE_CRC_RES_GREEN_ILK(pipe)), - I915_READ(PIPE_CRC_RES_BLUE_ILK(pipe)), - I915_READ(PIPE_CRC_RES_RES1_ILK(pipe)), - I915_READ(PIPE_CRC_RES_RES2_ILK(pipe))); + I915_READ(PIPE_CRC_RES_RED(pipe)), + I915_READ(PIPE_CRC_RES_GREEN(pipe)), + I915_READ(PIPE_CRC_RES_BLUE(pipe)), + res1, res2); } #else static inline void hsw_pipe_crc_update(struct drm_device *dev, int pipe) {} static inline void ivb_pipe_crc_update(struct drm_device *dev, int pipe) {} -static inline void ilk_pipe_crc_update(struct drm_device *dev, int pipe) {} +static inline void i9xx_pipe_crc_update(struct drm_device *dev, int pipe) {} #endif /* The RPS events need forcewake, so we add them to a work queue and mask their @@ -1543,10 +1553,10 @@ static void ilk_display_irq_handler(struct drm_device *dev, u32 de_iir) DRM_DEBUG_DRIVER("Pipe B FIFO underrun\n"); if (de_iir & DE_PIPEA_CRC_DONE) - ilk_pipe_crc_update(dev, PIPE_A); + i9xx_pipe_crc_update(dev, PIPE_A); if (de_iir & DE_PIPEB_CRC_DONE) - ilk_pipe_crc_update(dev, PIPE_B); + i9xx_pipe_crc_update(dev, PIPE_B); if (de_iir & DE_PLANEA_FLIP_DONE) { intel_prepare_page_flip(dev, 0); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 5d4b97b..1c104fe 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1862,11 +1862,11 @@ #define _PIPE_CRC_RES_4_A_IVB 0x60070 #define _PIPE_CRC_RES_5_A_IVB 0x60074 -#define _PIPE_CRC_RES_RED_A_ILK 0x60060 -#define _PIPE_CRC_RES_GREEN_A_ILK 0x60064 -#define _PIPE_CRC_RES_BLUE_A_ILK 0x60068 -#define _PIPE_CRC_RES_RES1_A_ILK 0x6006c -#define _PIPE_CRC_RES_RES2_A_ILK 0x60080 +#define _PIPE_CRC_RES_RED_A (dev_priv->info->display_mmio_offset + 0x60060) +#define _PIPE_CRC_RES_GREEN_A (dev_priv->info->display_mmio_offset + 0x60064) +#define _PIPE_CRC_RES_BLUE_A (dev_priv->info->display_mmio_offset + 0x60068) +#define _PIPE_CRC_RES_RES1_A_I915 (dev_priv->info->display_mmio_offset + 0x6006c) +#define _PIPE_CRC_RES_RES2_A_G4X (dev_priv->info->display_mmio_offset + 0x60080) /* Pipe B CRC regs */ #define _PIPE_CRC_CTL_B 0x61050 @@ -1888,16 +1888,16 @@ #define PIPE_CRC_RES_5_IVB(pipe) \ _PIPE(pipe, _PIPE_CRC_RES_5_A_IVB, _PIPE_CRC_RES_5_B_IVB) -#define PIPE_CRC_RES_RED_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_RED_A_ILK, 0x01000) -#define PIPE_CRC_RES_GREEN_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_GREEN_A_ILK, 0x01000) -#define PIPE_CRC_RES_BLUE_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_BLUE_A_ILK, 0x01000) -#define PIPE_CRC_RES_RES1_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_RES1_A_ILK, 0x01000) -#define PIPE_CRC_RES_RES2_ILK(pipe) \ - _PIPE_INC(pipe, _PIPE_CRC_RES_RES2_A_ILK, 0x01000) +#define PIPE_CRC_RES_RED(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_RED_A, 0x01000) +#define PIPE_CRC_RES_GREEN(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_GREEN_A, 0x01000) +#define PIPE_CRC_RES_BLUE(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_BLUE_A, 0x01000) +#define PIPE_CRC_RES_RES1_I915(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_RES1_A_I915, 0x01000) +#define PIPE_CRC_RES_RES2_G4X(pipe) \ + _PIPE_INC(pipe, _PIPE_CRC_RES_RES2_A_G4X, 0x01000) /* Pipe A timing regs */ #define _HTOTAL_A (dev_priv->info->display_mmio_offset + 0x60000) -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:34 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:34 -0000 Subject: [LTSI-dev] [PATCH 49/50] drm/i915: CRC source selection #defines for gmch/vlv chips In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-50-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter A bit a mess, since with DP/TV outputs we can't use the pipe CRC. Also, no plane CRCs, so we need to update the basic testcases. Reviewed-by: Ville Syrj?l? Signed-off-by: Daniel Vetter (cherry picked from commit b4437a4139f455d1d6557d81789dcbbe849b0496) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_reg.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 1c104fe..05cd840 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -1847,15 +1847,37 @@ /* Pipe A CRC regs */ #define _PIPE_CRC_CTL_A (dev_priv->info->display_mmio_offset + 0x60050) #define PIPE_CRC_ENABLE (1 << 31) +/* ivb+ source selection */ #define PIPE_CRC_SOURCE_PRIMARY_IVB (0 << 29) #define PIPE_CRC_SOURCE_SPRITE_IVB (1 << 29) #define PIPE_CRC_SOURCE_PF_IVB (2 << 29) +/* ilk+ source selection */ #define PIPE_CRC_SOURCE_PRIMARY_ILK (0 << 28) #define PIPE_CRC_SOURCE_SPRITE_ILK (1 << 28) #define PIPE_CRC_SOURCE_PIPE_ILK (2 << 28) /* embedded DP port on the north display block, reserved on ivb */ #define PIPE_CRC_SOURCE_PORT_A_ILK (4 << 28) #define PIPE_CRC_SOURCE_FDI_ILK (5 << 28) /* reserved on ivb */ +/* vlv source selection */ +#define PIPE_CRC_SOURCE_PIPE_VLV (0 << 27) +#define PIPE_CRC_SOURCE_HDMIB_VLV (1 << 27) +#define PIPE_CRC_SOURCE_HDMIC_VLV (2 << 27) +/* with DP port the pipe source is invalid */ +#define PIPE_CRC_SOURCE_DP_D_VLV (3 << 27) +#define PIPE_CRC_SOURCE_DP_B_VLV (6 << 27) +#define PIPE_CRC_SOURCE_DP_C_VLV (7 << 27) +/* gen3+ source selection */ +#define PIPE_CRC_SOURCE_PIPE_I9XX (0 << 28) +#define PIPE_CRC_SOURCE_SDVOB_I9XX (1 << 28) +#define PIPE_CRC_SOURCE_SDVOC_I9XX (2 << 28) +/* with DP/TV port the pipe source is invalid */ +#define PIPE_CRC_SOURCE_DP_D_G4X (3 << 28) +#define PIPE_CRC_SOURCE_TV_PRE (4 << 28) +#define PIPE_CRC_SOURCE_TV_POST (5 << 28) +#define PIPE_CRC_SOURCE_DP_B_G4X (6 << 28) +#define PIPE_CRC_SOURCE_DP_C_G4X (7 << 28) +/* gen2 doesn't have source selection bits */ + #define _PIPE_CRC_RES_1_A_IVB 0x60064 #define _PIPE_CRC_RES_2_A_IVB 0x60068 #define _PIPE_CRC_RES_3_A_IVB 0x6006c -- 1.7.9.5 From dheerajx.s.jamwal at intel.com Fri Jul 25 03:26:36 2014 From: dheerajx.s.jamwal at intel.com (Dheeraj Jamwal) Date: Fri, 25 Jul 2014 03:26:36 -0000 Subject: [LTSI-dev] [PATCH 50/50] drm/i915: Wire up CRC interrupts for pre-gen5/vlv In-Reply-To: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> References: <1406258918-18934-1-git-send-email-dheerajx.s.jamwal@intel.com> Message-ID: <1406258918-18934-51-git-send-email-dheerajx.s.jamwal@intel.com> From: Daniel Vetter And throw in a tiny for_each_pipe refactoring for gen2. Reviewed-by: Ville Syrj?l? Signed-off-by: Daniel Vetter (cherry picked from commit 4356d5864c29b9f822a496ab62f24a8971e1fbce) Signed-off-by: Dheeraj Jamwal --- drivers/gpu/drm/i915/i915_irq.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 98f5ac3..b31e7ca 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c @@ -1350,6 +1350,9 @@ static irqreturn_t valleyview_irq_handler(int irq, void *arg) intel_prepare_page_flip(dev, pipe); intel_finish_page_flip(dev, pipe); } + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_update(dev, pipe); } /* Consume port. Then clear IIR or we'll miss events */ @@ -2800,13 +2803,14 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg) if (iir & I915_USER_INTERRUPT) notify_ring(dev, &dev_priv->ring[RCS]); - if (pipe_stats[0] & PIPE_VBLANK_INTERRUPT_STATUS && - i8xx_handle_vblank(dev, 0, iir)) - flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(0); + for_each_pipe(pipe) { + if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS && + i8xx_handle_vblank(dev, pipe, iir)) + flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe); - if (pipe_stats[1] & PIPE_VBLANK_INTERRUPT_STATUS && - i8xx_handle_vblank(dev, 1, iir)) - flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(1); + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_update(dev, pipe); + } iir = new_iir; } @@ -2999,6 +3003,9 @@ static irqreturn_t i915_irq_handler(int irq, void *arg) if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) blc_event = true; + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_update(dev, pipe); } if (blc_event || (iir & I915_ASLE_INTERRUPT)) @@ -3243,6 +3250,9 @@ static irqreturn_t i965_irq_handler(int irq, void *arg) if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS) blc_event = true; + + if (pipe_stats[pipe] & PIPE_CRC_DONE_INTERRUPT_STATUS) + i9xx_pipe_crc_update(dev, pipe); } -- 1.7.9.5