From f9fc049ef1e05da3e3d2a45d098ec89b89bf687e Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Wed, 20 Dec 2017 09:47:07 -0700 Subject: [PATCH 001/237] iommu/amd - Record more information about unknown events When an unknown type event occurs, the default information written to the syslog should dump raw event data. This could provide insight into the event that occurred. Signed-off-by: Gary R Hook Signed-off-by: Alex Williamson --- drivers/iommu/amd_iommu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 7d5eb004091d1d..6af7ae6eac5e61 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -616,7 +616,9 @@ static void iommu_print_event(struct amd_iommu *iommu, void *__evt) address, flags); break; default: - printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type); + printk(KERN_ERR "UNKNOWN type=0x%02x event[0]=0x%08x " + "event[1]=0x%08x event[2]=0x%08x event[3]=0x%08x\n", + type, event[0], event[1], event[2], event[3]); } memset(__evt, 0, 4 * sizeof(u32)); From ff18c4e598de13af6503d6adb66f3ad768b6a53e Mon Sep 17 00:00:00 2001 From: Gary R Hook Date: Wed, 20 Dec 2017 09:47:08 -0700 Subject: [PATCH 002/237] iommu/amd: Set the device table entry PPR bit for IOMMU V2 devices The AMD IOMMU specification Rev 3.00 (December 2016) introduces a new Enhanced PPR Handling Support (EPHSup) bit in the MMIO register offset 0030h (IOMMU Extended Feature Register). When EPHSup=1, the IOMMU hardware requires the PPR bit of the device table entry (DTE) to be set in order to support PPR for a particular endpoint device. Please see https://support.amd.com/TechDocs/48882_IOMMU.pdf for this revision of the AMD IOMMU specification. Signed-off-by: Gary R Hook Signed-off-by: Alex Williamson --- drivers/iommu/amd_iommu.c | 20 +++++++++++++++----- drivers/iommu/amd_iommu_types.h | 2 ++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 6af7ae6eac5e61..0c71442e331cf5 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -1817,7 +1817,8 @@ static bool dma_ops_domain(struct protection_domain *domain) return domain->flags & PD_DMA_OPS_MASK; } -static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) +static void set_dte_entry(u16 devid, struct protection_domain *domain, + bool ats, bool ppr) { u64 pte_root = 0; u64 flags = 0; @@ -1834,6 +1835,13 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats) if (ats) flags |= DTE_FLAG_IOTLB; + if (ppr) { + struct amd_iommu *iommu = amd_iommu_rlookup_table[devid]; + + if (iommu_feature(iommu, FEATURE_EPHSUP)) + pte_root |= 1ULL << DEV_ENTRY_PPR; + } + if (domain->flags & PD_IOMMUV2_MASK) { u64 gcr3 = iommu_virt_to_phys(domain->gcr3_tbl); u64 glx = domain->glx; @@ -1896,9 +1904,9 @@ static void do_attach(struct iommu_dev_data *dev_data, domain->dev_cnt += 1; /* Update device table */ - set_dte_entry(dev_data->devid, domain, ats); + set_dte_entry(dev_data->devid, domain, ats, dev_data->iommu_v2); if (alias != dev_data->devid) - set_dte_entry(alias, domain, ats); + set_dte_entry(alias, domain, ats, dev_data->iommu_v2); device_flush_dte(dev_data); } @@ -2277,13 +2285,15 @@ static void update_device_table(struct protection_domain *domain) struct iommu_dev_data *dev_data; list_for_each_entry(dev_data, &domain->dev_list, list) { - set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled); + set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled, + dev_data->iommu_v2); if (dev_data->devid == dev_data->alias) continue; /* There is an alias, update device table entry for it */ - set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled); + set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled, + dev_data->iommu_v2); } } diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h index f6b24c7d8b70e3..6a877ebd058b1e 100644 --- a/drivers/iommu/amd_iommu_types.h +++ b/drivers/iommu/amd_iommu_types.h @@ -98,6 +98,7 @@ #define FEATURE_HE (1ULL<<8) #define FEATURE_PC (1ULL<<9) #define FEATURE_GAM_VAPIC (1ULL<<21) +#define FEATURE_EPHSUP (1ULL<<50) #define FEATURE_PASID_SHIFT 32 #define FEATURE_PASID_MASK (0x1fULL << FEATURE_PASID_SHIFT) @@ -192,6 +193,7 @@ /* macros and definitions for device table entries */ #define DEV_ENTRY_VALID 0x00 #define DEV_ENTRY_TRANSLATION 0x01 +#define DEV_ENTRY_PPR 0x34 #define DEV_ENTRY_IR 0x3d #define DEV_ENTRY_IW 0x3e #define DEV_ENTRY_NO_PAGE_FAULT 0x62 From ca84eaeb3e0520555ee031b5ed26ce1b4b1bbd84 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 20 Dec 2017 09:48:00 -0700 Subject: [PATCH 003/237] iommu/ipmmu-vmsa: Add r8a7796 DT binding Update the IPMMU DT binding documentation to include the r8a7796 compat string for R-Car M3-W. Signed-off-by: Magnus Damm Acked-by: Laurent Pinchart Acked-by: Rob Herring Acked-by: Simon Horman Acked-by: Geert Uytterhoeven Signed-off-by: Alex Williamson --- Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt index 857df929a65421..43cff3e449d01b 100644 --- a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt +++ b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt @@ -16,6 +16,7 @@ Required Properties: - "renesas,ipmmu-r8a7793" for the R8A7793 (R-Car M2-N) IPMMU. - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU. - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU. + - "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU. - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU. - reg: Base address and size of the IPMMU registers. From 9327b810bb7e1f3322fe8ed862a62fe0f2c9f14b Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 20 Dec 2017 09:48:01 -0700 Subject: [PATCH 004/237] iommu/ipmmu-vmsa: Add r8a779(70|95) DT bindings Update the IPMMU DT binding documentation to include the r8a77970 (R-Car V3M) and r8a77995 (R-Car D3) compat strings. Based on work for r8a7796 by Magnus Damm. Signed-off-by: Simon Horman Reviewed-by: Geert Uytterhoeven Signed-off-by: Alex Williamson --- Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt index 43cff3e449d01b..1fd5d69647ca0d 100644 --- a/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt +++ b/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt @@ -17,6 +17,8 @@ Required Properties: - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU. - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU. - "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU. + - "renesas,ipmmu-r8a77970" for the R8A77970 (R-Car V3M) IPMMU. + - "renesas,ipmmu-r8a77995" for the R8A77995 (R-Car D3) IPMMU. - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU. - reg: Base address and size of the IPMMU registers. From 9ae9df035c274c89b7fe3dbc74cbe2fa63386668 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Wed, 20 Dec 2017 09:48:36 -0700 Subject: [PATCH 005/237] iommu: Check the result of iommu_group_get() for NULL The result of iommu_group_get() was being blindly used in both attach and detach which results in a dereference when trying to work with an unknown device. Signed-off-by: Jordan Crouse Signed-off-by: Alex Williamson --- drivers/iommu/iommu.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index 3de5c0bcb5cc9f..69fef991c651de 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -1303,6 +1303,9 @@ int iommu_attach_device(struct iommu_domain *domain, struct device *dev) int ret; group = iommu_group_get(dev); + if (!group) + return -ENODEV; + /* * Lock the group to make sure the device-count doesn't * change while we are attaching @@ -1341,6 +1344,8 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) struct iommu_group *group; group = iommu_group_get(dev); + if (!group) + return; mutex_lock(&group->mutex); if (iommu_group_device_count(group) != 1) { From 72d548113881dd32bf7f0b221d031e6586468437 Mon Sep 17 00:00:00 2001 From: Jerry Snitselaar Date: Wed, 20 Dec 2017 09:48:56 -0700 Subject: [PATCH 006/237] iommu/vt-d: clean up pr_irq if request_threaded_irq fails It is unlikely request_threaded_irq will fail, but if it does for some reason we should clear iommu->pr_irq in the error path. Also intel_svm_finish_prq shouldn't try to clean up the page request interrupt if pr_irq is 0. Without these, if request_threaded_irq were to fail the following occurs: fail with no fixes: [ 0.683147] ------------[ cut here ]------------ [ 0.683148] NULL pointer, cannot free irq [ 0.683158] WARNING: CPU: 1 PID: 1 at kernel/irq/irqdomain.c:1632 irq_domain_free_irqs+0x126/0x140 [ 0.683160] Modules linked in: [ 0.683163] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 4.15.0-rc2 #3 [ 0.683165] Hardware name: /NUC7i3BNB, BIOS BNKBL357.86A.0036.2017.0105.1112 01/05/2017 [ 0.683168] RIP: 0010:irq_domain_free_irqs+0x126/0x140 [ 0.683169] RSP: 0000:ffffc90000037ce8 EFLAGS: 00010292 [ 0.683171] RAX: 000000000000001d RBX: ffff880276283c00 RCX: ffffffff81c5e5e8 [ 0.683172] RDX: 0000000000000001 RSI: 0000000000000096 RDI: 0000000000000246 [ 0.683174] RBP: ffff880276283c00 R08: 0000000000000000 R09: 000000000000023c [ 0.683175] R10: 0000000000000007 R11: 0000000000000000 R12: 000000000000007a [ 0.683176] R13: 0000000000000001 R14: 0000000000000000 R15: 0000010010000000 [ 0.683178] FS: 0000000000000000(0000) GS:ffff88027ec80000(0000) knlGS:0000000000000000 [ 0.683180] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 0.683181] CR2: 0000000000000000 CR3: 0000000001c09001 CR4: 00000000003606e0 [ 0.683182] Call Trace: [ 0.683189] intel_svm_finish_prq+0x3c/0x60 [ 0.683191] free_dmar_iommu+0x1ac/0x1b0 [ 0.683195] init_dmars+0xaaa/0xaea [ 0.683200] ? klist_next+0x19/0xc0 [ 0.683203] ? pci_do_find_bus+0x50/0x50 [ 0.683205] ? pci_get_dev_by_id+0x52/0x70 [ 0.683208] intel_iommu_init+0x498/0x5c7 [ 0.683211] pci_iommu_init+0x13/0x3c [ 0.683214] ? e820__memblock_setup+0x61/0x61 [ 0.683217] do_one_initcall+0x4d/0x1a0 [ 0.683220] kernel_init_freeable+0x186/0x20e [ 0.683222] ? set_debug_rodata+0x11/0x11 [ 0.683225] ? rest_init+0xb0/0xb0 [ 0.683226] kernel_init+0xa/0xff [ 0.683229] ret_from_fork+0x1f/0x30 [ 0.683259] Code: 89 ee 44 89 e7 e8 3b e8 ff ff 5b 5d 44 89 e7 44 89 ee 41 5c 41 5d 41 5e e9 a8 84 ff ff 48 c7 c7 a8 71 a7 81 31 c0 e8 6a d3 f9 ff <0f> ff 5b 5d 41 5c 41 5d 41 5 e c3 0f 1f 44 00 00 66 2e 0f 1f 84 [ 0.683285] ---[ end trace f7650e42792627ca ]--- with iommu->pr_irq = 0, but no check in intel_svm_finish_prq: [ 0.669561] ------------[ cut here ]------------ [ 0.669563] Trying to free already-free IRQ 0 [ 0.669573] WARNING: CPU: 3 PID: 1 at kernel/irq/manage.c:1546 __free_irq+0xa4/0x2c0 [ 0.669574] Modules linked in: [ 0.669577] CPU: 3 PID: 1 Comm: swapper/0 Not tainted 4.15.0-rc2 #4 [ 0.669579] Hardware name: /NUC7i3BNB, BIOS BNKBL357.86A.0036.2017.0105.1112 01/05/2017 [ 0.669581] RIP: 0010:__free_irq+0xa4/0x2c0 [ 0.669582] RSP: 0000:ffffc90000037cc0 EFLAGS: 00010082 [ 0.669584] RAX: 0000000000000021 RBX: 0000000000000000 RCX: ffffffff81c5e5e8 [ 0.669585] RDX: 0000000000000001 RSI: 0000000000000086 RDI: 0000000000000046 [ 0.669587] RBP: 0000000000000000 R08: 0000000000000000 R09: 000000000000023c [ 0.669588] R10: 0000000000000007 R11: 0000000000000000 R12: ffff880276253960 [ 0.669589] R13: ffff8802762538a4 R14: ffff880276253800 R15: ffff880276283600 [ 0.669593] FS: 0000000000000000(0000) GS:ffff88027ed80000(0000) knlGS:0000000000000000 [ 0.669594] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 0.669596] CR2: 0000000000000000 CR3: 0000000001c09001 CR4: 00000000003606e0 [ 0.669602] Call Trace: [ 0.669616] free_irq+0x30/0x60 [ 0.669620] intel_svm_finish_prq+0x34/0x60 [ 0.669623] free_dmar_iommu+0x1ac/0x1b0 [ 0.669627] init_dmars+0xaaa/0xaea [ 0.669631] ? klist_next+0x19/0xc0 [ 0.669634] ? pci_do_find_bus+0x50/0x50 [ 0.669637] ? pci_get_dev_by_id+0x52/0x70 [ 0.669639] intel_iommu_init+0x498/0x5c7 [ 0.669642] pci_iommu_init+0x13/0x3c [ 0.669645] ? e820__memblock_setup+0x61/0x61 [ 0.669648] do_one_initcall+0x4d/0x1a0 [ 0.669651] kernel_init_freeable+0x186/0x20e [ 0.669653] ? set_debug_rodata+0x11/0x11 [ 0.669656] ? rest_init+0xb0/0xb0 [ 0.669658] kernel_init+0xa/0xff [ 0.669661] ret_from_fork+0x1f/0x30 [ 0.669662] Code: 7a 08 75 0e e9 c3 01 00 00 4c 39 7b 08 74 57 48 89 da 48 8b 5a 18 48 85 db 75 ee 89 ee 48 c7 c7 78 67 a7 81 31 c0 e8 4c 37 fa ff <0f> ff 48 8b 34 24 4c 89 ef e 8 0e 4c 68 00 49 8b 46 40 48 8b 80 [ 0.669688] ---[ end trace 58a470248700f2fc ]--- Cc: Alex Williamson Cc: Joerg Roedel Cc: Ashok Raj Signed-off-by: Jerry Snitselaar Reviewed-by: Ashok Raj Signed-off-by: Alex Williamson --- drivers/iommu/intel-svm.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index ed1cf7c5a43ba3..6643277e321e22 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -129,6 +129,7 @@ int intel_svm_enable_prq(struct intel_iommu *iommu) pr_err("IOMMU: %s: Failed to request IRQ for page request queue\n", iommu->name); dmar_free_hwirq(irq); + iommu->pr_irq = 0; goto err; } dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL); @@ -144,9 +145,11 @@ int intel_svm_finish_prq(struct intel_iommu *iommu) dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL); dmar_writeq(iommu->reg + DMAR_PQA_REG, 0ULL); - free_irq(iommu->pr_irq, iommu); - dmar_free_hwirq(iommu->pr_irq); - iommu->pr_irq = 0; + if (iommu->pr_irq) { + free_irq(iommu->pr_irq, iommu); + dmar_free_hwirq(iommu->pr_irq); + iommu->pr_irq = 0; + } free_pages((unsigned long)iommu->prq, PRQ_ORDER); iommu->prq = NULL; From be819f7b66031c4a21fdc8edc47a3ecd4cac635d Mon Sep 17 00:00:00 2001 From: Elena Reshetova Date: Wed, 29 Nov 2017 13:15:44 +0200 Subject: [PATCH 007/237] lockd: convert nsm_handle.sm_count from atomic_t to refcount_t atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable nsm_handle.sm_count is used as pure reference counter. Convert it to refcount_t and fix up the operations. **Important note for maintainers: Some functions from refcount_t API defined in lib/refcount.c have different memory ordering guarantees than their atomic counterparts. The full comparison can be seen in https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon in state to be merged to the documentation tree. Normally the differences should not matter since refcount_t provides enough guarantees to satisfy the refcounting use cases, but in some rare cases it might matter. Please double check that you don't have some undocumented memory guarantees for this variable usage. For the nsm_handle.sm_count it might make a difference in following places: - nsm_release(): decrement in refcount_dec_and_lock() only provides RELEASE ordering, control dependency on success and holds a spin lock on success vs. fully ordered atomic counterpart. No change for the spin lock guarantees. Suggested-by: Kees Cook Reviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova Signed-off-by: J. Bruce Fields --- fs/lockd/host.c | 2 +- fs/lockd/mon.c | 14 +++++++------- include/linux/lockd/lockd.h | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/lockd/host.c b/fs/lockd/host.c index 826a89184f90fc..063095ee39ec6d 100644 --- a/fs/lockd/host.c +++ b/fs/lockd/host.c @@ -114,7 +114,7 @@ static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni, unsigned long now = jiffies; if (nsm != NULL) - atomic_inc(&nsm->sm_count); + refcount_inc(&nsm->sm_count); else { host = NULL; nsm = nsm_get_handle(ni->net, ni->sap, ni->salen, diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c index 96cfb2967ac757..654594ef4f945a 100644 --- a/fs/lockd/mon.c +++ b/fs/lockd/mon.c @@ -191,7 +191,7 @@ void nsm_unmonitor(const struct nlm_host *host) struct nsm_res res; int status; - if (atomic_read(&nsm->sm_count) == 1 + if (refcount_read(&nsm->sm_count) == 1 && nsm->sm_monitored && !nsm->sm_sticky) { dprintk("lockd: nsm_unmonitor(%s)\n", nsm->sm_name); @@ -279,7 +279,7 @@ static struct nsm_handle *nsm_create_handle(const struct sockaddr *sap, if (unlikely(new == NULL)) return NULL; - atomic_set(&new->sm_count, 1); + refcount_set(&new->sm_count, 1); new->sm_name = (char *)(new + 1); memcpy(nsm_addr(new), sap, salen); new->sm_addrlen = salen; @@ -337,13 +337,13 @@ struct nsm_handle *nsm_get_handle(const struct net *net, cached = nsm_lookup_addr(&ln->nsm_handles, sap); if (cached != NULL) { - atomic_inc(&cached->sm_count); + refcount_inc(&cached->sm_count); spin_unlock(&nsm_lock); kfree(new); dprintk("lockd: found nsm_handle for %s (%s), " "cnt %d\n", cached->sm_name, cached->sm_addrbuf, - atomic_read(&cached->sm_count)); + refcount_read(&cached->sm_count)); return cached; } @@ -388,12 +388,12 @@ struct nsm_handle *nsm_reboot_lookup(const struct net *net, return cached; } - atomic_inc(&cached->sm_count); + refcount_inc(&cached->sm_count); spin_unlock(&nsm_lock); dprintk("lockd: host %s (%s) rebooted, cnt %d\n", cached->sm_name, cached->sm_addrbuf, - atomic_read(&cached->sm_count)); + refcount_read(&cached->sm_count)); return cached; } @@ -404,7 +404,7 @@ struct nsm_handle *nsm_reboot_lookup(const struct net *net, */ void nsm_release(struct nsm_handle *nsm) { - if (atomic_dec_and_lock(&nsm->sm_count, &nsm_lock)) { + if (refcount_dec_and_lock(&nsm->sm_count, &nsm_lock)) { list_del(&nsm->sm_link); spin_unlock(&nsm_lock); dprintk("lockd: destroyed nsm_handle for %s (%s)\n", diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index d7d313fb9cd4c1..809619553e9b8d 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -83,7 +83,7 @@ struct nlm_host { struct nsm_handle { struct list_head sm_link; - atomic_t sm_count; + refcount_t sm_count; char *sm_mon_name; char *sm_name; struct sockaddr_storage sm_addr; From 8bb3ea77933e9796f8f15a5492481a96af8302d6 Mon Sep 17 00:00:00 2001 From: Elena Reshetova Date: Wed, 29 Nov 2017 13:15:45 +0200 Subject: [PATCH 008/237] lockd: convert nlm_lockowner.count from atomic_t to refcount_t atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable nlm_lockowner.count is used as pure reference counter. Convert it to refcount_t and fix up the operations. **Important note for maintainers: Some functions from refcount_t API defined in lib/refcount.c have different memory ordering guarantees than their atomic counterparts. The full comparison can be seen in https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon in state to be merged to the documentation tree. Normally the differences should not matter since refcount_t provides enough guarantees to satisfy the refcounting use cases, but in some rare cases it might matter. Please double check that you don't have some undocumented memory guarantees for this variable usage. For the nlm_lockowner.count it might make a difference in following places: - nlm_put_lockowner(): decrement in refcount_dec_and_lock() only provides RELEASE ordering, control dependency on success and holds a spin lock on success vs. fully ordered atomic counterpart. No changes in spin lock guarantees. Suggested-by: Kees Cook Reviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova Signed-off-by: J. Bruce Fields --- fs/lockd/clntproc.c | 6 +++--- include/linux/lockd/lockd.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 066ac313ae5c0f..112173dbea7605 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -48,13 +48,13 @@ void nlmclnt_next_cookie(struct nlm_cookie *c) static struct nlm_lockowner *nlm_get_lockowner(struct nlm_lockowner *lockowner) { - atomic_inc(&lockowner->count); + refcount_inc(&lockowner->count); return lockowner; } static void nlm_put_lockowner(struct nlm_lockowner *lockowner) { - if (!atomic_dec_and_lock(&lockowner->count, &lockowner->host->h_lock)) + if (!refcount_dec_and_lock(&lockowner->count, &lockowner->host->h_lock)) return; list_del(&lockowner->list); spin_unlock(&lockowner->host->h_lock); @@ -105,7 +105,7 @@ static struct nlm_lockowner *nlm_find_lockowner(struct nlm_host *host, fl_owner_ res = __nlm_find_lockowner(host, owner); if (res == NULL && new != NULL) { res = new; - atomic_set(&new->count, 1); + refcount_set(&new->count, 1); new->owner = owner; new->pid = __nlm_alloc_pid(host); new->host = nlm_get_host(host); diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 809619553e9b8d..345fced8339e62 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -122,7 +122,7 @@ static inline struct sockaddr *nlm_srcaddr(const struct nlm_host *host) */ struct nlm_lockowner { struct list_head list; - atomic_t count; + refcount_t count; struct nlm_host *host; fl_owner_t owner; From d9226ec9ef01832b1edc1781241920614c6407db Mon Sep 17 00:00:00 2001 From: Elena Reshetova Date: Wed, 29 Nov 2017 13:15:46 +0200 Subject: [PATCH 009/237] lockd: convert nlm_rqst.a_count from atomic_t to refcount_t atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable nlm_rqst.a_count is used as pure reference counter. Convert it to refcount_t and fix up the operations. **Important note for maintainers: Some functions from refcount_t API defined in lib/refcount.c have different memory ordering guarantees than their atomic counterparts. The full comparison can be seen in https://lkml.org/lkml/2017/11/15/57 and it is hopefully soon in state to be merged to the documentation tree. Normally the differences should not matter since refcount_t provides enough guarantees to satisfy the refcounting use cases, but in some rare cases it might matter. Please double check that you don't have some undocumented memory guarantees for this variable usage. For the nlm_rqst.a_count it might make a difference in following places: - nlmclnt_release_call() and nlmsvc_release_call(): decrement in refcount_dec_and_test() only provides RELEASE ordering and control dependency on success vs. fully ordered atomic counterpart Suggested-by: Kees Cook Reviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova Signed-off-by: J. Bruce Fields --- fs/lockd/clntproc.c | 8 ++++---- fs/lockd/svcproc.c | 2 +- include/linux/lockd/lockd.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/lockd/clntproc.c b/fs/lockd/clntproc.c index 112173dbea7605..a2c0dfc6fdc001 100644 --- a/fs/lockd/clntproc.c +++ b/fs/lockd/clntproc.c @@ -204,7 +204,7 @@ struct nlm_rqst *nlm_alloc_call(struct nlm_host *host) for(;;) { call = kzalloc(sizeof(*call), GFP_KERNEL); if (call != NULL) { - atomic_set(&call->a_count, 1); + refcount_set(&call->a_count, 1); locks_init_lock(&call->a_args.lock.fl); locks_init_lock(&call->a_res.lock.fl); call->a_host = nlm_get_host(host); @@ -222,7 +222,7 @@ void nlmclnt_release_call(struct nlm_rqst *call) { const struct nlmclnt_operations *nlmclnt_ops = call->a_host->h_nlmclnt_ops; - if (!atomic_dec_and_test(&call->a_count)) + if (!refcount_dec_and_test(&call->a_count)) return; if (nlmclnt_ops && nlmclnt_ops->nlmclnt_release_call) nlmclnt_ops->nlmclnt_release_call(call->a_callback_data); @@ -678,7 +678,7 @@ nlmclnt_unlock(struct nlm_rqst *req, struct file_lock *fl) goto out; } - atomic_inc(&req->a_count); + refcount_inc(&req->a_count); status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req, NLMPROC_UNLOCK, &nlmclnt_unlock_ops); if (status < 0) @@ -769,7 +769,7 @@ static int nlmclnt_cancel(struct nlm_host *host, int block, struct file_lock *fl nlmclnt_setlockargs(req, fl); req->a_args.block = block; - atomic_inc(&req->a_count); + refcount_inc(&req->a_count); status = nlmclnt_async_call(nfs_file_cred(fl->fl_file), req, NLMPROC_CANCEL, &nlmclnt_cancel_ops); if (status == 0 && req->a_res.status == nlm_lck_denied) diff --git a/fs/lockd/svcproc.c b/fs/lockd/svcproc.c index 0d670c5c378fcf..ea77c66d3cc33f 100644 --- a/fs/lockd/svcproc.c +++ b/fs/lockd/svcproc.c @@ -295,7 +295,7 @@ static void nlmsvc_callback_exit(struct rpc_task *task, void *data) void nlmsvc_release_call(struct nlm_rqst *call) { - if (!atomic_dec_and_test(&call->a_count)) + if (!refcount_dec_and_test(&call->a_count)) return; nlmsvc_release_host(call->a_host); kfree(call); diff --git a/include/linux/lockd/lockd.h b/include/linux/lockd/lockd.h index 345fced8339e62..94c9ff58fc91f9 100644 --- a/include/linux/lockd/lockd.h +++ b/include/linux/lockd/lockd.h @@ -136,7 +136,7 @@ struct nlm_wait; */ #define NLMCLNT_OHSIZE ((__NEW_UTS_LEN) + 10u) struct nlm_rqst { - atomic_t a_count; + refcount_t a_count; unsigned int a_flags; /* initial RPC task flags */ struct nlm_host * a_host; /* host handle */ struct nlm_args a_args; /* arguments */ From 66282ec1cf004c09083c29cb5e49019037937bbd Mon Sep 17 00:00:00 2001 From: Benjamin Coddington Date: Tue, 19 Dec 2017 09:35:25 -0500 Subject: [PATCH 010/237] nfsd4: permit layoutget of executable-only files Clients must be able to read a file in order to execute it, and for pNFS that means the client needs to be able to perform a LAYOUTGET on the file. This behavior for executable-only files was added for OPEN in commit a043226bc140 "nfsd4: permit read opens of executable-only files". This fixes up xfstests generic/126 on block/scsi layouts. Signed-off-by: Benjamin Coddington Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 008ea0b627d02d..effeeb4f556f64 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1363,14 +1363,14 @@ nfsd4_layoutget(struct svc_rqst *rqstp, const struct nfsd4_layout_ops *ops; struct nfs4_layout_stateid *ls; __be32 nfserr; - int accmode; + int accmode = NFSD_MAY_READ_IF_EXEC; switch (lgp->lg_seg.iomode) { case IOMODE_READ: - accmode = NFSD_MAY_READ; + accmode |= NFSD_MAY_READ; break; case IOMODE_RW: - accmode = NFSD_MAY_READ | NFSD_MAY_WRITE; + accmode |= NFSD_MAY_READ | NFSD_MAY_WRITE; break; default: dprintk("%s: invalid iomode %d\n", From fd989db807a00d552ebf29d8ffb20c2ef04742da Mon Sep 17 00:00:00 2001 From: Sergey Senozhatsky Date: Fri, 5 Jan 2018 11:47:44 +0900 Subject: [PATCH 011/237] cris: Fix conflicting types for _etext, _edata, _end Include asm/sections.h header which contains the correct types for _etext, _edata and _end - char arrays. Signed-off-by: Sergey Senozhatsky Signed-off-by: Jesper Nilsson --- arch/cris/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/cris/kernel/setup.c b/arch/cris/kernel/setup.c index 524d47501a236c..1b61a7207afb05 100644 --- a/arch/cris/kernel/setup.c +++ b/arch/cris/kernel/setup.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * Setup options @@ -31,7 +32,6 @@ struct screen_info screen_info; extern int root_mountflags; -extern char _etext, _edata, _end; char __initdata cris_command_line[COMMAND_LINE_SIZE] = { 0, }; From f18affbea8f7aebb235bfdaf3ad4c307aa5f3d64 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 2 Jan 2018 16:29:45 +0100 Subject: [PATCH 012/237] iommu/omap: Fix debugfs_create_*() usage When exposing data access through debugfs, the correct debugfs_create_*() functions must be used, depending on data type. Remove all casts from data pointers passed to debugfs_create_*() functions, as such casts prevent the compiler from flagging bugs. omap_iommu.nr_tlb_entries is "int", hence casting to "u8 *" exposes only a part of it. Fix this by using debugfs_create_u32() instead. Signed-off-by: Geert Uytterhoeven Signed-off-by: Joerg Roedel --- drivers/iommu/omap-iommu-debug.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/omap-iommu-debug.c b/drivers/iommu/omap-iommu-debug.c index 505548aafeff22..50217548c3b8e7 100644 --- a/drivers/iommu/omap-iommu-debug.c +++ b/drivers/iommu/omap-iommu-debug.c @@ -274,8 +274,8 @@ void omap_iommu_debugfs_add(struct omap_iommu *obj) if (!obj->debug_dir) return; - d = debugfs_create_u8("nr_tlb_entries", 0400, obj->debug_dir, - (u8 *)&obj->nr_tlb_entries); + d = debugfs_create_u32("nr_tlb_entries", 0400, obj->debug_dir, + &obj->nr_tlb_entries); if (!d) return; From dc98b8480d8a68c2ce9aa28b9f0d714fd258bc0b Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 9 Jan 2018 15:34:07 +0000 Subject: [PATCH 013/237] iommu/exynos: Don't unconditionally steal bus ops Removing the early device registration hook overlooked the fact that it only ran conditionally on a compatible device being present in the DT. With exynos_iommu_init() now running as an unconditional initcall, problems arise on non-Exynos systems when other IOMMU drivers find themselves unable to install their ops on the platform bus, or at worst the Exynos ops get called with someone else's domain and all hell breaks loose. The global ops/cache setup could probably all now be triggered from the first IOMMU probe, as with dma_dev assigment, but for the time being the simplest fix is to resurrect the logic from commit a7b67cd5d9af ("iommu/exynos: Play nice in multi-platform builds") to explicitly check the DT for the presence of an Exynos IOMMU before trying anything. Fixes: 928055a01b3f ("iommu/exynos: Remove custom platform device registration code") Signed-off-by: Robin Murphy Acked-by: Marek Szyprowski Signed-off-by: Joerg Roedel --- drivers/iommu/exynos-iommu.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 79c45650f8de6b..736d4552d96f34 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1353,8 +1353,15 @@ static const struct iommu_ops exynos_iommu_ops = { static int __init exynos_iommu_init(void) { + struct device_node *np; int ret; + np = of_find_matching_node(NULL, sysmmu_of_match); + if (!np) + return 0; + + of_node_put(np); + lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table", LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL); if (!lv2table_kmem_cache) { From 9d2e6505f6d6934e681aed502f566198cb25c74a Mon Sep 17 00:00:00 2001 From: Peter Xu Date: Wed, 10 Jan 2018 13:51:37 +0800 Subject: [PATCH 014/237] iommu/vt-d: Use domain instead of cache fetching after commit a1ddcbe93010 ("iommu/vt-d: Pass dmar_domain directly into iommu_flush_iotlb_psi", 2015-08-12), we have domain pointer as parameter to iommu_flush_iotlb_psi(), so no need to fetch it from cache again. More importantly, a NULL reference pointer bug is reported on RHEL7 (and it can be reproduced on some old upstream kernels too, e.g., v4.13) by unplugging an 40g nic from a VM (hard to test unplug on real host, but it should be the same): https://bugzilla.redhat.com/show_bug.cgi?id=1531367 [ 24.391863] pciehp 0000:00:03.0:pcie004: Slot(0): Attention button pressed [ 24.393442] pciehp 0000:00:03.0:pcie004: Slot(0): Powering off due to button press [ 29.721068] i40evf 0000:01:00.0: Unable to send opcode 2 to PF, err I40E_ERR_QUEUE_EMPTY, aq_err OK [ 29.783557] iommu: Removing device 0000:01:00.0 from group 3 [ 29.784662] BUG: unable to handle kernel NULL pointer dereference at 0000000000000304 [ 29.785817] IP: iommu_flush_iotlb_psi+0xcf/0x120 [ 29.786486] PGD 0 [ 29.786487] P4D 0 [ 29.786812] [ 29.787390] Oops: 0000 [#1] SMP [ 29.787876] Modules linked in: ip6t_rpfilter ip6t_REJECT nf_reject_ipv6 xt_conntrack ip_set nfnetlink ebtable_nat ebtable_broute bridge stp llc ip6table_ng [ 29.795371] CPU: 0 PID: 156 Comm: kworker/0:2 Not tainted 4.13.0 #14 [ 29.796366] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.11.0-1.el7 04/01/2014 [ 29.797593] Workqueue: pciehp-0 pciehp_power_thread [ 29.798328] task: ffff94f5745b4a00 task.stack: ffffb326805ac000 [ 29.799178] RIP: 0010:iommu_flush_iotlb_psi+0xcf/0x120 [ 29.799919] RSP: 0018:ffffb326805afbd0 EFLAGS: 00010086 [ 29.800666] RAX: ffff94f5bc56e800 RBX: 0000000000000000 RCX: 0000000200000025 [ 29.801667] RDX: ffff94f5bc56e000 RSI: 0000000000000082 RDI: 0000000000000000 [ 29.802755] RBP: ffffb326805afbf8 R08: 0000000000000000 R09: ffff94f5bc86bbf0 [ 29.803772] R10: ffffb326805afba8 R11: 00000000000ffdc4 R12: ffff94f5bc86a400 [ 29.804789] R13: 0000000000000000 R14: 00000000ffdc4000 R15: 0000000000000000 [ 29.805792] FS: 0000000000000000(0000) GS:ffff94f5bfc00000(0000) knlGS:0000000000000000 [ 29.806923] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 29.807736] CR2: 0000000000000304 CR3: 000000003499d000 CR4: 00000000000006f0 [ 29.808747] Call Trace: [ 29.809156] flush_unmaps_timeout+0x126/0x1c0 [ 29.809800] domain_exit+0xd6/0x100 [ 29.810322] device_notifier+0x6b/0x70 [ 29.810902] notifier_call_chain+0x4a/0x70 [ 29.812822] __blocking_notifier_call_chain+0x47/0x60 [ 29.814499] blocking_notifier_call_chain+0x16/0x20 [ 29.816137] device_del+0x233/0x320 [ 29.817588] pci_remove_bus_device+0x6f/0x110 [ 29.819133] pci_stop_and_remove_bus_device+0x1a/0x20 [ 29.820817] pciehp_unconfigure_device+0x7a/0x1d0 [ 29.822434] pciehp_disable_slot+0x52/0xe0 [ 29.823931] pciehp_power_thread+0x8a/0xa0 [ 29.825411] process_one_work+0x18c/0x3a0 [ 29.826875] worker_thread+0x4e/0x3b0 [ 29.828263] kthread+0x109/0x140 [ 29.829564] ? process_one_work+0x3a0/0x3a0 [ 29.831081] ? kthread_park+0x60/0x60 [ 29.832464] ret_from_fork+0x25/0x30 [ 29.833794] Code: 85 ed 74 0b 5b 41 5c 41 5d 41 5e 41 5f 5d c3 49 8b 54 24 60 44 89 f8 0f b6 c4 48 8b 04 c2 48 85 c0 74 49 45 0f b6 ff 4a 8b 3c f8 <80> bf [ 29.838514] RIP: iommu_flush_iotlb_psi+0xcf/0x120 RSP: ffffb326805afbd0 [ 29.840362] CR2: 0000000000000304 [ 29.841716] ---[ end trace b10ec0d6900868d3 ]--- This patch fixes that problem if applied to v4.13 kernel. The bug does not exist on latest upstream kernel since it's fixed as a side effect of commit 13cf01744608 ("iommu/vt-d: Make use of iova deferred flushing", 2017-08-15). But IMHO it's still good to have this patch upstream. CC: Alex Williamson Signed-off-by: Peter Xu Fixes: a1ddcbe93010 ("iommu/vt-d: Pass dmar_domain directly into iommu_flush_iotlb_psi") Reviewed-by: Alex Williamson Signed-off-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 4a2de34895ec31..869f37d1f3b7bd 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -1601,8 +1601,7 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu, * flush. However, device IOTLB doesn't need to be flushed in this case. */ if (!cap_caching_mode(iommu->cap) || !map) - iommu_flush_dev_iotlb(get_iommu_domain(iommu, did), - addr, mask); + iommu_flush_dev_iotlb(domain, addr, mask); } static void iommu_flush_iova(struct iova_domain *iovad) From 5e3b4a15dd8da6bded2092694c8db3b505cbf711 Mon Sep 17 00:00:00 2001 From: Sohil Mehta Date: Wed, 20 Dec 2017 11:59:24 -0800 Subject: [PATCH 015/237] iommu/vt-d: Enable upto 57 bits of domain address width Update the IOMMU default domain address width to 57 bits. This would enable the IOMMU to do upto 5-levels of paging for second level translations - IOVA translation requests without PASID. Even though the maximum supported address width is being increased to 57, __iommu_calculate_agaw() would set the actual supported address width to the maximum support available in IOMMU hardware. Signed-off-by: Sohil Mehta Signed-off-by: Joerg Roedel --- drivers/iommu/intel-iommu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 869f37d1f3b7bd..53227d6e911e91 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -64,7 +64,7 @@ #define IOAPIC_RANGE_END (0xfeefffff) #define IOVA_START_ADDR (0x1000) -#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48 +#define DEFAULT_DOMAIN_ADDRESS_WIDTH 57 #define MAX_AGAW_WIDTH 64 #define MAX_AGAW_PFN_WIDTH (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT) From 59103caa6839592788e7ad58b35863aac034631a Mon Sep 17 00:00:00 2001 From: Sohil Mehta Date: Wed, 20 Dec 2017 11:59:25 -0800 Subject: [PATCH 016/237] iommu/vt-d: Add a check for 1GB page support Add a check to verify IOMMU 1GB page support. If the CPU supports 1GB pages but the IOMMU does not support it then disable SVM by not allocating PASID tables. Signed-off-by: Sohil Mehta Signed-off-by: Joerg Roedel --- drivers/iommu/intel-svm.c | 4 ++++ include/linux/intel-iommu.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index 6643277e321e22..e9a56ad09a7613 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -41,6 +41,10 @@ int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu) struct page *pages; int order; + if (cpu_feature_enabled(X86_FEATURE_GBPAGES) && + !cap_fl1gp_support(iommu->cap)) + return -EINVAL; + /* Start at 2 because it's defined as 2^(1+PSS) */ iommu->pasid_max = 2 << ecap_pss(iommu->ecap); diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index f3274d9f46a252..a56bab114f3903 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -84,6 +84,7 @@ * Decoding Capability Register */ #define cap_pi_support(c) (((c) >> 59) & 1) +#define cap_fl1gp_support(c) (((c) >> 56) & 1) #define cap_read_drain(c) (((c) >> 55) & 1) #define cap_write_drain(c) (((c) >> 54) & 1) #define cap_max_amask_val(c) (((c) >> 48) & 0x3f) From f1ac10c24efbbcba0f8dae37ee90d45847f5c5af Mon Sep 17 00:00:00 2001 From: Sohil Mehta Date: Wed, 20 Dec 2017 11:59:26 -0800 Subject: [PATCH 017/237] iommu/vt-d: Add a check for 5-level paging support Add a check to verify IOMMU 5-level paging support. If the CPU supports supports 5-level paging but the IOMMU does not support it then disable SVM by not allocating PASID tables. Signed-off-by: Sohil Mehta Signed-off-by: Joerg Roedel --- drivers/iommu/intel-svm.c | 4 ++++ include/linux/intel-iommu.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index e9a56ad09a7613..b43dc1edcef065 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -45,6 +45,10 @@ int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu) !cap_fl1gp_support(iommu->cap)) return -EINVAL; + if (cpu_feature_enabled(X86_FEATURE_LA57) && + !cap_5lp_support(iommu->cap)) + return -EINVAL; + /* Start at 2 because it's defined as 2^(1+PSS) */ iommu->pasid_max = 2 << ecap_pss(iommu->ecap); diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h index a56bab114f3903..8dad3dd26eaedd 100644 --- a/include/linux/intel-iommu.h +++ b/include/linux/intel-iommu.h @@ -83,6 +83,7 @@ /* * Decoding Capability Register */ +#define cap_5lp_support(c) (((c) >> 60) & 1) #define cap_pi_support(c) (((c) >> 59) & 1) #define cap_fl1gp_support(c) (((c) >> 56) & 1) #define cap_read_drain(c) (((c) >> 55) & 1) From 2f13eb7c580fcbe3d73ebbe6fb1841381cad0a05 Mon Sep 17 00:00:00 2001 From: Sohil Mehta Date: Wed, 20 Dec 2017 11:59:27 -0800 Subject: [PATCH 018/237] iommu/vt-d: Enable 5-level paging mode in the PASID entry If the CPU has support for 5-level paging enabled and the IOMMU also supports 5-level paging then enable the 5-level paging mode for first- level translations - used when SVM is enabled. Signed-off-by: Sohil Mehta Signed-off-by: Joerg Roedel --- drivers/iommu/intel-svm.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index b43dc1edcef065..859b61ddd508b6 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -26,6 +26,10 @@ #include #include +#define PASID_ENTRY_P BIT_ULL(0) +#define PASID_ENTRY_FLPM_5LP BIT_ULL(9) +#define PASID_ENTRY_SRE BIT_ULL(11) + static irqreturn_t prq_event_thread(int irq, void *d); struct pasid_entry { @@ -300,6 +304,7 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ struct intel_svm_dev *sdev; struct intel_svm *svm = NULL; struct mm_struct *mm = NULL; + u64 pasid_entry_val; int pasid_max; int ret; @@ -406,9 +411,15 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_ kfree(sdev); goto out; } - iommu->pasid_table[svm->pasid].val = (u64)__pa(mm->pgd) | 1; + pasid_entry_val = (u64)__pa(mm->pgd) | PASID_ENTRY_P; } else - iommu->pasid_table[svm->pasid].val = (u64)__pa(init_mm.pgd) | 1 | (1ULL << 11); + pasid_entry_val = (u64)__pa(init_mm.pgd) | + PASID_ENTRY_P | PASID_ENTRY_SRE; + if (cpu_feature_enabled(X86_FEATURE_LA57)) + pasid_entry_val |= PASID_ENTRY_FLPM_5LP; + + iommu->pasid_table[svm->pasid].val = pasid_entry_val; + wmb(); /* In caching mode, we still have to flush with PASID 0 when * a PASID table entry becomes present. Not entirely clear From 892d7aaddb24b0d3eaf05534ed29a264d3b52646 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 9 Jan 2018 16:17:25 +0000 Subject: [PATCH 019/237] iommu/msm: Claim bus ops on probe Since the MSM IOMMU driver now probes via DT exclusively rather than platform data, dependent masters should be deferred until the IOMMU itself is ready. Thus we can do away with the early initialisation hook to unconditionally claim the bus ops, and instead do that only once an IOMMU is actually probed. Furthermore, this should also make the driver safe for multiplatform kernels on non-MSM SoCs. Reviewed-by: Sricharan R Signed-off-by: Robin Murphy Signed-off-by: Joerg Roedel --- drivers/iommu/msm_iommu.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index 04f4d51ffacb1e..dda1ce87a0704f 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -823,6 +823,8 @@ static int msm_iommu_probe(struct platform_device *pdev) goto fail; } + bus_set_iommu(&platform_bus_type, &msm_iommu_ops); + pr_info("device mapped at %p, irq %d with %d ctx banks\n", iommu->base, iommu->irq, iommu->ncb); @@ -875,19 +877,7 @@ static void __exit msm_iommu_driver_exit(void) subsys_initcall(msm_iommu_driver_init); module_exit(msm_iommu_driver_exit); -static int __init msm_iommu_init(void) -{ - bus_set_iommu(&platform_bus_type, &msm_iommu_ops); - return 0; -} - -static int __init msm_iommu_of_setup(struct device_node *np) -{ - msm_iommu_init(); - return 0; -} - -IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", msm_iommu_of_setup); +IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", NULL); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Stepan Moskovchenko "); From e7747d88e05eabed6fd921c3636a9d1f5b4f754f Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 9 Jan 2018 16:17:26 +0000 Subject: [PATCH 020/237] iommu/ipmmu-vmsa: Remove redundant of_iommu_init_fn hook Having of_iommu_init() call ipmmu_init() via ipmmu_vmsa_iommu_of_setup() does nothing that the subsys_initcall wouldn't do slightly later anyway, since probe-deferral of masters means it is no longer critical to register the driver super-early. Clean it up. Signed-off-by: Robin Murphy Signed-off-by: Joerg Roedel --- drivers/iommu/ipmmu-vmsa.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 8dce3a9de9d86e..331dad9093019c 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -1108,18 +1108,8 @@ static void __exit ipmmu_exit(void) subsys_initcall(ipmmu_init); module_exit(ipmmu_exit); -#ifdef CONFIG_IOMMU_DMA -static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np) -{ - ipmmu_init(); - return 0; -} - -IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa", - ipmmu_vmsa_iommu_of_setup); -IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795", - ipmmu_vmsa_iommu_of_setup); -#endif +IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa", NULL); +IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795", NULL); MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); MODULE_AUTHOR("Laurent Pinchart "); From b0c560f7d8a4b333bcc18f692d0af0d5cca90fe2 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Tue, 9 Jan 2018 16:17:27 +0000 Subject: [PATCH 021/237] iommu: Clean up of_iommu_init_fn Now that no more drivers rely on arbitrary early initialisation via an of_iommu_init_fn hook, let's clean up the redundant remnants. The IOMMU_OF_DECLARE() macro needs to remain for now, as the probe-deferral mechanism has no other nice way to detect built-in drivers before they have registered themselves, such that it can make the right decision. Reviewed-by: Sricharan R Signed-off-by: Robin Murphy Signed-off-by: Joerg Roedel --- drivers/iommu/arm-smmu-v3.c | 2 +- drivers/iommu/arm-smmu.c | 12 ++++++------ drivers/iommu/exynos-iommu.c | 2 +- drivers/iommu/ipmmu-vmsa.c | 4 ++-- drivers/iommu/msm_iommu.c | 2 +- drivers/iommu/of_iommu.c | 16 ---------------- drivers/iommu/qcom_iommu.c | 2 +- include/linux/of_iommu.h | 5 +---- 8 files changed, 13 insertions(+), 32 deletions(-) diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c index f122071688fd53..7f186beaa1a6af 100644 --- a/drivers/iommu/arm-smmu-v3.c +++ b/drivers/iommu/arm-smmu-v3.c @@ -2962,7 +2962,7 @@ static struct platform_driver arm_smmu_driver = { }; module_platform_driver(arm_smmu_driver); -IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL); +IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3"); MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations"); MODULE_AUTHOR("Will Deacon "); diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 78d4c6b8f1bad5..69e7c60792a8e3 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -2211,12 +2211,12 @@ static struct platform_driver arm_smmu_driver = { }; module_platform_driver(arm_smmu_driver); -IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", NULL); -IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", NULL); -IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", NULL); -IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", NULL); -IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", NULL); -IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", NULL); +IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1"); +IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2"); +IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400"); +IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401"); +IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500"); +IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2"); MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations"); MODULE_AUTHOR("Will Deacon "); diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c index 79c45650f8de6b..1c7f926fad0e99 100644 --- a/drivers/iommu/exynos-iommu.c +++ b/drivers/iommu/exynos-iommu.c @@ -1394,4 +1394,4 @@ static int __init exynos_iommu_init(void) } core_initcall(exynos_iommu_init); -IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu", NULL); +IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu"); diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index 331dad9093019c..40ae6e87cb8802 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -1108,8 +1108,8 @@ static void __exit ipmmu_exit(void) subsys_initcall(ipmmu_init); module_exit(ipmmu_exit); -IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa", NULL); -IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795", NULL); +IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa"); +IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795"); MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU"); MODULE_AUTHOR("Laurent Pinchart "); diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c index dda1ce87a0704f..0d3350463a3f48 100644 --- a/drivers/iommu/msm_iommu.c +++ b/drivers/iommu/msm_iommu.c @@ -877,7 +877,7 @@ static void __exit msm_iommu_driver_exit(void) subsys_initcall(msm_iommu_driver_init); module_exit(msm_iommu_driver_exit); -IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", NULL); +IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu"); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Stepan Moskovchenko "); diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c index 50947ebb6d1700..5c36a8b7656ae2 100644 --- a/drivers/iommu/of_iommu.c +++ b/drivers/iommu/of_iommu.c @@ -231,19 +231,3 @@ const struct iommu_ops *of_iommu_configure(struct device *dev, return ops; } - -static int __init of_iommu_init(void) -{ - struct device_node *np; - const struct of_device_id *match, *matches = &__iommu_of_table; - - for_each_matching_node_and_match(np, matches, &match) { - const of_iommu_init_fn init_fn = match->data; - - if (init_fn && init_fn(np)) - pr_err("Failed to initialise IOMMU %pOF\n", np); - } - - return 0; -} -postcore_initcall_sync(of_iommu_init); diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index e07f02d00c688f..65b9c99707f848 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -947,7 +947,7 @@ static void __exit qcom_iommu_exit(void) module_init(qcom_iommu_init); module_exit(qcom_iommu_exit); -IOMMU_OF_DECLARE(qcom_iommu_dev, "qcom,msm-iommu-v1", NULL); +IOMMU_OF_DECLARE(qcom_iommu_dev, "qcom,msm-iommu-v1"); MODULE_DESCRIPTION("IOMMU API for QCOM IOMMU v1 implementations"); MODULE_LICENSE("GPL v2"); diff --git a/include/linux/of_iommu.h b/include/linux/of_iommu.h index cddfaff4d0b70f..4fa654e4b5a92e 100644 --- a/include/linux/of_iommu.h +++ b/include/linux/of_iommu.h @@ -34,9 +34,6 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev, extern struct of_device_id __iommu_of_table; -typedef int (*of_iommu_init_fn)(struct device_node *); - -#define IOMMU_OF_DECLARE(name, compat, fn) \ - _OF_DECLARE(iommu, name, compat, fn, of_iommu_init_fn) +#define IOMMU_OF_DECLARE(name, compat) OF_DECLARE_1(iommu, name, compat, NULL) #endif /* __OF_IOMMU_H */ From 482725027ff32bc857f5527fb17feda5361265fe Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Wed, 3 Jan 2018 15:42:18 -0500 Subject: [PATCH 022/237] svcrdma: Post Receives in the Receive completion handler This change improves Receive efficiency by posting Receives only on the same CPU that handles Receive completion. Improved latency and throughput has been noted with this change. Signed-off-by: Chuck Lever Signed-off-by: J. Bruce Fields --- include/linux/sunrpc/svc_rdma.h | 2 -- net/sunrpc/xprtrdma/svc_rdma_backchannel.c | 5 ----- net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 9 +------- net/sunrpc/xprtrdma/svc_rdma_sendto.c | 6 ------ net/sunrpc/xprtrdma/svc_rdma_transport.c | 25 ++++++---------------- 5 files changed, 8 insertions(+), 39 deletions(-) diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h index 995c6fe9ee907f..4b731b046bcde1 100644 --- a/include/linux/sunrpc/svc_rdma.h +++ b/include/linux/sunrpc/svc_rdma.h @@ -185,8 +185,6 @@ extern void svc_rdma_wc_reg(struct ib_cq *, struct ib_wc *); extern void svc_rdma_wc_read(struct ib_cq *, struct ib_wc *); extern void svc_rdma_wc_inv(struct ib_cq *, struct ib_wc *); extern int svc_rdma_send(struct svcxprt_rdma *, struct ib_send_wr *); -extern int svc_rdma_post_recv(struct svcxprt_rdma *, gfp_t); -extern int svc_rdma_repost_recv(struct svcxprt_rdma *, gfp_t); extern int svc_rdma_create_listen(struct svc_serv *, int, struct sockaddr *); extern struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *); extern void svc_rdma_put_context(struct svc_rdma_op_ctxt *, int); diff --git a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c index af7893501e40ac..a73632ca904822 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_backchannel.c +++ b/net/sunrpc/xprtrdma/svc_rdma_backchannel.c @@ -95,7 +95,6 @@ int svc_rdma_handle_bc_reply(struct rpc_xprt *xprt, __be32 *rdma_resp, out_notfound: dprintk("svcrdma: unrecognized bc reply: xprt=%p, xid=%08x\n", xprt, be32_to_cpu(xid)); - goto out_unlock; } @@ -129,10 +128,6 @@ static int svc_rdma_bc_sendto(struct svcxprt_rdma *rdma, if (ret < 0) goto out_err; - ret = svc_rdma_repost_recv(rdma, GFP_NOIO); - if (ret) - goto out_err; - /* Bump page refcnt so Send completion doesn't release * the rq_buffer before all retransmits are complete. */ diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index ad4bd62eebf1ac..19e9c6b3304272 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c @@ -400,10 +400,6 @@ static void svc_rdma_send_error(struct svcxprt_rdma *xprt, struct page *page; int ret; - ret = svc_rdma_repost_recv(xprt, GFP_KERNEL); - if (ret) - return; - page = alloc_page(GFP_KERNEL); if (!page) return; @@ -554,8 +550,6 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) ret = svc_rdma_handle_bc_reply(xprt->xpt_bc_xprt, p, &rqstp->rq_arg); svc_rdma_put_context(ctxt, 0); - if (ret) - goto repost; return ret; } @@ -590,6 +584,5 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp) out_drop: svc_rdma_put_context(ctxt, 1); -repost: - return svc_rdma_repost_recv(rdma_xprt, GFP_KERNEL); + return 0; } diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 7c3a211e0e9a9e..649441d5087d9a 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c @@ -674,9 +674,6 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) svc_rdma_xdr_encode_reply_chunk(rdma_resp, rp_ch, ret); } - ret = svc_rdma_post_recv(rdma, GFP_KERNEL); - if (ret) - goto err1; ret = svc_rdma_send_reply_msg(rdma, rdma_argp, rdma_resp, rqstp, wr_lst, rp_ch); if (ret < 0) @@ -687,9 +684,6 @@ int svc_rdma_sendto(struct svc_rqst *rqstp) if (ret != -E2BIG && ret != -EINVAL) goto err1; - ret = svc_rdma_post_recv(rdma, GFP_KERNEL); - if (ret) - goto err1; ret = svc_rdma_send_error_msg(rdma, rdma_resp, rqstp); if (ret < 0) goto err0; diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 46ec069150d50f..9ad12a215b514b 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c @@ -58,6 +58,7 @@ #define RPCDBG_FACILITY RPCDBG_SVCXPRT +static int svc_rdma_post_recv(struct svcxprt_rdma *xprt); static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *, int); static struct svc_xprt *svc_rdma_create(struct svc_serv *serv, struct net *net, @@ -320,6 +321,8 @@ static void svc_rdma_wc_receive(struct ib_cq *cq, struct ib_wc *wc) list_add_tail(&ctxt->list, &xprt->sc_rq_dto_q); spin_unlock(&xprt->sc_rq_dto_lock); + svc_rdma_post_recv(xprt); + set_bit(XPT_DATA, &xprt->sc_xprt.xpt_flags); if (test_bit(RDMAXPRT_CONN_PENDING, &xprt->sc_flags)) goto out; @@ -404,7 +407,8 @@ static struct svcxprt_rdma *rdma_create_xprt(struct svc_serv *serv, return cma_xprt; } -int svc_rdma_post_recv(struct svcxprt_rdma *xprt, gfp_t flags) +static int +svc_rdma_post_recv(struct svcxprt_rdma *xprt) { struct ib_recv_wr recv_wr, *bad_recv_wr; struct svc_rdma_op_ctxt *ctxt; @@ -423,7 +427,7 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt, gfp_t flags) pr_err("svcrdma: Too many sges (%d)\n", sge_no); goto err_put_ctxt; } - page = alloc_page(flags); + page = alloc_page(GFP_KERNEL); if (!page) goto err_put_ctxt; ctxt->pages[sge_no] = page; @@ -459,21 +463,6 @@ int svc_rdma_post_recv(struct svcxprt_rdma *xprt, gfp_t flags) return -ENOMEM; } -int svc_rdma_repost_recv(struct svcxprt_rdma *xprt, gfp_t flags) -{ - int ret = 0; - - ret = svc_rdma_post_recv(xprt, flags); - if (ret) { - pr_err("svcrdma: could not post a receive buffer, err=%d.\n", - ret); - pr_err("svcrdma: closing transport %p.\n", xprt); - set_bit(XPT_CLOSE, &xprt->sc_xprt.xpt_flags); - ret = -ENOTCONN; - } - return ret; -} - static void svc_rdma_parse_connect_private(struct svcxprt_rdma *newxprt, struct rdma_conn_param *param) @@ -833,7 +822,7 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) /* Post receive buffers */ for (i = 0; i < newxprt->sc_max_requests; i++) { - ret = svc_rdma_post_recv(newxprt, GFP_KERNEL); + ret = svc_rdma_post_recv(newxprt); if (ret) { dprintk("svcrdma: failure posting receive buffers\n"); goto errout; From af87fae7c1cd9c3f1caf8e3f12067c5a951280b0 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 22 Jan 2018 21:31:43 +0100 Subject: [PATCH 023/237] pcmcia: remove mailing list, update MAINTAINERS In recent years, the linux-pcmcia mailing list gained a pretty bad signal-to-noise ratio. It does not seem worth the hassle to keep it any longer. Thanks to David for hosting the list for the last couple of years! Acked-by: David Woodhouse CC: Russell King Signed-off-by: Dominik Brodowski --- MAINTAINERS | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index e3581413420c61..3dc821ddfc6be0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10641,11 +10641,9 @@ S: Maintained F: drivers/pci/dwc/*spear* PCMCIA SUBSYSTEM -P: Linux PCMCIA Team -L: linux-pcmcia@lists.infradead.org -W: http://lists.infradead.org/mailman/listinfo/linux-pcmcia +M: Dominik Brodowski T: git git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia.git -S: Maintained +S: Odd Fixes F: Documentation/pcmcia/ F: tools/pcmcia/ F: drivers/pcmcia/ From 3490a69bdd815ab38230c993b3a6e02937237ac8 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Mon, 22 Jan 2018 21:36:27 +0100 Subject: [PATCH 024/237] pcmcia: use proper printk format for resource Even though it is just in a dev_dbg statement, improve the printk format to use %pr instead of plain %p. Signed-off-by: Dominik Brodowski --- drivers/pcmcia/rsrc_nonstatic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c index 5ef7b46a25786b..49377d502b740d 100644 --- a/drivers/pcmcia/rsrc_nonstatic.c +++ b/drivers/pcmcia/rsrc_nonstatic.c @@ -367,7 +367,7 @@ static int do_validate_mem(struct pcmcia_socket *s, } } - dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %p %p %u %u %u", + dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %pr %pr %u %u %u", base, base+size-1, res1, res2, ret, info1, info2); free_region(res2); From d3fdd701248290b511683ff8d348073295f07833 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Thu, 1 Jun 2017 16:17:10 +0530 Subject: [PATCH 025/237] pcmcia: soc_common: Handle return value of clk_prepare_enable clk_prepare_enable() can fail here and we must check its return value. Signed-off-by: Arvind Yadav CC: Russell King Signed-off-by: Dominik Brodowski --- drivers/pcmcia/soc_common.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c index 764650eb889799..c5f2344c189bad 100644 --- a/drivers/pcmcia/soc_common.c +++ b/drivers/pcmcia/soc_common.c @@ -191,12 +191,16 @@ static int soc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret = 0, i; - clk_prepare_enable(skt->clk); + ret = clk_prepare_enable(skt->clk); + if (ret) + return ret; if (skt->ops->hw_init) { ret = skt->ops->hw_init(skt); - if (ret) + if (ret) { + clk_disable_unprepare(skt->clk); return ret; + } } for (i = 0; i < ARRAY_SIZE(skt->stat); i++) { From 2e584bce706a42a5dd86e9ac9f39900a20ba5175 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Mon, 15 Jan 2018 17:24:51 +0100 Subject: [PATCH 026/237] rbd: obj_request->completion is unused Signed-off-by: Ilya Dryomov --- drivers/block/rbd.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index cc93522a6d419d..89d00038b7ce0f 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -281,7 +281,6 @@ struct rbd_obj_request { int result; rbd_obj_callback_t callback; - struct completion completion; struct kref kref; }; @@ -1734,10 +1733,7 @@ static void rbd_obj_request_complete(struct rbd_obj_request *obj_request) { dout("%s: obj %p cb %p\n", __func__, obj_request, obj_request->callback); - if (obj_request->callback) - obj_request->callback(obj_request); - else - complete_all(&obj_request->completion); + obj_request->callback(obj_request); } static void rbd_obj_request_error(struct rbd_obj_request *obj_request, int err) @@ -2013,7 +2009,6 @@ rbd_obj_request_create(enum obj_request_type type) obj_request->which = BAD_WHICH; obj_request->type = type; INIT_LIST_HEAD(&obj_request->links); - init_completion(&obj_request->completion); kref_init(&obj_request->kref); dout("%s %p\n", __func__, obj_request); From a0c5895b27f6bbf8aa20a2c640845fc261740051 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Mon, 22 Jan 2018 16:03:06 +0100 Subject: [PATCH 027/237] rbd: use kmem_cache_zalloc() in rbd_img_request_create() Signed-off-by: Ilya Dryomov --- drivers/block/rbd.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 89d00038b7ce0f..7646a2d3119c12 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -2124,15 +2124,13 @@ static struct rbd_img_request *rbd_img_request_create( { struct rbd_img_request *img_request; - img_request = kmem_cache_alloc(rbd_img_request_cache, GFP_NOIO); + img_request = kmem_cache_zalloc(rbd_img_request_cache, GFP_NOIO); if (!img_request) return NULL; - img_request->rq = NULL; img_request->rbd_dev = rbd_dev; img_request->offset = offset; img_request->length = length; - img_request->flags = 0; if (op_type == OBJ_OP_DISCARD) { img_request_discard_set(img_request); img_request->snapc = snapc; @@ -2144,11 +2142,8 @@ static struct rbd_img_request *rbd_img_request_create( } if (rbd_dev_parent_get(rbd_dev)) img_request_layered_set(img_request); + spin_lock_init(&img_request->completion_lock); - img_request->next_completion = 0; - img_request->callback = NULL; - img_request->result = 0; - img_request->obj_request_count = 0; INIT_LIST_HEAD(&img_request->obj_requests); kref_init(&img_request->kref); From d98f153f1a116f79e636edd34b4fec07e49ae9b2 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Thu, 18 Jan 2018 16:32:00 +0100 Subject: [PATCH 028/237] rbd: don't NULL out ->obj_request in rbd_img_obj_parent_read_full() If rbd_img_request_submit() fails, parent_request->obj_request is NULLed out, triggering an assert in rbd_obj_request_put(): rbd_img_request_put(parent_request) rbd_parent_request_destroy rbd_obj_request_put(NULL) Just remove it -- parent_request->obj_request will be put in rbd_parent_request_destroy(). Signed-off-by: Ilya Dryomov --- drivers/block/rbd.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 7646a2d3119c12..4a886d8c4a3c46 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -2682,8 +2682,6 @@ static int rbd_img_obj_parent_read_full(struct rbd_obj_request *obj_request) parent_request->copyup_pages = NULL; parent_request->copyup_page_count = 0; - parent_request->obj_request = NULL; - rbd_obj_request_put(obj_request); out_err: if (pages) ceph_release_page_vector(pages, page_count); From e573427a440fd67d3f522357d7ac901d59281948 Mon Sep 17 00:00:00 2001 From: Ilya Dryomov Date: Tue, 16 Jan 2018 15:41:54 +0100 Subject: [PATCH 029/237] rbd: whitelist RBD_FEATURE_OPERATIONS feature bit This feature bit restricts older clients from performing certain maintenance operations against an image (e.g. clone, snap create). krbd does not perform maintenance operations. Cc: stable@vger.kernel.org Signed-off-by: Ilya Dryomov Reviewed-by: Jason Dillaman --- drivers/block/rbd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 4a886d8c4a3c46..8e40da0937667a 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c @@ -124,11 +124,13 @@ static int atomic_dec_return_safe(atomic_t *v) #define RBD_FEATURE_STRIPINGV2 (1ULL<<1) #define RBD_FEATURE_EXCLUSIVE_LOCK (1ULL<<2) #define RBD_FEATURE_DATA_POOL (1ULL<<7) +#define RBD_FEATURE_OPERATIONS (1ULL<<8) #define RBD_FEATURES_ALL (RBD_FEATURE_LAYERING | \ RBD_FEATURE_STRIPINGV2 | \ RBD_FEATURE_EXCLUSIVE_LOCK | \ - RBD_FEATURE_DATA_POOL) + RBD_FEATURE_DATA_POOL | \ + RBD_FEATURE_OPERATIONS) /* Features supported by this (client software) implementation. */ From 222b7f90ba3825728fd27e9105aeee7af9576819 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 23 Nov 2017 17:47:15 +0800 Subject: [PATCH 030/237] ceph: voluntarily drop Ax cap for requests that create new inode MDS need to rdlock directory inode's authlock when handling these requests. Voluntarily dropping CEPH_CAP_AUTH_EXCL avoids a cap revoke message. Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/caps.c | 21 +++++++++++++++------ fs/ceph/dir.c | 6 +++--- fs/ceph/file.c | 2 +- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index a14b2c974c9eac..029cab71373102 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -3939,11 +3939,20 @@ int ceph_encode_inode_release(void **p, struct inode *inode, cap = __get_cap_for_mds(ci, mds); if (cap && __cap_is_valid(cap)) { - if (force || - ((cap->issued & drop) && - (cap->issued & unless) == 0)) { - if ((cap->issued & drop) && - (cap->issued & unless) == 0) { + unless &= cap->issued; + if (unless) { + if (unless & CEPH_CAP_AUTH_EXCL) + drop &= ~CEPH_CAP_AUTH_SHARED; + if (unless & CEPH_CAP_LINK_EXCL) + drop &= ~CEPH_CAP_LINK_SHARED; + if (unless & CEPH_CAP_XATTR_EXCL) + drop &= ~CEPH_CAP_XATTR_SHARED; + if (unless & CEPH_CAP_FILE_EXCL) + drop &= ~CEPH_CAP_FILE_SHARED; + } + + if (force || (cap->issued & drop)) { + if (cap->issued & drop) { int wanted = __ceph_caps_wanted(ci); if ((ci->i_ceph_flags & CEPH_I_NODELAY) == 0) wanted |= cap->mds_wanted; @@ -3975,7 +3984,7 @@ int ceph_encode_inode_release(void **p, struct inode *inode, *p += sizeof(*rel); ret = 1; } else { - dout("encode_inode_release %p cap %p %s\n", + dout("encode_inode_release %p cap %p %s (noop)\n", inode, cap, ceph_cap_string(cap->issued)); } } diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 8a5266699b6765..3a60d113aa4e63 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -835,7 +835,7 @@ static int ceph_mknod(struct inode *dir, struct dentry *dentry, set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags); req->r_args.mknod.mode = cpu_to_le32(mode); req->r_args.mknod.rdev = cpu_to_le32(rdev); - req->r_dentry_drop = CEPH_CAP_FILE_SHARED; + req->r_dentry_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_AUTH_EXCL; req->r_dentry_unless = CEPH_CAP_FILE_EXCL; if (acls.pagelist) { req->r_pagelist = acls.pagelist; @@ -887,7 +887,7 @@ static int ceph_symlink(struct inode *dir, struct dentry *dentry, set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags); req->r_dentry = dget(dentry); req->r_num_caps = 2; - req->r_dentry_drop = CEPH_CAP_FILE_SHARED; + req->r_dentry_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_AUTH_EXCL; req->r_dentry_unless = CEPH_CAP_FILE_EXCL; err = ceph_mdsc_do_request(mdsc, dir, req); if (!err && !req->r_reply_info.head->is_dentry) @@ -936,7 +936,7 @@ static int ceph_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) req->r_parent = dir; set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags); req->r_args.mkdir.mode = cpu_to_le32(mode); - req->r_dentry_drop = CEPH_CAP_FILE_SHARED; + req->r_dentry_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_AUTH_EXCL; req->r_dentry_unless = CEPH_CAP_FILE_EXCL; if (acls.pagelist) { req->r_pagelist = acls.pagelist; diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 5c17125f45c786..770dd3b413e4fa 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -396,7 +396,7 @@ int ceph_atomic_open(struct inode *dir, struct dentry *dentry, req->r_dentry = dget(dentry); req->r_num_caps = 2; if (flags & O_CREAT) { - req->r_dentry_drop = CEPH_CAP_FILE_SHARED; + req->r_dentry_drop = CEPH_CAP_FILE_SHARED | CEPH_CAP_AUTH_EXCL; req->r_dentry_unless = CEPH_CAP_FILE_EXCL; if (acls.pagelist) { req->r_pagelist = acls.pagelist; From d19a0b540182a742338d88f6501e4f29a30d7541 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 23 Nov 2017 17:59:13 +0800 Subject: [PATCH 031/237] ceph: voluntarily drop Lx cap for link/rename requests MDS need to xlock inode's linklock when handling link/rename requests. Voluntarily dropping CEPH_CAP_AUTH_EXCL avoids a cap revoke message. Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/dir.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 3a60d113aa4e63..aa2618f12cb7ab 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -983,7 +983,7 @@ static int ceph_link(struct dentry *old_dentry, struct inode *dir, req->r_dentry_drop = CEPH_CAP_FILE_SHARED; req->r_dentry_unless = CEPH_CAP_FILE_EXCL; /* release LINK_SHARED on source inode (mds will lock it) */ - req->r_old_inode_drop = CEPH_CAP_LINK_SHARED; + req->r_old_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL; err = ceph_mdsc_do_request(mdsc, dir, req); if (err) { d_drop(dentry); @@ -1096,7 +1096,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, req->r_dentry_drop = CEPH_CAP_FILE_SHARED; req->r_dentry_unless = CEPH_CAP_FILE_EXCL; /* release LINK_RDCACHE on source inode (mds will lock it) */ - req->r_old_inode_drop = CEPH_CAP_LINK_SHARED; + req->r_old_inode_drop = CEPH_CAP_LINK_SHARED | CEPH_CAP_LINK_EXCL; if (d_really_is_positive(new_dentry)) req->r_inode_drop = drop_caps_for_unlink(d_inode(new_dentry)); err = ceph_mdsc_do_request(mdsc, old_dir, req); From be70489eff41a84f26b1d772b595cc043e0edeb6 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 23 Nov 2017 18:22:06 +0800 Subject: [PATCH 032/237] ceph: properly drop caps for setattr request For CEPH_SETATTR_ATIME, MDS needs to xlock filelock, Fsxrw caps are not allowed for xlocked filelock. For CEPH_SETATTR_SIZE request that truncates file to smaller size, MDS needs to xlock filelock, Fsxrw caps are not allowed for xlocked filelock. Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/inode.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index ab81652198c48e..666ad10e2b8532 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -2000,8 +2000,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr) ceph_encode_timespec(&req->r_args.setattr.atime, &attr->ia_atime); mask |= CEPH_SETATTR_ATIME; - release |= CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_RD | - CEPH_CAP_FILE_WR; + release |= CEPH_CAP_FILE_SHARED | + CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR; } } if (ia_valid & ATTR_MTIME) { @@ -2022,8 +2022,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr) ceph_encode_timespec(&req->r_args.setattr.mtime, &attr->ia_mtime); mask |= CEPH_SETATTR_MTIME; - release |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_RD | - CEPH_CAP_FILE_WR; + release |= CEPH_CAP_FILE_SHARED | + CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR; } } if (ia_valid & ATTR_SIZE) { @@ -2041,8 +2041,8 @@ int __ceph_setattr(struct inode *inode, struct iattr *attr) req->r_args.setattr.old_size = cpu_to_le64(inode->i_size); mask |= CEPH_SETATTR_SIZE; - release |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_RD | - CEPH_CAP_FILE_WR; + release |= CEPH_CAP_FILE_SHARED | CEPH_CAP_FILE_EXCL | + CEPH_CAP_FILE_RD | CEPH_CAP_FILE_WR; } } From 87c91a965aa28809888cbae3b2de35a486ed7107 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Thu, 23 Nov 2017 18:28:16 +0800 Subject: [PATCH 033/237] ceph: voluntarily drop Fx cap for readdir request MDS need to rdlock directory inode's filelock when handling readdir request. Voluntarily dropping CEPH_CAP_AUTH_EXCL avoids a cap revoke message. Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/dir.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index aa2618f12cb7ab..9fde02cd5568d8 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -381,6 +381,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) if (op == CEPH_MDS_OP_READDIR) { req->r_direct_hash = ceph_frag_value(frag); __set_bit(CEPH_MDS_R_DIRECT_IS_HASH, &req->r_req_flags); + req->r_inode_drop = CEPH_CAP_FILE_EXCL; } if (fi->last_name) { req->r_path2 = kstrdup(fi->last_name, GFP_KERNEL); From 8d8f371c83838d74bc3d0708afba631488a12201 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 24 Nov 2017 11:51:32 +0800 Subject: [PATCH 034/237] ceph: cleanup traceless reply handling for rename ceph_fill_trace() already calls ceph_invalidate_dir_request() for traceless reply. No need to duplicate the code in ceph_rename(). Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/dir.c | 9 --------- fs/ceph/mds_client.c | 9 ++++++--- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 9fde02cd5568d8..64afa46b211ff4 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -1107,16 +1107,7 @@ static int ceph_rename(struct inode *old_dir, struct dentry *old_dentry, * do_request, above). If there is no trace, we need * to do it here. */ - - /* d_move screws up sibling dentries' offsets */ - ceph_dir_clear_complete(old_dir); - ceph_dir_clear_complete(new_dir); - d_move(old_dentry, new_dentry); - - /* ensure target dentry is invalidated, despite - rehashing bug in vfs_rename_dir */ - ceph_invalidate_dentry_lease(new_dentry); } ceph_mdsc_put_request(req); return err; diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 1b468250e94752..251dc44d84a04f 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -2438,11 +2438,14 @@ int ceph_mdsc_do_request(struct ceph_mds_client *mdsc, */ void ceph_invalidate_dir_request(struct ceph_mds_request *req) { - struct inode *inode = req->r_parent; + struct inode *dir = req->r_parent; + struct inode *old_dir = req->r_old_dentry_dir; - dout("invalidate_dir_request %p (complete, lease(s))\n", inode); + dout("invalidate_dir_request %p %p (complete, lease(s))\n", dir, old_dir); - ceph_dir_clear_complete(inode); + ceph_dir_clear_complete(dir); + if (old_dir) + ceph_dir_clear_complete(old_dir); if (req->r_dentry) ceph_invalidate_dentry_lease(req->r_dentry); if (req->r_old_dentry) From 97aeb6bf988e0830fd80dca724fd89526b3f35e4 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 27 Nov 2017 10:47:46 +0800 Subject: [PATCH 035/237] ceph: use atomic_t for ceph_inode_info::i_shared_gen It allows accessing i_shared_gen without holding i_ceph_lock. It is preparation for later patch. Signed-off-by: "Yan, Zheng" Acked-by: Jeff Layton Signed-off-by: Ilya Dryomov --- fs/ceph/caps.c | 2 +- fs/ceph/dir.c | 14 +++++++------- fs/ceph/inode.c | 4 ++-- fs/ceph/super.h | 5 +++-- 4 files changed, 13 insertions(+), 12 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 029cab71373102..57120e3d44de2f 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -498,7 +498,7 @@ static void __check_cap_issue(struct ceph_inode_info *ci, struct ceph_cap *cap, */ if ((issued & CEPH_CAP_FILE_SHARED) != (had & CEPH_CAP_FILE_SHARED)) { if (issued & CEPH_CAP_FILE_SHARED) - ci->i_shared_gen++; + atomic_inc(&ci->i_shared_gen); if (S_ISDIR(ci->vfs_inode.i_mode)) { dout(" marking %p NOT complete\n", &ci->vfs_inode); __ceph_dir_clear_complete(ci); diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index 64afa46b211ff4..d671d587682823 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -173,7 +173,7 @@ __dcache_find_get_entry(struct dentry *parent, u64 idx, * the MDS if/when the directory is modified). */ static int __dcache_readdir(struct file *file, struct dir_context *ctx, - u32 shared_gen) + int shared_gen) { struct ceph_file_info *fi = file->private_data; struct dentry *parent = file->f_path.dentry; @@ -184,7 +184,7 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx, u64 idx = 0; int err = 0; - dout("__dcache_readdir %p v%u at %llx\n", dir, shared_gen, ctx->pos); + dout("__dcache_readdir %p v%u at %llx\n", dir, (unsigned)shared_gen, ctx->pos); /* search start position */ if (ctx->pos > 2) { @@ -333,7 +333,7 @@ static int ceph_readdir(struct file *file, struct dir_context *ctx) ceph_snap(inode) != CEPH_SNAPDIR && __ceph_dir_is_complete_ordered(ci) && __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1)) { - u32 shared_gen = ci->i_shared_gen; + int shared_gen = atomic_read(&ci->i_shared_gen); spin_unlock(&ci->i_ceph_lock); err = __dcache_readdir(file, ctx, shared_gen); if (err != -EAGAIN) @@ -751,7 +751,7 @@ static struct dentry *ceph_lookup(struct inode *dir, struct dentry *dentry, spin_unlock(&ci->i_ceph_lock); dout(" dir %p complete, -ENOENT\n", dir); d_add(dentry, NULL); - di->lease_shared_gen = ci->i_shared_gen; + di->lease_shared_gen = atomic_read(&ci->i_shared_gen); return NULL; } spin_unlock(&ci->i_ceph_lock); @@ -1191,12 +1191,12 @@ static int dir_lease_is_valid(struct inode *dir, struct dentry *dentry) int valid = 0; spin_lock(&ci->i_ceph_lock); - if (ci->i_shared_gen == di->lease_shared_gen) + if (atomic_read(&ci->i_shared_gen) == di->lease_shared_gen) valid = __ceph_caps_issued_mask(ci, CEPH_CAP_FILE_SHARED, 1); spin_unlock(&ci->i_ceph_lock); dout("dir_lease_is_valid dir %p v%u dentry %p v%u = %d\n", - dir, (unsigned)ci->i_shared_gen, dentry, - (unsigned)di->lease_shared_gen, valid); + dir, (unsigned)atomic_read(&ci->i_shared_gen), + dentry, (unsigned)di->lease_shared_gen, valid); return valid; } diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 666ad10e2b8532..6d02528eb61fe8 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -494,7 +494,7 @@ struct inode *ceph_alloc_inode(struct super_block *sb) ci->i_wrbuffer_ref = 0; ci->i_wrbuffer_ref_head = 0; atomic_set(&ci->i_filelock_ref, 0); - ci->i_shared_gen = 0; + atomic_set(&ci->i_shared_gen, 0); ci->i_rdcache_gen = 0; ci->i_rdcache_revoking = 0; @@ -1041,7 +1041,7 @@ static void update_dentry_lease(struct dentry *dentry, if (ceph_snap(dir) != CEPH_NOSNAP) goto out_unlock; - di->lease_shared_gen = ceph_inode(dir)->i_shared_gen; + di->lease_shared_gen = atomic_read(&ceph_inode(dir)->i_shared_gen); if (duration == 0) goto out_unlock; diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 2beeec07fa76ce..75701c199b2b48 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -256,7 +256,8 @@ struct ceph_inode_xattr { */ struct ceph_dentry_info { struct ceph_mds_session *lease_session; - u32 lease_gen, lease_shared_gen; + int lease_shared_gen; + u32 lease_gen; u32 lease_seq; unsigned long lease_renew_after, lease_renew_from; struct list_head lru; @@ -353,7 +354,7 @@ struct ceph_inode_info { int i_rd_ref, i_rdcache_ref, i_wr_ref, i_wb_ref; int i_wrbuffer_ref, i_wrbuffer_ref_head; atomic_t i_filelock_ref; - u32 i_shared_gen; /* increment each time we get FILE_SHARED */ + atomic_t i_shared_gen; /* increment each time we get FILE_SHARED */ u32 i_rdcache_gen; /* incremented each time we get FILE_CACHE. */ u32 i_rdcache_revoking; /* RDCACHE gen to async invalidate, if any */ From 5495c2d04f85da09512f5f346ed24dc0261d905d Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 27 Nov 2017 11:23:48 +0800 Subject: [PATCH 036/237] ceph: avoid dereferencing invalid pointer during cached readdir Readdir cache keeps array of dentry pointers in page cache. If any dentry in readdir cache gets pruned, ceph_d_prune() disables readdir cache for later readdir syscall. The problem is that ceph_d_prune() ignores unhashed dentry. Ideally MDS should have already revoked CEPH_CAP_FILE_SHARED (which also disables readdir cache) when dentry gets unhashed. But if it is somehow MDS does not properly revoke CEPH_CAP_FILE_SHARED and the unhashed dentry gets pruned later, ceph_d_prune() will not disable readdir cache, later readdir may reference invalid dentry pointer. The fix is make ceph_d_prune() do extra check for unhashed dentry. Disable readdir cache if the unhashed dentry is still referenced by readdir cache. Another fix in this patch is handle d_splice_alias(). If a dentry gets spliced into new parent dentry, treat it as if it was pruned (call ceph_d_prune() for it). Signed-off-by: "Yan, Zheng" Acked-by: Jeff Layton Signed-off-by: Ilya Dryomov --- fs/ceph/dir.c | 45 ++++++++++++++++++++++++++++++++------------- fs/ceph/inode.c | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 66 insertions(+), 19 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index d671d587682823..0c4346806e17a6 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -231,11 +231,17 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx, goto out; } - di = ceph_dentry(dentry); spin_lock(&dentry->d_lock); - if (di->lease_shared_gen == shared_gen && - d_really_is_positive(dentry) && - fpos_cmp(ctx->pos, di->offset) <= 0) { + di = ceph_dentry(dentry); + if (d_unhashed(dentry) || + d_really_is_negative(dentry) || + di->lease_shared_gen != shared_gen) { + spin_unlock(&dentry->d_lock); + dput(dentry); + err = -EAGAIN; + goto out; + } + if (fpos_cmp(ctx->pos, di->offset) <= 0) { emit_dentry = true; } spin_unlock(&dentry->d_lock); @@ -1324,24 +1330,37 @@ static void ceph_d_release(struct dentry *dentry) */ static void ceph_d_prune(struct dentry *dentry) { - dout("ceph_d_prune %p\n", dentry); + struct ceph_inode_info *dir_ci; + struct ceph_dentry_info *di; + + dout("ceph_d_prune %pd %p\n", dentry, dentry); /* do we have a valid parent? */ if (IS_ROOT(dentry)) return; - /* if we are not hashed, we don't affect dir's completeness */ - if (d_unhashed(dentry)) + /* we hold d_lock, so d_parent is stable */ + dir_ci = ceph_inode(d_inode(dentry->d_parent)); + if (dir_ci->i_vino.snap == CEPH_SNAPDIR) return; - if (ceph_snap(d_inode(dentry->d_parent)) == CEPH_SNAPDIR) + /* who calls d_delete() should also disable dcache readdir */ + if (d_really_is_negative(dentry)) return; - /* - * we hold d_lock, so d_parent is stable, and d_fsdata is never - * cleared until d_release - */ - ceph_dir_clear_complete(d_inode(dentry->d_parent)); + /* d_fsdata does not get cleared until d_release */ + if (!d_unhashed(dentry)) { + __ceph_dir_clear_complete(dir_ci); + return; + } + + /* Disable dcache readdir just in case that someone called d_drop() + * or d_invalidate(), but MDS didn't revoke CEPH_CAP_FILE_SHARED + * properly (dcache readdir is still enabled) */ + di = ceph_dentry(dentry); + if (di->offset > 0 && + di->lease_shared_gen == atomic_read(&dir_ci->i_shared_gen)) + __ceph_dir_clear_ordered(dir_ci); } /* diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c index 6d02528eb61fe8..c6ec5aa4610027 100644 --- a/fs/ceph/inode.c +++ b/fs/ceph/inode.c @@ -1080,6 +1080,27 @@ static struct dentry *splice_dentry(struct dentry *dn, struct inode *in) BUG_ON(d_inode(dn)); + if (S_ISDIR(in->i_mode)) { + /* If inode is directory, d_splice_alias() below will remove + * 'realdn' from its origin parent. We need to ensure that + * origin parent's readdir cache will not reference 'realdn' + */ + realdn = d_find_any_alias(in); + if (realdn) { + struct ceph_dentry_info *di = ceph_dentry(realdn); + spin_lock(&realdn->d_lock); + + realdn->d_op->d_prune(realdn); + + di->time = jiffies; + di->lease_shared_gen = 0; + di->offset = 0; + + spin_unlock(&realdn->d_lock); + dput(realdn); + } + } + /* dn must be unhashed */ if (!d_unhashed(dn)) d_drop(dn); @@ -1295,8 +1316,8 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) if (!rinfo->head->is_target) { dout("fill_trace null dentry\n"); if (d_really_is_positive(dn)) { - ceph_dir_clear_ordered(dir); dout("d_delete %p\n", dn); + ceph_dir_clear_ordered(dir); d_delete(dn); } else if (have_lease) { if (d_unhashed(dn)) @@ -1323,7 +1344,6 @@ int ceph_fill_trace(struct super_block *sb, struct ceph_mds_request *req) dout(" %p links to %p %llx.%llx, not %llx.%llx\n", dn, d_inode(dn), ceph_vinop(d_inode(dn)), ceph_vinop(in)); - ceph_dir_clear_ordered(dir); d_invalidate(dn); have_lease = false; } @@ -1573,9 +1593,19 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, } else if (d_really_is_positive(dn) && (ceph_ino(d_inode(dn)) != tvino.ino || ceph_snap(d_inode(dn)) != tvino.snap)) { + struct ceph_dentry_info *di = ceph_dentry(dn); dout(" dn %p points to wrong inode %p\n", dn, d_inode(dn)); - __ceph_dir_clear_ordered(ci); + + spin_lock(&dn->d_lock); + if (di->offset > 0 && + di->lease_shared_gen == + atomic_read(&ci->i_shared_gen)) { + __ceph_dir_clear_ordered(ci); + di->offset = 0; + } + spin_unlock(&dn->d_lock); + d_delete(dn); dput(dn); goto retry_lookup; @@ -1600,9 +1630,7 @@ int ceph_readdir_prepopulate(struct ceph_mds_request *req, &req->r_caps_reservation); if (ret < 0) { pr_err("fill_inode badness on %p\n", in); - if (d_really_is_positive(dn)) - __ceph_dir_clear_ordered(ci); - else + if (d_really_is_negative(dn)) iput(in); d_drop(dn); err = ret; From 5d988308283ecf062fa88f20ae05c52cce0bcdca Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 15 Dec 2017 11:15:36 +0800 Subject: [PATCH 037/237] ceph: track read contexts in ceph_file_info Previously ceph_read_iter() uses current->journal to pass context info to ceph_readpages(), so that ceph_readpages() can distinguish read(2) from readahead(2)/fadvise(2)/madvise(2). The problem is that page fault can happen when copying data to userspace memory. Page fault may call other filesystem's page_mkwrite() if the userspace memory is mapped to a file. The later filesystem may also want to use current->journal. The fix is define a on-stack data structure in ceph_read_iter(), add it to context list in ceph_file_info. ceph_readpages() searches the list, find if there is a context belongs to current thread. Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/addr.c | 19 ++++++++++++------- fs/ceph/file.c | 10 ++++++++-- fs/ceph/super.h | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index dbf07051aacd26..78a1208b878e5c 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -299,7 +299,8 @@ static void finish_read(struct ceph_osd_request *req) * start an async read(ahead) operation. return nr_pages we submitted * a read for on success, or negative error code. */ -static int start_read(struct inode *inode, struct list_head *page_list, int max) +static int start_read(struct inode *inode, struct ceph_rw_context *rw_ctx, + struct list_head *page_list, int max) { struct ceph_osd_client *osdc = &ceph_inode_to_client(inode)->client->osdc; @@ -316,7 +317,7 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max) int got = 0; int ret = 0; - if (!current->journal_info) { + if (!rw_ctx) { /* caller of readpages does not hold buffer and read caps * (fadvise, madvise and readahead cases) */ int want = CEPH_CAP_FILE_CACHE; @@ -437,6 +438,8 @@ static int ceph_readpages(struct file *file, struct address_space *mapping, { struct inode *inode = file_inode(file); struct ceph_fs_client *fsc = ceph_inode_to_client(inode); + struct ceph_file_info *ci = file->private_data; + struct ceph_rw_context *rw_ctx; int rc = 0; int max = 0; @@ -449,11 +452,12 @@ static int ceph_readpages(struct file *file, struct address_space *mapping, if (rc == 0) goto out; + rw_ctx = ceph_find_rw_context(ci); max = fsc->mount_options->rsize >> PAGE_SHIFT; - dout("readpages %p file %p nr_pages %d max %d\n", - inode, file, nr_pages, max); + dout("readpages %p file %p ctx %p nr_pages %d max %d\n", + inode, file, rw_ctx, nr_pages, max); while (!list_empty(page_list)) { - rc = start_read(inode, page_list, max); + rc = start_read(inode, rw_ctx, page_list, max); if (rc < 0) goto out; } @@ -1450,9 +1454,10 @@ static int ceph_filemap_fault(struct vm_fault *vmf) if ((got & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) || ci->i_inline_version == CEPH_INLINE_NONE) { - current->journal_info = vma->vm_file; + CEPH_DEFINE_RW_CONTEXT(rw_ctx, got); + ceph_add_rw_context(fi, &rw_ctx); ret = filemap_fault(vmf); - current->journal_info = NULL; + ceph_del_rw_context(fi, &rw_ctx); } else ret = -EAGAIN; diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 770dd3b413e4fa..6639926eed4e84 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -181,6 +181,10 @@ static int ceph_init_file(struct inode *inode, struct file *file, int fmode) return -ENOMEM; } cf->fmode = fmode; + + spin_lock_init(&cf->rw_contexts_lock); + INIT_LIST_HEAD(&cf->rw_contexts); + cf->next_offset = 2; cf->readdir_cache_idx = -1; file->private_data = cf; @@ -464,6 +468,7 @@ int ceph_release(struct inode *inode, struct file *file) ceph_mdsc_put_request(cf->last_readdir); kfree(cf->last_name); kfree(cf->dir_info); + WARN_ON(!list_empty(&cf->rw_contexts)); kmem_cache_free(ceph_file_cachep, cf); /* wake up anyone waiting for caps on this inode */ @@ -1199,12 +1204,13 @@ static ssize_t ceph_read_iter(struct kiocb *iocb, struct iov_iter *to) retry_op = READ_INLINE; } } else { + CEPH_DEFINE_RW_CONTEXT(rw_ctx, got); dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n", inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len, ceph_cap_string(got)); - current->journal_info = filp; + ceph_add_rw_context(fi, &rw_ctx); ret = generic_file_read_iter(iocb, to); - current->journal_info = NULL; + ceph_del_rw_context(fi, &rw_ctx); } dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n", inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret); diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 75701c199b2b48..601100da738f86 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -669,6 +669,9 @@ struct ceph_file_info { short fmode; /* initialized on open */ short flags; /* CEPH_F_* */ + spinlock_t rw_contexts_lock; + struct list_head rw_contexts; + /* readdir: position within the dir */ u32 frag; struct ceph_mds_request *last_readdir; @@ -685,6 +688,49 @@ struct ceph_file_info { int dir_info_len; }; +struct ceph_rw_context { + struct list_head list; + struct task_struct *thread; + int caps; +}; + +#define CEPH_DEFINE_RW_CONTEXT(_name, _caps) \ + struct ceph_rw_context _name = { \ + .thread = current, \ + .caps = _caps, \ + } + +static inline void ceph_add_rw_context(struct ceph_file_info *cf, + struct ceph_rw_context *ctx) +{ + spin_lock(&cf->rw_contexts_lock); + list_add(&ctx->list, &cf->rw_contexts); + spin_unlock(&cf->rw_contexts_lock); +} + +static inline void ceph_del_rw_context(struct ceph_file_info *cf, + struct ceph_rw_context *ctx) +{ + spin_lock(&cf->rw_contexts_lock); + list_del(&ctx->list); + spin_unlock(&cf->rw_contexts_lock); +} + +static inline struct ceph_rw_context* +ceph_find_rw_context(struct ceph_file_info *cf) +{ + struct ceph_rw_context *ctx, *found = NULL; + spin_lock(&cf->rw_contexts_lock); + list_for_each_entry(ctx, &cf->rw_contexts, list) { + if (ctx->thread == current) { + found = ctx; + break; + } + } + spin_unlock(&cf->rw_contexts_lock); + return found; +} + struct ceph_readdir_cache_control { struct page *page; struct dentry **dentries; From 314c4737a45dd4447eac6d313e3715b25785f58b Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Fri, 15 Dec 2017 16:57:40 +0800 Subject: [PATCH 038/237] ceph: fix un-balanced fsc->writeback_count update Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/addr.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index 78a1208b878e5c..b4336b42ce3bb1 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -578,7 +578,6 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) struct ceph_fs_client *fsc; struct ceph_snap_context *snapc, *oldest; loff_t page_off = page_offset(page); - long writeback_stat; int err, len = PAGE_SIZE; struct ceph_writeback_ctl ceph_wbc; @@ -619,8 +618,7 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) dout("writepage %p page %p index %lu on %llu~%u snapc %p seq %lld\n", inode, page, page->index, page_off, len, snapc, snapc->seq); - writeback_stat = atomic_long_inc_return(&fsc->writeback_count); - if (writeback_stat > + if (atomic_long_inc_return(&fsc->writeback_count) > CONGESTION_ON_THRESH(fsc->mount_options->congestion_kb)) set_bdi_congested(inode_to_bdi(inode), BLK_RW_ASYNC); @@ -655,6 +653,11 @@ static int writepage_nounlock(struct page *page, struct writeback_control *wbc) end_page_writeback(page); ceph_put_wrbuffer_cap_refs(ci, 1, snapc); ceph_put_snap_context(snapc); /* page's reference */ + + if (atomic_long_dec_return(&fsc->writeback_count) < + CONGESTION_OFF_THRESH(fsc->mount_options->congestion_kb)) + clear_bdi_congested(inode_to_bdi(inode), BLK_RW_ASYNC); + return err; } From 7d9c9193b5d0b1b806f453a3baa9bfe7e6fac52d Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Tue, 19 Dec 2017 18:00:54 +0800 Subject: [PATCH 039/237] ceph: fix incorrect snaprealm when adding caps Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/caps.c | 14 +++++++++++++- fs/ceph/snap.c | 8 ++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 57120e3d44de2f..7e09fa8ab0edaf 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -577,18 +577,30 @@ void ceph_add_cap(struct inode *inode, } } - if (!ci->i_snap_realm) { + if (!ci->i_snap_realm || + ((flags & CEPH_CAP_FLAG_AUTH) && + realmino != (u64)-1 && ci->i_snap_realm->ino != realmino)) { /* * add this inode to the appropriate snap realm */ struct ceph_snap_realm *realm = ceph_lookup_snap_realm(mdsc, realmino); if (realm) { + struct ceph_snap_realm *oldrealm = ci->i_snap_realm; + if (oldrealm) { + spin_lock(&oldrealm->inodes_with_caps_lock); + list_del_init(&ci->i_snap_realm_item); + spin_unlock(&oldrealm->inodes_with_caps_lock); + } + spin_lock(&realm->inodes_with_caps_lock); ci->i_snap_realm = realm; list_add(&ci->i_snap_realm_item, &realm->inodes_with_caps); spin_unlock(&realm->inodes_with_caps_lock); + + if (oldrealm) + ceph_put_snap_realm(mdsc, oldrealm); } else { pr_err("ceph_add_cap: couldn't find snap realm %llx\n", realmino); diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c index 8a2ca41e4b97ca..07cf95e6413d77 100644 --- a/fs/ceph/snap.c +++ b/fs/ceph/snap.c @@ -922,13 +922,17 @@ void ceph_handle_snap(struct ceph_mds_client *mdsc, /* * Move the inode to the new realm */ - spin_lock(&realm->inodes_with_caps_lock); + oldrealm = ci->i_snap_realm; + spin_lock(&oldrealm->inodes_with_caps_lock); list_del_init(&ci->i_snap_realm_item); + spin_unlock(&oldrealm->inodes_with_caps_lock); + + spin_lock(&realm->inodes_with_caps_lock); list_add(&ci->i_snap_realm_item, &realm->inodes_with_caps); - oldrealm = ci->i_snap_realm; ci->i_snap_realm = realm; spin_unlock(&realm->inodes_with_caps_lock); + spin_unlock(&ci->i_ceph_lock); ceph_get_snap_realm(mdsc, realm); From d84b37f9fa9b23a46af28d2e9430c87718b6b044 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Wed, 3 Jan 2018 11:16:27 +0800 Subject: [PATCH 040/237] ceph: limit rate of cap import/export error messages Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/caps.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 7e09fa8ab0edaf..f28efaecbb502b 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -3438,7 +3438,14 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex, */ issued = cap->issued; - WARN_ON(issued != cap->implemented); + if (issued != cap->implemented) + pr_err_ratelimited("handle_cap_export: issued != implemented: " + "ino (%llx.%llx) mds%d seq %d mseq %d " + "issued %s implemented %s\n", + ceph_vinop(inode), mds, cap->seq, cap->mseq, + ceph_cap_string(issued), + ceph_cap_string(cap->implemented)); + tcap = __get_cap_for_mds(ci, target); if (tcap) { @@ -3584,12 +3591,13 @@ static void handle_cap_import(struct ceph_mds_client *mdsc, if ((ph->flags & CEPH_CAP_FLAG_AUTH) && (ocap->seq != le32_to_cpu(ph->seq) || ocap->mseq != le32_to_cpu(ph->mseq))) { - pr_err("handle_cap_import: mismatched seq/mseq: " - "ino (%llx.%llx) mds%d seq %d mseq %d " - "importer mds%d has peer seq %d mseq %d\n", - ceph_vinop(inode), peer, ocap->seq, - ocap->mseq, mds, le32_to_cpu(ph->seq), - le32_to_cpu(ph->mseq)); + pr_err_ratelimited("handle_cap_import: " + "mismatched seq/mseq: ino (%llx.%llx) " + "mds%d seq %d mseq %d importer mds%d " + "has peer seq %d mseq %d\n", + ceph_vinop(inode), peer, ocap->seq, + ocap->mseq, mds, le32_to_cpu(ph->seq), + le32_to_cpu(ph->mseq)); } __ceph_remove_cap(ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE)); } From ee612d954fe96612afaa966d8a67b736ba0c571e Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 8 Jan 2018 14:36:25 +0800 Subject: [PATCH 041/237] ceph: delete unreachable code in ceph_check_caps() "revoking & (CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO)" has already been tested before calling try_nonblocking_invalidate() Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/caps.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index f28efaecbb502b..36f8a4bdf8c57c 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -1793,18 +1793,9 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, !tried_invalidate) { dout("check_caps trying to invalidate on %p\n", inode); if (try_nonblocking_invalidate(inode) < 0) { - if (revoking & (CEPH_CAP_FILE_CACHE| - CEPH_CAP_FILE_LAZYIO)) { - dout("check_caps queuing invalidate\n"); - queue_invalidate = true; - ci->i_rdcache_revoking = ci->i_rdcache_gen; - } else { - dout("check_caps failed to invalidate pages\n"); - /* we failed to invalidate pages. check these - caps again later. */ - force_requeue = true; - __cap_set_timeouts(mdsc, ci); - } + dout("check_caps queuing invalidate\n"); + queue_invalidate = true; + ci->i_rdcache_revoking = ci->i_rdcache_gen; } tried_invalidate = true; goto retry_locked; From 0f439c746c8cb370ce3ae1668182b18a5cb12b14 Mon Sep 17 00:00:00 2001 From: "Yan, Zheng" Date: Mon, 8 Jan 2018 14:44:10 +0800 Subject: [PATCH 042/237] ceph: fix race of queuing delayed caps When called with CHECK_CAPS_AUTHONLY flag, ceph_check_caps() only processes auth caps. In that case, it's unsafe to remove inode from mdsc->cap_delay_list, because there can be delayed non-auth caps. Besides, ceph_check_caps() may lock/unlock i_ceph_lock several times, when multiple threads call ceph_check_caps() at the same time. It's possible that one thread calls __cap_delay_requeue(), another thread calls __cap_delay_cancel(). __cap_delay_cancel() should be called at very beginning of ceph_check_caps(), so that it does not race with __cap_delay_requeue(). Signed-off-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/caps.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 36f8a4bdf8c57c..1726ddcf5e34fc 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -902,6 +902,11 @@ int __ceph_caps_mds_wanted(struct ceph_inode_info *ci, bool check) /* * called under i_ceph_lock */ +static int __ceph_is_single_caps(struct ceph_inode_info *ci) +{ + return rb_first(&ci->i_caps) == rb_last(&ci->i_caps); +} + static int __ceph_is_any_caps(struct ceph_inode_info *ci) { return !RB_EMPTY_ROOT(&ci->i_caps); @@ -1715,21 +1720,24 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, int mds = -1; /* keep track of how far we've gone through i_caps list to avoid an infinite loop on retry */ struct rb_node *p; - int delayed = 0, sent = 0, num; - bool is_delayed = flags & CHECK_CAPS_NODELAY; + int delayed = 0, sent = 0; + bool no_delay = flags & CHECK_CAPS_NODELAY; bool queue_invalidate = false; - bool force_requeue = false; bool tried_invalidate = false; /* if we are unmounting, flush any unused caps immediately. */ if (mdsc->stopping) - is_delayed = true; + no_delay = true; spin_lock(&ci->i_ceph_lock); if (ci->i_ceph_flags & CEPH_I_FLUSH) flags |= CHECK_CAPS_FLUSH; + if (!(flags & CHECK_CAPS_AUTHONLY) || + (ci->i_auth_cap && __ceph_is_single_caps(ci))) + __cap_delay_cancel(mdsc, ci); + goto retry_locked; retry: spin_lock(&ci->i_ceph_lock); @@ -1784,7 +1792,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, * have cached pages, but don't want them, then try to invalidate. * If we fail, it's because pages are locked.... try again later. */ - if ((!is_delayed || mdsc->stopping) && + if ((!no_delay || mdsc->stopping) && !S_ISDIR(inode->i_mode) && /* ignore readdir cache */ !(ci->i_wb_ref || ci->i_wrbuffer_ref) && /* no dirty pages... */ inode->i_data.nrpages && /* have cached pages */ @@ -1801,10 +1809,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, goto retry_locked; } - num = 0; for (p = rb_first(&ci->i_caps); p; p = rb_next(p)) { cap = rb_entry(p, struct ceph_cap, ci_node); - num++; /* avoid looping forever */ if (mds >= cap->mds || @@ -1867,7 +1873,7 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, cap->mds_wanted == want) continue; /* nope, all good */ - if (is_delayed) + if (no_delay) goto ack; /* delay? */ @@ -1958,15 +1964,8 @@ void ceph_check_caps(struct ceph_inode_info *ci, int flags, goto retry; /* retake i_ceph_lock and restart our cap scan. */ } - /* - * Reschedule delayed caps release if we delayed anything, - * otherwise cancel. - */ - if (delayed && is_delayed) - force_requeue = true; /* __send_cap delayed release; requeue */ - if (!delayed && !is_delayed) - __cap_delay_cancel(mdsc, ci); - else if (!is_delayed || force_requeue) + /* Reschedule delayed caps release if we delayed anything */ + if (delayed) __cap_delay_requeue(mdsc, ci); spin_unlock(&ci->i_ceph_lock); From e30ee58121e34831b9665934d70dbc72ab0fe2fb Mon Sep 17 00:00:00 2001 From: Zhi Zhang Date: Wed, 24 Jan 2018 21:24:33 +0800 Subject: [PATCH 043/237] ceph: try to allocate enough memory for reserved caps ceph_reserve_caps() may not reserve enough caps under high memory pressure, but it saved the needed caps number that expected to be reserved. When getting caps, crash would happen due to number mismatch. Now we will try to trim more caps when failing to allocate memory for caps need to be reserved, then try again. If still failing to allocate memory, return -ENOMEM. Signed-off-by: Zhi Zhang Reviewed-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/caps.c | 61 ++++++++++++++++++++++++++++++++++++++------ fs/ceph/mds_client.c | 24 ++++++++++++----- fs/ceph/mds_client.h | 3 +++ fs/ceph/super.h | 2 +- 4 files changed, 74 insertions(+), 16 deletions(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 1726ddcf5e34fc..8e66fb0e743d1f 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -154,13 +154,19 @@ void ceph_adjust_min_caps(struct ceph_mds_client *mdsc, int delta) spin_unlock(&mdsc->caps_list_lock); } -void ceph_reserve_caps(struct ceph_mds_client *mdsc, +/* + * Called under mdsc->mutex. + */ +int ceph_reserve_caps(struct ceph_mds_client *mdsc, struct ceph_cap_reservation *ctx, int need) { - int i; + int i, j; struct ceph_cap *cap; int have; int alloc = 0; + int max_caps; + bool trimmed = false; + struct ceph_mds_session *s; LIST_HEAD(newcaps); dout("reserve caps ctx=%p need=%d\n", ctx, need); @@ -179,16 +185,37 @@ void ceph_reserve_caps(struct ceph_mds_client *mdsc, spin_unlock(&mdsc->caps_list_lock); for (i = have; i < need; i++) { +retry: cap = kmem_cache_alloc(ceph_cap_cachep, GFP_NOFS); - if (!cap) - break; + if (!cap) { + if (!trimmed) { + for (j = 0; j < mdsc->max_sessions; j++) { + s = __ceph_lookup_mds_session(mdsc, j); + if (!s) + continue; + mutex_unlock(&mdsc->mutex); + + mutex_lock(&s->s_mutex); + max_caps = s->s_nr_caps - (need - i); + ceph_trim_caps(mdsc, s, max_caps); + mutex_unlock(&s->s_mutex); + + ceph_put_mds_session(s); + mutex_lock(&mdsc->mutex); + } + trimmed = true; + goto retry; + } else { + pr_warn("reserve caps ctx=%p ENOMEM " + "need=%d got=%d\n", + ctx, need, have + alloc); + goto out_nomem; + } + } list_add(&cap->caps_item, &newcaps); alloc++; } - /* we didn't manage to reserve as much as we needed */ - if (have + alloc != need) - pr_warn("reserve caps ctx=%p ENOMEM need=%d got=%d\n", - ctx, need, have + alloc); + BUG_ON(have + alloc != need); spin_lock(&mdsc->caps_list_lock); mdsc->caps_total_count += alloc; @@ -204,6 +231,24 @@ void ceph_reserve_caps(struct ceph_mds_client *mdsc, dout("reserve caps ctx=%p %d = %d used + %d resv + %d avail\n", ctx, mdsc->caps_total_count, mdsc->caps_use_count, mdsc->caps_reserve_count, mdsc->caps_avail_count); + return 0; + +out_nomem: + while (!list_empty(&newcaps)) { + cap = list_first_entry(&newcaps, + struct ceph_cap, caps_item); + list_del(&cap->caps_item); + kmem_cache_free(ceph_cap_cachep, cap); + } + + spin_lock(&mdsc->caps_list_lock); + mdsc->caps_avail_count += have; + mdsc->caps_reserve_count -= have; + BUG_ON(mdsc->caps_total_count != mdsc->caps_use_count + + mdsc->caps_reserve_count + + mdsc->caps_avail_count); + spin_unlock(&mdsc->caps_list_lock); + return -ENOMEM; } int ceph_unreserve_caps(struct ceph_mds_client *mdsc, diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 251dc44d84a04f..2e8f90f9654029 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -604,10 +604,20 @@ static void __register_request(struct ceph_mds_client *mdsc, struct ceph_mds_request *req, struct inode *dir) { + int ret = 0; + req->r_tid = ++mdsc->last_tid; - if (req->r_num_caps) - ceph_reserve_caps(mdsc, &req->r_caps_reservation, - req->r_num_caps); + if (req->r_num_caps) { + ret = ceph_reserve_caps(mdsc, &req->r_caps_reservation, + req->r_num_caps); + if (ret < 0) { + pr_err("__register_request %p " + "failed to reserve caps: %d\n", req, ret); + /* set req->r_err to fail early from __do_request */ + req->r_err = ret; + return; + } + } dout("__register_request %p tid %lld\n", req, req->r_tid); ceph_mdsc_get_request(req); insert_request(&mdsc->request_tree, req); @@ -1545,9 +1555,9 @@ static int trim_caps_cb(struct inode *inode, struct ceph_cap *cap, void *arg) /* * Trim session cap count down to some max number. */ -static int trim_caps(struct ceph_mds_client *mdsc, - struct ceph_mds_session *session, - int max_caps) +int ceph_trim_caps(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session, + int max_caps) { int trim_caps = session->s_nr_caps - max_caps; @@ -2776,7 +2786,7 @@ static void handle_session(struct ceph_mds_session *session, break; case CEPH_SESSION_RECALL_STATE: - trim_caps(mdsc, session, le32_to_cpu(h->max_caps)); + ceph_trim_caps(mdsc, session, le32_to_cpu(h->max_caps)); break; case CEPH_SESSION_FLUSHMSG: diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 837ac4b087a0ba..71e3b783ee6fae 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -444,4 +444,7 @@ ceph_mdsc_open_export_target_session(struct ceph_mds_client *mdsc, int target); extern void ceph_mdsc_open_export_target_sessions(struct ceph_mds_client *mdsc, struct ceph_mds_session *session); +extern int ceph_trim_caps(struct ceph_mds_client *mdsc, + struct ceph_mds_session *session, + int max_caps); #endif diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 601100da738f86..21b2e5b004eb72 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -649,7 +649,7 @@ extern int __ceph_caps_mds_wanted(struct ceph_inode_info *ci, bool check); extern void ceph_caps_init(struct ceph_mds_client *mdsc); extern void ceph_caps_finalize(struct ceph_mds_client *mdsc); extern void ceph_adjust_min_caps(struct ceph_mds_client *mdsc, int delta); -extern void ceph_reserve_caps(struct ceph_mds_client *mdsc, +extern int ceph_reserve_caps(struct ceph_mds_client *mdsc, struct ceph_cap_reservation *ctx, int need); extern int ceph_unreserve_caps(struct ceph_mds_client *mdsc, struct ceph_cap_reservation *ctx); From affff07739392920d3d2095212c72af220481b95 Mon Sep 17 00:00:00 2001 From: Chengguang Xu Date: Fri, 26 Jan 2018 14:54:43 +0800 Subject: [PATCH 044/237] libceph: check kstrndup() return value Should check result of kstrndup() in case of memory allocation failure. Signed-off-by: Chengguang Xu Signed-off-by: Ilya Dryomov --- net/ceph/ceph_common.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 5c036d2f401e25..1e492ef2a33d94 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c @@ -421,6 +421,10 @@ ceph_parse_options(char *options, const char *dev_name, opt->name = kstrndup(argstr[0].from, argstr[0].to-argstr[0].from, GFP_KERNEL); + if (!opt->name) { + err = -ENOMEM; + goto out; + } break; case Opt_secret: opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); From a86170290c38ca1dad556a42f1d57f39dd62af45 Mon Sep 17 00:00:00 2001 From: Roger He Date: Fri, 19 Jan 2018 14:34:16 +0800 Subject: [PATCH 045/237] drm/ttm: fix missing parameter change for ttm_bo_cleanup_refs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Missed in the patche: dc94777 drm/ttm: enable swapout for reserved BOs during allocation. don't unreserve the BO if it is not reserved by itself. Signed-off-by: Roger He Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_bo.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 893003fc76a14d..2fef09a56d16b6 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1727,7 +1727,7 @@ int ttm_bo_swapout(struct ttm_bo_global *glob, struct ttm_operation_ctx *ctx) kref_get(&bo->list_kref); if (!list_empty(&bo->ddestroy)) { - ret = ttm_bo_cleanup_refs(bo, false, false, true); + ret = ttm_bo_cleanup_refs(bo, false, false, locked); kref_put(&bo->list_kref, ttm_bo_release_list); return ret; } From 95244db2d3f743f37e69446a2807dd1a42750542 Mon Sep 17 00:00:00 2001 From: Tom St Denis Date: Fri, 26 Jan 2018 09:32:29 -0500 Subject: [PATCH 046/237] drm/ttm: Fix 'buf' pointer update in ttm_bo_vm_access_kmap() (v2) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The buf pointer was not being incremented inside the loop meaning the same block of data would be read or written repeatedly. (v2) Change 'buf' pointer to uint8_t* type Cc: stable@vger.kernel.org Fixes: 09ac4fcb3f25 ("drm/ttm: Implement vm_operations_struct.access v2") Signed-off-by: Tom St Denis Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/ttm/ttm_bo_vm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 08a3c324242e6f..60fcef1593dd64 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -316,7 +316,7 @@ static void ttm_bo_vm_close(struct vm_area_struct *vma) static int ttm_bo_vm_access_kmap(struct ttm_buffer_object *bo, unsigned long offset, - void *buf, int len, int write) + uint8_t *buf, int len, int write) { unsigned long page = offset >> PAGE_SHIFT; unsigned long bytes_left = len; @@ -345,6 +345,7 @@ static int ttm_bo_vm_access_kmap(struct ttm_buffer_object *bo, ttm_bo_kunmap(&map); page++; + buf += bytes; bytes_left -= bytes; offset = 0; } while (bytes_left); From 59fd27cd2fd762b08a1f54de8bbe3b82aba06a13 Mon Sep 17 00:00:00 2001 From: Huang Rui Date: Fri, 15 Dec 2017 09:33:21 +0800 Subject: [PATCH 047/237] drm/amdgpu: use queue 0 for kiq ring It must use queue id 0, because CGPG_IDLE/SAVE/LOAD/RUN only can be issued on queue 0. Signed-off-by: Huang Rui Acked-by: Hawking Zhang Reviewed-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c index bb40d2529a307e..239bf2a4b3c68b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c @@ -179,8 +179,12 @@ static int amdgpu_gfx_kiq_acquire(struct amdgpu_device *adev, amdgpu_gfx_bit_to_queue(adev, queue_bit, &mec, &pipe, &queue); - /* Using pipes 2/3 from MEC 2 seems cause problems */ - if (mec == 1 && pipe > 1) + /* + * 1. Using pipes 2/3 from MEC 2 seems cause problems. + * 2. It must use queue id 0, because CGPG_IDLE/SAVE/LOAD/RUN + * only can be issued on queue 0. + */ + if ((mec == 1 && pipe > 1) || queue != 0) continue; ring->me = mec + 1; From d3aab672de4902ce25e9858fbb5bf67e8254b23c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 24 Jan 2018 14:57:02 +0100 Subject: [PATCH 048/237] drm/amdgpu: fix another potential cause of VM faults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The root PD can be evicted directly after allocating it, just validate it on first use. Signed-off-by: Christian König Acked-by: Felix Kuehling Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 32 ++++++++++---------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 6fc16eecf2dce5..5afbc5e714d084 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2262,12 +2262,12 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, { const unsigned align = min(AMDGPU_VM_PTB_ALIGN_SIZE, AMDGPU_VM_PTE_COUNT(adev) * 8); + uint64_t init_pde_value = 0, flags; unsigned ring_instance; struct amdgpu_ring *ring; struct drm_sched_rq *rq; + unsigned long size; int r, i; - u64 flags; - uint64_t init_pde_value = 0; vm->va = RB_ROOT_CACHED; for (i = 0; i < AMDGPU_MAX_VMHUBS; i++) @@ -2318,29 +2318,21 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, flags |= (AMDGPU_GEM_CREATE_NO_CPU_ACCESS | AMDGPU_GEM_CREATE_SHADOW); - r = amdgpu_bo_create(adev, - amdgpu_vm_bo_size(adev, adev->vm_manager.root_level), - align, true, - AMDGPU_GEM_DOMAIN_VRAM, - flags, - NULL, NULL, init_pde_value, &vm->root.base.bo); + size = amdgpu_vm_bo_size(adev, adev->vm_manager.root_level); + r = amdgpu_bo_create(adev, size, align, true, AMDGPU_GEM_DOMAIN_VRAM, + flags, NULL, NULL, init_pde_value, + &vm->root.base.bo); if (r) goto error_free_sched_entity; + r = amdgpu_bo_reserve(vm->root.base.bo, true); + if (r) + goto error_free_root; + vm->root.base.vm = vm; list_add_tail(&vm->root.base.bo_list, &vm->root.base.bo->va); - INIT_LIST_HEAD(&vm->root.base.vm_status); - - if (vm->use_cpu_for_update) { - r = amdgpu_bo_reserve(vm->root.base.bo, false); - if (r) - goto error_free_root; - - r = amdgpu_bo_kmap(vm->root.base.bo, NULL); - amdgpu_bo_unreserve(vm->root.base.bo); - if (r) - goto error_free_root; - } + list_add_tail(&vm->root.base.vm_status, &vm->evicted); + amdgpu_bo_unreserve(vm->root.base.bo); if (pasid) { unsigned long flags; From 153b9e1b75441cd51f69e88b4748c23166de0d64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 24 Jan 2018 13:37:48 +0100 Subject: [PATCH 049/237] drm/amdgpu: fix locking in vega10_ih_prescreen_iv MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The vm pointer can become invalid as soon as the lock is released. Signed-off-by: Christian König Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vega10_ih.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c index b69ceafb78883e..746748e6b73156 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c @@ -278,9 +278,9 @@ static bool vega10_ih_prescreen_iv(struct amdgpu_device *adev) /* Track retry faults in per-VM fault FIFO. */ spin_lock(&adev->vm_manager.pasid_lock); vm = idr_find(&adev->vm_manager.pasid_idr, pasid); - spin_unlock(&adev->vm_manager.pasid_lock); if (WARN_ON_ONCE(!vm)) { /* VM not found, process it normally */ + spin_unlock(&adev->vm_manager.pasid_lock); amdgpu_ih_clear_fault(adev, key); return true; } @@ -288,9 +288,11 @@ static bool vega10_ih_prescreen_iv(struct amdgpu_device *adev) r = kfifo_put(&vm->faults, key); if (!r) { /* FIFO is full. Ignore it until there is space */ + spin_unlock(&adev->vm_manager.pasid_lock); amdgpu_ih_clear_fault(adev, key); goto ignore_iv; } + spin_unlock(&adev->vm_manager.pasid_lock); /* It's the first fault for this address, process it normally */ return true; From 147f255884a7d9bd3707d4674a8bbacf24efbcf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 24 Jan 2018 13:38:52 +0100 Subject: [PATCH 050/237] drm/amdgpu: remove WARN_ON when VM isn't found v2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It can easily be that the VM is already destroyed when this runs. v2: fix test inversion Signed-off-by: Christian König Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vega10_ih.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c index 746748e6b73156..ee14d78be2a900 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c @@ -278,7 +278,7 @@ static bool vega10_ih_prescreen_iv(struct amdgpu_device *adev) /* Track retry faults in per-VM fault FIFO. */ spin_lock(&adev->vm_manager.pasid_lock); vm = idr_find(&adev->vm_manager.pasid_idr, pasid); - if (WARN_ON_ONCE(!vm)) { + if (!vm) { /* VM not found, process it normally */ spin_unlock(&adev->vm_manager.pasid_lock); amdgpu_ih_clear_fault(adev, key); From 3a61b527b4e1f285d21b6e9e623dc45cf8bb391f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 27 Jan 2018 15:28:15 +0100 Subject: [PATCH 051/237] drm/radeon: adjust tested variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check the variable that was most recently initialized. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression x, y, f, g, e, m; statement S1,S2,S3,S4; @@ x = f(...); if (\(<+...x...+>\&e\)) S1 else S2 ( x = g(...); | m = g(...,&x,...); | y = g(...); *if (e) S3 else S4 ) // Signed-off-by: Julia Lawall Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_uvd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index d34d1cf3389576..95f4db70dd2232 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -995,7 +995,7 @@ int radeon_uvd_calc_upll_dividers(struct radeon_device *rdev, /* calc dclk divider with current vco freq */ dclk_div = radeon_uvd_calc_upll_post_div(vco_freq, dclk, pd_min, pd_even); - if (vclk_div > pd_max) + if (dclk_div > pd_max) break; /* vco is too big, it has to stop */ /* calc score with current vco freq */ From 7e24a3ea825e546487c3fc47f8cbf6512f6c9e8c Mon Sep 17 00:00:00 2001 From: Shirish S Date: Fri, 19 Jan 2018 14:17:22 +0530 Subject: [PATCH 052/237] drm/amdgpu: disable coarse grain clockgating for ST The CGCG feature on Stoney is causing GFX related issues such as freezes and blank outs. Signed-off-by: Shirish S Reviewed-by: Arindam Nath Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index da2b99c2d95f06..5bd10f52ca8af2 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1022,7 +1022,6 @@ static int vi_common_early_init(void *handle) AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_CGTS | AMD_CG_SUPPORT_GFX_CGTS_LS | - AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_MGCG | From 16515a6d54183349b858b9c05e483afc55fa7948 Mon Sep 17 00:00:00 2001 From: Chengguang Xu Date: Tue, 30 Jan 2018 10:02:30 +0800 Subject: [PATCH 053/237] ceph: improving efficiency of syncfs write_inode() could be called variety of reasons, in the case of syncfs(2) there is no need to wait for flush getting completed in write_inode(), ->sync_fs is for guaranteeing flush completion for all inodes at that point. Signed-off-by: Chengguang Xu Reviewed-by: "Yan, Zheng" Signed-off-by: Ilya Dryomov --- fs/ceph/caps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c index 8e66fb0e743d1f..6582c4507e6c9d 100644 --- a/fs/ceph/caps.c +++ b/fs/ceph/caps.c @@ -2207,7 +2207,7 @@ int ceph_write_inode(struct inode *inode, struct writeback_control *wbc) u64 flush_tid; int err = 0; int dirty; - int wait = wbc->sync_mode == WB_SYNC_ALL; + int wait = (wbc->sync_mode == WB_SYNC_ALL && !wbc->for_sync); dout("write_inode %p wait=%d\n", inode, wait); if (wait) { From 4d32029b8ddb7be4d1699c6d8e1675ff5476d149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= Date: Sun, 12 Nov 2017 13:05:38 +0100 Subject: [PATCH 054/237] virtio_balloon: include disk/file caches memory statistics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new field VIRTIO_BALLOON_S_CACHES to virtio_balloon memory statistics protocol. The value represents all disk/file caches. In this case it corresponds to the sum of values Buffers+Cached+SwapCached from /proc/meminfo. Signed-off-by: Tomáš Golembiovský Signed-off-by: Michael S. Tsirkin --- drivers/virtio/virtio_balloon.c | 4 ++++ include/uapi/linux/virtio_balloon.h | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index a1fb52cb3f0ab5..dfe5684000beb4 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -257,11 +257,13 @@ static unsigned int update_balloon_stats(struct virtio_balloon *vb) struct sysinfo i; unsigned int idx = 0; long available; + unsigned long caches; all_vm_events(events); si_meminfo(&i); available = si_mem_available(); + caches = global_node_page_state(NR_FILE_PAGES); #ifdef CONFIG_VM_EVENT_COUNTERS update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_IN, @@ -277,6 +279,8 @@ static unsigned int update_balloon_stats(struct virtio_balloon *vb) pages_to_bytes(i.totalram)); update_stat(vb, idx++, VIRTIO_BALLOON_S_AVAIL, pages_to_bytes(available)); + update_stat(vb, idx++, VIRTIO_BALLOON_S_CACHES, + pages_to_bytes(caches)); return idx; } diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h index 343d7ddefe0458..4e8b8304b79396 100644 --- a/include/uapi/linux/virtio_balloon.h +++ b/include/uapi/linux/virtio_balloon.h @@ -52,7 +52,8 @@ struct virtio_balloon_config { #define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */ #define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */ #define VIRTIO_BALLOON_S_AVAIL 6 /* Available memory as in /proc */ -#define VIRTIO_BALLOON_S_NR 7 +#define VIRTIO_BALLOON_S_CACHES 7 /* Disk caches */ +#define VIRTIO_BALLOON_S_NR 8 /* * Memory statistics structure. From 473f0b15a4c97d398387965b7eb56939543d6091 Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Sat, 20 May 2017 13:48:44 +0200 Subject: [PATCH 055/237] vhost/scsi: Improve a size determination in four functions Replace the specification of four data structures by pointer dereferences as the parameter for the operator "sizeof" to make the corresponding size determination a bit safer according to the Linux coding style convention. Signed-off-by: Markus Elfring Reviewed-by: Stefan Hajnoczi Signed-off-by: Michael S. Tsirkin --- drivers/vhost/scsi.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 71517b3c555822..1e321e9fd59a7d 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -586,8 +586,7 @@ vhost_scsi_get_tag(struct vhost_virtqueue *vq, struct vhost_scsi_tpg *tpg, sg = cmd->tvc_sgl; prot_sg = cmd->tvc_prot_sgl; pages = cmd->tvc_upages; - memset(cmd, 0, sizeof(struct vhost_scsi_cmd)); - + memset(cmd, 0, sizeof(*cmd)); cmd->tvc_sgl = sg; cmd->tvc_prot_sgl = prot_sg; cmd->tvc_upages = pages; @@ -1725,7 +1724,7 @@ static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg, return -EEXIST; } - tv_nexus = kzalloc(sizeof(struct vhost_scsi_nexus), GFP_KERNEL); + tv_nexus = kzalloc(sizeof(*tv_nexus), GFP_KERNEL); if (!tv_nexus) { mutex_unlock(&tpg->tv_tpg_mutex); pr_err("Unable to allocate struct vhost_scsi_nexus\n"); @@ -1926,7 +1925,7 @@ vhost_scsi_make_tpg(struct se_wwn *wwn, if (kstrtou16(name + 5, 10, &tpgt) || tpgt >= VHOST_SCSI_MAX_TARGET) return ERR_PTR(-EINVAL); - tpg = kzalloc(sizeof(struct vhost_scsi_tpg), GFP_KERNEL); + tpg = kzalloc(sizeof(*tpg), GFP_KERNEL); if (!tpg) { pr_err("Unable to allocate struct vhost_scsi_tpg"); return ERR_PTR(-ENOMEM); @@ -1980,7 +1979,7 @@ vhost_scsi_make_tport(struct target_fabric_configfs *tf, /* if (vhost_scsi_parse_wwn(name, &wwpn, 1) < 0) return ERR_PTR(-EINVAL); */ - tport = kzalloc(sizeof(struct vhost_scsi_tport), GFP_KERNEL); + tport = kzalloc(sizeof(*tport), GFP_KERNEL); if (!tport) { pr_err("Unable to allocate struct vhost_scsi_tport"); return ERR_PTR(-ENOMEM); From c2c9f9bc5b830cbb63d6674b0d51a7773e54c90c Mon Sep 17 00:00:00 2001 From: Vasyl Gomonovych Date: Tue, 28 Nov 2017 16:15:47 +0100 Subject: [PATCH 056/237] virtio-mmio: Use PTR_ERR_OR_ZERO() Fix ptr_ret.cocci warnings: drivers/virtio/virtio_mmio.c:653:1-3: WARNING: PTR_ERR_OR_ZERO can be used Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR Generated by: scripts/coccinelle/api/ptr_ret.cocci Signed-off-by: Vasyl Gomonovych Signed-off-by: Michael S. Tsirkin --- drivers/virtio/virtio_mmio.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index c92131edfabaad..b43ac9b8ae4899 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -662,10 +662,8 @@ static int vm_cmdline_set(const char *device, pdev = platform_device_register_resndata(&vm_cmdline_parent, "virtio-mmio", vm_cmdline_id++, resources, ARRAY_SIZE(resources), NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - return 0; + return PTR_ERR_OR_ZERO(pdev); } static int vm_cmdline_get_device(struct device *dev, void *data) From 0a9e63aa397711cb7dd8a5c3db33448740a0b844 Mon Sep 17 00:00:00 2001 From: Vasyl Gomonovych Date: Tue, 28 Nov 2017 22:40:27 +0100 Subject: [PATCH 057/237] firmware: Use PTR_ERR_OR_ZERO() Fix ptr_ret.cocci warnings: drivers/firmware/efi/efi.c:610:8-14: WARNING: PTR_ERR_OR_ZERO can be used Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR Generated by: scripts/coccinelle/api/ptr_ret.cocci Signed-off-by: Vasyl Gomonovych Signed-off-by: Michael S. Tsirkin Acked-by: Gabriel Somlo Reviewed-by: Stefan Hajnoczi --- drivers/firmware/qemu_fw_cfg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index deb483064f53c3..a41b572eeeb107 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -694,10 +694,8 @@ static int fw_cfg_cmdline_set(const char *arg, const struct kernel_param *kp) */ fw_cfg_cmdline_dev = platform_device_register_simple("fw_cfg", PLATFORM_DEVID_NONE, res, processed); - if (IS_ERR(fw_cfg_cmdline_dev)) - return PTR_ERR(fw_cfg_cmdline_dev); - return 0; + return PTR_ERR_OR_ZERO(fw_cfg_cmdline_dev); } static int fw_cfg_cmdline_get(char *buf, const struct kernel_param *kp) From 31919140ff8c88c236f697baa28a6305df45e4ea Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 19 Jun 2017 11:44:41 +0530 Subject: [PATCH 058/237] virtio: virtio_mmio: make of_device_ids const. of_device_ids are not supposed to change at runtime. All functions working with of_device_ids provided by work with const of_device_ids. So mark the non-const structs as const. File size before: text data bss dec hex filename 3647 608 0 4255 109f drivers/virtio/virtio_mmio.o File size after constify virtio_mmio_match. text data bss dec hex filename 4063 192 0 4255 109f drivers/virtio/virtio_mmio.o Signed-off-by: Arvind Yadav Signed-off-by: Michael S. Tsirkin --- drivers/virtio/virtio_mmio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index b43ac9b8ae4899..67763d3c7abfa7 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -723,7 +723,7 @@ static void vm_unregister_cmdline_devices(void) /* Platform driver */ -static struct of_device_id virtio_mmio_match[] = { +static const struct of_device_id virtio_mmio_match[] = { { .compatible = "virtio,mmio", }, {}, }; From f229a55c31a7e12a15c7b4dcf9a97a9bf7a72ce8 Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Thu, 26 Oct 2017 04:48:01 +0300 Subject: [PATCH 059/237] virtio/ringtest: fix up need_event math last kicked event index must be updated unconditionally: even if we don't need to kick, we do not want to re-check the same entry for events. Signed-off-by: Michael S. Tsirkin Acked-by: Cornelia Huck Acked-by: Jason Wang --- tools/virtio/ringtest/ring.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tools/virtio/ringtest/ring.c b/tools/virtio/ringtest/ring.c index 747c5dd47be8b0..2b9859beea6525 100644 --- a/tools/virtio/ringtest/ring.c +++ b/tools/virtio/ringtest/ring.c @@ -188,16 +188,18 @@ bool enable_call() void kick_available(void) { + bool need; + /* Flush in previous flags write */ /* Barrier C (for pairing) */ smp_mb(); - if (!need_event(event->kick_index, - guest.avail_idx, - guest.kicked_avail_idx)) - return; + need = need_event(event->kick_index, + guest.avail_idx, + guest.kicked_avail_idx); guest.kicked_avail_idx = guest.avail_idx; - kick(); + if (need) + kick(); } /* host side */ @@ -253,14 +255,18 @@ bool use_buf(unsigned *lenp, void **bufp) void call_used(void) { + bool need; + /* Flush in previous flags write */ /* Barrier D (for pairing) */ smp_mb(); - if (!need_event(event->call_index, + + need = need_event(event->call_index, host.used_idx, - host.called_used_idx)) - return; + host.called_used_idx); host.called_used_idx = host.used_idx; - call(); + + if (need) + call(); } From a311650ae6ad0c169ade2583f78aa519878ea13f Mon Sep 17 00:00:00 2001 From: "Michael S. Tsirkin" Date: Fri, 27 Oct 2017 16:11:13 +0300 Subject: [PATCH 060/237] virtio/ringtest: virtio_ring: fix up need_event math last kicked event index must be updated unconditionally: even if we don't need to kick, we do not want to re-check the same entry for events. Reported-by: Cornelia Huck Signed-off-by: Michael S. Tsirkin Reviewed-by: Jens Freimann --- tools/virtio/ringtest/virtio_ring_0_9.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/tools/virtio/ringtest/virtio_ring_0_9.c b/tools/virtio/ringtest/virtio_ring_0_9.c index bbc3043b2fb169..5fd3fbcb9e575b 100644 --- a/tools/virtio/ringtest/virtio_ring_0_9.c +++ b/tools/virtio/ringtest/virtio_ring_0_9.c @@ -225,16 +225,18 @@ bool enable_call() void kick_available(void) { + bool need; + /* Flush in previous flags write */ /* Barrier C (for pairing) */ smp_mb(); - if (!vring_need_event(vring_avail_event(&ring), - guest.avail_idx, - guest.kicked_avail_idx)) - return; + need = vring_need_event(vring_avail_event(&ring), + guest.avail_idx, + guest.kicked_avail_idx); guest.kicked_avail_idx = guest.avail_idx; - kick(); + if (need) + kick(); } /* host side */ @@ -316,14 +318,16 @@ bool use_buf(unsigned *lenp, void **bufp) void call_used(void) { + bool need; + /* Flush in previous flags write */ /* Barrier D (for pairing) */ smp_mb(); - if (!vring_need_event(vring_used_event(&ring), - host.used_idx, - host.called_used_idx)) - return; + need = vring_need_event(vring_used_event(&ring), + host.used_idx, + host.called_used_idx); host.called_used_idx = host.used_idx; - call(); + if (need) + call(); } From 7b95fec6d2ffa53f4a8d637b0f223644d458ea4e Mon Sep 17 00:00:00 2001 From: Vincent Legoll Date: Sun, 7 Jan 2018 12:33:56 +0100 Subject: [PATCH 061/237] virtio: make VIRTIO a menuconfig to ease disabling it all No need to get into the submenu to disable all VIRTIO-related config entries. This makes it easier to disable all VIRTIO config options without entering the submenu. It will also enable one to see that en/dis-abled state from the outside menu. This is only intended to change menuconfig UI, not change the config dependencies. Signed-off-by: Vincent Legoll Reviewed-by: Randy Dunlap Tested-by: Randy Dunlap Signed-off-by: Michael S. Tsirkin --- drivers/virtio/Kconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig index cff773f15b7e2e..35897649c24f64 100644 --- a/drivers/virtio/Kconfig +++ b/drivers/virtio/Kconfig @@ -5,7 +5,11 @@ config VIRTIO bus, such as CONFIG_VIRTIO_PCI, CONFIG_VIRTIO_MMIO, CONFIG_RPMSG or CONFIG_S390_GUEST. -menu "Virtio drivers" +menuconfig VIRTIO_MENU + bool "Virtio drivers" + default y + +if VIRTIO_MENU config VIRTIO_PCI tristate "PCI driver for virtio devices" @@ -79,4 +83,4 @@ config VIRTIO_MMIO_CMDLINE_DEVICES If unsure, say 'N'. -endmenu +endif # VIRTIO_MENU From daf2a5016983a1a533417bcdc729bd2b19af1b68 Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Wed, 3 Jan 2018 16:03:39 +0000 Subject: [PATCH 062/237] virtio_blk: print capacity at probe time Print the capacity of the block device when the driver is probed. Many users expect this since SCSI disks (sd) do it. Moreover, kernel dmesg output is the primary source of troubleshooting information so it's helpful to include the disk size there. The capacity is already printed by virtio_blk when a resize event occurs. Extract the code and reuse it from virtblk_probe(). This patch also adds the block device name to the message so it can be correlated with a specific device: virtio_blk virtio0: [vda] 20971520 512-byte logical blocks (10.7 GB/10.0 GiB) Cc: Rodrigo A B Freire Cc: Michael S. Tsirkin Signed-off-by: Stefan Hajnoczi Signed-off-by: Michael S. Tsirkin --- drivers/block/virtio_blk.c | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 68846897d2139b..787cd2a10b0bac 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c @@ -373,14 +373,12 @@ static ssize_t virtblk_serial_show(struct device *dev, static DEVICE_ATTR(serial, S_IRUGO, virtblk_serial_show, NULL); -static void virtblk_config_changed_work(struct work_struct *work) +/* The queue's logical block size must be set before calling this */ +static void virtblk_update_capacity(struct virtio_blk *vblk, bool resize) { - struct virtio_blk *vblk = - container_of(work, struct virtio_blk, config_work); struct virtio_device *vdev = vblk->vdev; struct request_queue *q = vblk->disk->queue; char cap_str_2[10], cap_str_10[10]; - char *envp[] = { "RESIZE=1", NULL }; unsigned long long nblocks; u64 capacity; @@ -402,13 +400,24 @@ static void virtblk_config_changed_work(struct work_struct *work) STRING_UNITS_10, cap_str_10, sizeof(cap_str_10)); dev_notice(&vdev->dev, - "new size: %llu %d-byte logical blocks (%s/%s)\n", + "[%s] %s%llu %d-byte logical blocks (%s/%s)\n", + vblk->disk->disk_name, + resize ? "new size: " : "", nblocks, queue_logical_block_size(q), cap_str_10, cap_str_2); set_capacity(vblk->disk, capacity); +} + +static void virtblk_config_changed_work(struct work_struct *work) +{ + struct virtio_blk *vblk = + container_of(work, struct virtio_blk, config_work); + char *envp[] = { "RESIZE=1", NULL }; + + virtblk_update_capacity(vblk, true); revalidate_disk(vblk->disk); kobject_uevent_env(&disk_to_dev(vblk->disk)->kobj, KOBJ_CHANGE, envp); } @@ -621,7 +630,6 @@ static int virtblk_probe(struct virtio_device *vdev) struct request_queue *q; int err, index; - u64 cap; u32 v, blk_size, sg_elems, opt_io_size; u16 min_io_size; u8 physical_block_exp, alignment_offset; @@ -719,17 +727,6 @@ static int virtblk_probe(struct virtio_device *vdev) if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO)) set_disk_ro(vblk->disk, 1); - /* Host must always specify the capacity. */ - virtio_cread(vdev, struct virtio_blk_config, capacity, &cap); - - /* If capacity is too big, truncate with warning. */ - if ((sector_t)cap != cap) { - dev_warn(&vdev->dev, "Capacity %llu too large: truncating\n", - (unsigned long long)cap); - cap = (sector_t)-1; - } - set_capacity(vblk->disk, cap); - /* We can handle whatever the host told us to handle. */ blk_queue_max_segments(q, vblk->sg_elems-2); @@ -780,6 +777,7 @@ static int virtblk_probe(struct virtio_device *vdev) if (!err && opt_io_size) blk_queue_io_opt(q, blk_size * opt_io_size); + virtblk_update_capacity(vblk, false); virtio_device_ready(vdev); device_add_disk(&vdev->dev, vblk->disk); From ac964d7a594290e230f8c1038934692e30c76fc8 Mon Sep 17 00:00:00 2001 From: Tonghao Zhang Date: Tue, 9 Jan 2018 07:38:22 -0800 Subject: [PATCH 063/237] vhost: Remove the unused variable. The patch (7235acdb1) changed the way of the work flushing in which the queued seq, done seq, and the flushing are not used anymore. Then remove them now. Fixes: 7235acdb1 ("vhost: simplify work flushing") Cc: Jason Wang Signed-off-by: Tonghao Zhang Acked-by: Jason Wang Signed-off-by: Michael S. Tsirkin --- drivers/vhost/vhost.c | 1 - drivers/vhost/vhost.h | 4 ---- 2 files changed, 5 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 5727b186b3ca56..67fa3d153072e8 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -181,7 +181,6 @@ void vhost_work_init(struct vhost_work *work, vhost_work_fn_t fn) { clear_bit(VHOST_WORK_QUEUED, &work->flags); work->fn = fn; - init_waitqueue_head(&work->done); } EXPORT_SYMBOL_GPL(vhost_work_init); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 79c6e7a60a5ec8..749fe13e061ce8 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -20,10 +20,6 @@ typedef void (*vhost_work_fn_t)(struct vhost_work *work); struct vhost_work { struct llist_node node; vhost_work_fn_t fn; - wait_queue_head_t done; - int flushing; - unsigned queue_seq; - unsigned done_seq; unsigned long flags; }; From f6f93f75afb65997f4a84aaaab59dd06a4a06c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=B7=E5=88=99=28Caspar=29?= Date: Mon, 25 Dec 2017 00:08:58 +0800 Subject: [PATCH 064/237] vhost: remove unused lock check flag in vhost_dev_cleanup() In commit ea5d404655ba ("vhost: fix release path lockdep checks"), Michael added a flag to check whether we should hold a lock in vhost_dev_cleanup(), however, in commit 47283bef7ed3 ("vhost: move memory pointer to VQs"), RCU operations have been replaced by mutex, we can remove the no-longer-used `locked' parameter now. Signed-off-by: Caspar Zhang Signed-off-by: Michael S. Tsirkin --- drivers/vhost/net.c | 2 +- drivers/vhost/scsi.c | 2 +- drivers/vhost/test.c | 2 +- drivers/vhost/vhost.c | 5 ++--- drivers/vhost/vhost.h | 2 +- drivers/vhost/vsock.c | 2 +- 6 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index c7bdeb6556469e..a354d8d731e3f8 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -996,7 +996,7 @@ static int vhost_net_release(struct inode *inode, struct file *f) vhost_net_stop(n, &tx_sock, &rx_sock); vhost_net_flush(n); vhost_dev_stop(&n->dev); - vhost_dev_cleanup(&n->dev, false); + vhost_dev_cleanup(&n->dev); vhost_net_vq_reset(n); if (tx_sock) sockfd_put(tx_sock); diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c index 1e321e9fd59a7d..7ad57094d73692 100644 --- a/drivers/vhost/scsi.c +++ b/drivers/vhost/scsi.c @@ -1419,7 +1419,7 @@ static int vhost_scsi_release(struct inode *inode, struct file *f) mutex_unlock(&vs->dev.mutex); vhost_scsi_clear_endpoint(vs, &t); vhost_dev_stop(&vs->dev); - vhost_dev_cleanup(&vs->dev, false); + vhost_dev_cleanup(&vs->dev); /* Jobs can re-queue themselves in evt kick handler. Do extra flush. */ vhost_scsi_flush(vs); kfree(vs->dev.vqs); diff --git a/drivers/vhost/test.c b/drivers/vhost/test.c index 3cc98c07dcd393..906b8f0f19f7be 100644 --- a/drivers/vhost/test.c +++ b/drivers/vhost/test.c @@ -157,7 +157,7 @@ static int vhost_test_release(struct inode *inode, struct file *f) vhost_test_stop(n, &private); vhost_test_flush(n); - vhost_dev_cleanup(&n->dev, false); + vhost_dev_cleanup(&n->dev); /* We do an extra flush before freeing memory, * since jobs can re-queue themselves. */ vhost_test_flush(n); diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 67fa3d153072e8..e5eba5acfd5558 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -543,7 +543,7 @@ void vhost_dev_reset_owner(struct vhost_dev *dev, struct vhost_umem *umem) { int i; - vhost_dev_cleanup(dev, true); + vhost_dev_cleanup(dev); /* Restore memory to default empty mapping. */ INIT_LIST_HEAD(&umem->umem_list); @@ -610,8 +610,7 @@ static void vhost_clear_msg(struct vhost_dev *dev) spin_unlock(&dev->iotlb_lock); } -/* Caller should have device mutex if and only if locked is set */ -void vhost_dev_cleanup(struct vhost_dev *dev, bool locked) +void vhost_dev_cleanup(struct vhost_dev *dev) { int i; diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 749fe13e061ce8..d56b711577eb5f 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -177,7 +177,7 @@ bool vhost_dev_has_owner(struct vhost_dev *dev); long vhost_dev_check_owner(struct vhost_dev *); struct vhost_umem *vhost_dev_reset_owner_prepare(void); void vhost_dev_reset_owner(struct vhost_dev *, struct vhost_umem *); -void vhost_dev_cleanup(struct vhost_dev *, bool locked); +void vhost_dev_cleanup(struct vhost_dev *); void vhost_dev_stop(struct vhost_dev *); long vhost_dev_ioctl(struct vhost_dev *, unsigned int ioctl, void __user *argp); long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp); diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c index 5a5e981bd8e4a2..0d14e2ff19f16b 100644 --- a/drivers/vhost/vsock.c +++ b/drivers/vhost/vsock.c @@ -599,7 +599,7 @@ static int vhost_vsock_dev_release(struct inode *inode, struct file *file) } spin_unlock_bh(&vsock->send_pkt_list_lock); - vhost_dev_cleanup(&vsock->dev, false); + vhost_dev_cleanup(&vsock->dev); kfree(vsock->dev.vqs); vhost_vsock_free(vsock); return 0; From f2b44cde7e1687ef7886831a3a30df653bda2481 Mon Sep 17 00:00:00 2001 From: weiping zhang Date: Thu, 21 Dec 2017 20:39:50 +0800 Subject: [PATCH 065/237] virtio: split device_register into device_initialize and device_add In order to make caller do a simple cleanup, we split device_register into device_initialize and device_add. device_initialize always succeeds, so the caller can always use put_device when register_virtio_device faild. Signed-off-by: weiping zhang Suggested-by: Cornelia Huck Signed-off-by: Michael S. Tsirkin Reviewed-by: Cornelia Huck --- drivers/virtio/virtio.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/virtio/virtio.c b/drivers/virtio/virtio.c index bf7ff3934d7fff..59e36ef4920f67 100644 --- a/drivers/virtio/virtio.c +++ b/drivers/virtio/virtio.c @@ -303,11 +303,21 @@ void unregister_virtio_driver(struct virtio_driver *driver) } EXPORT_SYMBOL_GPL(unregister_virtio_driver); +/** + * register_virtio_device - register virtio device + * @dev : virtio device to be registered + * + * On error, the caller must call put_device on &@dev->dev (and not kfree), + * as another code path may have obtained a reference to @dev. + * + * Returns: 0 on suceess, -error on failure + */ int register_virtio_device(struct virtio_device *dev) { int err; dev->dev.bus = &virtio_bus; + device_initialize(&dev->dev); /* Assign a unique device index and hence name. */ err = ida_simple_get(&virtio_index_ida, 0, 0, GFP_KERNEL); @@ -330,9 +340,11 @@ int register_virtio_device(struct virtio_device *dev) INIT_LIST_HEAD(&dev->vqs); - /* device_register() causes the bus infrastructure to look for a - * matching driver. */ - err = device_register(&dev->dev); + /* + * device_add() causes the bus infrastructure to look for a matching + * driver. + */ + err = device_add(&dev->dev); if (err) ida_simple_remove(&virtio_index_ida, dev->index); out: From 33635bd976fb4c3ccf0cfbb81a8d29bb87760607 Mon Sep 17 00:00:00 2001 From: weiping zhang Date: Thu, 21 Dec 2017 20:40:24 +0800 Subject: [PATCH 066/237] virtio_pci: don't kfree device on register failure As mentioned at drivers/base/core.c: /* * NOTE: _Never_ directly free @dev after calling this function, even * if it returned an error! Always use put_device() to give up the * reference initialized in this function instead. */ so we don't free vp_dev until vp_dev->vdev.dev.release be called. Signed-off-by: weiping zhang Reviewed-by: Cornelia Huck Signed-off-by: Michael S. Tsirkin --- drivers/virtio/virtio_pci_common.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c index 1c4797e53f686b..48d4d1cf1cb63f 100644 --- a/drivers/virtio/virtio_pci_common.c +++ b/drivers/virtio/virtio_pci_common.c @@ -513,7 +513,7 @@ static void virtio_pci_release_dev(struct device *_d) static int virtio_pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) { - struct virtio_pci_device *vp_dev; + struct virtio_pci_device *vp_dev, *reg_dev = NULL; int rc; /* allocate our structure and fill it out */ @@ -551,6 +551,7 @@ static int virtio_pci_probe(struct pci_dev *pci_dev, pci_set_master(pci_dev); rc = register_virtio_device(&vp_dev->vdev); + reg_dev = vp_dev; if (rc) goto err_register; @@ -564,7 +565,10 @@ static int virtio_pci_probe(struct pci_dev *pci_dev, err_probe: pci_disable_device(pci_dev); err_enable_device: - kfree(vp_dev); + if (reg_dev) + put_device(&vp_dev->vdev.dev); + else + kfree(vp_dev); return rc; } From 0063e8bbd2b62d13645d416625478c2199fdee0f Mon Sep 17 00:00:00 2001 From: weiping zhang Date: Thu, 21 Dec 2017 20:40:43 +0800 Subject: [PATCH 067/237] virtio_vop: don't kfree device on register failure As mentioned at drivers/base/core.c: /* * NOTE: _Never_ directly free @dev after calling this function, even * if it returned an error! Always use put_device() to give up the * reference initialized in this function instead. */ so we don't free vdev until vdev->vdev.dev.release be called. Signed-off-by: weiping zhang Reviewed-by: Cornelia Huck Signed-off-by: Michael S. Tsirkin --- drivers/misc/mic/vop/vop_main.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/drivers/misc/mic/vop/vop_main.c b/drivers/misc/mic/vop/vop_main.c index a341938c7e2c67..3633202e18f4f1 100644 --- a/drivers/misc/mic/vop/vop_main.c +++ b/drivers/misc/mic/vop/vop_main.c @@ -452,10 +452,12 @@ static irqreturn_t vop_virtio_intr_handler(int irq, void *data) static void vop_virtio_release_dev(struct device *_d) { - /* - * No need for a release method similar to virtio PCI. - * Provide an empty one to avoid getting a warning from core. - */ + struct virtio_device *vdev = + container_of(_d, struct virtio_device, dev); + struct _vop_vdev *vop_vdev = + container_of(vdev, struct _vop_vdev, vdev); + + kfree(vop_vdev); } /* @@ -466,7 +468,7 @@ static int _vop_add_device(struct mic_device_desc __iomem *d, unsigned int offset, struct vop_device *vpdev, int dnode) { - struct _vop_vdev *vdev; + struct _vop_vdev *vdev, *reg_dev = NULL; int ret; u8 type = ioread8(&d->type); @@ -497,6 +499,7 @@ static int _vop_add_device(struct mic_device_desc __iomem *d, vdev->c2h_vdev_db = ioread8(&vdev->dc->c2h_vdev_db); ret = register_virtio_device(&vdev->vdev); + reg_dev = vdev; if (ret) { dev_err(_vop_dev(vdev), "Failed to register vop device %u type %u\n", @@ -512,7 +515,10 @@ static int _vop_add_device(struct mic_device_desc __iomem *d, free_irq: vpdev->hw_ops->free_irq(vpdev, vdev->virtio_cookie, vdev); kfree: - kfree(vdev); + if (reg_dev) + put_device(&vdev->vdev.dev); + else + kfree(vdev); return ret; } @@ -568,7 +574,7 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d, iowrite8(-1, &dc->h2c_vdev_db); if (status & VIRTIO_CONFIG_S_DRIVER_OK) wait_for_completion(&vdev->reset_done); - kfree(vdev); + put_device(&vdev->vdev.dev); iowrite8(1, &dc->guest_ack); dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n", __func__, __LINE__, ioread8(&dc->guest_ack)); From 03ee47ae8a7c608975be7e45287bff0482e295d6 Mon Sep 17 00:00:00 2001 From: Peter Malone Date: Thu, 16 Feb 2017 15:42:26 -0500 Subject: [PATCH 068/237] ringtest: ring.c malloc & memset to calloc Code cleanup change - moving from malloc & memset to calloc. Signed-off-by: Peter Malone Signed-off-by: Michael S. Tsirkin --- tools/virtio/ringtest/ring.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tools/virtio/ringtest/ring.c b/tools/virtio/ringtest/ring.c index 2b9859beea6525..5a41404aaef566 100644 --- a/tools/virtio/ringtest/ring.c +++ b/tools/virtio/ringtest/ring.c @@ -84,12 +84,11 @@ void alloc_ring(void) perror("Unable to allocate ring buffer.\n"); exit(3); } - event = malloc(sizeof *event); + event = calloc(1, sizeof(*event)); if (!event) { perror("Unable to allocate event buffer.\n"); exit(3); } - memset(event, 0, sizeof *event); guest.avail_idx = 0; guest.kicked_avail_idx = -1; guest.last_used_idx = 0; @@ -102,12 +101,11 @@ void alloc_ring(void) ring[i] = desc; } guest.num_free = ring_size; - data = malloc(ring_size * sizeof *data); + data = calloc(ring_size, sizeof(*data)); if (!data) { perror("Unable to allocate data buffer.\n"); exit(3); } - memset(data, 0, ring_size * sizeof *data); } /* guest side */ From e050c7d93f4adb2a651711e2d4e0a86d41b9d76f Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 6 Jan 2018 14:52:19 -0800 Subject: [PATCH 069/237] vhost: don't hold onto file pointer for VHOST_SET_VRING_CALL We already hold a reference to the eventfd_ctx, which is sufficient; there's no need to hold a reference to the struct file as well. So get rid of vhost_virtqueue->call. Signed-off-by: Eric Biggers Signed-off-by: Michael S. Tsirkin Reviewed-by: Jason Wang --- drivers/vhost/vhost.c | 20 +++++--------------- drivers/vhost/vhost.h | 1 - 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index e5eba5acfd5558..7bf0b734ae7032 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -321,7 +321,6 @@ static void vhost_vq_reset(struct vhost_dev *dev, vq->error = NULL; vq->kick = NULL; vq->call_ctx = NULL; - vq->call = NULL; vq->log_ctx = NULL; vhost_reset_is_le(vq); vhost_disable_cross_endian(vq); @@ -623,8 +622,6 @@ void vhost_dev_cleanup(struct vhost_dev *dev) fput(dev->vqs[i]->kick); if (dev->vqs[i]->call_ctx) eventfd_ctx_put(dev->vqs[i]->call_ctx); - if (dev->vqs[i]->call) - fput(dev->vqs[i]->call); vhost_vq_reset(dev, dev->vqs[i]); } vhost_dev_free_iovecs(dev); @@ -1490,19 +1487,12 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp) r = -EFAULT; break; } - eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); - if (IS_ERR(eventfp)) { - r = PTR_ERR(eventfp); + ctx = f.fd == -1 ? NULL : eventfd_ctx_fdget(f.fd); + if (IS_ERR(ctx)) { + r = PTR_ERR(ctx); break; } - if (eventfp != vq->call) { - filep = vq->call; - ctx = vq->call_ctx; - vq->call = eventfp; - vq->call_ctx = eventfp ? - eventfd_ctx_fileget(eventfp) : NULL; - } else - filep = eventfp; + swap(ctx, vq->call_ctx); break; case VHOST_SET_VRING_ERR: if (copy_from_user(&f, argp, sizeof f)) { @@ -1549,7 +1539,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp) if (pollstop && vq->handle_kick) vhost_poll_stop(&vq->poll); - if (ctx) + if (!IS_ERR_OR_NULL(ctx)) eventfd_ctx_put(ctx); if (filep) fput(filep); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index d56b711577eb5f..0ba877e385ac83 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -92,7 +92,6 @@ struct vhost_virtqueue { struct vring_used __user *used; const struct vhost_umem_node *meta_iotlb[VHOST_NUM_ADDRS]; struct file *kick; - struct file *call; struct file *error; struct eventfd_ctx *call_ctx; struct eventfd_ctx *error_ctx; From 09f332a589232f524b579ba4319433dcc7c0ed32 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 6 Jan 2018 14:52:20 -0800 Subject: [PATCH 070/237] vhost: don't hold onto file pointer for VHOST_SET_VRING_ERR We already hold a reference to the eventfd_ctx, which is sufficient; there's no need to hold a reference to the struct file as well. So get rid of vhost_virtqueue->error. Signed-off-by: Eric Biggers Signed-off-by: Michael S. Tsirkin Reviewed-by: Jason Wang --- drivers/vhost/vhost.c | 18 ++++-------------- drivers/vhost/vhost.h | 1 - 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 7bf0b734ae7032..40a72d15361fac 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -318,7 +318,6 @@ static void vhost_vq_reset(struct vhost_dev *dev, vq->acked_features = 0; vq->log_base = NULL; vq->error_ctx = NULL; - vq->error = NULL; vq->kick = NULL; vq->call_ctx = NULL; vq->log_ctx = NULL; @@ -616,8 +615,6 @@ void vhost_dev_cleanup(struct vhost_dev *dev) for (i = 0; i < dev->nvqs; ++i) { if (dev->vqs[i]->error_ctx) eventfd_ctx_put(dev->vqs[i]->error_ctx); - if (dev->vqs[i]->error) - fput(dev->vqs[i]->error); if (dev->vqs[i]->kick) fput(dev->vqs[i]->kick); if (dev->vqs[i]->call_ctx) @@ -1499,19 +1496,12 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp) r = -EFAULT; break; } - eventfp = f.fd == -1 ? NULL : eventfd_fget(f.fd); - if (IS_ERR(eventfp)) { - r = PTR_ERR(eventfp); + ctx = f.fd == -1 ? NULL : eventfd_ctx_fdget(f.fd); + if (IS_ERR(ctx)) { + r = PTR_ERR(ctx); break; } - if (eventfp != vq->error) { - filep = vq->error; - vq->error = eventfp; - ctx = vq->error_ctx; - vq->error_ctx = eventfp ? - eventfd_ctx_fileget(eventfp) : NULL; - } else - filep = eventfp; + swap(ctx, vq->error_ctx); break; case VHOST_SET_VRING_ENDIAN: r = vhost_set_vring_endian(vq, argp); diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 0ba877e385ac83..e3c463ce3d4848 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -92,7 +92,6 @@ struct vhost_virtqueue { struct vring_used __user *used; const struct vhost_umem_node *meta_iotlb[VHOST_NUM_ADDRS]; struct file *kick; - struct file *error; struct eventfd_ctx *call_ctx; struct eventfd_ctx *error_ctx; struct eventfd_ctx *log_ctx; From d25cc43c6775bff6b8e3dad97c747954b805e421 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 6 Jan 2018 14:52:21 -0800 Subject: [PATCH 071/237] vhost: don't hold onto file pointer for VHOST_SET_LOG_FD We already hold a reference to the eventfd_ctx, which is sufficient; there's no need to hold a reference to the struct file as well. So get rid of vhost_dev->log_file. Signed-off-by: Eric Biggers Signed-off-by: Michael S. Tsirkin Reviewed-by: Jason Wang --- drivers/vhost/vhost.c | 24 +++++------------------- drivers/vhost/vhost.h | 1 - 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 40a72d15361fac..66775446248a79 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c @@ -419,7 +419,6 @@ void vhost_dev_init(struct vhost_dev *dev, dev->nvqs = nvqs; mutex_init(&dev->mutex); dev->log_ctx = NULL; - dev->log_file = NULL; dev->umem = NULL; dev->iotlb = NULL; dev->mm = NULL; @@ -625,9 +624,6 @@ void vhost_dev_cleanup(struct vhost_dev *dev) if (dev->log_ctx) eventfd_ctx_put(dev->log_ctx); dev->log_ctx = NULL; - if (dev->log_file) - fput(dev->log_file); - dev->log_file = NULL; /* No one will access memory at this point */ vhost_umem_clean(dev->umem); dev->umem = NULL; @@ -1572,8 +1568,7 @@ EXPORT_SYMBOL_GPL(vhost_init_device_iotlb); /* Caller must have device mutex */ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) { - struct file *eventfp, *filep = NULL; - struct eventfd_ctx *ctx = NULL; + struct eventfd_ctx *ctx; u64 p; long r; int i, fd; @@ -1619,19 +1614,12 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) r = get_user(fd, (int __user *)argp); if (r < 0) break; - eventfp = fd == -1 ? NULL : eventfd_fget(fd); - if (IS_ERR(eventfp)) { - r = PTR_ERR(eventfp); + ctx = fd == -1 ? NULL : eventfd_ctx_fdget(fd); + if (IS_ERR(ctx)) { + r = PTR_ERR(ctx); break; } - if (eventfp != d->log_file) { - filep = d->log_file; - d->log_file = eventfp; - ctx = d->log_ctx; - d->log_ctx = eventfp ? - eventfd_ctx_fileget(eventfp) : NULL; - } else - filep = eventfp; + swap(ctx, d->log_ctx); for (i = 0; i < d->nvqs; ++i) { mutex_lock(&d->vqs[i]->mutex); d->vqs[i]->log_ctx = d->log_ctx; @@ -1639,8 +1627,6 @@ long vhost_dev_ioctl(struct vhost_dev *d, unsigned int ioctl, void __user *argp) } if (ctx) eventfd_ctx_put(ctx); - if (filep) - fput(filep); break; default: r = -ENOIOCTLCMD; diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index e3c463ce3d4848..45d12b01cfe4e9 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h @@ -157,7 +157,6 @@ struct vhost_dev { struct mutex mutex; struct vhost_virtqueue **vqs; int nvqs; - struct file *log_file; struct eventfd_ctx *log_ctx; struct llist_head work_list; struct task_struct *worker; From d9df2c0943811f3880393be738ab86675029f3d0 Mon Sep 17 00:00:00 2001 From: Xiong Zhang Date: Wed, 27 Dec 2017 05:01:16 +0800 Subject: [PATCH 072/237] drm/i915/gvt: Fix gen8/9_render_mmio_list[0] don't take effect while(mmio++) increase mmio to next, mmio[0] never take effect in while loop. This patch change while to for and fix the above issue. v2: Correct Fixes format.(Zhenyu) v3: Rebase to latest staging.(Zhenyu) Fixes: 83164886e455("drm/i915/gvt: Select appropriate mmio list at initialization time") Signed-off-by: Xiong Zhang Signed-off-by: Zhenyu Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/mmio_context.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index 74834395dd892d..48ee61ac9bc591 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c @@ -80,7 +80,7 @@ static struct engine_mmio gen8_engine_mmio_list[] __cacheline_aligned = { {BCS, RING_INSTPM(BLT_RING_BASE), 0xffff, false}, /* 0x220c0 */ {BCS, RING_HWSTAM(BLT_RING_BASE), 0x0, false}, /* 0x22098 */ {BCS, RING_EXCC(BLT_RING_BASE), 0x0, false}, /* 0x22028 */ - { /* Terminated */ } + {RCS, INVALID_MMIO_REG, 0, false } /* Terminated */ }; static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = { @@ -146,7 +146,7 @@ static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = { {RCS, GEN8_GARBCNTL, 0x0, false}, /* 0xb004 */ {RCS, GEN7_FF_THREAD_MODE, 0x0, false}, /* 0x20a0 */ {RCS, FF_SLICE_CS_CHICKEN2, 0xffff, false}, /* 0x20e4 */ - { /* Terminated */ } + {RCS, INVALID_MMIO_REG, 0, false } /* Terminated */ }; static struct { @@ -310,8 +310,8 @@ static void switch_mmio(struct intel_vgpu *pre, if (IS_SKYLAKE(dev_priv) || IS_KABYLAKE(dev_priv)) switch_mocs(pre, next, ring_id); - mmio = dev_priv->gvt->engine_mmio_list; - while (i915_mmio_reg_offset((mmio++)->reg)) { + for (mmio = dev_priv->gvt->engine_mmio_list; + i915_mmio_reg_valid(mmio->reg); mmio++) { if (mmio->ring_id != ring_id) continue; // save From 03fa9350c30b5db827e9b155715df09660ba28b1 Mon Sep 17 00:00:00 2001 From: Pei Zhang Date: Tue, 26 Dec 2017 14:31:25 +0800 Subject: [PATCH 073/237] drm/i915/gvt: add PLANE_KEYMAX regs to mmio track list Running 4.15 Linux kernel in VM will cause host GVT reports 'untrack mmio 0x701a0' errror, which identifies the PLANE_KEYMAX registers. Add them to track list. v2: rebase to latest staging code. Signed-off-by: Pei Zhang Signed-off-by: Zhenyu Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/handlers.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 92d6468daeee15..38f3b00d3a7a0e 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -2843,6 +2843,9 @@ static int init_skl_mmio_info(struct intel_gvt *gvt) MMIO_D(_MMIO(_PLANE_KEYVAL_1(PIPE_A)), D_SKL_PLUS); MMIO_D(_MMIO(_PLANE_KEYVAL_1(PIPE_B)), D_SKL_PLUS); MMIO_D(_MMIO(_PLANE_KEYVAL_1(PIPE_C)), D_SKL_PLUS); + MMIO_D(_MMIO(_PLANE_KEYMAX_1(PIPE_A)), D_SKL_PLUS); + MMIO_D(_MMIO(_PLANE_KEYMAX_1(PIPE_B)), D_SKL_PLUS); + MMIO_D(_MMIO(_PLANE_KEYMAX_1(PIPE_C)), D_SKL_PLUS); MMIO_D(_MMIO(_PLANE_KEYMSK_1(PIPE_A)), D_SKL_PLUS); MMIO_D(_MMIO(_PLANE_KEYMSK_1(PIPE_B)), D_SKL_PLUS); MMIO_D(_MMIO(_PLANE_KEYMSK_1(PIPE_C)), D_SKL_PLUS); From cc753fbe1ac47560e1517e3e11fb0c8a3c95eef5 Mon Sep 17 00:00:00 2001 From: Hang Yuan Date: Fri, 22 Dec 2017 18:06:31 +0800 Subject: [PATCH 074/237] drm/i915/gvt: validate gfn before set shadow page entry GVT may receive partial write on one guest PTE update. Validate gfn not to translate incomplete gfn. This avoids some unnecessary error messages incurred by the incomplete gfn translating. Also fix the bug that the whole PPGTT shadow page update is aborted on any invalid gfn entry. gfn validation relys on hypervisor's help. Add one MPT module function to provide the function. Signed-off-by: Hang Yuan Reviewed-by: Zhi Wang Signed-off-by: Zhenyu Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/gtt.c | 24 +++++++++++++++++++----- drivers/gpu/drm/i915/gvt/hypercall.h | 1 + drivers/gpu/drm/i915/gvt/kvmgt.c | 16 ++++++++++++++++ drivers/gpu/drm/i915/gvt/mpt.h | 17 +++++++++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index a529d2bd393cb9..8d5317d0122d41 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -997,9 +997,11 @@ static inline void ppgtt_generate_shadow_entry(struct intel_gvt_gtt_entry *se, static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) { struct intel_vgpu *vgpu = spt->vgpu; + struct intel_gvt *gvt = vgpu->gvt; + struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; struct intel_vgpu_ppgtt_spt *s; struct intel_gvt_gtt_entry se, ge; - unsigned long i; + unsigned long gfn, i; int ret; trace_spt_change(spt->vgpu->id, "born", spt, @@ -1007,9 +1009,10 @@ static int ppgtt_populate_shadow_page(struct intel_vgpu_ppgtt_spt *spt) if (gtt_type_is_pte_pt(spt->shadow_page.type)) { for_each_present_guest_entry(spt, &ge, i) { - ret = gtt_entry_p2m(vgpu, &ge, &se); - if (ret) - goto fail; + gfn = ops->get_pfn(&ge); + if (!intel_gvt_hypervisor_is_valid_gfn(vgpu, gfn) || + gtt_entry_p2m(vgpu, &ge, &se)) + ops->set_pfn(&se, gvt->gtt.scratch_mfn); ppgtt_set_shadow_entry(spt, &se, i); } return 0; @@ -1906,7 +1909,7 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, struct intel_vgpu_mm *ggtt_mm = vgpu->gtt.ggtt_mm; struct intel_gvt_gtt_pte_ops *ops = gvt->gtt.pte_ops; unsigned long g_gtt_index = off >> info->gtt_entry_size_shift; - unsigned long gma; + unsigned long gma, gfn; struct intel_gvt_gtt_entry e, m; int ret; @@ -1925,6 +1928,16 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, bytes); if (ops->test_present(&e)) { + gfn = ops->get_pfn(&e); + + /* one PTE update may be issued in multiple writes and the + * first write may not construct a valid gfn + */ + if (!intel_gvt_hypervisor_is_valid_gfn(vgpu, gfn)) { + ops->set_pfn(&m, gvt->gtt.scratch_mfn); + goto out; + } + ret = gtt_entry_p2m(vgpu, &e, &m); if (ret) { gvt_vgpu_err("fail to translate guest gtt entry\n"); @@ -1939,6 +1952,7 @@ static int emulate_gtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off, ops->set_pfn(&m, gvt->gtt.scratch_mfn); } +out: ggtt_set_shadow_entry(ggtt_mm, &m, g_gtt_index); gtt_invalidate(gvt->dev_priv); ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index); diff --git a/drivers/gpu/drm/i915/gvt/hypercall.h b/drivers/gpu/drm/i915/gvt/hypercall.h index a1bd82feb82745..f8e77e1662462f 100644 --- a/drivers/gpu/drm/i915/gvt/hypercall.h +++ b/drivers/gpu/drm/i915/gvt/hypercall.h @@ -58,6 +58,7 @@ struct intel_gvt_mpt { int (*set_opregion)(void *vgpu); int (*get_vfio_device)(void *vgpu); void (*put_vfio_device)(void *vgpu); + bool (*is_valid_gfn)(unsigned long handle, unsigned long gfn); }; extern struct intel_gvt_mpt xengt_mpt; diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index 45bab5a6290bea..eb92572056c37e 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -1570,6 +1570,21 @@ static unsigned long kvmgt_virt_to_pfn(void *addr) return PFN_DOWN(__pa(addr)); } +static bool kvmgt_is_valid_gfn(unsigned long handle, unsigned long gfn) +{ + struct kvmgt_guest_info *info; + struct kvm *kvm; + + if (!handle_valid(handle)) + return false; + + info = (struct kvmgt_guest_info *)handle; + kvm = info->kvm; + + return kvm_is_visible_gfn(kvm, gfn); + +} + struct intel_gvt_mpt kvmgt_mpt = { .host_init = kvmgt_host_init, .host_exit = kvmgt_host_exit, @@ -1585,6 +1600,7 @@ struct intel_gvt_mpt kvmgt_mpt = { .set_opregion = kvmgt_set_opregion, .get_vfio_device = kvmgt_get_vfio_device, .put_vfio_device = kvmgt_put_vfio_device, + .is_valid_gfn = kvmgt_is_valid_gfn, }; EXPORT_SYMBOL_GPL(kvmgt_mpt); diff --git a/drivers/gpu/drm/i915/gvt/mpt.h b/drivers/gpu/drm/i915/gvt/mpt.h index ca8005a6d5faa1..81aff4eacbfeb6 100644 --- a/drivers/gpu/drm/i915/gvt/mpt.h +++ b/drivers/gpu/drm/i915/gvt/mpt.h @@ -339,4 +339,21 @@ static inline void intel_gvt_hypervisor_put_vfio_device(struct intel_vgpu *vgpu) intel_gvt_host.mpt->put_vfio_device(vgpu); } +/** + * intel_gvt_hypervisor_is_valid_gfn - check if a visible gfn + * @vgpu: a vGPU + * @gfn: guest PFN + * + * Returns: + * true on valid gfn, false on not. + */ +static inline bool intel_gvt_hypervisor_is_valid_gfn( + struct intel_vgpu *vgpu, unsigned long gfn) +{ + if (!intel_gvt_host.mpt->is_valid_gfn) + return true; + + return intel_gvt_host.mpt->is_valid_gfn(vgpu->handle, gfn); +} + #endif /* _GVT_MPT_H_ */ From 8466169ab9fe9f0c3412881116aca895feea6e70 Mon Sep 17 00:00:00 2001 From: Michel Thierry Date: Mon, 8 Jan 2018 10:37:34 -0800 Subject: [PATCH 075/237] drm/i915/gvt: Do not use I915_NUM_ENGINES to iterate over the mocs regs array The mocs reg array is defined locally but then we iterate over its elements using I915_NUM_ENGINES. There is no 'hard' connection between I915_NUM_ENGINES and the regs array and there will be problems if either of them increases. Use the size of the mocs reg array instead to safely iterate over it. Signed-off-by: Michel Thierry Cc: Weinan Li Cc: Zhenyu Wang Signed-off-by: Zhenyu Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/mmio_context.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index 48ee61ac9bc591..73ad6e90e49db1 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c @@ -167,7 +167,7 @@ static void load_render_mocs(struct drm_i915_private *dev_priv) }; int ring_id, i; - for (ring_id = 0; ring_id < I915_NUM_ENGINES; ring_id++) { + for (ring_id = 0; ring_id < ARRAY_SIZE(regs); ring_id++) { offset.reg = regs[ring_id]; for (i = 0; i < 64; i++) { gen9_render_mocs.control_table[ring_id][i] = From 2afba81c7909ac259720c0d3e7616cf54d4a5368 Mon Sep 17 00:00:00 2001 From: Anusha Srivatsa Date: Wed, 3 Jan 2018 11:03:45 -0800 Subject: [PATCH 076/237] drm/i915/glk: Disable Guc and HuC on GLK Since the firmwares are not yet released to public repo, disable them on Geminilake. v2: Remove the firmware versions (Michal) v3: Remove unwanted defines (Rodrigo) Correct commit message (Michal) Cc: Michal Wajdeczko Cc: Rodrigo Vivi Cc: Signed-off-by: Anusha Srivatsa Fixes: 90f192c8241e ("drm/i915/GuC/GLK: Load GuC on GLK") Fixes: db5ba0d8931e ("drm/i915/GLK/HuC: Load HuC on GLK") Reviewed-by: Michal Wajdeczko Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/1515006225-13003-1-git-send-email-anusha.srivatsa@intel.com (cherry picked from commit a76050a4837860fcadb6ca11d69d41e08f4090d8) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_guc_fw.c | 9 --------- drivers/gpu/drm/i915/intel_huc.c | 11 ----------- 2 files changed, 20 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_guc_fw.c b/drivers/gpu/drm/i915/intel_guc_fw.c index cbc51c9604256d..3b0932942857f6 100644 --- a/drivers/gpu/drm/i915/intel_guc_fw.c +++ b/drivers/gpu/drm/i915/intel_guc_fw.c @@ -39,9 +39,6 @@ #define KBL_FW_MAJOR 9 #define KBL_FW_MINOR 39 -#define GLK_FW_MAJOR 10 -#define GLK_FW_MINOR 56 - #define GUC_FW_PATH(platform, major, minor) \ "i915/" __stringify(platform) "_guc_ver" __stringify(major) "_" __stringify(minor) ".bin" @@ -54,8 +51,6 @@ MODULE_FIRMWARE(I915_BXT_GUC_UCODE); #define I915_KBL_GUC_UCODE GUC_FW_PATH(kbl, KBL_FW_MAJOR, KBL_FW_MINOR) MODULE_FIRMWARE(I915_KBL_GUC_UCODE); -#define I915_GLK_GUC_UCODE GUC_FW_PATH(glk, GLK_FW_MAJOR, GLK_FW_MINOR) - static void guc_fw_select(struct intel_uc_fw *guc_fw) { struct intel_guc *guc = container_of(guc_fw, struct intel_guc, fw); @@ -82,10 +77,6 @@ static void guc_fw_select(struct intel_uc_fw *guc_fw) guc_fw->path = I915_KBL_GUC_UCODE; guc_fw->major_ver_wanted = KBL_FW_MAJOR; guc_fw->minor_ver_wanted = KBL_FW_MINOR; - } else if (IS_GEMINILAKE(dev_priv)) { - guc_fw->path = I915_GLK_GUC_UCODE; - guc_fw->major_ver_wanted = GLK_FW_MAJOR; - guc_fw->minor_ver_wanted = GLK_FW_MINOR; } else { DRM_WARN("%s: No firmware known for this platform!\n", intel_uc_fw_type_repr(guc_fw->type)); diff --git a/drivers/gpu/drm/i915/intel_huc.c b/drivers/gpu/drm/i915/intel_huc.c index 974be3defa7091..8ed05182f94448 100644 --- a/drivers/gpu/drm/i915/intel_huc.c +++ b/drivers/gpu/drm/i915/intel_huc.c @@ -54,10 +54,6 @@ #define KBL_HUC_FW_MINOR 00 #define KBL_BLD_NUM 1810 -#define GLK_HUC_FW_MAJOR 02 -#define GLK_HUC_FW_MINOR 00 -#define GLK_BLD_NUM 1748 - #define HUC_FW_PATH(platform, major, minor, bld_num) \ "i915/" __stringify(platform) "_huc_ver" __stringify(major) "_" \ __stringify(minor) "_" __stringify(bld_num) ".bin" @@ -74,9 +70,6 @@ MODULE_FIRMWARE(I915_BXT_HUC_UCODE); KBL_HUC_FW_MINOR, KBL_BLD_NUM) MODULE_FIRMWARE(I915_KBL_HUC_UCODE); -#define I915_GLK_HUC_UCODE HUC_FW_PATH(glk, GLK_HUC_FW_MAJOR, \ - GLK_HUC_FW_MINOR, GLK_BLD_NUM) - static void huc_fw_select(struct intel_uc_fw *huc_fw) { struct intel_huc *huc = container_of(huc_fw, struct intel_huc, fw); @@ -103,10 +96,6 @@ static void huc_fw_select(struct intel_uc_fw *huc_fw) huc_fw->path = I915_KBL_HUC_UCODE; huc_fw->major_ver_wanted = KBL_HUC_FW_MAJOR; huc_fw->minor_ver_wanted = KBL_HUC_FW_MINOR; - } else if (IS_GEMINILAKE(dev_priv)) { - huc_fw->path = I915_GLK_HUC_UCODE; - huc_fw->major_ver_wanted = GLK_HUC_FW_MAJOR; - huc_fw->minor_ver_wanted = GLK_HUC_FW_MINOR; } else { DRM_WARN("%s: No firmware known for this platform!\n", intel_uc_fw_type_repr(huc_fw->type)); From 90024a5951029685acc5396258f1b0de9b23cf4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Br=C3=BCns?= Date: Sun, 31 Dec 2017 23:34:54 +0100 Subject: [PATCH 077/237] drm/i915: Try EDID bitbanging on HDMI after failed read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ACK/NACK implementation as found in e.g. the G965 has the falling clock edge and the release of the data line after the ACK for the received byte happen at the same time. This is conformant with the I2C specification, which allows a zero hold time, see footnote [3]: "A device must internally provide a hold time of at least 300 ns for the SDA signal (with respect to the V IH(min) of the SCL signal) to bridge the undefined region of the falling edge of SCL." Some HDMI-to-VGA converters apparently fail to adhere to this requirement and latch SDA at the falling clock edge, so instead of an ACK sometimes a NACK is read and the slave (i.e. the EDID ROM) ends the transfer. The bitbanging releases the data line for the ACK only 1/4 bit time after the falling clock edge, so a slave will see the correct value no matter if it samples at the rising or the falling clock edge or in the center. Fallback to bitbanging is already done for the CRT connector. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92685 Signed-off-by: Stefan Brüns Cc: stable@vger.kernel.org Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/a39f080b-81a5-4c93-b3f7-7cb0a58daca3@rwthex-w2-a.rwth-ad.de (cherry picked from commit cfb926e148e99acc02351d72e8b85e32b5f786ef) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_hdmi.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index bced7b954d93d8..179d0ad3889d1f 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c @@ -1595,12 +1595,20 @@ intel_hdmi_set_edid(struct drm_connector *connector) struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector); struct edid *edid; bool connected = false; + struct i2c_adapter *i2c; intel_display_power_get(dev_priv, POWER_DOMAIN_GMBUS); - edid = drm_get_edid(connector, - intel_gmbus_get_adapter(dev_priv, - intel_hdmi->ddc_bus)); + i2c = intel_gmbus_get_adapter(dev_priv, intel_hdmi->ddc_bus); + + edid = drm_get_edid(connector, i2c); + + if (!edid && !intel_gmbus_is_forced_bit(i2c)) { + DRM_DEBUG_KMS("HDMI GMBUS EDID read failed, retry using GPIO bit-banging\n"); + intel_gmbus_force_bit(i2c, true); + edid = drm_get_edid(connector, i2c); + intel_gmbus_force_bit(i2c, false); + } intel_hdmi_dp_dual_mode_detect(connector, edid != NULL); From 6389902072db658366ec53711a83d711364b7330 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 9 Jan 2018 14:20:40 +0200 Subject: [PATCH 078/237] drm/i915: Fix using BIT_ULL() vs. BIT() for power domain masks The power domain masks are 64 bit wide, so we need BIT_ULL() when setting bits in them, these ones were missed during converting from 32 to 64 bit masks. All 3 enums are <32 atm, so this didn't cause a real problem. Fixes: d8fc70b7367b ("drm/i915: Make power domain masks 64 bit long") Cc: Joonas Lahtinen Reported-by: Fengguang Wu Signed-off-by: Imre Deak Reviewed-by: Chris Wilson Reviewed-by: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20180109122040.19425-1-imre.deak@intel.com (cherry picked from commit 17bd6e66d8f677b1b250d098097fbed6e70175ef) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_display.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 0cd355978ab42a..f288bcc7be22d6 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -5661,8 +5661,8 @@ static u64 get_crtc_power_domains(struct drm_crtc *crtc, if (!crtc_state->base.active) return 0; - mask = BIT(POWER_DOMAIN_PIPE(pipe)); - mask |= BIT(POWER_DOMAIN_TRANSCODER(transcoder)); + mask = BIT_ULL(POWER_DOMAIN_PIPE(pipe)); + mask |= BIT_ULL(POWER_DOMAIN_TRANSCODER(transcoder)); if (crtc_state->pch_pfit.enabled || crtc_state->pch_pfit.force_thru) mask |= BIT_ULL(POWER_DOMAIN_PIPE_PANEL_FITTER(pipe)); @@ -5674,7 +5674,7 @@ static u64 get_crtc_power_domains(struct drm_crtc *crtc, } if (HAS_DDI(dev_priv) && crtc_state->has_audio) - mask |= BIT(POWER_DOMAIN_AUDIO); + mask |= BIT_ULL(POWER_DOMAIN_AUDIO); if (crtc_state->shared_dpll) mask |= BIT_ULL(POWER_DOMAIN_PLLS); From c950af50e5983a119bebedceed94ef505df8d552 Mon Sep 17 00:00:00 2001 From: Sagar Arun Kamble Date: Wed, 10 Jan 2018 18:24:16 +0530 Subject: [PATCH 079/237] drm/i915/guc: Add uc_fini_wq in gem_init unwind path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit While moving code around for solving lockdep issue for GuC log relay, spotted that uc_fini_wq is not being called in failure path in gem_init. Missed in the below commit. Add it. v2: Removed GEM_BUG_ON(!HAS_GUC()) from intel_uc_fini_wq as init happens only based on enable_guc module parameter and does not consider has_guc capability. (Michal) Signed-off-by: Sagar Arun Kamble Fixes: 3176ff49bc3e ("drm/i915/guc: Move GuC workqueue allocations outside of the mutex") Cc: MichaÅ‚ Winiarski Cc: Chris Wilson Reviewed-by: MichaÅ‚ Winiarski Link: https://patchwork.freedesktop.org/patch/msgid/1515588857-10283-1-git-send-email-sagar.a.kamble@intel.com Signed-off-by: Chris Wilson (cherry picked from commit da943b5ab071584fcb9cfa896dc8c643d376f362) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_gem.c | 2 ++ drivers/gpu/drm/i915/intel_uc.c | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 8bc3283484be22..1135a77b383ae7 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -5283,6 +5283,8 @@ int i915_gem_init(struct drm_i915_private *dev_priv) intel_uncore_forcewake_put(dev_priv, FORCEWAKE_ALL); mutex_unlock(&dev_priv->drm.struct_mutex); + intel_uc_fini_wq(dev_priv); + if (ret != -EIO) i915_gem_cleanup_userptr(dev_priv); diff --git a/drivers/gpu/drm/i915/intel_uc.c b/drivers/gpu/drm/i915/intel_uc.c index 907deac6e3fa8c..d82ca0f438f529 100644 --- a/drivers/gpu/drm/i915/intel_uc.c +++ b/drivers/gpu/drm/i915/intel_uc.c @@ -209,8 +209,6 @@ void intel_uc_fini_wq(struct drm_i915_private *dev_priv) if (!USES_GUC(dev_priv)) return; - GEM_BUG_ON(!HAS_GUC(dev_priv)); - intel_guc_fini_wq(&dev_priv->guc); } From 25da77f83068bfc95d08ddfb8e6c53983901e278 Mon Sep 17 00:00:00 2001 From: Oscar Mateo Date: Fri, 22 Dec 2017 14:38:49 -0800 Subject: [PATCH 080/237] drm/i915: Stop getting the fault address from RING_FAULT_REG This register does not contain it. Instead, we have to look into FAULT_TLB_DATA0 & 1 (where, by the way, we can also get the address space). v2: Right formatting v3: - Use 12 (as per the register format) instead of PAGE_SIZE (Chris) - s/BITS_44_TO_47/HIGHBITS (Chris) - Right formatting, this time for real Fixes: b03ec3d67ab8 ("drm/i915: There is only one fault register from GEN8 onwards") Signed-off-by: Oscar Mateo Cc: Michel Thierry Cc: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/1513982329-32191-1-git-send-email-oscar.mateo@intel.com Reviewed-by: Michel Thierry Signed-off-by: Chris Wilson (cherry picked from commit 5a3f58dfd1420347be838546e00a4a9e847bda30) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_gem_gtt.c | 15 +++++++++++++-- drivers/gpu/drm/i915/i915_reg.h | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index c5f393870532f5..0de4f3f13fc483 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -2287,12 +2287,23 @@ static void gen8_check_and_clear_faults(struct drm_i915_private *dev_priv) u32 fault = I915_READ(GEN8_RING_FAULT_REG); if (fault & RING_FAULT_VALID) { + u32 fault_data0, fault_data1; + u64 fault_addr; + + fault_data0 = I915_READ(GEN8_FAULT_TLB_DATA0); + fault_data1 = I915_READ(GEN8_FAULT_TLB_DATA1); + fault_addr = ((u64)(fault_data1 & FAULT_VA_HIGH_BITS) << 44) | + ((u64)fault_data0 << 12); + DRM_DEBUG_DRIVER("Unexpected fault\n" - "\tAddr: 0x%08lx\n" + "\tAddr: 0x%08x_%08x\n" + "\tAddress space: %s\n" "\tEngine ID: %d\n" "\tSource ID: %d\n" "\tType: %d\n", - fault & PAGE_MASK, + upper_32_bits(fault_addr), + lower_32_bits(fault_addr), + fault_data1 & FAULT_GTT_SEL ? "GGTT" : "PPGTT", GEN8_RING_FAULT_ENGINE_ID(fault), RING_FAULT_SRCID(fault), RING_FAULT_FAULT_TYPE(fault)); diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 505c605eff9892..a2108e35c59998 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2489,6 +2489,8 @@ enum i915_power_well_id { #define GEN8_FAULT_TLB_DATA0 _MMIO(0x4b10) #define GEN8_FAULT_TLB_DATA1 _MMIO(0x4b14) +#define FAULT_VA_HIGH_BITS (0xf << 0) +#define FAULT_GTT_SEL (1 << 4) #define FPGA_DBG _MMIO(0x42300) #define FPGA_DBG_RM_NOCLAIM (1<<31) From cc4f8fc72eb949889caa1d574d3db65fa9d71a12 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 11 Jan 2018 07:30:31 +0000 Subject: [PATCH 081/237] drm/i915/pmu: Reconstruct active state on starting busy-stats We have a hole in our busy-stat accounting if the pmu is enabled during a long running batch, the pmu will not start accumulating busy-time until the next context switch. This then fails tests that are only sampling a single batch. v2: Count each active port just once (context in/out events are only on the first and last assignment to a port). v3: Avoid hardcoding knowledge of 2 submission ports Fixes: 30e17b7847f5 ("drm/i915: Engine busy time tracking") Testcase: igt/perf_pmu/busy-start Testcase: igt/perf_pmu/busy-double-start Signed-off-by: Chris Wilson Cc: Tvrtko Ursulin Reviewed-by: Tvrtko Ursulin Link: https://patchwork.freedesktop.org/patch/msgid/20180111073031.14614-1-chris@chris-wilson.co.uk (cherry picked from commit 4900727d35bb20028f9bd83146ec4bf78afffe30) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_engine_cs.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_engine_cs.c b/drivers/gpu/drm/i915/intel_engine_cs.c index 6bb51a502b8b4e..d790bdc227ffb5 100644 --- a/drivers/gpu/drm/i915/intel_engine_cs.c +++ b/drivers/gpu/drm/i915/intel_engine_cs.c @@ -1951,8 +1951,22 @@ int intel_enable_engine_stats(struct intel_engine_cs *engine) spin_lock_irqsave(&engine->stats.lock, flags); if (engine->stats.enabled == ~0) goto busy; - if (engine->stats.enabled++ == 0) + if (engine->stats.enabled++ == 0) { + struct intel_engine_execlists *execlists = &engine->execlists; + const struct execlist_port *port = execlists->port; + unsigned int num_ports = execlists_num_ports(execlists); + engine->stats.enabled_at = ktime_get(); + + /* XXX submission method oblivious? */ + while (num_ports-- && port_isset(port)) { + engine->stats.active++; + port++; + } + + if (engine->stats.active) + engine->stats.start = engine->stats.enabled_at; + } spin_unlock_irqrestore(&engine->stats.lock, flags); return 0; From 412718a10926f77052d8107cb3c5d9dbc96cf8c9 Mon Sep 17 00:00:00 2001 From: Tina Zhang Date: Mon, 15 Jan 2018 14:41:42 +0800 Subject: [PATCH 082/237] drm/i915/gvt: Keep obj->dma_buf link NULL during exporting According to commit (319c933c71f3dbdb2b3274d1634d3494c70efa06) Author: Daniel Vetter Date: Thu Aug 15 00:02:46 2013 +0200 drm/prime: proper locking+refcounting for obj->dma_buf link obj->dma_buf link should be reinstated at import time. Gvt-g dma-buf buffer exposeing might be simpler, as there won't be much racing during Gvt-g dma-buf exposing. In other words, Gvt-g dma-buf exposing can guarantee exposing happens before gem close ioctl, and Gvt-g is the only exporter of the guest framebuffer. But following the drm prime scheme can give Gvt-g a chance to increase a dma-buf reference count during importing. Otherwise, we have to increase the reference during exposing, which will break the case that the only reference userspace has held was through the dma-buf fd and the reference count is one. Signed-off-by: Tina Zhang Cc: Daniel Vetter Cc: Zhenyu Wang Cc: Zhi Wang Cc: Hang Yuan Cc: Gerd Hoffmann Signed-off-by: Zhenyu Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/dmabuf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c index 2ab584f97dfb6a..2fb7b34ef561ef 100644 --- a/drivers/gpu/drm/i915/gvt/dmabuf.c +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c @@ -472,7 +472,6 @@ int intel_vgpu_get_dmabuf(struct intel_vgpu *vgpu, unsigned int dmabuf_id) ret = PTR_ERR(dmabuf); goto out_free_gem; } - obj->base.dma_buf = dmabuf; i915_gem_object_put(obj); From 14b4434bff1aab69f3785bc67276efbff7fffa3d Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 15 Jan 2018 16:36:11 +0800 Subject: [PATCH 083/237] drm/i915/gvt: cancel virtual vblank timer when no vGPU exists Stop irq timer for virtual vblank timer emulation if no vGPU exists, otherwise it will keep gvt service thread busy to handle virtual vblank but no use. Reviewed-by: Zhi Wang Signed-off-by: Zhenyu Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/vgpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index 4688619f6a1cab..a8784fa91289c8 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -258,6 +258,8 @@ void intel_gvt_destroy_vgpu(struct intel_vgpu *vgpu) intel_gvt_debugfs_remove_vgpu(vgpu); idr_remove(&gvt->vgpu_idr, vgpu->id); + if (idr_is_empty(&gvt->vgpu_idr)) + intel_gvt_clean_irq(gvt); intel_vgpu_clean_sched_policy(vgpu); intel_vgpu_clean_submission(vgpu); intel_vgpu_clean_display(vgpu); From 61a669473f82cd5cac66146644b829b370c791ca Mon Sep 17 00:00:00 2001 From: Zhenyu Wang Date: Mon, 15 Jan 2018 16:36:12 +0800 Subject: [PATCH 084/237] drm/i915/gvt: cancel scheduler timer when no vGPU exists Stop gvt scheduler timer if no vGPU exists, otherwise it keeps gvt service thread busy to handle request schedule event but no actual schedule activity required. Reviewed-by: Zhi Wang Signed-off-by: Zhenyu Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/sched_policy.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index eea1a2f920990a..d031f6486ce3fa 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c @@ -308,8 +308,15 @@ static int tbs_sched_init_vgpu(struct intel_vgpu *vgpu) static void tbs_sched_clean_vgpu(struct intel_vgpu *vgpu) { + struct intel_gvt *gvt = vgpu->gvt; + struct gvt_sched_data *sched_data = gvt->scheduler.sched_data; + kfree(vgpu->sched_data); vgpu->sched_data = NULL; + + /* this vgpu id has been removed */ + if (idr_is_empty(&gvt->vgpu_idr)) + hrtimer_cancel(&sched_data->timer); } static void tbs_sched_start_schedule(struct intel_vgpu *vgpu) From d13a8479f3584613b6aacbb793eae64578b8f69a Mon Sep 17 00:00:00 2001 From: Maarten Lankhorst Date: Tue, 16 Jan 2018 16:53:24 +0100 Subject: [PATCH 085/237] drm/i915: Always call to intel_display_set_init_power() in resume_early. intel_power_domains_init_hw() calls set_init_power, but when using runtime power management this call is skipped. This prevents hw readout from taking place. Signed-off-by: Maarten Lankhorst Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104172 Link: https://patchwork.freedesktop.org/patch/msgid/20180116155324.75120-1-maarten.lankhorst@linux.intel.com Fixes: bc87229f323e ("drm/i915/skl: enable PC9/10 power states during suspend-to-idle") Cc: Nivedita Swaminathan Cc: Imre Deak Cc: Patrik Jakobsson Cc: Jani Nikula Cc: Joonas Lahtinen Cc: Rodrigo Vivi Cc: # v4.5+ Reviewed-by: Imre Deak (cherry picked from commit ac25dfed15d470d7f23dd817e965b54aa3f94a1e) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 6c8da9d20c3322..173d0095e3b212 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1842,6 +1842,8 @@ static int i915_drm_resume_early(struct drm_device *dev) if (IS_GEN9_LP(dev_priv) || !(dev_priv->suspended_to_idle && dev_priv->csr.dmc_payload)) intel_power_domains_init_hw(dev_priv, true); + else + intel_display_set_init_power(dev_priv, true); i915_gem_sanitize(dev_priv); From c5bd1fc9a6c843c85a5cea5765cdc997f832df3c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 15 Jan 2018 21:24:46 +0000 Subject: [PATCH 086/237] drm/i915: Only attempt to scan the requested number of shrinker slabs Since commit 4e773c3a8a69 ("drm/i915: Wire up shrinkctl->nr_scanned"), we track the number of objects we scan and do not wish to exceed that as it will overly penalise our own slabs under mempressure. Given that we now know the target number of objects to scan, use that as our guide for deciding to shrink as opposed to the number of objects we manage to shrink (which doesn't correspond to the numbers we report to shrinkctl). Fixes: 4e773c3a8a69 ("drm/i915: Wire up shrinkctl->nr_scanned") Signed-off-by: Chris Wilson Cc: Joonas Lahtinen Link: https://patchwork.freedesktop.org/patch/msgid/20180115212455.24046-2-chris@chris-wilson.co.uk Reviewed-by: Tvrtko Ursulin (cherry picked from commit 29d384e34c55d696cf37bd4159e05f4b14d45da0) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_gem_shrinker.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_shrinker.c b/drivers/gpu/drm/i915/i915_gem_shrinker.c index 9029ed04879c30..0e158f9287c46e 100644 --- a/drivers/gpu/drm/i915/i915_gem_shrinker.c +++ b/drivers/gpu/drm/i915/i915_gem_shrinker.c @@ -363,13 +363,13 @@ i915_gem_shrinker_scan(struct shrinker *shrinker, struct shrink_control *sc) I915_SHRINK_BOUND | I915_SHRINK_UNBOUND | I915_SHRINK_PURGEABLE); - if (freed < sc->nr_to_scan) + if (sc->nr_scanned < sc->nr_to_scan) freed += i915_gem_shrink(i915, sc->nr_to_scan - sc->nr_scanned, &sc->nr_scanned, I915_SHRINK_BOUND | I915_SHRINK_UNBOUND); - if (freed < sc->nr_to_scan && current_is_kswapd()) { + if (sc->nr_scanned < sc->nr_to_scan && current_is_kswapd()) { intel_runtime_pm_get(i915); freed += i915_gem_shrink(i915, sc->nr_to_scan - sc->nr_scanned, From 124804c4c4b2e84e956cedd17878562e230a907f Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 21 Jan 2018 17:31:43 +0000 Subject: [PATCH 087/237] drm/i915: Protect WC stash allocation against direct reclaim As we attempt to allocate pages for use in a new WC stash, direct reclaim may run underneath us and fill up the WC stash. We have to be careful then not to overflow the pvec. Fixes: 66df1014efba ("drm/i915: Keep a small stash of preallocated WC pages") Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103109 Signed-off-by: Chris Wilson Cc: Matthew Auld Cc: Joonas Lahtinen Reviewed-by: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20180121173143.17090-1-chris@chris-wilson.co.uk (cherry picked from commit 073cd7816685ac77c6d8b4d321a5586c9177b76a) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_gem_gtt.c | 32 ++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 0de4f3f13fc483..133cb9590003dd 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -377,6 +377,7 @@ static gen6_pte_t iris_pte_encode(dma_addr_t addr, static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp) { struct pagevec *pvec = &vm->free_pages; + struct pagevec stash; if (I915_SELFTEST_ONLY(should_fail(&vm->fault_attr, 1))) i915_gem_shrink_all(vm->i915); @@ -395,7 +396,15 @@ static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp) if (likely(pvec->nr)) return pvec->pages[--pvec->nr]; - /* Otherwise batch allocate pages to amoritize cost of set_pages_wc. */ + /* + * Otherwise batch allocate pages to amoritize cost of set_pages_wc. + * + * We have to be careful as page allocation may trigger the shrinker + * (via direct reclaim) which will fill up the WC stash underneath us. + * So we add our WB pages into a temporary pvec on the stack and merge + * them into the WC stash after all the allocations are complete. + */ + pagevec_init(&stash); do { struct page *page; @@ -403,15 +412,24 @@ static struct page *vm_alloc_page(struct i915_address_space *vm, gfp_t gfp) if (unlikely(!page)) break; - pvec->pages[pvec->nr++] = page; - } while (pagevec_space(pvec)); + stash.pages[stash.nr++] = page; + } while (stash.nr < pagevec_space(pvec)); - if (unlikely(!pvec->nr)) - return NULL; + if (stash.nr) { + int nr = min_t(int, stash.nr, pagevec_space(pvec)); + struct page **pages = stash.pages + stash.nr - nr; - set_pages_array_wc(pvec->pages, pvec->nr); + if (nr && !set_pages_array_wc(pages, nr)) { + memcpy(pvec->pages + pvec->nr, + pages, sizeof(pages[0]) * nr); + pvec->nr += nr; + stash.nr -= nr; + } + + pagevec_release(&stash); + } - return pvec->pages[--pvec->nr]; + return likely(pvec->nr) ? pvec->pages[--pvec->nr] : NULL; } static void vm_free_pages_release(struct i915_address_space *vm, From 9965db26ac0548648309f506dc155a92daa2158f Mon Sep 17 00:00:00 2001 From: Mika Kahola Date: Mon, 18 Dec 2017 10:04:03 +0200 Subject: [PATCH 088/237] drm/i915: Check for fused or unused pipes We may have fused or unused pipes in our system. Let's check that the pipe in question is within limits of accessible pipes. In case, that we are not able to access the pipe, we return early with a warning. v2: Rephrasing of the commit message (Jani) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103206 Reported-by: Thomas Gleixner Tested-by: Jaswinder Singh Rajput Suggested-by: Jani Nikula Reviewed-by: Jani Nikula Signed-off-by: Mika Kahola Signed-off-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/1513584243-12607-1-git-send-email-mika.kahola@intel.com (cherry picked from commit 0b7029b7e43fda1304c181a3ade0b429b9edcd9d) Signed-off-by: Rodrigo Vivi Cc: # v4.10+ --- drivers/gpu/drm/i915/intel_audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index f1502a0188eb23..522d54fecb5348 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -779,7 +779,7 @@ static struct intel_encoder *get_saved_enc(struct drm_i915_private *dev_priv, { struct intel_encoder *encoder; - if (WARN_ON(pipe >= INTEL_INFO(dev_priv)->num_pipes)) + if (WARN_ON(pipe >= ARRAY_SIZE(dev_priv->av_enc_map))) return NULL; /* MST */ From a306343bcd7df89d9d45a601929e26866e7b7a81 Mon Sep 17 00:00:00 2001 From: Manasi Navare Date: Thu, 12 Oct 2017 12:13:38 -0700 Subject: [PATCH 089/237] drm/i915/edp: Do not do link training fallback or prune modes on EDP In case of eDP because the panel has a fixed mode, the link rate and lane count at which it is trained corresponds to the link BW required to support the native resolution of the panel. In case of panles with lower resolutions where fewer lanes are hooked up internally, that number is reflected in the MAX_LANE_COUNT DPCD register of the panel. So it is pointless to fallback to lower link rate/lane count in case of link training failure on eDP connector since the lower link BW will not support the native resolution of the panel and we cannot prune the preferred mode on the eDP connector. In case of Link training failure on the eDP panel, something is wrong in the HW internally and hence driver errors out with a loud and clear DRM_ERROR message. v2: * Fix the DEBUG_ERROR and add {} in else (Ville Syrjala) Cc: Clinton Taylor Cc: Jim Bride Cc: Jani Nikula Cc: Ville Syrjala Cc: Dave Airlie Cc: Daniel Vetter Signed-off-by: Manasi Navare Reviewed-by: Ville Syrjala Reference: https://bugs.freedesktop.org/show_bug.cgi?id=103369 Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/1507835618-23051-1-git-send-email-manasi.d.navare@intel.com (cherry picked from commit c0cfb10d9e1de490e36d3b9d4228c0ea0ca30677) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_dp_link_training.c | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_dp_link_training.c b/drivers/gpu/drm/i915/intel_dp_link_training.c index 05907fa8a553dc..cf8fef8b6f58e7 100644 --- a/drivers/gpu/drm/i915/intel_dp_link_training.c +++ b/drivers/gpu/drm/i915/intel_dp_link_training.c @@ -328,14 +328,22 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) return; failure_handling: - DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d", - intel_connector->base.base.id, - intel_connector->base.name, - intel_dp->link_rate, intel_dp->lane_count); - if (!intel_dp_get_link_train_fallback_values(intel_dp, - intel_dp->link_rate, - intel_dp->lane_count)) - /* Schedule a Hotplug Uevent to userspace to start modeset */ - schedule_work(&intel_connector->modeset_retry_work); + /* Dont fallback and prune modes if its eDP */ + if (!intel_dp_is_edp(intel_dp)) { + DRM_DEBUG_KMS("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d", + intel_connector->base.base.id, + intel_connector->base.name, + intel_dp->link_rate, intel_dp->lane_count); + if (!intel_dp_get_link_train_fallback_values(intel_dp, + intel_dp->link_rate, + intel_dp->lane_count)) + /* Schedule a Hotplug Uevent to userspace to start modeset */ + schedule_work(&intel_connector->modeset_retry_work); + } else { + DRM_ERROR("[CONNECTOR:%d:%s] Link Training failed at link rate = %d, lane count = %d", + intel_connector->base.base.id, + intel_connector->base.name, + intel_dp->link_rate, intel_dp->lane_count); + } return; } From b5a756a722286af9702d565501e1f690d075d16b Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Mon, 29 Jan 2018 08:33:46 +0000 Subject: [PATCH 090/237] Revert "drm/i915: mark all device info struct with __initconst" This reverts commit 5b54eddd3920e9f6f1a6d972454baf350cbae77e. Conflicts: drivers/gpu/drm/i915/i915_pci.c Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104805 Signed-off-by: Lionel Landwerlin Reviewed-by: Chris Wilson Fixes: 5b54eddd3920 ("drm/i915: mark all device info struct with __initconst") Link: https://patchwork.freedesktop.org/patch/msgid/20180129083346.29173-1-lionel.g.landwerlin@intel.com (cherry picked from commit 5db47e37b38755c5e26e6b8fbc1a32ce73495940) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_pci.c | 94 ++++++++++++++++----------------- 1 file changed, 47 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_pci.c b/drivers/gpu/drm/i915/i915_pci.c index 36d48422b4752a..1c30c688f23a4a 100644 --- a/drivers/gpu/drm/i915/i915_pci.c +++ b/drivers/gpu/drm/i915/i915_pci.c @@ -74,19 +74,19 @@ GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS -static const struct intel_device_info intel_i830_info __initconst = { +static const struct intel_device_info intel_i830_info = { GEN2_FEATURES, .platform = INTEL_I830, .is_mobile = 1, .cursor_needs_physical = 1, .num_pipes = 2, /* legal, last one wins */ }; -static const struct intel_device_info intel_i845g_info __initconst = { +static const struct intel_device_info intel_i845g_info = { GEN2_FEATURES, .platform = INTEL_I845G, }; -static const struct intel_device_info intel_i85x_info __initconst = { +static const struct intel_device_info intel_i85x_info = { GEN2_FEATURES, .platform = INTEL_I85X, .is_mobile = 1, .num_pipes = 2, /* legal, last one wins */ @@ -94,7 +94,7 @@ static const struct intel_device_info intel_i85x_info __initconst = { .has_fbc = 1, }; -static const struct intel_device_info intel_i865g_info __initconst = { +static const struct intel_device_info intel_i865g_info = { GEN2_FEATURES, .platform = INTEL_I865G, }; @@ -108,7 +108,7 @@ static const struct intel_device_info intel_i865g_info __initconst = { GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS -static const struct intel_device_info intel_i915g_info __initconst = { +static const struct intel_device_info intel_i915g_info = { GEN3_FEATURES, .platform = INTEL_I915G, .cursor_needs_physical = 1, .has_overlay = 1, .overlay_needs_physical = 1, @@ -116,7 +116,7 @@ static const struct intel_device_info intel_i915g_info __initconst = { .unfenced_needs_alignment = 1, }; -static const struct intel_device_info intel_i915gm_info __initconst = { +static const struct intel_device_info intel_i915gm_info = { GEN3_FEATURES, .platform = INTEL_I915GM, .is_mobile = 1, @@ -128,7 +128,7 @@ static const struct intel_device_info intel_i915gm_info __initconst = { .unfenced_needs_alignment = 1, }; -static const struct intel_device_info intel_i945g_info __initconst = { +static const struct intel_device_info intel_i945g_info = { GEN3_FEATURES, .platform = INTEL_I945G, .has_hotplug = 1, .cursor_needs_physical = 1, @@ -137,7 +137,7 @@ static const struct intel_device_info intel_i945g_info __initconst = { .unfenced_needs_alignment = 1, }; -static const struct intel_device_info intel_i945gm_info __initconst = { +static const struct intel_device_info intel_i945gm_info = { GEN3_FEATURES, .platform = INTEL_I945GM, .is_mobile = 1, .has_hotplug = 1, .cursor_needs_physical = 1, @@ -148,14 +148,14 @@ static const struct intel_device_info intel_i945gm_info __initconst = { .unfenced_needs_alignment = 1, }; -static const struct intel_device_info intel_g33_info __initconst = { +static const struct intel_device_info intel_g33_info = { GEN3_FEATURES, .platform = INTEL_G33, .has_hotplug = 1, .has_overlay = 1, }; -static const struct intel_device_info intel_pineview_info __initconst = { +static const struct intel_device_info intel_pineview_info = { GEN3_FEATURES, .platform = INTEL_PINEVIEW, .is_mobile = 1, .has_hotplug = 1, @@ -172,7 +172,7 @@ static const struct intel_device_info intel_pineview_info __initconst = { GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS -static const struct intel_device_info intel_i965g_info __initconst = { +static const struct intel_device_info intel_i965g_info = { GEN4_FEATURES, .platform = INTEL_I965G, .has_overlay = 1, @@ -180,7 +180,7 @@ static const struct intel_device_info intel_i965g_info __initconst = { .has_snoop = false, }; -static const struct intel_device_info intel_i965gm_info __initconst = { +static const struct intel_device_info intel_i965gm_info = { GEN4_FEATURES, .platform = INTEL_I965GM, .is_mobile = 1, .has_fbc = 1, @@ -190,13 +190,13 @@ static const struct intel_device_info intel_i965gm_info __initconst = { .has_snoop = false, }; -static const struct intel_device_info intel_g45_info __initconst = { +static const struct intel_device_info intel_g45_info = { GEN4_FEATURES, .platform = INTEL_G45, .ring_mask = RENDER_RING | BSD_RING, }; -static const struct intel_device_info intel_gm45_info __initconst = { +static const struct intel_device_info intel_gm45_info = { GEN4_FEATURES, .platform = INTEL_GM45, .is_mobile = 1, .has_fbc = 1, @@ -215,12 +215,12 @@ static const struct intel_device_info intel_gm45_info __initconst = { GEN_DEFAULT_PAGE_SIZES, \ CURSOR_OFFSETS -static const struct intel_device_info intel_ironlake_d_info __initconst = { +static const struct intel_device_info intel_ironlake_d_info = { GEN5_FEATURES, .platform = INTEL_IRONLAKE, }; -static const struct intel_device_info intel_ironlake_m_info __initconst = { +static const struct intel_device_info intel_ironlake_m_info = { GEN5_FEATURES, .platform = INTEL_IRONLAKE, .is_mobile = 1, .has_fbc = 1, @@ -243,12 +243,12 @@ static const struct intel_device_info intel_ironlake_m_info __initconst = { GEN6_FEATURES, \ .platform = INTEL_SANDYBRIDGE -static const struct intel_device_info intel_sandybridge_d_gt1_info __initconst = { +static const struct intel_device_info intel_sandybridge_d_gt1_info = { SNB_D_PLATFORM, .gt = 1, }; -static const struct intel_device_info intel_sandybridge_d_gt2_info __initconst = { +static const struct intel_device_info intel_sandybridge_d_gt2_info = { SNB_D_PLATFORM, .gt = 2, }; @@ -259,12 +259,12 @@ static const struct intel_device_info intel_sandybridge_d_gt2_info __initconst = .is_mobile = 1 -static const struct intel_device_info intel_sandybridge_m_gt1_info __initconst = { +static const struct intel_device_info intel_sandybridge_m_gt1_info = { SNB_M_PLATFORM, .gt = 1, }; -static const struct intel_device_info intel_sandybridge_m_gt2_info __initconst = { +static const struct intel_device_info intel_sandybridge_m_gt2_info = { SNB_M_PLATFORM, .gt = 2, }; @@ -288,12 +288,12 @@ static const struct intel_device_info intel_sandybridge_m_gt2_info __initconst = .platform = INTEL_IVYBRIDGE, \ .has_l3_dpf = 1 -static const struct intel_device_info intel_ivybridge_d_gt1_info __initconst = { +static const struct intel_device_info intel_ivybridge_d_gt1_info = { IVB_D_PLATFORM, .gt = 1, }; -static const struct intel_device_info intel_ivybridge_d_gt2_info __initconst = { +static const struct intel_device_info intel_ivybridge_d_gt2_info = { IVB_D_PLATFORM, .gt = 2, }; @@ -304,17 +304,17 @@ static const struct intel_device_info intel_ivybridge_d_gt2_info __initconst = { .is_mobile = 1, \ .has_l3_dpf = 1 -static const struct intel_device_info intel_ivybridge_m_gt1_info __initconst = { +static const struct intel_device_info intel_ivybridge_m_gt1_info = { IVB_M_PLATFORM, .gt = 1, }; -static const struct intel_device_info intel_ivybridge_m_gt2_info __initconst = { +static const struct intel_device_info intel_ivybridge_m_gt2_info = { IVB_M_PLATFORM, .gt = 2, }; -static const struct intel_device_info intel_ivybridge_q_info __initconst = { +static const struct intel_device_info intel_ivybridge_q_info = { GEN7_FEATURES, .platform = INTEL_IVYBRIDGE, .gt = 2, @@ -322,7 +322,7 @@ static const struct intel_device_info intel_ivybridge_q_info __initconst = { .has_l3_dpf = 1, }; -static const struct intel_device_info intel_valleyview_info __initconst = { +static const struct intel_device_info intel_valleyview_info = { .platform = INTEL_VALLEYVIEW, .gen = 7, .is_lp = 1, @@ -358,17 +358,17 @@ static const struct intel_device_info intel_valleyview_info __initconst = { .platform = INTEL_HASWELL, \ .has_l3_dpf = 1 -static const struct intel_device_info intel_haswell_gt1_info __initconst = { +static const struct intel_device_info intel_haswell_gt1_info = { HSW_PLATFORM, .gt = 1, }; -static const struct intel_device_info intel_haswell_gt2_info __initconst = { +static const struct intel_device_info intel_haswell_gt2_info = { HSW_PLATFORM, .gt = 2, }; -static const struct intel_device_info intel_haswell_gt3_info __initconst = { +static const struct intel_device_info intel_haswell_gt3_info = { HSW_PLATFORM, .gt = 3, }; @@ -388,17 +388,17 @@ static const struct intel_device_info intel_haswell_gt3_info __initconst = { .gen = 8, \ .platform = INTEL_BROADWELL -static const struct intel_device_info intel_broadwell_gt1_info __initconst = { +static const struct intel_device_info intel_broadwell_gt1_info = { BDW_PLATFORM, .gt = 1, }; -static const struct intel_device_info intel_broadwell_gt2_info __initconst = { +static const struct intel_device_info intel_broadwell_gt2_info = { BDW_PLATFORM, .gt = 2, }; -static const struct intel_device_info intel_broadwell_rsvd_info __initconst = { +static const struct intel_device_info intel_broadwell_rsvd_info = { BDW_PLATFORM, .gt = 3, /* According to the device ID those devices are GT3, they were @@ -406,13 +406,13 @@ static const struct intel_device_info intel_broadwell_rsvd_info __initconst = { */ }; -static const struct intel_device_info intel_broadwell_gt3_info __initconst = { +static const struct intel_device_info intel_broadwell_gt3_info = { BDW_PLATFORM, .gt = 3, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, }; -static const struct intel_device_info intel_cherryview_info __initconst = { +static const struct intel_device_info intel_cherryview_info = { .gen = 8, .num_pipes = 3, .has_hotplug = 1, .is_lp = 1, @@ -455,12 +455,12 @@ static const struct intel_device_info intel_cherryview_info __initconst = { .gen = 9, \ .platform = INTEL_SKYLAKE -static const struct intel_device_info intel_skylake_gt1_info __initconst = { +static const struct intel_device_info intel_skylake_gt1_info = { SKL_PLATFORM, .gt = 1, }; -static const struct intel_device_info intel_skylake_gt2_info __initconst = { +static const struct intel_device_info intel_skylake_gt2_info = { SKL_PLATFORM, .gt = 2, }; @@ -470,12 +470,12 @@ static const struct intel_device_info intel_skylake_gt2_info __initconst = { .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING -static const struct intel_device_info intel_skylake_gt3_info __initconst = { +static const struct intel_device_info intel_skylake_gt3_info = { SKL_GT3_PLUS_PLATFORM, .gt = 3, }; -static const struct intel_device_info intel_skylake_gt4_info __initconst = { +static const struct intel_device_info intel_skylake_gt4_info = { SKL_GT3_PLUS_PLATFORM, .gt = 4, }; @@ -511,13 +511,13 @@ static const struct intel_device_info intel_skylake_gt4_info __initconst = { IVB_CURSOR_OFFSETS, \ BDW_COLORS -static const struct intel_device_info intel_broxton_info __initconst = { +static const struct intel_device_info intel_broxton_info = { GEN9_LP_FEATURES, .platform = INTEL_BROXTON, .ddb_size = 512, }; -static const struct intel_device_info intel_geminilake_info __initconst = { +static const struct intel_device_info intel_geminilake_info = { GEN9_LP_FEATURES, .platform = INTEL_GEMINILAKE, .ddb_size = 1024, @@ -529,17 +529,17 @@ static const struct intel_device_info intel_geminilake_info __initconst = { .gen = 9, \ .platform = INTEL_KABYLAKE -static const struct intel_device_info intel_kabylake_gt1_info __initconst = { +static const struct intel_device_info intel_kabylake_gt1_info = { KBL_PLATFORM, .gt = 1, }; -static const struct intel_device_info intel_kabylake_gt2_info __initconst = { +static const struct intel_device_info intel_kabylake_gt2_info = { KBL_PLATFORM, .gt = 2, }; -static const struct intel_device_info intel_kabylake_gt3_info __initconst = { +static const struct intel_device_info intel_kabylake_gt3_info = { KBL_PLATFORM, .gt = 3, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, @@ -550,17 +550,17 @@ static const struct intel_device_info intel_kabylake_gt3_info __initconst = { .gen = 9, \ .platform = INTEL_COFFEELAKE -static const struct intel_device_info intel_coffeelake_gt1_info __initconst = { +static const struct intel_device_info intel_coffeelake_gt1_info = { CFL_PLATFORM, .gt = 1, }; -static const struct intel_device_info intel_coffeelake_gt2_info __initconst = { +static const struct intel_device_info intel_coffeelake_gt2_info = { CFL_PLATFORM, .gt = 2, }; -static const struct intel_device_info intel_coffeelake_gt3_info __initconst = { +static const struct intel_device_info intel_coffeelake_gt3_info = { CFL_PLATFORM, .gt = 3, .ring_mask = RENDER_RING | BSD_RING | BLT_RING | VEBOX_RING | BSD2_RING, @@ -571,7 +571,7 @@ static const struct intel_device_info intel_coffeelake_gt3_info __initconst = { .ddb_size = 1024, \ GLK_COLORS -static const struct intel_device_info intel_cannonlake_gt2_info __initconst = { +static const struct intel_device_info intel_cannonlake_gt2_info = { GEN10_FEATURES, .is_alpha_support = 1, .platform = INTEL_CANNONLAKE, From b26a32a82a901f894c79d1ec8b1ac94dde83e83c Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Mon, 29 Jan 2018 14:41:04 +0000 Subject: [PATCH 091/237] drm/i915: Always run hangcheck while the GPU is busy Previously, we relied on only running the hangcheck while somebody was waiting on the GPU, in order to minimise the amount of time hangcheck had to run. (If nobody was watching the GPU, nobody would notice if the GPU wasn't responding -- eventually somebody would care and so kick hangcheck into action.) However, this falls apart from around commit 4680816be336 ("drm/i915: Wait first for submission, before waiting for request completion"), as not all waiters declare themselves to hangcheck and so we could switch off hangcheck and miss GPU hangs even when waiting under the struct_mutex. If we enable hangcheck from the first request submission, and let it run until the GPU is idle again, we forgo all the complexity involved with only enabling around waiters. We just have to remember to be careful that we do not declare a GPU hang when idly waiting for the next request to be come ready, as we will run hangcheck continuously even when the engines are stalled waiting for external events. This should be true already as we should only be tracking requests submitted to hardware for execution as an indicator that the engine is busy. Fixes: 4680816be336 ("drm/i915: Wait first for submission, before waiting for request completion" Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104840 Signed-off-by: Chris Wilson Cc: Chris Wilson Cc: Mika Kuoppala Link: https://patchwork.freedesktop.org/patch/msgid/20180129144104.3921-1-chris@chris-wilson.co.uk Reviewed-by: Mika Kuoppala (cherry picked from commit 889230489b6b138ba97ba2f13fc9644a3d16d0d2) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_gem.c | 7 +++---- drivers/gpu/drm/i915/i915_gem_request.c | 2 ++ drivers/gpu/drm/i915/intel_breadcrumbs.c | 11 ----------- drivers/gpu/drm/i915/intel_hangcheck.c | 7 +------ 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 1135a77b383ae7..dd89abd2263d20 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -3323,16 +3323,15 @@ i915_gem_retire_work_handler(struct work_struct *work) mutex_unlock(&dev->struct_mutex); } - /* Keep the retire handler running until we are finally idle. + /* + * Keep the retire handler running until we are finally idle. * We do not need to do this test under locking as in the worst-case * we queue the retire worker once too often. */ - if (READ_ONCE(dev_priv->gt.awake)) { - i915_queue_hangcheck(dev_priv); + if (READ_ONCE(dev_priv->gt.awake)) queue_delayed_work(dev_priv->wq, &dev_priv->gt.retire_work, round_jiffies_up_relative(HZ)); - } } static inline bool diff --git a/drivers/gpu/drm/i915/i915_gem_request.c b/drivers/gpu/drm/i915/i915_gem_request.c index d575109f7a7fe2..e09d18df8b7f18 100644 --- a/drivers/gpu/drm/i915/i915_gem_request.c +++ b/drivers/gpu/drm/i915/i915_gem_request.c @@ -276,6 +276,8 @@ static void mark_busy(struct drm_i915_private *i915) intel_engines_unpark(i915); + i915_queue_hangcheck(i915); + queue_delayed_work(i915->wq, &i915->gt.retire_work, round_jiffies_up_relative(HZ)); diff --git a/drivers/gpu/drm/i915/intel_breadcrumbs.c b/drivers/gpu/drm/i915/intel_breadcrumbs.c index 58c624f982d91c..bd40fea16b4f1f 100644 --- a/drivers/gpu/drm/i915/intel_breadcrumbs.c +++ b/drivers/gpu/drm/i915/intel_breadcrumbs.c @@ -149,17 +149,6 @@ static void intel_breadcrumbs_fake_irq(struct timer_list *t) return; mod_timer(&b->fake_irq, jiffies + 1); - - /* Ensure that even if the GPU hangs, we get woken up. - * - * However, note that if no one is waiting, we never notice - * a gpu hang. Eventually, we will have to wait for a resource - * held by the GPU and so trigger a hangcheck. In the most - * pathological case, this will be upon memory starvation! To - * prevent this, we also queue the hangcheck from the retire - * worker. - */ - i915_queue_hangcheck(engine->i915); } static void irq_enable(struct intel_engine_cs *engine) diff --git a/drivers/gpu/drm/i915/intel_hangcheck.c b/drivers/gpu/drm/i915/intel_hangcheck.c index 31f01d64c0212c..348a4f7ffb674b 100644 --- a/drivers/gpu/drm/i915/intel_hangcheck.c +++ b/drivers/gpu/drm/i915/intel_hangcheck.c @@ -411,7 +411,6 @@ static void i915_hangcheck_elapsed(struct work_struct *work) struct intel_engine_cs *engine; enum intel_engine_id id; unsigned int hung = 0, stuck = 0; - int busy_count = 0; if (!i915_modparams.enable_hangcheck) return; @@ -429,7 +428,6 @@ static void i915_hangcheck_elapsed(struct work_struct *work) intel_uncore_arm_unclaimed_mmio_detection(dev_priv); for_each_engine(engine, dev_priv, id) { - const bool busy = intel_engine_has_waiter(engine); struct intel_engine_hangcheck hc; semaphore_clear_deadlocks(dev_priv); @@ -443,16 +441,13 @@ static void i915_hangcheck_elapsed(struct work_struct *work) if (hc.action != ENGINE_DEAD) stuck |= intel_engine_flag(engine); } - - busy_count += busy; } if (hung) hangcheck_declare_hang(dev_priv, hung, stuck); /* Reset timer in case GPU hangs without another request being added */ - if (busy_count) - i915_queue_hangcheck(dev_priv); + i915_queue_hangcheck(dev_priv); } void intel_engine_init_hangcheck(struct intel_engine_cs *engine) From 751b01cb07ebf0dbbe4a4fbfeaa509388e4a2b0a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 31 Jan 2018 21:44:39 +0000 Subject: [PATCH 092/237] drm/i915/ppgtt: Pin page directories before allocation Commit e2b763caa6eb ("drm/i915: Remove bitmap tracking for used-pdpes") believed that because it did not insert its freshly allocated page directory into the pd tree, it was safe from the shrinker. I failed to heed the lesson learnt from commit dd19674bacba ("drm/i915: Remove bitmap tracking for used-ptes") that we need to pin all the levels in the tree before hitting the shrinker or else the shrinker may free an upper layer as we proceed to allocate the tree. Thus leaving dangling pointers everywhere and a GPF should we hit direct reclaim at just the wrong moment. CPU: 0 PID: 7374 Comm: chromium Tainted: P O 4.14.13-1-ARCH #1 Hardware name: Apple Inc. MacBookPro12,1/Mac-E43C1C25D4880AD6, BIOS MBP121.88Z.0167.B33.1706181928 06/18/2017 task: ffff994f696c2c40 task.stack: ffffb1a789d4c000 RIP: 0010:gen8_ppgtt_set_pde.isra.40+0x48/0x70 [i915] RSP: 0018:ffffb1a789d4f940 EFLAGS: 00010206 RAX: 81c1788cc4f68138 RBX: ffff994f54db8000 RCX: ffff994f696c2c40 RDX: 000000023bc73003 RSI: ffff994d598b6b80 RDI: ffff994f54db8000 RBP: ffff994d598b6b80 R08: 0000000000000000 R09: 0000000000000000 R10: ffffb1a789d4f550 R11: ffff994eaf3c3208 R12: 0000000000000027 R13: 0000000000005000 R14: 0000000004e8f000 R15: ffff994f54dba000 FS: 00007f585886aa00(0000) GS:ffff994faec00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000004ac8e8 CR3: 00000002552c8004 CR4: 00000000003606f0 Call Trace: gen8_ppgtt_alloc_pdp+0x178/0x320 [i915] gen8_ppgtt_alloc_4lvl+0x5f/0x150 [i915] ppgtt_bind_vma+0x30/0x70 [i915] i915_vma_bind+0x68/0xd0 [i915] __i915_vma_do_pin+0x2d6/0x3a0 [i915] eb_lookup_vmas+0x7a2/0xb50 [i915] i915_gem_do_execbuffer+0x4d7/0x10e0 [i915] ? sock_wfree+0x34/0x60 ? unix_stream_read_generic+0x1f9/0x7e0 ? import_iovec+0x37/0xd0 ? i915_gem_execbuffer2+0x5d/0x390 [i915] i915_gem_execbuffer2+0x1b7/0x390 [i915] ? i915_gem_execbuffer+0x2d0/0x2d0 [i915] drm_ioctl_kernel+0x59/0xb0 [drm] drm_ioctl+0x2d5/0x370 [drm] ? i915_gem_execbuffer+0x2d0/0x2d0 [i915] ? __seccomp_filter+0x3b/0x260 do_vfs_ioctl+0xa1/0x610 ? syscall_trace_enter+0xdb/0x2b0 SyS_ioctl+0x74/0x80 do_syscall_64+0x55/0x110 entry_SYSCALL64_slow_path+0x25/0x25 RIP: 0033:0x7f584fa82d27 RSP: 002b:00007ffee14a7828 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 000003b0126a1030 RCX: 00007f584fa82d27 RDX: 00007ffee14a7870 RSI: 0000000040406469 RDI: 0000000000000080 RBP: 00007ffee14a7870 R08: 0000000000000002 R09: 0000000000000077 R10: 00007f5839f2b780 R11: 0000000000000246 R12: 0000000040406469 R13: 0000000000000080 R14: 00007f5842b00040 R15: 0000000000000000 Code: 01 00 83 81 58 0a 00 00 01 48 2b 05 13 9d fd c9 48 c1 f8 06 48 c1 e0 0c 48 8d 04 d0 48 8b 56 08 48 03 05 0c 9d fd c9 48 83 ca 03 <48> 89 10 83 a9 58 0a 00 00 01 65 ff 0d 37 03 fb 3e 74 02 f3 c3 RIP: gen8_ppgtt_set_pde.isra.40+0x48/0x70 [i915] RSP: ffffb1a789d4f940 Reported-by: Eric Blau Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104773 Fixes: e2b763caa6eb ("drm/i915: Remove bitmap tracking for used-pdpes") References: dd19674bacba ("drm/i915: Remove bitmap tracking for used-ptes") Testcase: igt/drv_selftest/live_gtt (igt_ppgtt_shrink_boom) Signed-off-by: Chris Wilson Cc: Matthew Auld Link: https://patchwork.freedesktop.org/patch/msgid/20180131214440.7141-1-chris@chris-wilson.co.uk Reviewed-by: Matthew Auld (cherry picked from commit b715a2f0c7714a399e7f8e951cc8dea9cd4eeb4b) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_gem_gtt.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 133cb9590003dd..7e403eaa9e0fa1 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1359,15 +1359,18 @@ static int gen8_ppgtt_alloc_pd(struct i915_address_space *vm, int count = gen8_pte_count(start, length); if (pt == vm->scratch_pt) { + pd->used_pdes++; + pt = alloc_pt(vm); - if (IS_ERR(pt)) + if (IS_ERR(pt)) { + pd->used_pdes--; goto unwind; + } if (count < GEN8_PTES || intel_vgpu_active(vm->i915)) gen8_initialize_pt(vm, pt); gen8_ppgtt_set_pde(vm, pd, pt, pde); - pd->used_pdes++; GEM_BUG_ON(pd->used_pdes > I915_PDES); } @@ -1391,13 +1394,16 @@ static int gen8_ppgtt_alloc_pdp(struct i915_address_space *vm, gen8_for_each_pdpe(pd, pdp, start, length, pdpe) { if (pd == vm->scratch_pd) { + pdp->used_pdpes++; + pd = alloc_pd(vm); - if (IS_ERR(pd)) + if (IS_ERR(pd)) { + pdp->used_pdpes--; goto unwind; + } gen8_initialize_pd(vm, pd); gen8_ppgtt_set_pdpe(vm, pdp, pd, pdpe); - pdp->used_pdpes++; GEM_BUG_ON(pdp->used_pdpes > i915_pdpes_per_pdp(vm)); mark_tlbs_dirty(i915_vm_to_ppgtt(vm)); From fe9748b7b41cee11f8db57fb8b20bc540a33102a Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Mon, 6 Nov 2017 16:32:41 +0100 Subject: [PATCH 093/237] drm/nouveau/pmu/fuc: don't use movw directly anymore Fixes failure to compile with recent envyas as a result of the 'movw' alias being removed for v5. A bit of history: v3 only has a 16-bit sign-extended immediate mov op. In order to set the high bits, there's a separate 'sethi' op. envyas validates that the value passed to mov(imm) is between -0x8000 and 0x7fff. In order to simplify macros that load both the low and high word, a 'movw' alias was added which takes an unsigned 16-bit immediate. However the actual hardware op still sign extends. v5 has a full 32-bit immediate mov op. The v3 16-bit immediate mov op is gone (loads 0 into the dst reg). However due to a bug in envyas, the movw alias still existed, and selected the no-longer-present v3 16-bit immediate mov op. As a result usage of movw on v5 is the same as mov with a 0x0 argument. The proper fix throughout is to only ever use the 'movw' alias in combination with 'sethi'. Anything else should get the sign-extended validation to ensure that the intended value ends up in the destination register. Changes in fuc3 binaries is the result of a different encoding being selected for a mov with an 8-bit value. v2: added commit message written by Ilia, thanks for that! v3: messed up rebasing, now it should apply Signed-off-by: Karol Herbst Signed-off-by: Ben Skeggs --- .../nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h | 746 ++++++------ .../nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h | 802 ++++++------- .../nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h | 1006 ++++++++--------- .../drm/nouveau/nvkm/subdev/pmu/fuc/memx.fuc | 30 +- 4 files changed, 1292 insertions(+), 1292 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h index 53d01fb00a8b66..1dbe593e596093 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gf100.fuc3.h @@ -47,8 +47,8 @@ static uint32_t gf100_pmu_data[] = { 0x00000000, 0x00000000, 0x584d454d, - 0x00000756, - 0x00000748, + 0x00000754, + 0x00000746, 0x00000000, 0x00000000, 0x00000000, @@ -69,8 +69,8 @@ static uint32_t gf100_pmu_data[] = { 0x00000000, 0x00000000, 0x46524550, - 0x0000075a, 0x00000758, + 0x00000756, 0x00000000, 0x00000000, 0x00000000, @@ -91,8 +91,8 @@ static uint32_t gf100_pmu_data[] = { 0x00000000, 0x00000000, 0x5f433249, - 0x00000b8a, - 0x00000a2d, + 0x00000b88, + 0x00000a2b, 0x00000000, 0x00000000, 0x00000000, @@ -113,8 +113,8 @@ static uint32_t gf100_pmu_data[] = { 0x00000000, 0x00000000, 0x54534554, - 0x00000bb3, - 0x00000b8c, + 0x00000bb1, + 0x00000b8a, 0x00000000, 0x00000000, 0x00000000, @@ -135,8 +135,8 @@ static uint32_t gf100_pmu_data[] = { 0x00000000, 0x00000000, 0x454c4449, - 0x00000bbf, 0x00000bbd, + 0x00000bbb, 0x00000000, 0x00000000, 0x00000000, @@ -237,19 +237,19 @@ static uint32_t gf100_pmu_data[] = { 0x000005d3, 0x00000003, 0x00000002, - 0x0000069d, + 0x0000069b, 0x00040004, 0x00000000, - 0x000006b9, + 0x000006b7, 0x00010005, 0x00000000, - 0x000006d6, + 0x000006d4, 0x00010006, 0x00000000, 0x0000065b, 0x00000007, 0x00000000, - 0x000006e1, + 0x000006df, /* 0x03c4: memx_func_tail */ /* 0x03c4: memx_ts_start */ 0x00000000, @@ -1373,432 +1373,432 @@ static uint32_t gf100_pmu_code[] = { /* 0x065b: memx_func_wait_vblank */ 0x9800f840, 0x66b00016, - 0x130bf400, + 0x120bf400, 0xf40166b0, 0x0ef4060b, /* 0x066d: memx_func_wait_vblank_head1 */ - 0x2077f12e, - 0x070ef400, -/* 0x0674: memx_func_wait_vblank_head0 */ - 0x000877f1, -/* 0x0678: memx_func_wait_vblank_0 */ - 0x07c467f1, - 0xcf0664b6, - 0x67fd0066, - 0xf31bf404, -/* 0x0688: memx_func_wait_vblank_1 */ - 0x07c467f1, - 0xcf0664b6, - 0x67fd0066, - 0xf30bf404, -/* 0x0698: memx_func_wait_vblank_fini */ - 0xf80410b6, -/* 0x069d: memx_func_wr32 */ - 0x00169800, - 0xb6011598, - 0x60f90810, - 0xd0fc50f9, - 0x21f4e0fc, - 0x0242b640, - 0xf8e91bf4, -/* 0x06b9: memx_func_wait */ - 0x2c87f000, - 0xcf0684b6, - 0x1e980088, - 0x011d9800, - 0x98021c98, - 0x10b6031b, - 0xa321f410, -/* 0x06d6: memx_func_delay */ - 0x1e9800f8, - 0x0410b600, - 0xf87e21f4, -/* 0x06e1: memx_func_train */ -/* 0x06e3: memx_exec */ - 0xf900f800, - 0xb9d0f9e0, - 0xb2b902c1, -/* 0x06ed: memx_exec_next */ - 0x00139802, - 0xe70410b6, - 0xe701f034, - 0xb601e033, - 0x30f00132, - 0xde35980c, - 0x12b855f9, - 0xe41ef406, - 0x98f10b98, - 0xcbbbf20c, - 0xc4b7f102, - 0x06b4b607, - 0xfc00bbcf, - 0xf5e0fcd0, - 0xf8033621, -/* 0x0729: memx_info */ - 0x01c67000, -/* 0x072f: memx_info_data */ - 0xf10e0bf4, - 0xf103ccc7, - 0xf40800b7, -/* 0x073a: memx_info_train */ - 0xc7f10b0e, - 0xb7f10bcc, -/* 0x0742: memx_info_send */ - 0x21f50100, - 0x00f80336, -/* 0x0748: memx_recv */ - 0xf401d6b0, - 0xd6b0980b, - 0xd80bf400, -/* 0x0756: memx_init */ - 0x00f800f8, -/* 0x0758: perf_recv */ -/* 0x075a: perf_init */ + 0x2077f02c, +/* 0x0673: memx_func_wait_vblank_head0 */ + 0xf0060ef4, +/* 0x0676: memx_func_wait_vblank_0 */ + 0x67f10877, + 0x64b607c4, + 0x0066cf06, + 0xf40467fd, +/* 0x0686: memx_func_wait_vblank_1 */ + 0x67f1f31b, + 0x64b607c4, + 0x0066cf06, + 0xf40467fd, +/* 0x0696: memx_func_wait_vblank_fini */ + 0x10b6f30b, +/* 0x069b: memx_func_wr32 */ + 0x9800f804, + 0x15980016, + 0x0810b601, + 0x50f960f9, + 0xe0fcd0fc, + 0xb64021f4, + 0x1bf40242, +/* 0x06b7: memx_func_wait */ + 0xf000f8e9, + 0x84b62c87, + 0x0088cf06, + 0x98001e98, + 0x1c98011d, + 0x031b9802, + 0xf41010b6, + 0x00f8a321, +/* 0x06d4: memx_func_delay */ + 0xb6001e98, + 0x21f40410, +/* 0x06df: memx_func_train */ + 0xf800f87e, +/* 0x06e1: memx_exec */ + 0xf9e0f900, + 0x02c1b9d0, +/* 0x06eb: memx_exec_next */ + 0x9802b2b9, + 0x10b60013, + 0xf034e704, + 0xe033e701, + 0x0132b601, + 0x980c30f0, + 0x55f9de35, + 0xf40612b8, + 0x0b98e41e, + 0xf20c98f1, + 0xf102cbbb, + 0xb607c4b7, + 0xbbcf06b4, + 0xfcd0fc00, + 0x3621f5e0, +/* 0x0727: memx_info */ + 0x7000f803, + 0x0bf401c6, +/* 0x072d: memx_info_data */ + 0xccc7f10e, + 0x00b7f103, + 0x0b0ef408, +/* 0x0738: memx_info_train */ + 0x0bccc7f1, + 0x0100b7f1, +/* 0x0740: memx_info_send */ + 0x033621f5, +/* 0x0746: memx_recv */ + 0xd6b000f8, + 0x980bf401, + 0xf400d6b0, + 0x00f8d80b, +/* 0x0754: memx_init */ +/* 0x0756: perf_recv */ 0x00f800f8, -/* 0x075c: i2c_drive_scl */ - 0xf40036b0, - 0x07f1110b, - 0x04b607e0, - 0x0001d006, - 0x00f804bd, -/* 0x0770: i2c_drive_scl_lo */ - 0x07e407f1, - 0xd00604b6, - 0x04bd0001, -/* 0x077e: i2c_drive_sda */ +/* 0x0758: perf_init */ +/* 0x075a: i2c_drive_scl */ 0x36b000f8, 0x110bf400, 0x07e007f1, 0xd00604b6, - 0x04bd0002, -/* 0x0792: i2c_drive_sda_lo */ + 0x04bd0001, +/* 0x076e: i2c_drive_scl_lo */ 0x07f100f8, 0x04b607e4, + 0x0001d006, + 0x00f804bd, +/* 0x077c: i2c_drive_sda */ + 0xf40036b0, + 0x07f1110b, + 0x04b607e0, 0x0002d006, 0x00f804bd, -/* 0x07a0: i2c_sense_scl */ - 0xf10132f4, - 0xb607c437, - 0x33cf0634, - 0x0431fd00, - 0xf4060bf4, -/* 0x07b6: i2c_sense_scl_done */ - 0x00f80131, -/* 0x07b8: i2c_sense_sda */ - 0xf10132f4, - 0xb607c437, - 0x33cf0634, - 0x0432fd00, - 0xf4060bf4, -/* 0x07ce: i2c_sense_sda_done */ - 0x00f80131, -/* 0x07d0: i2c_raise_scl */ - 0x47f140f9, - 0x37f00898, - 0x5c21f501, -/* 0x07dd: i2c_raise_scl_wait */ - 0xe8e7f107, - 0x7e21f403, - 0x07a021f5, - 0xb60901f4, - 0x1bf40142, -/* 0x07f1: i2c_raise_scl_done */ - 0xf840fcef, -/* 0x07f5: i2c_start */ - 0xa021f500, - 0x0d11f407, - 0x07b821f5, - 0xf40611f4, -/* 0x0806: i2c_start_rep */ - 0x37f0300e, - 0x5c21f500, - 0x0137f007, - 0x077e21f5, - 0xb60076bb, - 0x50f90465, - 0xbb046594, - 0x50bd0256, - 0xfc0475fd, - 0xd021f550, - 0x0464b607, -/* 0x0833: i2c_start_send */ - 0xf01f11f4, +/* 0x0790: i2c_drive_sda_lo */ + 0x07e407f1, + 0xd00604b6, + 0x04bd0002, +/* 0x079e: i2c_sense_scl */ + 0x32f400f8, + 0xc437f101, + 0x0634b607, + 0xfd0033cf, + 0x0bf40431, + 0x0131f406, +/* 0x07b4: i2c_sense_scl_done */ +/* 0x07b6: i2c_sense_sda */ + 0x32f400f8, + 0xc437f101, + 0x0634b607, + 0xfd0033cf, + 0x0bf40432, + 0x0131f406, +/* 0x07cc: i2c_sense_sda_done */ +/* 0x07ce: i2c_raise_scl */ + 0x40f900f8, + 0x089847f1, + 0xf50137f0, +/* 0x07db: i2c_raise_scl_wait */ + 0xf1075a21, + 0xf403e8e7, + 0x21f57e21, + 0x01f4079e, + 0x0142b609, +/* 0x07ef: i2c_raise_scl_done */ + 0xfcef1bf4, +/* 0x07f3: i2c_start */ + 0xf500f840, + 0xf4079e21, + 0x21f50d11, + 0x11f407b6, + 0x300ef406, +/* 0x0804: i2c_start_rep */ + 0xf50037f0, + 0xf0075a21, + 0x21f50137, + 0x76bb077c, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb607ce21, + 0x11f40464, +/* 0x0831: i2c_start_send */ + 0x0037f01f, + 0x077c21f5, + 0x1388e7f1, + 0xf07e21f4, 0x21f50037, - 0xe7f1077e, + 0xe7f1075a, 0x21f41388, - 0x0037f07e, - 0x075c21f5, - 0x1388e7f1, -/* 0x084f: i2c_start_out */ - 0xf87e21f4, -/* 0x0851: i2c_stop */ - 0x0037f000, - 0x075c21f5, - 0xf50037f0, - 0xf1077e21, - 0xf403e8e7, - 0x37f07e21, - 0x5c21f501, - 0x88e7f107, - 0x7e21f413, +/* 0x084d: i2c_start_out */ +/* 0x084f: i2c_stop */ + 0xf000f87e, + 0x21f50037, + 0x37f0075a, + 0x7c21f500, + 0xe8e7f107, + 0x7e21f403, 0xf50137f0, - 0xf1077e21, + 0xf1075a21, 0xf41388e7, - 0x00f87e21, -/* 0x0884: i2c_bitw */ - 0x077e21f5, - 0x03e8e7f1, - 0xbb7e21f4, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x07d021f5, - 0xf40464b6, - 0xe7f11811, - 0x21f41388, - 0x0037f07e, - 0x075c21f5, - 0x1388e7f1, -/* 0x08c3: i2c_bitw_out */ - 0xf87e21f4, -/* 0x08c5: i2c_bitr */ - 0x0137f000, - 0x077e21f5, - 0x03e8e7f1, - 0xbb7e21f4, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x07d021f5, - 0xf40464b6, - 0x21f51b11, - 0x37f007b8, - 0x5c21f500, + 0x37f07e21, + 0x7c21f501, 0x88e7f107, 0x7e21f413, - 0xf4013cf0, -/* 0x090a: i2c_bitr_done */ - 0x00f80131, -/* 0x090c: i2c_get_byte */ - 0xf00057f0, -/* 0x0912: i2c_get_byte_next */ - 0x54b60847, - 0x0076bb01, +/* 0x0882: i2c_bitw */ + 0x21f500f8, + 0xe7f1077c, + 0x21f403e8, + 0x0076bb7e, 0xf90465b6, 0x04659450, 0xbd0256bb, 0x0475fd50, 0x21f550fc, - 0x64b608c5, - 0x2b11f404, - 0xb60553fd, - 0x1bf40142, - 0x0137f0d8, - 0xb60076bb, - 0x50f90465, - 0xbb046594, - 0x50bd0256, - 0xfc0475fd, - 0x8421f550, - 0x0464b608, -/* 0x095c: i2c_get_byte_done */ -/* 0x095e: i2c_put_byte */ - 0x47f000f8, -/* 0x0961: i2c_put_byte_next */ - 0x0142b608, - 0xbb3854ff, + 0x64b607ce, + 0x1811f404, + 0x1388e7f1, + 0xf07e21f4, + 0x21f50037, + 0xe7f1075a, + 0x21f41388, +/* 0x08c1: i2c_bitw_out */ +/* 0x08c3: i2c_bitr */ + 0xf000f87e, + 0x21f50137, + 0xe7f1077c, + 0x21f403e8, + 0x0076bb7e, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b607ce, + 0x1b11f404, + 0x07b621f5, + 0xf50037f0, + 0xf1075a21, + 0xf41388e7, + 0x3cf07e21, + 0x0131f401, +/* 0x0908: i2c_bitr_done */ +/* 0x090a: i2c_get_byte */ + 0x57f000f8, + 0x0847f000, +/* 0x0910: i2c_get_byte_next */ + 0xbb0154b6, 0x65b60076, 0x9450f904, 0x56bb0465, 0xfd50bd02, 0x50fc0475, - 0x088421f5, + 0x08c321f5, 0xf40464b6, - 0x46b03411, - 0xd81bf400, - 0xb60076bb, - 0x50f90465, - 0xbb046594, - 0x50bd0256, - 0xfc0475fd, - 0xc521f550, - 0x0464b608, - 0xbb0f11f4, - 0x36b00076, - 0x061bf401, -/* 0x09b7: i2c_put_byte_done */ - 0xf80132f4, -/* 0x09b9: i2c_addr */ - 0x0076bb00, + 0x53fd2b11, + 0x0142b605, + 0xf0d81bf4, + 0x76bb0137, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb6088221, +/* 0x095a: i2c_get_byte_done */ + 0x00f80464, +/* 0x095c: i2c_put_byte */ +/* 0x095f: i2c_put_byte_next */ + 0xb60847f0, + 0x54ff0142, + 0x0076bb38, 0xf90465b6, 0x04659450, 0xbd0256bb, 0x0475fd50, 0x21f550fc, - 0x64b607f5, - 0x2911f404, - 0x012ec3e7, - 0xfd0134b6, - 0x76bb0553, + 0x64b60882, + 0x3411f404, + 0xf40046b0, + 0x76bbd81b, 0x0465b600, 0x659450f9, 0x0256bb04, 0x75fd50bd, 0xf550fc04, - 0xb6095e21, -/* 0x09fe: i2c_addr_done */ - 0x00f80464, -/* 0x0a00: i2c_acquire_addr */ - 0xb6f8cec7, - 0xe0b702e4, - 0xee980d1c, -/* 0x0a0f: i2c_acquire */ - 0xf500f800, - 0xf40a0021, - 0xd9f00421, - 0x4021f403, -/* 0x0a1e: i2c_release */ - 0x21f500f8, - 0x21f40a00, - 0x03daf004, - 0xf84021f4, -/* 0x0a2d: i2c_recv */ - 0x0132f400, - 0xb6f8c1c7, - 0x16b00214, - 0x3a1ff528, - 0xf413a001, - 0x0032980c, - 0x0ccc13a0, - 0xf4003198, - 0xd0f90231, - 0xd0f9e0f9, - 0x000067f1, - 0x100063f1, - 0xbb016792, + 0xb608c321, + 0x11f40464, + 0x0076bb0f, + 0xf40136b0, + 0x32f4061b, +/* 0x09b5: i2c_put_byte_done */ +/* 0x09b7: i2c_addr */ + 0xbb00f801, 0x65b60076, 0x9450f904, 0x56bb0465, 0xfd50bd02, 0x50fc0475, - 0x0a0f21f5, - 0xfc0464b6, - 0x00d6b0d0, - 0x00b31bf5, - 0xbb0057f0, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x09b921f5, - 0xf50464b6, - 0xc700d011, - 0x76bbe0c5, - 0x0465b600, - 0x659450f9, - 0x0256bb04, - 0x75fd50bd, - 0xf550fc04, - 0xb6095e21, - 0x11f50464, - 0x57f000ad, + 0x07f321f5, + 0xf40464b6, + 0xc3e72911, + 0x34b6012e, + 0x0553fd01, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x5c21f550, + 0x0464b609, +/* 0x09fc: i2c_addr_done */ +/* 0x09fe: i2c_acquire_addr */ + 0xcec700f8, + 0x02e4b6f8, + 0x0d1ce0b7, + 0xf800ee98, +/* 0x0a0d: i2c_acquire */ + 0xfe21f500, + 0x0421f409, + 0xf403d9f0, + 0x00f84021, +/* 0x0a1c: i2c_release */ + 0x09fe21f5, + 0xf00421f4, + 0x21f403da, +/* 0x0a2b: i2c_recv */ + 0xf400f840, + 0xc1c70132, + 0x0214b6f8, + 0xf52816b0, + 0xa0013a1f, + 0x980cf413, + 0x13a00032, + 0x31980ccc, + 0x0231f400, + 0xe0f9d0f9, + 0x67f1d0f9, + 0x63f10000, + 0x67921000, 0x0076bb01, 0xf90465b6, 0x04659450, 0xbd0256bb, 0x0475fd50, 0x21f550fc, - 0x64b609b9, - 0x8a11f504, + 0x64b60a0d, + 0xb0d0fc04, + 0x1bf500d6, + 0x57f000b3, 0x0076bb00, 0xf90465b6, 0x04659450, 0xbd0256bb, 0x0475fd50, 0x21f550fc, - 0x64b6090c, - 0x6a11f404, - 0xbbe05bcb, + 0x64b609b7, + 0xd011f504, + 0xe0c5c700, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x5c21f550, + 0x0464b609, + 0x00ad11f5, + 0xbb0157f0, 0x65b60076, 0x9450f904, 0x56bb0465, 0xfd50bd02, 0x50fc0475, - 0x085121f5, - 0xb90464b6, - 0x74bd025b, -/* 0x0b33: i2c_recv_not_rd08 */ - 0xb0430ef4, - 0x1bf401d6, - 0x0057f03d, - 0x09b921f5, - 0xc73311f4, - 0x21f5e0c5, - 0x11f4095e, - 0x0057f029, - 0x09b921f5, - 0xc71f11f4, - 0x21f5e0b5, - 0x11f4095e, - 0x5121f515, - 0xc774bd08, - 0x1bf408c5, - 0x0232f409, -/* 0x0b73: i2c_recv_not_wr08 */ -/* 0x0b73: i2c_recv_done */ - 0xc7030ef4, - 0x21f5f8ce, - 0xe0fc0a1e, - 0x12f4d0fc, - 0x027cb90a, - 0x033621f5, -/* 0x0b88: i2c_recv_exit */ -/* 0x0b8a: i2c_init */ - 0x00f800f8, -/* 0x0b8c: test_recv */ - 0x05d817f1, + 0x09b721f5, + 0xf50464b6, + 0xbb008a11, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x090a21f5, + 0xf40464b6, + 0x5bcb6a11, + 0x0076bbe0, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b6084f, + 0x025bb904, + 0x0ef474bd, +/* 0x0b31: i2c_recv_not_rd08 */ + 0x01d6b043, + 0xf03d1bf4, + 0x21f50057, + 0x11f409b7, + 0xe0c5c733, + 0x095c21f5, + 0xf02911f4, + 0x21f50057, + 0x11f409b7, + 0xe0b5c71f, + 0x095c21f5, + 0xf51511f4, + 0xbd084f21, + 0x08c5c774, + 0xf4091bf4, + 0x0ef40232, +/* 0x0b71: i2c_recv_not_wr08 */ +/* 0x0b71: i2c_recv_done */ + 0xf8cec703, + 0x0a1c21f5, + 0xd0fce0fc, + 0xb90a12f4, + 0x21f5027c, +/* 0x0b86: i2c_recv_exit */ + 0x00f80336, +/* 0x0b88: i2c_init */ +/* 0x0b8a: test_recv */ + 0x17f100f8, + 0x14b605d8, + 0x0011cf06, + 0xf10110b6, + 0xb605d807, + 0x01d00604, + 0xf104bd00, + 0xf1d900e7, + 0xf5134fe3, + 0xf8025621, +/* 0x0bb1: test_init */ + 0x00e7f100, + 0x5621f508, +/* 0x0bbb: idle_recv */ + 0xf800f802, +/* 0x0bbd: idle */ + 0x0031f400, + 0x05d417f1, 0xcf0614b6, 0x10b60011, - 0xd807f101, + 0xd407f101, 0x0604b605, 0xbd0001d0, - 0x00e7f104, - 0x4fe3f1d9, - 0x5621f513, -/* 0x0bb3: test_init */ - 0xf100f802, - 0xf50800e7, - 0xf8025621, -/* 0x0bbd: idle_recv */ -/* 0x0bbf: idle */ - 0xf400f800, - 0x17f10031, - 0x14b605d4, - 0x0011cf06, - 0xf10110b6, - 0xb605d407, - 0x01d00604, -/* 0x0bdb: idle_loop */ - 0xf004bd00, - 0x32f45817, -/* 0x0be1: idle_proc */ -/* 0x0be1: idle_proc_exec */ - 0xb910f902, - 0x21f5021e, - 0x10fc033f, - 0xf40911f4, - 0x0ef40231, -/* 0x0bf5: idle_proc_next */ - 0x5810b6ef, - 0xf4061fb8, - 0x02f4e61b, - 0x0028f4dd, - 0x00bb0ef4, +/* 0x0bd9: idle_loop */ + 0x5817f004, +/* 0x0bdf: idle_proc */ +/* 0x0bdf: idle_proc_exec */ + 0xf90232f4, + 0x021eb910, + 0x033f21f5, + 0x11f410fc, + 0x0231f409, +/* 0x0bf3: idle_proc_next */ + 0xb6ef0ef4, + 0x1fb85810, + 0xe61bf406, + 0xf4dd02f4, + 0x0ef40028, + 0x000000bb, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h index c4edbc79e41a25..e0222cb832fbc6 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gk208.fuc5.h @@ -47,8 +47,8 @@ static uint32_t gk208_pmu_data[] = { 0x00000000, 0x00000000, 0x584d454d, - 0x000005f3, - 0x000005e5, + 0x000005ee, + 0x000005e0, 0x00000000, 0x00000000, 0x00000000, @@ -69,8 +69,8 @@ static uint32_t gk208_pmu_data[] = { 0x00000000, 0x00000000, 0x46524550, - 0x000005f7, - 0x000005f5, + 0x000005f2, + 0x000005f0, 0x00000000, 0x00000000, 0x00000000, @@ -91,8 +91,8 @@ static uint32_t gk208_pmu_data[] = { 0x00000000, 0x00000000, 0x5f433249, - 0x000009f8, - 0x000008a2, + 0x000009f3, + 0x0000089d, 0x00000000, 0x00000000, 0x00000000, @@ -113,8 +113,8 @@ static uint32_t gk208_pmu_data[] = { 0x00000000, 0x00000000, 0x54534554, - 0x00000a16, - 0x000009fa, + 0x00000a11, + 0x000009f5, 0x00000000, 0x00000000, 0x00000000, @@ -135,8 +135,8 @@ static uint32_t gk208_pmu_data[] = { 0x00000000, 0x00000000, 0x454c4449, - 0x00000a21, - 0x00000a1f, + 0x00000a1c, + 0x00000a1a, 0x00000000, 0x00000000, 0x00000000, @@ -234,22 +234,22 @@ static uint32_t gk208_pmu_data[] = { /* 0x037c: memx_func_next */ 0x00000002, 0x00000000, - 0x000004cf, + 0x000004cc, 0x00000003, 0x00000002, - 0x00000546, + 0x00000541, 0x00040004, 0x00000000, - 0x00000563, + 0x0000055e, 0x00010005, 0x00000000, - 0x0000057d, + 0x00000578, 0x00010006, 0x00000000, - 0x00000541, + 0x0000053c, 0x00000007, 0x00000000, - 0x00000589, + 0x00000584, /* 0x03c4: memx_func_tail */ /* 0x03c4: memx_ts_start */ 0x00000000, @@ -1239,454 +1239,454 @@ static uint32_t gk208_pmu_code[] = { 0x0001f604, 0x00f804bd, /* 0x045c: memx_func_enter */ - 0x162067f1, - 0xf55d77f1, - 0x047e6eb2, - 0xd8b20000, - 0xf90487fd, - 0xfc80f960, - 0x7ee0fcd0, - 0x0700002d, - 0x7e6eb2fe, + 0x47162046, + 0x6eb2f55d, + 0x0000047e, + 0x87fdd8b2, + 0xf960f904, + 0xfcd0fc80, + 0x002d7ee0, + 0xb2fe0700, + 0x00047e6e, + 0xfdd8b200, + 0x60f90487, + 0xd0fc80f9, + 0x2d7ee0fc, + 0xf0460000, + 0x7e6eb226, 0xb2000004, 0x0487fdd8, 0x80f960f9, 0xe0fcd0fc, 0x00002d7e, - 0x26f067f1, - 0x047e6eb2, - 0xd8b20000, - 0xf90487fd, - 0xfc80f960, - 0x7ee0fcd0, - 0x0600002d, - 0x07e04004, - 0xbd0006f6, -/* 0x04b9: memx_func_enter_wait */ - 0x07c04604, - 0xf00066cf, - 0x0bf40464, - 0xcf2c06f7, - 0x06b50066, -/* 0x04cf: memx_func_leave */ - 0x0600f8f1, - 0x0066cf2c, - 0x06f206b5, - 0x07e44004, - 0xbd0006f6, -/* 0x04e1: memx_func_leave_wait */ - 0x07c04604, - 0xf00066cf, - 0x1bf40464, - 0xf067f1f7, + 0xe0400406, + 0x0006f607, +/* 0x04b6: memx_func_enter_wait */ + 0xc04604bd, + 0x0066cf07, + 0xf40464f0, + 0x2c06f70b, + 0xb50066cf, + 0x00f8f106, +/* 0x04cc: memx_func_leave */ + 0x66cf2c06, + 0xf206b500, + 0xe4400406, + 0x0006f607, +/* 0x04de: memx_func_leave_wait */ + 0xc04604bd, + 0x0066cf07, + 0xf40464f0, + 0xf046f71b, 0xb2010726, 0x00047e6e, 0xfdd8b200, 0x60f90587, 0xd0fc80f9, 0x2d7ee0fc, - 0x67f10000, - 0x6eb21620, - 0x0000047e, - 0x87fdd8b2, - 0xf960f905, - 0xfcd0fc80, - 0x002d7ee0, - 0x0aa24700, - 0x047e6eb2, - 0xd8b20000, - 0xf90587fd, - 0xfc80f960, - 0x7ee0fcd0, - 0xf800002d, -/* 0x0541: memx_func_wait_vblank */ + 0x20460000, + 0x7e6eb216, + 0xb2000004, + 0x0587fdd8, + 0x80f960f9, + 0xe0fcd0fc, + 0x00002d7e, + 0xb20aa247, + 0x00047e6e, + 0xfdd8b200, + 0x60f90587, + 0xd0fc80f9, + 0x2d7ee0fc, + 0x00f80000, +/* 0x053c: memx_func_wait_vblank */ + 0xf80410b6, +/* 0x0541: memx_func_wr32 */ + 0x00169800, + 0xb6011598, + 0x60f90810, + 0xd0fc50f9, + 0x2d7ee0fc, + 0x42b60000, + 0xe81bf402, +/* 0x055e: memx_func_wait */ + 0x2c0800f8, + 0x980088cf, + 0x1d98001e, + 0x021c9801, + 0xb6031b98, + 0x747e1010, + 0x00f80000, +/* 0x0578: memx_func_delay */ + 0xb6001e98, + 0x587e0410, + 0x00f80000, +/* 0x0584: memx_func_train */ +/* 0x0586: memx_exec */ + 0xe0f900f8, + 0xc1b2d0f9, +/* 0x058e: memx_exec_next */ + 0x1398b2b2, 0x0410b600, -/* 0x0546: memx_func_wr32 */ - 0x169800f8, - 0x01159800, - 0xf90810b6, - 0xfc50f960, + 0x01f034e7, + 0x01e033e7, + 0xf00132b6, + 0x35980c30, + 0xa655f9de, + 0xe51ef412, + 0x98f10b98, + 0xcbbbf20c, + 0x07c44b02, + 0xfc00bbcf, 0x7ee0fcd0, - 0xb600002d, - 0x1bf40242, -/* 0x0563: memx_func_wait */ - 0x0800f8e8, - 0x0088cf2c, - 0x98001e98, - 0x1c98011d, - 0x031b9802, - 0x7e1010b6, - 0xf8000074, -/* 0x057d: memx_func_delay */ - 0x001e9800, - 0x7e0410b6, - 0xf8000058, -/* 0x0589: memx_func_train */ -/* 0x058b: memx_exec */ - 0xf900f800, - 0xb2d0f9e0, -/* 0x0593: memx_exec_next */ - 0x98b2b2c1, - 0x10b60013, - 0xf034e704, - 0xe033e701, - 0x0132b601, - 0x980c30f0, - 0x55f9de35, - 0x1ef412a6, - 0xf10b98e5, - 0xbbf20c98, - 0xc44b02cb, - 0x00bbcf07, - 0xe0fcd0fc, - 0x00029f7e, -/* 0x05ca: memx_info */ - 0xc67000f8, - 0x0c0bf401, -/* 0x05d0: memx_info_data */ - 0x4b03cc4c, - 0x0ef40800, -/* 0x05d9: memx_info_train */ - 0x0bcc4c09, -/* 0x05df: memx_info_send */ - 0x7e01004b, 0xf800029f, -/* 0x05e5: memx_recv */ - 0x01d6b000, - 0xb0a30bf4, - 0x0bf400d6, -/* 0x05f3: memx_init */ - 0xf800f8dc, -/* 0x05f5: perf_recv */ -/* 0x05f7: perf_init */ - 0xf800f800, -/* 0x05f9: i2c_drive_scl */ - 0x0036b000, - 0x400d0bf4, - 0x01f607e0, - 0xf804bd00, -/* 0x0609: i2c_drive_scl_lo */ - 0x07e44000, - 0xbd0001f6, -/* 0x0613: i2c_drive_sda */ - 0xb000f804, - 0x0bf40036, - 0x07e0400d, - 0xbd0002f6, -/* 0x0623: i2c_drive_sda_lo */ - 0x4000f804, - 0x02f607e4, - 0xf804bd00, -/* 0x062d: i2c_sense_scl */ - 0x0132f400, - 0xcf07c443, - 0x31fd0033, - 0x060bf404, -/* 0x063f: i2c_sense_scl_done */ - 0xf80131f4, -/* 0x0641: i2c_sense_sda */ - 0x0132f400, - 0xcf07c443, - 0x32fd0033, - 0x060bf404, -/* 0x0653: i2c_sense_sda_done */ - 0xf80131f4, -/* 0x0655: i2c_raise_scl */ - 0x4440f900, - 0x01030898, - 0x0005f97e, -/* 0x0660: i2c_raise_scl_wait */ - 0x7e03e84e, - 0x7e000058, - 0xf400062d, - 0x42b60901, - 0xef1bf401, -/* 0x0674: i2c_raise_scl_done */ - 0x00f840fc, -/* 0x0678: i2c_start */ - 0x00062d7e, - 0x7e0d11f4, - 0xf4000641, - 0x0ef40611, -/* 0x0689: i2c_start_rep */ - 0x7e00032e, - 0x030005f9, - 0x06137e01, +/* 0x05c5: memx_info */ + 0x01c67000, +/* 0x05cb: memx_info_data */ + 0x4c0c0bf4, + 0x004b03cc, + 0x090ef408, +/* 0x05d4: memx_info_train */ + 0x4b0bcc4c, +/* 0x05da: memx_info_send */ + 0x9f7e0100, + 0x00f80002, +/* 0x05e0: memx_recv */ + 0xf401d6b0, + 0xd6b0a30b, + 0xdc0bf400, +/* 0x05ee: memx_init */ + 0x00f800f8, +/* 0x05f0: perf_recv */ +/* 0x05f2: perf_init */ + 0x00f800f8, +/* 0x05f4: i2c_drive_scl */ + 0xf40036b0, + 0xe0400d0b, + 0x0001f607, + 0x00f804bd, +/* 0x0604: i2c_drive_scl_lo */ + 0xf607e440, + 0x04bd0001, +/* 0x060e: i2c_drive_sda */ + 0x36b000f8, + 0x0d0bf400, + 0xf607e040, + 0x04bd0002, +/* 0x061e: i2c_drive_sda_lo */ + 0xe44000f8, + 0x0002f607, + 0x00f804bd, +/* 0x0628: i2c_sense_scl */ + 0x430132f4, + 0x33cf07c4, + 0x0431fd00, + 0xf4060bf4, +/* 0x063a: i2c_sense_scl_done */ + 0x00f80131, +/* 0x063c: i2c_sense_sda */ + 0x430132f4, + 0x33cf07c4, + 0x0432fd00, + 0xf4060bf4, +/* 0x064e: i2c_sense_sda_done */ + 0x00f80131, +/* 0x0650: i2c_raise_scl */ + 0x984440f9, + 0x7e010308, +/* 0x065b: i2c_raise_scl_wait */ + 0x4e0005f4, + 0x587e03e8, + 0x287e0000, + 0x01f40006, + 0x0142b609, +/* 0x066f: i2c_raise_scl_done */ + 0xfcef1bf4, +/* 0x0673: i2c_start */ + 0x7e00f840, + 0xf4000628, + 0x3c7e0d11, + 0x11f40006, + 0x2e0ef406, +/* 0x0684: i2c_start_rep */ + 0xf47e0003, + 0x01030005, + 0x00060e7e, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x06507e50, + 0x0464b600, +/* 0x06af: i2c_start_send */ + 0x031d11f4, + 0x060e7e00, + 0x13884e00, + 0x0000587e, + 0xf47e0003, + 0x884e0005, + 0x00587e13, +/* 0x06c9: i2c_start_out */ +/* 0x06cb: i2c_stop */ + 0x0300f800, + 0x05f47e00, + 0x7e000300, + 0x4e00060e, + 0x587e03e8, + 0x01030000, + 0x0005f47e, + 0x7e13884e, + 0x03000058, + 0x060e7e01, + 0x13884e00, + 0x0000587e, +/* 0x06fa: i2c_bitw */ + 0x0e7e00f8, + 0xe84e0006, + 0x00587e03, 0x0076bb00, 0xf90465b6, 0x04659450, 0xbd0256bb, 0x0475fd50, - 0x557e50fc, + 0x507e50fc, 0x64b60006, - 0x1d11f404, -/* 0x06b4: i2c_start_send */ - 0x137e0003, - 0x884e0006, - 0x00587e13, - 0x7e000300, - 0x4e0005f9, - 0x587e1388, -/* 0x06ce: i2c_start_out */ - 0x00f80000, -/* 0x06d0: i2c_stop */ - 0xf97e0003, - 0x00030005, - 0x0006137e, - 0x7e03e84e, + 0x1711f404, + 0x7e13884e, 0x03000058, - 0x05f97e01, + 0x05f47e00, 0x13884e00, 0x0000587e, - 0x137e0103, - 0x884e0006, - 0x00587e13, -/* 0x06ff: i2c_bitw */ - 0x7e00f800, - 0x4e000613, - 0x587e03e8, - 0x76bb0000, +/* 0x0738: i2c_bitw_out */ +/* 0x073a: i2c_bitr */ + 0x010300f8, + 0x00060e7e, + 0x7e03e84e, + 0xbb000058, + 0x65b60076, + 0x9450f904, + 0x56bb0465, + 0xfd50bd02, + 0x50fc0475, + 0x0006507e, + 0xf40464b6, + 0x3c7e1a11, + 0x00030006, + 0x0005f47e, + 0x7e13884e, + 0xf0000058, + 0x31f4013c, +/* 0x077d: i2c_bitr_done */ +/* 0x077f: i2c_get_byte */ + 0x0500f801, +/* 0x0783: i2c_get_byte_next */ + 0xb6080400, + 0x76bb0154, 0x0465b600, 0x659450f9, 0x0256bb04, 0x75fd50bd, 0x7e50fc04, - 0xb6000655, + 0xb600073a, 0x11f40464, - 0x13884e17, - 0x0000587e, - 0xf97e0003, - 0x884e0005, - 0x00587e13, -/* 0x073d: i2c_bitw_out */ -/* 0x073f: i2c_bitr */ - 0x0300f800, - 0x06137e01, - 0x03e84e00, - 0x0000587e, + 0x0553fd2a, + 0xf40142b6, + 0x0103d81b, 0xb60076bb, 0x50f90465, 0xbb046594, 0x50bd0256, 0xfc0475fd, - 0x06557e50, + 0x06fa7e50, 0x0464b600, - 0x7e1a11f4, - 0x03000641, - 0x05f97e00, - 0x13884e00, - 0x0000587e, - 0xf4013cf0, -/* 0x0782: i2c_bitr_done */ - 0x00f80131, -/* 0x0784: i2c_get_byte */ - 0x08040005, -/* 0x0788: i2c_get_byte_next */ - 0xbb0154b6, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x00073f7e, - 0xf40464b6, - 0x53fd2a11, - 0x0142b605, - 0x03d81bf4, - 0x0076bb01, - 0xf90465b6, - 0x04659450, - 0xbd0256bb, - 0x0475fd50, - 0xff7e50fc, - 0x64b60006, -/* 0x07d1: i2c_get_byte_done */ -/* 0x07d3: i2c_put_byte */ - 0x0400f804, -/* 0x07d5: i2c_put_byte_next */ - 0x0142b608, - 0xbb3854ff, +/* 0x07cc: i2c_get_byte_done */ +/* 0x07ce: i2c_put_byte */ + 0x080400f8, +/* 0x07d0: i2c_put_byte_next */ + 0xff0142b6, + 0x76bb3854, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0x7e50fc04, + 0xb60006fa, + 0x11f40464, + 0x0046b034, + 0xbbd81bf4, 0x65b60076, 0x9450f904, 0x56bb0465, 0xfd50bd02, 0x50fc0475, - 0x0006ff7e, + 0x00073a7e, 0xf40464b6, - 0x46b03411, - 0xd81bf400, + 0x76bb0f11, + 0x0136b000, + 0xf4061bf4, +/* 0x0826: i2c_put_byte_done */ + 0x00f80132, +/* 0x0828: i2c_addr */ 0xb60076bb, 0x50f90465, 0xbb046594, 0x50bd0256, 0xfc0475fd, - 0x073f7e50, + 0x06737e50, 0x0464b600, - 0xbb0f11f4, - 0x36b00076, - 0x061bf401, -/* 0x082b: i2c_put_byte_done */ - 0xf80132f4, -/* 0x082d: i2c_addr */ - 0x0076bb00, + 0xe72911f4, + 0xb6012ec3, + 0x53fd0134, + 0x0076bb05, 0xf90465b6, 0x04659450, 0xbd0256bb, 0x0475fd50, - 0x787e50fc, - 0x64b60006, - 0x2911f404, - 0x012ec3e7, - 0xfd0134b6, - 0x76bb0553, - 0x0465b600, - 0x659450f9, - 0x0256bb04, - 0x75fd50bd, - 0x7e50fc04, - 0xb60007d3, -/* 0x0872: i2c_addr_done */ - 0x00f80464, -/* 0x0874: i2c_acquire_addr */ - 0xb6f8cec7, - 0xe0b705e4, - 0x00f8d014, -/* 0x0880: i2c_acquire */ - 0x0008747e, + 0xce7e50fc, + 0x64b60007, +/* 0x086d: i2c_addr_done */ +/* 0x086f: i2c_acquire_addr */ + 0xc700f804, + 0xe4b6f8ce, + 0x14e0b705, +/* 0x087b: i2c_acquire */ + 0x7e00f8d0, + 0x7e00086f, + 0xf0000004, + 0x2d7e03d9, + 0x00f80000, +/* 0x088c: i2c_release */ + 0x00086f7e, 0x0000047e, - 0x7e03d9f0, + 0x7e03daf0, 0xf800002d, -/* 0x0891: i2c_release */ - 0x08747e00, - 0x00047e00, - 0x03daf000, - 0x00002d7e, -/* 0x08a2: i2c_recv */ - 0x32f400f8, - 0xf8c1c701, - 0xb00214b6, - 0x1ff52816, - 0x13b80134, - 0x98000cf4, - 0x13b80032, - 0x98000ccc, - 0x31f40031, - 0xf9d0f902, - 0xd6d0f9e0, - 0x10000000, - 0xbb016792, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x0008807e, - 0xfc0464b6, - 0x00d6b0d0, - 0x00b01bf5, - 0x76bb0005, +/* 0x089d: i2c_recv */ + 0x0132f400, + 0xb6f8c1c7, + 0x16b00214, + 0x341ff528, + 0xf413b801, + 0x3298000c, + 0xcc13b800, + 0x3198000c, + 0x0231f400, + 0xe0f9d0f9, + 0x00d6d0f9, + 0x92100000, + 0x76bb0167, 0x0465b600, 0x659450f9, 0x0256bb04, 0x75fd50bd, 0x7e50fc04, - 0xb600082d, - 0x11f50464, - 0xc5c700cc, - 0x0076bbe0, - 0xf90465b6, - 0x04659450, - 0xbd0256bb, - 0x0475fd50, - 0xd37e50fc, - 0x64b60007, - 0xa911f504, - 0xbb010500, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x00082d7e, - 0xf50464b6, - 0xbb008711, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x0007847e, - 0xf40464b6, - 0x5bcb6711, - 0x0076bbe0, + 0xb600087b, + 0xd0fc0464, + 0xf500d6b0, + 0x0500b01b, + 0x0076bb00, 0xf90465b6, 0x04659450, 0xbd0256bb, 0x0475fd50, - 0xd07e50fc, - 0x64b60006, - 0xbd5bb204, - 0x410ef474, -/* 0x09a4: i2c_recv_not_rd08 */ - 0xf401d6b0, - 0x00053b1b, - 0x00082d7e, - 0xc73211f4, - 0xd37ee0c5, - 0x11f40007, - 0x7e000528, - 0xf400082d, - 0xb5c71f11, - 0x07d37ee0, - 0x1511f400, - 0x0006d07e, - 0xc5c774bd, - 0x091bf408, - 0xf40232f4, -/* 0x09e2: i2c_recv_not_wr08 */ -/* 0x09e2: i2c_recv_done */ - 0xcec7030e, - 0x08917ef8, - 0xfce0fc00, - 0x0912f4d0, - 0x9f7e7cb2, -/* 0x09f6: i2c_recv_exit */ - 0x00f80002, -/* 0x09f8: i2c_init */ -/* 0x09fa: test_recv */ - 0x584100f8, - 0x0011cf04, - 0x400110b6, - 0x01f60458, - 0xde04bd00, - 0x134fd900, - 0x0001de7e, -/* 0x0a16: test_init */ - 0x004e00f8, - 0x01de7e08, -/* 0x0a1f: idle_recv */ + 0x287e50fc, + 0x64b60008, + 0xcc11f504, + 0xe0c5c700, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x07ce7e50, + 0x0464b600, + 0x00a911f5, + 0x76bb0105, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0x7e50fc04, + 0xb6000828, + 0x11f50464, + 0x76bb0087, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0x7e50fc04, + 0xb600077f, + 0x11f40464, + 0xe05bcb67, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x06cb7e50, + 0x0464b600, + 0x74bd5bb2, +/* 0x099f: i2c_recv_not_rd08 */ + 0xb0410ef4, + 0x1bf401d6, + 0x7e00053b, + 0xf4000828, + 0xc5c73211, + 0x07ce7ee0, + 0x2811f400, + 0x287e0005, + 0x11f40008, + 0xe0b5c71f, + 0x0007ce7e, + 0x7e1511f4, + 0xbd0006cb, + 0x08c5c774, + 0xf4091bf4, + 0x0ef40232, +/* 0x09dd: i2c_recv_not_wr08 */ +/* 0x09dd: i2c_recv_done */ + 0xf8cec703, + 0x00088c7e, + 0xd0fce0fc, + 0xb20912f4, + 0x029f7e7c, +/* 0x09f1: i2c_recv_exit */ +/* 0x09f3: i2c_init */ 0xf800f800, -/* 0x0a21: idle */ - 0x0031f400, - 0xcf045441, - 0x10b60011, - 0x04544001, - 0xbd0001f6, -/* 0x0a35: idle_loop */ - 0xf4580104, -/* 0x0a3a: idle_proc */ -/* 0x0a3a: idle_proc_exec */ - 0x10f90232, - 0xa87e1eb2, - 0x10fc0002, - 0xf40911f4, - 0x0ef40231, -/* 0x0a4d: idle_proc_next */ - 0x5810b6f0, - 0x1bf41fa6, - 0xe002f4e8, - 0xf40028f4, - 0x0000c60e, +/* 0x09f5: test_recv */ + 0x04584100, + 0xb60011cf, + 0x58400110, + 0x0001f604, + 0x00de04bd, + 0x7e134fd9, + 0xf80001de, +/* 0x0a11: test_init */ + 0x08004e00, + 0x0001de7e, +/* 0x0a1a: idle_recv */ + 0x00f800f8, +/* 0x0a1c: idle */ + 0x410031f4, + 0x11cf0454, + 0x0110b600, + 0xf6045440, + 0x04bd0001, +/* 0x0a30: idle_loop */ + 0x32f45801, +/* 0x0a35: idle_proc */ +/* 0x0a35: idle_proc_exec */ + 0xb210f902, + 0x02a87e1e, + 0xf410fc00, + 0x31f40911, + 0xf00ef402, +/* 0x0a48: idle_proc_next */ + 0xa65810b6, + 0xe81bf41f, + 0xf4e002f4, + 0x0ef40028, + 0x000000c6, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h index 6a2572e8945ad7..defddf5957eee0 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/gt215.fuc3.h @@ -47,8 +47,8 @@ static uint32_t gt215_pmu_data[] = { 0x00000000, 0x00000000, 0x584d454d, - 0x0000083a, - 0x0000082c, + 0x00000833, + 0x00000825, 0x00000000, 0x00000000, 0x00000000, @@ -69,8 +69,8 @@ static uint32_t gt215_pmu_data[] = { 0x00000000, 0x00000000, 0x46524550, - 0x0000083e, - 0x0000083c, + 0x00000837, + 0x00000835, 0x00000000, 0x00000000, 0x00000000, @@ -91,8 +91,8 @@ static uint32_t gt215_pmu_data[] = { 0x00000000, 0x00000000, 0x5f433249, - 0x00000c6e, - 0x00000b11, + 0x00000c67, + 0x00000b0a, 0x00000000, 0x00000000, 0x00000000, @@ -113,8 +113,8 @@ static uint32_t gt215_pmu_data[] = { 0x00000000, 0x00000000, 0x54534554, - 0x00000c97, - 0x00000c70, + 0x00000c90, + 0x00000c69, 0x00000000, 0x00000000, 0x00000000, @@ -135,8 +135,8 @@ static uint32_t gt215_pmu_data[] = { 0x00000000, 0x00000000, 0x454c4449, - 0x00000ca3, - 0x00000ca1, + 0x00000c9c, + 0x00000c9a, 0x00000000, 0x00000000, 0x00000000, @@ -234,22 +234,22 @@ static uint32_t gt215_pmu_data[] = { /* 0x037c: memx_func_next */ 0x00000002, 0x00000000, - 0x000005a0, + 0x0000059f, 0x00000003, 0x00000002, - 0x00000632, + 0x0000062f, 0x00040004, 0x00000000, - 0x0000064e, + 0x0000064b, 0x00010005, 0x00000000, - 0x0000066b, + 0x00000668, 0x00010006, 0x00000000, - 0x000005f0, + 0x000005ef, 0x00000007, 0x00000000, - 0x00000676, + 0x00000673, /* 0x03c4: memx_func_tail */ /* 0x03c4: memx_ts_start */ 0x00000000, @@ -1305,560 +1305,560 @@ static uint32_t gt215_pmu_code[] = { 0x67f102d7, 0x63f1fffc, 0x76fdffff, - 0x0267f104, - 0x0576fd00, - 0x70f980f9, - 0xe0fcd0fc, - 0xf04021f4, + 0x0267f004, + 0xf90576fd, + 0xfc70f980, + 0xf4e0fcd0, + 0x67f04021, + 0xe007f104, + 0x0604b607, + 0xbd0006d0, +/* 0x0581: memx_func_enter_wait */ + 0xc067f104, + 0x0664b607, + 0xf00066cf, + 0x0bf40464, + 0x2c67f0f3, + 0xcf0664b6, + 0x06800066, +/* 0x059f: memx_func_leave */ + 0xf000f8f1, + 0x64b62c67, + 0x0066cf06, + 0xf0f20680, 0x07f10467, - 0x04b607e0, + 0x04b607e4, 0x0006d006, -/* 0x0582: memx_func_enter_wait */ +/* 0x05ba: memx_func_leave_wait */ 0x67f104bd, 0x64b607c0, 0x0066cf06, 0xf40464f0, - 0x67f0f30b, - 0x0664b62c, - 0x800066cf, - 0x00f8f106, -/* 0x05a0: memx_func_leave */ - 0xb62c67f0, - 0x66cf0664, - 0xf2068000, - 0xf10467f0, - 0xb607e407, - 0x06d00604, -/* 0x05bb: memx_func_leave_wait */ - 0xf104bd00, - 0xb607c067, - 0x66cf0664, - 0x0464f000, - 0xf1f31bf4, - 0xb9161087, - 0x21f4028e, - 0x02d7b904, - 0xffcc67f1, - 0xffff63f1, - 0xf90476fd, - 0xfc70f980, - 0xf4e0fcd0, - 0x00f84021, -/* 0x05f0: memx_func_wait_vblank */ - 0xb0001698, - 0x0bf40066, - 0x0166b013, - 0xf4060bf4, -/* 0x0602: memx_func_wait_vblank_head1 */ - 0x77f12e0e, - 0x0ef40020, -/* 0x0609: memx_func_wait_vblank_head0 */ - 0x0877f107, -/* 0x060d: memx_func_wait_vblank_0 */ - 0xc467f100, - 0x0664b607, - 0xfd0066cf, - 0x1bf40467, -/* 0x061d: memx_func_wait_vblank_1 */ - 0xc467f1f3, - 0x0664b607, - 0xfd0066cf, - 0x0bf40467, -/* 0x062d: memx_func_wait_vblank_fini */ - 0x0410b6f3, -/* 0x0632: memx_func_wr32 */ - 0x169800f8, - 0x01159800, - 0xf90810b6, - 0xfc50f960, - 0xf4e0fcd0, - 0x42b64021, - 0xe91bf402, -/* 0x064e: memx_func_wait */ - 0x87f000f8, - 0x0684b62c, - 0x980088cf, - 0x1d98001e, - 0x021c9801, - 0xb6031b98, - 0x21f41010, -/* 0x066b: memx_func_delay */ - 0x9800f8a3, - 0x10b6001e, - 0x7e21f404, -/* 0x0676: memx_func_train */ - 0x57f100f8, - 0x77f10003, - 0x97f10000, - 0x93f00000, - 0x029eb970, - 0xb90421f4, - 0xe7f102d8, - 0x21f42710, -/* 0x0695: memx_func_train_loop_outer */ - 0x0158e07e, - 0x0083f101, - 0xe097f102, - 0x1193f011, - 0x80f990f9, + 0x87f1f31b, + 0x8eb91610, + 0x0421f402, + 0xf102d7b9, + 0xf1ffcc67, + 0xfdffff63, + 0x80f90476, + 0xd0fc70f9, + 0x21f4e0fc, +/* 0x05ef: memx_func_wait_vblank */ + 0x9800f840, + 0x66b00016, + 0x120bf400, + 0xf40166b0, + 0x0ef4060b, +/* 0x0601: memx_func_wait_vblank_head1 */ + 0x2077f02c, +/* 0x0607: memx_func_wait_vblank_head0 */ + 0xf0060ef4, +/* 0x060a: memx_func_wait_vblank_0 */ + 0x67f10877, + 0x64b607c4, + 0x0066cf06, + 0xf40467fd, +/* 0x061a: memx_func_wait_vblank_1 */ + 0x67f1f31b, + 0x64b607c4, + 0x0066cf06, + 0xf40467fd, +/* 0x062a: memx_func_wait_vblank_fini */ + 0x10b6f30b, +/* 0x062f: memx_func_wr32 */ + 0x9800f804, + 0x15980016, + 0x0810b601, + 0x50f960f9, 0xe0fcd0fc, - 0xf94021f4, - 0x0067f150, -/* 0x06b5: memx_func_train_loop_inner */ - 0x1187f100, - 0x9068ff11, - 0xfd109894, - 0x97f10589, - 0x93f00720, - 0xf990f910, - 0xfcd0fc80, - 0x4021f4e0, - 0x008097f1, - 0xb91093f0, - 0x21f4029e, - 0x02d8b904, - 0xf92088c5, + 0xb64021f4, + 0x1bf40242, +/* 0x064b: memx_func_wait */ + 0xf000f8e9, + 0x84b62c87, + 0x0088cf06, + 0x98001e98, + 0x1c98011d, + 0x031b9802, + 0xf41010b6, + 0x00f8a321, +/* 0x0668: memx_func_delay */ + 0xb6001e98, + 0x21f40410, +/* 0x0673: memx_func_train */ + 0xf000f87e, + 0x77f00357, + 0x0097f100, + 0x7093f000, + 0xf4029eb9, + 0xd8b90421, + 0x10e7f102, + 0x7e21f427, +/* 0x0690: memx_func_train_loop_outer */ + 0x010158e0, + 0x020083f1, + 0x11e097f1, + 0xf91193f0, + 0xfc80f990, + 0xf4e0fcd0, + 0x50f94021, +/* 0x06af: memx_func_train_loop_inner */ + 0xf10067f0, + 0xff111187, + 0x98949068, + 0x0589fd10, + 0x072097f1, + 0xf91093f0, 0xfc80f990, 0xf4e0fcd0, 0x97f14021, - 0x93f0053c, - 0x0287f110, - 0x0083f130, - 0xf990f980, + 0x93f00080, + 0x029eb910, + 0xb90421f4, + 0x88c502d8, + 0xf990f920, 0xfcd0fc80, 0x4021f4e0, - 0x0560e7f1, - 0xf110e3f0, - 0xf10000d7, - 0x908000d3, - 0xb7f100dc, - 0xb3f08480, - 0xa321f41e, - 0x000057f1, - 0xffff97f1, - 0x830093f1, -/* 0x0734: memx_func_train_loop_4x */ - 0x0080a7f1, - 0xb910a3f0, - 0x21f402ae, - 0x02d8b904, - 0xffdfb7f1, - 0xffffb3f1, - 0xf9048bfd, - 0xfc80f9a0, + 0x053c97f1, + 0xf11093f0, + 0xf1300287, + 0xf9800083, + 0xfc80f990, 0xf4e0fcd0, - 0xa7f14021, - 0xa3f0053c, - 0x0287f110, - 0x0083f130, - 0xf9a0f980, - 0xfcd0fc80, - 0x4021f4e0, - 0x0560e7f1, - 0xf110e3f0, - 0xf10000d7, - 0xb98000d3, - 0xb7f102dc, - 0xb3f02710, - 0xa321f400, - 0xf402eeb9, - 0xddb90421, - 0x949dff02, + 0xe7f14021, + 0xe3f00560, + 0x00d7f110, + 0x00d3f100, + 0x00dc9080, + 0x8480b7f1, + 0xf41eb3f0, + 0x57f0a321, + 0xff97f100, + 0x0093f1ff, +/* 0x072d: memx_func_train_loop_4x */ + 0x80a7f183, + 0x10a3f000, + 0xf402aeb9, + 0xd8b90421, + 0xdfb7f102, + 0xffb3f1ff, + 0x048bfdff, + 0x80f9a0f9, + 0xe0fcd0fc, + 0xf14021f4, + 0xf0053ca7, + 0x87f110a3, + 0x83f13002, + 0xa0f98000, + 0xd0fc80f9, + 0x21f4e0fc, + 0x60e7f140, + 0x10e3f005, + 0x0000d7f1, + 0x8000d3f1, + 0xf102dcb9, + 0xf02710b7, + 0x21f400b3, + 0x02eeb9a3, + 0xb90421f4, + 0x9dff02dd, + 0x0150b694, + 0xf4045670, + 0x7aa0921e, + 0xa9800bcc, + 0x0160b600, + 0x700470b6, + 0x1ef51066, + 0x50fcff01, 0x700150b6, - 0x1ef40456, - 0xcc7aa092, - 0x00a9800b, - 0xb60160b6, - 0x66700470, - 0x001ef510, - 0xb650fcff, - 0x56700150, - 0xd41ef507, -/* 0x07c7: memx_exec */ - 0xf900f8fe, - 0xb9d0f9e0, - 0xb2b902c1, -/* 0x07d1: memx_exec_next */ - 0x00139802, - 0xe70410b6, - 0xe701f034, - 0xb601e033, - 0x30f00132, - 0xde35980c, - 0x12b855f9, - 0xe41ef406, - 0x98f10b98, - 0xcbbbf20c, - 0xc4b7f102, - 0x06b4b607, - 0xfc00bbcf, - 0xf5e0fcd0, + 0x1ef50756, + 0x00f8fed6, +/* 0x07c0: memx_exec */ + 0xd0f9e0f9, + 0xb902c1b9, +/* 0x07ca: memx_exec_next */ + 0x139802b2, + 0x0410b600, + 0x01f034e7, + 0x01e033e7, + 0xf00132b6, + 0x35980c30, + 0xb855f9de, + 0x1ef40612, + 0xf10b98e4, + 0xbbf20c98, + 0xb7f102cb, + 0xb4b607c4, + 0x00bbcf06, + 0xe0fcd0fc, + 0x033621f5, +/* 0x0806: memx_info */ + 0xc67000f8, + 0x0e0bf401, +/* 0x080c: memx_info_data */ + 0x03ccc7f1, + 0x0800b7f1, +/* 0x0817: memx_info_train */ + 0xf10b0ef4, + 0xf10bccc7, +/* 0x081f: memx_info_send */ + 0xf50100b7, 0xf8033621, -/* 0x080d: memx_info */ - 0x01c67000, -/* 0x0813: memx_info_data */ - 0xf10e0bf4, - 0xf103ccc7, - 0xf40800b7, -/* 0x081e: memx_info_train */ - 0xc7f10b0e, - 0xb7f10bcc, -/* 0x0826: memx_info_send */ - 0x21f50100, - 0x00f80336, -/* 0x082c: memx_recv */ - 0xf401d6b0, - 0xd6b0980b, - 0xd80bf400, -/* 0x083a: memx_init */ - 0x00f800f8, -/* 0x083c: perf_recv */ -/* 0x083e: perf_init */ - 0x00f800f8, -/* 0x0840: i2c_drive_scl */ - 0xf40036b0, - 0x07f1110b, - 0x04b607e0, - 0x0001d006, - 0x00f804bd, -/* 0x0854: i2c_drive_scl_lo */ - 0x07e407f1, - 0xd00604b6, - 0x04bd0001, -/* 0x0862: i2c_drive_sda */ - 0x36b000f8, - 0x110bf400, - 0x07e007f1, - 0xd00604b6, - 0x04bd0002, -/* 0x0876: i2c_drive_sda_lo */ - 0x07f100f8, - 0x04b607e4, - 0x0002d006, - 0x00f804bd, -/* 0x0884: i2c_sense_scl */ - 0xf10132f4, - 0xb607c437, - 0x33cf0634, - 0x0431fd00, - 0xf4060bf4, -/* 0x089a: i2c_sense_scl_done */ - 0x00f80131, -/* 0x089c: i2c_sense_sda */ - 0xf10132f4, - 0xb607c437, - 0x33cf0634, - 0x0432fd00, - 0xf4060bf4, -/* 0x08b2: i2c_sense_sda_done */ - 0x00f80131, -/* 0x08b4: i2c_raise_scl */ - 0x47f140f9, - 0x37f00898, - 0x4021f501, -/* 0x08c1: i2c_raise_scl_wait */ +/* 0x0825: memx_recv */ + 0x01d6b000, + 0xb0980bf4, + 0x0bf400d6, +/* 0x0833: memx_init */ + 0xf800f8d8, +/* 0x0835: perf_recv */ +/* 0x0837: perf_init */ + 0xf800f800, +/* 0x0839: i2c_drive_scl */ + 0x0036b000, + 0xf1110bf4, + 0xb607e007, + 0x01d00604, + 0xf804bd00, +/* 0x084d: i2c_drive_scl_lo */ + 0xe407f100, + 0x0604b607, + 0xbd0001d0, +/* 0x085b: i2c_drive_sda */ + 0xb000f804, + 0x0bf40036, + 0xe007f111, + 0x0604b607, + 0xbd0002d0, +/* 0x086f: i2c_drive_sda_lo */ + 0xf100f804, + 0xb607e407, + 0x02d00604, + 0xf804bd00, +/* 0x087d: i2c_sense_scl */ + 0x0132f400, + 0x07c437f1, + 0xcf0634b6, + 0x31fd0033, + 0x060bf404, +/* 0x0893: i2c_sense_scl_done */ + 0xf80131f4, +/* 0x0895: i2c_sense_sda */ + 0x0132f400, + 0x07c437f1, + 0xcf0634b6, + 0x32fd0033, + 0x060bf404, +/* 0x08ab: i2c_sense_sda_done */ + 0xf80131f4, +/* 0x08ad: i2c_raise_scl */ + 0xf140f900, + 0xf0089847, + 0x21f50137, +/* 0x08ba: i2c_raise_scl_wait */ + 0xe7f10839, + 0x21f403e8, + 0x7d21f57e, + 0x0901f408, + 0xf40142b6, +/* 0x08ce: i2c_raise_scl_done */ + 0x40fcef1b, +/* 0x08d2: i2c_start */ + 0x21f500f8, + 0x11f4087d, + 0x9521f50d, + 0x0611f408, +/* 0x08e3: i2c_start_rep */ + 0xf0300ef4, + 0x21f50037, + 0x37f00839, + 0x5b21f501, + 0x0076bb08, + 0xf90465b6, + 0x04659450, + 0xbd0256bb, + 0x0475fd50, + 0x21f550fc, + 0x64b608ad, + 0x1f11f404, +/* 0x0910: i2c_start_send */ + 0xf50037f0, + 0xf1085b21, + 0xf41388e7, + 0x37f07e21, + 0x3921f500, + 0x88e7f108, + 0x7e21f413, +/* 0x092c: i2c_start_out */ +/* 0x092e: i2c_stop */ + 0x37f000f8, + 0x3921f500, + 0x0037f008, + 0x085b21f5, + 0x03e8e7f1, + 0xf07e21f4, + 0x21f50137, + 0xe7f10839, + 0x21f41388, + 0x0137f07e, + 0x085b21f5, + 0x1388e7f1, + 0xf87e21f4, +/* 0x0961: i2c_bitw */ + 0x5b21f500, 0xe8e7f108, 0x7e21f403, - 0x088421f5, - 0xb60901f4, - 0x1bf40142, -/* 0x08d5: i2c_raise_scl_done */ - 0xf840fcef, -/* 0x08d9: i2c_start */ - 0x8421f500, - 0x0d11f408, - 0x089c21f5, - 0xf40611f4, -/* 0x08ea: i2c_start_rep */ - 0x37f0300e, - 0x4021f500, - 0x0137f008, - 0x086221f5, 0xb60076bb, 0x50f90465, 0xbb046594, 0x50bd0256, 0xfc0475fd, - 0xb421f550, + 0xad21f550, 0x0464b608, -/* 0x0917: i2c_start_send */ - 0xf01f11f4, - 0x21f50037, - 0xe7f10862, - 0x21f41388, - 0x0037f07e, - 0x084021f5, - 0x1388e7f1, -/* 0x0933: i2c_start_out */ - 0xf87e21f4, -/* 0x0935: i2c_stop */ - 0x0037f000, - 0x084021f5, - 0xf50037f0, - 0xf1086221, - 0xf403e8e7, + 0xf11811f4, + 0xf41388e7, 0x37f07e21, - 0x4021f501, + 0x3921f500, 0x88e7f108, 0x7e21f413, - 0xf50137f0, - 0xf1086221, - 0xf41388e7, - 0x00f87e21, -/* 0x0968: i2c_bitw */ - 0x086221f5, - 0x03e8e7f1, - 0xbb7e21f4, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x08b421f5, - 0xf40464b6, - 0xe7f11811, +/* 0x09a0: i2c_bitw_out */ +/* 0x09a2: i2c_bitr */ + 0x37f000f8, + 0x5b21f501, + 0xe8e7f108, + 0x7e21f403, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0xad21f550, + 0x0464b608, + 0xf51b11f4, + 0xf0089521, + 0x21f50037, + 0xe7f10839, 0x21f41388, - 0x0037f07e, - 0x084021f5, - 0x1388e7f1, -/* 0x09a7: i2c_bitw_out */ - 0xf87e21f4, -/* 0x09a9: i2c_bitr */ - 0x0137f000, - 0x086221f5, - 0x03e8e7f1, - 0xbb7e21f4, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x08b421f5, - 0xf40464b6, - 0x21f51b11, - 0x37f0089c, - 0x4021f500, - 0x88e7f108, - 0x7e21f413, - 0xf4013cf0, -/* 0x09ee: i2c_bitr_done */ - 0x00f80131, -/* 0x09f0: i2c_get_byte */ - 0xf00057f0, -/* 0x09f6: i2c_get_byte_next */ - 0x54b60847, + 0x013cf07e, +/* 0x09e7: i2c_bitr_done */ + 0xf80131f4, +/* 0x09e9: i2c_get_byte */ + 0x0057f000, +/* 0x09ef: i2c_get_byte_next */ + 0xb60847f0, + 0x76bb0154, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb609a221, + 0x11f40464, + 0x0553fd2b, + 0xf40142b6, + 0x37f0d81b, 0x0076bb01, 0xf90465b6, 0x04659450, 0xbd0256bb, 0x0475fd50, 0x21f550fc, - 0x64b609a9, - 0x2b11f404, - 0xb60553fd, - 0x1bf40142, - 0x0137f0d8, - 0xb60076bb, - 0x50f90465, - 0xbb046594, - 0x50bd0256, - 0xfc0475fd, - 0x6821f550, - 0x0464b609, -/* 0x0a40: i2c_get_byte_done */ -/* 0x0a42: i2c_put_byte */ - 0x47f000f8, -/* 0x0a45: i2c_put_byte_next */ - 0x0142b608, - 0xbb3854ff, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x096821f5, - 0xf40464b6, - 0x46b03411, - 0xd81bf400, + 0x64b60961, +/* 0x0a39: i2c_get_byte_done */ +/* 0x0a3b: i2c_put_byte */ + 0xf000f804, +/* 0x0a3e: i2c_put_byte_next */ + 0x42b60847, + 0x3854ff01, 0xb60076bb, 0x50f90465, 0xbb046594, 0x50bd0256, 0xfc0475fd, - 0xa921f550, + 0x6121f550, 0x0464b609, - 0xbb0f11f4, - 0x36b00076, - 0x061bf401, -/* 0x0a9b: i2c_put_byte_done */ - 0xf80132f4, -/* 0x0a9d: i2c_addr */ - 0x0076bb00, + 0xb03411f4, + 0x1bf40046, + 0x0076bbd8, 0xf90465b6, 0x04659450, 0xbd0256bb, 0x0475fd50, 0x21f550fc, - 0x64b608d9, - 0x2911f404, - 0x012ec3e7, - 0xfd0134b6, - 0x76bb0553, + 0x64b609a2, + 0x0f11f404, + 0xb00076bb, + 0x1bf40136, + 0x0132f406, +/* 0x0a94: i2c_put_byte_done */ +/* 0x0a96: i2c_addr */ + 0x76bb00f8, 0x0465b600, 0x659450f9, 0x0256bb04, 0x75fd50bd, 0xf550fc04, - 0xb60a4221, -/* 0x0ae2: i2c_addr_done */ - 0x00f80464, -/* 0x0ae4: i2c_acquire_addr */ - 0xb6f8cec7, - 0xe0b702e4, - 0xee980d1c, -/* 0x0af3: i2c_acquire */ - 0xf500f800, - 0xf40ae421, - 0xd9f00421, - 0x4021f403, -/* 0x0b02: i2c_release */ - 0x21f500f8, - 0x21f40ae4, - 0x03daf004, - 0xf84021f4, -/* 0x0b11: i2c_recv */ - 0x0132f400, - 0xb6f8c1c7, - 0x16b00214, - 0x3a1ff528, - 0xf413a001, - 0x0032980c, - 0x0ccc13a0, - 0xf4003198, - 0xd0f90231, - 0xd0f9e0f9, - 0x000067f1, - 0x100063f1, - 0xbb016792, + 0xb608d221, + 0x11f40464, + 0x2ec3e729, + 0x0134b601, + 0xbb0553fd, 0x65b60076, 0x9450f904, 0x56bb0465, 0xfd50bd02, 0x50fc0475, - 0x0af321f5, - 0xfc0464b6, - 0x00d6b0d0, - 0x00b31bf5, - 0xbb0057f0, + 0x0a3b21f5, +/* 0x0adb: i2c_addr_done */ + 0xf80464b6, +/* 0x0add: i2c_acquire_addr */ + 0xf8cec700, + 0xb702e4b6, + 0x980d1ce0, + 0x00f800ee, +/* 0x0aec: i2c_acquire */ + 0x0add21f5, + 0xf00421f4, + 0x21f403d9, +/* 0x0afb: i2c_release */ + 0xf500f840, + 0xf40add21, + 0xdaf00421, + 0x4021f403, +/* 0x0b0a: i2c_recv */ + 0x32f400f8, + 0xf8c1c701, + 0xb00214b6, + 0x1ff52816, + 0x13a0013a, + 0x32980cf4, + 0xcc13a000, + 0x0031980c, + 0xf90231f4, + 0xf9e0f9d0, + 0x0067f1d0, + 0x0063f100, + 0x01679210, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0xec21f550, + 0x0464b60a, + 0xd6b0d0fc, + 0xb31bf500, + 0x0057f000, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x9621f550, + 0x0464b60a, + 0x00d011f5, + 0xbbe0c5c7, 0x65b60076, 0x9450f904, 0x56bb0465, 0xfd50bd02, 0x50fc0475, - 0x0a9d21f5, + 0x0a3b21f5, 0xf50464b6, - 0xc700d011, - 0x76bbe0c5, + 0xf000ad11, + 0x76bb0157, 0x0465b600, 0x659450f9, 0x0256bb04, 0x75fd50bd, 0xf550fc04, - 0xb60a4221, + 0xb60a9621, 0x11f50464, - 0x57f000ad, - 0x0076bb01, - 0xf90465b6, - 0x04659450, - 0xbd0256bb, - 0x0475fd50, - 0x21f550fc, - 0x64b60a9d, - 0x8a11f504, - 0x0076bb00, - 0xf90465b6, - 0x04659450, - 0xbd0256bb, - 0x0475fd50, - 0x21f550fc, - 0x64b609f0, - 0x6a11f404, - 0xbbe05bcb, - 0x65b60076, - 0x9450f904, - 0x56bb0465, - 0xfd50bd02, - 0x50fc0475, - 0x093521f5, - 0xb90464b6, - 0x74bd025b, -/* 0x0c17: i2c_recv_not_rd08 */ - 0xb0430ef4, - 0x1bf401d6, - 0x0057f03d, - 0x0a9d21f5, - 0xc73311f4, - 0x21f5e0c5, - 0x11f40a42, - 0x0057f029, - 0x0a9d21f5, - 0xc71f11f4, - 0x21f5e0b5, - 0x11f40a42, - 0x3521f515, - 0xc774bd09, - 0x1bf408c5, - 0x0232f409, -/* 0x0c57: i2c_recv_not_wr08 */ -/* 0x0c57: i2c_recv_done */ - 0xc7030ef4, - 0x21f5f8ce, - 0xe0fc0b02, - 0x12f4d0fc, - 0x027cb90a, - 0x033621f5, -/* 0x0c6c: i2c_recv_exit */ -/* 0x0c6e: i2c_init */ + 0x76bb008a, + 0x0465b600, + 0x659450f9, + 0x0256bb04, + 0x75fd50bd, + 0xf550fc04, + 0xb609e921, + 0x11f40464, + 0xe05bcb6a, + 0xb60076bb, + 0x50f90465, + 0xbb046594, + 0x50bd0256, + 0xfc0475fd, + 0x2e21f550, + 0x0464b609, + 0xbd025bb9, + 0x430ef474, +/* 0x0c10: i2c_recv_not_rd08 */ + 0xf401d6b0, + 0x57f03d1b, + 0x9621f500, + 0x3311f40a, + 0xf5e0c5c7, + 0xf40a3b21, + 0x57f02911, + 0x9621f500, + 0x1f11f40a, + 0xf5e0b5c7, + 0xf40a3b21, + 0x21f51511, + 0x74bd092e, + 0xf408c5c7, + 0x32f4091b, + 0x030ef402, +/* 0x0c50: i2c_recv_not_wr08 */ +/* 0x0c50: i2c_recv_done */ + 0xf5f8cec7, + 0xfc0afb21, + 0xf4d0fce0, + 0x7cb90a12, + 0x3621f502, +/* 0x0c65: i2c_recv_exit */ +/* 0x0c67: i2c_init */ + 0xf800f803, +/* 0x0c69: test_recv */ + 0xd817f100, + 0x0614b605, + 0xb60011cf, + 0x07f10110, + 0x04b605d8, + 0x0001d006, + 0xe7f104bd, + 0xe3f1d900, + 0x21f5134f, + 0x00f80256, +/* 0x0c90: test_init */ + 0x0800e7f1, + 0x025621f5, +/* 0x0c9a: idle_recv */ 0x00f800f8, -/* 0x0c70: test_recv */ - 0x05d817f1, - 0xcf0614b6, - 0x10b60011, - 0xd807f101, - 0x0604b605, - 0xbd0001d0, - 0x00e7f104, - 0x4fe3f1d9, - 0x5621f513, -/* 0x0c97: test_init */ - 0xf100f802, - 0xf50800e7, - 0xf8025621, -/* 0x0ca1: idle_recv */ -/* 0x0ca3: idle */ - 0xf400f800, - 0x17f10031, - 0x14b605d4, - 0x0011cf06, - 0xf10110b6, - 0xb605d407, - 0x01d00604, -/* 0x0cbf: idle_loop */ - 0xf004bd00, - 0x32f45817, -/* 0x0cc5: idle_proc */ -/* 0x0cc5: idle_proc_exec */ - 0xb910f902, - 0x21f5021e, - 0x10fc033f, - 0xf40911f4, - 0x0ef40231, -/* 0x0cd9: idle_proc_next */ - 0x5810b6ef, - 0xf4061fb8, - 0x02f4e61b, - 0x0028f4dd, - 0x00bb0ef4, +/* 0x0c9c: idle */ + 0xf10031f4, + 0xb605d417, + 0x11cf0614, + 0x0110b600, + 0x05d407f1, + 0xd00604b6, + 0x04bd0001, +/* 0x0cb8: idle_loop */ + 0xf45817f0, +/* 0x0cbe: idle_proc */ +/* 0x0cbe: idle_proc_exec */ + 0x10f90232, + 0xf5021eb9, + 0xfc033f21, + 0x0911f410, + 0xf40231f4, +/* 0x0cd2: idle_proc_next */ + 0x10b6ef0e, + 0x061fb858, + 0xf4e61bf4, + 0x28f4dd02, + 0xbb0ef400, + 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/memx.fuc b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/memx.fuc index ec03f9a4290b4d..1663bf943d771a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/memx.fuc +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/pmu/fuc/memx.fuc @@ -82,15 +82,15 @@ memx_train_tail: // $r0 - zero memx_func_enter: #if NVKM_PPWR_CHIPSET == GT215 - movw $r8 0x1610 + mov $r8 0x1610 nv_rd32($r7, $r8) imm32($r6, 0xfffffffc) and $r7 $r6 - movw $r6 0x2 + mov $r6 0x2 or $r7 $r6 nv_wr32($r8, $r7) #else - movw $r6 0x001620 + mov $r6 0x001620 imm32($r7, ~0x00000aa2); nv_rd32($r8, $r6) and $r8 $r7 @@ -101,7 +101,7 @@ memx_func_enter: and $r8 $r7 nv_wr32($r6, $r8) - movw $r6 0x0026f0 + mov $r6 0x0026f0 nv_rd32($r8, $r6) and $r8 $r7 nv_wr32($r6, $r8) @@ -136,19 +136,19 @@ memx_func_leave: bra nz #memx_func_leave_wait #if NVKM_PPWR_CHIPSET == GT215 - movw $r8 0x1610 + mov $r8 0x1610 nv_rd32($r7, $r8) imm32($r6, 0xffffffcc) and $r7 $r6 nv_wr32($r8, $r7) #else - movw $r6 0x0026f0 + mov $r6 0x0026f0 imm32($r7, 0x00000001) nv_rd32($r8, $r6) or $r8 $r7 nv_wr32($r6, $r8) - movw $r6 0x001620 + mov $r6 0x001620 nv_rd32($r8, $r6) or $r8 $r7 nv_wr32($r6, $r8) @@ -177,11 +177,11 @@ memx_func_wait_vblank: bra #memx_func_wait_vblank_fini memx_func_wait_vblank_head1: - movw $r7 0x20 + mov $r7 0x20 bra #memx_func_wait_vblank_0 memx_func_wait_vblank_head0: - movw $r7 0x8 + mov $r7 0x8 memx_func_wait_vblank_0: nv_iord($r6, NV_PPWR_INPUT) @@ -273,13 +273,13 @@ memx_func_train: // $r5 - outer loop counter // $r6 - inner loop counter // $r7 - entry counter (#memx_train_head + $r7) - movw $r5 0x3 - movw $r7 0x0 + mov $r5 0x3 + mov $r7 0x0 // Read random memory to wake up... things imm32($r9, 0x700000) nv_rd32($r8,$r9) - movw $r14 0x2710 + mov $r14 0x2710 call(nsec) memx_func_train_loop_outer: @@ -289,9 +289,9 @@ memx_func_train: nv_wr32($r9, $r8) push $r5 - movw $r6 0x0 + mov $r6 0x0 memx_func_train_loop_inner: - movw $r8 0x1111 + mov $r8 0x1111 mulu $r9 $r6 $r8 shl b32 $r8 $r9 0x10 or $r8 $r9 @@ -315,7 +315,7 @@ memx_func_train: // $r5 - inner inner loop counter // $r9 - result - movw $r5 0 + mov $r5 0 imm32($r9, 0x8300ffff) memx_func_train_loop_4x: imm32($r10, 0x100080) From 94ee54dc808aa5a13630b082d6f892d0cf7bf527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20B=C3=B6hmwalder?= Date: Thu, 30 Nov 2017 20:53:54 +0100 Subject: [PATCH 094/237] drm/nouveau/drm/nouveau/mmu: fix odd_ptr_err.cocci warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The kbuild test bot complained about a new coccinelle warning nearby, which sparked a discussion about the assignment to 'memory' inside of the conditional expression. See Link below for the original post. Fix the assignment to silence the coccinelle warning and also make the code look a little nicer. Link: https://lists.freedesktop.org/archives/nouveau/2017-November/029242.html Signed-off-by: Christoph Böhmwalder Signed-off-by: Ben Skeggs Reviewed-by: Karol Herbst --- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c index fa81d0c1ba415f..37b201b95f15bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/uvmm.c @@ -106,7 +106,8 @@ nvkm_uvmm_mthd_map(struct nvkm_uvmm *uvmm, void *argv, u32 argc) } else return ret; - if (IS_ERR((memory = nvkm_umem_search(client, handle)))) { + memory = nvkm_umem_search(client, handle); + if (IS_ERR(memory)) { VMM_DEBUG(vmm, "memory %016llx %ld\n", handle, PTR_ERR(memory)); return PTR_ERR(memory); } From ee0d58100296d9b1a2aa23b913c09e8f297449a4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 4 Dec 2017 15:54:26 +0100 Subject: [PATCH 095/237] drm/nouveau: nouveau: use correct string length gcc-8 reports drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c: In function 'nvkm_perfmon_mthd': include/linux/string.h:265:9: error: '__builtin_strncpy' specified bound 64 equals destination size [-Werror=stringop-truncation] We need one less byte or call strlcpy() to make it a nul-terminated string. Signed-off-by: Arnd Bergmann Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c index dde89a4a0f5b95..53859b6254d624 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/pm/base.c @@ -462,7 +462,7 @@ nvkm_perfmon_mthd_query_domain(struct nvkm_perfmon *perfmon, args->v0.id = di; args->v0.signal_nr = nvkm_perfdom_count_perfsig(dom); - strncpy(args->v0.name, dom->name, sizeof(args->v0.name)); + strncpy(args->v0.name, dom->name, sizeof(args->v0.name) - 1); /* Currently only global counters (PCOUNTER) are implemented * but this will be different for local counters (MP). */ @@ -514,7 +514,7 @@ nvkm_perfmon_mthd_query_signal(struct nvkm_perfmon *perfmon, "/%s/%02x", dom->name, si); } else { strncpy(args->v0.name, sig->name, - sizeof(args->v0.name)); + sizeof(args->v0.name) - 1); } args->v0.signal = si; @@ -572,7 +572,7 @@ nvkm_perfmon_mthd_query_source(struct nvkm_perfmon *perfmon, args->v0.source = sig->source[si]; args->v0.mask = src->mask; - strncpy(args->v0.name, src->name, sizeof(args->v0.name)); + strncpy(args->v0.name, src->name, sizeof(args->v0.name) - 1); } if (++si < source_nr) { From b7997a35f936e92de0f69231c3ba6aa7cc6c20f1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 12 Dec 2017 15:50:10 +1000 Subject: [PATCH 096/237] drm/nouveau/secboot/r370: move a bunch of r375 stuff to a new implementation It's entirely possibly that the other r375 code is relevant to r370 too, but I've not confirmed this, so I'll leave it where it is for now. NVIDIA's copyright headers maintained, as it's still all their code. Signed-off-by: Ben Skeggs Reviewed-by: Gourav Samaiya --- .../drm/nouveau/nvkm/subdev/secboot/Kbuild | 1 + .../gpu/drm/nouveau/nvkm/subdev/secboot/acr.h | 1 + .../nouveau/nvkm/subdev/secboot/acr_r370.c | 105 ++++++++++++++++++ .../nouveau/nvkm/subdev/secboot/acr_r370.h | 49 ++++++++ .../nouveau/nvkm/subdev/secboot/acr_r375.c | 93 ++-------------- 5 files changed, 163 insertions(+), 86 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild index e698f483652164..35ca716a549bc9 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild @@ -7,6 +7,7 @@ nvkm-y += nvkm/subdev/secboot/acr_r352.o nvkm-y += nvkm/subdev/secboot/acr_r361.o nvkm-y += nvkm/subdev/secboot/acr_r364.o nvkm-y += nvkm/subdev/secboot/acr_r367.o +nvkm-y += nvkm/subdev/secboot/acr_r370.o nvkm-y += nvkm/subdev/secboot/acr_r375.o nvkm-y += nvkm/subdev/secboot/gm200.o nvkm-y += nvkm/subdev/secboot/gm20b.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h index b615fc81aca467..73a2ac81ac6929 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr.h @@ -64,6 +64,7 @@ struct nvkm_acr *acr_r352_new(unsigned long); struct nvkm_acr *acr_r361_new(unsigned long); struct nvkm_acr *acr_r364_new(unsigned long); struct nvkm_acr *acr_r367_new(enum nvkm_secboot_falcon, unsigned long); +struct nvkm_acr *acr_r370_new(enum nvkm_secboot_falcon, unsigned long); struct nvkm_acr *acr_r375_new(enum nvkm_secboot_falcon, unsigned long); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c new file mode 100644 index 00000000000000..1b451de31d252a --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include "acr_r370.h" +#include "acr_r367.h" + +#include +#include +#include + +static void +acr_r370_generate_flcn_bl_desc(const struct nvkm_acr *acr, + const struct ls_ucode_img *img, u64 wpr_addr, + void *_desc) +{ + struct acr_r370_flcn_bl_desc *desc = _desc; + const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; + u64 base, addr_code, addr_data; + + base = wpr_addr + img->ucode_off + pdesc->app_start_offset; + addr_code = base + pdesc->app_resident_code_offset; + addr_data = base + pdesc->app_resident_data_offset; + + desc->ctx_dma = FALCON_DMAIDX_UCODE; + desc->code_dma_base = u64_to_flcn64(addr_code); + desc->non_sec_code_off = pdesc->app_resident_code_offset; + desc->non_sec_code_size = pdesc->app_resident_code_size; + desc->code_entry_point = pdesc->app_imem_entry; + desc->data_dma_base = u64_to_flcn64(addr_data); + desc->data_size = pdesc->app_resident_data_size; +} + +const struct acr_r352_ls_func +acr_r370_ls_fecs_func = { + .load = acr_ls_ucode_load_fecs, + .generate_bl_desc = acr_r370_generate_flcn_bl_desc, + .bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), +}; + +const struct acr_r352_ls_func +acr_r370_ls_gpccs_func = { + .load = acr_ls_ucode_load_gpccs, + .generate_bl_desc = acr_r370_generate_flcn_bl_desc, + .bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), + /* GPCCS will be loaded using PRI */ + .lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, +}; + +void +acr_r370_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc, + u64 offset) +{ + struct acr_r370_flcn_bl_desc *bl_desc = _bl_desc; + + bl_desc->ctx_dma = FALCON_DMAIDX_VIRT; + bl_desc->non_sec_code_off = hdr->non_sec_code_off; + bl_desc->non_sec_code_size = hdr->non_sec_code_size; + bl_desc->sec_code_off = hsf_load_header_app_off(hdr, 0); + bl_desc->sec_code_size = hsf_load_header_app_size(hdr, 0); + bl_desc->code_entry_point = 0; + bl_desc->code_dma_base = u64_to_flcn64(offset); + bl_desc->data_dma_base = u64_to_flcn64(offset + hdr->data_dma_base); + bl_desc->data_size = hdr->data_size; +} + +const struct acr_r352_func +acr_r370_func = { + .fixup_hs_desc = acr_r367_fixup_hs_desc, + .generate_hs_bl_desc = acr_r370_generate_hs_bl_desc, + .hs_bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), + .shadow_blob = true, + .ls_ucode_img_load = acr_r367_ls_ucode_img_load, + .ls_fill_headers = acr_r367_ls_fill_headers, + .ls_write_wpr = acr_r367_ls_write_wpr, + .ls_func = { + [NVKM_SECBOOT_FALCON_FECS] = &acr_r370_ls_fecs_func, + [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r370_ls_gpccs_func, + }, +}; + +struct nvkm_acr * +acr_r370_new(enum nvkm_secboot_falcon boot_falcon, + unsigned long managed_falcons) +{ + return acr_r352_new_(&acr_r370_func, boot_falcon, managed_falcons); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h new file mode 100644 index 00000000000000..3426f86a15e476 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2016, NVIDIA CORPORATION. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef __NVKM_SECBOOT_ACR_R370_H__ +#define __NVKM_SECBOOT_ACR_R370_H__ + +#include "priv.h" +struct hsf_load_header; + +/* Same as acr_r361_flcn_bl_desc, plus argc/argv */ +struct acr_r370_flcn_bl_desc { + u32 reserved[4]; + u32 signature[4]; + u32 ctx_dma; + struct flcn_u64 code_dma_base; + u32 non_sec_code_off; + u32 non_sec_code_size; + u32 sec_code_off; + u32 sec_code_size; + u32 code_entry_point; + struct flcn_u64 data_dma_base; + u32 data_size; + u32 argc; + u32 argv; +}; + +void acr_r370_generate_hs_bl_desc(const struct hsf_load_header *, void *, u64); +extern const struct acr_r352_ls_func acr_r370_ls_fecs_func; +extern const struct acr_r352_ls_func acr_r370_ls_gpccs_func; +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c index ddb795bb007bec..7bdef93cb7aeac 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r375.c @@ -20,90 +20,12 @@ * DEALINGS IN THE SOFTWARE. */ +#include "acr_r370.h" #include "acr_r367.h" -#include #include #include -/* - * r375 ACR: similar to r367, but with a unified bootloader descriptor - * structure for GR and PMU falcons. - */ - -/* Same as acr_r361_flcn_bl_desc, plus argc/argv */ -struct acr_r375_flcn_bl_desc { - u32 reserved[4]; - u32 signature[4]; - u32 ctx_dma; - struct flcn_u64 code_dma_base; - u32 non_sec_code_off; - u32 non_sec_code_size; - u32 sec_code_off; - u32 sec_code_size; - u32 code_entry_point; - struct flcn_u64 data_dma_base; - u32 data_size; - u32 argc; - u32 argv; -}; - -static void -acr_r375_generate_flcn_bl_desc(const struct nvkm_acr *acr, - const struct ls_ucode_img *img, u64 wpr_addr, - void *_desc) -{ - struct acr_r375_flcn_bl_desc *desc = _desc; - const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; - u64 base, addr_code, addr_data; - - base = wpr_addr + img->ucode_off + pdesc->app_start_offset; - addr_code = base + pdesc->app_resident_code_offset; - addr_data = base + pdesc->app_resident_data_offset; - - desc->ctx_dma = FALCON_DMAIDX_UCODE; - desc->code_dma_base = u64_to_flcn64(addr_code); - desc->non_sec_code_off = pdesc->app_resident_code_offset; - desc->non_sec_code_size = pdesc->app_resident_code_size; - desc->code_entry_point = pdesc->app_imem_entry; - desc->data_dma_base = u64_to_flcn64(addr_data); - desc->data_size = pdesc->app_resident_data_size; -} - -static void -acr_r375_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc, - u64 offset) -{ - struct acr_r375_flcn_bl_desc *bl_desc = _bl_desc; - - bl_desc->ctx_dma = FALCON_DMAIDX_VIRT; - bl_desc->non_sec_code_off = hdr->non_sec_code_off; - bl_desc->non_sec_code_size = hdr->non_sec_code_size; - bl_desc->sec_code_off = hsf_load_header_app_off(hdr, 0); - bl_desc->sec_code_size = hsf_load_header_app_size(hdr, 0); - bl_desc->code_entry_point = 0; - bl_desc->code_dma_base = u64_to_flcn64(offset); - bl_desc->data_dma_base = u64_to_flcn64(offset + hdr->data_dma_base); - bl_desc->data_size = hdr->data_size; -} - -const struct acr_r352_ls_func -acr_r375_ls_fecs_func = { - .load = acr_ls_ucode_load_fecs, - .generate_bl_desc = acr_r375_generate_flcn_bl_desc, - .bl_desc_size = sizeof(struct acr_r375_flcn_bl_desc), -}; - -const struct acr_r352_ls_func -acr_r375_ls_gpccs_func = { - .load = acr_ls_ucode_load_gpccs, - .generate_bl_desc = acr_r375_generate_flcn_bl_desc, - .bl_desc_size = sizeof(struct acr_r375_flcn_bl_desc), - /* GPCCS will be loaded using PRI */ - .lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, -}; - - static void acr_r375_generate_pmu_bl_desc(const struct nvkm_acr *acr, const struct ls_ucode_img *img, u64 wpr_addr, @@ -111,7 +33,7 @@ acr_r375_generate_pmu_bl_desc(const struct nvkm_acr *acr, { const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; const struct nvkm_pmu *pmu = acr->subdev->device->pmu; - struct acr_r375_flcn_bl_desc *desc = _desc; + struct acr_r370_flcn_bl_desc *desc = _desc; u64 base, addr_code, addr_data; u32 addr_args; @@ -136,23 +58,22 @@ const struct acr_r352_ls_func acr_r375_ls_pmu_func = { .load = acr_ls_ucode_load_pmu, .generate_bl_desc = acr_r375_generate_pmu_bl_desc, - .bl_desc_size = sizeof(struct acr_r375_flcn_bl_desc), + .bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), .post_run = acr_ls_pmu_post_run, }; - const struct acr_r352_func acr_r375_func = { .fixup_hs_desc = acr_r367_fixup_hs_desc, - .generate_hs_bl_desc = acr_r375_generate_hs_bl_desc, - .hs_bl_desc_size = sizeof(struct acr_r375_flcn_bl_desc), + .generate_hs_bl_desc = acr_r370_generate_hs_bl_desc, + .hs_bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), .shadow_blob = true, .ls_ucode_img_load = acr_r367_ls_ucode_img_load, .ls_fill_headers = acr_r367_ls_fill_headers, .ls_write_wpr = acr_r367_ls_write_wpr, .ls_func = { - [NVKM_SECBOOT_FALCON_FECS] = &acr_r375_ls_fecs_func, - [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r375_ls_gpccs_func, + [NVKM_SECBOOT_FALCON_FECS] = &acr_r370_ls_fecs_func, + [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r370_ls_gpccs_func, [NVKM_SECBOOT_FALCON_PMU] = &acr_r375_ls_pmu_func, }, }; From dcc80c89477891e173d999fa8a13edf10d37b639 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 12 Dec 2017 16:08:05 +1000 Subject: [PATCH 097/237] drm/nouveau/secboot/r370: implement support for booting LS SEC2 ucode Signed-off-by: Ben Skeggs Reviewed-by: Gourav Samaiya --- .../nouveau/nvkm/subdev/secboot/acr_r370.c | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c index 1b451de31d252a..2f890dfae7fc16 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/acr_r370.c @@ -65,6 +65,44 @@ acr_r370_ls_gpccs_func = { .lhdr_flags = LSF_FLAG_FORCE_PRIV_LOAD, }; +static void +acr_r370_generate_sec2_bl_desc(const struct nvkm_acr *acr, + const struct ls_ucode_img *img, u64 wpr_addr, + void *_desc) +{ + const struct ls_ucode_img_desc *pdesc = &img->ucode_desc; + const struct nvkm_sec2 *sec = acr->subdev->device->sec2; + struct acr_r370_flcn_bl_desc *desc = _desc; + u64 base, addr_code, addr_data; + u32 addr_args; + + base = wpr_addr + img->ucode_off + pdesc->app_start_offset; + /* For some reason we should not add app_resident_code_offset here */ + addr_code = base; + addr_data = base + pdesc->app_resident_data_offset; + addr_args = sec->falcon->data.limit; + addr_args -= NVKM_MSGQUEUE_CMDLINE_SIZE; + + desc->ctx_dma = FALCON_SEC2_DMAIDX_UCODE; + desc->code_dma_base = u64_to_flcn64(addr_code); + desc->non_sec_code_off = pdesc->app_resident_code_offset; + desc->non_sec_code_size = pdesc->app_resident_code_size; + desc->code_entry_point = pdesc->app_imem_entry; + desc->data_dma_base = u64_to_flcn64(addr_data); + desc->data_size = pdesc->app_resident_data_size; + desc->argc = 1; + /* args are stored at the beginning of EMEM */ + desc->argv = 0x01000000; +} + +const struct acr_r352_ls_func +acr_r370_ls_sec2_func = { + .load = acr_ls_ucode_load_sec2, + .generate_bl_desc = acr_r370_generate_sec2_bl_desc, + .bl_desc_size = sizeof(struct acr_r370_flcn_bl_desc), + .post_run = acr_ls_sec2_post_run, +}; + void acr_r370_generate_hs_bl_desc(const struct hsf_load_header *hdr, void *_bl_desc, u64 offset) @@ -92,6 +130,7 @@ acr_r370_func = { .ls_fill_headers = acr_r367_ls_fill_headers, .ls_write_wpr = acr_r367_ls_write_wpr, .ls_func = { + [NVKM_SECBOOT_FALCON_SEC2] = &acr_r370_ls_sec2_func, [NVKM_SECBOOT_FALCON_FECS] = &acr_r370_ls_fecs_func, [NVKM_SECBOOT_FALCON_GPCCS] = &acr_r370_ls_gpccs_func, }, From 2c5ac5ba4f855b8cb3f20c52c1a1e0773e671164 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Tue, 12 Dec 2017 16:09:03 +1000 Subject: [PATCH 098/237] drm/nouveau/secboot/gp108: implement on top of acr_r370 Signed-off-by: Ben Skeggs Reviewed-by: Gourav Samaiya --- .../drm/nouveau/include/nvkm/subdev/secboot.h | 1 + .../gpu/drm/nouveau/nvkm/engine/device/base.c | 5 ++ .../gpu/drm/nouveau/nvkm/falcon/msgqueue.c | 1 + .../drm/nouveau/nvkm/subdev/secboot/Kbuild | 1 + .../drm/nouveau/nvkm/subdev/secboot/gp102.c | 2 +- .../drm/nouveau/nvkm/subdev/secboot/gp108.c | 67 +++++++++++++++++++ .../drm/nouveau/nvkm/subdev/secboot/priv.h | 2 + 7 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/secboot.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/secboot.h index 59f3ba55168135..b57fe4ae93bab8 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/secboot.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/secboot.h @@ -60,6 +60,7 @@ int nvkm_secboot_reset(struct nvkm_secboot *, unsigned long); int gm200_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); int gm20b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); int gp102_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); +int gp108_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); int gp10b_secboot_new(struct nvkm_device *, int, struct nvkm_secboot **); #endif diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index 00eeaaffeae565..a4a5ffce03d0ae 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -2345,6 +2345,7 @@ nv138_chipset = { .mc = gp100_mc_new, .mmu = gp100_mmu_new, .therm = gp100_therm_new, + .secboot = gp108_secboot_new, .pci = gp100_pci_new, .pmu = gp102_pmu_new, .timer = gk20a_timer_new, @@ -2356,6 +2357,10 @@ nv138_chipset = { .disp = gp102_disp_new, .dma = gf119_dma_new, .fifo = gp100_fifo_new, + .gr = gp107_gr_new, + .nvdec = gp102_nvdec_new, + .sec2 = gp102_sec2_new, + .sw = gf100_sw_new, }; static const struct nvkm_device_chip diff --git a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c index 77273b53672c2f..58a59b7db2e5fe 100644 --- a/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c +++ b/drivers/gpu/drm/nouveau/nvkm/falcon/msgqueue.c @@ -505,6 +505,7 @@ nvkm_msgqueue_new(u32 version, struct nvkm_falcon *falcon, ret = msgqueue_0137bca5_new(falcon, sb, queue); break; case 0x0148cdec: + case 0x015ccf3e: ret = msgqueue_0148cdec_new(falcon, sb, queue); break; default: diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild index 35ca716a549bc9..ed08120eefe014 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/Kbuild @@ -12,4 +12,5 @@ nvkm-y += nvkm/subdev/secboot/acr_r375.o nvkm-y += nvkm/subdev/secboot/gm200.o nvkm-y += nvkm/subdev/secboot/gm20b.o nvkm-y += nvkm/subdev/secboot/gp102.o +nvkm-y += nvkm/subdev/secboot/gp108.o nvkm-y += nvkm/subdev/secboot/gp10b.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c index f3b3c66349d201..1f7a3c1a7f5061 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp102.c @@ -133,7 +133,7 @@ gp102_secboot_run_blob(struct nvkm_secboot *sb, struct nvkm_gpuobj *blob, return gm200_secboot_run_blob(sb, blob, falcon); } -static const struct nvkm_secboot_func +const struct nvkm_secboot_func gp102_secboot = { .dtor = gm200_secboot_dtor, .oneinit = gm200_secboot_oneinit, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c new file mode 100644 index 00000000000000..e8c27ec700de89 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/gp108.c @@ -0,0 +1,67 @@ +/* + * Copyright 2017 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + */ +#include "gm200.h" +#include "acr.h" + +int +gp108_secboot_new(struct nvkm_device *device, int index, + struct nvkm_secboot **psb) +{ + struct gm200_secboot *gsb; + struct nvkm_acr *acr; + + acr = acr_r370_new(NVKM_SECBOOT_FALCON_SEC2, + BIT(NVKM_SECBOOT_FALCON_FECS) | + BIT(NVKM_SECBOOT_FALCON_GPCCS) | + BIT(NVKM_SECBOOT_FALCON_SEC2)); + if (IS_ERR(acr)) + return PTR_ERR(acr); + + if (!(gsb = kzalloc(sizeof(*gsb), GFP_KERNEL))) { + acr->func->dtor(acr); + return -ENOMEM; + } + *psb = &gsb->base; + + return nvkm_secboot_ctor(&gp102_secboot, acr, device, index, &gsb->base); +} + +MODULE_FIRMWARE("nvidia/gp108/acr/bl.bin"); +MODULE_FIRMWARE("nvidia/gp108/acr/unload_bl.bin"); +MODULE_FIRMWARE("nvidia/gp108/acr/ucode_load.bin"); +MODULE_FIRMWARE("nvidia/gp108/acr/ucode_unload.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/fecs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/fecs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/fecs_data.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/fecs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_bl.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_inst.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_data.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/gpccs_sig.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/sw_ctx.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/sw_nonctx.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/sw_bundle_init.bin"); +MODULE_FIRMWARE("nvidia/gp108/gr/sw_method_init.bin"); +MODULE_FIRMWARE("nvidia/gp108/nvdec/scrubber.bin"); +MODULE_FIRMWARE("nvidia/gp108/sec2/desc.bin"); +MODULE_FIRMWARE("nvidia/gp108/sec2/image.bin"); +MODULE_FIRMWARE("nvidia/gp108/sec2/sig.bin"); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h index d9091f029506cc..959a7b2dbdc92f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/secboot/priv.h @@ -40,6 +40,8 @@ int nvkm_secboot_ctor(const struct nvkm_secboot_func *, struct nvkm_acr *, int nvkm_secboot_falcon_reset(struct nvkm_secboot *); int nvkm_secboot_falcon_run(struct nvkm_secboot *); +extern const struct nvkm_secboot_func gp102_secboot; + struct flcn_u64 { u32 lo; u32 hi; From 27cda223327505a19d912536dff205ccdc5c5c2a Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 12 Jan 2018 17:50:37 +1000 Subject: [PATCH 099/237] drm/nouveau/fbcon: add module parameter to select bits-per-pixel Useful for debugging. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index ee5d1dc2eaf5ac..85c1f10bc2b676 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -56,6 +56,10 @@ MODULE_PARM_DESC(nofbaccel, "Disable fbcon acceleration"); int nouveau_nofbaccel = 0; module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400); +MODULE_PARM_DESC(fbcon_bpp, "fbcon bits-per-pixel (default: auto)"); +static int nouveau_fbcon_bpp; +module_param_named(fbcon_bpp, nouveau_fbcon_bpp, int, 0400); + static void nouveau_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) { @@ -488,7 +492,7 @@ nouveau_fbcon_init(struct drm_device *dev) { struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_fbdev *fbcon; - int preferred_bpp; + int preferred_bpp = nouveau_fbcon_bpp; int ret; if (!dev->mode_config.num_crtc || @@ -512,13 +516,15 @@ nouveau_fbcon_init(struct drm_device *dev) if (ret) goto fini; - if (drm->client.device.info.ram_size <= 32 * 1024 * 1024) - preferred_bpp = 8; - else - if (drm->client.device.info.ram_size <= 64 * 1024 * 1024) - preferred_bpp = 16; - else - preferred_bpp = 32; + if (preferred_bpp != 8 && preferred_bpp != 16 && preferred_bpp != 32) { + if (drm->client.device.info.ram_size <= 32 * 1024 * 1024) + preferred_bpp = 8; + else + if (drm->client.device.info.ram_size <= 64 * 1024 * 1024) + preferred_bpp = 16; + else + preferred_bpp = 32; + } /* disable all the possible outputs/crtcs before entering KMS mode */ if (!drm_drv_uses_atomic_modeset(dev)) From 561464ea543c2f39f07ac2da91043555fa133601 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 12 Jan 2018 17:05:03 +1000 Subject: [PATCH 100/237] drm/nouveau/bo: add helper functions for handling pinned+mapped buffers This is a common, awkward sequence. Let's wrap it up! Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_bo.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index 7b5cc5c73d2089..be8e00b49cdef1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -105,4 +105,32 @@ nvbo_kmap_obj_iovirtual(struct nouveau_bo *nvbo) return ioptr; } +static inline void +nouveau_bo_unmap_unpin_unref(struct nouveau_bo **pnvbo) +{ + if (*pnvbo) { + nouveau_bo_unmap(*pnvbo); + nouveau_bo_unpin(*pnvbo); + nouveau_bo_ref(NULL, pnvbo); + } +} + +static inline int +nouveau_bo_new_pin_map(struct nouveau_cli *cli, u64 size, int align, u32 flags, + struct nouveau_bo **pnvbo) +{ + int ret = nouveau_bo_new(cli, size, align, flags, + 0, 0, NULL, NULL, pnvbo); + if (ret == 0) { + ret = nouveau_bo_pin(*pnvbo, flags, true); + if (ret == 0) { + ret = nouveau_bo_map(*pnvbo); + if (ret == 0) + return ret; + nouveau_bo_unpin(*pnvbo); + } + nouveau_bo_ref(NULL, pnvbo); + } + return ret; +} #endif From 11fc017dfb1efffa93d803f7182d026962ea2aae Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 12 Jan 2018 17:10:49 +1000 Subject: [PATCH 101/237] drm/nouveau/kms/nv50: prepare for double-buffered LUTs We need to double-buffer LUTs to handle their update atomically. Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_crtc.h | 1 - drivers/gpu/drm/nouveau/nv50_display.c | 37 +++++++++++--------------- 2 files changed, 15 insertions(+), 23 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_crtc.h b/drivers/gpu/drm/nouveau/nouveau_crtc.h index b7a18fbee6dc48..366acb928f5771 100644 --- a/drivers/gpu/drm/nouveau/nouveau_crtc.h +++ b/drivers/gpu/drm/nouveau/nouveau_crtc.h @@ -60,7 +60,6 @@ struct nouveau_crtc { } cursor; struct { - struct nouveau_bo *nvbo; int depth; } lut; diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index b22c37bde13ffb..2293b8ff56c676 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -660,6 +660,9 @@ nv50_ovly_create(struct nvif_device *device, struct nvif_object *disp, struct nv50_head { struct nouveau_crtc base; + struct { + struct nouveau_bo *nvbo[1]; + } lut; struct nv50_ovly ovly; struct nv50_oimm oimm; }; @@ -2162,7 +2165,7 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) asyh->core.block = 0; asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4; asyh->lut.handle = disp->mast.base.vram.handle; - asyh->lut.offset = head->base.lut.nvbo->bo.offset; + asyh->lut.offset = head->lut.nvbo[0]->bo.offset; asyh->set.base = armh->base.cpp != asyh->base.cpp; asyh->set.ovly = armh->ovly.cpp != asyh->ovly.cpp; } else { @@ -2204,8 +2207,8 @@ static void nv50_head_lut_load(struct drm_crtc *crtc) { struct nv50_disp *disp = nv50_disp(crtc->dev); - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); - void __iomem *lut = nvbo_kmap_obj_iovirtual(nv_crtc->lut.nvbo); + struct nv50_head *head = nv50_head(crtc); + void __iomem *lut = nvbo_kmap_obj_iovirtual(head->lut.nvbo[0]); u16 *r, *g, *b; int i; @@ -2296,17 +2299,15 @@ nv50_head_reset(struct drm_crtc *crtc) static void nv50_head_destroy(struct drm_crtc *crtc) { - struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nv50_disp *disp = nv50_disp(crtc->dev); struct nv50_head *head = nv50_head(crtc); + int i; nv50_dmac_destroy(&head->ovly.base, disp->disp); nv50_pioc_destroy(&head->oimm.base); - nouveau_bo_unmap(nv_crtc->lut.nvbo); - if (nv_crtc->lut.nvbo) - nouveau_bo_unpin(nv_crtc->lut.nvbo); - nouveau_bo_ref(NULL, &nv_crtc->lut.nvbo); + for (i = 0; i < ARRAY_SIZE(head->lut.nvbo); i++) + nouveau_bo_unmap_unpin_unref(&head->lut.nvbo[i]); drm_crtc_cleanup(crtc); kfree(crtc); @@ -2333,7 +2334,7 @@ nv50_head_create(struct drm_device *dev, int index) struct nv50_base *base; struct nv50_curs *curs; struct drm_crtc *crtc; - int ret; + int ret, i; head = kzalloc(sizeof(*head), GFP_KERNEL); if (!head) @@ -2355,22 +2356,14 @@ nv50_head_create(struct drm_device *dev, int index) drm_crtc_helper_add(crtc, &nv50_head_help); drm_mode_crtc_set_gamma_size(crtc, 256); - ret = nouveau_bo_new(&drm->client, 8192, 0x100, TTM_PL_FLAG_VRAM, - 0, 0x0000, NULL, NULL, &head->base.lut.nvbo); - if (!ret) { - ret = nouveau_bo_pin(head->base.lut.nvbo, TTM_PL_FLAG_VRAM, true); - if (!ret) { - ret = nouveau_bo_map(head->base.lut.nvbo); - if (ret) - nouveau_bo_unpin(head->base.lut.nvbo); - } + for (i = 0; i < ARRAY_SIZE(head->lut.nvbo); i++) { + ret = nouveau_bo_new_pin_map(&drm->client, 1025 * 8, 0x100, + TTM_PL_FLAG_VRAM, + &head->lut.nvbo[i]); if (ret) - nouveau_bo_ref(NULL, &head->base.lut.nvbo); + goto out; } - if (ret) - goto out; - /* allocate overlay resources */ ret = nv50_oimm_create(device, disp->disp, index, &head->oimm); if (ret) From e75182f68b7b3a073e33b89ee4c1688160755930 Mon Sep 17 00:00:00 2001 From: Ilia Mirkin Date: Sat, 30 Dec 2017 23:35:28 -0500 Subject: [PATCH 102/237] drm/nouveau/kms/nv50: use "low res" lut for indexed mode This is what was done prior to the big refactor in kernel 3.8, and what was done by xf86-video-nv. Experimentally, it seems like there's some sort of issue with the high-res lut to be used there. Tested on G92. This ends up mattering because fbcon/fbdev chooses the C8 fb format for low-vram systems, which can occur with some IGP-based configurations with little "stolen" vram. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80675 Signed-off-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 2293b8ff56c676..f4daf8c55de11e 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1805,12 +1805,14 @@ nv50_head_lut_set(struct nv50_head *head, struct nv50_head_atom *asyh) if ((push = evo_wait(core, 7))) { if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2); - evo_data(push, 0xc0000000); + evo_data(push, asyh->base.depth == 8 ? + 0x80000000 : 0xc0000000); evo_data(push, asyh->lut.offset >> 8); } else if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2); - evo_data(push, 0xc0000000); + evo_data(push, asyh->base.depth == 8 ? + 0x80000000 : 0xc0000000); evo_data(push, asyh->lut.offset >> 8); evo_mthd(push, 0x085c + (head->base.index * 0x400), 1); evo_data(push, asyh->lut.handle); From 90df522912ac1fa88836fa1b1b9fa102a48d1f33 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 12 Jan 2018 19:02:05 +1000 Subject: [PATCH 103/237] drm/nouveau/kms/nv50: use INTERPOLATE_257_UNITY_RANGE LUT on newer chipsets For some reason forgotten by history, we've been using a 1025-entry LUT mode, and sparsely filling it with the 256-entry LUT we're handed. Until we land support for the full atomic colour management properties, this commit switches to using the 257-entry mode to fix colour mapping with depth 30 framebuffers. Reported-by: Ilia Mirkin Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index f4daf8c55de11e..973a4126213902 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -1818,7 +1818,7 @@ nv50_head_lut_set(struct nv50_head *head, struct nv50_head_atom *asyh) evo_data(push, asyh->lut.handle); } else { evo_mthd(push, 0x0440 + (head->base.index * 0x300), 4); - evo_data(push, 0x83000000); + evo_data(push, 0x87000000); evo_data(push, asyh->lut.offset >> 8); evo_data(push, 0x00000000); evo_data(push, 0x00000000); @@ -2225,9 +2225,9 @@ nv50_head_lut_load(struct drm_crtc *crtc) writew((*b++ >> 2) + 0x0000, lut + (i * 0x08) + 4); } else { /* 0x6000 interferes with the 14-bit color??? */ - writew((*r++ >> 2) + 0x6000, lut + (i * 0x20) + 0); - writew((*g++ >> 2) + 0x6000, lut + (i * 0x20) + 2); - writew((*b++ >> 2) + 0x6000, lut + (i * 0x20) + 4); + writew((*r++ >> 2) + 0x6000, lut + (i * 0x08) + 0); + writew((*g++ >> 2) + 0x6000, lut + (i * 0x08) + 2); + writew((*b++ >> 2) + 0x6000, lut + (i * 0x08) + 4); } } } From f4778f08a038d48ab8528416a51bf7ad231f9cc1 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 12 Jan 2018 17:05:33 +1000 Subject: [PATCH 104/237] drm/nouveau/kms/nv50: fix handling of gamma since atomic conversion We've still been directly using the legacy crtc gamma_set() hook even after conversion to atomic modesetting. For userspace clients this was fine, however, fbcon will use the atomic property when it's running on an atomic driver, which means we miss its colormap updates - which is particularly bad for 8bpp framebuffers! This commit converts the driver to use the atomic property + the helper function implementing the legacy hook on top of atomic. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=80675 Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nv50_display.c | 162 +++++++++++++++++-------- 1 file changed, 109 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 973a4126213902..dd8d4352ed998e 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c @@ -137,8 +137,10 @@ struct nv50_head_atom { } mode; struct { + bool visible; u32 handle; u64 offset:40; + u8 mode:4; } lut; struct { @@ -192,6 +194,7 @@ struct nv50_head_atom { union { struct { + bool ilut:1; bool core:1; bool curs:1; }; @@ -200,6 +203,7 @@ struct nv50_head_atom { union { struct { + bool ilut:1; bool core:1; bool curs:1; bool view:1; @@ -661,7 +665,8 @@ nv50_ovly_create(struct nvif_device *device, struct nvif_object *disp, struct nv50_head { struct nouveau_crtc base; struct { - struct nouveau_bo *nvbo[1]; + struct nouveau_bo *nvbo[2]; + int next; } lut; struct nv50_ovly ovly; struct nv50_oimm oimm; @@ -1797,6 +1802,54 @@ nv50_head_lut_clr(struct nv50_head *head) } } +static void +nv50_head_lut_load(struct drm_property_blob *blob, int mode, + struct nouveau_bo *nvbo) +{ + struct drm_color_lut *in = (struct drm_color_lut *)blob->data; + void __iomem *lut = (u8 *)nvbo_kmap_obj_iovirtual(nvbo); + const int size = blob->length / sizeof(*in); + int bits, shift, i; + u16 zero, r, g, b; + + /* This can't happen.. But it shuts the compiler up. */ + if (WARN_ON(size != 256)) + return; + + switch (mode) { + case 0: /* LORES. */ + case 1: /* HIRES. */ + bits = 11; + shift = 3; + zero = 0x0000; + break; + case 7: /* INTERPOLATE_257_UNITY_RANGE. */ + bits = 14; + shift = 0; + zero = 0x6000; + break; + default: + WARN_ON(1); + return; + } + + for (i = 0; i < size; i++) { + r = (drm_color_lut_extract(in[i]. red, bits) + zero) << shift; + g = (drm_color_lut_extract(in[i].green, bits) + zero) << shift; + b = (drm_color_lut_extract(in[i]. blue, bits) + zero) << shift; + writew(r, lut + (i * 0x08) + 0); + writew(g, lut + (i * 0x08) + 2); + writew(b, lut + (i * 0x08) + 4); + } + + /* INTERPOLATE modes require a "next" entry to interpolate with, + * so we replicate the last entry to deal with this for now. + */ + writew(r, lut + (i * 0x08) + 0); + writew(g, lut + (i * 0x08) + 2); + writew(b, lut + (i * 0x08) + 4); +} + static void nv50_head_lut_set(struct nv50_head *head, struct nv50_head_atom *asyh) { @@ -1805,20 +1858,18 @@ nv50_head_lut_set(struct nv50_head *head, struct nv50_head_atom *asyh) if ((push = evo_wait(core, 7))) { if (core->base.user.oclass < G82_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2); - evo_data(push, asyh->base.depth == 8 ? - 0x80000000 : 0xc0000000); + evo_data(push, 0x80000000 | asyh->lut.mode << 30); evo_data(push, asyh->lut.offset >> 8); } else if (core->base.user.oclass < GF110_DISP_CORE_CHANNEL_DMA) { evo_mthd(push, 0x0840 + (head->base.index * 0x400), 2); - evo_data(push, asyh->base.depth == 8 ? - 0x80000000 : 0xc0000000); + evo_data(push, 0x80000000 | asyh->lut.mode << 30); evo_data(push, asyh->lut.offset >> 8); evo_mthd(push, 0x085c + (head->base.index * 0x400), 1); evo_data(push, asyh->lut.handle); } else { evo_mthd(push, 0x0440 + (head->base.index * 0x300), 4); - evo_data(push, 0x87000000); + evo_data(push, 0x80000000 | asyh->lut.mode << 24); evo_data(push, asyh->lut.offset >> 8); evo_data(push, 0x00000000); evo_data(push, 0x00000000); @@ -1901,7 +1952,7 @@ nv50_head_view(struct nv50_head *head, struct nv50_head_atom *asyh) static void nv50_head_flush_clr(struct nv50_head *head, struct nv50_head_atom *asyh, bool y) { - if (asyh->clr.core && (!asyh->set.core || y)) + if (asyh->clr.ilut && (!asyh->set.ilut || y)) nv50_head_lut_clr(head); if (asyh->clr.core && (!asyh->set.core || y)) nv50_head_core_clr(head); @@ -1914,7 +1965,15 @@ nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh) { if (asyh->set.view ) nv50_head_view (head, asyh); if (asyh->set.mode ) nv50_head_mode (head, asyh); - if (asyh->set.core ) nv50_head_lut_set (head, asyh); + if (asyh->set.ilut ) { + struct nouveau_bo *nvbo = head->lut.nvbo[head->lut.next]; + struct drm_property_blob *blob = asyh->state.gamma_lut; + if (blob) + nv50_head_lut_load(blob, asyh->lut.mode, nvbo); + asyh->lut.offset = nvbo->bo.offset; + head->lut.next ^= 1; + nv50_head_lut_set(head, asyh); + } if (asyh->set.core ) nv50_head_core_set(head, asyh); if (asyh->set.curs ) nv50_head_curs_set(head, asyh); if (asyh->set.base ) nv50_head_base (head, asyh); @@ -2048,6 +2107,37 @@ nv50_head_atomic_check_view(struct nv50_head_atom *armh, asyh->set.view = true; } +static void +nv50_head_atomic_check_lut(struct nv50_head *head, + struct nv50_head_atom *armh, + struct nv50_head_atom *asyh) +{ + struct nv50_disp *disp = nv50_disp(head->base.base.dev); + + /* An I8 surface without an input LUT makes no sense, and + * EVO will throw an error if you try. + * + * Legacy clients actually cause this due to the order in + * which they call ioctls, so we will enable the LUT with + * whatever contents the buffer already contains to avoid + * triggering the error check. + */ + if (!asyh->state.gamma_lut && asyh->base.cpp != 1) { + asyh->lut.handle = 0; + asyh->clr.ilut = armh->lut.visible; + return; + } + + if (disp->disp->oclass < GF110_DISP) { + asyh->lut.mode = (asyh->base.cpp == 1) ? 0 : 1; + asyh->set.ilut = true; + } else { + asyh->lut.mode = 7; + asyh->set.ilut = asyh->state.color_mgmt_changed; + } + asyh->lut.handle = disp->mast.base.vram.handle; +} + static void nv50_head_atomic_check_mode(struct nv50_head *head, struct nv50_head_atom *asyh) { @@ -2133,6 +2223,11 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) if (asyh->state.mode_changed) nv50_head_atomic_check_mode(head, asyh); + if (asyh->state.color_mgmt_changed || + asyh->base.cpp != armh->base.cpp) + nv50_head_atomic_check_lut(head, armh, asyh); + asyh->lut.visible = asyh->lut.handle != 0; + if (asyc) { if (asyc->set.scaler) nv50_head_atomic_check_view(armh, asyh, asyc); @@ -2148,7 +2243,8 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) asyh->core.w = asyh->base.w; asyh->core.h = asyh->base.h; } else - if ((asyh->core.visible = asyh->curs.visible)) { + if ((asyh->core.visible = asyh->curs.visible) || + (asyh->core.visible = asyh->lut.visible)) { /*XXX: We need to either find some way of having the * primary base layer appear black, while still * being able to display the other layers, or we @@ -2166,11 +2262,10 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) asyh->core.layout = 1; asyh->core.block = 0; asyh->core.pitch = ALIGN(asyh->core.w, 64) * 4; - asyh->lut.handle = disp->mast.base.vram.handle; - asyh->lut.offset = head->lut.nvbo[0]->bo.offset; asyh->set.base = armh->base.cpp != asyh->base.cpp; asyh->set.ovly = armh->ovly.cpp != asyh->ovly.cpp; } else { + asyh->lut.visible = false; asyh->core.visible = false; asyh->curs.visible = false; asyh->base.cpp = 0; @@ -2194,8 +2289,10 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) asyh->clr.curs = true; } } else { + asyh->clr.ilut = armh->lut.visible; asyh->clr.core = armh->core.visible; asyh->clr.curs = armh->curs.visible; + asyh->set.ilut = asyh->lut.visible; asyh->set.core = asyh->core.visible; asyh->set.curs = asyh->curs.visible; } @@ -2205,47 +2302,11 @@ nv50_head_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) return 0; } -static void -nv50_head_lut_load(struct drm_crtc *crtc) -{ - struct nv50_disp *disp = nv50_disp(crtc->dev); - struct nv50_head *head = nv50_head(crtc); - void __iomem *lut = nvbo_kmap_obj_iovirtual(head->lut.nvbo[0]); - u16 *r, *g, *b; - int i; - - r = crtc->gamma_store; - g = r + crtc->gamma_size; - b = g + crtc->gamma_size; - - for (i = 0; i < 256; i++) { - if (disp->disp->oclass < GF110_DISP) { - writew((*r++ >> 2) + 0x0000, lut + (i * 0x08) + 0); - writew((*g++ >> 2) + 0x0000, lut + (i * 0x08) + 2); - writew((*b++ >> 2) + 0x0000, lut + (i * 0x08) + 4); - } else { - /* 0x6000 interferes with the 14-bit color??? */ - writew((*r++ >> 2) + 0x6000, lut + (i * 0x08) + 0); - writew((*g++ >> 2) + 0x6000, lut + (i * 0x08) + 2); - writew((*b++ >> 2) + 0x6000, lut + (i * 0x08) + 4); - } - } -} - static const struct drm_crtc_helper_funcs nv50_head_help = { .atomic_check = nv50_head_atomic_check, }; -static int -nv50_head_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, - uint32_t size, - struct drm_modeset_acquire_ctx *ctx) -{ - nv50_head_lut_load(crtc); - return 0; -} - static void nv50_head_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_state *state) @@ -2318,7 +2379,7 @@ nv50_head_destroy(struct drm_crtc *crtc) static const struct drm_crtc_funcs nv50_head_func = { .reset = nv50_head_reset, - .gamma_set = nv50_head_gamma_set, + .gamma_set = drm_atomic_helper_legacy_gamma_set, .destroy = nv50_head_destroy, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, @@ -4345,7 +4406,6 @@ nv50_display_init(struct drm_device *dev) { struct drm_encoder *encoder; struct drm_plane *plane; - struct drm_crtc *crtc; u32 *push; push = evo_wait(nv50_mast(dev), 32); @@ -4364,10 +4424,6 @@ nv50_display_init(struct drm_device *dev) } } - drm_for_each_crtc(crtc, dev) { - nv50_head_lut_load(crtc); - } - drm_for_each_plane(plane, dev) { struct nv50_wndw *wndw = nv50_wndw(plane); if (plane->funcs != &nv50_wndw) From b138eca661ccee2b43f8ef3cfd952a5c71c1dc90 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 1 Feb 2018 13:13:55 -0500 Subject: [PATCH 105/237] drm/nouveau: Add support for basic clockgating on Kepler1 This adds support for enabling automatic clockgating on nvidia GPUs for Kepler1. While this is not technically a clockgating level, it does enable clockgating using the clockgating values initially set by the vbios (which should be safe to use). This introduces two therm helpers for controlling basic clockgating: nvkm_therm_clkgate_enable() - enables clockgating through CG_CTRL, done after initializing the GPU fully nvkm_therm_clkgate_fini() - prepares clockgating for suspend or driver unload A lot of this code was originally going to be based off of fermi; however it turns out that while Fermi's the first line of GPUs that introduced this kind of power saving, Fermi requires more fine tuned control of the CG_CTRL registers from the driver while reclocking that we don't entirely understand yet. For the simple parts we will be sharing with Fermi for certain however, we at least add those into a new subdev/therm/gf100.h header. Signed-off-by: Lyude Paul Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- .../drm/nouveau/include/nvkm/subdev/therm.h | 5 + .../gpu/drm/nouveau/nvkm/engine/device/base.c | 17 ++- .../gpu/drm/nouveau/nvkm/subdev/therm/Kbuild | 1 + .../gpu/drm/nouveau/nvkm/subdev/therm/base.c | 58 ++++++-- .../gpu/drm/nouveau/nvkm/subdev/therm/gf100.h | 35 +++++ .../gpu/drm/nouveau/nvkm/subdev/therm/gf119.c | 8 +- .../gpu/drm/nouveau/nvkm/subdev/therm/gk104.c | 135 ++++++++++++++++++ .../gpu/drm/nouveau/nvkm/subdev/therm/gk104.h | 48 +++++++ .../gpu/drm/nouveau/nvkm/subdev/therm/priv.h | 15 +- 9 files changed, 301 insertions(+), 21 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.h diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h index b1ac47eb786e7a..240b19bb466799 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h @@ -85,17 +85,22 @@ struct nvkm_therm { int (*attr_get)(struct nvkm_therm *, enum nvkm_therm_attr_type); int (*attr_set)(struct nvkm_therm *, enum nvkm_therm_attr_type, int); + + bool clkgating_enabled; }; int nvkm_therm_temp_get(struct nvkm_therm *); int nvkm_therm_fan_sense(struct nvkm_therm *); int nvkm_therm_cstate(struct nvkm_therm *, int, int); +void nvkm_therm_clkgate_enable(struct nvkm_therm *); +void nvkm_therm_clkgate_fini(struct nvkm_therm *, bool); int nv40_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int nv50_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int g84_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int gt215_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int gf119_therm_new(struct nvkm_device *, int, struct nvkm_therm **); +int gk104_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int gm107_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int gm200_therm_new(struct nvkm_device *, int, struct nvkm_therm **); int gp100_therm_new(struct nvkm_device *, int, struct nvkm_therm **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index a4a5ffce03d0ae..eab529dceb7301 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -28,6 +28,7 @@ #include #include +#include static DEFINE_MUTEX(nv_devices_mutex); static LIST_HEAD(nv_devices); @@ -1682,7 +1683,7 @@ nve4_chipset = { .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk104_pmu_new, - .therm = gf119_therm_new, + .therm = gk104_therm_new, .timer = nv41_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -1721,7 +1722,7 @@ nve6_chipset = { .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk104_pmu_new, - .therm = gf119_therm_new, + .therm = gk104_therm_new, .timer = nv41_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -1760,7 +1761,7 @@ nve7_chipset = { .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk104_pmu_new, - .therm = gf119_therm_new, + .therm = gk104_therm_new, .timer = nv41_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -1824,7 +1825,7 @@ nvf0_chipset = { .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk110_pmu_new, - .therm = gf119_therm_new, + .therm = gk104_therm_new, .timer = nv41_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -1862,7 +1863,7 @@ nvf1_chipset = { .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk110_pmu_new, - .therm = gf119_therm_new, + .therm = gk104_therm_new, .timer = nv41_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -1900,7 +1901,7 @@ nv106_chipset = { .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk208_pmu_new, - .therm = gf119_therm_new, + .therm = gk104_therm_new, .timer = nv41_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -1938,7 +1939,7 @@ nv108_chipset = { .mxm = nv50_mxm_new, .pci = gk104_pci_new, .pmu = gk208_pmu_new, - .therm = gf119_therm_new, + .therm = gk104_therm_new, .timer = nv41_timer_new, .top = gk104_top_new, .volt = gk104_volt_new, @@ -2513,6 +2514,7 @@ nvkm_device_fini(struct nvkm_device *device, bool suspend) } } + nvkm_therm_clkgate_fini(device->therm, suspend); if (device->func->fini) device->func->fini(device, suspend); @@ -2602,6 +2604,7 @@ nvkm_device_init(struct nvkm_device *device) } nvkm_acpi_init(device); + nvkm_therm_clkgate_enable(device->therm); time = ktime_to_us(ktime_get()) - time; nvdev_trace(device, "init completed in %lldus\n", time); diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild index 7ba56b12badd8d..4bac4772d8ed8b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild @@ -10,6 +10,7 @@ nvkm-y += nvkm/subdev/therm/nv50.o nvkm-y += nvkm/subdev/therm/g84.o nvkm-y += nvkm/subdev/therm/gt215.o nvkm-y += nvkm/subdev/therm/gf119.o +nvkm-y += nvkm/subdev/therm/gk104.o nvkm-y += nvkm/subdev/therm/gm107.o nvkm-y += nvkm/subdev/therm/gm200.o nvkm-y += nvkm/subdev/therm/gp100.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index f27fc6d0d4c65f..cf1d5af30f5f0f 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -21,6 +21,7 @@ * * Authors: Martin Peres */ +#include #include "priv.h" int @@ -297,6 +298,38 @@ nvkm_therm_attr_set(struct nvkm_therm *therm, return -EINVAL; } +void +nvkm_therm_clkgate_enable(struct nvkm_therm *therm) +{ + if (!therm->func->clkgate_enable || !therm->clkgating_enabled) + return; + + nvkm_debug(&therm->subdev, + "Enabling clockgating\n"); + therm->func->clkgate_enable(therm); +} + +void +nvkm_therm_clkgate_fini(struct nvkm_therm *therm, bool suspend) +{ + if (!therm->func->clkgate_fini || !therm->clkgating_enabled) + return; + + nvkm_debug(&therm->subdev, + "Preparing clockgating for %s\n", + suspend ? "suspend" : "fini"); + therm->func->clkgate_fini(therm, suspend); +} + +static void +nvkm_therm_clkgate_oneinit(struct nvkm_therm *therm) +{ + if (!therm->func->clkgate_enable || !therm->clkgating_enabled) + return; + + nvkm_info(&therm->subdev, "Clockgating enabled\n"); +} + static void nvkm_therm_intr(struct nvkm_subdev *subdev) { @@ -333,6 +366,7 @@ nvkm_therm_oneinit(struct nvkm_subdev *subdev) nvkm_therm_fan_ctor(therm); nvkm_therm_fan_mode(therm, NVKM_THERM_CTRL_AUTO); nvkm_therm_sensor_preinit(therm); + nvkm_therm_clkgate_oneinit(therm); return 0; } @@ -374,15 +408,10 @@ nvkm_therm = { .intr = nvkm_therm_intr, }; -int -nvkm_therm_new_(const struct nvkm_therm_func *func, struct nvkm_device *device, - int index, struct nvkm_therm **ptherm) +void +nvkm_therm_ctor(struct nvkm_therm *therm, struct nvkm_device *device, + int index, const struct nvkm_therm_func *func) { - struct nvkm_therm *therm; - - if (!(therm = *ptherm = kzalloc(sizeof(*therm), GFP_KERNEL))) - return -ENOMEM; - nvkm_subdev_ctor(&nvkm_therm, device, index, &therm->subdev); therm->func = func; @@ -395,5 +424,18 @@ nvkm_therm_new_(const struct nvkm_therm_func *func, struct nvkm_device *device, therm->attr_get = nvkm_therm_attr_get; therm->attr_set = nvkm_therm_attr_set; therm->mode = therm->suspend = -1; /* undefined */ + therm->clkgating_enabled = false; +} + +int +nvkm_therm_new_(const struct nvkm_therm_func *func, struct nvkm_device *device, + int index, struct nvkm_therm **ptherm) +{ + struct nvkm_therm *therm; + + if (!(therm = *ptherm = kzalloc(sizeof(*therm), GFP_KERNEL))) + return -ENOMEM; + + nvkm_therm_ctor(therm, device, index, func); return 0; } diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.h b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.h new file mode 100644 index 00000000000000..cfb25af77c60d3 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Lyude Paul + */ + +#ifndef __GF100_THERM_H__ +#define __GF100_THERM_H__ + +#include + +struct gf100_idle_filter { + u32 fecs; + u32 hubmmu; +}; + +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c index 06dcfd6ee96645..0981b02790e2bd 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf119.c @@ -49,7 +49,7 @@ pwm_info(struct nvkm_therm *therm, int line) return -ENODEV; } -static int +int gf119_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable) { struct nvkm_device *device = therm->subdev.device; @@ -63,7 +63,7 @@ gf119_fan_pwm_ctrl(struct nvkm_therm *therm, int line, bool enable) return 0; } -static int +int gf119_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) { struct nvkm_device *device = therm->subdev.device; @@ -85,7 +85,7 @@ gf119_fan_pwm_get(struct nvkm_therm *therm, int line, u32 *divs, u32 *duty) return -EINVAL; } -static int +int gf119_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty) { struct nvkm_device *device = therm->subdev.device; @@ -102,7 +102,7 @@ gf119_fan_pwm_set(struct nvkm_therm *therm, int line, u32 divs, u32 duty) return 0; } -static int +int gf119_fan_pwm_clock(struct nvkm_therm *therm, int line) { struct nvkm_device *device = therm->subdev.device; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c new file mode 100644 index 00000000000000..79806a7578931f --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c @@ -0,0 +1,135 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Lyude Paul + */ +#include + +#include "priv.h" +#include "gk104.h" + +void +gk104_clkgate_enable(struct nvkm_therm *base) +{ + struct gk104_therm *therm = gk104_therm(base); + struct nvkm_device *dev = therm->base.subdev.device; + const struct gk104_clkgate_engine_info *order = therm->clkgate_order; + int i; + + /* Program ENG_MANT, ENG_FILTER */ + for (i = 0; order[i].engine != NVKM_SUBDEV_NR; i++) { + if (!nvkm_device_subdev(dev, order[i].engine)) + continue; + + nvkm_mask(dev, 0x20200 + order[i].offset, 0xff00, 0x4500); + } + + /* magic */ + nvkm_wr32(dev, 0x020288, therm->idle_filter->fecs); + nvkm_wr32(dev, 0x02028c, therm->idle_filter->hubmmu); + + /* Enable clockgating (ENG_CLK = RUN->AUTO) */ + for (i = 0; order[i].engine != NVKM_SUBDEV_NR; i++) { + if (!nvkm_device_subdev(dev, order[i].engine)) + continue; + + nvkm_mask(dev, 0x20200 + order[i].offset, 0x00ff, 0x0045); + } +} + +void +gk104_clkgate_fini(struct nvkm_therm *base, bool suspend) +{ + struct gk104_therm *therm = gk104_therm(base); + struct nvkm_device *dev = therm->base.subdev.device; + const struct gk104_clkgate_engine_info *order = therm->clkgate_order; + int i; + + /* ENG_CLK = AUTO->RUN, ENG_PWR = RUN->AUTO */ + for (i = 0; order[i].engine != NVKM_SUBDEV_NR; i++) { + if (!nvkm_device_subdev(dev, order[i].engine)) + continue; + + nvkm_mask(dev, 0x20200 + order[i].offset, 0xff, 0x54); + } +} + +const struct gk104_clkgate_engine_info gk104_clkgate_engine_info[] = { + { NVKM_ENGINE_GR, 0x00 }, + { NVKM_ENGINE_MSPDEC, 0x04 }, + { NVKM_ENGINE_MSPPP, 0x08 }, + { NVKM_ENGINE_MSVLD, 0x0c }, + { NVKM_ENGINE_CE0, 0x10 }, + { NVKM_ENGINE_CE1, 0x14 }, + { NVKM_ENGINE_MSENC, 0x18 }, + { NVKM_ENGINE_CE2, 0x1c }, + { NVKM_SUBDEV_NR, 0 }, +}; + +const struct gf100_idle_filter gk104_idle_filter = { + .fecs = 0x00001000, + .hubmmu = 0x00001000, +}; + +static const struct nvkm_therm_func +gk104_therm_func = { + .init = gf119_therm_init, + .fini = g84_therm_fini, + .pwm_ctrl = gf119_fan_pwm_ctrl, + .pwm_get = gf119_fan_pwm_get, + .pwm_set = gf119_fan_pwm_set, + .pwm_clock = gf119_fan_pwm_clock, + .temp_get = g84_temp_get, + .fan_sense = gt215_therm_fan_sense, + .program_alarms = nvkm_therm_program_alarms_polling, + .clkgate_enable = gk104_clkgate_enable, + .clkgate_fini = gk104_clkgate_fini, +}; + +static int +gk104_therm_new_(const struct nvkm_therm_func *func, + struct nvkm_device *device, + int index, + const struct gk104_clkgate_engine_info *clkgate_order, + const struct gf100_idle_filter *idle_filter, + struct nvkm_therm **ptherm) +{ + struct gk104_therm *therm = kzalloc(sizeof(*therm), GFP_KERNEL); + + if (!therm) + return -ENOMEM; + + nvkm_therm_ctor(&therm->base, device, index, func); + *ptherm = &therm->base; + therm->clkgate_order = clkgate_order; + therm->idle_filter = idle_filter; + + return 0; +} + +int +gk104_therm_new(struct nvkm_device *device, + int index, struct nvkm_therm **ptherm) +{ + return gk104_therm_new_(&gk104_therm_func, device, index, + gk104_clkgate_engine_info, &gk104_idle_filter, + ptherm); +} diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.h b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.h new file mode 100644 index 00000000000000..293e7743b19bb2 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.h @@ -0,0 +1,48 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Lyude Paul + */ + +#ifndef __GK104_THERM_H__ +#define __GK104_THERM_H__ +#define gk104_therm(p) (container_of((p), struct gk104_therm, base)) + +#include +#include "priv.h" +#include "gf100.h" + +struct gk104_clkgate_engine_info { + enum nvkm_devidx engine; + u8 offset; +}; + +struct gk104_therm { + struct nvkm_therm base; + + const struct gk104_clkgate_engine_info *clkgate_order; + const struct gf100_idle_filter *idle_filter; +}; + +extern const struct gk104_clkgate_engine_info gk104_clkgate_engine_info[]; +extern const struct gf100_idle_filter gk104_idle_filter; + +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h index 1f46e371d7c480..f30202dd88e702 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h @@ -32,6 +32,8 @@ int nvkm_therm_new_(const struct nvkm_therm_func *, struct nvkm_device *, int index, struct nvkm_therm **); +void nvkm_therm_ctor(struct nvkm_therm *therm, struct nvkm_device *device, + int index, const struct nvkm_therm_func *func); struct nvkm_fan { struct nvkm_therm *parent; @@ -66,8 +68,6 @@ int nvkm_therm_fan_set(struct nvkm_therm *, bool now, int percent); int nvkm_therm_fan_user_get(struct nvkm_therm *); int nvkm_therm_fan_user_set(struct nvkm_therm *, int percent); -int nvkm_therm_preinit(struct nvkm_therm *); - int nvkm_therm_sensor_init(struct nvkm_therm *); int nvkm_therm_sensor_fini(struct nvkm_therm *, bool suspend); void nvkm_therm_sensor_preinit(struct nvkm_therm *); @@ -96,6 +96,9 @@ struct nvkm_therm_func { int (*fan_sense)(struct nvkm_therm *); void (*program_alarms)(struct nvkm_therm *); + + void (*clkgate_enable)(struct nvkm_therm *); + void (*clkgate_fini)(struct nvkm_therm *, bool); }; void nv40_therm_intr(struct nvkm_therm *); @@ -112,8 +115,16 @@ void g84_therm_fini(struct nvkm_therm *); int gt215_therm_fan_sense(struct nvkm_therm *); void g84_therm_init(struct nvkm_therm *); + +int gf119_fan_pwm_ctrl(struct nvkm_therm *, int, bool); +int gf119_fan_pwm_get(struct nvkm_therm *, int, u32 *, u32 *); +int gf119_fan_pwm_set(struct nvkm_therm *, int, u32, u32); +int gf119_fan_pwm_clock(struct nvkm_therm *, int); void gf119_therm_init(struct nvkm_therm *); +void gk104_clkgate_enable(struct nvkm_therm *); +void gk104_clkgate_fini(struct nvkm_therm *, bool); + int nvkm_fanpwm_create(struct nvkm_therm *, struct dcb_gpio_func *); int nvkm_fantog_create(struct nvkm_therm *, struct dcb_gpio_func *); int nvkm_fannil_create(struct nvkm_therm *); From 1bab09acc9b165c5cd87dc46bc983372e103ae5d Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 1 Feb 2018 13:13:56 -0500 Subject: [PATCH 106/237] drm/nouveau: Add support for BLCG on Kepler1 This enables BLCG optimization for kepler1. When using clockgating, nvidia's firmware has a set of registers which are initially programmed by the vbios with various engine delays and other mysterious settings that are safe enough to bring up the GPU. However, the values used by the vbios are more power hungry then they need to be, so the nvidia driver writes it's own more optimized set of BLCG settings before enabling CG_CTRL. This adds support for programming the optimized BLCG values during engine/subdev init, which enables rather significant power savings. This introduces the nvkm_therm_clkgate_init() helper, which we use to program the optimized BLCG settings before enabling clockgating with nvkm_therm_clkgate_enable. As well, this commit shares a lot more code with Fermi since BLCG is mostly the same there as far as we can tell. In the future, it's likely we'll reformat the clkgate_packs for kepler1 so that they share a list of mmio packs with Fermi. Signed-off-by: Lyude Paul Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- .../drm/nouveau/include/nvkm/subdev/therm.h | 12 + .../gpu/drm/nouveau/nvkm/engine/gr/gf100.h | 1 + .../gpu/drm/nouveau/nvkm/engine/gr/gk104.c | 207 ++++++++++++++++++ .../gpu/drm/nouveau/nvkm/engine/gr/gk104.h | 55 +++++ .../gpu/drm/nouveau/nvkm/subdev/fb/gf100.c | 6 + .../gpu/drm/nouveau/nvkm/subdev/fb/gk104.c | 47 ++++ .../gpu/drm/nouveau/nvkm/subdev/fb/gk104.h | 35 +++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h | 2 + .../gpu/drm/nouveau/nvkm/subdev/therm/Kbuild | 1 + .../gpu/drm/nouveau/nvkm/subdev/therm/base.c | 10 + .../gpu/drm/nouveau/nvkm/subdev/therm/gf100.c | 58 +++++ .../gpu/drm/nouveau/nvkm/subdev/therm/gk104.c | 1 + .../gpu/drm/nouveau/nvkm/subdev/therm/gt215.c | 2 +- .../gpu/drm/nouveau/nvkm/subdev/therm/priv.h | 6 + 14 files changed, 442 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h index 240b19bb466799..9398d9f093398b 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/therm.h @@ -46,6 +46,16 @@ enum nvkm_therm_attr_type { NVKM_THERM_ATTR_THRS_SHUTDOWN_HYST = 17, }; +struct nvkm_therm_clkgate_init { + u32 addr; + u8 count; + u32 data; +}; + +struct nvkm_therm_clkgate_pack { + const struct nvkm_therm_clkgate_init *init; +}; + struct nvkm_therm { const struct nvkm_therm_func *func; struct nvkm_subdev subdev; @@ -92,6 +102,8 @@ struct nvkm_therm { int nvkm_therm_temp_get(struct nvkm_therm *); int nvkm_therm_fan_sense(struct nvkm_therm *); int nvkm_therm_cstate(struct nvkm_therm *, int, int); +void nvkm_therm_clkgate_init(struct nvkm_therm *, + const struct nvkm_therm_clkgate_pack *); void nvkm_therm_clkgate_enable(struct nvkm_therm *); void nvkm_therm_clkgate_fini(struct nvkm_therm *, bool); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h index d7c2adb9b543ce..c8ec3fd9715591 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gf100.h @@ -137,6 +137,7 @@ struct gf100_gr_func { int (*rops)(struct gf100_gr *); int ppc_nr; const struct gf100_grctx_func *grctx; + const struct nvkm_therm_clkgate_pack *clkgate_pack; struct nvkm_sclass sclass[]; }; diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c index 5e82f94c224514..1b52fcb2c49a20 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "gf100.h" +#include "gk104.h" #include "ctxgf100.h" #include @@ -173,6 +174,208 @@ gk104_gr_pack_mmio[] = { {} }; +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_main_0[] = { + { 0x4041f0, 1, 0x00004046 }, + { 0x409890, 1, 0x00000045 }, + { 0x4098b0, 1, 0x0000007f }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_rstr2d_0[] = { + { 0x4078c0, 1, 0x00000042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_unk_0[] = { + { 0x406000, 1, 0x00004044 }, + { 0x405860, 1, 0x00004042 }, + { 0x40590c, 1, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gcc_0[] = { + { 0x408040, 1, 0x00004044 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_sked_0[] = { + { 0x407000, 1, 0x00004044 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_unk_1[] = { + { 0x405bf0, 1, 0x00004044 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_ctxctl_0[] = { + { 0x41a890, 1, 0x00000042 }, + { 0x41a8b0, 1, 0x0000007f }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_unk_0[] = { + { 0x418500, 1, 0x00004042 }, + { 0x418608, 1, 0x00004042 }, + { 0x418688, 1, 0x00004042 }, + { 0x418718, 1, 0x00000042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_esetup_0[] = { + { 0x418828, 1, 0x00000044 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_tpbus_0[] = { + { 0x418bbc, 1, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_zcull_0[] = { + { 0x418970, 1, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_tpconf_0[] = { + { 0x418c70, 1, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_unk_1[] = { + { 0x418cf0, 1, 0x00004042 }, + { 0x418d70, 1, 0x00004042 }, + { 0x418f0c, 1, 0x00004042 }, + { 0x418e0c, 1, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_gcc_0[] = { + { 0x419020, 1, 0x00004042 }, + { 0x419038, 1, 0x00000042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_ffb_0[] = { + { 0x418898, 1, 0x00000042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_tex_0[] = { + { 0x419a40, 9, 0x00004042 }, + { 0x419acc, 1, 0x00004047 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_poly_0[] = { + { 0x419868, 1, 0x00000042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_l1c_0[] = { + { 0x419ccc, 3, 0x00000042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_unk_2[] = { + { 0x419c70, 1, 0x00004045 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_mp_0[] = { + { 0x419fd0, 1, 0x00004043 }, + { 0x419fd8, 1, 0x00004049 }, + { 0x419fe0, 2, 0x00004042 }, + { 0x419ff0, 1, 0x00004046 }, + { 0x419ff8, 1, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_gpc_ppc_0[] = { + { 0x41be28, 1, 0x00000042 }, + { 0x41bfe8, 1, 0x00004042 }, + { 0x41bed0, 1, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_rop_zrop_0[] = { + { 0x408810, 2, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_rop_0[] = { + { 0x408a80, 6, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_rop_crop_0[] = { + { 0x4089a8, 1, 0x00004042 }, + { 0x4089b0, 1, 0x00000042 }, + { 0x4089b8, 1, 0x00004042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_clkgate_blcg_init_pxbar_0[] = { + { 0x13c820, 1, 0x0001007f }, + { 0x13cbe0, 1, 0x00000042 }, + {} +}; + +static const struct nvkm_therm_clkgate_pack +gk104_clkgate_pack[] = { + { gk104_clkgate_blcg_init_main_0 }, + { gk104_clkgate_blcg_init_rstr2d_0 }, + { gk104_clkgate_blcg_init_unk_0 }, + { gk104_clkgate_blcg_init_gcc_0 }, + { gk104_clkgate_blcg_init_sked_0 }, + { gk104_clkgate_blcg_init_unk_1 }, + { gk104_clkgate_blcg_init_gpc_ctxctl_0 }, + { gk104_clkgate_blcg_init_gpc_unk_0 }, + { gk104_clkgate_blcg_init_gpc_esetup_0 }, + { gk104_clkgate_blcg_init_gpc_tpbus_0 }, + { gk104_clkgate_blcg_init_gpc_zcull_0 }, + { gk104_clkgate_blcg_init_gpc_tpconf_0 }, + { gk104_clkgate_blcg_init_gpc_unk_1 }, + { gk104_clkgate_blcg_init_gpc_gcc_0 }, + { gk104_clkgate_blcg_init_gpc_ffb_0 }, + { gk104_clkgate_blcg_init_gpc_tex_0 }, + { gk104_clkgate_blcg_init_gpc_poly_0 }, + { gk104_clkgate_blcg_init_gpc_l1c_0 }, + { gk104_clkgate_blcg_init_gpc_unk_2 }, + { gk104_clkgate_blcg_init_gpc_mp_0 }, + { gk104_clkgate_blcg_init_gpc_ppc_0 }, + { gk104_clkgate_blcg_init_rop_zrop_0 }, + { gk104_clkgate_blcg_init_rop_0 }, + { gk104_clkgate_blcg_init_rop_crop_0 }, + { gk104_clkgate_blcg_init_pxbar_0 }, + {} +}; + /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ @@ -214,6 +417,9 @@ gk104_gr_init(struct gf100_gr *gr) gr->func->init_gpc_mmu(gr); gf100_gr_mmio(gr, gr->func->mmio); + if (gr->func->clkgate_pack) + nvkm_therm_clkgate_init(gr->base.engine.subdev.device->therm, + gr->func->clkgate_pack); nvkm_wr32(device, GPC_UNIT(0, 0x3018), 0x00000001); @@ -338,6 +544,7 @@ gk104_gr = { .rops = gf100_gr_rops, .ppc_nr = 1, .grctx = &gk104_grctx, + .clkgate_pack = gk104_clkgate_pack, .sclass = { { -1, -1, FERMI_TWOD_A }, { -1, -1, KEPLER_INLINE_TO_MEMORY_A }, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h new file mode 100644 index 00000000000000..a24c177365d182 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk104.h @@ -0,0 +1,55 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Lyude Paul + */ +#ifndef __GK104_GR_H__ +#define __GK104_GR_H__ + +#include + +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_main_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rstr2d_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_unk_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gcc_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_sked_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_unk_1[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_ctxctl_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_unk_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_esetup_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_tpbus_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_zcull_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_tpconf_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_unk_1[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_gcc_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_ffb_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_tex_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_poly_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_l1c_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_unk_2[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_mp_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_gpc_ppc_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rop_zrop_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rop_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_rop_crop_0[]; +extern const struct nvkm_therm_clkgate_init gk104_clkgate_blcg_init_pxbar_0[]; + +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c index 47d28c27970789..cdc4e0a2cc6bf1 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gf100.c @@ -26,6 +26,7 @@ #include #include +#include void gf100_fb_intr(struct nvkm_fb *base) @@ -92,6 +93,11 @@ gf100_fb_init(struct nvkm_fb *base) if (fb->r100c10_page) nvkm_wr32(device, 0x100c10, fb->r100c10 >> 8); + + if (base->func->clkgate_pack) { + nvkm_therm_clkgate_init(device->therm, + base->func->clkgate_pack); + } } void * diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c index 0a6e8eaad42ca3..48fd98e08baae3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.c @@ -20,10 +20,56 @@ * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Ben Skeggs + * Lyude Paul */ +#include "gk104.h" #include "gf100.h" #include "ram.h" +/* + ******************************************************************************* + * PGRAPH registers for clockgating + ******************************************************************************* + */ +const struct nvkm_therm_clkgate_init +gk104_fb_clkgate_blcg_init_unk_0[] = { + { 0x100d10, 1, 0x0000c244 }, + { 0x100d30, 1, 0x0000c242 }, + { 0x100d3c, 1, 0x00000242 }, + { 0x100d48, 1, 0x00000242 }, + { 0x100d1c, 1, 0x00000042 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_fb_clkgate_blcg_init_vm_0[] = { + { 0x100c98, 1, 0x00000242 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_fb_clkgate_blcg_init_main_0[] = { + { 0x10f000, 1, 0x00000042 }, + { 0x17e030, 1, 0x00000044 }, + { 0x17e040, 1, 0x00000044 }, + {} +}; + +const struct nvkm_therm_clkgate_init +gk104_fb_clkgate_blcg_init_bcast_0[] = { + { 0x17ea60, 4, 0x00000044 }, + {} +}; + +static const struct nvkm_therm_clkgate_pack +gk104_fb_clkgate_pack[] = { + { gk104_fb_clkgate_blcg_init_unk_0 }, + { gk104_fb_clkgate_blcg_init_vm_0 }, + { gk104_fb_clkgate_blcg_init_main_0 }, + { gk104_fb_clkgate_blcg_init_bcast_0 }, + {} +}; + static const struct nvkm_fb_func gk104_fb = { .dtor = gf100_fb_dtor, @@ -33,6 +79,7 @@ gk104_fb = { .intr = gf100_fb_intr, .ram_new = gk104_ram_new, .default_bigpage = 17, + .clkgate_pack = gk104_fb_clkgate_pack, }; int diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h new file mode 100644 index 00000000000000..b3c78e4ff7068a --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk104.h @@ -0,0 +1,35 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Lyude Paul + */ + +#ifndef __GK104_FB_H__ +#define __GK104_FB_H__ + +#include + +extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_unk_0[]; +extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_vm_0[]; +extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_main_0[]; +extern const struct nvkm_therm_clkgate_init gk104_fb_clkgate_blcg_init_bcast_0[]; + +#endif diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h index 9351188d5d764b..414a423e0e55f2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/priv.h @@ -3,6 +3,7 @@ #define __NVKM_FB_PRIV_H__ #define nvkm_fb(p) container_of((p), struct nvkm_fb, subdev) #include +#include struct nvkm_bios; struct nvkm_fb_func { @@ -27,6 +28,7 @@ struct nvkm_fb_func { int (*ram_new)(struct nvkm_fb *, struct nvkm_ram **); u8 default_bigpage; + const struct nvkm_therm_clkgate_pack *clkgate_pack; }; void nvkm_fb_ctor(const struct nvkm_fb_func *, struct nvkm_device *device, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild index 4bac4772d8ed8b..550702eab0b100 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/Kbuild @@ -9,6 +9,7 @@ nvkm-y += nvkm/subdev/therm/nv40.o nvkm-y += nvkm/subdev/therm/nv50.o nvkm-y += nvkm/subdev/therm/g84.o nvkm-y += nvkm/subdev/therm/gt215.o +nvkm-y += nvkm/subdev/therm/gf100.o nvkm-y += nvkm/subdev/therm/gf119.o nvkm-y += nvkm/subdev/therm/gk104.o nvkm-y += nvkm/subdev/therm/gm107.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index cf1d5af30f5f0f..de07bc07abdb9c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -391,6 +391,16 @@ nvkm_therm_init(struct nvkm_subdev *subdev) return 0; } +void +nvkm_therm_clkgate_init(struct nvkm_therm *therm, + const struct nvkm_therm_clkgate_pack *p) +{ + if (!therm->func->clkgate_init || !therm->clkgating_enabled) + return; + + therm->func->clkgate_init(therm, p); +} + static void * nvkm_therm_dtor(struct nvkm_subdev *subdev) { diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c new file mode 100644 index 00000000000000..5ae6913320e842 --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gf100.c @@ -0,0 +1,58 @@ +/* + * Copyright 2018 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Lyude Paul + */ +#include + +#include "priv.h" + +#define pack_for_each_init(init, pack, head) \ + for (pack = head; pack && pack->init; pack++) \ + for (init = pack->init; init && init->count; init++) +void +gf100_clkgate_init(struct nvkm_therm *therm, + const struct nvkm_therm_clkgate_pack *p) +{ + struct nvkm_device *device = therm->subdev.device; + const struct nvkm_therm_clkgate_pack *pack; + const struct nvkm_therm_clkgate_init *init; + u32 next, addr; + + pack_for_each_init(init, pack, p) { + next = init->addr + init->count * 8; + addr = init->addr; + + nvkm_trace(&therm->subdev, "{ 0x%06x, %d, 0x%08x }\n", + init->addr, init->count, init->data); + while (addr < next) { + nvkm_trace(&therm->subdev, "\t0x%06x = 0x%08x\n", + addr, init->data); + nvkm_wr32(device, addr, init->data); + addr += 8; + } + } +} + +/* + * TODO: Fermi clockgating isn't understood fully yet, so we don't specify any + * clockgate functions to use + */ diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c index 79806a7578931f..4e03971d2e3df2 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gk104.c @@ -100,6 +100,7 @@ gk104_therm_func = { .temp_get = g84_temp_get, .fan_sense = gt215_therm_fan_sense, .program_alarms = nvkm_therm_program_alarms_polling, + .clkgate_init = gf100_clkgate_init, .clkgate_enable = gk104_clkgate_enable, .clkgate_fini = gk104_clkgate_fini, }; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c index c08097f2aff502..4caf401d001a41 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/gt215.c @@ -36,7 +36,7 @@ gt215_therm_fan_sense(struct nvkm_therm *therm) return -ENODEV; } -static void +void gt215_therm_init(struct nvkm_therm *therm) { struct nvkm_device *device = therm->subdev.device; diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h index f30202dd88e702..21659daf18649c 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/priv.h @@ -97,6 +97,8 @@ struct nvkm_therm_func { void (*program_alarms)(struct nvkm_therm *); + void (*clkgate_init)(struct nvkm_therm *, + const struct nvkm_therm_clkgate_pack *); void (*clkgate_enable)(struct nvkm_therm *); void (*clkgate_fini)(struct nvkm_therm *, bool); }; @@ -114,6 +116,9 @@ void g84_therm_fini(struct nvkm_therm *); int gt215_therm_fan_sense(struct nvkm_therm *); +void gf100_clkgate_init(struct nvkm_therm *, + const struct nvkm_therm_clkgate_pack *); + void g84_therm_init(struct nvkm_therm *); int gf119_fan_pwm_ctrl(struct nvkm_therm *, int, bool); @@ -122,6 +127,7 @@ int gf119_fan_pwm_set(struct nvkm_therm *, int, u32, u32); int gf119_fan_pwm_clock(struct nvkm_therm *, int); void gf119_therm_init(struct nvkm_therm *); +void gk104_therm_init(struct nvkm_therm *); void gk104_clkgate_enable(struct nvkm_therm *); void gk104_clkgate_fini(struct nvkm_therm *, bool); From 7d094d29584ff5a571be45dcdab5659d97f01020 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 1 Feb 2018 13:13:57 -0500 Subject: [PATCH 107/237] drm/nouveau: Add support for BLCG on Kepler2 Same as the previous patch, but for Kepler2 now Signed-off-by: Lyude Paul Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/include/nvkm/subdev/fb.h | 1 + .../gpu/drm/nouveau/nvkm/engine/device/base.c | 8 +-- .../gpu/drm/nouveau/nvkm/engine/gr/gk110.c | 62 ++++++++++++++++ drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild | 1 + .../gpu/drm/nouveau/nvkm/subdev/fb/gk110.c | 71 +++++++++++++++++++ 5 files changed, 139 insertions(+), 4 deletions(-) create mode 100644 drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.c diff --git a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h index adb78f7d083ad8..92be0e5269c637 100644 --- a/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h +++ b/drivers/gpu/drm/nouveau/include/nvkm/subdev/fb.h @@ -75,6 +75,7 @@ int mcp89_fb_new(struct nvkm_device *, int, struct nvkm_fb **); int gf100_fb_new(struct nvkm_device *, int, struct nvkm_fb **); int gf108_fb_new(struct nvkm_device *, int, struct nvkm_fb **); int gk104_fb_new(struct nvkm_device *, int, struct nvkm_fb **); +int gk110_fb_new(struct nvkm_device *, int, struct nvkm_fb **); int gk20a_fb_new(struct nvkm_device *, int, struct nvkm_fb **); int gm107_fb_new(struct nvkm_device *, int, struct nvkm_fb **); int gm200_fb_new(struct nvkm_device *, int, struct nvkm_fb **); diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c index eab529dceb7301..073534ab691182 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/device/base.c @@ -1812,7 +1812,7 @@ nvf0_chipset = { .bus = gf100_bus_new, .clk = gk104_clk_new, .devinit = gf100_devinit_new, - .fb = gk104_fb_new, + .fb = gk110_fb_new, .fuse = gf100_fuse_new, .gpio = gk104_gpio_new, .i2c = gk104_i2c_new, @@ -1850,7 +1850,7 @@ nvf1_chipset = { .bus = gf100_bus_new, .clk = gk104_clk_new, .devinit = gf100_devinit_new, - .fb = gk104_fb_new, + .fb = gk110_fb_new, .fuse = gf100_fuse_new, .gpio = gk104_gpio_new, .i2c = gk104_i2c_new, @@ -1888,7 +1888,7 @@ nv106_chipset = { .bus = gf100_bus_new, .clk = gk104_clk_new, .devinit = gf100_devinit_new, - .fb = gk104_fb_new, + .fb = gk110_fb_new, .fuse = gf100_fuse_new, .gpio = gk104_gpio_new, .i2c = gk104_i2c_new, @@ -1926,7 +1926,7 @@ nv108_chipset = { .bus = gf100_bus_new, .clk = gk104_clk_new, .devinit = gf100_devinit_new, - .fb = gk104_fb_new, + .fb = gk110_fb_new, .fuse = gf100_fuse_new, .gpio = gk104_gpio_new, .i2c = gk104_i2c_new, diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c index a38e19b61c1da2..a528894231d073 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c @@ -22,6 +22,7 @@ * Authors: Ben Skeggs */ #include "gf100.h" +#include "gk104.h" #include "ctxgf100.h" #include @@ -156,6 +157,66 @@ gk110_gr_pack_mmio[] = { {} }; +static const struct nvkm_therm_clkgate_init +gk110_clkgate_blcg_init_sked_0[] = { + { 0x407000, 1, 0x00004041 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_blcg_init_gpc_gcc_0[] = { + { 0x419020, 1, 0x00000042 }, + { 0x419038, 1, 0x00000042 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_blcg_init_gpc_l1c_0[] = { + { 0x419cd4, 2, 0x00004042 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_blcg_init_gpc_mp_0[] = { + { 0x419fd0, 1, 0x00004043 }, + { 0x419fd8, 1, 0x00004049 }, + { 0x419fe0, 2, 0x00004042 }, + { 0x419ff0, 1, 0x00000046 }, + { 0x419ff8, 1, 0x00004042 }, + { 0x419f90, 1, 0x00004042 }, + {} +}; + +static const struct nvkm_therm_clkgate_pack +gk110_clkgate_pack[] = { + { gk104_clkgate_blcg_init_main_0 }, + { gk104_clkgate_blcg_init_rstr2d_0 }, + { gk104_clkgate_blcg_init_unk_0 }, + { gk104_clkgate_blcg_init_gcc_0 }, + { gk110_clkgate_blcg_init_sked_0 }, + { gk104_clkgate_blcg_init_unk_1 }, + { gk104_clkgate_blcg_init_gpc_ctxctl_0 }, + { gk104_clkgate_blcg_init_gpc_unk_0 }, + { gk104_clkgate_blcg_init_gpc_esetup_0 }, + { gk104_clkgate_blcg_init_gpc_tpbus_0 }, + { gk104_clkgate_blcg_init_gpc_zcull_0 }, + { gk104_clkgate_blcg_init_gpc_tpconf_0 }, + { gk104_clkgate_blcg_init_gpc_unk_1 }, + { gk110_clkgate_blcg_init_gpc_gcc_0 }, + { gk104_clkgate_blcg_init_gpc_ffb_0 }, + { gk104_clkgate_blcg_init_gpc_tex_0 }, + { gk104_clkgate_blcg_init_gpc_poly_0 }, + { gk110_clkgate_blcg_init_gpc_l1c_0 }, + { gk104_clkgate_blcg_init_gpc_unk_2 }, + { gk110_clkgate_blcg_init_gpc_mp_0 }, + { gk104_clkgate_blcg_init_gpc_ppc_0 }, + { gk104_clkgate_blcg_init_rop_zrop_0 }, + { gk104_clkgate_blcg_init_rop_0 }, + { gk104_clkgate_blcg_init_rop_crop_0 }, + { gk104_clkgate_blcg_init_pxbar_0 }, + {} +}; + /******************************************************************************* * PGRAPH engine/subdev functions ******************************************************************************/ @@ -192,6 +253,7 @@ gk110_gr = { .rops = gf100_gr_rops, .ppc_nr = 2, .grctx = &gk110_grctx, + .clkgate_pack = gk110_clkgate_pack, .sclass = { { -1, -1, FERMI_TWOD_A }, { -1, -1, KEPLER_INLINE_TO_MEMORY_B }, diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild index 2571530e82f1c3..b4f22cce5d4334 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/Kbuild @@ -22,6 +22,7 @@ nvkm-y += nvkm/subdev/fb/mcp89.o nvkm-y += nvkm/subdev/fb/gf100.o nvkm-y += nvkm/subdev/fb/gf108.o nvkm-y += nvkm/subdev/fb/gk104.o +nvkm-y += nvkm/subdev/fb/gk110.o nvkm-y += nvkm/subdev/fb/gk20a.o nvkm-y += nvkm/subdev/fb/gm107.o nvkm-y += nvkm/subdev/fb/gm200.o diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.c new file mode 100644 index 00000000000000..0695e5dd360e4b --- /dev/null +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/gk110.c @@ -0,0 +1,71 @@ +/* + * Copyright 2017 Red Hat Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: Lyude Paul + */ +#include "gf100.h" +#include "gk104.h" +#include "ram.h" +#include +#include + +/* + ******************************************************************************* + * PGRAPH registers for clockgating + ******************************************************************************* + */ + +static const struct nvkm_therm_clkgate_init +gk110_fb_clkgate_blcg_init_unk_0[] = { + { 0x100d10, 1, 0x0000c242 }, + { 0x100d30, 1, 0x0000c242 }, + { 0x100d3c, 1, 0x00000242 }, + { 0x100d48, 1, 0x0000c242 }, + { 0x100d1c, 1, 0x00000042 }, + {} +}; + +static const struct nvkm_therm_clkgate_pack +gk110_fb_clkgate_pack[] = { + { gk110_fb_clkgate_blcg_init_unk_0 }, + { gk104_fb_clkgate_blcg_init_vm_0 }, + { gk104_fb_clkgate_blcg_init_main_0 }, + { gk104_fb_clkgate_blcg_init_bcast_0 }, + {} +}; + +static const struct nvkm_fb_func +gk110_fb = { + .dtor = gf100_fb_dtor, + .oneinit = gf100_fb_oneinit, + .init = gf100_fb_init, + .init_page = gf100_fb_init_page, + .intr = gf100_fb_intr, + .ram_new = gk104_ram_new, + .default_bigpage = 17, + .clkgate_pack = gk110_fb_clkgate_pack, +}; + +int +gk110_fb_new(struct nvkm_device *device, int index, struct nvkm_fb **pfb) +{ + return gf100_fb_new_(&gk110_fb, device, index, pfb); +} From a0f79082bd1740137371f989dbdcbc19a52d3557 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 1 Feb 2018 13:13:58 -0500 Subject: [PATCH 108/237] drm/nouveau: Add support for SLCG for Kepler2 That's right, there's still more power saving to go! Starting with kepler 2, nvidia hardware has an additional level of clockgating known as second level clockgating. The details of this are not exact, but it seems to work by waiting for a collection of dependent hardware blocks to be gated before taking affect. As with the previous series, this results in another noticeable drop in power consumption and is programmed in the same manner. Signed-off-by: Lyude Paul Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- .../gpu/drm/nouveau/nvkm/engine/gr/gk110.c | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c index a528894231d073..4da916a9fc73d3 100644 --- a/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c +++ b/drivers/gpu/drm/nouveau/nvkm/engine/gr/gk110.c @@ -187,6 +187,87 @@ gk110_clkgate_blcg_init_gpc_mp_0[] = { {} }; +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_main_0[] = { + { 0x4041f4, 1, 0x00000000 }, + { 0x409894, 1, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_unk_0[] = { + { 0x406004, 1, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_sked_0[] = { + { 0x407004, 1, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_gpc_ctxctl_0[] = { + { 0x41a894, 1, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_gpc_unk_0[] = { + { 0x418504, 1, 0x00000000 }, + { 0x41860c, 1, 0x00000000 }, + { 0x41868c, 1, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_gpc_esetup_0[] = { + { 0x41882c, 1, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_gpc_zcull_0[] = { + { 0x418974, 1, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_gpc_l1c_0[] = { + { 0x419cd8, 2, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_gpc_unk_1[] = { + { 0x419c74, 1, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_gpc_mp_0[] = { + { 0x419fd4, 1, 0x00004a4a }, + { 0x419fdc, 1, 0x00000014 }, + { 0x419fe4, 1, 0x00000000 }, + { 0x419ff4, 1, 0x00001724 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_gpc_ppc_0[] = { + { 0x41be2c, 1, 0x00000000 }, + {} +}; + +static const struct nvkm_therm_clkgate_init +gk110_clkgate_slcg_init_pcounter_0[] = { + { 0x1be018, 1, 0x000001ff }, + { 0x1bc018, 1, 0x000001ff }, + { 0x1b8018, 1, 0x000001ff }, + { 0x1b4124, 1, 0x00000000 }, + {} +}; + static const struct nvkm_therm_clkgate_pack gk110_clkgate_pack[] = { { gk104_clkgate_blcg_init_main_0 }, @@ -214,6 +295,18 @@ gk110_clkgate_pack[] = { { gk104_clkgate_blcg_init_rop_0 }, { gk104_clkgate_blcg_init_rop_crop_0 }, { gk104_clkgate_blcg_init_pxbar_0 }, + { gk110_clkgate_slcg_init_main_0 }, + { gk110_clkgate_slcg_init_unk_0 }, + { gk110_clkgate_slcg_init_sked_0 }, + { gk110_clkgate_slcg_init_gpc_ctxctl_0 }, + { gk110_clkgate_slcg_init_gpc_unk_0 }, + { gk110_clkgate_slcg_init_gpc_esetup_0 }, + { gk110_clkgate_slcg_init_gpc_zcull_0 }, + { gk110_clkgate_slcg_init_gpc_l1c_0 }, + { gk110_clkgate_slcg_init_gpc_unk_1 }, + { gk110_clkgate_slcg_init_gpc_mp_0 }, + { gk110_clkgate_slcg_init_gpc_ppc_0 }, + { gk110_clkgate_slcg_init_pcounter_0 }, {} }; From 3ea74559d851b0e3f611da45d0dd9d505c4f44d5 Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 1 Feb 2018 13:13:59 -0500 Subject: [PATCH 109/237] drm/nouveau: Introduce NvPmEnableGating option This adds the NvPmEnableGating config option to nouveau, which can be used to enable or disable clockgating for supported chipsets. Enabling can be done by passing config=NvPmEnableGating=1 To nouveau. If your chipset supports it, you'll see a message in your kernel log indicating that clockgating is enabled. Since clockgating has only had limited testing thus far, we leave this option disabled by default for now. Signed-off-by: Lyude Paul Reviewed-by: Martin Peres Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c index de07bc07abdb9c..bf62303571b39a 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/therm/base.c @@ -434,7 +434,9 @@ nvkm_therm_ctor(struct nvkm_therm *therm, struct nvkm_device *device, therm->attr_get = nvkm_therm_attr_get; therm->attr_set = nvkm_therm_attr_set; therm->mode = therm->suspend = -1; /* undefined */ - therm->clkgating_enabled = false; + + therm->clkgating_enabled = nvkm_boolopt(device->cfgopt, + "NvPmEnableGating", false); } int From e64fe9db2d1a31f6475ab1d5758860e7aa0cbb88 Mon Sep 17 00:00:00 2001 From: Luis de Bethencourt Date: Wed, 17 Jan 2018 18:53:14 +0000 Subject: [PATCH 110/237] drm/nouveau/mmu: Fix trailing semicolon The trailing semicolon is an empty statement that does no operation. Removing it since it doesn't do anything. Signed-off-by: Luis de Bethencourt Reviewed-by: Karol Herbst Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c index e35d3e17cd7ca3..93946dcee3191b 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c @@ -642,7 +642,7 @@ nvkm_vmm_ptes_sparse(struct nvkm_vmm *vmm, u64 addr, u64 size, bool ref) else block = (size >> page[i].shift) << page[i].shift; } else { - block = (size >> page[i].shift) << page[i].shift;; + block = (size >> page[i].shift) << page[i].shift; } /* Perform operation. */ From b515483e12b81da8cb62f1ff2461d6c29cf5115f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 16 Jan 2018 14:44:50 +0100 Subject: [PATCH 111/237] drm/nouveau/clk: fix gcc-7 -Wint-in-bool-context warning gcc thinks that interpreting a multiplication result as a bool is confusing: drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c: In function 'read_pll': drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c:133:8: error: '*' in boolean context, suggest '&&' instead [-Werror=int-in-bool-context] Adding a temporary variable to contain the divisor helps make it clear what is going on and avoids that warning. Signed-off-by: Arnd Bergmann Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c index 96e0941c8edd94..f0a26881d9b9bc 100644 --- a/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/clk/gt215.c @@ -110,6 +110,7 @@ read_pll(struct gt215_clk *clk, int idx, u32 pll) struct nvkm_device *device = clk->base.subdev.device; u32 ctrl = nvkm_rd32(device, pll + 0); u32 sclk = 0, P = 1, N = 1, M = 1; + u32 MP; if (!(ctrl & 0x00000008)) { if (ctrl & 0x00000001) { @@ -130,10 +131,12 @@ read_pll(struct gt215_clk *clk, int idx, u32 pll) sclk = read_clk(clk, 0x10 + idx, false); } - if (M * P) - return sclk * N / (M * P); + MP = M * P; - return 0; + if (!MP) + return 0; + + return sclk * N / MP; } static int From 97e45dd6e82a556e64a81824bb87c2b9bf98ddd3 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 23 Jan 2018 09:59:20 -0600 Subject: [PATCH 112/237] ACPI / video: Use true for boolean value Assign true or false to boolean variables instead of an integer value. This issue was detected with the help of Coccinelle. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_video.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/acpi_video.c b/drivers/acpi/acpi_video.c index f53ccc68023819..76fb96966f7b11 100644 --- a/drivers/acpi/acpi_video.c +++ b/drivers/acpi/acpi_video.c @@ -53,7 +53,7 @@ MODULE_AUTHOR("Bruno Ducrot"); MODULE_DESCRIPTION("ACPI Video Driver"); MODULE_LICENSE("GPL"); -static bool brightness_switch_enabled = 1; +static bool brightness_switch_enabled = true; module_param(brightness_switch_enabled, bool, 0644); /* From 0eedae8e5f983aba6fb5c29c8699ecf03c7e50e0 Mon Sep 17 00:00:00 2001 From: Anuj Mittal Date: Wed, 24 Jan 2018 15:42:29 -0800 Subject: [PATCH 113/237] ACPICA: Linux: add support for X32 ABI compilation X32 follows ILP32 model. Check for ILP32 as well when checking for x86_64 to ensure the defines are correct for X32 ABI. Signed-off-by: Anuj Mittal Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- include/acpi/platform/aclinux.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 1b473efd9eb606..97e088276c6d24 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -206,7 +206,7 @@ #define ACPI_FLUSH_CPU_CACHE() #define ACPI_CAST_PTHREAD_T(pthread) ((acpi_thread_id) (pthread)) -#if defined(__ia64__) || defined(__x86_64__) ||\ +#if defined(__ia64__) || (defined(__x86_64__) && !defined(__ILP32__)) ||\ defined(__aarch64__) || defined(__PPC64__) ||\ defined(__s390x__) #define ACPI_MACHINE_WIDTH 64 From 761f0b82393353507930b6721ae4311a9df2ca36 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Wed, 24 Jan 2018 15:42:30 -0800 Subject: [PATCH 114/237] ACPICA: Avoid NULL pointer arithmetic We should not assume NULL is defined as "(void *)0" because NULL is an implementation-defined macro. Especially, Clang 6 complains about it, i.e., "arithmetic on a null pointer treated as a cast from integer to pointer is a GNU extension". Signed-off-by: Jung-uk Kim Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- include/acpi/actypes.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 31f1be74dd1657..f3999ae7a43f11 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -485,7 +485,7 @@ typedef u8 acpi_owner_id; /* * Constants with special meanings */ -#define ACPI_ROOT_OBJECT ACPI_ADD_PTR (acpi_handle, NULL, ACPI_MAX_PTR) +#define ACPI_ROOT_OBJECT ACPI_ADD_PTR (acpi_handle, (void *) 0, ACPI_MAX_PTR) #define ACPI_WAIT_FOREVER 0xFFFF /* u16, as per ACPI spec */ #define ACPI_DO_NOT_WAIT 0 @@ -536,9 +536,9 @@ typedef u64 acpi_integer; /* Pointer/Integer type conversions */ -#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void, (void *) NULL,(acpi_size) i) -#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) NULL) -#define ACPI_OFFSET(d, f) ACPI_PTR_DIFF (&(((d *) 0)->f), (void *) NULL) +#define ACPI_TO_POINTER(i) ACPI_ADD_PTR (void, (void *) 0, (acpi_size) (i)) +#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) +#define ACPI_OFFSET(d, f) ACPI_PTR_DIFF (&(((d *) 0)->f), (void *) 0) #define ACPI_PHYSADDR_TO_PTR(i) ACPI_TO_POINTER(i) #define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) From 9cf02a0a66da50a990604533fa7d2dbf74aae054 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Wed, 24 Jan 2018 15:42:31 -0800 Subject: [PATCH 115/237] ACPICA: Prefer ACPI_TO_POINTER() over ACPI_ADD_PTR() This is more easy to read. Signed-off-by: Jung-uk Kim Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- include/acpi/actypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index f3999ae7a43f11..0b6b55f1e597ff 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -485,7 +485,7 @@ typedef u8 acpi_owner_id; /* * Constants with special meanings */ -#define ACPI_ROOT_OBJECT ACPI_ADD_PTR (acpi_handle, (void *) 0, ACPI_MAX_PTR) +#define ACPI_ROOT_OBJECT ((acpi_handle) ACPI_TO_POINTER (ACPI_MAX_PTR)) #define ACPI_WAIT_FOREVER 0xFFFF /* u16, as per ACPI spec */ #define ACPI_DO_NOT_WAIT 0 From 0649a0989fcb02ecaf7b0c15ae6a5051637c8f34 Mon Sep 17 00:00:00 2001 From: Jung-uk Kim Date: Wed, 24 Jan 2018 15:42:32 -0800 Subject: [PATCH 116/237] ACPICA: Add a missing pair of parentheses Signed-off-by: Jung-uk Kim Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- include/acpi/actypes.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 0b6b55f1e597ff..4fed3310235a5d 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -532,7 +532,7 @@ typedef u64 acpi_integer; #define ACPI_CAST_INDIRECT_PTR(t, p) ((t **) (acpi_uintptr_t) (p)) #define ACPI_ADD_PTR(t, a, b) ACPI_CAST_PTR (t, (ACPI_CAST_PTR (u8, (a)) + (acpi_size)(b))) #define ACPI_SUB_PTR(t, a, b) ACPI_CAST_PTR (t, (ACPI_CAST_PTR (u8, (a)) - (acpi_size)(b))) -#define ACPI_PTR_DIFF(a, b) (acpi_size) (ACPI_CAST_PTR (u8, (a)) - ACPI_CAST_PTR (u8, (b))) +#define ACPI_PTR_DIFF(a, b) ((acpi_size) (ACPI_CAST_PTR (u8, (a)) - ACPI_CAST_PTR (u8, (b)))) /* Pointer/Integer type conversions */ From 5a98231f554779fb1649f477b70bed1fd17222f2 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 26 Jan 2018 16:02:56 +0100 Subject: [PATCH 117/237] ACPI: export acpi_bus_get_status_handle() Some modular drivers need this, export it. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 4d0979e02a287d..d44d2c287b9185 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -108,6 +108,7 @@ acpi_status acpi_bus_get_status_handle(acpi_handle handle, } return status; } +EXPORT_SYMBOL_GPL(acpi_bus_get_status_handle); int acpi_bus_get_status(struct acpi_device *device) { From b0fd6772cfe10cd1edd65a376522e430e5f1bc58 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 26 Jan 2018 16:02:57 +0100 Subject: [PATCH 118/237] PCI: acpiphp_ibm: prepare for acpi_get_object_info() no longer returning status acpi_get_object_info() is intended for early probe usage and as such should not call any methods which may rely on OpRegions, but it used to also call _STA to get the status, which on some systems does rely on OpRegions, this behavior and the acpi_device_info.current_status member are being removed. This commit prepares the acpiphp_ibm code for this by having it get the status itself using acpi_bus_get_status_handle(). Note no error handling is necessary on any errors acpi_bus_get_status_handle() leaves the value of the passed in current_status at its 0 initialization value. Acked-by: Bjorn Helgaas Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/pci/hotplug/acpiphp_ibm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/pci/hotplug/acpiphp_ibm.c b/drivers/pci/hotplug/acpiphp_ibm.c index 984c7e8cec5aee..8472c4a27f7001 100644 --- a/drivers/pci/hotplug/acpiphp_ibm.c +++ b/drivers/pci/hotplug/acpiphp_ibm.c @@ -399,6 +399,7 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_handle *phandle = (acpi_handle *)context; + unsigned long long current_status = 0; acpi_status status; struct acpi_device_info *info; int retval = 0; @@ -410,7 +411,9 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle, return retval; } - if (info->current_status && (info->valid & ACPI_VALID_HID) && + acpi_bus_get_status_handle(handle, ¤t_status); + + if (current_status && (info->valid & ACPI_VALID_HID) && (!strcmp(info->hardware_id.string, IBM_HARDWARE_ID1) || !strcmp(info->hardware_id.string, IBM_HARDWARE_ID2))) { pr_debug("found hardware: %s, handle: %p\n", From 54ddce7062242036402242242c07c60c0b505f84 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 26 Jan 2018 16:02:58 +0100 Subject: [PATCH 119/237] ACPI / bus: Do not call _STA on battery devices with unmet dependencies The battery code uses acpi_device->dep_unmet to check for unmet deps and if there are unmet deps it does not bind to the device to avoid errors about missing OpRegions when calling ACPI methods on the device. The missing OpRegions when there are unmet deps problem also applies to the _STA method of some battery devices and calling it too early results in errors like these: [ 0.123579] ACPI Error: No handler for Region [ECRM] (00000000ba9edc4c) [GenericSerialBus] (20170831/evregion-166) [ 0.123601] ACPI Error: Region GenericSerialBus (ID=9) has no handler (20170831/exfldio-299) [ 0.123618] ACPI Error: Method parse/execution failed \_SB.I2C1.BAT1._STA, AE_NOT_EXIST (20170831/psparse-550) This commit fixes these errors happening when acpi_get_bus_status gets called by checking dep_unmet for battery devices and reporting a status of 0 until all dependencies are met. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index d44d2c287b9185..433bb5a3f32779 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -120,6 +120,12 @@ int acpi_bus_get_status(struct acpi_device *device) return 0; } + /* Battery devices must have their deps met before calling _STA */ + if (acpi_device_is_battery(device) && device->dep_unmet) { + acpi_set_device_status(device, 0); + return 0; + } + status = acpi_bus_get_status_handle(device->handle, &sta); if (ACPI_FAILURE(status)) return -ENODEV; From 63347db0affadcbccd5613116ea8431c70139b3e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 26 Jan 2018 16:02:59 +0100 Subject: [PATCH 120/237] ACPI / scan: Use acpi_bus_get_status() to initialize ACPI_TYPE_DEVICE devs The acpi_get_bus_status wrapper for acpi_bus_get_status_handle has some code to handle certain device quirks, in some cases we also need this quirk handling for the initial _STA call. Specifically on some devices calling _STA before all _DEP dependencies are met results in errors like these: [ 0.123579] ACPI Error: No handler for Region [ECRM] (00000000ba9edc4c) [GenericSerialBus] (20170831/evregion-166) [ 0.123601] ACPI Error: Region GenericSerialBus (ID=9) has no handler (20170831/exfldio-299) [ 0.123618] ACPI Error: Method parse/execution failed \_SB.I2C1.BAT1._STA, AE_NOT_EXIST (20170831/psparse-550) acpi_get_bus_status already has code to avoid this, so by using it we also silence these errors from the initial _STA call. Note that in order for the acpi_get_bus_status handling for this to work, we initialize dep_unmet to 1 until acpi_device_dep_initialize gets called, this means that battery devices will be instantiated with an initial status of 0. This is not a problem, acpi_bus_attach will get called soon after the instantiation anyways and it will update the status as first point of order. Signed-off-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index b0fe5272c76aad..8e63d937babb0d 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1565,6 +1565,8 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, device_initialize(&device->dev); dev_set_uevent_suppress(&device->dev, true); acpi_init_coherency(device); + /* Assume there are unmet deps until acpi_device_dep_initialize() runs */ + device->dep_unmet = 1; } void acpi_device_add_finalize(struct acpi_device *device) @@ -1588,6 +1590,14 @@ static int acpi_add_single_object(struct acpi_device **child, } acpi_init_device_object(device, handle, type, sta); + /* + * For ACPI_BUS_TYPE_DEVICE getting the status is delayed till here so + * that we can call acpi_bus_get_status() and use its quirk handling. + * Note this must be done before the get power-/wakeup_dev-flags calls. + */ + if (type == ACPI_BUS_TYPE_DEVICE) + acpi_bus_get_status(device); + acpi_bus_get_power_flags(device); acpi_bus_get_wakeup_device_flags(device); @@ -1660,9 +1670,11 @@ static int acpi_bus_type_and_status(acpi_handle handle, int *type, return -ENODEV; *type = ACPI_BUS_TYPE_DEVICE; - status = acpi_bus_get_status_handle(handle, sta); - if (ACPI_FAILURE(status)) - *sta = 0; + /* + * acpi_add_single_object updates this once we've an acpi_device + * so that acpi_bus_get_status' quirk handling can be used. + */ + *sta = 0; break; case ACPI_TYPE_PROCESSOR: *type = ACPI_BUS_TYPE_PROCESSOR; @@ -1760,6 +1772,8 @@ static void acpi_device_dep_initialize(struct acpi_device *adev) acpi_status status; int i; + adev->dep_unmet = 0; + if (!acpi_has_method(adev->handle, "_DEP")) return; From ba1edb9a5125a617d612f98eead14b9b84e75c3a Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Mon, 29 Jan 2018 10:26:46 +0800 Subject: [PATCH 121/237] ACPI: processor_perflib: Do not send _PPC change notification if not ready The following warning was triggered after resumed from S3 - if all the nonboot CPUs were put offline before suspend: [ 1840.329515] unchecked MSR access error: RDMSR from 0x771 at rIP: 0xffffffff86061e3a (native_read_msr+0xa/0x30) [ 1840.329516] Call Trace: [ 1840.329521] __rdmsr_on_cpu+0x33/0x50 [ 1840.329525] generic_exec_single+0x81/0xb0 [ 1840.329527] smp_call_function_single+0xd2/0x100 [ 1840.329530] ? acpi_ds_result_pop+0xdd/0xf2 [ 1840.329532] ? acpi_ds_create_operand+0x215/0x23c [ 1840.329534] rdmsrl_on_cpu+0x57/0x80 [ 1840.329536] ? cpumask_next+0x1b/0x20 [ 1840.329538] ? rdmsrl_on_cpu+0x57/0x80 [ 1840.329541] intel_pstate_update_perf_limits+0xf3/0x220 [ 1840.329544] ? notifier_call_chain+0x4a/0x70 [ 1840.329546] intel_pstate_set_policy+0x4e/0x150 [ 1840.329548] cpufreq_set_policy+0xcd/0x2f0 [ 1840.329550] cpufreq_update_policy+0xb2/0x130 [ 1840.329552] ? cpufreq_update_policy+0x130/0x130 [ 1840.329556] acpi_processor_ppc_has_changed+0x65/0x80 [ 1840.329558] acpi_processor_notify+0x80/0x100 [ 1840.329561] acpi_ev_notify_dispatch+0x44/0x5c [ 1840.329563] acpi_os_execute_deferred+0x14/0x20 [ 1840.329565] process_one_work+0x193/0x3c0 [ 1840.329567] worker_thread+0x35/0x3b0 [ 1840.329569] kthread+0x125/0x140 [ 1840.329571] ? process_one_work+0x3c0/0x3c0 [ 1840.329572] ? kthread_park+0x60/0x60 [ 1840.329575] ? do_syscall_64+0x67/0x180 [ 1840.329577] ret_from_fork+0x25/0x30 [ 1840.329585] unchecked MSR access error: WRMSR to 0x774 (tried to write 0x0000000000000000) at rIP: 0xffffffff86061f78 (native_write_msr+0x8/0x30) [ 1840.329586] Call Trace: [ 1840.329587] __wrmsr_on_cpu+0x37/0x40 [ 1840.329589] generic_exec_single+0x81/0xb0 [ 1840.329592] smp_call_function_single+0xd2/0x100 [ 1840.329594] ? acpi_ds_create_operand+0x215/0x23c [ 1840.329595] ? cpumask_next+0x1b/0x20 [ 1840.329597] wrmsrl_on_cpu+0x57/0x70 [ 1840.329598] ? rdmsrl_on_cpu+0x57/0x80 [ 1840.329599] ? wrmsrl_on_cpu+0x57/0x70 [ 1840.329602] intel_pstate_hwp_set+0xd3/0x150 [ 1840.329604] intel_pstate_set_policy+0x119/0x150 [ 1840.329606] cpufreq_set_policy+0xcd/0x2f0 [ 1840.329607] cpufreq_update_policy+0xb2/0x130 [ 1840.329610] ? cpufreq_update_policy+0x130/0x130 [ 1840.329613] acpi_processor_ppc_has_changed+0x65/0x80 [ 1840.329615] acpi_processor_notify+0x80/0x100 [ 1840.329617] acpi_ev_notify_dispatch+0x44/0x5c [ 1840.329619] acpi_os_execute_deferred+0x14/0x20 [ 1840.329620] process_one_work+0x193/0x3c0 [ 1840.329622] worker_thread+0x35/0x3b0 [ 1840.329624] kthread+0x125/0x140 [ 1840.329625] ? process_one_work+0x3c0/0x3c0 [ 1840.329626] ? kthread_park+0x60/0x60 [ 1840.329628] ? do_syscall_64+0x67/0x180 [ 1840.329631] ret_from_fork+0x25/0x30 This is because if there's only one online CPU, the MSR_PM_ENABLE (package wide)can not be enabled after resumed, due to intel_pstate_hwp_enable() will only be invoked on AP's online process after resumed - if there's no AP online, the HWP remains disabled after resumed (BIOS has disabled it in S3). Then if there comes a _PPC change notification which touches HWP register during this stage, the warning is triggered. Since we don't call acpi_processor_register_performance() when HWP is enabled, the pr->performance will be NULL. When this is NULL we don't need to do _PPC change notification. Reported-by: Doug Smythies Suggested-by: Srinivas Pandruvada Signed-off-by: Yu Chen Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_perflib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 18b72eec350764..c7cf48ad5cb9da 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -159,7 +159,7 @@ void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag) { int ret; - if (ignore_ppc) { + if (ignore_ppc || !pr->performance) { /* * Only when it is notification event, the _OST object * will be evaluated. Otherwise it is skipped. From 4446823e2573e97b26f0534ff8db9e9c4cb65840 Mon Sep 17 00:00:00 2001 From: Kai Heng Feng Date: Mon, 29 Jan 2018 13:40:36 +0800 Subject: [PATCH 122/237] ACPI / battery: Add quirk for Asus UX360UA and UX410UAK Same issue as other Asus laptops, ACPI incorrectly reports discharging when battery is full and AC is plugged. Use the same battery quirk can workaround the issue. Link: https://bugs.launchpad.net/bugs/1661876 Link: https://bugs.launchpad.net/bugs/1745032 Signed-off-by: Kai-Heng Feng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 19bc440820e64d..7128488a3a728f 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1209,6 +1209,22 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = { DMI_MATCH(DMI_PRODUCT_NAME, "UX305LA"), }, }, + { + .callback = battery_full_discharging_quirk, + .ident = "ASUS UX360UA", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "UX360UA"), + }, + }, + { + .callback = battery_full_discharging_quirk, + .ident = "ASUS UX410UAK", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), + DMI_MATCH(DMI_PRODUCT_NAME, "UX410UAK"), + }, + }, {}, }; From 248e8841b4fbb07048f1eb4f63b74bd3c4cf91f2 Mon Sep 17 00:00:00 2001 From: Yazen Ghannam Date: Mon, 29 Jan 2018 14:22:49 -0600 Subject: [PATCH 123/237] ACPI / processor: Set default C1 idle state description The ACPI idle driver will default to ACPI_CSTATE_HALT for C1 if a _CST object for C1 is not defined. However, the description will not be set, so users will see "" when reading the description from sysfs. Set the C1 state description when defaulting to ACPI_CSTATE_HALT. Signed-off-by: Yazen Ghannam Signed-off-by: Rafael J. Wysocki --- drivers/acpi/processor_idle.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d50a7b6ccddd99..226dc5665d8103 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -291,6 +291,9 @@ static int acpi_processor_get_power_info_default(struct acpi_processor *pr) pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1; pr->power.states[ACPI_STATE_C1].valid = 1; pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT; + + snprintf(pr->power.states[ACPI_STATE_C1].desc, + ACPI_CX_DESC_LEN, "ACPI HLT"); } /* the C0 state only exists as a filler in our array */ pr->power.states[ACPI_STATE_C0].valid = 1; From 703cbaa601ff3fb554d1246c336ba727cc083ea0 Mon Sep 17 00:00:00 2001 From: Bo Yan Date: Tue, 23 Jan 2018 13:57:55 -0800 Subject: [PATCH 124/237] cpufreq: Skip cpufreq resume if it's not suspended cpufreq_resume can be called even without preceding cpufreq_suspend. This can happen in following scenario: suspend_devices_and_enter --> dpm_suspend_start --> dpm_prepare --> device_prepare : this function errors out --> dpm_suspend: this is skipped due to dpm_prepare failure this means cpufreq_suspend is skipped over --> goto Recover_platform, due to previous error --> goto Resume_devices --> dpm_resume_end --> dpm_resume --> cpufreq_resume In case schedutil is used as frequency governor, cpufreq_resume will eventually call sugov_start, which does following: memset(sg_cpu, 0, sizeof(*sg_cpu)); .... This effectively erases function pointer for frequency update, causing crash later on. The function pointer would have been set correctly if subsequent cpufreq_add_update_util_hook runs successfully, but that function returns earlier because cpufreq_suspend was not called: if (WARN_ON(per_cpu(cpufreq_update_util_data, cpu))) return; The fix is to check cpufreq_suspended first, if it's false, that means cpufreq_suspend was not called in the first place, so do not resume cpufreq. Signed-off-by: Bo Yan Acked-by: Viresh Kumar [ rjw: Dropped printing a message ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 421f318c0e6697..de33ebf008ada0 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1686,6 +1686,9 @@ void cpufreq_resume(void) if (!cpufreq_driver) return; + if (unlikely(!cpufreq_suspended)) + return; + cpufreq_suspended = false; if (!has_target() && !cpufreq_driver->resume) From d0945caafcccac9d8f4d78f99e0eac9e60386381 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 8 Jan 2018 12:21:04 +0100 Subject: [PATCH 125/237] sunrpc: remove dead code in svc_sock_setbufsize Setting values in struct sock directly is the usual method. Remove the long dead code using set_fs() and the related comment. Signed-off-by: Christoph Hellwig Signed-off-by: J. Bruce Fields --- net/sunrpc/svcsock.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index ff8e06cd067e97..5884583f93a4c5 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -384,25 +384,11 @@ static int svc_partial_recvfrom(struct svc_rqst *rqstp, static void svc_sock_setbufsize(struct socket *sock, unsigned int snd, unsigned int rcv) { -#if 0 - mm_segment_t oldfs; - oldfs = get_fs(); set_fs(KERNEL_DS); - sock_setsockopt(sock, SOL_SOCKET, SO_SNDBUF, - (char*)&snd, sizeof(snd)); - sock_setsockopt(sock, SOL_SOCKET, SO_RCVBUF, - (char*)&rcv, sizeof(rcv)); -#else - /* sock_setsockopt limits use to sysctl_?mem_max, - * which isn't acceptable. Until that is made conditional - * on not having CAP_SYS_RESOURCE or similar, we go direct... - * DaveM said I could! - */ lock_sock(sock->sk); sock->sk->sk_sndbuf = snd * 2; sock->sk->sk_rcvbuf = rcv * 2; sock->sk->sk_write_space(sock->sk); release_sock(sock->sk); -#endif } static int svc_sock_secure_port(struct svc_rqst *rqstp) From 4f1764172a0aa7395d12b96cae640ca1438c5085 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 12 Jan 2018 17:42:30 -0500 Subject: [PATCH 126/237] nfsd: Detect unhashed stids in nfsd4_verify_open_stid() The state of the stid is guaranteed by 2 locks: - The nfs4_client 'cl_lock' spinlock - The nfs4_ol_stateid 'st_mutex' mutex so it is quite possible for the stid to be unhashed after lookup, but before calling nfsd4_lock_ol_stateid(). So we do need to check for a zero value for 'sc_type' in nfsd4_verify_open_stid(). Signed-off-by: Trond Myklebust Tested-by: Checuk Lever Cc: stable@vger.kernel.org Fixes: 659aefb68eca "nfsd: Ensure we don't recognise lock stateids..." Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index b29b5a185a2cb4..5a75135f5f53b4 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -3590,6 +3590,7 @@ nfsd4_verify_open_stid(struct nfs4_stid *s) switch (s->sc_type) { default: break; + case 0: case NFS4_CLOSED_STID: case NFS4_CLOSED_DELEG_STID: ret = nfserr_bad_stateid; From 2502072058b35e2297f4ad7b211a45ad95a6a3d5 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 17 Jan 2018 16:25:59 -0500 Subject: [PATCH 127/237] nfsd4: don't set lock stateid's sc_type to CLOSED There's no point I can see to stp->st_stid.sc_type = NFS4_CLOSED_STID; given release_lock_stateid immediately sets sc_type to 0. That set of sc_type to 0 should be enough to prevent it being used where we don't want it to be; NFS4_CLOSED_STID should only be needed for actual open stateid's that are actually closed. Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4state.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 5a75135f5f53b4..150521c9671b9f 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -5183,7 +5183,6 @@ nfsd4_free_lock_stateid(stateid_t *stateid, struct nfs4_stid *s) lockowner(stp->st_stateowner))) goto out; - stp->st_stid.sc_type = NFS4_CLOSED_STID; release_lock_stateid(stp); ret = nfs_ok; @@ -6079,10 +6078,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, * If this is a new, never-before-used stateid, and we are * returning an error, then just go ahead and release it. */ - if (status && new) { - lock_stp->st_stid.sc_type = NFS4_CLOSED_STID; + if (status && new) release_lock_stateid(lock_stp); - } mutex_unlock(&lock_stp->st_mutex); From 80d172431696482d9acd8d2c4ea78fed8956e2a1 Mon Sep 17 00:00:00 2001 From: "valdis.kletnieks@vt.edu" Date: Sun, 4 Feb 2018 12:01:43 -0500 Subject: [PATCH 128/237] gcc-plugins: Add include required by GCC release 8 GCC requires another #include to get the gcc-plugins to build cleanly. Signed-off-by: Valdis Kletnieks Signed-off-by: Kees Cook --- scripts/gcc-plugins/gcc-common.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/gcc-plugins/gcc-common.h b/scripts/gcc-plugins/gcc-common.h index ffd1dfaa1cc10b..f467500533776c 100644 --- a/scripts/gcc-plugins/gcc-common.h +++ b/scripts/gcc-plugins/gcc-common.h @@ -97,6 +97,10 @@ #include "predict.h" #include "ipa-utils.h" +#if BUILDING_GCC_VERSION >= 8000 +#include "stringpool.h" +#endif + #if BUILDING_GCC_VERSION >= 4009 #include "attribs.h" #include "varasm.h" From b86729109c5fd0a480300f40608aac68764b5adf Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Mon, 5 Feb 2018 17:27:46 -0800 Subject: [PATCH 129/237] gcc-plugins: Use dynamic initializers GCC 8 changed the order of some fields and is very picky about ordering in static initializers, so instead just move to dynamic initializers, and drop the redundant already-zero field assignments. Suggested-by: Valdis Kletnieks Signed-off-by: Kees Cook --- scripts/gcc-plugins/latent_entropy_plugin.c | 17 ++--- scripts/gcc-plugins/randomize_layout_plugin.c | 75 ++++++------------- scripts/gcc-plugins/structleak_plugin.c | 19 ++--- 3 files changed, 33 insertions(+), 78 deletions(-) diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c index 65264960910d36..cbe1d6c4b1a517 100644 --- a/scripts/gcc-plugins/latent_entropy_plugin.c +++ b/scripts/gcc-plugins/latent_entropy_plugin.c @@ -255,21 +255,14 @@ static tree handle_latent_entropy_attribute(tree *node, tree name, return NULL_TREE; } -static struct attribute_spec latent_entropy_attr = { - .name = "latent_entropy", - .min_length = 0, - .max_length = 0, - .decl_required = true, - .type_required = false, - .function_type_required = false, - .handler = handle_latent_entropy_attribute, -#if BUILDING_GCC_VERSION >= 4007 - .affects_type_identity = false -#endif -}; +static struct attribute_spec latent_entropy_attr = { }; static void register_attributes(void *event_data __unused, void *data __unused) { + latent_entropy_attr.name = "latent_entropy"; + latent_entropy_attr.decl_required = true; + latent_entropy_attr.handler = handle_latent_entropy_attribute; + register_attribute(&latent_entropy_attr); } diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c index 0073af32644986..c4a345c3715b63 100644 --- a/scripts/gcc-plugins/randomize_layout_plugin.c +++ b/scripts/gcc-plugins/randomize_layout_plugin.c @@ -580,68 +580,35 @@ static void finish_type(void *event_data, void *data) return; } -static struct attribute_spec randomize_layout_attr = { - .name = "randomize_layout", - // related to args - .min_length = 0, - .max_length = 0, - .decl_required = false, - // need type declaration - .type_required = true, - .function_type_required = false, - .handler = handle_randomize_layout_attr, -#if BUILDING_GCC_VERSION >= 4007 - .affects_type_identity = true -#endif -}; +static struct attribute_spec randomize_layout_attr = { }; +static struct attribute_spec no_randomize_layout_attr = { }; +static struct attribute_spec randomize_considered_attr = { }; +static struct attribute_spec randomize_performed_attr = { }; -static struct attribute_spec no_randomize_layout_attr = { - .name = "no_randomize_layout", - // related to args - .min_length = 0, - .max_length = 0, - .decl_required = false, - // need type declaration - .type_required = true, - .function_type_required = false, - .handler = handle_randomize_layout_attr, +static void register_attributes(void *event_data, void *data) +{ + randomize_layout_attr.name = "randomize_layout"; + randomize_layout_attr.type_required = true; + randomize_layout_attr.handler = handle_randomize_layout_attr; #if BUILDING_GCC_VERSION >= 4007 - .affects_type_identity = true + randomize_layout_attr.affects_type_identity = true; #endif -}; -static struct attribute_spec randomize_considered_attr = { - .name = "randomize_considered", - // related to args - .min_length = 0, - .max_length = 0, - .decl_required = false, - // need type declaration - .type_required = true, - .function_type_required = false, - .handler = handle_randomize_considered_attr, + no_randomize_layout_attr.name = "no_randomize_layout"; + no_randomize_layout_attr.type_required = true; + no_randomize_layout_attr.handler = handle_randomize_layout_attr; #if BUILDING_GCC_VERSION >= 4007 - .affects_type_identity = false + no_randomize_layout_attr.affects_type_identity = true; #endif -}; -static struct attribute_spec randomize_performed_attr = { - .name = "randomize_performed", - // related to args - .min_length = 0, - .max_length = 0, - .decl_required = false, - // need type declaration - .type_required = true, - .function_type_required = false, - .handler = handle_randomize_performed_attr, -#if BUILDING_GCC_VERSION >= 4007 - .affects_type_identity = false -#endif -}; + randomize_considered_attr.name = "randomize_considered"; + randomize_considered_attr.type_required = true; + randomize_considered_attr.handler = handle_randomize_considered_attr; + + randomize_performed_attr.name = "randomize_performed"; + randomize_performed_attr.type_required = true; + randomize_performed_attr.handler = handle_randomize_performed_attr; -static void register_attributes(void *event_data, void *data) -{ register_attribute(&randomize_layout_attr); register_attribute(&no_randomize_layout_attr); register_attribute(&randomize_considered_attr); diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c index 3f8dd486817814..10292f791e992a 100644 --- a/scripts/gcc-plugins/structleak_plugin.c +++ b/scripts/gcc-plugins/structleak_plugin.c @@ -57,21 +57,16 @@ static tree handle_user_attribute(tree *node, tree name, tree args, int flags, b return NULL_TREE; } -static struct attribute_spec user_attr = { - .name = "user", - .min_length = 0, - .max_length = 0, - .decl_required = false, - .type_required = false, - .function_type_required = false, - .handler = handle_user_attribute, -#if BUILDING_GCC_VERSION >= 4007 - .affects_type_identity = true -#endif -}; +static struct attribute_spec user_attr = { }; static void register_attributes(void *event_data, void *data) { + user_attr.name = "user"; + user_attr.handler = handle_user_attribute; +#if BUILDING_GCC_VERSION >= 4007 + user_attr.affects_type_identity = true; +#endif + register_attribute(&user_attr); } From fb4bbba2775399149ca902f31eb5c46cc7a8d8b8 Mon Sep 17 00:00:00 2001 From: Shirish S Date: Mon, 5 Feb 2018 09:23:00 +0530 Subject: [PATCH 130/237] drm/amdgpu: re-enable CGCG on CZ and disable on ST The CGCG feature on Stoney is causing GFX related issues such as freezes and blank outs. Signed-off-by: Shirish S Reviewed-by: Arindam Nath Acked-by: Alex Deucher Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/vi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 5bd10f52ca8af2..1e3e05a11f7a47 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -1022,6 +1022,7 @@ static int vi_common_early_init(void *handle) AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_CGTS | AMD_CG_SUPPORT_GFX_CGTS_LS | + AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_MGCG | @@ -1048,7 +1049,6 @@ static int vi_common_early_init(void *handle) AMD_CG_SUPPORT_GFX_CP_LS | AMD_CG_SUPPORT_GFX_CGTS | AMD_CG_SUPPORT_GFX_CGTS_LS | - AMD_CG_SUPPORT_GFX_CGCG | AMD_CG_SUPPORT_GFX_CGLS | AMD_CG_SUPPORT_BIF_LS | AMD_CG_SUPPORT_HDP_MGCG | From da6f8320d58623eae9b6fa2f09b1b4f60a772ce9 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Thu, 4 Jan 2018 10:06:38 -0800 Subject: [PATCH 131/237] ACPICA: All acpica: Update copyrights to 2018 including tool signons. Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpica/acapps.h | 4 ++-- drivers/acpi/acpica/accommon.h | 2 +- drivers/acpi/acpica/acconvert.h | 2 +- drivers/acpi/acpica/acdebug.h | 2 +- drivers/acpi/acpica/acdispat.h | 2 +- drivers/acpi/acpica/acevents.h | 2 +- drivers/acpi/acpica/acglobal.h | 2 +- drivers/acpi/acpica/achware.h | 2 +- drivers/acpi/acpica/acinterp.h | 2 +- drivers/acpi/acpica/aclocal.h | 2 +- drivers/acpi/acpica/acmacros.h | 2 +- drivers/acpi/acpica/acnamesp.h | 2 +- drivers/acpi/acpica/acobject.h | 2 +- drivers/acpi/acpica/acopcode.h | 2 +- drivers/acpi/acpica/acparser.h | 2 +- drivers/acpi/acpica/acpredef.h | 2 +- drivers/acpi/acpica/acresrc.h | 2 +- drivers/acpi/acpica/acstruct.h | 2 +- drivers/acpi/acpica/actables.h | 2 +- drivers/acpi/acpica/acutils.h | 2 +- drivers/acpi/acpica/amlcode.h | 2 +- drivers/acpi/acpica/amlresrc.h | 2 +- drivers/acpi/acpica/dbcmds.c | 2 +- drivers/acpi/acpica/dbconvert.c | 2 +- drivers/acpi/acpica/dbdisply.c | 2 +- drivers/acpi/acpica/dbexec.c | 2 +- drivers/acpi/acpica/dbfileio.c | 2 +- drivers/acpi/acpica/dbhistry.c | 2 +- drivers/acpi/acpica/dbinput.c | 2 +- drivers/acpi/acpica/dbmethod.c | 2 +- drivers/acpi/acpica/dbnames.c | 2 +- drivers/acpi/acpica/dbobject.c | 2 +- drivers/acpi/acpica/dbstats.c | 2 +- drivers/acpi/acpica/dbtest.c | 2 +- drivers/acpi/acpica/dbutils.c | 2 +- drivers/acpi/acpica/dbxface.c | 2 +- drivers/acpi/acpica/dsargs.c | 2 +- drivers/acpi/acpica/dscontrol.c | 2 +- drivers/acpi/acpica/dsdebug.c | 2 +- drivers/acpi/acpica/dsfield.c | 2 +- drivers/acpi/acpica/dsinit.c | 2 +- drivers/acpi/acpica/dsmethod.c | 2 +- drivers/acpi/acpica/dsmthdat.c | 2 +- drivers/acpi/acpica/dsobject.c | 2 +- drivers/acpi/acpica/dsopcode.c | 2 +- drivers/acpi/acpica/dspkginit.c | 2 +- drivers/acpi/acpica/dsutils.c | 2 +- drivers/acpi/acpica/dswexec.c | 2 +- drivers/acpi/acpica/dswload.c | 2 +- drivers/acpi/acpica/dswload2.c | 2 +- drivers/acpi/acpica/dswscope.c | 2 +- drivers/acpi/acpica/dswstate.c | 2 +- drivers/acpi/acpica/evevent.c | 2 +- drivers/acpi/acpica/evglock.c | 2 +- drivers/acpi/acpica/evgpe.c | 2 +- drivers/acpi/acpica/evgpeblk.c | 2 +- drivers/acpi/acpica/evgpeinit.c | 2 +- drivers/acpi/acpica/evgpeutil.c | 2 +- drivers/acpi/acpica/evhandler.c | 2 +- drivers/acpi/acpica/evmisc.c | 2 +- drivers/acpi/acpica/evregion.c | 2 +- drivers/acpi/acpica/evrgnini.c | 2 +- drivers/acpi/acpica/evsci.c | 2 +- drivers/acpi/acpica/evxface.c | 2 +- drivers/acpi/acpica/evxfevnt.c | 2 +- drivers/acpi/acpica/evxfgpe.c | 2 +- drivers/acpi/acpica/evxfregn.c | 2 +- drivers/acpi/acpica/exconcat.c | 2 +- drivers/acpi/acpica/exconfig.c | 2 +- drivers/acpi/acpica/exconvrt.c | 2 +- drivers/acpi/acpica/excreate.c | 2 +- drivers/acpi/acpica/exdebug.c | 2 +- drivers/acpi/acpica/exdump.c | 2 +- drivers/acpi/acpica/exfield.c | 2 +- drivers/acpi/acpica/exfldio.c | 2 +- drivers/acpi/acpica/exmisc.c | 2 +- drivers/acpi/acpica/exmutex.c | 2 +- drivers/acpi/acpica/exnames.c | 2 +- drivers/acpi/acpica/exoparg1.c | 2 +- drivers/acpi/acpica/exoparg2.c | 2 +- drivers/acpi/acpica/exoparg3.c | 2 +- drivers/acpi/acpica/exoparg6.c | 2 +- drivers/acpi/acpica/exprep.c | 2 +- drivers/acpi/acpica/exregion.c | 2 +- drivers/acpi/acpica/exresnte.c | 2 +- drivers/acpi/acpica/exresolv.c | 2 +- drivers/acpi/acpica/exresop.c | 2 +- drivers/acpi/acpica/exstore.c | 2 +- drivers/acpi/acpica/exstoren.c | 2 +- drivers/acpi/acpica/exstorob.c | 2 +- drivers/acpi/acpica/exsystem.c | 2 +- drivers/acpi/acpica/extrace.c | 2 +- drivers/acpi/acpica/exutils.c | 2 +- drivers/acpi/acpica/hwacpi.c | 2 +- drivers/acpi/acpica/hwesleep.c | 2 +- drivers/acpi/acpica/hwgpe.c | 2 +- drivers/acpi/acpica/hwpci.c | 2 +- drivers/acpi/acpica/hwregs.c | 2 +- drivers/acpi/acpica/hwsleep.c | 2 +- drivers/acpi/acpica/hwtimer.c | 2 +- drivers/acpi/acpica/hwvalid.c | 2 +- drivers/acpi/acpica/hwxface.c | 2 +- drivers/acpi/acpica/hwxfsleep.c | 2 +- drivers/acpi/acpica/nsaccess.c | 2 +- drivers/acpi/acpica/nsalloc.c | 2 +- drivers/acpi/acpica/nsarguments.c | 2 +- drivers/acpi/acpica/nsconvert.c | 2 +- drivers/acpi/acpica/nsdump.c | 2 +- drivers/acpi/acpica/nsdumpdv.c | 2 +- drivers/acpi/acpica/nseval.c | 2 +- drivers/acpi/acpica/nsinit.c | 2 +- drivers/acpi/acpica/nsload.c | 2 +- drivers/acpi/acpica/nsnames.c | 2 +- drivers/acpi/acpica/nsobject.c | 2 +- drivers/acpi/acpica/nsparse.c | 2 +- drivers/acpi/acpica/nspredef.c | 2 +- drivers/acpi/acpica/nsprepkg.c | 2 +- drivers/acpi/acpica/nsrepair.c | 2 +- drivers/acpi/acpica/nsrepair2.c | 2 +- drivers/acpi/acpica/nssearch.c | 2 +- drivers/acpi/acpica/nsutils.c | 2 +- drivers/acpi/acpica/nswalk.c | 2 +- drivers/acpi/acpica/nsxfeval.c | 2 +- drivers/acpi/acpica/nsxfname.c | 2 +- drivers/acpi/acpica/nsxfobj.c | 2 +- drivers/acpi/acpica/psargs.c | 2 +- drivers/acpi/acpica/psloop.c | 2 +- drivers/acpi/acpica/psobject.c | 2 +- drivers/acpi/acpica/psopcode.c | 2 +- drivers/acpi/acpica/psopinfo.c | 2 +- drivers/acpi/acpica/psparse.c | 2 +- drivers/acpi/acpica/psscope.c | 2 +- drivers/acpi/acpica/pstree.c | 2 +- drivers/acpi/acpica/psutils.c | 2 +- drivers/acpi/acpica/pswalk.c | 2 +- drivers/acpi/acpica/psxface.c | 2 +- drivers/acpi/acpica/rsaddr.c | 2 +- drivers/acpi/acpica/rscalc.c | 2 +- drivers/acpi/acpica/rscreate.c | 2 +- drivers/acpi/acpica/rsdump.c | 2 +- drivers/acpi/acpica/rsdumpinfo.c | 2 +- drivers/acpi/acpica/rsinfo.c | 2 +- drivers/acpi/acpica/rsio.c | 2 +- drivers/acpi/acpica/rsirq.c | 2 +- drivers/acpi/acpica/rslist.c | 2 +- drivers/acpi/acpica/rsmemory.c | 2 +- drivers/acpi/acpica/rsmisc.c | 2 +- drivers/acpi/acpica/rsserial.c | 2 +- drivers/acpi/acpica/rsutils.c | 2 +- drivers/acpi/acpica/rsxface.c | 2 +- drivers/acpi/acpica/tbdata.c | 2 +- drivers/acpi/acpica/tbfadt.c | 2 +- drivers/acpi/acpica/tbfind.c | 2 +- drivers/acpi/acpica/tbinstal.c | 2 +- drivers/acpi/acpica/tbprint.c | 2 +- drivers/acpi/acpica/tbutils.c | 2 +- drivers/acpi/acpica/tbxface.c | 2 +- drivers/acpi/acpica/tbxfload.c | 2 +- drivers/acpi/acpica/tbxfroot.c | 2 +- drivers/acpi/acpica/utaddress.c | 2 +- drivers/acpi/acpica/utalloc.c | 2 +- drivers/acpi/acpica/utascii.c | 2 +- drivers/acpi/acpica/utbuffer.c | 2 +- drivers/acpi/acpica/utcache.c | 2 +- drivers/acpi/acpica/utcopy.c | 2 +- drivers/acpi/acpica/utdebug.c | 2 +- drivers/acpi/acpica/utdecode.c | 2 +- drivers/acpi/acpica/utdelete.c | 2 +- drivers/acpi/acpica/uterror.c | 2 +- drivers/acpi/acpica/uteval.c | 2 +- drivers/acpi/acpica/utexcep.c | 2 +- drivers/acpi/acpica/utglobal.c | 2 +- drivers/acpi/acpica/uthex.c | 2 +- drivers/acpi/acpica/utids.c | 2 +- drivers/acpi/acpica/utinit.c | 2 +- drivers/acpi/acpica/utlock.c | 2 +- drivers/acpi/acpica/utmath.c | 2 +- drivers/acpi/acpica/utmisc.c | 2 +- drivers/acpi/acpica/utmutex.c | 2 +- drivers/acpi/acpica/utnonansi.c | 2 +- drivers/acpi/acpica/utobject.c | 2 +- drivers/acpi/acpica/utosi.c | 2 +- drivers/acpi/acpica/utownerid.c | 2 +- drivers/acpi/acpica/utpredef.c | 2 +- drivers/acpi/acpica/utprint.c | 2 +- drivers/acpi/acpica/utresdecode.c | 2 +- drivers/acpi/acpica/utresrc.c | 2 +- drivers/acpi/acpica/utstate.c | 2 +- drivers/acpi/acpica/utstring.c | 2 +- drivers/acpi/acpica/utstrsuppt.c | 2 +- drivers/acpi/acpica/utstrtoul64.c | 2 +- drivers/acpi/acpica/uttrack.c | 2 +- drivers/acpi/acpica/utuuid.c | 2 +- drivers/acpi/acpica/utxface.c | 2 +- drivers/acpi/acpica/utxferror.c | 2 +- drivers/acpi/acpica/utxfinit.c | 2 +- drivers/acpi/acpica/utxfmutex.c | 2 +- include/acpi/acbuffer.h | 2 +- include/acpi/acconfig.h | 2 +- include/acpi/acexcep.h | 2 +- include/acpi/acnames.h | 2 +- include/acpi/acoutput.h | 2 +- include/acpi/acpi.h | 2 +- include/acpi/acpiosxf.h | 2 +- include/acpi/acpixf.h | 2 +- include/acpi/acrestyp.h | 2 +- include/acpi/actbl.h | 2 +- include/acpi/actbl1.h | 2 +- include/acpi/actbl2.h | 2 +- include/acpi/actbl3.h | 2 +- include/acpi/actypes.h | 2 +- include/acpi/acuuid.h | 2 +- include/acpi/platform/acenv.h | 2 +- include/acpi/platform/acenvex.h | 2 +- include/acpi/platform/acgcc.h | 2 +- include/acpi/platform/acgccex.h | 2 +- include/acpi/platform/acintel.h | 2 +- include/acpi/platform/aclinux.h | 2 +- include/acpi/platform/aclinuxex.h | 2 +- tools/power/acpi/common/cmfsize.c | 2 +- tools/power/acpi/common/getopt.c | 2 +- tools/power/acpi/os_specific/service_layers/oslinuxtbl.c | 2 +- tools/power/acpi/os_specific/service_layers/osunixdir.c | 2 +- tools/power/acpi/os_specific/service_layers/osunixmap.c | 2 +- tools/power/acpi/os_specific/service_layers/osunixxf.c | 2 +- tools/power/acpi/tools/acpidump/acpidump.h | 2 +- tools/power/acpi/tools/acpidump/apdump.c | 2 +- tools/power/acpi/tools/acpidump/apfiles.c | 2 +- tools/power/acpi/tools/acpidump/apmain.c | 2 +- 229 files changed, 230 insertions(+), 230 deletions(-) diff --git a/drivers/acpi/acpica/acapps.h b/drivers/acpi/acpica/acapps.h index 2243c8164b3419..e65478593f9aee 100644 --- a/drivers/acpi/acpica/acapps.h +++ b/drivers/acpi/acpica/acapps.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -51,7 +51,7 @@ /* Common info for tool signons */ #define ACPICA_NAME "Intel ACPI Component Architecture" -#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2017 Intel Corporation" +#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2018 Intel Corporation" #if ACPI_MACHINE_WIDTH == 64 #define ACPI_WIDTH " (64-bit version)" diff --git a/drivers/acpi/acpica/accommon.h b/drivers/acpi/acpica/accommon.h index 49bf47ca54777e..c349ffdf555787 100644 --- a/drivers/acpi/acpica/accommon.h +++ b/drivers/acpi/acpica/accommon.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acconvert.h b/drivers/acpi/acpica/acconvert.h index c84223b60b3563..ce6e8db83e2748 100644 --- a/drivers/acpi/acpica/acconvert.h +++ b/drivers/acpi/acpica/acconvert.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acdebug.h b/drivers/acpi/acpica/acdebug.h index 54b8d9df9423cd..8b2cca5a717b75 100644 --- a/drivers/acpi/acpica/acdebug.h +++ b/drivers/acpi/acpica/acdebug.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acdispat.h b/drivers/acpi/acpica/acdispat.h index f8f3a6e74128a0..fab590bc5fd3e4 100644 --- a/drivers/acpi/acpica/acdispat.h +++ b/drivers/acpi/acpica/acdispat.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index a2adfd42f85ccb..1b0269f6ac2dd9 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index 45ef3f5dc9ad29..27f322b2fed1aa 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index cd722d8edacbb4..3569aa3bf5ee87 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acinterp.h b/drivers/acpi/acpica/acinterp.h index 29555c8789a31e..744374ab928535 100644 --- a/drivers/acpi/acpica/acinterp.h +++ b/drivers/acpi/acpica/acinterp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index a56675f0661eb1..3ba3ff0f1c0422 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acmacros.h b/drivers/acpi/acpica/acmacros.h index 128a3d71b59865..6463340c452202 100644 --- a/drivers/acpi/acpica/acmacros.h +++ b/drivers/acpi/acpica/acmacros.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h index 2fb1bb78d85c60..6c8f364fe2fc59 100644 --- a/drivers/acpi/acpica/acnamesp.h +++ b/drivers/acpi/acpica/acnamesp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h index 5226146190bf92..a1f4d3f385c82a 100644 --- a/drivers/acpi/acpica/acobject.h +++ b/drivers/acpi/acpica/acobject.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acopcode.h b/drivers/acpi/acpica/acopcode.h index cbd59a302679e6..36c2c582598660 100644 --- a/drivers/acpi/acpica/acopcode.h +++ b/drivers/acpi/acpica/acopcode.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h index c23c47328060b7..e25634951d0388 100644 --- a/drivers/acpi/acpica/acparser.h +++ b/drivers/acpi/acpica/acparser.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acpredef.h b/drivers/acpi/acpica/acpredef.h index cdfcad8eb74c8c..7c27bcee6ac754 100644 --- a/drivers/acpi/acpica/acpredef.h +++ b/drivers/acpi/acpica/acpredef.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acresrc.h b/drivers/acpi/acpica/acresrc.h index 438f3098a093a3..20f36949928ac2 100644 --- a/drivers/acpi/acpica/acresrc.h +++ b/drivers/acpi/acpica/acresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acstruct.h b/drivers/acpi/acpica/acstruct.h index 62134bdbeda65f..0338ac32f9c6aa 100644 --- a/drivers/acpi/acpica/acstruct.h +++ b/drivers/acpi/acpica/acstruct.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/actables.h b/drivers/acpi/acpica/actables.h index 84a3ceb6e38426..15b23414245aa5 100644 --- a/drivers/acpi/acpica/actables.h +++ b/drivers/acpi/acpica/actables.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/acutils.h b/drivers/acpi/acpica/acutils.h index b6b29d71782461..00d21d2f766eae 100644 --- a/drivers/acpi/acpica/acutils.h +++ b/drivers/acpi/acpica/acutils.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/amlcode.h b/drivers/acpi/acpica/amlcode.h index f54dc5a34bdc49..b0e9492a6297ee 100644 --- a/drivers/acpi/acpica/amlcode.h +++ b/drivers/acpi/acpica/amlcode.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/amlresrc.h b/drivers/acpi/acpica/amlresrc.h index 1236e9a414e4d4..b680c229ddd592 100644 --- a/drivers/acpi/acpica/amlresrc.h +++ b/drivers/acpi/acpica/amlresrc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbcmds.c b/drivers/acpi/acpica/dbcmds.c index 5984b90eb5907c..4112c85f2aab36 100644 --- a/drivers/acpi/acpica/dbcmds.c +++ b/drivers/acpi/acpica/dbcmds.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbconvert.c b/drivers/acpi/acpica/dbconvert.c index 32d546f0db2f56..27236a6c51ff33 100644 --- a/drivers/acpi/acpica/dbconvert.c +++ b/drivers/acpi/acpica/dbconvert.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbdisply.c b/drivers/acpi/acpica/dbdisply.c index 5a606eac0c2243..7df920cda77dd3 100644 --- a/drivers/acpi/acpica/dbdisply.c +++ b/drivers/acpi/acpica/dbdisply.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbexec.c b/drivers/acpi/acpica/dbexec.c index ed088fceb18d3c..8ad9e6d9e54b3a 100644 --- a/drivers/acpi/acpica/dbexec.c +++ b/drivers/acpi/acpica/dbexec.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbfileio.c b/drivers/acpi/acpica/dbfileio.c index cf9607945704cf..084bb332f8e26f 100644 --- a/drivers/acpi/acpica/dbfileio.c +++ b/drivers/acpi/acpica/dbfileio.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbhistry.c b/drivers/acpi/acpica/dbhistry.c index 7d08974c64c2c8..55c0f2742339e1 100644 --- a/drivers/acpi/acpica/dbhistry.c +++ b/drivers/acpi/acpica/dbhistry.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbinput.c b/drivers/acpi/acpica/dbinput.c index 954ca3b981a732..f7c661e06f379e 100644 --- a/drivers/acpi/acpica/dbinput.c +++ b/drivers/acpi/acpica/dbinput.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbmethod.c b/drivers/acpi/acpica/dbmethod.c index df62c9245efc24..2cda0bff6f2cd4 100644 --- a/drivers/acpi/acpica/dbmethod.c +++ b/drivers/acpi/acpica/dbmethod.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbnames.c b/drivers/acpi/acpica/dbnames.c index 8c207c77251797..8796fc1e0360e4 100644 --- a/drivers/acpi/acpica/dbnames.c +++ b/drivers/acpi/acpica/dbnames.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbobject.c b/drivers/acpi/acpica/dbobject.c index e7b415c20aa88a..d2063cbab39af4 100644 --- a/drivers/acpi/acpica/dbobject.c +++ b/drivers/acpi/acpica/dbobject.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbstats.c b/drivers/acpi/acpica/dbstats.c index 99fb0160b8fb5c..d6aaef54e36935 100644 --- a/drivers/acpi/acpica/dbstats.c +++ b/drivers/acpi/acpica/dbstats.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbtest.c b/drivers/acpi/acpica/dbtest.c index c6bee6143266b6..56e446b89d18b7 100644 --- a/drivers/acpi/acpica/dbtest.c +++ b/drivers/acpi/acpica/dbtest.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbutils.c b/drivers/acpi/acpica/dbutils.c index bfa972b6417196..cd40854ee9be67 100644 --- a/drivers/acpi/acpica/dbutils.c +++ b/drivers/acpi/acpica/dbutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dbxface.c b/drivers/acpi/acpica/dbxface.c index b6985323e7eb9a..77bbfa97cf9135 100644 --- a/drivers/acpi/acpica/dbxface.c +++ b/drivers/acpi/acpica/dbxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsargs.c b/drivers/acpi/acpica/dsargs.c index 2873455c986d7b..04a9f60e7ad101 100644 --- a/drivers/acpi/acpica/dsargs.c +++ b/drivers/acpi/acpica/dsargs.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dscontrol.c b/drivers/acpi/acpica/dscontrol.c index 4b6ebc2a285104..606697e741a513 100644 --- a/drivers/acpi/acpica/dscontrol.c +++ b/drivers/acpi/acpica/dscontrol.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsdebug.c b/drivers/acpi/acpica/dsdebug.c index d1f457eda98051..14ec52eba40873 100644 --- a/drivers/acpi/acpica/dsdebug.c +++ b/drivers/acpi/acpica/dsdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c index 0cab34a593d504..95ea639a942422 100644 --- a/drivers/acpi/acpica/dsfield.c +++ b/drivers/acpi/acpica/dsfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsinit.c b/drivers/acpi/acpica/dsinit.c index b1842dd4edf7e3..946ff2e130d93d 100644 --- a/drivers/acpi/acpica/dsinit.c +++ b/drivers/acpi/acpica/dsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c index d7fc36917c6714..b9c460c2d76360 100644 --- a/drivers/acpi/acpica/dsmethod.c +++ b/drivers/acpi/acpica/dsmethod.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsmthdat.c b/drivers/acpi/acpica/dsmthdat.c index 27a7de95f7b0ac..157f1645d91a57 100644 --- a/drivers/acpi/acpica/dsmthdat.c +++ b/drivers/acpi/acpica/dsmthdat.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsobject.c b/drivers/acpi/acpica/dsobject.c index b21fe084ffc8cd..4fa3400a95ba02 100644 --- a/drivers/acpi/acpica/dsobject.c +++ b/drivers/acpi/acpica/dsobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 0336df7ac47dd1..0181cd31775112 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dspkginit.c b/drivers/acpi/acpica/dspkginit.c index 5a602b75084ef8..902bee78036c2f 100644 --- a/drivers/acpi/acpica/dspkginit.c +++ b/drivers/acpi/acpica/dspkginit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dsutils.c b/drivers/acpi/acpica/dsutils.c index 4c5faf629a8318..a4ce0b4a55a61f 100644 --- a/drivers/acpi/acpica/dsutils.c +++ b/drivers/acpi/acpica/dsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswexec.c b/drivers/acpi/acpica/dswexec.c index 22f45d09073324..2c07d220a50fea 100644 --- a/drivers/acpi/acpica/dswexec.c +++ b/drivers/acpi/acpica/dswexec.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 5771e4e4a99af2..fa4ef9229e1716 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c index b3d0aaec8203a0..3b1313ba60d0a1 100644 --- a/drivers/acpi/acpica/dswload2.c +++ b/drivers/acpi/acpica/dswload2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswscope.c b/drivers/acpi/acpica/dswscope.c index 3e081983d2ee62..8b5c3613c06087 100644 --- a/drivers/acpi/acpica/dswscope.c +++ b/drivers/acpi/acpica/dswscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/dswstate.c b/drivers/acpi/acpica/dswstate.c index da111a1f5bfbc3..ee002d17526e0e 100644 --- a/drivers/acpi/acpica/dswstate.c +++ b/drivers/acpi/acpica/dswstate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evevent.c b/drivers/acpi/acpica/evevent.c index d3b6b314fa5070..4b2b0b44a16b6a 100644 --- a/drivers/acpi/acpica/evevent.c +++ b/drivers/acpi/acpica/evevent.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evglock.c b/drivers/acpi/acpica/evglock.c index 0ce33b0f430c4d..012b80de150136 100644 --- a/drivers/acpi/acpica/evglock.c +++ b/drivers/acpi/acpica/evglock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index 263d8fc4a9e2f8..410a3907c0518a 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 3a3cb8624f4195..7ce756cc28abb4 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c index 8649c6242478ef..8ad4816c995006 100644 --- a/drivers/acpi/acpica/evgpeinit.c +++ b/drivers/acpi/acpica/evgpeinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evgpeutil.c b/drivers/acpi/acpica/evgpeutil.c index c8adb400330af8..729a8960a3af4a 100644 --- a/drivers/acpi/acpica/evgpeutil.c +++ b/drivers/acpi/acpica/evgpeutil.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evhandler.c b/drivers/acpi/acpica/evhandler.c index 2db61ef1b4a3bf..20fb51c06b8dde 100644 --- a/drivers/acpi/acpica/evhandler.c +++ b/drivers/acpi/acpica/evhandler.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evmisc.c b/drivers/acpi/acpica/evmisc.c index 4f6bb3f016abdb..40d0b1f541a04f 100644 --- a/drivers/acpi/acpica/evmisc.c +++ b/drivers/acpi/acpica/evmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index bb58419f0d610e..de196c8e3f3048 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evrgnini.c b/drivers/acpi/acpica/evrgnini.c index 93ec528bcd9a96..4187f563fede2f 100644 --- a/drivers/acpi/acpica/evrgnini.c +++ b/drivers/acpi/acpica/evrgnini.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evsci.c b/drivers/acpi/acpica/evsci.c index 8ce73b962006fb..d5594f79f877a4 100644 --- a/drivers/acpi/acpica/evsci.c +++ b/drivers/acpi/acpica/evsci.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evxface.c b/drivers/acpi/acpica/evxface.c index dd1b9dd64cef8e..9b3c01bf1438ec 100644 --- a/drivers/acpi/acpica/evxface.c +++ b/drivers/acpi/acpica/evxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index c773ac4892cb72..96c2520f957060 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evxfgpe.c b/drivers/acpi/acpica/evxfgpe.c index 67c7c4ce276c7b..cbb1598df9dcfc 100644 --- a/drivers/acpi/acpica/evxfgpe.c +++ b/drivers/acpi/acpica/evxfgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c index beba9d56a0d871..705fcd86151ae1 100644 --- a/drivers/acpi/acpica/evxfregn.c +++ b/drivers/acpi/acpica/evxfregn.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exconcat.c b/drivers/acpi/acpica/exconcat.c index 59b8de2f07d391..ea20e10dd1f2be 100644 --- a/drivers/acpi/acpica/exconcat.c +++ b/drivers/acpi/acpica/exconcat.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 61813bd43f9e42..827f47b726632f 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exconvrt.c b/drivers/acpi/acpica/exconvrt.c index 23ebadb06a95b2..9abcc41a573bf3 100644 --- a/drivers/acpi/acpica/exconvrt.c +++ b/drivers/acpi/acpica/exconvrt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/excreate.c b/drivers/acpi/acpica/excreate.c index b8adb11f1b075a..3dece45dd997eb 100644 --- a/drivers/acpi/acpica/excreate.c +++ b/drivers/acpi/acpica/excreate.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exdebug.c b/drivers/acpi/acpica/exdebug.c index a8191d2ca5e36d..d931a66a16e3c4 100644 --- a/drivers/acpi/acpica/exdebug.c +++ b/drivers/acpi/acpica/exdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exdump.c b/drivers/acpi/acpica/exdump.c index b2ff61bdb9a8fe..4989ce9591aef0 100644 --- a/drivers/acpi/acpica/exdump.c +++ b/drivers/acpi/acpica/exdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exfield.c b/drivers/acpi/acpica/exfield.c index 5fda981f649886..e3b0650e5bb63c 100644 --- a/drivers/acpi/acpica/exfield.c +++ b/drivers/acpi/acpica/exfield.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exfldio.c b/drivers/acpi/acpica/exfldio.c index a656608dca8497..3d0f274be88b29 100644 --- a/drivers/acpi/acpica/exfldio.c +++ b/drivers/acpi/acpica/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exmisc.c b/drivers/acpi/acpica/exmisc.c index dbad3ebd7df504..1518fcb22ae12b 100644 --- a/drivers/acpi/acpica/exmisc.c +++ b/drivers/acpi/acpica/exmisc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exmutex.c b/drivers/acpi/acpica/exmutex.c index ecd95b3f35f195..24c9741dee4820 100644 --- a/drivers/acpi/acpica/exmutex.c +++ b/drivers/acpi/acpica/exmutex.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exnames.c b/drivers/acpi/acpica/exnames.c index caa5ed1f65eca2..c7b249cda5c0e4 100644 --- a/drivers/acpi/acpica/exnames.c +++ b/drivers/acpi/acpica/exnames.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg1.c b/drivers/acpi/acpica/exoparg1.c index f787651348c117..dae01c93e4800d 100644 --- a/drivers/acpi/acpica/exoparg1.c +++ b/drivers/acpi/acpica/exoparg1.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg2.c b/drivers/acpi/acpica/exoparg2.c index 57980b7d35940a..3cafa1d6f31a5c 100644 --- a/drivers/acpi/acpica/exoparg2.c +++ b/drivers/acpi/acpica/exoparg2.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg3.c b/drivers/acpi/acpica/exoparg3.c index ce857addc8dbd6..f16c655121ffd0 100644 --- a/drivers/acpi/acpica/exoparg3.c +++ b/drivers/acpi/acpica/exoparg3.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exoparg6.c b/drivers/acpi/acpica/exoparg6.c index 688032b58a213b..8b39fffce6dcde 100644 --- a/drivers/acpi/acpica/exoparg6.c +++ b/drivers/acpi/acpica/exoparg6.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exprep.c b/drivers/acpi/acpica/exprep.c index 8de060664204ec..1d1040f2e3f875 100644 --- a/drivers/acpi/acpica/exprep.c +++ b/drivers/acpi/acpica/exprep.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 7bcc9d809b7e97..387c438aa4853e 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exresnte.c b/drivers/acpi/acpica/exresnte.c index 91c1de046442f6..77fa8d9aa5bf77 100644 --- a/drivers/acpi/acpica/exresnte.c +++ b/drivers/acpi/acpica/exresnte.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exresolv.c b/drivers/acpi/acpica/exresolv.c index 5e1854ea85f602..b104bc3ca809b1 100644 --- a/drivers/acpi/acpica/exresolv.c +++ b/drivers/acpi/acpica/exresolv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exresop.c b/drivers/acpi/acpica/exresop.c index 1c7c9962b0de7f..2643d34f194d97 100644 --- a/drivers/acpi/acpica/exresop.c +++ b/drivers/acpi/acpica/exresop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exstore.c b/drivers/acpi/acpica/exstore.c index bdd43cde8f3641..8f106bdcad5fb4 100644 --- a/drivers/acpi/acpica/exstore.c +++ b/drivers/acpi/acpica/exstore.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exstoren.c b/drivers/acpi/acpica/exstoren.c index 56f59cf5da2934..3d458d1996b0f5 100644 --- a/drivers/acpi/acpica/exstoren.c +++ b/drivers/acpi/acpica/exstoren.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exstorob.c b/drivers/acpi/acpica/exstorob.c index 4ba7fcbf23b052..905443a3c28f7d 100644 --- a/drivers/acpi/acpica/exstorob.c +++ b/drivers/acpi/acpica/exstorob.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exsystem.c b/drivers/acpi/acpica/exsystem.c index ad3b610057f3de..420d9b145d2ed8 100644 --- a/drivers/acpi/acpica/exsystem.c +++ b/drivers/acpi/acpica/exsystem.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/extrace.c b/drivers/acpi/acpica/extrace.c index ae9df8672d9ef6..9a67d507a132f1 100644 --- a/drivers/acpi/acpica/extrace.c +++ b/drivers/acpi/acpica/extrace.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/exutils.c b/drivers/acpi/acpica/exutils.c index 34d608358eaf04..fb80d3f55d63f9 100644 --- a/drivers/acpi/acpica/exutils.c +++ b/drivers/acpi/acpica/exutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index fad249e774b41a..68e958d4c25f21 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwesleep.c b/drivers/acpi/acpica/hwesleep.c index 12626d021a9b5e..64855b62a5aeba 100644 --- a/drivers/acpi/acpica/hwesleep.c +++ b/drivers/acpi/acpica/hwesleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwgpe.c b/drivers/acpi/acpica/hwgpe.c index 09b6822aa5cc25..c1c54af148d0b5 100644 --- a/drivers/acpi/acpica/hwgpe.c +++ b/drivers/acpi/acpica/hwgpe.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwpci.c b/drivers/acpi/acpica/hwpci.c index 283819930be6b5..faa2fa45eb1c80 100644 --- a/drivers/acpi/acpica/hwpci.c +++ b/drivers/acpi/acpica/hwpci.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index aa6e0008191550..f3e7b7851a3a16 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 1fe7387a00e678..c85c373ecbc4e3 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwtimer.c b/drivers/acpi/acpica/hwtimer.c index 5b4282902a839d..511e3b8ffc6d9a 100644 --- a/drivers/acpi/acpica/hwtimer.c +++ b/drivers/acpi/acpica/hwtimer.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c index d1679035d5f31b..65d82e6add0b1d 100644 --- a/drivers/acpi/acpica/hwvalid.c +++ b/drivers/acpi/acpica/hwvalid.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index b3c6e439933c56..d320b129b7d7d5 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/hwxfsleep.c b/drivers/acpi/acpica/hwxfsleep.c index e5c095ca6083a9..589c774bbf9a71 100644 --- a/drivers/acpi/acpica/hwxfsleep.c +++ b/drivers/acpi/acpica/hwxfsleep.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsaccess.c b/drivers/acpi/acpica/nsaccess.c index 33e652a12fca53..07f672b5a1d1b3 100644 --- a/drivers/acpi/acpica/nsaccess.c +++ b/drivers/acpi/acpica/nsaccess.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsalloc.c b/drivers/acpi/acpica/nsalloc.c index 8ba5b32c9f7173..ce57ccf4c1bf1f 100644 --- a/drivers/acpi/acpica/nsalloc.c +++ b/drivers/acpi/acpica/nsalloc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsarguments.c b/drivers/acpi/acpica/nsarguments.c index 67b7370dcae520..ce296ac14cf06f 100644 --- a/drivers/acpi/acpica/nsarguments.c +++ b/drivers/acpi/acpica/nsarguments.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsconvert.c b/drivers/acpi/acpica/nsconvert.c index d55dcc82f4348f..2f9d5d190fa96a 100644 --- a/drivers/acpi/acpica/nsconvert.c +++ b/drivers/acpi/acpica/nsconvert.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsdump.c b/drivers/acpi/acpica/nsdump.c index 4123b5077a7d4e..e2ac16818dc3b2 100644 --- a/drivers/acpi/acpica/nsdump.c +++ b/drivers/acpi/acpica/nsdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsdumpdv.c b/drivers/acpi/acpica/nsdumpdv.c index 5026594763eaf0..09ac00dee45063 100644 --- a/drivers/acpi/acpica/nsdumpdv.c +++ b/drivers/acpi/acpica/nsdumpdv.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c index d22167cbd0ca65..c2d883b8c45e9e 100644 --- a/drivers/acpi/acpica/nseval.c +++ b/drivers/acpi/acpica/nseval.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsinit.c b/drivers/acpi/acpica/nsinit.c index 9c629794971221..c17af4a3ab6798 100644 --- a/drivers/acpi/acpica/nsinit.c +++ b/drivers/acpi/acpica/nsinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsload.c b/drivers/acpi/acpica/nsload.c index d2915e186ae14a..fdfe9309bd330c 100644 --- a/drivers/acpi/acpica/nsload.c +++ b/drivers/acpi/acpica/nsload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsnames.c b/drivers/acpi/acpica/nsnames.c index 22c92d1a24d8f8..c686eda7ca66f7 100644 --- a/drivers/acpi/acpica/nsnames.c +++ b/drivers/acpi/acpica/nsnames.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsobject.c b/drivers/acpi/acpica/nsobject.c index 707b2aa501e1b4..757e44555ec302 100644 --- a/drivers/acpi/acpica/nsobject.c +++ b/drivers/acpi/acpica/nsobject.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsparse.c b/drivers/acpi/acpica/nsparse.c index 2fc33a5203f40a..c5b22ea5b3695d 100644 --- a/drivers/acpi/acpica/nsparse.c +++ b/drivers/acpi/acpica/nsparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nspredef.c b/drivers/acpi/acpica/nspredef.c index 9d14b509529e30..4f1f6d6d9ddffc 100644 --- a/drivers/acpi/acpica/nspredef.c +++ b/drivers/acpi/acpica/nspredef.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsprepkg.c b/drivers/acpi/acpica/nsprepkg.c index a8ea8fb1d29946..7805d5ce81272d 100644 --- a/drivers/acpi/acpica/nsprepkg.c +++ b/drivers/acpi/acpica/nsprepkg.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsrepair.c b/drivers/acpi/acpica/nsrepair.c index 418ef2ac82abed..7b6b6d281f1cb5 100644 --- a/drivers/acpi/acpica/nsrepair.c +++ b/drivers/acpi/acpica/nsrepair.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsrepair2.c b/drivers/acpi/acpica/nsrepair2.c index 06037e04469413..29c3973c781531 100644 --- a/drivers/acpi/acpica/nsrepair2.c +++ b/drivers/acpi/acpica/nsrepair2.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nssearch.c b/drivers/acpi/acpica/nssearch.c index e91dbee9235f36..a469447f5c02d8 100644 --- a/drivers/acpi/acpica/nssearch.c +++ b/drivers/acpi/acpica/nssearch.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsutils.c b/drivers/acpi/acpica/nsutils.c index b43fe5fce64baa..0487fdb59b0ee8 100644 --- a/drivers/acpi/acpica/nsutils.c +++ b/drivers/acpi/acpica/nsutils.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nswalk.c b/drivers/acpi/acpica/nswalk.c index 6b6e6f498cffb6..dd7ae1bc8af8c1 100644 --- a/drivers/acpi/acpica/nswalk.c +++ b/drivers/acpi/acpica/nswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsxfeval.c b/drivers/acpi/acpica/nsxfeval.c index 9b51f65823b294..1075bd9541f563 100644 --- a/drivers/acpi/acpica/nsxfeval.c +++ b/drivers/acpi/acpica/nsxfeval.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsxfname.c b/drivers/acpi/acpica/nsxfname.c index 10696623580505..e9603fc9586ce7 100644 --- a/drivers/acpi/acpica/nsxfname.c +++ b/drivers/acpi/acpica/nsxfname.c @@ -6,7 +6,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/nsxfobj.c b/drivers/acpi/acpica/nsxfobj.c index 47f689ec3fcbca..ac1fbf767cac31 100644 --- a/drivers/acpi/acpica/nsxfobj.c +++ b/drivers/acpi/acpica/nsxfobj.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psargs.c b/drivers/acpi/acpica/psargs.c index 171e2faa7c5064..dbc51bc5fdd67a 100644 --- a/drivers/acpi/acpica/psargs.c +++ b/drivers/acpi/acpica/psargs.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c index bb04dec168ad72..7dca287d7690a5 100644 --- a/drivers/acpi/acpica/psloop.c +++ b/drivers/acpi/acpica/psloop.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psobject.c b/drivers/acpi/acpica/psobject.c index c0b179883ff25f..b18f1e04898547 100644 --- a/drivers/acpi/acpica/psobject.c +++ b/drivers/acpi/acpica/psobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psopcode.c b/drivers/acpi/acpica/psopcode.c index a402ad772a1e5f..d31f3eb232254c 100644 --- a/drivers/acpi/acpica/psopcode.c +++ b/drivers/acpi/acpica/psopcode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psopinfo.c b/drivers/acpi/acpica/psopinfo.c index eff22950232b64..1dc1fc79297eb0 100644 --- a/drivers/acpi/acpica/psopinfo.c +++ b/drivers/acpi/acpica/psopinfo.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psparse.c b/drivers/acpi/acpica/psparse.c index ac88319dc11142..2474ff96129407 100644 --- a/drivers/acpi/acpica/psparse.c +++ b/drivers/acpi/acpica/psparse.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psscope.c b/drivers/acpi/acpica/psscope.c index 22d7f1d6849b31..f49cdcc65700a6 100644 --- a/drivers/acpi/acpica/psscope.c +++ b/drivers/acpi/acpica/psscope.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/pstree.c b/drivers/acpi/acpica/pstree.c index c06d6e2fc7a5d0..f9fa88c79b32df 100644 --- a/drivers/acpi/acpica/pstree.c +++ b/drivers/acpi/acpica/pstree.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psutils.c b/drivers/acpi/acpica/psutils.c index cd59dfe6a47d91..fe151f42de3a5b 100644 --- a/drivers/acpi/acpica/psutils.c +++ b/drivers/acpi/acpica/psutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/pswalk.c b/drivers/acpi/acpica/pswalk.c index 22a37c82af19ac..bc5c779e54e80a 100644 --- a/drivers/acpi/acpica/pswalk.c +++ b/drivers/acpi/acpica/pswalk.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c index c88a681586bf3b..d2270ade5cf824 100644 --- a/drivers/acpi/acpica/psxface.c +++ b/drivers/acpi/acpica/psxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsaddr.c b/drivers/acpi/acpica/rsaddr.c index a131a28bb09d6d..213bad89675b77 100644 --- a/drivers/acpi/acpica/rsaddr.c +++ b/drivers/acpi/acpica/rsaddr.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rscalc.c b/drivers/acpi/acpica/rscalc.c index 659fb718504a66..576f7aae162b4d 100644 --- a/drivers/acpi/acpica/rscalc.c +++ b/drivers/acpi/acpica/rscalc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rscreate.c b/drivers/acpi/acpica/rscreate.c index f72ff0b54a639d..fe07001ea8651e 100644 --- a/drivers/acpi/acpica/rscreate.c +++ b/drivers/acpi/acpica/rscreate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsdump.c b/drivers/acpi/acpica/rsdump.c index 55fd1880efbec2..bc4c4755aeb9ed 100644 --- a/drivers/acpi/acpica/rsdump.c +++ b/drivers/acpi/acpica/rsdump.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsdumpinfo.c b/drivers/acpi/acpica/rsdumpinfo.c index da150e17795b9f..c4a2a08e31acc7 100644 --- a/drivers/acpi/acpica/rsdumpinfo.c +++ b/drivers/acpi/acpica/rsdumpinfo.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsinfo.c b/drivers/acpi/acpica/rsinfo.c index b0e50518d76663..e819bb0f45af53 100644 --- a/drivers/acpi/acpica/rsinfo.c +++ b/drivers/acpi/acpica/rsinfo.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsio.c b/drivers/acpi/acpica/rsio.c index b7a47fbc519b65..eafd993592f6ac 100644 --- a/drivers/acpi/acpica/rsio.c +++ b/drivers/acpi/acpica/rsio.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsirq.c b/drivers/acpi/acpica/rsirq.c index 092a733c42b80f..aabd73298eb8bb 100644 --- a/drivers/acpi/acpica/rsirq.c +++ b/drivers/acpi/acpica/rsirq.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rslist.c b/drivers/acpi/acpica/rslist.c index 36a6657dd34d21..11214780ea8fda 100644 --- a/drivers/acpi/acpica/rslist.c +++ b/drivers/acpi/acpica/rslist.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsmemory.c b/drivers/acpi/acpica/rsmemory.c index 273eecb3001b42..05e375abc6b566 100644 --- a/drivers/acpi/acpica/rsmemory.c +++ b/drivers/acpi/acpica/rsmemory.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsmisc.c b/drivers/acpi/acpica/rsmisc.c index cc4b5486c4bcc8..7b4627181cc6f1 100644 --- a/drivers/acpi/acpica/rsmisc.c +++ b/drivers/acpi/acpica/rsmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsserial.c b/drivers/acpi/acpica/rsserial.c index 14d12d6eb716f8..87dac2812072bf 100644 --- a/drivers/acpi/acpica/rsserial.c +++ b/drivers/acpi/acpica/rsserial.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsutils.c b/drivers/acpi/acpica/rsutils.c index b2aeca01204a09..49ff7f851d58c4 100644 --- a/drivers/acpi/acpica/rsutils.c +++ b/drivers/acpi/acpica/rsutils.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/rsxface.c b/drivers/acpi/acpica/rsxface.c index be65e65e216ebe..3b481f0b81c571 100644 --- a/drivers/acpi/acpica/rsxface.c +++ b/drivers/acpi/acpica/rsxface.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbdata.c b/drivers/acpi/acpica/tbdata.c index b19a2f0ea331db..ec69267f1447a2 100644 --- a/drivers/acpi/acpica/tbdata.c +++ b/drivers/acpi/acpica/tbdata.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbfadt.c b/drivers/acpi/acpica/tbfadt.c index 5f051d82188d13..d1763c5e4e9131 100644 --- a/drivers/acpi/acpica/tbfadt.c +++ b/drivers/acpi/acpica/tbfadt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbfind.c b/drivers/acpi/acpica/tbfind.c index fea89c8d305cb4..999a64a48e1a2a 100644 --- a/drivers/acpi/acpica/tbfind.c +++ b/drivers/acpi/acpica/tbfind.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbinstal.c b/drivers/acpi/acpica/tbinstal.c index 0dfc0ac3c141f1..00be16da1ee2c2 100644 --- a/drivers/acpi/acpica/tbinstal.c +++ b/drivers/acpi/acpica/tbinstal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbprint.c b/drivers/acpi/acpica/tbprint.c index edfd7b10be19f2..8cdcdd2c46975d 100644 --- a/drivers/acpi/acpica/tbprint.c +++ b/drivers/acpi/acpica/tbprint.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbutils.c b/drivers/acpi/acpica/tbutils.c index 0c6768d2039580..30d40ff8992b49 100644 --- a/drivers/acpi/acpica/tbutils.c +++ b/drivers/acpi/acpica/tbutils.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbxface.c b/drivers/acpi/acpica/tbxface.c index 5ecb8d2e683479..dca91b6f8cc2b8 100644 --- a/drivers/acpi/acpica/tbxface.c +++ b/drivers/acpi/acpica/tbxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbxfload.c b/drivers/acpi/acpica/tbxfload.c index d81f442228b8b9..e09b4b26300e74 100644 --- a/drivers/acpi/acpica/tbxfload.c +++ b/drivers/acpi/acpica/tbxfload.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/tbxfroot.c b/drivers/acpi/acpica/tbxfroot.c index f9f9a7da2cadee..abf3c62e1e800e 100644 --- a/drivers/acpi/acpica/tbxfroot.c +++ b/drivers/acpi/acpica/tbxfroot.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utaddress.c b/drivers/acpi/acpica/utaddress.c index 26a0633115be33..d8540f380ae5ff 100644 --- a/drivers/acpi/acpica/utaddress.c +++ b/drivers/acpi/acpica/utaddress.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utalloc.c b/drivers/acpi/acpica/utalloc.c index 5594a359dbf178..12fbaddbfb0db1 100644 --- a/drivers/acpi/acpica/utalloc.c +++ b/drivers/acpi/acpica/utalloc.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utascii.c b/drivers/acpi/acpica/utascii.c index 909bdb19865158..95565e46a69561 100644 --- a/drivers/acpi/acpica/utascii.c +++ b/drivers/acpi/acpica/utascii.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utbuffer.c b/drivers/acpi/acpica/utbuffer.c index f17eaa009dde75..2c5a14c2f46bd0 100644 --- a/drivers/acpi/acpica/utbuffer.c +++ b/drivers/acpi/acpica/utbuffer.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utcache.c b/drivers/acpi/acpica/utcache.c index 531493306dee92..08e6944404b3eb 100644 --- a/drivers/acpi/acpica/utcache.c +++ b/drivers/acpi/acpica/utcache.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utcopy.c b/drivers/acpi/acpica/utcopy.c index e9382255d6c6cc..01434af99035d4 100644 --- a/drivers/acpi/acpica/utcopy.c +++ b/drivers/acpi/acpica/utcopy.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utdebug.c b/drivers/acpi/acpica/utdebug.c index cff7154b7feeae..2201be1bf4c292 100644 --- a/drivers/acpi/acpica/utdebug.c +++ b/drivers/acpi/acpica/utdebug.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utdecode.c b/drivers/acpi/acpica/utdecode.c index 55debbad487dc7..1a3f316a18a8e6 100644 --- a/drivers/acpi/acpica/utdecode.c +++ b/drivers/acpi/acpica/utdecode.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utdelete.c b/drivers/acpi/acpica/utdelete.c index c6eb9fae70f9a6..7d8d0208f0a351 100644 --- a/drivers/acpi/acpica/utdelete.c +++ b/drivers/acpi/acpica/utdelete.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/uterror.c b/drivers/acpi/acpica/uterror.c index 42388dcb5ccc9f..ce5e891291bf8d 100644 --- a/drivers/acpi/acpica/uterror.c +++ b/drivers/acpi/acpica/uterror.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 3fce7519c6902f..b8be0b82a130eb 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utexcep.c b/drivers/acpi/acpica/utexcep.c index eb6dcab33d2f89..e3dbad8b73e568 100644 --- a/drivers/acpi/acpica/utexcep.c +++ b/drivers/acpi/acpica/utexcep.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 230a50c82f22c4..933595b0e59425 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/uthex.c b/drivers/acpi/acpica/uthex.c index fb406daf47fac9..f5886d557a9427 100644 --- a/drivers/acpi/acpica/uthex.c +++ b/drivers/acpi/acpica/uthex.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utids.c b/drivers/acpi/acpica/utids.c index a6eb580ee21d7a..db3c3c1d33da11 100644 --- a/drivers/acpi/acpica/utids.c +++ b/drivers/acpi/acpica/utids.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utinit.c b/drivers/acpi/acpica/utinit.c index 45eeb0dcf283b7..a2005b03034743 100644 --- a/drivers/acpi/acpica/utinit.c +++ b/drivers/acpi/acpica/utinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utlock.c b/drivers/acpi/acpica/utlock.c index db2d9910866ee2..0636074a4c23fd 100644 --- a/drivers/acpi/acpica/utlock.c +++ b/drivers/acpi/acpica/utlock.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utmath.c b/drivers/acpi/acpica/utmath.c index 2055a858e5f596..eddf719904331a 100644 --- a/drivers/acpi/acpica/utmath.c +++ b/drivers/acpi/acpica/utmath.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utmisc.c b/drivers/acpi/acpica/utmisc.c index 45c78c2adbf0f2..a331313ad5fa2d 100644 --- a/drivers/acpi/acpica/utmisc.c +++ b/drivers/acpi/acpica/utmisc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utmutex.c b/drivers/acpi/acpica/utmutex.c index 524ba931d5e834..6767bd1626f709 100644 --- a/drivers/acpi/acpica/utmutex.c +++ b/drivers/acpi/acpica/utmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utnonansi.c b/drivers/acpi/acpica/utnonansi.c index 33a0970646df53..94219610e259ea 100644 --- a/drivers/acpi/acpica/utnonansi.c +++ b/drivers/acpi/acpica/utnonansi.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utobject.c b/drivers/acpi/acpica/utobject.c index cb3db9fed50d1d..375901c0a596ee 100644 --- a/drivers/acpi/acpica/utobject.c +++ b/drivers/acpi/acpica/utobject.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utosi.c b/drivers/acpi/acpica/utosi.c index f6b8dd24b006c0..00ea104f6a0a9a 100644 --- a/drivers/acpi/acpica/utosi.c +++ b/drivers/acpi/acpica/utosi.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utownerid.c b/drivers/acpi/acpica/utownerid.c index 1b3ee74a87ebf6..9923dfa708be84 100644 --- a/drivers/acpi/acpica/utownerid.c +++ b/drivers/acpi/acpica/utownerid.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utpredef.c b/drivers/acpi/acpica/utpredef.c index 350709f23e4cf7..ae6fef02b692bd 100644 --- a/drivers/acpi/acpica/utpredef.c +++ b/drivers/acpi/acpica/utpredef.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utprint.c b/drivers/acpi/acpica/utprint.c index c008589b41bd9c..ac07700f5b7991 100644 --- a/drivers/acpi/acpica/utprint.c +++ b/drivers/acpi/acpica/utprint.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utresdecode.c b/drivers/acpi/acpica/utresdecode.c index e15a2538558b3f..93fa3450ca8849 100644 --- a/drivers/acpi/acpica/utresdecode.c +++ b/drivers/acpi/acpica/utresdecode.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utresrc.c b/drivers/acpi/acpica/utresrc.c index f9801d13547fe5..4d289d9c734cfb 100644 --- a/drivers/acpi/acpica/utresrc.c +++ b/drivers/acpi/acpica/utresrc.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utstate.c b/drivers/acpi/acpica/utstate.c index eafabcd2fada3c..7750c48739d8cd 100644 --- a/drivers/acpi/acpica/utstate.c +++ b/drivers/acpi/acpica/utstate.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utstring.c b/drivers/acpi/acpica/utstring.c index 9eacbcb9e4f457..a9507d1976ffac 100644 --- a/drivers/acpi/acpica/utstring.c +++ b/drivers/acpi/acpica/utstring.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utstrsuppt.c b/drivers/acpi/acpica/utstrsuppt.c index 97f48d71f9e603..6fc76f0b60e9d1 100644 --- a/drivers/acpi/acpica/utstrsuppt.c +++ b/drivers/acpi/acpica/utstrsuppt.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utstrtoul64.c b/drivers/acpi/acpica/utstrtoul64.c index e2067dcb93893c..9f7cef1de34aa2 100644 --- a/drivers/acpi/acpica/utstrtoul64.c +++ b/drivers/acpi/acpica/utstrtoul64.c @@ -6,7 +6,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/uttrack.c b/drivers/acpi/acpica/uttrack.c index 633b4e2c669f65..8cc70ca4e0fb8f 100644 --- a/drivers/acpi/acpica/uttrack.c +++ b/drivers/acpi/acpica/uttrack.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utuuid.c b/drivers/acpi/acpica/utuuid.c index 5028e06718b1c2..95946fdb55d5b2 100644 --- a/drivers/acpi/acpica/utuuid.c +++ b/drivers/acpi/acpica/utuuid.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c index 6b9ba4029f8e96..25ef2ce6460368 100644 --- a/drivers/acpi/acpica/utxface.c +++ b/drivers/acpi/acpica/utxface.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utxferror.c b/drivers/acpi/acpica/utxferror.c index 9da4f8ef2e77ba..a78861ded8940a 100644 --- a/drivers/acpi/acpica/utxferror.c +++ b/drivers/acpi/acpica/utxferror.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utxfinit.c b/drivers/acpi/acpica/utxfinit.c index 6d5180601cf2a3..e727db52a55edd 100644 --- a/drivers/acpi/acpica/utxfinit.c +++ b/drivers/acpi/acpica/utxfinit.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/drivers/acpi/acpica/utxfmutex.c b/drivers/acpi/acpica/utxfmutex.c index 0b85f113f72629..764782fcf1bda2 100644 --- a/drivers/acpi/acpica/utxfmutex.c +++ b/drivers/acpi/acpica/utxfmutex.c @@ -5,7 +5,7 @@ ******************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acbuffer.h b/include/acpi/acbuffer.h index c77b91ff1149c6..f2eac81bfbd21f 100644 --- a/include/acpi/acbuffer.h +++ b/include/acpi/acbuffer.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h index ffe364fa4040c6..1adcda4bfb541c 100644 --- a/include/acpi/acconfig.h +++ b/include/acpi/acconfig.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acexcep.h b/include/acpi/acexcep.h index 3c46f0ef5f7a7c..bb3e746dad342d 100644 --- a/include/acpi/acexcep.h +++ b/include/acpi/acexcep.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acnames.h b/include/acpi/acnames.h index d8dd3bf51ca735..d497b9bcd84ef3 100644 --- a/include/acpi/acnames.h +++ b/include/acpi/acnames.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acoutput.h b/include/acpi/acoutput.h index c2e664e74075c7..6eceb69cffc4c9 100644 --- a/include/acpi/acoutput.h +++ b/include/acpi/acoutput.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acpi.h b/include/acpi/acpi.h index 0887d7cbb7e142..fae98927052fc5 100644 --- a/include/acpi/acpi.h +++ b/include/acpi/acpi.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acpiosxf.h b/include/acpi/acpiosxf.h index d5c0f5153c4e58..d6345e9870a1a0 100644 --- a/include/acpi/acpiosxf.h +++ b/include/acpi/acpiosxf.h @@ -7,7 +7,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index c589c3e12d90bc..285d0c602b800e 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acrestyp.h b/include/acpi/acrestyp.h index 343dbdcef20c66..1becc88da82f8c 100644 --- a/include/acpi/acrestyp.h +++ b/include/acpi/acrestyp.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actbl.h b/include/acpi/actbl.h index 89509b86cb54bd..17c4d1fdc88d5d 100644 --- a/include/acpi/actbl.h +++ b/include/acpi/actbl.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actbl1.h b/include/acpi/actbl1.h index 4c304bf4d59151..a398d5938f3404 100644 --- a/include/acpi/actbl1.h +++ b/include/acpi/actbl1.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actbl2.h b/include/acpi/actbl2.h index 0d60d5df14f8b7..366a491f2af038 100644 --- a/include/acpi/actbl2.h +++ b/include/acpi/actbl2.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actbl3.h b/include/acpi/actbl3.h index 5bde2e700530e8..ebad40eda9b781 100644 --- a/include/acpi/actbl3.h +++ b/include/acpi/actbl3.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/actypes.h b/include/acpi/actypes.h index 4fed3310235a5d..310b542abe238e 100644 --- a/include/acpi/actypes.h +++ b/include/acpi/actypes.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/acuuid.h b/include/acpi/acuuid.h index b1a0a8a64c3dcd..f0ba9bca2b12c7 100644 --- a/include/acpi/acuuid.h +++ b/include/acpi/acuuid.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/acenv.h b/include/acpi/platform/acenv.h index 043fd559de6ed6..c33ec562b58536 100644 --- a/include/acpi/platform/acenv.h +++ b/include/acpi/platform/acenv.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/acenvex.h b/include/acpi/platform/acenvex.h index 127c848a1ba7cd..c4b1b110aeb9b5 100644 --- a/include/acpi/platform/acenvex.h +++ b/include/acpi/platform/acenvex.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/acgcc.h b/include/acpi/platform/acgcc.h index 9c8f8b79644edd..666256f6c97d37 100644 --- a/include/acpi/platform/acgcc.h +++ b/include/acpi/platform/acgcc.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/acgccex.h b/include/acpi/platform/acgccex.h index 4f701b288cece7..e7baa58b0e3132 100644 --- a/include/acpi/platform/acgccex.h +++ b/include/acpi/platform/acgccex.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/acintel.h b/include/acpi/platform/acintel.h index bdb6858e245824..f0c5be8ba4d5be 100644 --- a/include/acpi/platform/acintel.h +++ b/include/acpi/platform/acintel.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/aclinux.h b/include/acpi/platform/aclinux.h index 97e088276c6d24..adee92c38c43d7 100644 --- a/include/acpi/platform/aclinux.h +++ b/include/acpi/platform/aclinux.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/include/acpi/platform/aclinuxex.h b/include/acpi/platform/aclinuxex.h index efdff527f8fc75..b066d75a93597b 100644 --- a/include/acpi/platform/aclinuxex.h +++ b/include/acpi/platform/aclinuxex.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/common/cmfsize.c b/tools/power/acpi/common/cmfsize.c index 5b38dc2fec4f8f..dfa6fee1b915bf 100644 --- a/tools/power/acpi/common/cmfsize.c +++ b/tools/power/acpi/common/cmfsize.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c index 6e78413bb2cbe7..f7032c9ab35e11 100644 --- a/tools/power/acpi/common/getopt.c +++ b/tools/power/acpi/common/getopt.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c index 52a39ecf5ca18d..e7347edfd4f9f7 100644 --- a/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c +++ b/tools/power/acpi/os_specific/service_layers/oslinuxtbl.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/os_specific/service_layers/osunixdir.c b/tools/power/acpi/os_specific/service_layers/osunixdir.c index ea14eaeb268f3e..9b5e61b636d926 100644 --- a/tools/power/acpi/os_specific/service_layers/osunixdir.c +++ b/tools/power/acpi/os_specific/service_layers/osunixdir.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/os_specific/service_layers/osunixmap.c b/tools/power/acpi/os_specific/service_layers/osunixmap.c index cf9b5a54df9218..8b26924e260206 100644 --- a/tools/power/acpi/os_specific/service_layers/osunixmap.c +++ b/tools/power/acpi/os_specific/service_layers/osunixmap.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c index 025c1b07049d51..34c044da433cf7 100644 --- a/tools/power/acpi/os_specific/service_layers/osunixxf.c +++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h index d6aa40fce2b143..3c679607d1c344 100644 --- a/tools/power/acpi/tools/acpidump/acpidump.h +++ b/tools/power/acpi/tools/acpidump/acpidump.h @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c index 0634449156d82e..9ad1712e4cf942 100644 --- a/tools/power/acpi/tools/acpidump/apdump.c +++ b/tools/power/acpi/tools/acpidump/apdump.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c index d686e11936c45f..856e1b83407ba1 100644 --- a/tools/power/acpi/tools/acpidump/apfiles.c +++ b/tools/power/acpi/tools/acpidump/apfiles.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c index be418fba9441b8..f4ef826800cfbe 100644 --- a/tools/power/acpi/tools/acpidump/apmain.c +++ b/tools/power/acpi/tools/acpidump/apmain.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2017, Intel Corp. + * Copyright (C) 2000 - 2018, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without From 9481a2c5c1d9920938297e47509716fff43aa601 Mon Sep 17 00:00:00 2001 From: Bob Moore Date: Wed, 24 Jan 2018 15:42:34 -0800 Subject: [PATCH 132/237] ACPICA: Update version to 20180105 Version 20180105. Signed-off-by: Bob Moore Signed-off-by: Erik Schmauss Signed-off-by: Rafael J. Wysocki --- include/acpi/acpixf.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/acpi/acpixf.h b/include/acpi/acpixf.h index 285d0c602b800e..c2bf1255f5aa0a 100644 --- a/include/acpi/acpixf.h +++ b/include/acpi/acpixf.h @@ -46,7 +46,7 @@ /* Current ACPICA subsystem version in YYYYMMDD format */ -#define ACPI_CA_VERSION 0x20171215 +#define ACPI_CA_VERSION 0x20180105 #include #include From e44150157f42219fa5c074588efdb31ccfb197fc Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Feb 2018 09:26:27 +0000 Subject: [PATCH 133/237] afs: Add missing afs_put_cell() afs_alloc_volume() needs to release the cell ref it obtained in the case of an error. Fix this by adding an afs_put_cell() call into the error path. This can triggered when a lookup for a cell in a dynamic root or an autocell mount returns an error whilst trying to look up the server (such as ENOMEDIUM). This results in an assertion failure oops when the module is unloaded due to outstanding refs on a cell record. Fixes: d2ddc776a458 ("afs: Overhaul volume and server record caching and fileserver rotation") Signed-off-by: David Howells cc: stable@vger.kernel.org --- fs/afs/volume.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/afs/volume.c b/fs/afs/volume.c index 684c48293353e7..79db9021f140fc 100644 --- a/fs/afs/volume.c +++ b/fs/afs/volume.c @@ -102,6 +102,7 @@ static struct afs_volume *afs_alloc_volume(struct afs_mount_params *params, error_2: afs_put_serverlist(params->net, slist); error_1: + afs_put_cell(params->net, volume->cell); kfree(volume); error_0: return ERR_PTR(ret); From fe4d774c847398c2a45c10a780ccfde069840793 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Feb 2018 06:26:30 +0000 Subject: [PATCH 134/237] afs: Fix missing cursor clearance afs_select_fileserver() ends the address cursor it is using in the case in which we get some sort of network error and run out of addresses to iterate through, before it jumps to try the next server. This also needs to be done when the server aborts with some sort of error that means we should try the next server. Fix this by: (1) Move the iterate_address afs_end_cursor() call to the next_server case. (2) End the cursor in the failed case. (3) Make afs_end_cursor() clear the ->begun flag and ->addr pointer in the address cursor. (4) Make afs_end_cursor() able to be called on an already cleared cursor. Without this, something like the following oops may occur: AFS: Assertion failed 18446612134397189888 == 0 is false 0xffff88007c279f00 == 0x0 is false ------------[ cut here ]------------ kernel BUG at fs/afs/rotate.c:360! RIP: 0010:afs_select_fileserver+0x79b/0xa30 [kafs] Call Trace: afs_statfs+0xcc/0x180 [kafs] ? p9_client_statfs+0x9e/0x110 [9pnet] ? _cond_resched+0x19/0x40 statfs_by_dentry+0x6d/0x90 vfs_statfs+0x1b/0xc0 user_statfs+0x4b/0x80 SYSC_statfs+0x15/0x30 SyS_statfs+0xe/0x10 entry_SYSCALL_64_fastpath+0x20/0x83 Fixes: d2ddc776a458 ("afs: Overhaul volume and server record caching and fileserver rotation") Reported-by: Marc Dionne Signed-off-by: David Howells cc: stable@vger.kernel.org --- fs/afs/addr_list.c | 13 ++++++++++--- fs/afs/rotate.c | 12 ++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/fs/afs/addr_list.c b/fs/afs/addr_list.c index a537368ba0db9a..fd9f28b8a933a9 100644 --- a/fs/afs/addr_list.c +++ b/fs/afs/addr_list.c @@ -332,11 +332,18 @@ bool afs_iterate_addresses(struct afs_addr_cursor *ac) */ int afs_end_cursor(struct afs_addr_cursor *ac) { - if (ac->responded && ac->index != ac->start) - WRITE_ONCE(ac->alist->index, ac->index); + struct afs_addr_list *alist; + + alist = ac->alist; + if (alist) { + if (ac->responded && ac->index != ac->start) + WRITE_ONCE(alist->index, ac->index); + afs_put_addrlist(alist); + } - afs_put_addrlist(ac->alist); + ac->addr = NULL; ac->alist = NULL; + ac->begun = false; return ac->error; } diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index d04511fb387974..b473b25c697896 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c @@ -334,6 +334,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) next_server: _debug("next"); + afs_end_cursor(&fc->ac); afs_put_cb_interest(afs_v2net(vnode), fc->cbi); fc->cbi = NULL; fc->index++; @@ -410,16 +411,15 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) /* Iterate over the current server's address list to try and find an * address on which it will respond to us. */ - if (afs_iterate_addresses(&fc->ac)) { - _leave(" = t"); - return true; - } + if (!afs_iterate_addresses(&fc->ac)) + goto next_server; - afs_end_cursor(&fc->ac); - goto next_server; + _leave(" = t"); + return true; failed: fc->flags |= AFS_FS_CURSOR_STOP; + afs_end_cursor(&fc->ac); _leave(" = f [failed %d]", fc->ac.error); return false; } From 8305e579c653b127b292fcdce551e930f9560260 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Feb 2018 06:26:30 +0000 Subject: [PATCH 135/237] afs: Need to clear responded flag in addr cursor In afs_select_fileserver(), we need to clear the ->responded flag in the address list when reusing it. We should also clear it in afs_select_current_fileserver(). To this end, just memset() the object before initialising it. Fixes: d2ddc776a458 ("afs: Overhaul volume and server record caching and fileserver rotation") Signed-off-by: David Howells cc: stable@vger.kernel.org --- fs/afs/rotate.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index b473b25c697896..892a4904fd77de 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c @@ -384,6 +384,7 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) afs_get_addrlist(alist); read_unlock(&server->fs_lock); + memset(&fc->ac, 0, sizeof(fc->ac)); /* Probe the current fileserver if we haven't done so yet. */ if (!test_bit(AFS_SERVER_FL_PROBED, &server->flags)) { @@ -398,11 +399,8 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) else afs_put_addrlist(alist); - fc->ac.addr = NULL; fc->ac.start = READ_ONCE(alist->index); fc->ac.index = fc->ac.start; - fc->ac.error = 0; - fc->ac.begun = false; goto iterate_address; iterate_address: @@ -458,12 +456,10 @@ bool afs_select_current_fileserver(struct afs_fs_cursor *fc) return false; } + memset(&fc->ac, 0, sizeof(fc->ac)); fc->ac.alist = alist; - fc->ac.addr = NULL; fc->ac.start = READ_ONCE(alist->index); fc->ac.index = fc->ac.start; - fc->ac.error = 0; - fc->ac.begun = false; goto iterate_address; case 0: From 45df8462730d2149834980d3db16e2d2b9daaf60 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Feb 2018 14:12:32 +0000 Subject: [PATCH 136/237] afs: Fix server list handling Fix server list handling in the following ways: (1) In afs_alloc_volume(), remove duplicate server list build code. This was already done by afs_alloc_server_list() which afs_alloc_volume() previously called. This just results in twice as many VL RPCs. (2) In afs_deliver_vl_get_entry_by_name_u(), use the number of server records indicated by ->nServers in the UVLDB record returned by the VL.GetEntryByNameU RPC call rather than scanning all NMAXNSERVERS slots. Unused slots may contain garbage. (3) In afs_alloc_server_list(), don't stop converting a UVLDB record into a server list just because we can't look up one of the servers. Just skip that server and go on to the next. If we can't look up any of the servers then we'll fail at the end. Without this patch, an attempt to view the umich.edu root cell using something like "ls /afs/umich.edu" on a dynamic root (future patch) mount or an autocell mount will result in ENOMEDIUM. The failure is due to kafs not stopping after nServers'worth of records have been read, but then trying to access a server with a garbage UUID and getting an error, which aborts the server list build. Fixes: d2ddc776a458 ("afs: Overhaul volume and server record caching and fileserver rotation") Reported-by: Jonathan Billings Signed-off-by: David Howells cc: stable@vger.kernel.org --- fs/afs/server_list.c | 3 ++- fs/afs/vlclient.c | 10 +++++++--- fs/afs/volume.c | 46 ++------------------------------------------ 3 files changed, 11 insertions(+), 48 deletions(-) diff --git a/fs/afs/server_list.c b/fs/afs/server_list.c index 0ab3f84578390e..0f8dc4c8f07c43 100644 --- a/fs/afs/server_list.c +++ b/fs/afs/server_list.c @@ -58,7 +58,8 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell, server = afs_lookup_server(cell, key, &vldb->fs_server[i]); if (IS_ERR(server)) { ret = PTR_ERR(server); - if (ret == -ENOENT) + if (ret == -ENOENT || + ret == -ENOMEDIUM) continue; goto error_2; } diff --git a/fs/afs/vlclient.c b/fs/afs/vlclient.c index e372f89fd36a23..5d8562f1ad4ad6 100644 --- a/fs/afs/vlclient.c +++ b/fs/afs/vlclient.c @@ -23,7 +23,7 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) struct afs_uvldbentry__xdr *uvldb; struct afs_vldb_entry *entry; bool new_only = false; - u32 tmp; + u32 tmp, nr_servers; int i, ret; _enter(""); @@ -36,6 +36,10 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) uvldb = call->buffer; entry = call->reply[0]; + nr_servers = ntohl(uvldb->nServers); + if (nr_servers > AFS_NMAXNSERVERS) + nr_servers = AFS_NMAXNSERVERS; + for (i = 0; i < ARRAY_SIZE(uvldb->name) - 1; i++) entry->name[i] = (u8)ntohl(uvldb->name[i]); entry->name[i] = 0; @@ -44,14 +48,14 @@ static int afs_deliver_vl_get_entry_by_name_u(struct afs_call *call) /* If there is a new replication site that we can use, ignore all the * sites that aren't marked as new. */ - for (i = 0; i < AFS_NMAXNSERVERS; i++) { + for (i = 0; i < nr_servers; i++) { tmp = ntohl(uvldb->serverFlags[i]); if (!(tmp & AFS_VLSF_DONTUSE) && (tmp & AFS_VLSF_NEWREPSITE)) new_only = true; } - for (i = 0; i < AFS_NMAXNSERVERS; i++) { + for (i = 0; i < nr_servers; i++) { struct afs_uuid__xdr *xdr; struct afs_uuid *uuid; int j; diff --git a/fs/afs/volume.c b/fs/afs/volume.c index 79db9021f140fc..b517a588781fe2 100644 --- a/fs/afs/volume.c +++ b/fs/afs/volume.c @@ -26,9 +26,8 @@ static struct afs_volume *afs_alloc_volume(struct afs_mount_params *params, unsigned long type_mask) { struct afs_server_list *slist; - struct afs_server *server; struct afs_volume *volume; - int ret = -ENOMEM, nr_servers = 0, i, j; + int ret = -ENOMEM, nr_servers = 0, i; for (i = 0; i < vldb->nr_servers; i++) if (vldb->fs_mask[i] & type_mask) @@ -58,49 +57,8 @@ static struct afs_volume *afs_alloc_volume(struct afs_mount_params *params, refcount_set(&slist->usage, 1); volume->servers = slist; - - /* Make sure a records exists for each server this volume occupies. */ - for (i = 0; i < nr_servers; i++) { - if (!(vldb->fs_mask[i] & type_mask)) - continue; - - server = afs_lookup_server(params->cell, params->key, - &vldb->fs_server[i]); - if (IS_ERR(server)) { - ret = PTR_ERR(server); - if (ret == -ENOENT) - continue; - goto error_2; - } - - /* Insertion-sort by server pointer */ - for (j = 0; j < slist->nr_servers; j++) - if (slist->servers[j].server >= server) - break; - if (j < slist->nr_servers) { - if (slist->servers[j].server == server) { - afs_put_server(params->net, server); - continue; - } - - memmove(slist->servers + j + 1, - slist->servers + j, - (slist->nr_servers - j) * sizeof(struct afs_server_entry)); - } - - slist->servers[j].server = server; - slist->nr_servers++; - } - - if (slist->nr_servers == 0) { - ret = -EDESTADDRREQ; - goto error_2; - } - return volume; -error_2: - afs_put_serverlist(params->net, slist); error_1: afs_put_cell(params->net, volume->cell); kfree(volume); @@ -328,7 +286,7 @@ static int afs_update_volume_status(struct afs_volume *volume, struct key *key) /* See if the volume's server list got updated. */ new = afs_alloc_server_list(volume->cell, key, - vldb, (1 << volume->type)); + vldb, (1 << volume->type)); if (IS_ERR(new)) { ret = PTR_ERR(new); goto error_vldb; From 63dc4e4aa5ab61868199960979fe1feecdabd01e Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Feb 2018 06:26:30 +0000 Subject: [PATCH 137/237] afs: Remove unused code Remove some old unused code. Signed-off-by: David Howells --- fs/afs/rotate.c | 235 ------------------------------------------------ 1 file changed, 235 deletions(-) diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index 892a4904fd77de..cfe0931e784448 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c @@ -516,238 +516,3 @@ int afs_end_vnode_operation(struct afs_fs_cursor *fc) return fc->ac.error; } - -#if 0 -/* - * Set a filesystem server cursor for using a specific FS server. - */ -int afs_set_fs_cursor(struct afs_fs_cursor *fc, struct afs_vnode *vnode) -{ - afs_init_fs_cursor(fc, vnode); - - read_seqlock_excl(&vnode->cb_lock); - if (vnode->cb_interest) { - if (vnode->cb_interest->server->fs_state == 0) - fc->server = afs_get_server(vnode->cb_interest->server); - else - fc->ac.error = vnode->cb_interest->server->fs_state; - } else { - fc->ac.error = -ESTALE; - } - read_sequnlock_excl(&vnode->cb_lock); - - return fc->ac.error; -} - -/* - * pick a server to use to try accessing this volume - * - returns with an elevated usage count on the server chosen - */ -bool afs_volume_pick_fileserver(struct afs_fs_cursor *fc, struct afs_vnode *vnode) -{ - struct afs_volume *volume = vnode->volume; - struct afs_server *server; - int ret, state, loop; - - _enter("%s", volume->vlocation->vldb.name); - - /* stick with the server we're already using if we can */ - if (vnode->cb_interest && vnode->cb_interest->server->fs_state == 0) { - fc->server = afs_get_server(vnode->cb_interest->server); - goto set_server; - } - - down_read(&volume->server_sem); - - /* handle the no-server case */ - if (volume->nservers == 0) { - fc->ac.error = volume->rjservers ? -ENOMEDIUM : -ESTALE; - up_read(&volume->server_sem); - _leave(" = f [no servers %d]", fc->ac.error); - return false; - } - - /* basically, just search the list for the first live server and use - * that */ - ret = 0; - for (loop = 0; loop < volume->nservers; loop++) { - server = volume->servers[loop]; - state = server->fs_state; - - _debug("consider %d [%d]", loop, state); - - switch (state) { - case 0: - goto picked_server; - - case -ENETUNREACH: - if (ret == 0) - ret = state; - break; - - case -EHOSTUNREACH: - if (ret == 0 || - ret == -ENETUNREACH) - ret = state; - break; - - case -ECONNREFUSED: - if (ret == 0 || - ret == -ENETUNREACH || - ret == -EHOSTUNREACH) - ret = state; - break; - - default: - case -EREMOTEIO: - if (ret == 0 || - ret == -ENETUNREACH || - ret == -EHOSTUNREACH || - ret == -ECONNREFUSED) - ret = state; - break; - } - } - -error: - fc->ac.error = ret; - - /* no available servers - * - TODO: handle the no active servers case better - */ - up_read(&volume->server_sem); - _leave(" = f [%d]", fc->ac.error); - return false; - -picked_server: - /* Found an apparently healthy server. We need to register an interest - * in receiving callbacks before we talk to it. - */ - ret = afs_register_server_cb_interest(vnode, - &volume->cb_interests[loop], server); - if (ret < 0) - goto error; - - fc->server = afs_get_server(server); - up_read(&volume->server_sem); -set_server: - fc->ac.alist = afs_get_addrlist(fc->server->addrs); - fc->ac.addr = &fc->ac.alist->addrs[0]; - _debug("USING SERVER: %pIS\n", &fc->ac.addr->transport); - _leave(" = t (picked %pIS)", &fc->ac.addr->transport); - return true; -} - -/* - * release a server after use - * - releases the ref on the server struct that was acquired by picking - * - records result of using a particular server to access a volume - * - return true to try again, false if okay or to issue error - * - the caller must release the server struct if result was false - */ -bool afs_iterate_fs_cursor(struct afs_fs_cursor *fc, - struct afs_vnode *vnode) -{ - struct afs_volume *volume = vnode->volume; - struct afs_server *server = fc->server; - unsigned loop; - - _enter("%s,%pIS,%d", - volume->vlocation->vldb.name, &fc->ac.addr->transport, - fc->ac.error); - - switch (fc->ac.error) { - /* success */ - case 0: - server->fs_state = 0; - _leave(" = f"); - return false; - - /* the fileserver denied all knowledge of the volume */ - case -ENOMEDIUM: - down_write(&volume->server_sem); - - /* firstly, find where the server is in the active list (if it - * is) */ - for (loop = 0; loop < volume->nservers; loop++) - if (volume->servers[loop] == server) - goto present; - - /* no longer there - may have been discarded by another op */ - goto try_next_server_upw; - - present: - volume->nservers--; - memmove(&volume->servers[loop], - &volume->servers[loop + 1], - sizeof(volume->servers[loop]) * - (volume->nservers - loop)); - volume->servers[volume->nservers] = NULL; - afs_put_server(afs_v2net(vnode), server); - volume->rjservers++; - - if (volume->nservers > 0) - /* another server might acknowledge its existence */ - goto try_next_server_upw; - - /* handle the case where all the fileservers have rejected the - * volume - * - TODO: try asking the fileservers for volume information - * - TODO: contact the VL server again to see if the volume is - * no longer registered - */ - up_write(&volume->server_sem); - afs_put_server(afs_v2net(vnode), server); - fc->server = NULL; - _leave(" = f [completely rejected]"); - return false; - - /* problem reaching the server */ - case -ENETUNREACH: - case -EHOSTUNREACH: - case -ECONNREFUSED: - case -ETIME: - case -ETIMEDOUT: - case -EREMOTEIO: - /* mark the server as dead - * TODO: vary dead timeout depending on error - */ - spin_lock(&server->fs_lock); - if (!server->fs_state) { - server->fs_state = fc->ac.error; - printk("kAFS: SERVER DEAD state=%d\n", fc->ac.error); - } - spin_unlock(&server->fs_lock); - goto try_next_server; - - /* miscellaneous error */ - default: - case -ENOMEM: - case -ENONET: - /* tell the caller to accept the result */ - afs_put_server(afs_v2net(vnode), server); - fc->server = NULL; - _leave(" = f [local failure]"); - return false; - } - - /* tell the caller to loop around and try the next server */ -try_next_server_upw: - up_write(&volume->server_sem); -try_next_server: - afs_put_server(afs_v2net(vnode), server); - _leave(" = t [try next server]"); - return true; -} - -/* - * Clean up a fileserver cursor. - */ -int afs_end_fs_cursor(struct afs_fs_cursor *fc, struct afs_net *net) -{ - afs_end_cursor(&fc->ac); - afs_put_server(net, fc->server); - return fc->ac.error; -} - -#endif From 16280a15be751b9994e94c5dc944e93fa4293199 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Feb 2018 06:26:30 +0000 Subject: [PATCH 138/237] afs: Rearrange afs_select_fileserver() a little Rearrange afs_select_fileserver() a little to put the use_server chunk before the next_server chunk so that with the removal of a couple of gotos the main path through the function is all one sequence. Signed-off-by: David Howells --- fs/afs/rotate.c | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/fs/afs/rotate.c b/fs/afs/rotate.c index cfe0931e784448..ad1328d855261a 100644 --- a/fs/afs/rotate.c +++ b/fs/afs/rotate.c @@ -330,27 +330,6 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) if (!afs_start_fs_iteration(fc, vnode)) goto failed; - goto use_server; - -next_server: - _debug("next"); - afs_end_cursor(&fc->ac); - afs_put_cb_interest(afs_v2net(vnode), fc->cbi); - fc->cbi = NULL; - fc->index++; - if (fc->index >= fc->server_list->nr_servers) - fc->index = 0; - if (fc->index != fc->start) - goto use_server; - - /* That's all the servers poked to no good effect. Try again if some - * of them were busy. - */ - if (fc->flags & AFS_FS_CURSOR_VBUSY) - goto restart_from_beginning; - - fc->ac.error = -EDESTADDRREQ; - goto failed; use_server: _debug("use"); @@ -401,7 +380,6 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) fc->ac.start = READ_ONCE(alist->index); fc->ac.index = fc->ac.start; - goto iterate_address; iterate_address: ASSERT(fc->ac.alist); @@ -415,6 +393,26 @@ bool afs_select_fileserver(struct afs_fs_cursor *fc) _leave(" = t"); return true; +next_server: + _debug("next"); + afs_end_cursor(&fc->ac); + afs_put_cb_interest(afs_v2net(vnode), fc->cbi); + fc->cbi = NULL; + fc->index++; + if (fc->index >= fc->server_list->nr_servers) + fc->index = 0; + if (fc->index != fc->start) + goto use_server; + + /* That's all the servers poked to no good effect. Try again if some + * of them were busy. + */ + if (fc->flags & AFS_FS_CURSOR_VBUSY) + goto restart_from_beginning; + + fc->ac.error = -EDESTADDRREQ; + goto failed; + failed: fc->flags |= AFS_FS_CURSOR_STOP; afs_end_cursor(&fc->ac); From 4d673da14533b32fe8d3125b5b7be4fea14e39a8 Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 6 Feb 2018 06:26:30 +0000 Subject: [PATCH 139/237] afs: Support the AFS dynamic root Support the AFS dynamic root which is a pseudo-volume that doesn't connect to any server resource, but rather is just a root directory that dynamically creates mountpoint directories where the name of such a directory is the name of the cell. Such a mount can be created thus: mount -t afs none /afs -o dyn Dynamic root superblocks aren't shared except by bind mounts and propagation. Cell root volumes can then be mounted by referring to them by name, e.g.: ls /afs/grand.central.org/ ls /afs/.grand.central.org/ The kernel will upcall to consult the DNS if the address wasn't supplied directly. Signed-off-by: David Howells --- Documentation/filesystems/afs.txt | 17 ++++ fs/afs/dir.c | 122 +++++++++++++++++++++++---- fs/afs/inode.c | 48 +++++++---- fs/afs/internal.h | 12 ++- fs/afs/mntpt.c | 20 +++-- fs/afs/super.c | 132 ++++++++++++++++++++---------- net/dns_resolver/dns_query.c | 22 ++--- 7 files changed, 276 insertions(+), 97 deletions(-) diff --git a/Documentation/filesystems/afs.txt b/Documentation/filesystems/afs.txt index ba99b5ac4fd802..c5254f6d234dbb 100644 --- a/Documentation/filesystems/afs.txt +++ b/Documentation/filesystems/afs.txt @@ -7,6 +7,7 @@ Contents: - Overview. - Usage. - Mountpoints. + - Dynamic root. - Proc filesystem. - The cell database. - Security. @@ -127,6 +128,22 @@ mounted on /afs in one go by doing: umount /afs +============ +DYNAMIC ROOT +============ + +A mount option is available to create a serverless mount that is only usable +for dynamic lookup. Creating such a mount can be done by, for example: + + mount -t afs none /afs -o dyn + +This creates a mount that just has an empty directory at the root. Attempting +to look up a name in this directory will cause a mountpoint to be created that +looks up a cell of the same name, for example: + + ls /afs/grand.central.org/ + + =============== PROC FILESYSTEM =============== diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 23c7f395d71827..ba2b458b36d15e 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c @@ -17,10 +17,13 @@ #include #include #include +#include #include "internal.h" static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags); +static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags); static int afs_dir_open(struct inode *inode, struct file *file); static int afs_readdir(struct file *file, struct dir_context *ctx); static int afs_d_revalidate(struct dentry *dentry, unsigned int flags); @@ -64,6 +67,17 @@ const struct inode_operations afs_dir_inode_operations = { .listxattr = afs_listxattr, }; +const struct file_operations afs_dynroot_file_operations = { + .open = dcache_dir_open, + .release = dcache_dir_close, + .iterate_shared = dcache_readdir, + .llseek = dcache_dir_lseek, +}; + +const struct inode_operations afs_dynroot_inode_operations = { + .lookup = afs_dynroot_lookup, +}; + const struct dentry_operations afs_fs_dentry_operations = { .d_revalidate = afs_d_revalidate, .d_delete = afs_d_delete, @@ -467,26 +481,59 @@ static int afs_do_lookup(struct inode *dir, struct dentry *dentry, return 0; } +/* + * Probe to see if a cell may exist. This prevents positive dentries from + * being created unnecessarily. + */ +static int afs_probe_cell_name(struct dentry *dentry) +{ + struct afs_cell *cell; + const char *name = dentry->d_name.name; + size_t len = dentry->d_name.len; + int ret; + + /* Names prefixed with a dot are R/W mounts. */ + if (name[0] == '.') { + if (len == 1) + return -EINVAL; + name++; + len--; + } + + cell = afs_lookup_cell_rcu(afs_d2net(dentry), name, len); + if (!IS_ERR(cell)) { + afs_put_cell(afs_d2net(dentry), cell); + return 0; + } + + ret = dns_query("afsdb", name, len, "ipv4", NULL, NULL); + if (ret == -ENODATA) + ret = -EDESTADDRREQ; + return ret; +} + /* * Try to auto mount the mountpoint with pseudo directory, if the autocell * operation is setted. */ -static struct inode *afs_try_auto_mntpt( - int ret, struct dentry *dentry, struct inode *dir, struct key *key, - struct afs_fid *fid) +static struct inode *afs_try_auto_mntpt(struct dentry *dentry, + struct inode *dir, struct afs_fid *fid) { - const char *devname = dentry->d_name.name; struct afs_vnode *vnode = AFS_FS_I(dir); struct inode *inode; + int ret = -ENOENT; - _enter("%d, %p{%pd}, {%x:%u}, %p", - ret, dentry, dentry, vnode->fid.vid, vnode->fid.vnode, key); + _enter("%p{%pd}, {%x:%u}", + dentry, dentry, vnode->fid.vid, vnode->fid.vnode); + + if (!test_bit(AFS_VNODE_AUTOCELL, &vnode->flags)) + goto out; - if (ret != -ENOENT || - !test_bit(AFS_VNODE_AUTOCELL, &vnode->flags)) + ret = afs_probe_cell_name(dentry); + if (ret < 0) goto out; - inode = afs_iget_autocell(dir, devname, strlen(devname), key); + inode = afs_iget_pseudo_dir(dir->i_sb, false); if (IS_ERR(inode)) { ret = PTR_ERR(inode); goto out; @@ -545,13 +592,16 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, ret = afs_do_lookup(dir, dentry, &fid, key); if (ret < 0) { - inode = afs_try_auto_mntpt(ret, dentry, dir, key, &fid); - if (!IS_ERR(inode)) { - key_put(key); - goto success; + if (ret == -ENOENT) { + inode = afs_try_auto_mntpt(dentry, dir, &fid); + if (!IS_ERR(inode)) { + key_put(key); + goto success; + } + + ret = PTR_ERR(inode); } - ret = PTR_ERR(inode); key_put(key); if (ret == -ENOENT) { d_add(dentry, NULL); @@ -582,6 +632,46 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, return NULL; } +/* + * Look up an entry in a dynroot directory. + */ +static struct dentry *afs_dynroot_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags) +{ + struct afs_vnode *vnode; + struct afs_fid fid; + struct inode *inode; + int ret; + + vnode = AFS_FS_I(dir); + + _enter("%pd", dentry); + + ASSERTCMP(d_inode(dentry), ==, NULL); + + if (dentry->d_name.len >= AFSNAMEMAX) { + _leave(" = -ENAMETOOLONG"); + return ERR_PTR(-ENAMETOOLONG); + } + + inode = afs_try_auto_mntpt(dentry, dir, &fid); + if (IS_ERR(inode)) { + ret = PTR_ERR(inode); + if (ret == -ENOENT) { + d_add(dentry, NULL); + _leave(" = NULL [negative]"); + return NULL; + } + _leave(" = %d [do]", ret); + return ERR_PTR(ret); + } + + d_add(dentry, inode); + _leave(" = 0 { ino=%lu v=%u }", + d_inode(dentry)->i_ino, d_inode(dentry)->i_generation); + return NULL; +} + /* * check that a dentry lookup hit has found a valid entry * - NOTE! the hit can be a negative hit too, so we can't assume we have an @@ -589,6 +679,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry, */ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) { + struct afs_super_info *as = dentry->d_sb->s_fs_info; struct afs_vnode *vnode, *dir; struct afs_fid uninitialized_var(fid); struct dentry *parent; @@ -600,6 +691,9 @@ static int afs_d_revalidate(struct dentry *dentry, unsigned int flags) if (flags & LOOKUP_RCU) return -ECHILD; + if (as->dyn_root) + return 1; + if (d_really_is_positive(dentry)) { vnode = AFS_FS_I(d_inode(dentry)); _enter("{v={%x:%u} n=%pd fl=%lx},", diff --git a/fs/afs/inode.c b/fs/afs/inode.c index c7f17c44c7ce88..6b39d0255b7219 100644 --- a/fs/afs/inode.c +++ b/fs/afs/inode.c @@ -147,7 +147,7 @@ int afs_iget5_test(struct inode *inode, void *opaque) * * These pseudo inodes don't match anything. */ -static int afs_iget5_autocell_test(struct inode *inode, void *opaque) +static int afs_iget5_pseudo_dir_test(struct inode *inode, void *opaque) { return 0; } @@ -169,31 +169,34 @@ static int afs_iget5_set(struct inode *inode, void *opaque) } /* - * inode retrieval for autocell + * Create an inode for a dynamic root directory or an autocell dynamic + * automount dir. */ -struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name, - int namesz, struct key *key) +struct inode *afs_iget_pseudo_dir(struct super_block *sb, bool root) { struct afs_iget_data data; struct afs_super_info *as; struct afs_vnode *vnode; - struct super_block *sb; struct inode *inode; static atomic_t afs_autocell_ino; - _enter("{%x:%u},%*.*s,", - AFS_FS_I(dir)->fid.vid, AFS_FS_I(dir)->fid.vnode, - namesz, namesz, dev_name ?: ""); + _enter(""); - sb = dir->i_sb; as = sb->s_fs_info; - data.volume = as->volume; - data.fid.vid = as->volume->vid; - data.fid.unique = 0; - data.fid.vnode = 0; + if (as->volume) { + data.volume = as->volume; + data.fid.vid = as->volume->vid; + } + if (root) { + data.fid.vnode = 1; + data.fid.unique = 1; + } else { + data.fid.vnode = atomic_inc_return(&afs_autocell_ino); + data.fid.unique = 0; + } - inode = iget5_locked(sb, atomic_inc_return(&afs_autocell_ino), - afs_iget5_autocell_test, afs_iget5_set, + inode = iget5_locked(sb, data.fid.vnode, + afs_iget5_pseudo_dir_test, afs_iget5_set, &data); if (!inode) { _leave(" = -ENOMEM"); @@ -211,7 +214,12 @@ struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name, inode->i_size = 0; inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO; - inode->i_op = &afs_autocell_inode_operations; + if (root) { + inode->i_op = &afs_dynroot_inode_operations; + inode->i_fop = &afs_dynroot_file_operations; + } else { + inode->i_op = &afs_autocell_inode_operations; + } set_nlink(inode, 2); inode->i_uid = GLOBAL_ROOT_UID; inode->i_gid = GLOBAL_ROOT_GID; @@ -223,8 +231,12 @@ struct inode *afs_iget_autocell(struct inode *dir, const char *dev_name, inode->i_generation = 0; set_bit(AFS_VNODE_PSEUDODIR, &vnode->flags); - set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); - inode->i_flags |= S_AUTOMOUNT | S_NOATIME; + if (!root) { + set_bit(AFS_VNODE_MOUNTPOINT, &vnode->flags); + inode->i_flags |= S_AUTOMOUNT; + } + + inode->i_flags |= S_NOATIME; unlock_new_inode(inode); _leave(" = %p", inode); return inode; diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 804d1f90562207..f38d6a561a8482 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h @@ -36,6 +36,7 @@ struct afs_mount_params { bool rwpath; /* T if the parent should be considered R/W */ bool force; /* T to force cell type */ bool autocell; /* T if set auto mount operation */ + bool dyn_root; /* T if dynamic root */ afs_voltype_t type; /* type of volume requested */ int volnamesz; /* size of volume name */ const char *volname; /* name of volume to mount */ @@ -186,6 +187,7 @@ struct afs_super_info { struct afs_net *net; /* Network namespace */ struct afs_cell *cell; /* The cell in which the volume resides */ struct afs_volume *volume; /* volume record */ + bool dyn_root; /* True if dynamic root */ }; static inline struct afs_super_info *AFS_FS_S(struct super_block *sb) @@ -634,10 +636,13 @@ extern bool afs_cm_incoming_call(struct afs_call *); /* * dir.c */ -extern bool afs_dir_check_page(struct inode *, struct page *); +extern const struct file_operations afs_dir_file_operations; extern const struct inode_operations afs_dir_inode_operations; +extern const struct file_operations afs_dynroot_file_operations; +extern const struct inode_operations afs_dynroot_inode_operations; extern const struct dentry_operations afs_fs_dentry_operations; -extern const struct file_operations afs_dir_file_operations; + +extern bool afs_dir_check_page(struct inode *, struct page *); /* * file.c @@ -695,8 +700,7 @@ extern int afs_fs_get_capabilities(struct afs_net *, struct afs_server *, */ extern int afs_fetch_status(struct afs_vnode *, struct key *); extern int afs_iget5_test(struct inode *, void *); -extern struct inode *afs_iget_autocell(struct inode *, const char *, int, - struct key *); +extern struct inode *afs_iget_pseudo_dir(struct super_block *, bool); extern struct inode *afs_iget(struct super_block *, struct key *, struct afs_fid *, struct afs_file_status *, struct afs_callback *, diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 690fea9d84c33a..99fd13500a97f9 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c @@ -72,7 +72,7 @@ static int afs_mntpt_open(struct inode *inode, struct file *file) */ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) { - struct afs_super_info *super; + struct afs_super_info *as; struct vfsmount *mnt; struct afs_vnode *vnode; struct page *page; @@ -104,13 +104,13 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) goto error_no_page; if (mntpt->d_name.name[0] == '.') { - devname[0] = '#'; - memcpy(devname + 1, mntpt->d_name.name, size - 1); + devname[0] = '%'; + memcpy(devname + 1, mntpt->d_name.name + 1, size - 1); memcpy(devname + size, afs_root_cell, sizeof(afs_root_cell)); rwpath = true; } else { - devname[0] = '%'; + devname[0] = '#'; memcpy(devname + 1, mntpt->d_name.name, size); memcpy(devname + size + 1, afs_root_cell, sizeof(afs_root_cell)); @@ -142,11 +142,13 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) } /* work out what options we want */ - super = AFS_FS_S(mntpt->d_sb); - memcpy(options, "cell=", 5); - strcpy(options + 5, super->volume->cell->name); - if (super->volume->type == AFSVL_RWVOL || rwpath) - strcat(options, ",rwpath"); + as = AFS_FS_S(mntpt->d_sb); + if (as->cell) { + memcpy(options, "cell=", 5); + strcpy(options + 5, as->cell->name); + if ((as->volume && as->volume->type == AFSVL_RWVOL) || rwpath) + strcat(options, ",rwpath"); + } /* try and do the mount */ _debug("--- attempting mount %s -o %s ---", devname, options); diff --git a/fs/afs/super.c b/fs/afs/super.c index 1037dd41a62210..3623c952b6ffcb 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c @@ -64,6 +64,7 @@ static atomic_t afs_count_active_inodes; enum { afs_no_opt, afs_opt_cell, + afs_opt_dyn, afs_opt_rwpath, afs_opt_vol, afs_opt_autocell, @@ -71,6 +72,7 @@ enum { static const match_table_t afs_options_list = { { afs_opt_cell, "cell=%s" }, + { afs_opt_dyn, "dyn" }, { afs_opt_rwpath, "rwpath" }, { afs_opt_vol, "vol=%s" }, { afs_opt_autocell, "autocell" }, @@ -148,6 +150,11 @@ static int afs_show_devname(struct seq_file *m, struct dentry *root) const char *suf = ""; char pref = '%'; + if (as->dyn_root) { + seq_puts(m, "none"); + return 0; + } + switch (volume->type) { case AFSVL_RWVOL: break; @@ -171,8 +178,12 @@ static int afs_show_devname(struct seq_file *m, struct dentry *root) */ static int afs_show_options(struct seq_file *m, struct dentry *root) { + struct afs_super_info *as = AFS_FS_S(root->d_sb); + + if (as->dyn_root) + seq_puts(m, ",dyn"); if (test_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(d_inode(root))->flags)) - seq_puts(m, "autocell"); + seq_puts(m, ",autocell"); return 0; } @@ -212,7 +223,7 @@ static int afs_parse_options(struct afs_mount_params *params, break; case afs_opt_rwpath: - params->rwpath = 1; + params->rwpath = true; break; case afs_opt_vol: @@ -220,7 +231,11 @@ static int afs_parse_options(struct afs_mount_params *params, break; case afs_opt_autocell: - params->autocell = 1; + params->autocell = true; + break; + + case afs_opt_dyn: + params->dyn_root = true; break; default: @@ -254,7 +269,7 @@ static int afs_parse_device_name(struct afs_mount_params *params, int cellnamesz; _enter(",%s", name); - + if (!name) { printk(KERN_ERR "kAFS: no volume name specified\n"); return -EINVAL; @@ -336,7 +351,14 @@ static int afs_test_super(struct super_block *sb, void *data) struct afs_super_info *as1 = data; struct afs_super_info *as = AFS_FS_S(sb); - return as->net == as1->net && as->volume->vid == as1->volume->vid; + return (as->net == as1->net && + as->volume && + as->volume->vid == as1->volume->vid); +} + +static int afs_dynroot_test_super(struct super_block *sb, void *data) +{ + return false; } static int afs_set_super(struct super_block *sb, void *data) @@ -365,24 +387,30 @@ static int afs_fill_super(struct super_block *sb, sb->s_blocksize_bits = PAGE_SHIFT; sb->s_magic = AFS_FS_MAGIC; sb->s_op = &afs_super_ops; - sb->s_xattr = afs_xattr_handlers; + if (!as->dyn_root) + sb->s_xattr = afs_xattr_handlers; ret = super_setup_bdi(sb); if (ret) return ret; sb->s_bdi->ra_pages = VM_MAX_READAHEAD * 1024 / PAGE_SIZE; - sprintf(sb->s_id, "%u", as->volume->vid); - - afs_activate_volume(as->volume); /* allocate the root inode and dentry */ - fid.vid = as->volume->vid; - fid.vnode = 1; - fid.unique = 1; - inode = afs_iget(sb, params->key, &fid, NULL, NULL, NULL); + if (as->dyn_root) { + inode = afs_iget_pseudo_dir(sb, true); + sb->s_flags |= SB_RDONLY; + } else { + sprintf(sb->s_id, "%u", as->volume->vid); + afs_activate_volume(as->volume); + fid.vid = as->volume->vid; + fid.vnode = 1; + fid.unique = 1; + inode = afs_iget(sb, params->key, &fid, NULL, NULL, NULL); + } + if (IS_ERR(inode)) return PTR_ERR(inode); - if (params->autocell) + if (params->autocell || params->dyn_root) set_bit(AFS_VNODE_AUTOCELL, &AFS_FS_I(inode)->flags); ret = -ENOMEM; @@ -407,7 +435,10 @@ static struct afs_super_info *afs_alloc_sbi(struct afs_mount_params *params) as = kzalloc(sizeof(struct afs_super_info), GFP_KERNEL); if (as) { as->net = afs_get_net(params->net); - as->cell = afs_get_cell(params->cell); + if (params->dyn_root) + as->dyn_root = true; + else + as->cell = afs_get_cell(params->cell); } return as; } @@ -451,18 +482,20 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, goto error; } - ret = afs_parse_device_name(¶ms, dev_name); - if (ret < 0) - goto error; + if (!params.dyn_root) { + ret = afs_parse_device_name(¶ms, dev_name); + if (ret < 0) + goto error; - /* try and do the mount securely */ - key = afs_request_key(params.cell); - if (IS_ERR(key)) { - _leave(" = %ld [key]", PTR_ERR(key)); - ret = PTR_ERR(key); - goto error; + /* try and do the mount securely */ + key = afs_request_key(params.cell); + if (IS_ERR(key)) { + _leave(" = %ld [key]", PTR_ERR(key)); + ret = PTR_ERR(key); + goto error; + } + params.key = key; } - params.key = key; /* allocate a superblock info record */ ret = -ENOMEM; @@ -470,20 +503,25 @@ static struct dentry *afs_mount(struct file_system_type *fs_type, if (!as) goto error_key; - /* Assume we're going to need a volume record; at the very least we can - * use it to update the volume record if we have one already. This - * checks that the volume exists within the cell. - */ - candidate = afs_create_volume(¶ms); - if (IS_ERR(candidate)) { - ret = PTR_ERR(candidate); - goto error_as; - } + if (!params.dyn_root) { + /* Assume we're going to need a volume record; at the very + * least we can use it to update the volume record if we have + * one already. This checks that the volume exists within the + * cell. + */ + candidate = afs_create_volume(¶ms); + if (IS_ERR(candidate)) { + ret = PTR_ERR(candidate); + goto error_as; + } - as->volume = candidate; + as->volume = candidate; + } /* allocate a deviceless superblock */ - sb = sget(fs_type, afs_test_super, afs_set_super, flags, as); + sb = sget(fs_type, + as->dyn_root ? afs_dynroot_test_super : afs_test_super, + afs_set_super, flags, as); if (IS_ERR(sb)) { ret = PTR_ERR(sb); goto error_as; @@ -529,9 +567,11 @@ static void afs_kill_super(struct super_block *sb) /* Clear the callback interests (which will do ilookup5) before * deactivating the superblock. */ - afs_clear_callback_interests(as->net, as->volume->servers); + if (as->volume) + afs_clear_callback_interests(as->net, as->volume->servers); kill_anon_super(sb); - afs_deactivate_volume(as->volume); + if (as->volume) + afs_deactivate_volume(as->volume); afs_destroy_sbi(as); } @@ -619,12 +659,24 @@ static void afs_destroy_inode(struct inode *inode) */ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf) { + struct afs_super_info *as = AFS_FS_S(dentry->d_sb); struct afs_fs_cursor fc; struct afs_volume_status vs; struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); struct key *key; int ret; + buf->f_type = dentry->d_sb->s_magic; + buf->f_bsize = AFS_BLOCK_SIZE; + buf->f_namelen = AFSNAMEMAX - 1; + + if (as->dyn_root) { + buf->f_blocks = 1; + buf->f_bavail = 0; + buf->f_bfree = 0; + return 0; + } + key = afs_request_key(vnode->volume->cell); if (IS_ERR(key)) return PTR_ERR(key); @@ -645,10 +697,6 @@ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf) key_put(key); if (ret == 0) { - buf->f_type = dentry->d_sb->s_magic; - buf->f_bsize = AFS_BLOCK_SIZE; - buf->f_namelen = AFSNAMEMAX - 1; - if (vs.max_quota == 0) buf->f_blocks = vs.part_max_blocks; else diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c index af781010753b0f..49da67034f29cd 100644 --- a/net/dns_resolver/dns_query.c +++ b/net/dns_resolver/dns_query.c @@ -52,11 +52,11 @@ * @name: Name to look up * @namelen: Length of name * @options: Request options (or NULL if no options) - * @_result: Where to place the returned data. + * @_result: Where to place the returned data (or NULL) * @_expiry: Where to store the result expiry time (or NULL) * - * The data will be returned in the pointer at *result, and the caller is - * responsible for freeing it. + * The data will be returned in the pointer at *result, if provided, and the + * caller is responsible for freeing it. * * The description should be of the form "[:]", and * the options need to be appropriate for the query type requested. If no @@ -81,7 +81,7 @@ int dns_query(const char *type, const char *name, size_t namelen, kenter("%s,%*.*s,%zu,%s", type, (int)namelen, (int)namelen, name, namelen, options); - if (!name || namelen == 0 || !_result) + if (!name || namelen == 0) return -EINVAL; /* construct the query key description as "[:]" */ @@ -146,13 +146,15 @@ int dns_query(const char *type, const char *name, size_t namelen, upayload = user_key_payload_locked(rkey); len = upayload->datalen; - ret = -ENOMEM; - *_result = kmalloc(len + 1, GFP_KERNEL); - if (!*_result) - goto put; + if (_result) { + ret = -ENOMEM; + *_result = kmalloc(len + 1, GFP_KERNEL); + if (!*_result) + goto put; - memcpy(*_result, upayload->data, len); - (*_result)[len] = '\0'; + memcpy(*_result, upayload->data, len); + (*_result)[len] = '\0'; + } if (_expiry) *_expiry = rkey->expiry; From 36904703aeeeb6cd31993f1353c8325006229f9a Mon Sep 17 00:00:00 2001 From: Kai Heng Feng Date: Mon, 5 Feb 2018 13:19:24 +0800 Subject: [PATCH 140/237] ACPI / bus: Parse tables as term_list for Dell XPS 9570 and Precision M5530 The i2c touchpad on Dell XPS 9570 and Precision M5530 doesn't work out of box. The touchpad relies on its _INI method to update its _HID value from XXXX0000 to SYNA2393. Also, the _STA relies on value of I2CN to report correct status. Set acpi_gbl_parse_table_as_term_list so the value of I2CN can be correctly set up, and _INI can get run. The ACPI table in this machine is designed to get parsed this way. Also, change the quirk table to a more generic name. Link: https://bugzilla.kernel.org/show_bug.cgi?id=198515 Signed-off-by: Kai-Heng Feng Signed-off-by: Rafael J. Wysocki --- drivers/acpi/bus.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 433bb5a3f32779..5c00e5e18da8c1 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -66,10 +66,37 @@ static int set_copy_dsdt(const struct dmi_system_id *id) return 0; } #endif +static int set_gbl_term_list(const struct dmi_system_id *id) +{ + acpi_gbl_parse_table_as_term_list = 1; + return 0; +} -static const struct dmi_system_id dsdt_dmi_table[] __initconst = { +static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = { + /* + * Touchpad on Dell XPS 9570/Precision M5530 doesn't work under I2C + * mode. + * https://bugzilla.kernel.org/show_bug.cgi?id=198515 + */ + { + .callback = set_gbl_term_list, + .ident = "Dell Precision M5530", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Precision M5530"), + }, + }, + { + .callback = set_gbl_term_list, + .ident = "Dell XPS 15 9570", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "XPS 15 9570"), + }, + }, /* * Invoke DSDT corruption work-around on all Toshiba Satellite. + * DSDT will be copied to memory. * https://bugzilla.kernel.org/show_bug.cgi?id=14679 */ { @@ -83,7 +110,7 @@ static const struct dmi_system_id dsdt_dmi_table[] __initconst = { {} }; #else -static const struct dmi_system_id dsdt_dmi_table[] __initconst = { +static const struct dmi_system_id acpi_quirks_dmi_table[] __initconst = { {} }; #endif @@ -1008,11 +1035,8 @@ void __init acpi_early_init(void) acpi_permanent_mmap = true; - /* - * If the machine falls into the DMI check table, - * DSDT will be copied to memory - */ - dmi_check_system(dsdt_dmi_table); + /* Check machine-specific quirks */ + dmi_check_system(acpi_quirks_dmi_table); status = acpi_reallocate_root_table(); if (ACPI_FAILURE(status)) { From f859422075165e32c00c8d75d63f300015cc07ae Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 6 Feb 2018 18:55:12 +0100 Subject: [PATCH 141/237] x86: PM: Make APM idle driver initialize polling state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update the APM driver overlooked by commit 1b39e3f813b4 (cpuidle: Make drivers initialize polling state) to initialize the polling state like the other cpuidle drivers modified by that commit to prevent cpuidle from crashing. Fixes: 1b39e3f813b4 (cpuidle: Make drivers initialize polling state) Reported-by: Ville Syrjälä Tested-by: Ville Syrjälä Cc: 4.14+ # 4.14+ Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/apm_32.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c index e4b0d92b3ae067..2a7fd56e67b364 100644 --- a/arch/x86/kernel/apm_32.c +++ b/arch/x86/kernel/apm_32.c @@ -2389,6 +2389,7 @@ static int __init apm_init(void) if (HZ != 100) idle_period = (idle_period * HZ) / 100; if (idle_threshold < 100) { + cpuidle_poll_state_init(&apm_idle_driver); if (!cpuidle_register_driver(&apm_idle_driver)) if (cpuidle_register_device(&apm_cpuidle_device)) cpuidle_unregister_driver(&apm_idle_driver); From 7569a06dc80ec05c96783f541fa706ea3bebec79 Mon Sep 17 00:00:00 2001 From: Weinan Li Date: Fri, 26 Jan 2018 15:09:07 +0800 Subject: [PATCH 142/237] drm/i915/gvt: refine intel_vgpu_submission_ops as per engine ops Using per engine ops will be more flexible, here refine sub-ops(init, clean) as per engine operation align with reset operation. This change also will be used in next fix patch for VM engine reset. Cc: Fred Gao Cc: Zhi Wang Signed-off-by: Weinan Li Signed-off-by: Zhenyu Wang Signed-off-by: Zhi Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/execlist.c | 22 +++++++++++----------- drivers/gpu/drm/i915/gvt/gvt.h | 4 ++-- drivers/gpu/drm/i915/gvt/handlers.c | 1 + drivers/gpu/drm/i915/gvt/scheduler.c | 7 ++++--- drivers/gpu/drm/i915/gvt/scheduler.h | 1 + drivers/gpu/drm/i915/gvt/vgpu.c | 3 +-- 6 files changed, 20 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/execlist.c b/drivers/gpu/drm/i915/gvt/execlist.c index 769c1c24ae7598..70494e394d2cbd 100644 --- a/drivers/gpu/drm/i915/gvt/execlist.c +++ b/drivers/gpu/drm/i915/gvt/execlist.c @@ -521,24 +521,23 @@ static void init_vgpu_execlist(struct intel_vgpu *vgpu, int ring_id) ctx_status_ptr_reg = execlist_ring_mmio(vgpu->gvt, ring_id, _EL_OFFSET_STATUS_PTR); - ctx_status_ptr.dw = vgpu_vreg(vgpu, ctx_status_ptr_reg); ctx_status_ptr.read_ptr = 0; ctx_status_ptr.write_ptr = 0x7; vgpu_vreg(vgpu, ctx_status_ptr_reg) = ctx_status_ptr.dw; } -static void clean_execlist(struct intel_vgpu *vgpu) +static void clean_execlist(struct intel_vgpu *vgpu, unsigned long engine_mask) { - enum intel_engine_id i; + unsigned int tmp; + struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv; struct intel_engine_cs *engine; + struct intel_vgpu_submission *s = &vgpu->submission; - for_each_engine(engine, vgpu->gvt->dev_priv, i) { - struct intel_vgpu_submission *s = &vgpu->submission; - - kfree(s->ring_scan_buffer[i]); - s->ring_scan_buffer[i] = NULL; - s->ring_scan_buffer_size[i] = 0; + for_each_engine_masked(engine, dev_priv, engine_mask, tmp) { + kfree(s->ring_scan_buffer[engine->id]); + s->ring_scan_buffer[engine->id] = NULL; + s->ring_scan_buffer_size[engine->id] = 0; } } @@ -553,9 +552,10 @@ static void reset_execlist(struct intel_vgpu *vgpu, init_vgpu_execlist(vgpu, engine->id); } -static int init_execlist(struct intel_vgpu *vgpu) +static int init_execlist(struct intel_vgpu *vgpu, + unsigned long engine_mask) { - reset_execlist(vgpu, ALL_ENGINES); + reset_execlist(vgpu, engine_mask); return 0; } diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 7dc7a80213a8af..c88c48989822da 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -152,8 +152,8 @@ enum { struct intel_vgpu_submission_ops { const char *name; - int (*init)(struct intel_vgpu *vgpu); - void (*clean)(struct intel_vgpu *vgpu); + int (*init)(struct intel_vgpu *vgpu, unsigned long engine_mask); + void (*clean)(struct intel_vgpu *vgpu, unsigned long engine_mask); void (*reset)(struct intel_vgpu *vgpu, unsigned long engine_mask); }; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 38f3b00d3a7a0e..befda75601ff6c 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1527,6 +1527,7 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, return 0; ret = intel_vgpu_select_submission_ops(vgpu, + ALL_ENGINES, INTEL_VGPU_EXECLIST_SUBMISSION); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index 0056638b0c16dc..f0997a2f05138f 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -991,7 +991,7 @@ void intel_vgpu_clean_submission(struct intel_vgpu *vgpu) { struct intel_vgpu_submission *s = &vgpu->submission; - intel_vgpu_select_submission_ops(vgpu, 0); + intel_vgpu_select_submission_ops(vgpu, ALL_ENGINES, 0); i915_gem_context_put(s->shadow_ctx); kmem_cache_destroy(s->workloads); } @@ -1079,6 +1079,7 @@ int intel_vgpu_setup_submission(struct intel_vgpu *vgpu) * */ int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu, + unsigned long engine_mask, unsigned int interface) { struct intel_vgpu_submission *s = &vgpu->submission; @@ -1092,7 +1093,7 @@ int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu, return -EINVAL; if (s->active) { - s->ops->clean(vgpu); + s->ops->clean(vgpu, engine_mask); s->active = false; gvt_dbg_core("vgpu%d: de-select ops [ %s ] \n", vgpu->id, s->ops->name); @@ -1105,7 +1106,7 @@ int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu, return 0; } - ret = ops[interface]->init(vgpu); + ret = ops[interface]->init(vgpu, engine_mask); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/gvt/scheduler.h b/drivers/gpu/drm/i915/gvt/scheduler.h index 3de77dfa7c59f2..ff175a98b19ed4 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.h +++ b/drivers/gpu/drm/i915/gvt/scheduler.h @@ -141,6 +141,7 @@ void intel_vgpu_reset_submission(struct intel_vgpu *vgpu, void intel_vgpu_clean_submission(struct intel_vgpu *vgpu); int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu, + unsigned long engine_mask, unsigned int interface); extern const struct intel_vgpu_submission_ops diff --git a/drivers/gpu/drm/i915/gvt/vgpu.c b/drivers/gpu/drm/i915/gvt/vgpu.c index a8784fa91289c8..b87b19d8443c64 100644 --- a/drivers/gpu/drm/i915/gvt/vgpu.c +++ b/drivers/gpu/drm/i915/gvt/vgpu.c @@ -520,8 +520,7 @@ void intel_gvt_reset_vgpu_locked(struct intel_vgpu *vgpu, bool dmlr, intel_vgpu_reset_submission(vgpu, resetting_eng); /* full GPU reset or device model level reset */ if (engine_mask == ALL_ENGINES || dmlr) { - intel_vgpu_select_submission_ops(vgpu, 0); - + intel_vgpu_select_submission_ops(vgpu, ALL_ENGINES, 0); /*fence will not be reset during virtual reset */ if (dmlr) { intel_vgpu_reset_gtt(vgpu); From 9212b13f28374815d9def65e3c877a35092e1c6e Mon Sep 17 00:00:00 2001 From: Weinan Li Date: Fri, 26 Jan 2018 15:09:08 +0800 Subject: [PATCH 143/237] drm/i915/gvt: only reset execlist state of one engine during VM engine reset Only reset vgpu execlist state of the exact engine which gets reset request from VM. After read context status from HWSP enabled, KMD will use the saved CSB read pointer but not always read from MMIO. When one engine reset happen, only the read pointer of this engine will be reset, in GVT-g host side also need to align with this policy, otherwise VM may get wrong CSB status after one engine reset compeleted. v2: Split refine and fix patch, code refine(Zhenyu) v3: Move active flag of vgpu scheduler into sched_data(Zhenyu) Cc: Fred Gao Cc: Zhi Wang Cc: Zhenyu Wang Signed-off-by: Weinan Li Signed-off-by: Zhenyu Wang Signed-off-by: Zhi Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/handlers.c | 8 ++------ drivers/gpu/drm/i915/gvt/sched_policy.c | 14 ++++++++++++-- drivers/gpu/drm/i915/gvt/scheduler.c | 12 ++++++------ 3 files changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index befda75601ff6c..9be639aa3b5543 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1494,7 +1494,6 @@ static int elsp_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, void *p_data, unsigned int bytes) { - struct intel_vgpu_submission *s = &vgpu->submission; u32 data = *(u32 *)p_data; int ring_id = intel_gvt_render_mmio_to_ring_id(vgpu->gvt, offset); bool enable_execlist; @@ -1523,12 +1522,9 @@ static int ring_mode_mmio_write(struct intel_vgpu *vgpu, unsigned int offset, if (!enable_execlist) return 0; - if (s->active) - return 0; - ret = intel_vgpu_select_submission_ops(vgpu, - ALL_ENGINES, - INTEL_VGPU_EXECLIST_SUBMISSION); + ENGINE_MASK(ring_id), + INTEL_VGPU_EXECLIST_SUBMISSION); if (ret) return ret; diff --git a/drivers/gpu/drm/i915/gvt/sched_policy.c b/drivers/gpu/drm/i915/gvt/sched_policy.c index d031f6486ce3fa..cc1ce361cd76a3 100644 --- a/drivers/gpu/drm/i915/gvt/sched_policy.c +++ b/drivers/gpu/drm/i915/gvt/sched_policy.c @@ -50,6 +50,7 @@ static bool vgpu_has_pending_workload(struct intel_vgpu *vgpu) struct vgpu_sched_data { struct list_head lru_list; struct intel_vgpu *vgpu; + bool active; ktime_t sched_in_time; ktime_t sched_out_time; @@ -332,6 +333,7 @@ static void tbs_sched_start_schedule(struct intel_vgpu *vgpu) if (!hrtimer_active(&sched_data->timer)) hrtimer_start(&sched_data->timer, ktime_add_ns(ktime_get(), sched_data->period), HRTIMER_MODE_ABS); + vgpu_data->active = true; } static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu) @@ -339,6 +341,7 @@ static void tbs_sched_stop_schedule(struct intel_vgpu *vgpu) struct vgpu_sched_data *vgpu_data = vgpu->sched_data; list_del_init(&vgpu_data->lru_list); + vgpu_data->active = false; } static struct intel_gvt_sched_policy_ops tbs_schedule_ops = { @@ -374,9 +377,12 @@ void intel_vgpu_clean_sched_policy(struct intel_vgpu *vgpu) void intel_vgpu_start_schedule(struct intel_vgpu *vgpu) { - gvt_dbg_core("vgpu%d: start schedule\n", vgpu->id); + struct vgpu_sched_data *vgpu_data = vgpu->sched_data; - vgpu->gvt->scheduler.sched_ops->start_schedule(vgpu); + if (!vgpu_data->active) { + gvt_dbg_core("vgpu%d: start schedule\n", vgpu->id); + vgpu->gvt->scheduler.sched_ops->start_schedule(vgpu); + } } void intel_gvt_kick_schedule(struct intel_gvt *gvt) @@ -389,6 +395,10 @@ void intel_vgpu_stop_schedule(struct intel_vgpu *vgpu) struct intel_gvt_workload_scheduler *scheduler = &vgpu->gvt->scheduler; int ring_id; + struct vgpu_sched_data *vgpu_data = vgpu->sched_data; + + if (!vgpu_data->active) + return; gvt_dbg_core("vgpu%d: stop schedule\n", vgpu->id); diff --git a/drivers/gpu/drm/i915/gvt/scheduler.c b/drivers/gpu/drm/i915/gvt/scheduler.c index f0997a2f05138f..b55b3580ca1dd0 100644 --- a/drivers/gpu/drm/i915/gvt/scheduler.c +++ b/drivers/gpu/drm/i915/gvt/scheduler.c @@ -1092,17 +1092,17 @@ int intel_vgpu_select_submission_ops(struct intel_vgpu *vgpu, if (WARN_ON(interface >= ARRAY_SIZE(ops))) return -EINVAL; - if (s->active) { + if (WARN_ON(interface == 0 && engine_mask != ALL_ENGINES)) + return -EINVAL; + + if (s->active) s->ops->clean(vgpu, engine_mask); - s->active = false; - gvt_dbg_core("vgpu%d: de-select ops [ %s ] \n", - vgpu->id, s->ops->name); - } if (interface == 0) { s->ops = NULL; s->virtual_submission_interface = 0; - gvt_dbg_core("vgpu%d: no submission ops\n", vgpu->id); + s->active = false; + gvt_dbg_core("vgpu%d: remove submission ops\n", vgpu->id); return 0; } From d480b28a41a628e356dbacfa1c9f6d05b9baf838 Mon Sep 17 00:00:00 2001 From: Changbin Du Date: Tue, 30 Jan 2018 13:51:31 +0800 Subject: [PATCH 144/237] drm/i915/gvt: Fix aperture read/write emulation when enable x-no-mmap=on When add 'x-no-mmap=on' for vfio-pci option, aperture access in guest is emulated. But the vgpu_aperture_rw() function take wrong offset when do memcpy, since vgpu->gm.aperture_va is not the base of entire aperture. This mistake cause GPU command in guest get lost and so the seqno is not updated in engine HWSP. This patch fix this, and it also move the emulation code to kvmgt. Because only vfio need to emulate it. Put aperture rw to MMIO emulation path breaks assumptions in xengt. v2: Remove PAGE_ALIGN for size (zhenyu) Fixes: f090a00df9ec ("drm/i915/gvt: Add emulation for BAR2 (aperture) with normal file RW approach") Signed-off-by: Changbin Du Signed-off-by: Zhi Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/cfg_space.c | 15 +--------- drivers/gpu/drm/i915/gvt/gvt.h | 1 - drivers/gpu/drm/i915/gvt/kvmgt.c | 36 ++++++++++++++++++++++-- drivers/gpu/drm/i915/gvt/mmio.c | 42 ---------------------------- 4 files changed, 35 insertions(+), 59 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/cfg_space.c b/drivers/gpu/drm/i915/gvt/cfg_space.c index 97bfc00d2a8204..c62346fdc05d5f 100644 --- a/drivers/gpu/drm/i915/gvt/cfg_space.c +++ b/drivers/gpu/drm/i915/gvt/cfg_space.c @@ -119,16 +119,6 @@ static int map_aperture(struct intel_vgpu *vgpu, bool map) if (map == vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked) return 0; - if (map) { - vgpu->gm.aperture_va = memremap(aperture_pa, aperture_sz, - MEMREMAP_WC); - if (!vgpu->gm.aperture_va) - return -ENOMEM; - } else { - memunmap(vgpu->gm.aperture_va); - vgpu->gm.aperture_va = NULL; - } - val = vgpu_cfg_space(vgpu)[PCI_BASE_ADDRESS_2]; if (val & PCI_BASE_ADDRESS_MEM_TYPE_64) val = *(u64 *)(vgpu_cfg_space(vgpu) + PCI_BASE_ADDRESS_2); @@ -141,11 +131,8 @@ static int map_aperture(struct intel_vgpu *vgpu, bool map) aperture_pa >> PAGE_SHIFT, aperture_sz >> PAGE_SHIFT, map); - if (ret) { - memunmap(vgpu->gm.aperture_va); - vgpu->gm.aperture_va = NULL; + if (ret) return ret; - } vgpu->cfg_space.bar[INTEL_GVT_PCI_BAR_APERTURE].tracked = map; return 0; diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index c88c48989822da..39bfe81f79ab93 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -82,7 +82,6 @@ struct intel_gvt_device_info { struct intel_vgpu_gm { u64 aperture_sz; u64 hidden_sz; - void *aperture_va; struct drm_mm_node low_gm_node; struct drm_mm_node high_gm_node; }; diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c index eb92572056c37e..801a3375c7b4fc 100644 --- a/drivers/gpu/drm/i915/gvt/kvmgt.c +++ b/drivers/gpu/drm/i915/gvt/kvmgt.c @@ -651,6 +651,39 @@ static int intel_vgpu_bar_rw(struct intel_vgpu *vgpu, int bar, uint64_t off, return ret; } +static inline bool intel_vgpu_in_aperture(struct intel_vgpu *vgpu, uint64_t off) +{ + return off >= vgpu_aperture_offset(vgpu) && + off < vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu); +} + +static int intel_vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t off, + void *buf, unsigned long count, bool is_write) +{ + void *aperture_va; + + if (!intel_vgpu_in_aperture(vgpu, off) || + !intel_vgpu_in_aperture(vgpu, off + count)) { + gvt_vgpu_err("Invalid aperture offset %llu\n", off); + return -EINVAL; + } + + aperture_va = io_mapping_map_wc(&vgpu->gvt->dev_priv->ggtt.iomap, + ALIGN_DOWN(off, PAGE_SIZE), + count + offset_in_page(off)); + if (!aperture_va) + return -EIO; + + if (is_write) + memcpy(aperture_va + offset_in_page(off), buf, count); + else + memcpy(buf, aperture_va + offset_in_page(off), count); + + io_mapping_unmap(aperture_va); + + return 0; +} + static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, size_t count, loff_t *ppos, bool is_write) { @@ -679,8 +712,7 @@ static ssize_t intel_vgpu_rw(struct mdev_device *mdev, char *buf, buf, count, is_write); break; case VFIO_PCI_BAR2_REGION_INDEX: - ret = intel_vgpu_bar_rw(vgpu, PCI_BASE_ADDRESS_2, pos, - buf, count, is_write); + ret = intel_vgpu_aperture_rw(vgpu, pos, buf, count, is_write); break; case VFIO_PCI_BAR1_REGION_INDEX: case VFIO_PCI_BAR3_REGION_INDEX: diff --git a/drivers/gpu/drm/i915/gvt/mmio.c b/drivers/gpu/drm/i915/gvt/mmio.c index 562b5ad857a4ee..5c869e3fdf3bc5 100644 --- a/drivers/gpu/drm/i915/gvt/mmio.c +++ b/drivers/gpu/drm/i915/gvt/mmio.c @@ -56,38 +56,6 @@ int intel_vgpu_gpa_to_mmio_offset(struct intel_vgpu *vgpu, u64 gpa) (reg >= gvt->device_info.gtt_start_offset \ && reg < gvt->device_info.gtt_start_offset + gvt_ggtt_sz(gvt)) -static bool vgpu_gpa_is_aperture(struct intel_vgpu *vgpu, uint64_t gpa) -{ - u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2); - u64 aperture_sz = vgpu_aperture_sz(vgpu); - - return gpa >= aperture_gpa && gpa < aperture_gpa + aperture_sz; -} - -static int vgpu_aperture_rw(struct intel_vgpu *vgpu, uint64_t gpa, - void *pdata, unsigned int size, bool is_read) -{ - u64 aperture_gpa = intel_vgpu_get_bar_gpa(vgpu, PCI_BASE_ADDRESS_2); - u64 offset = gpa - aperture_gpa; - - if (!vgpu_gpa_is_aperture(vgpu, gpa + size - 1)) { - gvt_vgpu_err("Aperture rw out of range, offset %llx, size %d\n", - offset, size); - return -EINVAL; - } - - if (!vgpu->gm.aperture_va) { - gvt_vgpu_err("BAR is not enabled\n"); - return -ENXIO; - } - - if (is_read) - memcpy(pdata, vgpu->gm.aperture_va + offset, size); - else - memcpy(vgpu->gm.aperture_va + offset, pdata, size); - return 0; -} - static void failsafe_emulate_mmio_rw(struct intel_vgpu *vgpu, uint64_t pa, void *p_data, unsigned int bytes, bool read) { @@ -144,11 +112,6 @@ int intel_vgpu_emulate_mmio_read(struct intel_vgpu *vgpu, uint64_t pa, } mutex_lock(&gvt->lock); - if (vgpu_gpa_is_aperture(vgpu, pa)) { - ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, true); - goto out; - } - offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa); if (WARN_ON(bytes > 8)) @@ -222,11 +185,6 @@ int intel_vgpu_emulate_mmio_write(struct intel_vgpu *vgpu, uint64_t pa, mutex_lock(&gvt->lock); - if (vgpu_gpa_is_aperture(vgpu, pa)) { - ret = vgpu_aperture_rw(vgpu, pa, p_data, bytes, false); - goto out; - } - offset = intel_vgpu_gpa_to_mmio_offset(vgpu, pa); if (WARN_ON(bytes > 8)) From 95925b9595d95fdf2bfb73fc73dfb696f0c3fc7f Mon Sep 17 00:00:00 2001 From: Tina Zhang Date: Wed, 31 Jan 2018 14:42:44 +0800 Subject: [PATCH 145/237] drm/i915/gvt: Use KVM r/w to access guest opregion For KVMGT, the guest opregion, which is handled by VFIO, is actually a piece of guest memory which won't be accessed by devices. So, its mfn shouldn't be obtained through VFIO interface. This patch uses KVM r/w interface to access the data in guest opregion. Fix the guest opregion accessing issue when host "intel_iommu=on". v3: - Remove mapped flag for KVM/VFIO usage, as it's useless for KVM. v2: - Set the gpa correctly when invoking KVM r/w operations. (Zhenyu) Signed-off-by: Tina Zhang Cc: Yan Zhao Cc: Xiong Zhang Signed-off-by: Zhi Wang Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/gvt/gvt.h | 1 - drivers/gpu/drm/i915/gvt/opregion.c | 98 ++++++++++++++++++++--------- 2 files changed, 70 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/i915/gvt/gvt.h b/drivers/gpu/drm/i915/gvt/gvt.h index 39bfe81f79ab93..c6197d99081861 100644 --- a/drivers/gpu/drm/i915/gvt/gvt.h +++ b/drivers/gpu/drm/i915/gvt/gvt.h @@ -126,7 +126,6 @@ struct intel_vgpu_irq { struct intel_vgpu_opregion { bool mapped; void *va; - void *va_gopregion; u32 gfn[INTEL_GVT_OPREGION_PAGES]; }; diff --git a/drivers/gpu/drm/i915/gvt/opregion.c b/drivers/gpu/drm/i915/gvt/opregion.c index 8420d1fc3ddbe9..fa75a2eead9070 100644 --- a/drivers/gpu/drm/i915/gvt/opregion.c +++ b/drivers/gpu/drm/i915/gvt/opregion.c @@ -299,21 +299,13 @@ int intel_vgpu_opregion_base_write_handler(struct intel_vgpu *vgpu, u32 gpa) { int i, ret = 0; - unsigned long pfn; gvt_dbg_core("emulate opregion from kernel\n"); switch (intel_gvt_host.hypervisor_type) { case INTEL_GVT_HYPERVISOR_KVM: - pfn = intel_gvt_hypervisor_gfn_to_mfn(vgpu, gpa >> PAGE_SHIFT); - vgpu_opregion(vgpu)->va_gopregion = memremap(pfn << PAGE_SHIFT, - INTEL_GVT_OPREGION_SIZE, - MEMREMAP_WB); - if (!vgpu_opregion(vgpu)->va_gopregion) { - gvt_vgpu_err("failed to map guest opregion\n"); - ret = -EFAULT; - } - vgpu_opregion(vgpu)->mapped = true; + for (i = 0; i < INTEL_GVT_OPREGION_PAGES; i++) + vgpu_opregion(vgpu)->gfn[i] = (gpa >> PAGE_SHIFT) + i; break; case INTEL_GVT_HYPERVISOR_XEN: /** @@ -352,10 +344,7 @@ void intel_vgpu_clean_opregion(struct intel_vgpu *vgpu) if (vgpu_opregion(vgpu)->mapped) map_vgpu_opregion(vgpu, false); } else if (intel_gvt_host.hypervisor_type == INTEL_GVT_HYPERVISOR_KVM) { - if (vgpu_opregion(vgpu)->mapped) { - memunmap(vgpu_opregion(vgpu)->va_gopregion); - vgpu_opregion(vgpu)->va_gopregion = NULL; - } + /* Guest opregion is released by VFIO */ } free_pages((unsigned long)vgpu_opregion(vgpu)->va, get_order(INTEL_GVT_OPREGION_SIZE)); @@ -480,19 +469,40 @@ static bool querying_capabilities(u32 scic) */ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci) { - u32 *scic, *parm; + u32 scic, parm; u32 func, subfunc; + u64 scic_pa = 0, parm_pa = 0; + int ret; switch (intel_gvt_host.hypervisor_type) { case INTEL_GVT_HYPERVISOR_XEN: - scic = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_SCIC; - parm = vgpu_opregion(vgpu)->va + INTEL_GVT_OPREGION_PARM; + scic = *((u32 *)vgpu_opregion(vgpu)->va + + INTEL_GVT_OPREGION_SCIC); + parm = *((u32 *)vgpu_opregion(vgpu)->va + + INTEL_GVT_OPREGION_PARM); break; case INTEL_GVT_HYPERVISOR_KVM: - scic = vgpu_opregion(vgpu)->va_gopregion + - INTEL_GVT_OPREGION_SCIC; - parm = vgpu_opregion(vgpu)->va_gopregion + - INTEL_GVT_OPREGION_PARM; + scic_pa = (vgpu_opregion(vgpu)->gfn[0] << PAGE_SHIFT) + + INTEL_GVT_OPREGION_SCIC; + parm_pa = (vgpu_opregion(vgpu)->gfn[0] << PAGE_SHIFT) + + INTEL_GVT_OPREGION_PARM; + + ret = intel_gvt_hypervisor_read_gpa(vgpu, scic_pa, + &scic, sizeof(scic)); + if (ret) { + gvt_vgpu_err("guest opregion read error %d, gpa 0x%llx, len %lu\n", + ret, scic_pa, sizeof(scic)); + return ret; + } + + ret = intel_gvt_hypervisor_read_gpa(vgpu, parm_pa, + &parm, sizeof(parm)); + if (ret) { + gvt_vgpu_err("guest opregion read error %d, gpa 0x%llx, len %lu\n", + ret, scic_pa, sizeof(scic)); + return ret; + } + break; default: gvt_vgpu_err("not supported hypervisor\n"); @@ -510,9 +520,9 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci) return 0; } - func = GVT_OPREGION_FUNC(*scic); - subfunc = GVT_OPREGION_SUBFUNC(*scic); - if (!querying_capabilities(*scic)) { + func = GVT_OPREGION_FUNC(scic); + subfunc = GVT_OPREGION_SUBFUNC(scic); + if (!querying_capabilities(scic)) { gvt_vgpu_err("requesting runtime service: func \"%s\"," " subfunc \"%s\"\n", opregion_func_name(func), @@ -521,11 +531,43 @@ int intel_vgpu_emulate_opregion_request(struct intel_vgpu *vgpu, u32 swsci) * emulate exit status of function call, '0' means * "failure, generic, unsupported or unknown cause" */ - *scic &= ~OPREGION_SCIC_EXIT_MASK; - return 0; + scic &= ~OPREGION_SCIC_EXIT_MASK; + goto out; + } + + scic = 0; + parm = 0; + +out: + switch (intel_gvt_host.hypervisor_type) { + case INTEL_GVT_HYPERVISOR_XEN: + *((u32 *)vgpu_opregion(vgpu)->va + + INTEL_GVT_OPREGION_SCIC) = scic; + *((u32 *)vgpu_opregion(vgpu)->va + + INTEL_GVT_OPREGION_PARM) = parm; + break; + case INTEL_GVT_HYPERVISOR_KVM: + ret = intel_gvt_hypervisor_write_gpa(vgpu, scic_pa, + &scic, sizeof(scic)); + if (ret) { + gvt_vgpu_err("guest opregion write error %d, gpa 0x%llx, len %lu\n", + ret, scic_pa, sizeof(scic)); + return ret; + } + + ret = intel_gvt_hypervisor_write_gpa(vgpu, parm_pa, + &parm, sizeof(parm)); + if (ret) { + gvt_vgpu_err("guest opregion write error %d, gpa 0x%llx, len %lu\n", + ret, scic_pa, sizeof(scic)); + return ret; + } + + break; + default: + gvt_vgpu_err("not supported hypervisor\n"); + return -EINVAL; } - *scic = 0; - *parm = 0; return 0; } From 5e1df40f40ee45a97bb1066c3d71f0ae920a9672 Mon Sep 17 00:00:00 2001 From: Imre Deak Date: Tue, 30 Jan 2018 16:29:38 +0200 Subject: [PATCH 146/237] drm/i915/bxt, glk: Increase PCODE timeouts during CDCLK freq changing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently we see sporadic timeouts during CDCLK changing both on BXT and GLK as reported by the Bugzilla: ticket. It's easy to reproduce this by changing the frequency in a tight loop after blanking the display. The upper bound for the completion time is 800us based on my tests, so increase it from the current 500us to 2ms; with that I couldn't trigger the problem either on BXT or GLK. Note that timeouts happened during both the change notification and the voltage level setting PCODE request. (For the latter one BSpec doesn't require us to wait for completion before further HW programming.) This issue is similar to commit 2c7d0602c815 ("drm/i915/gen9: Fix PCODE polling during CDCLK change notification") but there the PCODE request does complete (as shown by the mbox busy flag), only the reply we get from PCODE indicates a failure. So there we keep resending the request until a success reply, here we just have to increase the timeout for the one PCODE request we send. v2: - s/snb_pcode_request/sandybridge_pcode_write_timeout/ (Ville) Cc: Chris Wilson Cc: Ville Syrjälä Cc: # v4.4+ Acked-by: Chris Wilson (v1) Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103326 Reviewed-by: Ville Syrjälä Signed-off-by: Imre Deak Link: https://patchwork.freedesktop.org/patch/msgid/20180130142939.17983-1-imre.deak@intel.com (cherry picked from commit e76019a81921e87a4d9e7b3d86102bc708a6c227) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_drv.h | 6 +++++- drivers/gpu/drm/i915/intel_cdclk.c | 22 +++++++++++++++++----- drivers/gpu/drm/i915/intel_pm.c | 6 +++--- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index caebd5825279e4..a42deebedb0f12 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -3717,7 +3717,11 @@ extern void intel_display_print_error_state(struct drm_i915_error_state_buf *e, struct intel_display_error_state *error); int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val); -int sandybridge_pcode_write(struct drm_i915_private *dev_priv, u32 mbox, u32 val); +int sandybridge_pcode_write_timeout(struct drm_i915_private *dev_priv, u32 mbox, + u32 val, int timeout_us); +#define sandybridge_pcode_write(dev_priv, mbox, val) \ + sandybridge_pcode_write_timeout(dev_priv, mbox, val, 500) + int skl_pcode_request(struct drm_i915_private *dev_priv, u32 mbox, u32 request, u32 reply_mask, u32 reply, int timeout_base_ms); diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index d77e2bec1e29de..5dc118f26b51b7 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -1370,10 +1370,15 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, break; } - /* Inform power controller of upcoming frequency change */ + /* + * Inform power controller of upcoming frequency change. BSpec + * requires us to wait up to 150usec, but that leads to timeouts; + * the 2ms used here is based on experiment. + */ mutex_lock(&dev_priv->pcu_lock); - ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, - 0x80000000); + ret = sandybridge_pcode_write_timeout(dev_priv, + HSW_PCODE_DE_WRITE_FREQ_REQ, + 0x80000000, 2000); mutex_unlock(&dev_priv->pcu_lock); if (ret) { @@ -1404,8 +1409,15 @@ static void bxt_set_cdclk(struct drm_i915_private *dev_priv, I915_WRITE(CDCLK_CTL, val); mutex_lock(&dev_priv->pcu_lock); - ret = sandybridge_pcode_write(dev_priv, HSW_PCODE_DE_WRITE_FREQ_REQ, - cdclk_state->voltage_level); + /* + * The timeout isn't specified, the 2ms used here is based on + * experiment. + * FIXME: Waiting for the request completion could be delayed until + * the next PCODE request based on BSpec. + */ + ret = sandybridge_pcode_write_timeout(dev_priv, + HSW_PCODE_DE_WRITE_FREQ_REQ, + cdclk_state->voltage_level, 2000); mutex_unlock(&dev_priv->pcu_lock); if (ret) { diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1db79a860b96ee..1a6e699e19e004 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -9149,8 +9149,8 @@ int sandybridge_pcode_read(struct drm_i915_private *dev_priv, u32 mbox, u32 *val return 0; } -int sandybridge_pcode_write(struct drm_i915_private *dev_priv, - u32 mbox, u32 val) +int sandybridge_pcode_write_timeout(struct drm_i915_private *dev_priv, + u32 mbox, u32 val, int timeout_us) { int status; @@ -9173,7 +9173,7 @@ int sandybridge_pcode_write(struct drm_i915_private *dev_priv, if (__intel_wait_for_register_fw(dev_priv, GEN6_PCODE_MAILBOX, GEN6_PCODE_READY, 0, - 500, 0, NULL)) { + timeout_us, 0, NULL)) { DRM_ERROR("timeout waiting for pcode write of 0x%08x to mbox %x to finish for %ps\n", val, mbox, __builtin_return_address(0)); return -ETIMEDOUT; From b18224e95cb13ef7517aa26e6b47c85117327f11 Mon Sep 17 00:00:00 2001 From: Michal Srb Date: Mon, 5 Feb 2018 16:04:37 +0000 Subject: [PATCH 147/237] drm/i915/cmdparser: Check reg_table_count before derefencing. The find_reg function was assuming that there is always at least one table in reg_tables. It is not always true. In case of VCS or VECS, the reg_tables is NULL and reg_table_count is 0, implying that no register-accessing commands are allowed. However, the command tables include commands such as MI_STORE_REGISTER_MEM. When trying to check such command, the find_reg would dereference NULL pointer. Now it will just return NULL meaning that the register was not found and the command will be rejected. Fixes: 76ff480ec963 ("drm/i915/cmdparser: Use binary search for faster register lookup") Signed-off-by: Michal Srb Link: https://patchwork.freedesktop.org/patch/msgid/20180205142916.27092-2-msrb@suse.com Cc: Chris Wilson Cc: Matthew Auld Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180205160438.3267-1-chris@chris-wilson.co.uk register lookup") (cherry picked from commit 2f265fad9756a40c09e3f4dcc62d5d7fa73a9fb2) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_cmd_parser.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index ccb5ba043b63a3..ab4c8b0ec886e2 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1032,7 +1032,7 @@ find_reg(const struct intel_engine_cs *engine, bool is_master, u32 addr) const struct drm_i915_reg_table *table = engine->reg_tables; int count = engine->reg_table_count; - do { + for (; count > 0; ++table, --count) { if (!table->master || is_master) { const struct drm_i915_reg_descriptor *reg; @@ -1040,7 +1040,7 @@ find_reg(const struct intel_engine_cs *engine, bool is_master, u32 addr) if (reg != NULL) return reg; } - } while (table++, --count); + } return NULL; } From b3ad99ed45917f42884fee731fa3cf9b8229a26c Mon Sep 17 00:00:00 2001 From: Michal Srb Date: Mon, 5 Feb 2018 16:04:38 +0000 Subject: [PATCH 148/237] drm/i915/cmdparser: Do not check past the cmd length. The command MEDIA_VFE_STATE checks bits at offset +2 dwords. However, it is possible to have MEDIA_VFE_STATE command with length = 0 + LENGTH_BIAS = 2. In that case check_cmd will read bits from the following command, or even past the end of the buffer. If the offset ends up outside of the command length, reject the command. Fixes: 351e3db2b363 ("drm/i915: Implement command buffer parsing logic") Signed-off-by: Michal Srb Link: https://patchwork.freedesktop.org/patch/msgid/20180205151745.29292-1-msrb@suse.com Reviewed-by: Chris Wilson Signed-off-by: Chris Wilson Link: https://patchwork.freedesktop.org/patch/msgid/20180205160438.3267-2-chris@chris-wilson.co.uk (cherry picked from commit 3aec7f871c65eb5f76b4125fda432593c834a6f2) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/i915_cmd_parser.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/gpu/drm/i915/i915_cmd_parser.c b/drivers/gpu/drm/i915/i915_cmd_parser.c index ab4c8b0ec886e2..95478db9998b51 100644 --- a/drivers/gpu/drm/i915/i915_cmd_parser.c +++ b/drivers/gpu/drm/i915/i915_cmd_parser.c @@ -1212,6 +1212,12 @@ static bool check_cmd(const struct intel_engine_cs *engine, continue; } + if (desc->bits[i].offset >= length) { + DRM_DEBUG_DRIVER("CMD: Rejected command 0x%08X, too short to check bitmask (%s)\n", + *cmd, engine->name); + return false; + } + dword = cmd[desc->bits[i].offset] & desc->bits[i].mask; From f24c606c21a8cb6f75adc20edcd80b6d851991bf Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Tue, 23 Jan 2018 09:40:50 -0800 Subject: [PATCH 149/237] drm/i915/cnp: Ignore VBT request for know invalid DDC pin. Let's ignore VBT request if the pin is clearly wrong. Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=104139 Cc: Kai Heng Feng Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180123174050.4261-1-rodrigo.vivi@intel.com Reviewed-by: Radhakrishna Sripada (cherry picked from commit a8e6f3888b05c1e7b685800a3371ce050720368f) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_bios.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 51108ffc28d1d0..7c6391459d8f75 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1115,9 +1115,14 @@ static const u8 cnp_ddc_pin_map[] = { static u8 map_ddc_pin(struct drm_i915_private *dev_priv, u8 vbt_pin) { - if (HAS_PCH_CNP(dev_priv) && - vbt_pin > 0 && vbt_pin < ARRAY_SIZE(cnp_ddc_pin_map)) - return cnp_ddc_pin_map[vbt_pin]; + if (HAS_PCH_CNP(dev_priv)) { + if (vbt_pin > 0 && vbt_pin < ARRAY_SIZE(cnp_ddc_pin_map)) + return cnp_ddc_pin_map[vbt_pin]; + if (vbt_pin > GMBUS_PIN_4_CNP) { + DRM_DEBUG_KMS("Ignoring alternate pin: VBT claims DDC pin %d, which is not valid for this platform\n", vbt_pin); + return 0; + } + } return vbt_pin; } From 6e3322c226f15bc1838007f5a75566f1482b8e40 Mon Sep 17 00:00:00 2001 From: Rodrigo Vivi Date: Thu, 25 Jan 2018 14:25:24 -0800 Subject: [PATCH 150/237] drm/i915/cnp: Properly handle VBT ddc pin out of bounds. If the table result is out of bounds on the array map there is something really wrong with VBT pin so we don't return that vbt_pin, but only return 0 instead. This basically reverts commit 'a8e6f3888b05 ("drm/i915/cnp: Ignore VBT request for know invalid DDC pin.")' Also this properly fixes commit 9c3b2689d01f ("drm/i915/cnl: Map VBT DDC Pin to BSpec DDC Pin.") v2: Do in a way that we don't break other platforms. (Jani) v3: Keep debug message (Jani) v4: Don't mess with 0 mapping was noticed by Jani and addressed with a simple solution suggested by Lucas that makes this even simpler. Fixes: a8e6f3888b05 ("drm/i915/cnp: Ignore VBT request for know invalid DDC pin.") Fixes: 9c3b2689d01f ("drm/i915/cnl: Map VBT DDC Pin to BSpec DDC Pin.") Cc: Radhakrishna Sripada Cc: Jani Nikula Cc: Kai Heng Feng Cc: Lucas De Marchi Suggested-by: Lucas De Marchi Signed-off-by: Rodrigo Vivi Reviewed-by: Lucas De Marchi Tested-by: Kai-Heng Feng Link: https://patchwork.freedesktop.org/patch/msgid/20180125222524.22059-1-rodrigo.vivi@intel.com (cherry picked from commit 3393ce1ed8fc43dbdb83952facaf04e644ca1d54) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_bios.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 7c6391459d8f75..4c42cc4b193b87 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1107,6 +1107,7 @@ static void sanitize_aux_ch(struct drm_i915_private *dev_priv, } static const u8 cnp_ddc_pin_map[] = { + [0] = 0, /* N/A */ [DDC_BUS_DDI_B] = GMBUS_PIN_1_BXT, [DDC_BUS_DDI_C] = GMBUS_PIN_2_BXT, [DDC_BUS_DDI_D] = GMBUS_PIN_4_CNP, /* sic */ @@ -1116,9 +1117,9 @@ static const u8 cnp_ddc_pin_map[] = { static u8 map_ddc_pin(struct drm_i915_private *dev_priv, u8 vbt_pin) { if (HAS_PCH_CNP(dev_priv)) { - if (vbt_pin > 0 && vbt_pin < ARRAY_SIZE(cnp_ddc_pin_map)) + if (vbt_pin < ARRAY_SIZE(cnp_ddc_pin_map)) { return cnp_ddc_pin_map[vbt_pin]; - if (vbt_pin > GMBUS_PIN_4_CNP) { + } else { DRM_DEBUG_KMS("Ignoring alternate pin: VBT claims DDC pin %d, which is not valid for this platform\n", vbt_pin); return 0; } From 051803c0d01f4d8a197ecc08bfeffdff00d86c62 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 3 Nov 2017 23:06:32 -0400 Subject: [PATCH 151/237] radix tree test suite: Remove ARRAY_SIZE This is now defined in tools/include/linux/kernel.h, so our definition generates a warning. Signed-off-by: Matthew Wilcox --- tools/testing/radix-tree/linux/kernel.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/testing/radix-tree/linux/kernel.h b/tools/testing/radix-tree/linux/kernel.h index c3bc3f364f6827..426f32f2854706 100644 --- a/tools/testing/radix-tree/linux/kernel.h +++ b/tools/testing/radix-tree/linux/kernel.h @@ -17,6 +17,4 @@ #define pr_debug printk #define pr_cont printk -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - #endif /* _KERNEL_H */ From 490645d027c5925b30c88b9c7a663850a641d15d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 9 Nov 2017 20:15:14 -0500 Subject: [PATCH 152/237] idr test suite: Fix ida_test_random() The test was checking the wrong errno; ida_get_new_above() returns EAGAIN, not ENOMEM on memory allocation failure. Double the number of threads to increase the chance that we actually exercise this path during the test suite (it was a bit sporadic before). Signed-off-by: Matthew Wilcox --- tools/testing/radix-tree/idr-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 30cd0b296f1a76..193450b29bf014 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -380,7 +380,7 @@ void ida_check_random(void) do { ida_pre_get(&ida, GFP_KERNEL); err = ida_get_new_above(&ida, bit, &id); - } while (err == -ENOMEM); + } while (err == -EAGAIN); assert(!err); assert(id == bit); } @@ -489,7 +489,7 @@ static void *ida_random_fn(void *arg) void ida_thread_tests(void) { - pthread_t threads[10]; + pthread_t threads[20]; int i; for (i = 0; i < ARRAY_SIZE(threads); i++) From 6e6d301490936789ff57daaaaf63f44d928a4028 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 14:27:14 -0500 Subject: [PATCH 153/237] IDR test suite: Check handling negative end correctly One of the charming quirks of the idr_alloc() interface is that you can pass a negative end and it will be interpreted as "maximum". Ensure we don't break that. Signed-off-by: Matthew Wilcox --- tools/testing/radix-tree/idr-test.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 193450b29bf014..892ef8855b0245 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -207,6 +207,7 @@ void idr_checks(void) assert(idr_alloc(&idr, item, i, i + 10, GFP_KERNEL) == i); } assert(idr_alloc(&idr, DUMMY_PTR, i - 2, i, GFP_KERNEL) == -ENOSPC); + assert(idr_alloc(&idr, DUMMY_PTR, i - 2, i + 10, GFP_KERNEL) == -ENOSPC); idr_for_each(&idr, item_idr_free, &idr); idr_destroy(&idr); From b3f08b1301592936976eec0944c91e383e95803c Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Thu, 1 Feb 2018 18:06:34 +0000 Subject: [PATCH 154/237] MAINTAINERS: update orangefs list and add myself as reviewer Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 845fc25812f1db..9bf2c650d792e3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10181,7 +10181,8 @@ F: fs/ocfs2/ ORANGEFS FILESYSTEM M: Mike Marshall -L: pvfs2-developers@beowulf-underground.org (subscribers-only) +R: Martin Brandenburg +L: devel@lists.orangefs.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/hubcap/linux.git S: Supported F: fs/orangefs/ From 7a3bc1f019e3ba25c7056e651fb463f05e395e9d Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Fri, 26 Jan 2018 14:07:11 -0500 Subject: [PATCH 155/237] orangefs: make orangefs_client_debug_init static Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall --- fs/orangefs/orangefs-debugfs.c | 2 +- fs/orangefs/orangefs-debugfs.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c index 1c59dff530dee5..67d531ad5a562b 100644 --- a/fs/orangefs/orangefs-debugfs.c +++ b/fs/orangefs/orangefs-debugfs.c @@ -328,7 +328,7 @@ static int help_show(struct seq_file *m, void *v) /* * initialize the client-debug file. */ -int orangefs_client_debug_init(void) +static int orangefs_client_debug_init(void) { int rc = -ENOMEM; diff --git a/fs/orangefs/orangefs-debugfs.h b/fs/orangefs/orangefs-debugfs.h index b5fd9cd4960f41..51147f9ce3d6a1 100644 --- a/fs/orangefs/orangefs-debugfs.h +++ b/fs/orangefs/orangefs-debugfs.h @@ -1,7 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0 */ int orangefs_debugfs_init(int); void orangefs_debugfs_cleanup(void); -int orangefs_client_debug_init(void); int orangefs_prepare_debugfs_help_string(int); int orangefs_debugfs_new_client_mask(void __user *); int orangefs_debugfs_new_client_string(void __user *); From 79d7cd611d9e0ee9b4c38bd33f6082979826885f Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Fri, 26 Jan 2018 14:07:12 -0500 Subject: [PATCH 156/237] orangefs: remove gossip_ldebug and gossip_lerr gossip_ldebug is unused. gossip_lerr is used in two places. The messages are unique so line numbers are unnecessary. Also remove support for compiling gossip messages out. It wasn't possible to enable it anyway. Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall --- fs/orangefs/orangefs-debugfs.c | 2 +- fs/orangefs/protocol.h | 15 --------------- fs/orangefs/super.c | 2 +- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/fs/orangefs/orangefs-debugfs.c b/fs/orangefs/orangefs-debugfs.c index 67d531ad5a562b..6e35f2f3c897b5 100644 --- a/fs/orangefs/orangefs-debugfs.c +++ b/fs/orangefs/orangefs-debugfs.c @@ -1056,7 +1056,7 @@ int orangefs_debugfs_new_debug(void __user *arg) client_debug_string, llu(mask_info.mask_value)); } else { - gossip_lerr("Invalid mask type....\n"); + gossip_err("Invalid mask type....\n"); return -EINVAL; } diff --git a/fs/orangefs/protocol.h b/fs/orangefs/protocol.h index e0bf5e4dce0da1..dc6e3e6269c385 100644 --- a/fs/orangefs/protocol.h +++ b/fs/orangefs/protocol.h @@ -395,13 +395,6 @@ struct ORANGEFS_dev_map_desc { /* gossip.h *****************************************************************/ -#ifdef GOSSIP_DISABLE_DEBUG -#define gossip_debug(mask, fmt, ...) \ -do { \ - if (0) \ - printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ -} while (0) -#else extern __u64 orangefs_gossip_debug_mask; /* try to avoid function call overhead by checking masks in macro */ @@ -410,13 +403,5 @@ do { \ if (orangefs_gossip_debug_mask & (mask)) \ printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ } while (0) -#endif /* GOSSIP_DISABLE_DEBUG */ - -/* do file and line number printouts w/ the GNU preprocessor */ -#define gossip_ldebug(mask, fmt, ...) \ - gossip_debug(mask, "%s: " fmt, __func__, ##__VA_ARGS__) #define gossip_err pr_err -#define gossip_lerr(fmt, ...) \ - gossip_err("%s line %d: " fmt, \ - __FILE__, __LINE__, ##__VA_ARGS__) diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index 36f1390b5ed7d6..a4f4b508eff288 100644 --- a/fs/orangefs/super.c +++ b/fs/orangefs/super.c @@ -335,7 +335,7 @@ static int orangefs_encode_fh(struct inode *inode, struct orangefs_object_kref refn; if (*max_len < len) { - gossip_lerr("fh buffer is too small for encoding\n"); + gossip_err("fh buffer is too small for encoding\n"); *max_len = len; type = 255; goto out; From 538e30482155dbaaa53495ed37b889e9c2577cb9 Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Fri, 26 Jan 2018 14:07:13 -0500 Subject: [PATCH 157/237] orangefs: remove ORANGEFS_KERNEL_DEBUG It wasn't possible to enable it, and it would've had very little effect. Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall --- fs/orangefs/orangefs-kernel.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h index 2595453fe7370a..25bacc334d9186 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h @@ -56,11 +56,7 @@ #include "orangefs-dev-proto.h" -#ifdef ORANGEFS_KERNEL_DEBUG -#define ORANGEFS_DEFAULT_OP_TIMEOUT_SECS 10 -#else #define ORANGEFS_DEFAULT_OP_TIMEOUT_SECS 20 -#endif #define ORANGEFS_BUFMAP_WAIT_TIMEOUT_SECS 30 @@ -104,11 +100,11 @@ enum orangefs_vfs_op_states { * orangefs kernel memory related flags */ -#if ((defined ORANGEFS_KERNEL_DEBUG) && (defined CONFIG_DEBUG_SLAB)) +#if (defined CONFIG_DEBUG_SLAB) #define ORANGEFS_CACHE_CREATE_FLAGS SLAB_RED_ZONE #else #define ORANGEFS_CACHE_CREATE_FLAGS 0 -#endif /* ((defined ORANGEFS_KERNEL_DEBUG) && (defined CONFIG_DEBUG_SLAB)) */ +#endif extern int orangefs_init_acl(struct inode *inode, struct inode *dir); extern const struct xattr_handler *orangefs_xattr_handlers[]; From 4d0cac7e752cccb9eb30cd0f22438b9506ed51bc Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Fri, 26 Jan 2018 14:07:14 -0500 Subject: [PATCH 158/237] orangefs: make orangefs_make_bad_inode static Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall --- fs/orangefs/orangefs-kernel.h | 2 -- fs/orangefs/orangefs-utils.c | 38 +++++++++++++++++------------------ 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/fs/orangefs/orangefs-kernel.h b/fs/orangefs/orangefs-kernel.h index 25bacc334d9186..eebbaece85ef73 100644 --- a/fs/orangefs/orangefs-kernel.h +++ b/fs/orangefs/orangefs-kernel.h @@ -467,8 +467,6 @@ int orangefs_inode_check_changed(struct inode *inode); int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr); -void orangefs_make_bad_inode(struct inode *inode); - int orangefs_unmount_sb(struct super_block *sb); bool orangefs_cancel_op_in_progress(struct orangefs_kernel_op_s *op); diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c index 97fe93129f3887..3098c2ee7b5f1c 100644 --- a/fs/orangefs/orangefs-utils.c +++ b/fs/orangefs/orangefs-utils.c @@ -230,6 +230,25 @@ static int orangefs_inode_type(enum orangefs_ds_type objtype) return -1; } +static void orangefs_make_bad_inode(struct inode *inode) +{ + if (is_root_handle(inode)) { + /* + * if this occurs, the pvfs2-client-core was killed but we + * can't afford to lose the inode operations and such + * associated with the root handle in any case. + */ + gossip_debug(GOSSIP_UTILS_DEBUG, + "*** NOT making bad root inode %pU\n", + get_khandle_from_ino(inode)); + } else { + gossip_debug(GOSSIP_UTILS_DEBUG, + "*** making bad inode %pU\n", + get_khandle_from_ino(inode)); + make_bad_inode(inode); + } +} + static int orangefs_inode_is_stale(struct inode *inode, int new, struct ORANGEFS_sys_attr_s *attrs, char *link_target) { @@ -444,25 +463,6 @@ int orangefs_inode_setattr(struct inode *inode, struct iattr *iattr) return ret; } -void orangefs_make_bad_inode(struct inode *inode) -{ - if (is_root_handle(inode)) { - /* - * if this occurs, the pvfs2-client-core was killed but we - * can't afford to lose the inode operations and such - * associated with the root handle in any case. - */ - gossip_debug(GOSSIP_UTILS_DEBUG, - "*** NOT making bad root inode %pU\n", - get_khandle_from_ino(inode)); - } else { - gossip_debug(GOSSIP_UTILS_DEBUG, - "*** making bad inode %pU\n", - get_khandle_from_ino(inode)); - make_bad_inode(inode); - } -} - /* * The following is a very dirty hack that is now a permanent part of the * ORANGEFS protocol. See protocol.h for more error definitions. From 6bdfb48dae8e1b98735bf9387557298d17510be9 Mon Sep 17 00:00:00 2001 From: Xiongfeng Wang Date: Mon, 8 Jan 2018 20:22:33 +0800 Subject: [PATCH 159/237] orangefs: use correct string length gcc-8 reports fs/orangefs/dcache.c: In function 'orangefs_d_revalidate': ./include/linux/string.h:245:9: warning: '__builtin_strncpy' specified bound 256 equals destination size [-Wstringop-truncation] fs/orangefs/namei.c: In function 'orangefs_rename': ./include/linux/string.h:245:9: warning: '__builtin_strncpy' specified bound 256 equals destination size [-Wstringop-truncation] fs/orangefs/super.c: In function 'orangefs_mount': ./include/linux/string.h:245:9: warning: '__builtin_strncpy' specified bound 256 equals destination size [-Wstringop-truncation] We need one less byte or call strlcpy() to make it a nul-terminated string. Signed-off-by: Xiongfeng Wang Signed-off-by: Mike Marshall --- fs/orangefs/dcache.c | 2 +- fs/orangefs/namei.c | 16 ++++++++-------- fs/orangefs/super.c | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/fs/orangefs/dcache.c b/fs/orangefs/dcache.c index ae782df5c063e4..be06e1532a3b7d 100644 --- a/fs/orangefs/dcache.c +++ b/fs/orangefs/dcache.c @@ -33,7 +33,7 @@ static int orangefs_revalidate_lookup(struct dentry *dentry) new_op->upcall.req.lookup.parent_refn = parent->refn; strncpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name, - ORANGEFS_NAME_MAX); + ORANGEFS_NAME_MAX - 1); gossip_debug(GOSSIP_DCACHE_DEBUG, "%s:%s:%d interrupt flag [%d]\n", diff --git a/fs/orangefs/namei.c b/fs/orangefs/namei.c index c98bba2dbc94c3..6e3134e6d98a51 100644 --- a/fs/orangefs/namei.c +++ b/fs/orangefs/namei.c @@ -41,7 +41,7 @@ static int orangefs_create(struct inode *dir, ORANGEFS_TYPE_METAFILE, mode); strncpy(new_op->upcall.req.create.d_name, - dentry->d_name.name, ORANGEFS_NAME_MAX); + dentry->d_name.name, ORANGEFS_NAME_MAX - 1); ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); @@ -142,7 +142,7 @@ static struct dentry *orangefs_lookup(struct inode *dir, struct dentry *dentry, new_op->upcall.req.lookup.parent_refn = parent->refn; strncpy(new_op->upcall.req.lookup.d_name, dentry->d_name.name, - ORANGEFS_NAME_MAX); + ORANGEFS_NAME_MAX - 1); gossip_debug(GOSSIP_NAME_DEBUG, "%s: doing lookup on %s under %pU,%d\n", @@ -244,7 +244,7 @@ static int orangefs_unlink(struct inode *dir, struct dentry *dentry) new_op->upcall.req.remove.parent_refn = parent->refn; strncpy(new_op->upcall.req.remove.d_name, dentry->d_name.name, - ORANGEFS_NAME_MAX); + ORANGEFS_NAME_MAX - 1); ret = service_operation(new_op, "orangefs_unlink", get_interruptible_flag(inode)); @@ -300,8 +300,8 @@ static int orangefs_symlink(struct inode *dir, strncpy(new_op->upcall.req.sym.entry_name, dentry->d_name.name, - ORANGEFS_NAME_MAX); - strncpy(new_op->upcall.req.sym.target, symname, ORANGEFS_NAME_MAX); + ORANGEFS_NAME_MAX - 1); + strncpy(new_op->upcall.req.sym.target, symname, ORANGEFS_NAME_MAX - 1); ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); @@ -372,7 +372,7 @@ static int orangefs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode ORANGEFS_TYPE_DIRECTORY, mode); strncpy(new_op->upcall.req.mkdir.d_name, - dentry->d_name.name, ORANGEFS_NAME_MAX); + dentry->d_name.name, ORANGEFS_NAME_MAX - 1); ret = service_operation(new_op, __func__, get_interruptible_flag(dir)); @@ -453,10 +453,10 @@ static int orangefs_rename(struct inode *old_dir, strncpy(new_op->upcall.req.rename.d_old_name, old_dentry->d_name.name, - ORANGEFS_NAME_MAX); + ORANGEFS_NAME_MAX - 1); strncpy(new_op->upcall.req.rename.d_new_name, new_dentry->d_name.name, - ORANGEFS_NAME_MAX); + ORANGEFS_NAME_MAX - 1); ret = service_operation(new_op, "orangefs_rename", diff --git a/fs/orangefs/super.c b/fs/orangefs/super.c index a4f4b508eff288..b28b75c7d275ee 100644 --- a/fs/orangefs/super.c +++ b/fs/orangefs/super.c @@ -383,7 +383,7 @@ static int orangefs_unmount(int id, __s32 fs_id, const char *devname) op->upcall.req.fs_umount.id = id; op->upcall.req.fs_umount.fs_id = fs_id; strncpy(op->upcall.req.fs_umount.orangefs_config_server, - devname, ORANGEFS_MAX_SERVER_ADDR_LEN); + devname, ORANGEFS_MAX_SERVER_ADDR_LEN - 1); r = service_operation(op, "orangefs_fs_umount", 0); /* Not much to do about an error here. */ if (r) @@ -478,7 +478,7 @@ struct dentry *orangefs_mount(struct file_system_type *fst, strncpy(new_op->upcall.req.fs_mount.orangefs_config_server, devname, - ORANGEFS_MAX_SERVER_ADDR_LEN); + ORANGEFS_MAX_SERVER_ADDR_LEN - 1); gossip_debug(GOSSIP_SUPER_DEBUG, "Attempting ORANGEFS Mount via host %s\n", @@ -520,7 +520,7 @@ struct dentry *orangefs_mount(struct file_system_type *fst, */ strncpy(ORANGEFS_SB(sb)->devname, devname, - ORANGEFS_MAX_SERVER_ADDR_LEN); + ORANGEFS_MAX_SERVER_ADDR_LEN - 1); /* mount_pending must be cleared */ ORANGEFS_SB(sb)->mount_pending = 0; From cf546ab6b189ab8b3acb26bbc2f0af4df21f16c7 Mon Sep 17 00:00:00 2001 From: Mike Marshall Date: Thu, 25 Jan 2018 14:43:28 -0500 Subject: [PATCH 160/237] Orangefs: don't propogate whacky error codes When we get an error return code from userspace (the client-core) we check to make sure it is a valid code. This patch maps the whacky return code to -EINVAL instead of propagating garbage back up the call chain potentially resulting in a hard-to-find train-wreck. The client-core doesn't have any business returning whacky return codes, but if it does, we don't want the kernel to crash as a result. Signed-off-by: Mike Marshall --- fs/orangefs/orangefs-utils.c | 1 + 1 file changed, 1 insertion(+) diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c index 3098c2ee7b5f1c..ccddfcab7fc0f3 100644 --- a/fs/orangefs/orangefs-utils.c +++ b/fs/orangefs/orangefs-utils.c @@ -537,6 +537,7 @@ int orangefs_normalize_to_errno(__s32 error_code) */ } else { gossip_err("orangefs: orangefs_normalize_to_errno: got error code which is not from ORANGEFS.\n"); + error_code = -EINVAL; } return error_code; } From 480e5ae9b860c8a1c74ab9414f9bd78a43ad356f Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Tue, 6 Feb 2018 14:01:25 +0000 Subject: [PATCH 161/237] orangefs: simplify orangefs_inode_is_stale Check whether this is a new inode at location of call. Raises the question of what to do with an unknown inode type. Old code would've marked the inode bad and returned ESTALE. Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall --- fs/orangefs/orangefs-utils.c | 54 ++++++++++++++++++++---------------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/fs/orangefs/orangefs-utils.c b/fs/orangefs/orangefs-utils.c index ccddfcab7fc0f3..ea6256d136d1cd 100644 --- a/fs/orangefs/orangefs-utils.c +++ b/fs/orangefs/orangefs-utils.c @@ -249,25 +249,23 @@ static void orangefs_make_bad_inode(struct inode *inode) } } -static int orangefs_inode_is_stale(struct inode *inode, int new, +static int orangefs_inode_is_stale(struct inode *inode, struct ORANGEFS_sys_attr_s *attrs, char *link_target) { struct orangefs_inode_s *orangefs_inode = ORANGEFS_I(inode); int type = orangefs_inode_type(attrs->objtype); - if (!new) { - /* - * If the inode type or symlink target have changed then this - * inode is stale. - */ - if (type == -1 || !(inode->i_mode & type)) { - orangefs_make_bad_inode(inode); - return 1; - } - if (type == S_IFLNK && strncmp(orangefs_inode->link_target, - link_target, ORANGEFS_NAME_MAX)) { - orangefs_make_bad_inode(inode); - return 1; - } + /* + * If the inode type or symlink target have changed then this + * inode is stale. + */ + if (type == -1 || !(inode->i_mode & type)) { + orangefs_make_bad_inode(inode); + return 1; + } + if (type == S_IFLNK && strncmp(orangefs_inode->link_target, + link_target, ORANGEFS_NAME_MAX)) { + orangefs_make_bad_inode(inode); + return 1; } return 0; } @@ -313,16 +311,18 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass, if (ret != 0) goto out; - type = orangefs_inode_type(new_op-> - downcall.resp.getattr.attributes.objtype); - ret = orangefs_inode_is_stale(inode, new, - &new_op->downcall.resp.getattr.attributes, - new_op->downcall.resp.getattr.link_target); - if (ret) { - ret = -ESTALE; - goto out; + if (!new) { + ret = orangefs_inode_is_stale(inode, + &new_op->downcall.resp.getattr.attributes, + new_op->downcall.resp.getattr.link_target); + if (ret) { + ret = -ESTALE; + goto out; + } } + type = orangefs_inode_type(new_op-> + downcall.resp.getattr.attributes.objtype); switch (type) { case S_IFREG: inode->i_flags = orangefs_inode_flags(&new_op-> @@ -367,6 +367,12 @@ int orangefs_inode_getattr(struct inode *inode, int new, int bypass, inode->i_link = orangefs_inode->link_target; } break; + /* i.e. -1 */ + default: + /* XXX: ESTALE? This is what is done if it is not new. */ + orangefs_make_bad_inode(inode); + ret = -ESTALE; + goto out; } inode->i_uid = make_kuid(&init_user_ns, new_op-> @@ -420,7 +426,7 @@ int orangefs_inode_check_changed(struct inode *inode) if (ret != 0) goto out; - ret = orangefs_inode_is_stale(inode, 0, + ret = orangefs_inode_is_stale(inode, &new_op->downcall.resp.getattr.attributes, new_op->downcall.resp.getattr.link_target); out: From 74e938c22705c7b80d4422e84eea927fc78e60a8 Mon Sep 17 00:00:00 2001 From: Martin Brandenburg Date: Tue, 6 Feb 2018 14:01:26 +0000 Subject: [PATCH 162/237] orangefs: reverse sense of is-inode-stale test in d_revalidate If a dentry is deleted, then a dentry is recreated with the same handle but a different type (i.e. it was a file and now it's a symlink), then its a different inode. The check was backwards, so d_revalidate would not have noticed. Due to the design of the OrangeFS server, this is rather unlikely. It's also possible for the dentry to be deleted and recreated with the same type. This would be undetectable. It's a bit of a ship of Theseus. Signed-off-by: Martin Brandenburg Signed-off-by: Mike Marshall --- fs/orangefs/dcache.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/fs/orangefs/dcache.c b/fs/orangefs/dcache.c index be06e1532a3b7d..fe484cf93e5cd5 100644 --- a/fs/orangefs/dcache.c +++ b/fs/orangefs/dcache.c @@ -118,8 +118,12 @@ static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags) return 0; /* We do not need to continue with negative dentries. */ - if (!dentry->d_inode) - goto out; + if (!dentry->d_inode) { + gossip_debug(GOSSIP_DCACHE_DEBUG, + "%s: negative dentry or positive dentry and inode valid.\n", + __func__); + return 1; + } /* Now we must perform a getattr to validate the inode contents. */ @@ -129,14 +133,7 @@ static int orangefs_d_revalidate(struct dentry *dentry, unsigned int flags) __FILE__, __func__, __LINE__); return 0; } - if (ret == 0) - return 0; - -out: - gossip_debug(GOSSIP_DCACHE_DEBUG, - "%s: negative dentry or positive dentry and inode valid.\n", - __func__); - return 1; + return !ret; } const struct dentry_operations orangefs_dentry_operations = { From 9c160941403ba833c8e67981806ccae73ff7aca7 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 09:48:43 -0500 Subject: [PATCH 163/237] idr: Delete idr_remove_ext function Simply changing idr_remove's 'id' argument to 'unsigned long' suffices for all callers. Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 7 +------ net/sched/act_api.c | 2 +- net/sched/cls_api.c | 2 +- net/sched/cls_basic.c | 6 +++--- net/sched/cls_bpf.c | 4 ++-- net/sched/cls_flower.c | 4 ++-- net/sched/cls_u32.c | 8 ++++---- 7 files changed, 14 insertions(+), 19 deletions(-) diff --git a/include/linux/idr.h b/include/linux/idr.h index fa14f834e4ede3..118987a17ada29 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -140,16 +140,11 @@ void *idr_replace(struct idr *, void *, int id); void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id); void idr_destroy(struct idr *); -static inline void *idr_remove_ext(struct idr *idr, unsigned long id) +static inline void *idr_remove(struct idr *idr, unsigned long id) { return radix_tree_delete_item(&idr->idr_rt, id, NULL); } -static inline void *idr_remove(struct idr *idr, int id) -{ - return idr_remove_ext(idr, id); -} - static inline void idr_init(struct idr *idr) { INIT_RADIX_TREE(&idr->idr_rt, IDR_RT_MARKER); diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 52622a3d25172e..be5b2b455371bd 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -78,7 +78,7 @@ static void free_tcf(struct tc_action *p) static void tcf_idr_remove(struct tcf_idrinfo *idrinfo, struct tc_action *p) { spin_lock_bh(&idrinfo->lock); - idr_remove_ext(&idrinfo->action_idr, p->tcfa_index); + idr_remove(&idrinfo->action_idr, p->tcfa_index); spin_unlock_bh(&idrinfo->lock); gen_kill_estimator(&p->tcfa_rate_est); free_tcf(p); diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index bcb4ccb5f894b8..6d0e9bc4c78280 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -393,7 +393,7 @@ static void tcf_block_remove(struct tcf_block *block, struct net *net) { struct tcf_net *tn = net_generic(net, tcf_net_id); - idr_remove_ext(&tn->idr, block->index); + idr_remove(&tn->idr, block->index); } static struct tcf_block *tcf_block_create(struct net *net, struct Qdisc *q, diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index d333f5c5101d0d..121dff0a176345 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -120,7 +120,7 @@ static void basic_destroy(struct tcf_proto *tp, struct netlink_ext_ack *extack) list_for_each_entry_safe(f, n, &head->flist, link) { list_del_rcu(&f->link); tcf_unbind_filter(tp, &f->res); - idr_remove_ext(&head->handle_idr, f->handle); + idr_remove(&head->handle_idr, f->handle); if (tcf_exts_get_net(&f->exts)) call_rcu(&f->rcu, basic_delete_filter); else @@ -138,7 +138,7 @@ static int basic_delete(struct tcf_proto *tp, void *arg, bool *last, list_del_rcu(&f->link); tcf_unbind_filter(tp, &f->res); - idr_remove_ext(&head->handle_idr, f->handle); + idr_remove(&head->handle_idr, f->handle); tcf_exts_get_net(&f->exts); call_rcu(&f->rcu, basic_delete_filter); *last = list_empty(&head->flist); @@ -228,7 +228,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, extack); if (err < 0) { if (!fold) - idr_remove_ext(&head->handle_idr, fnew->handle); + idr_remove(&head->handle_idr, fnew->handle); goto errout; } diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 8e5326bc64402f..e45137e3f56762 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -295,7 +295,7 @@ static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog, { struct cls_bpf_head *head = rtnl_dereference(tp->root); - idr_remove_ext(&head->handle_idr, prog->handle); + idr_remove(&head->handle_idr, prog->handle); cls_bpf_stop_offload(tp, prog, extack); list_del_rcu(&prog->link); tcf_unbind_filter(tp, &prog->res); @@ -542,7 +542,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, cls_bpf_free_parms(prog); errout_idr: if (!oldprog) - idr_remove_ext(&head->handle_idr, prog->handle); + idr_remove(&head->handle_idr, prog->handle); errout: tcf_exts_destroy(&prog->exts); kfree(prog); diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index dc9acaafc0a809..e098e8ab76c9d7 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -288,7 +288,7 @@ static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f, { struct cls_fl_head *head = rtnl_dereference(tp->root); - idr_remove_ext(&head->handle_idr, f->handle); + idr_remove(&head->handle_idr, f->handle); list_del_rcu(&f->list); if (!tc_skip_hw(f->flags)) fl_hw_destroy_filter(tp, f, extack); @@ -981,7 +981,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, errout_idr: if (fnew->handle) - idr_remove_ext(&head->handle_idr, fnew->handle); + idr_remove(&head->handle_idr, fnew->handle); errout: tcf_exts_destroy(&fnew->exts); kfree(fnew); diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index e3c5e390ec23a4..bd55ed783cb176 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -596,7 +596,7 @@ static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht, rtnl_dereference(n->next)); tcf_unbind_filter(tp, &n->res); u32_remove_hw_knode(tp, n, extack); - idr_remove_ext(&ht->handle_idr, n->handle); + idr_remove(&ht->handle_idr, n->handle); if (tcf_exts_get_net(&n->exts)) call_rcu(&n->rcu, u32_delete_key_freepf_rcu); else @@ -623,7 +623,7 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht, if (phn == ht) { u32_clear_hw_hnode(tp, ht, extack); idr_destroy(&ht->handle_idr); - idr_remove_ext(&tp_c->handle_idr, ht->handle); + idr_remove(&tp_c->handle_idr, ht->handle); RCU_INIT_POINTER(*hn, ht->next); kfree_rcu(ht, rcu); return 0; @@ -1026,7 +1026,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, err = u32_replace_hw_hnode(tp, ht, flags, extack); if (err) { - idr_remove_ext(&tp_c->handle_idr, handle); + idr_remove(&tp_c->handle_idr, handle); kfree(ht); return err; } @@ -1162,7 +1162,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, #endif kfree(n); erridr: - idr_remove_ext(&ht->handle_idr, handle); + idr_remove(&ht->handle_idr, handle); return err; } From 234a4624efe5629a777b4c00dbdf41dd8b7332db Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 09:56:36 -0500 Subject: [PATCH 164/237] idr: Delete idr_replace_ext function Changing idr_replace's 'id' argument to 'unsigned long' works for all callers. Callers which passed a negative ID now get -ENOENT instead of -EINVAL. No callers relied on this error value. Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 3 +-- lib/idr.c | 15 +++------------ net/sched/act_api.c | 2 +- net/sched/cls_basic.c | 2 +- net/sched/cls_bpf.c | 2 +- net/sched/cls_flower.c | 2 +- net/sched/cls_u32.c | 2 +- 7 files changed, 9 insertions(+), 19 deletions(-) diff --git a/include/linux/idr.h b/include/linux/idr.h index 118987a17ada29..f1299c4dc45fe1 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -136,8 +136,7 @@ int idr_for_each(const struct idr *, int (*fn)(int id, void *p, void *data), void *data); void *idr_get_next(struct idr *, int *nextid); void *idr_get_next_ext(struct idr *idr, unsigned long *nextid); -void *idr_replace(struct idr *, void *, int id); -void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id); +void *idr_replace(struct idr *, void *, unsigned long id); void idr_destroy(struct idr *); static inline void *idr_remove(struct idr *idr, unsigned long id) diff --git a/lib/idr.c b/lib/idr.c index 2593ce513a180a..577bfd4fe5c2db 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -147,18 +147,9 @@ EXPORT_SYMBOL(idr_get_next_ext); * the one being replaced!). * * Returns: the old value on success. %-ENOENT indicates that @id was not - * found. %-EINVAL indicates that @id or @ptr were not valid. + * found. %-EINVAL indicates that @ptr was not valid. */ -void *idr_replace(struct idr *idr, void *ptr, int id) -{ - if (id < 0) - return ERR_PTR(-EINVAL); - - return idr_replace_ext(idr, ptr, id); -} -EXPORT_SYMBOL(idr_replace); - -void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id) +void *idr_replace(struct idr *idr, void *ptr, unsigned long id) { struct radix_tree_node *node; void __rcu **slot = NULL; @@ -175,7 +166,7 @@ void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id) return entry; } -EXPORT_SYMBOL(idr_replace_ext); +EXPORT_SYMBOL(idr_replace); /** * DOC: IDA description diff --git a/net/sched/act_api.c b/net/sched/act_api.c index be5b2b455371bd..1572466be0315b 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -348,7 +348,7 @@ void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a) struct tcf_idrinfo *idrinfo = tn->idrinfo; spin_lock_bh(&idrinfo->lock); - idr_replace_ext(&idrinfo->action_idr, a, a->tcfa_index); + idr_replace(&idrinfo->action_idr, a, a->tcfa_index); spin_unlock_bh(&idrinfo->lock); } EXPORT_SYMBOL(tcf_idr_insert); diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 121dff0a176345..588c635f195e9c 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -235,7 +235,7 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, *arg = fnew; if (fold) { - idr_replace_ext(&head->handle_idr, fnew, fnew->handle); + idr_replace(&head->handle_idr, fnew, fnew->handle); list_replace_rcu(&fold->link, &fnew->link); tcf_unbind_filter(tp, &fold->res); tcf_exts_get_net(&fold->exts); diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index e45137e3f56762..8cb3a33b1afdf3 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -526,7 +526,7 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, prog->gen_flags |= TCA_CLS_FLAGS_NOT_IN_HW; if (oldprog) { - idr_replace_ext(&head->handle_idr, prog, handle); + idr_replace(&head->handle_idr, prog, handle); list_replace_rcu(&oldprog->link, &prog->link); tcf_unbind_filter(tp, &oldprog->res); tcf_exts_get_net(&oldprog->exts); diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index e098e8ab76c9d7..0d1b0c11de347a 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -967,7 +967,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, if (fold) { fnew->handle = handle; - idr_replace_ext(&head->handle_idr, fnew, fnew->handle); + idr_replace(&head->handle_idr, fnew, fnew->handle); list_replace_rcu(&fold->list, &fnew->list); tcf_unbind_filter(tp, &fold->res); tcf_exts_get_net(&fold->exts); diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index bd55ed783cb176..5b256da985b15e 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -848,7 +848,7 @@ static void u32_replace_knode(struct tcf_proto *tp, struct tc_u_common *tp_c, if (pins->handle == n->handle) break; - idr_replace_ext(&ht->handle_idr, n, n->handle); + idr_replace(&ht->handle_idr, n, n->handle); RCU_INIT_POINTER(n->next, pins->next); rcu_assign_pointer(*ins, n); } From 322d884ba731e05ca79ae58e9dee1ef7dc4de504 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:01:24 -0500 Subject: [PATCH 165/237] idr: Delete idr_find_ext function Simply changing idr_remove's 'id' argument to 'unsigned long' works for all callers. Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 7 +------ net/sched/act_api.c | 2 +- net/sched/cls_api.c | 2 +- net/sched/cls_flower.c | 2 +- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/include/linux/idr.h b/include/linux/idr.h index f1299c4dc45fe1..7867d611753512 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -179,16 +179,11 @@ static inline void idr_preload_end(void) * This function can be called under rcu_read_lock(), given that the leaf * pointers lifetimes are correctly managed. */ -static inline void *idr_find_ext(const struct idr *idr, unsigned long id) +static inline void *idr_find(const struct idr *idr, unsigned long id) { return radix_tree_lookup(&idr->idr_rt, id); } -static inline void *idr_find(const struct idr *idr, int id) -{ - return idr_find_ext(idr, id); -} - /** * idr_for_each_entry - iterate over an idr's elements of a given type * @idr: idr handle diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 1572466be0315b..89e9189ab35c7b 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -222,7 +222,7 @@ static struct tc_action *tcf_idr_lookup(u32 index, struct tcf_idrinfo *idrinfo) struct tc_action *p = NULL; spin_lock_bh(&idrinfo->lock); - p = idr_find_ext(&idrinfo->action_idr, index); + p = idr_find(&idrinfo->action_idr, index); spin_unlock_bh(&idrinfo->lock); return p; diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 6d0e9bc4c78280..802ac9d1eaab2f 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -434,7 +434,7 @@ static struct tcf_block *tcf_block_lookup(struct net *net, u32 block_index) { struct tcf_net *tn = net_generic(net, tcf_net_id); - return idr_find_ext(&tn->idr, block_index); + return idr_find(&tn->idr, block_index); } static struct tcf_chain *tcf_block_chain_zero(struct tcf_block *block) diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 0d1b0c11de347a..2162e1c1f38205 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -334,7 +334,7 @@ static void *fl_get(struct tcf_proto *tp, u32 handle) { struct cls_fl_head *head = rtnl_dereference(tp->root); - return idr_find_ext(&head->handle_idr, handle); + return idr_find(&head->handle_idr, handle); } static const struct nla_policy fl_policy[TCA_FLOWER_MAX + 1] = { From e096f6a762bc54d0e5d44ba8b196e70b58e04367 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:14:27 -0500 Subject: [PATCH 166/237] idr: Add idr_alloc_u32 helper All current users of idr_alloc_ext() actually want to allocate a u32 and idr_alloc_u32() fits their needs better. Like idr_get_next(), it uses a 'nextid' argument which serves as both a pointer to the start ID and the assigned ID (instead of a separate minimum and pointer-to-assigned-ID argument). It uses a 'max' argument rather than 'end' because the semantics that idr_alloc has for 'end' don't work well for unsigned types. Since idr_alloc_u32() returns an errno instead of the allocated ID, mark it as __must_check to help callers use it correctly. Include copious kernel-doc. Chris Mi has promised to contribute test-cases for idr_alloc_u32. Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 2 ++ lib/idr.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/include/linux/idr.h b/include/linux/idr.h index 7867d611753512..561a4cbabca6ba 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -131,6 +131,8 @@ static inline int idr_alloc_ext(struct idr *idr, void *ptr, return idr_alloc_cmn(idr, ptr, index, start, end, gfp, true); } +int __must_check idr_alloc_u32(struct idr *, void *ptr, u32 *nextid, + unsigned long max, gfp_t); int idr_alloc_cyclic(struct idr *, void *entry, int start, int end, gfp_t); int idr_for_each(const struct idr *, int (*fn)(int id, void *p, void *data), void *data); diff --git a/lib/idr.c b/lib/idr.c index 577bfd4fe5c2db..6d4ec2c2982b66 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -7,6 +7,37 @@ DEFINE_PER_CPU(struct ida_bitmap *, ida_bitmap); static DEFINE_SPINLOCK(simple_ida_lock); +/** + * idr_alloc_u32() - Allocate an ID. + * @idr: IDR handle. + * @ptr: Pointer to be associated with the new ID. + * @nextid: Pointer to an ID. + * @max: The maximum ID to allocate (inclusive). + * @gfp: Memory allocation flags. + * + * Allocates an unused ID in the range specified by @nextid and @max. + * Note that @max is inclusive whereas the @end parameter to idr_alloc() + * is exclusive. + * + * The caller should provide their own locking to ensure that two + * concurrent modifications to the IDR are not possible. Read-only + * accesses to the IDR may be done under the RCU read lock or may + * exclude simultaneous writers. + * + * Return: 0 if an ID was allocated, -ENOMEM if memory allocation failed, + * or -ENOSPC if no free IDs could be found. If an error occurred, + * @nextid is unchanged. + */ +int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid, + unsigned long max, gfp_t gfp) +{ + unsigned long tmp = *nextid; + int ret = idr_alloc_ext(idr, ptr, &tmp, tmp, max + 1, gfp); + *nextid = tmp; + return ret; +} +EXPORT_SYMBOL_GPL(idr_alloc_u32); + int idr_alloc_cmn(struct idr *idr, void *ptr, unsigned long *index, unsigned long start, unsigned long end, gfp_t gfp, bool ext) From 339913a8be8a98fca5c72f5552f0316ff6d5e701 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:28:15 -0500 Subject: [PATCH 167/237] net sched actions: Convert to use idr_alloc_u32 Use the new helper. Also untangle the error path, and in so doing noticed that estimator generator failure would lead to us leaking an ID. Fix that bug. Signed-off-by: Matthew Wilcox --- net/sched/act_api.c | 60 +++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 89e9189ab35c7b..9b6916a924232e 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -274,7 +274,6 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, struct tcf_idrinfo *idrinfo = tn->idrinfo; struct idr *idr = &idrinfo->action_idr; int err = -ENOMEM; - unsigned long idr_index; if (unlikely(!p)) return -ENOMEM; @@ -284,45 +283,28 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, if (cpustats) { p->cpu_bstats = netdev_alloc_pcpu_stats(struct gnet_stats_basic_cpu); - if (!p->cpu_bstats) { -err1: - kfree(p); - return err; - } - p->cpu_qstats = alloc_percpu(struct gnet_stats_queue); - if (!p->cpu_qstats) { -err2: - free_percpu(p->cpu_bstats); + if (!p->cpu_bstats) goto err1; - } + p->cpu_qstats = alloc_percpu(struct gnet_stats_queue); + if (!p->cpu_qstats) + goto err2; } spin_lock_init(&p->tcfa_lock); + idr_preload(GFP_KERNEL); + spin_lock_bh(&idrinfo->lock); /* user doesn't specify an index */ if (!index) { - idr_preload(GFP_KERNEL); - spin_lock_bh(&idrinfo->lock); - err = idr_alloc_ext(idr, NULL, &idr_index, 1, 0, - GFP_ATOMIC); - spin_unlock_bh(&idrinfo->lock); - idr_preload_end(); - if (err) { -err3: - free_percpu(p->cpu_qstats); - goto err2; - } - p->tcfa_index = idr_index; + index = 1; + err = idr_alloc_u32(idr, NULL, &index, UINT_MAX, GFP_ATOMIC); } else { - idr_preload(GFP_KERNEL); - spin_lock_bh(&idrinfo->lock); - err = idr_alloc_ext(idr, NULL, NULL, index, index + 1, - GFP_ATOMIC); - spin_unlock_bh(&idrinfo->lock); - idr_preload_end(); - if (err) - goto err3; - p->tcfa_index = index; + err = idr_alloc_u32(idr, NULL, &index, index, GFP_ATOMIC); } + spin_unlock_bh(&idrinfo->lock); + idr_preload_end(); + if (err) + goto err3; + p->tcfa_index = index; p->tcfa_tm.install = jiffies; p->tcfa_tm.lastuse = jiffies; p->tcfa_tm.firstuse = 0; @@ -330,9 +312,8 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, err = gen_new_estimator(&p->tcfa_bstats, p->cpu_bstats, &p->tcfa_rate_est, &p->tcfa_lock, NULL, est); - if (err) { - goto err3; - } + if (err) + goto err4; } p->idrinfo = idrinfo; @@ -340,6 +321,15 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, INIT_LIST_HEAD(&p->list); *a = p; return 0; +err4: + idr_remove(idr, index); +err3: + free_percpu(p->cpu_qstats); +err2: + free_percpu(p->cpu_bstats); +err1: + kfree(p); + return err; } EXPORT_SYMBOL(tcf_idr_create); From 9ce75499ac140af71f0003322c99b6e58f39dfbe Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 6 Feb 2018 16:37:52 -0500 Subject: [PATCH 168/237] cls_api: Convert to idr_alloc_u32 Use the new helper. Signed-off-by: Matthew Wilcox --- net/sched/cls_api.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 802ac9d1eaab2f..2bc1bc23d42ecd 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -381,8 +381,8 @@ static int tcf_block_insert(struct tcf_block *block, struct net *net, struct tcf_net *tn = net_generic(net, tcf_net_id); int err; - err = idr_alloc_ext(&tn->idr, block, NULL, block_index, - block_index + 1, GFP_KERNEL); + err = idr_alloc_u32(&tn->idr, block, &block_index, block_index, + GFP_KERNEL); if (err) return err; block->index = block_index; From 05af0ebb0810ba3f9669649134b4b4ad42540eba Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:36:09 -0500 Subject: [PATCH 169/237] cls_basic: Convert to use idr_alloc_u32 Use the new helper which saves a temporary variable and a few lines of code. Signed-off-by: Matthew Wilcox --- net/sched/cls_basic.c | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 588c635f195e9c..6b7ab3512f5bb8 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c @@ -185,7 +185,6 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, struct nlattr *tb[TCA_BASIC_MAX + 1]; struct basic_filter *fold = (struct basic_filter *) *arg; struct basic_filter *fnew; - unsigned long idr_index; if (tca[TCA_OPTIONS] == NULL) return -EINVAL; @@ -208,21 +207,17 @@ static int basic_change(struct net *net, struct sk_buff *in_skb, if (err < 0) goto errout; - if (handle) { - fnew->handle = handle; - if (!fold) { - err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index, - handle, handle + 1, GFP_KERNEL); - if (err) - goto errout; - } - } else { - err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index, - 1, 0x7FFFFFFF, GFP_KERNEL); - if (err) - goto errout; - fnew->handle = idr_index; + if (!handle) { + handle = 1; + err = idr_alloc_u32(&head->handle_idr, fnew, &handle, + INT_MAX, GFP_KERNEL); + } else if (!fold) { + err = idr_alloc_u32(&head->handle_idr, fnew, &handle, + handle, GFP_KERNEL); } + if (err) + goto errout; + fnew->handle = handle; err = basic_set_parms(net, tp, fnew, base, tb, tca[TCA_RATE], ovr, extack); From 0b4ce8da79d65f9773601619bfc90d096f0a170e Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:46:29 -0500 Subject: [PATCH 170/237] cls_bpf: Convert to use idr_alloc_u32 Use the new helper. This has a modest reduction in both lines of code and compiled code size. Signed-off-by: Matthew Wilcox --- net/sched/cls_bpf.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 8cb3a33b1afdf3..b07c1fa8bc0dd8 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c @@ -471,7 +471,6 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, struct cls_bpf_prog *oldprog = *arg; struct nlattr *tb[TCA_BPF_MAX + 1]; struct cls_bpf_prog *prog; - unsigned long idr_index; int ret; if (tca[TCA_OPTIONS] == NULL) @@ -498,21 +497,18 @@ static int cls_bpf_change(struct net *net, struct sk_buff *in_skb, } if (handle == 0) { - ret = idr_alloc_ext(&head->handle_idr, prog, &idr_index, - 1, 0x7FFFFFFF, GFP_KERNEL); - if (ret) - goto errout; - prog->handle = idr_index; - } else { - if (!oldprog) { - ret = idr_alloc_ext(&head->handle_idr, prog, &idr_index, - handle, handle + 1, GFP_KERNEL); - if (ret) - goto errout; - } - prog->handle = handle; + handle = 1; + ret = idr_alloc_u32(&head->handle_idr, prog, &handle, + INT_MAX, GFP_KERNEL); + } else if (!oldprog) { + ret = idr_alloc_u32(&head->handle_idr, prog, &handle, + handle, GFP_KERNEL); } + if (ret) + goto errout; + prog->handle = handle; + ret = cls_bpf_set_parms(net, tp, prog, base, tb, tca[TCA_RATE], ovr, extack); if (ret < 0) From 85bd0438a249e7a7a0622e0b0b6663595fadcc27 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 10:53:03 -0500 Subject: [PATCH 171/237] cls_flower: Convert to idr_alloc_u32 Use the new helper which saves a temporary variable and a few lines of code. Signed-off-by: Matthew Wilcox --- net/sched/cls_flower.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c index 2162e1c1f38205..7d0ce2c40f9333 100644 --- a/net/sched/cls_flower.c +++ b/net/sched/cls_flower.c @@ -865,7 +865,6 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, struct cls_fl_filter *fnew; struct nlattr **tb; struct fl_flow_mask mask = {}; - unsigned long idr_index; int err; if (!tca[TCA_OPTIONS]) @@ -896,21 +895,17 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, goto errout; if (!handle) { - err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index, - 1, 0x80000000, GFP_KERNEL); - if (err) - goto errout; - fnew->handle = idr_index; - } - - /* user specifies a handle and it doesn't exist */ - if (handle && !fold) { - err = idr_alloc_ext(&head->handle_idr, fnew, &idr_index, - handle, handle + 1, GFP_KERNEL); - if (err) - goto errout; - fnew->handle = idr_index; + handle = 1; + err = idr_alloc_u32(&head->handle_idr, fnew, &handle, + INT_MAX, GFP_KERNEL); + } else if (!fold) { + /* user specifies a handle and it doesn't exist */ + err = idr_alloc_u32(&head->handle_idr, fnew, &handle, + handle, GFP_KERNEL); } + if (err) + goto errout; + fnew->handle = handle; if (tb[TCA_FLOWER_FLAGS]) { fnew->flags = nla_get_u32(tb[TCA_FLOWER_FLAGS]); @@ -966,7 +961,6 @@ static int fl_change(struct net *net, struct sk_buff *in_skb, *arg = fnew; if (fold) { - fnew->handle = handle; idr_replace(&head->handle_idr, fnew, fnew->handle); list_replace_rcu(&fold->list, &fnew->list); tcf_unbind_filter(tp, &fold->res); From ffdc2d9e1afd20e9f9d205115661481e984542d6 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 12:05:54 -0500 Subject: [PATCH 172/237] cls_u32: Reinstate cyclic allocation Commit e7614370d6f0 ("net_sched: use idr to allocate u32 filter handles) converted htid allocation to use the IDR. The ID allocated by this scheme changes; it used to be cyclic, but now always allocates the lowest available. The IDR supports cyclic allocation, so just use the right function. Signed-off-by: Matthew Wilcox --- net/sched/cls_u32.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index 5b256da985b15e..d2805f24ddd37e 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -316,19 +316,13 @@ static void *u32_get(struct tcf_proto *tp, u32 handle) return u32_lookup_key(ht, handle); } +/* Protected by rtnl lock */ static u32 gen_new_htid(struct tc_u_common *tp_c, struct tc_u_hnode *ptr) { - unsigned long idr_index; - int err; - - /* This is only used inside rtnl lock it is safe to increment - * without read _copy_ update semantics - */ - err = idr_alloc_ext(&tp_c->handle_idr, ptr, &idr_index, - 1, 0x7FF, GFP_KERNEL); - if (err) + int id = idr_alloc_cyclic(&tp_c->handle_idr, ptr, 1, 0x7FF, GFP_KERNEL); + if (id < 0) return 0; - return (u32)(idr_index | 0x800) << 20; + return (id | 0x800U) << 20; } static struct hlist_head *tc_u_common_hash; From f730cb93db8e640f95ba4acb339d5732e1721730 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 13:45:02 -0500 Subject: [PATCH 173/237] cls_u32: Convert to idr_alloc_u32 No real benefit to this classifier, but since we're allocating a u32 anyway, we should use this function. Signed-off-by: Matthew Wilcox --- net/sched/cls_u32.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index d2805f24ddd37e..82f85d6a245a31 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c @@ -740,19 +740,17 @@ static int u32_delete(struct tcf_proto *tp, void *arg, bool *last, static u32 gen_new_kid(struct tc_u_hnode *ht, u32 htid) { - unsigned long idr_index; - u32 start = htid | 0x800; + u32 index = htid | 0x800; u32 max = htid | 0xFFF; - u32 min = htid; - if (idr_alloc_ext(&ht->handle_idr, NULL, &idr_index, - start, max + 1, GFP_KERNEL)) { - if (idr_alloc_ext(&ht->handle_idr, NULL, &idr_index, - min + 1, max + 1, GFP_KERNEL)) - return max; + if (idr_alloc_u32(&ht->handle_idr, NULL, &index, max, GFP_KERNEL)) { + index = htid + 1; + if (idr_alloc_u32(&ht->handle_idr, NULL, &index, max, + GFP_KERNEL)) + index = max; } - return (u32)idr_index; + return index; } static const struct nla_policy u32_policy[TCA_U32_MAX + 1] = { @@ -1003,8 +1001,8 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, return -ENOMEM; } } else { - err = idr_alloc_ext(&tp_c->handle_idr, ht, NULL, - handle, handle + 1, GFP_KERNEL); + err = idr_alloc_u32(&tp_c->handle_idr, ht, &handle, + handle, GFP_KERNEL); if (err) { kfree(ht); return err; @@ -1060,8 +1058,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb, return -EINVAL; } handle = htid | TC_U32_NODE(handle); - err = idr_alloc_ext(&ht->handle_idr, NULL, NULL, - handle, handle + 1, + err = idr_alloc_u32(&ht->handle_idr, NULL, &handle, handle, GFP_KERNEL); if (err) return err; From 460488c58ca8b9167463ac22ec9a2e33db351962 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 15:16:24 -0500 Subject: [PATCH 174/237] idr: Remove idr_alloc_ext It has no more users, so remove it. Move idr_alloc() back into idr.c, move the guts of idr_alloc_cmn() into idr_alloc_u32(), remove the wrappers around idr_get_free_cmn() and rename it to idr_get_free(). While there is now no interface to allocate IDs larger than a u32, the IDR internals remain ready to handle a larger ID should a need arise. These changes make it possible to provide the guarantee that, if the nextid pointer points into the object, the object's ID will be initialised before a concurrent lookup can find the object. Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 51 +---------- include/linux/radix-tree.h | 17 +--- lib/idr.c | 128 ++++++++++++++++++---------- lib/radix-tree.c | 3 +- tools/testing/radix-tree/idr-test.c | 17 ++++ 5 files changed, 105 insertions(+), 111 deletions(-) diff --git a/include/linux/idr.h b/include/linux/idr.h index 561a4cbabca6ba..fa2a04b984df44 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -15,7 +15,6 @@ #include #include #include -#include struct idr { struct radix_tree_root idr_rt; @@ -82,55 +81,7 @@ static inline void idr_set_cursor(struct idr *idr, unsigned int val) void idr_preload(gfp_t gfp_mask); -int idr_alloc_cmn(struct idr *idr, void *ptr, unsigned long *index, - unsigned long start, unsigned long end, gfp_t gfp, - bool ext); - -/** - * idr_alloc - allocate an id - * @idr: idr handle - * @ptr: pointer to be associated with the new id - * @start: the minimum id (inclusive) - * @end: the maximum id (exclusive) - * @gfp: memory allocation flags - * - * Allocates an unused ID in the range [start, end). Returns -ENOSPC - * if there are no unused IDs in that range. - * - * Note that @end is treated as max when <= 0. This is to always allow - * using @start + N as @end as long as N is inside integer range. - * - * Simultaneous modifications to the @idr are not allowed and should be - * prevented by the user, usually with a lock. idr_alloc() may be called - * concurrently with read-only accesses to the @idr, such as idr_find() and - * idr_for_each_entry(). - */ -static inline int idr_alloc(struct idr *idr, void *ptr, - int start, int end, gfp_t gfp) -{ - unsigned long id; - int ret; - - if (WARN_ON_ONCE(start < 0)) - return -EINVAL; - - ret = idr_alloc_cmn(idr, ptr, &id, start, end, gfp, false); - - if (ret) - return ret; - - return id; -} - -static inline int idr_alloc_ext(struct idr *idr, void *ptr, - unsigned long *index, - unsigned long start, - unsigned long end, - gfp_t gfp) -{ - return idr_alloc_cmn(idr, ptr, index, start, end, gfp, true); -} - +int idr_alloc(struct idr *, void *, int start, int end, gfp_t); int __must_check idr_alloc_u32(struct idr *, void *ptr, u32 *nextid, unsigned long max, gfp_t); int idr_alloc_cyclic(struct idr *, void *entry, int start, int end, gfp_t); diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 23a9c89c7ad962..fc55ff31eca704 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -356,24 +356,9 @@ int radix_tree_split(struct radix_tree_root *, unsigned long index, int radix_tree_join(struct radix_tree_root *, unsigned long index, unsigned new_order, void *); -void __rcu **idr_get_free_cmn(struct radix_tree_root *root, +void __rcu **idr_get_free(struct radix_tree_root *root, struct radix_tree_iter *iter, gfp_t gfp, unsigned long max); -static inline void __rcu **idr_get_free(struct radix_tree_root *root, - struct radix_tree_iter *iter, - gfp_t gfp, - int end) -{ - return idr_get_free_cmn(root, iter, gfp, end > 0 ? end - 1 : INT_MAX); -} - -static inline void __rcu **idr_get_free_ext(struct radix_tree_root *root, - struct radix_tree_iter *iter, - gfp_t gfp, - unsigned long end) -{ - return idr_get_free_cmn(root, iter, gfp, end - 1); -} enum { RADIX_TREE_ITER_TAG_MASK = 0x0f, /* tag index in lower nybble */ diff --git a/lib/idr.c b/lib/idr.c index 6d4ec2c2982b66..c3f16307b9082f 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -17,7 +18,9 @@ static DEFINE_SPINLOCK(simple_ida_lock); * * Allocates an unused ID in the range specified by @nextid and @max. * Note that @max is inclusive whereas the @end parameter to idr_alloc() - * is exclusive. + * is exclusive. The new ID is assigned to @nextid before the pointer + * is inserted into the IDR, so if @nextid points into the object pointed + * to by @ptr, a concurrent lookup will not find an uninitialised ID. * * The caller should provide their own locking to ensure that two * concurrent modifications to the IDR are not possible. Read-only @@ -30,67 +33,104 @@ static DEFINE_SPINLOCK(simple_ida_lock); */ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid, unsigned long max, gfp_t gfp) -{ - unsigned long tmp = *nextid; - int ret = idr_alloc_ext(idr, ptr, &tmp, tmp, max + 1, gfp); - *nextid = tmp; - return ret; -} -EXPORT_SYMBOL_GPL(idr_alloc_u32); - -int idr_alloc_cmn(struct idr *idr, void *ptr, unsigned long *index, - unsigned long start, unsigned long end, gfp_t gfp, - bool ext) { struct radix_tree_iter iter; void __rcu **slot; if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) return -EINVAL; + if (WARN_ON_ONCE(!(idr->idr_rt.gfp_mask & ROOT_IS_IDR))) + idr->idr_rt.gfp_mask |= IDR_RT_MARKER; - radix_tree_iter_init(&iter, start); - if (ext) - slot = idr_get_free_ext(&idr->idr_rt, &iter, gfp, end); - else - slot = idr_get_free(&idr->idr_rt, &iter, gfp, end); + radix_tree_iter_init(&iter, *nextid); + slot = idr_get_free(&idr->idr_rt, &iter, gfp, max); if (IS_ERR(slot)) return PTR_ERR(slot); + *nextid = iter.index; + /* there is a memory barrier inside radix_tree_iter_replace() */ radix_tree_iter_replace(&idr->idr_rt, &iter, slot, ptr); radix_tree_iter_tag_clear(&idr->idr_rt, &iter, IDR_FREE); - if (index) - *index = iter.index; return 0; } -EXPORT_SYMBOL_GPL(idr_alloc_cmn); +EXPORT_SYMBOL_GPL(idr_alloc_u32); /** - * idr_alloc_cyclic - allocate new idr entry in a cyclical fashion - * @idr: idr handle - * @ptr: pointer to be associated with the new id - * @start: the minimum id (inclusive) - * @end: the maximum id (exclusive) - * @gfp: memory allocation flags - * - * Allocates an ID larger than the last ID allocated if one is available. - * If not, it will attempt to allocate the smallest ID that is larger or - * equal to @start. + * idr_alloc() - Allocate an ID. + * @idr: IDR handle. + * @ptr: Pointer to be associated with the new ID. + * @start: The minimum ID (inclusive). + * @end: The maximum ID (exclusive). + * @gfp: Memory allocation flags. + * + * Allocates an unused ID in the range specified by @start and @end. If + * @end is <= 0, it is treated as one larger than %INT_MAX. This allows + * callers to use @start + N as @end as long as N is within integer range. + * + * The caller should provide their own locking to ensure that two + * concurrent modifications to the IDR are not possible. Read-only + * accesses to the IDR may be done under the RCU read lock or may + * exclude simultaneous writers. + * + * Return: The newly allocated ID, -ENOMEM if memory allocation failed, + * or -ENOSPC if no free IDs could be found. */ -int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp) +int idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp) { - int id, curr = idr->idr_next; + u32 id = start; + int ret; + + if (WARN_ON_ONCE(start < 0)) + return -EINVAL; - if (curr < start) - curr = start; + ret = idr_alloc_u32(idr, ptr, &id, end > 0 ? end - 1 : INT_MAX, gfp); + if (ret) + return ret; - id = idr_alloc(idr, ptr, curr, end, gfp); - if ((id == -ENOSPC) && (curr > start)) - id = idr_alloc(idr, ptr, start, curr, gfp); + return id; +} +EXPORT_SYMBOL_GPL(idr_alloc); - if (id >= 0) - idr->idr_next = id + 1U; +/** + * idr_alloc_cyclic() - Allocate an ID cyclically. + * @idr: IDR handle. + * @ptr: Pointer to be associated with the new ID. + * @start: The minimum ID (inclusive). + * @end: The maximum ID (exclusive). + * @gfp: Memory allocation flags. + * + * Allocates an unused ID in the range specified by @nextid and @end. If + * @end is <= 0, it is treated as one larger than %INT_MAX. This allows + * callers to use @start + N as @end as long as N is within integer range. + * The search for an unused ID will start at the last ID allocated and will + * wrap around to @start if no free IDs are found before reaching @end. + * + * The caller should provide their own locking to ensure that two + * concurrent modifications to the IDR are not possible. Read-only + * accesses to the IDR may be done under the RCU read lock or may + * exclude simultaneous writers. + * + * Return: The newly allocated ID, -ENOMEM if memory allocation failed, + * or -ENOSPC if no free IDs could be found. + */ +int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp) +{ + u32 id = idr->idr_next; + int err, max = end > 0 ? end - 1 : INT_MAX; + if ((int)id < start) + id = start; + + err = idr_alloc_u32(idr, ptr, &id, max, gfp); + if ((err == -ENOSPC) && (id > start)) { + id = start; + err = idr_alloc_u32(idr, ptr, &id, max, gfp); + } + if (err) + return err; + + idr->idr_next = id + 1; return id; } EXPORT_SYMBOL(idr_alloc_cyclic); @@ -167,10 +207,10 @@ void *idr_get_next_ext(struct idr *idr, unsigned long *nextid) EXPORT_SYMBOL(idr_get_next_ext); /** - * idr_replace - replace pointer for given id - * @idr: idr handle - * @ptr: New pointer to associate with the ID - * @id: Lookup key + * idr_replace() - replace pointer for given ID. + * @idr: IDR handle. + * @ptr: New pointer to associate with the ID. + * @id: ID to change. * * Replace the pointer registered with an ID and return the old value. * This function can be called under the RCU read lock concurrently with @@ -257,7 +297,7 @@ EXPORT_SYMBOL(idr_replace); * bitmap, which is excessive. */ -#define IDA_MAX (0x80000000U / IDA_BITMAP_BITS) +#define IDA_MAX (0x80000000U / IDA_BITMAP_BITS - 1) /** * ida_get_new_above - allocate new ID above or equal to a start id diff --git a/lib/radix-tree.c b/lib/radix-tree.c index c8d55565fafa6b..0a7ae3288a248e 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -24,6 +24,7 @@ #include #include +#include #include #include #include @@ -2135,7 +2136,7 @@ int ida_pre_get(struct ida *ida, gfp_t gfp) } EXPORT_SYMBOL(ida_pre_get); -void __rcu **idr_get_free_cmn(struct radix_tree_root *root, +void __rcu **idr_get_free(struct radix_tree_root *root, struct radix_tree_iter *iter, gfp_t gfp, unsigned long max) { diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 892ef8855b0245..36437ade429cb8 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -215,6 +215,23 @@ void idr_checks(void) assert(idr_is_empty(&idr)); + idr_set_cursor(&idr, INT_MAX - 3UL); + for (i = INT_MAX - 3UL; i < INT_MAX + 3UL; i++) { + struct item *item; + unsigned int id; + if (i <= INT_MAX) + item = item_create(i, 0); + else + item = item_create(i - INT_MAX - 1, 0); + + id = idr_alloc_cyclic(&idr, item, 0, 0, GFP_KERNEL); + assert(id == item->index); + } + + idr_for_each(&idr, item_idr_free, &idr); + idr_destroy(&idr); + assert(idr_is_empty(&idr)); + for (i = 1; i < 10000; i++) { struct item *item = item_create(i, 0); assert(idr_alloc(&idr, item, 1, 20000, GFP_KERNEL) == i); From 7a4575778f4db109b8b78e6dba03271096793f88 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 15:39:51 -0500 Subject: [PATCH 175/237] idr: Rename idr_for_each_entry_ext Most places in the kernel that we need to distinguish functions by the type of their arguments, we use '_ul' as a suffix for the unsigned long variant, not '_ext'. Also add kernel-doc. Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 52 ++++++++++++++++++++++++++++----------------- lib/idr.c | 30 +++++++++++++++++--------- net/sched/act_api.c | 6 +++--- 3 files changed, 55 insertions(+), 33 deletions(-) diff --git a/include/linux/idr.h b/include/linux/idr.h index fa2a04b984df44..95a82cf2ed02d7 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -88,7 +88,7 @@ int idr_alloc_cyclic(struct idr *, void *entry, int start, int end, gfp_t); int idr_for_each(const struct idr *, int (*fn)(int id, void *p, void *data), void *data); void *idr_get_next(struct idr *, int *nextid); -void *idr_get_next_ext(struct idr *idr, unsigned long *nextid); +void *idr_get_next_ul(struct idr *, unsigned long *nextid); void *idr_replace(struct idr *, void *, unsigned long id); void idr_destroy(struct idr *); @@ -121,16 +121,18 @@ static inline void idr_preload_end(void) } /** - * idr_find - return pointer for given id - * @idr: idr handle - * @id: lookup key + * idr_find() - Return pointer for given ID. + * @idr: IDR handle. + * @id: Pointer ID. * - * Return the pointer given the id it has been registered with. A %NULL - * return indicates that @id is not valid or you passed %NULL in - * idr_get_new(). + * Looks up the pointer associated with this ID. A %NULL pointer may + * indicate that @id is not allocated or that the %NULL pointer was + * associated with this ID. * * This function can be called under rcu_read_lock(), given that the leaf * pointers lifetimes are correctly managed. + * + * Return: The pointer associated with this ID. */ static inline void *idr_find(const struct idr *idr, unsigned long id) { @@ -138,28 +140,38 @@ static inline void *idr_find(const struct idr *idr, unsigned long id) } /** - * idr_for_each_entry - iterate over an idr's elements of a given type - * @idr: idr handle - * @entry: the type * to use as cursor - * @id: id entry's key + * idr_for_each_entry() - Iterate over an IDR's elements of a given type. + * @idr: IDR handle. + * @entry: The type * to use as cursor + * @id: Entry ID. * * @entry and @id do not need to be initialized before the loop, and - * after normal terminatinon @entry is left with the value NULL. This + * after normal termination @entry is left with the value NULL. This * is convenient for a "not found" value. */ #define idr_for_each_entry(idr, entry, id) \ for (id = 0; ((entry) = idr_get_next(idr, &(id))) != NULL; ++id) -#define idr_for_each_entry_ext(idr, entry, id) \ - for (id = 0; ((entry) = idr_get_next_ext(idr, &(id))) != NULL; ++id) /** - * idr_for_each_entry_continue - continue iteration over an idr's elements of a given type - * @idr: idr handle - * @entry: the type * to use as cursor - * @id: id entry's key + * idr_for_each_entry_ul() - Iterate over an IDR's elements of a given type. + * @idr: IDR handle. + * @entry: The type * to use as cursor. + * @id: Entry ID. + * + * @entry and @id do not need to be initialized before the loop, and + * after normal termination @entry is left with the value NULL. This + * is convenient for a "not found" value. + */ +#define idr_for_each_entry_ul(idr, entry, id) \ + for (id = 0; ((entry) = idr_get_next_ul(idr, &(id))) != NULL; ++id) + +/** + * idr_for_each_entry_continue() - Continue iteration over an IDR's elements of a given type + * @idr: IDR handle. + * @entry: The type * to use as a cursor. + * @id: Entry ID. * - * Continue to iterate over list of given type, continuing after - * the current position. + * Continue to iterate over entries, continuing after the current position. */ #define idr_for_each_entry_continue(idr, entry, id) \ for ((entry) = idr_get_next((idr), &(id)); \ diff --git a/lib/idr.c b/lib/idr.c index c3f16307b9082f..3df44d528b6875 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -136,13 +136,13 @@ int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp) EXPORT_SYMBOL(idr_alloc_cyclic); /** - * idr_for_each - iterate through all stored pointers - * @idr: idr handle - * @fn: function to be called for each pointer - * @data: data passed to callback function + * idr_for_each() - Iterate through all stored pointers. + * @idr: IDR handle. + * @fn: Function to be called for each pointer. + * @data: Data passed to callback function. * * The callback function will be called for each entry in @idr, passing - * the id, the pointer and the data pointer passed to this function. + * the ID, the entry and @data. * * If @fn returns anything other than %0, the iteration stops and that * value is returned from this function. @@ -169,9 +169,9 @@ int idr_for_each(const struct idr *idr, EXPORT_SYMBOL(idr_for_each); /** - * idr_get_next - Find next populated entry - * @idr: idr handle - * @nextid: Pointer to lowest possible ID to return + * idr_get_next() - Find next populated entry. + * @idr: IDR handle. + * @nextid: Pointer to an ID. * * Returns the next populated entry in the tree with an ID greater than * or equal to the value pointed to by @nextid. On exit, @nextid is updated @@ -192,7 +192,17 @@ void *idr_get_next(struct idr *idr, int *nextid) } EXPORT_SYMBOL(idr_get_next); -void *idr_get_next_ext(struct idr *idr, unsigned long *nextid) +/** + * idr_get_next_ul() - Find next populated entry. + * @idr: IDR handle. + * @nextid: Pointer to an ID. + * + * Returns the next populated entry in the tree with an ID greater than + * or equal to the value pointed to by @nextid. On exit, @nextid is updated + * to the ID of the found value. To use in a loop, the value pointed to by + * nextid must be incremented by the user. + */ +void *idr_get_next_ul(struct idr *idr, unsigned long *nextid) { struct radix_tree_iter iter; void __rcu **slot; @@ -204,7 +214,7 @@ void *idr_get_next_ext(struct idr *idr, unsigned long *nextid) *nextid = iter.index; return rcu_dereference_raw(*slot); } -EXPORT_SYMBOL(idr_get_next_ext); +EXPORT_SYMBOL(idr_get_next_ul); /** * idr_replace() - replace pointer for given ID. diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 9b6916a924232e..eba6682727dd9c 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -124,7 +124,7 @@ static int tcf_dump_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, s_i = cb->args[0]; - idr_for_each_entry_ext(idr, p, id) { + idr_for_each_entry_ul(idr, p, id) { index++; if (index < s_i) continue; @@ -181,7 +181,7 @@ static int tcf_del_walker(struct tcf_idrinfo *idrinfo, struct sk_buff *skb, if (nla_put_string(skb, TCA_KIND, ops->kind)) goto nla_put_failure; - idr_for_each_entry_ext(idr, p, id) { + idr_for_each_entry_ul(idr, p, id) { ret = __tcf_idr_release(p, false, true); if (ret == ACT_P_DELETED) { module_put(ops->owner); @@ -351,7 +351,7 @@ void tcf_idrinfo_destroy(const struct tc_action_ops *ops, int ret; unsigned long id = 1; - idr_for_each_entry_ext(idr, p, id) { + idr_for_each_entry_ul(idr, p, id) { ret = __tcf_idr_release(p, false, true); if (ret == ACT_P_DELETED) module_put(ops->owner); From 72fd6c7be701d80eef34da305a6294c61520fe13 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 28 Nov 2017 15:50:12 -0500 Subject: [PATCH 176/237] idr: Warn if old iterators see large IDs Now that the IDR can be used to store large IDs, it is possible somebody might only partially convert their old code and use the iterators which can only handle IDs up to INT_MAX. It's probably unwise to show them a truncated ID, so settle for spewing warnings to dmesg, and terminating the iteration. Signed-off-by: Matthew Wilcox --- lib/idr.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/idr.c b/lib/idr.c index 3df44d528b6875..b47055efceb0a8 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -159,7 +159,11 @@ int idr_for_each(const struct idr *idr, void __rcu **slot; radix_tree_for_each_slot(slot, &idr->idr_rt, &iter, 0) { - int ret = fn(iter.index, rcu_dereference_raw(*slot), data); + int ret; + + if (WARN_ON_ONCE(iter.index > INT_MAX)) + break; + ret = fn(iter.index, rcu_dereference_raw(*slot), data); if (ret) return ret; } @@ -187,6 +191,9 @@ void *idr_get_next(struct idr *idr, int *nextid) if (!slot) return NULL; + if (WARN_ON_ONCE(iter.index > INT_MAX)) + return NULL; + *nextid = iter.index; return rcu_dereference_raw(*slot); } From 6ce711f2750031d12cec91384ac5cfa0a485b60a Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Thu, 30 Nov 2017 13:45:11 -0500 Subject: [PATCH 177/237] idr: Make 1-based IDRs more efficient About 20% of the IDR users in the kernel want the allocated IDs to start at 1. The implementation currently searches all the way down the left hand side of the tree, finds no free ID other than ID 0, walks all the way back up, and then all the way down again. This patch 'rebases' the ID so we fill the entire radix tree, rather than leave a gap at 0. Chris Wilson says: "I did the quick hack of allocating index 0 of the idr and that eradicated idr_get_free() from being at the top of the profiles for the many-object stress tests. This improvement will be much appreciated." Signed-off-by: Matthew Wilcox --- include/linux/idr.h | 66 +++++++++++++++------------ lib/idr.c | 70 +++++++++++++++++++++++++---- tools/testing/radix-tree/idr-test.c | 7 ++- 3 files changed, 103 insertions(+), 40 deletions(-) diff --git a/include/linux/idr.h b/include/linux/idr.h index 95a82cf2ed02d7..86b38df6e1217e 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -18,6 +18,7 @@ struct idr { struct radix_tree_root idr_rt; + unsigned int idr_base; unsigned int idr_next; }; @@ -30,12 +31,20 @@ struct idr { /* Set the IDR flag and the IDR_FREE tag */ #define IDR_RT_MARKER ((__force gfp_t)(3 << __GFP_BITS_SHIFT)) -#define IDR_INIT \ -{ \ - .idr_rt = RADIX_TREE_INIT(IDR_RT_MARKER) \ +#define IDR_INIT_BASE(base) { \ + .idr_rt = RADIX_TREE_INIT(IDR_RT_MARKER), \ + .idr_base = (base), \ + .idr_next = 0, \ } #define DEFINE_IDR(name) struct idr name = IDR_INIT +/** + * IDR_INIT() - Initialise an IDR. + * + * A freshly-initialised IDR contains no IDs. + */ +#define IDR_INIT IDR_INIT_BASE(0) + /** * idr_get_cursor - Return the current position of the cyclic allocator * @idr: idr handle @@ -81,10 +90,12 @@ static inline void idr_set_cursor(struct idr *idr, unsigned int val) void idr_preload(gfp_t gfp_mask); -int idr_alloc(struct idr *, void *, int start, int end, gfp_t); -int __must_check idr_alloc_u32(struct idr *, void *ptr, u32 *nextid, +int idr_alloc(struct idr *, void *ptr, int start, int end, gfp_t); +int __must_check idr_alloc_u32(struct idr *, void *ptr, u32 *id, unsigned long max, gfp_t); -int idr_alloc_cyclic(struct idr *, void *entry, int start, int end, gfp_t); +int idr_alloc_cyclic(struct idr *, void *ptr, int start, int end, gfp_t); +void *idr_remove(struct idr *, unsigned long id); +void *idr_find(const struct idr *, unsigned long id); int idr_for_each(const struct idr *, int (*fn)(int id, void *p, void *data), void *data); void *idr_get_next(struct idr *, int *nextid); @@ -92,15 +103,31 @@ void *idr_get_next_ul(struct idr *, unsigned long *nextid); void *idr_replace(struct idr *, void *, unsigned long id); void idr_destroy(struct idr *); -static inline void *idr_remove(struct idr *idr, unsigned long id) +/** + * idr_init_base() - Initialise an IDR. + * @idr: IDR handle. + * @base: The base value for the IDR. + * + * This variation of idr_init() creates an IDR which will allocate IDs + * starting at %base. + */ +static inline void idr_init_base(struct idr *idr, int base) { - return radix_tree_delete_item(&idr->idr_rt, id, NULL); + INIT_RADIX_TREE(&idr->idr_rt, IDR_RT_MARKER); + idr->idr_base = base; + idr->idr_next = 0; } +/** + * idr_init() - Initialise an IDR. + * @idr: IDR handle. + * + * Initialise a dynamically allocated IDR. To initialise a + * statically allocated IDR, use DEFINE_IDR(). + */ static inline void idr_init(struct idr *idr) { - INIT_RADIX_TREE(&idr->idr_rt, IDR_RT_MARKER); - idr->idr_next = 0; + idr_init_base(idr, 0); } static inline bool idr_is_empty(const struct idr *idr) @@ -120,25 +147,6 @@ static inline void idr_preload_end(void) preempt_enable(); } -/** - * idr_find() - Return pointer for given ID. - * @idr: IDR handle. - * @id: Pointer ID. - * - * Looks up the pointer associated with this ID. A %NULL pointer may - * indicate that @id is not allocated or that the %NULL pointer was - * associated with this ID. - * - * This function can be called under rcu_read_lock(), given that the leaf - * pointers lifetimes are correctly managed. - * - * Return: The pointer associated with this ID. - */ -static inline void *idr_find(const struct idr *idr, unsigned long id) -{ - return radix_tree_lookup(&idr->idr_rt, id); -} - /** * idr_for_each_entry() - Iterate over an IDR's elements of a given type. * @idr: IDR handle. diff --git a/lib/idr.c b/lib/idr.c index b47055efceb0a8..c98d77fcf3934d 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -36,18 +36,21 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid, { struct radix_tree_iter iter; void __rcu **slot; + int base = idr->idr_base; + int id = *nextid; if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) return -EINVAL; if (WARN_ON_ONCE(!(idr->idr_rt.gfp_mask & ROOT_IS_IDR))) idr->idr_rt.gfp_mask |= IDR_RT_MARKER; - radix_tree_iter_init(&iter, *nextid); - slot = idr_get_free(&idr->idr_rt, &iter, gfp, max); + id = (id < base) ? 0 : id - base; + radix_tree_iter_init(&iter, id); + slot = idr_get_free(&idr->idr_rt, &iter, gfp, max - base); if (IS_ERR(slot)) return PTR_ERR(slot); - *nextid = iter.index; + *nextid = iter.index + base; /* there is a memory barrier inside radix_tree_iter_replace() */ radix_tree_iter_replace(&idr->idr_rt, &iter, slot, ptr); radix_tree_iter_tag_clear(&idr->idr_rt, &iter, IDR_FREE); @@ -135,6 +138,46 @@ int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp) } EXPORT_SYMBOL(idr_alloc_cyclic); +/** + * idr_remove() - Remove an ID from the IDR. + * @idr: IDR handle. + * @id: Pointer ID. + * + * Removes this ID from the IDR. If the ID was not previously in the IDR, + * this function returns %NULL. + * + * Since this function modifies the IDR, the caller should provide their + * own locking to ensure that concurrent modification of the same IDR is + * not possible. + * + * Return: The pointer formerly associated with this ID. + */ +void *idr_remove(struct idr *idr, unsigned long id) +{ + return radix_tree_delete_item(&idr->idr_rt, id - idr->idr_base, NULL); +} +EXPORT_SYMBOL_GPL(idr_remove); + +/** + * idr_find() - Return pointer for given ID. + * @idr: IDR handle. + * @id: Pointer ID. + * + * Looks up the pointer associated with this ID. A %NULL pointer may + * indicate that @id is not allocated or that the %NULL pointer was + * associated with this ID. + * + * This function can be called under rcu_read_lock(), given that the leaf + * pointers lifetimes are correctly managed. + * + * Return: The pointer associated with this ID. + */ +void *idr_find(const struct idr *idr, unsigned long id) +{ + return radix_tree_lookup(&idr->idr_rt, id - idr->idr_base); +} +EXPORT_SYMBOL_GPL(idr_find); + /** * idr_for_each() - Iterate through all stored pointers. * @idr: IDR handle. @@ -157,13 +200,14 @@ int idr_for_each(const struct idr *idr, { struct radix_tree_iter iter; void __rcu **slot; + int base = idr->idr_base; radix_tree_for_each_slot(slot, &idr->idr_rt, &iter, 0) { int ret; if (WARN_ON_ONCE(iter.index > INT_MAX)) break; - ret = fn(iter.index, rcu_dereference_raw(*slot), data); + ret = fn(iter.index + base, rcu_dereference_raw(*slot), data); if (ret) return ret; } @@ -186,15 +230,19 @@ void *idr_get_next(struct idr *idr, int *nextid) { struct radix_tree_iter iter; void __rcu **slot; + int base = idr->idr_base; + int id = *nextid; - slot = radix_tree_iter_find(&idr->idr_rt, &iter, *nextid); + id = (id < base) ? 0 : id - base; + slot = radix_tree_iter_find(&idr->idr_rt, &iter, id); if (!slot) return NULL; + id = iter.index + base; - if (WARN_ON_ONCE(iter.index > INT_MAX)) + if (WARN_ON_ONCE(id > INT_MAX)) return NULL; - *nextid = iter.index; + *nextid = id; return rcu_dereference_raw(*slot); } EXPORT_SYMBOL(idr_get_next); @@ -213,12 +261,15 @@ void *idr_get_next_ul(struct idr *idr, unsigned long *nextid) { struct radix_tree_iter iter; void __rcu **slot; + unsigned long base = idr->idr_base; + unsigned long id = *nextid; - slot = radix_tree_iter_find(&idr->idr_rt, &iter, *nextid); + id = (id < base) ? 0 : id - base; + slot = radix_tree_iter_find(&idr->idr_rt, &iter, id); if (!slot) return NULL; - *nextid = iter.index; + *nextid = iter.index + base; return rcu_dereference_raw(*slot); } EXPORT_SYMBOL(idr_get_next_ul); @@ -245,6 +296,7 @@ void *idr_replace(struct idr *idr, void *ptr, unsigned long id) if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) return ERR_PTR(-EINVAL); + id -= idr->idr_base; entry = __radix_tree_lookup(&idr->idr_rt, id, &node, &slot); if (!slot || radix_tree_tag_get(&idr->idr_rt, id, IDR_FREE)) diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 36437ade429cb8..44ef9eba5a7a21 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -153,11 +153,12 @@ void idr_nowait_test(void) idr_destroy(&idr); } -void idr_get_next_test(void) +void idr_get_next_test(int base) { unsigned long i; int nextid; DEFINE_IDR(idr); + idr_init_base(&idr, base); int indices[] = {4, 7, 9, 15, 65, 128, 1000, 99999, 0}; @@ -244,7 +245,9 @@ void idr_checks(void) idr_alloc_test(); idr_null_test(); idr_nowait_test(); - idr_get_next_test(); + idr_get_next_test(0); + idr_get_next_test(1); + idr_get_next_test(4); } /* From ac665d9423474e64e64b34b0e2cea43601b50d7d Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Tue, 6 Feb 2018 15:05:49 -0500 Subject: [PATCH 178/237] idr: Add documentation Move the idr kernel-doc to its own idr.rst file and add a few paragraphs about how to use it. Also add some more kernel-doc. Signed-off-by: Matthew Wilcox --- Documentation/core-api/idr.rst | 79 +++++++++++++++++++++++++++ Documentation/core-api/index.rst | 1 + Documentation/core-api/kernel-api.rst | 12 ---- include/linux/idr.h | 16 +++++- 4 files changed, 95 insertions(+), 13 deletions(-) create mode 100644 Documentation/core-api/idr.rst diff --git a/Documentation/core-api/idr.rst b/Documentation/core-api/idr.rst new file mode 100644 index 00000000000000..9078a5c3ac9550 --- /dev/null +++ b/Documentation/core-api/idr.rst @@ -0,0 +1,79 @@ +.. SPDX-License-Identifier: CC-BY-SA-4.0 + +============= +ID Allocation +============= + +:Author: Matthew Wilcox + +Overview +======== + +A common problem to solve is allocating identifiers (IDs); generally +small numbers which identify a thing. Examples include file descriptors, +process IDs, packet identifiers in networking protocols, SCSI tags +and device instance numbers. The IDR and the IDA provide a reasonable +solution to the problem to avoid everybody inventing their own. The IDR +provides the ability to map an ID to a pointer, while the IDA provides +only ID allocation, and as a result is much more memory-efficient. + +IDR usage +========= + +Start by initialising an IDR, either with :c:func:`DEFINE_IDR` +for statically allocated IDRs or :c:func:`idr_init` for dynamically +allocated IDRs. + +You can call :c:func:`idr_alloc` to allocate an unused ID. Look up +the pointer you associated with the ID by calling :c:func:`idr_find` +and free the ID by calling :c:func:`idr_remove`. + +If you need to change the pointer associated with an ID, you can call +:c:func:`idr_replace`. One common reason to do this is to reserve an +ID by passing a ``NULL`` pointer to the allocation function; initialise the +object with the reserved ID and finally insert the initialised object +into the IDR. + +Some users need to allocate IDs larger than ``INT_MAX``. So far all of +these users have been content with a ``UINT_MAX`` limit, and they use +:c:func:`idr_alloc_u32`. If you need IDs that will not fit in a u32, +we will work with you to address your needs. + +If you need to allocate IDs sequentially, you can use +:c:func:`idr_alloc_cyclic`. The IDR becomes less efficient when dealing +with larger IDs, so using this function comes at a slight cost. + +To perform an action on all pointers used by the IDR, you can +either use the callback-based :c:func:`idr_for_each` or the +iterator-style :c:func:`idr_for_each_entry`. You may need to use +:c:func:`idr_for_each_entry_continue` to continue an iteration. You can +also use :c:func:`idr_get_next` if the iterator doesn't fit your needs. + +When you have finished using an IDR, you can call :c:func:`idr_destroy` +to release the memory used by the IDR. This will not free the objects +pointed to from the IDR; if you want to do that, use one of the iterators +to do it. + +You can use :c:func:`idr_is_empty` to find out whether there are any +IDs currently allocated. + +If you need to take a lock while allocating a new ID from the IDR, +you may need to pass a restrictive set of GFP flags, which can lead +to the IDR being unable to allocate memory. To work around this, +you can call :c:func:`idr_preload` before taking the lock, and then +:c:func:`idr_preload_end` after the allocation. + +.. kernel-doc:: include/linux/idr.h + :doc: idr sync + +IDA usage +========= + +.. kernel-doc:: lib/idr.c + :doc: IDA description + +Functions and structures +======================== + +.. kernel-doc:: include/linux/idr.h +.. kernel-doc:: lib/idr.c diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst index 1b1fd01990b592..c670a80317862d 100644 --- a/Documentation/core-api/index.rst +++ b/Documentation/core-api/index.rst @@ -16,6 +16,7 @@ Core utilities atomic_ops refcount-vs-atomic cpu_hotplug + idr local_ops workqueue genericirq diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst index e7fadf02c5112b..ff335f8aeb39e2 100644 --- a/Documentation/core-api/kernel-api.rst +++ b/Documentation/core-api/kernel-api.rst @@ -103,18 +103,6 @@ CRC Functions .. kernel-doc:: lib/crc-itu-t.c :export: -idr/ida Functions ------------------ - -.. kernel-doc:: include/linux/idr.h - :doc: idr sync - -.. kernel-doc:: lib/idr.c - :doc: IDA description - -.. kernel-doc:: lib/idr.c - :export: - Math Functions in Linux ======================= diff --git a/include/linux/idr.h b/include/linux/idr.h index 86b38df6e1217e..7d6a6313f0aba5 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -36,7 +36,6 @@ struct idr { .idr_base = (base), \ .idr_next = 0, \ } -#define DEFINE_IDR(name) struct idr name = IDR_INIT /** * IDR_INIT() - Initialise an IDR. @@ -45,6 +44,15 @@ struct idr { */ #define IDR_INIT IDR_INIT_BASE(0) +/** + * DEFINE_IDR() - Define a statically-allocated IDR + * @name: Name of IDR + * + * An IDR defined using this macro is ready for use with no additional + * initialisation required. It contains no IDs. + */ +#define DEFINE_IDR(name) struct idr name = IDR_INIT + /** * idr_get_cursor - Return the current position of the cyclic allocator * @idr: idr handle @@ -130,6 +138,12 @@ static inline void idr_init(struct idr *idr) idr_init_base(idr, 0); } +/** + * idr_is_empty() - Are there any IDs allocated? + * @idr: IDR handle. + * + * Return: %true if any IDs have been allocated from this IDR. + */ static inline bool idr_is_empty(const struct idr *idr) { return radix_tree_empty(&idr->idr_rt) && From 202fb4ef81e3ec765c23bd1e6746a5c25b797d0e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Wed, 31 Jan 2018 12:12:20 +0000 Subject: [PATCH 179/237] arm64: spinlock: Fix theoretical trylock() A-B-A with LSE atomics If the spinlock "next" ticket wraps around between the initial LDR and the cmpxchg in the LSE version of spin_trylock, then we can erroneously think that we have successfuly acquired the lock because we only check whether the next ticket return by the cmpxchg is equal to the owner ticket in our updated lock word. This patch fixes the issue by performing a full 32-bit check of the lock word when trying to determine whether or not the CASA instruction updated memory. Reported-by: Catalin Marinas Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/spinlock.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/include/asm/spinlock.h b/arch/arm64/include/asm/spinlock.h index fdb827c7832fd1..ebdae15d665de7 100644 --- a/arch/arm64/include/asm/spinlock.h +++ b/arch/arm64/include/asm/spinlock.h @@ -87,8 +87,8 @@ static inline int arch_spin_trylock(arch_spinlock_t *lock) " cbnz %w1, 1f\n" " add %w1, %w0, %3\n" " casa %w0, %w1, %2\n" - " and %w1, %w1, #0xffff\n" - " eor %w1, %w1, %w0, lsr #16\n" + " sub %w1, %w1, %3\n" + " eor %w1, %w1, %w0\n" "1:") : "=&r" (lockval), "=&r" (tmp), "+Q" (*lock) : "I" (1 << TICKET_SHIFT) From 3060e9f0d14b46eb1949aaf9a31519ef75e59fda Mon Sep 17 00:00:00 2001 From: Shanker Donthineni Date: Mon, 29 Jan 2018 11:59:52 +0000 Subject: [PATCH 180/237] arm64: Add software workaround for Falkor erratum 1041 The ARM architecture defines the memory locations that are permitted to be accessed as the result of a speculative instruction fetch from an exception level for which all stages of translation are disabled. Specifically, the core is permitted to speculatively fetch from the 4KB region containing the current program counter 4K and next 4K. When translation is changed from enabled to disabled for the running exception level (SCTLR_ELn[M] changed from a value of 1 to 0), the Falkor core may errantly speculatively access memory locations outside of the 4KB region permitted by the architecture. The errant memory access may lead to one of the following unexpected behaviors. 1) A System Error Interrupt (SEI) being raised by the Falkor core due to the errant memory access attempting to access a region of memory that is protected by a slave-side memory protection unit. 2) Unpredictable device behavior due to a speculative read from device memory. This behavior may only occur if the instruction cache is disabled prior to or coincident with translation being changed from enabled to disabled. The conditions leading to this erratum will not occur when either of the following occur: 1) A higher exception level disables translation of a lower exception level (e.g. EL2 changing SCTLR_EL1[M] from a value of 1 to 0). 2) An exception level disabling its stage-1 translation if its stage-2 translation is enabled (e.g. EL1 changing SCTLR_EL1[M] from a value of 1 to 0 when HCR_EL2[VM] has a value of 1). To avoid the errant behavior, software must execute an ISB immediately prior to executing the MSR that will change SCTLR_ELn[M] from 1 to 0. Signed-off-by: Shanker Donthineni Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- Documentation/arm64/silicon-errata.txt | 1 + arch/arm64/Kconfig | 12 +++++++++++- arch/arm64/include/asm/assembler.h | 10 ++++++++++ arch/arm64/kernel/cpu-reset.S | 1 + arch/arm64/kernel/efi-entry.S | 2 ++ arch/arm64/kernel/head.S | 1 + arch/arm64/kernel/relocate_kernel.S | 1 + arch/arm64/kvm/hyp-init.S | 1 + 8 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt index b9d93e981a0528..c1d520de6dfebd 100644 --- a/Documentation/arm64/silicon-errata.txt +++ b/Documentation/arm64/silicon-errata.txt @@ -75,3 +75,4 @@ stable kernels. | Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 | | Qualcomm Tech. | Falkor v1 | E1009 | QCOM_FALKOR_ERRATUM_1009 | | Qualcomm Tech. | QDF2400 ITS | E0065 | QCOM_QDF2400_ERRATUM_0065 | +| Qualcomm Tech. | Falkor v{1,2} | E1041 | QCOM_FALKOR_ERRATUM_1041 | diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 1d51c8edf34be6..b488076d63c2c3 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -550,7 +550,6 @@ config QCOM_QDF2400_ERRATUM_0065 If unsure, say Y. - config SOCIONEXT_SYNQUACER_PREITS bool "Socionext Synquacer: Workaround for GICv3 pre-ITS" default y @@ -569,6 +568,17 @@ config HISILICON_ERRATUM_161600802 a 128kB offset to be applied to the target address in this commands. If unsure, say Y. + +config QCOM_FALKOR_ERRATUM_E1041 + bool "Falkor E1041: Speculative instruction fetches might cause errant memory access" + default y + help + Falkor CPU may speculatively fetch instructions from an improper + memory location when MMU translation is changed from SCTLR_ELn[M]=1 + to SCTLR_ELn[M]=0. Prefix an ISB instruction to fix the problem. + + If unsure, say Y. + endmenu diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 794fe81226024f..3873dd7b5a3274 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -523,4 +523,14 @@ alternative_endif #endif .endm +/** + * Errata workaround prior to disable MMU. Insert an ISB immediately prior + * to executing the MSR that will change SCTLR_ELn[M] from a value of 1 to 0. + */ + .macro pre_disable_mmu_workaround +#ifdef CONFIG_QCOM_FALKOR_ERRATUM_E1041 + isb +#endif + .endm + #endif /* __ASM_ASSEMBLER_H */ diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S index 65f42d2574142d..2a752cb2a0f35a 100644 --- a/arch/arm64/kernel/cpu-reset.S +++ b/arch/arm64/kernel/cpu-reset.S @@ -37,6 +37,7 @@ ENTRY(__cpu_soft_restart) mrs x12, sctlr_el1 ldr x13, =SCTLR_ELx_FLAGS bic x12, x12, x13 + pre_disable_mmu_workaround msr sctlr_el1, x12 isb diff --git a/arch/arm64/kernel/efi-entry.S b/arch/arm64/kernel/efi-entry.S index 4e6ad355bd058e..6b9736c3fb5630 100644 --- a/arch/arm64/kernel/efi-entry.S +++ b/arch/arm64/kernel/efi-entry.S @@ -96,6 +96,7 @@ ENTRY(entry) mrs x0, sctlr_el2 bic x0, x0, #1 << 0 // clear SCTLR.M bic x0, x0, #1 << 2 // clear SCTLR.C + pre_disable_mmu_workaround msr sctlr_el2, x0 isb b 2f @@ -103,6 +104,7 @@ ENTRY(entry) mrs x0, sctlr_el1 bic x0, x0, #1 << 0 // clear SCTLR.M bic x0, x0, #1 << 2 // clear SCTLR.C + pre_disable_mmu_workaround msr sctlr_el1, x0 isb 2: diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index c3b241b8b659de..ba3ab04788dc98 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -849,6 +849,7 @@ __primary_switch: * to take into account by discarding the current kernel mapping and * creating a new one. */ + pre_disable_mmu_workaround msr sctlr_el1, x20 // disable the MMU isb bl __create_page_tables // recreate kernel mapping diff --git a/arch/arm64/kernel/relocate_kernel.S b/arch/arm64/kernel/relocate_kernel.S index ce704a4aeadd43..f407e422a7200b 100644 --- a/arch/arm64/kernel/relocate_kernel.S +++ b/arch/arm64/kernel/relocate_kernel.S @@ -45,6 +45,7 @@ ENTRY(arm64_relocate_new_kernel) mrs x0, sctlr_el2 ldr x1, =SCTLR_ELx_FLAGS bic x0, x0, x1 + pre_disable_mmu_workaround msr sctlr_el2, x0 isb 1: diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S index 8a00de187e5618..e086c6eff8c6b3 100644 --- a/arch/arm64/kvm/hyp-init.S +++ b/arch/arm64/kvm/hyp-init.S @@ -153,6 +153,7 @@ reset: mrs x5, sctlr_el2 ldr x6, =SCTLR_ELx_FLAGS bic x5, x5, x6 // Clear SCTL_M and etc + pre_disable_mmu_workaround msr sctlr_el2, x5 isb From 41acec624087b1268a15f414cf7d573deebafeec Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 29 Jan 2018 11:59:53 +0000 Subject: [PATCH 181/237] arm64: kpti: Make use of nG dependent on arm64_kernel_unmapped_at_el0() To allow systems which do not require kpti to continue running with global kernel mappings (which appears to be a requirement for Cavium ThunderX due to a CPU erratum), make the use of nG in the kernel page tables dependent on arm64_kernel_unmapped_at_el0(), which is resolved at runtime. Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/kernel-pgtable.h | 12 ++-------- arch/arm64/include/asm/pgtable-prot.h | 30 ++++++++++++------------- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/arch/arm64/include/asm/kernel-pgtable.h b/arch/arm64/include/asm/kernel-pgtable.h index 82386e860dd2aa..a780f6714b4458 100644 --- a/arch/arm64/include/asm/kernel-pgtable.h +++ b/arch/arm64/include/asm/kernel-pgtable.h @@ -123,16 +123,8 @@ /* * Initial memory map attributes. */ -#define _SWAPPER_PTE_FLAGS (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) -#define _SWAPPER_PMD_FLAGS (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) - -#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 -#define SWAPPER_PTE_FLAGS (_SWAPPER_PTE_FLAGS | PTE_NG) -#define SWAPPER_PMD_FLAGS (_SWAPPER_PMD_FLAGS | PMD_SECT_NG) -#else -#define SWAPPER_PTE_FLAGS _SWAPPER_PTE_FLAGS -#define SWAPPER_PMD_FLAGS _SWAPPER_PMD_FLAGS -#endif +#define SWAPPER_PTE_FLAGS (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) +#define SWAPPER_PMD_FLAGS (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) #if ARM64_SWAPPER_USES_SECTION_MAPS #define SWAPPER_MM_MMUFLAGS (PMD_ATTRINDX(MT_NORMAL) | SWAPPER_PMD_FLAGS) diff --git a/arch/arm64/include/asm/pgtable-prot.h b/arch/arm64/include/asm/pgtable-prot.h index 22a926825e3fb8..2db84df5eb4224 100644 --- a/arch/arm64/include/asm/pgtable-prot.h +++ b/arch/arm64/include/asm/pgtable-prot.h @@ -37,13 +37,11 @@ #define _PROT_DEFAULT (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED) #define _PROT_SECT_DEFAULT (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S) -#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 -#define PROT_DEFAULT (_PROT_DEFAULT | PTE_NG) -#define PROT_SECT_DEFAULT (_PROT_SECT_DEFAULT | PMD_SECT_NG) -#else -#define PROT_DEFAULT _PROT_DEFAULT -#define PROT_SECT_DEFAULT _PROT_SECT_DEFAULT -#endif /* CONFIG_UNMAP_KERNEL_AT_EL0 */ +#define PTE_MAYBE_NG (arm64_kernel_unmapped_at_el0() ? PTE_NG : 0) +#define PMD_MAYBE_NG (arm64_kernel_unmapped_at_el0() ? PMD_SECT_NG : 0) + +#define PROT_DEFAULT (_PROT_DEFAULT | PTE_MAYBE_NG) +#define PROT_SECT_DEFAULT (_PROT_SECT_DEFAULT | PMD_MAYBE_NG) #define PROT_DEVICE_nGnRnE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRnE)) #define PROT_DEVICE_nGnRE (PROT_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_ATTRINDX(MT_DEVICE_nGnRE)) @@ -55,22 +53,22 @@ #define PROT_SECT_NORMAL (PROT_SECT_DEFAULT | PMD_SECT_PXN | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) #define PROT_SECT_NORMAL_EXEC (PROT_SECT_DEFAULT | PMD_SECT_UXN | PMD_ATTRINDX(MT_NORMAL)) -#define _PAGE_DEFAULT (PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) -#define _HYP_PAGE_DEFAULT (_PAGE_DEFAULT & ~PTE_NG) +#define _PAGE_DEFAULT (_PROT_DEFAULT | PTE_ATTRINDX(MT_NORMAL)) +#define _HYP_PAGE_DEFAULT _PAGE_DEFAULT -#define PAGE_KERNEL __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_WRITE) -#define PAGE_KERNEL_RO __pgprot(_PAGE_DEFAULT | PTE_PXN | PTE_UXN | PTE_DIRTY | PTE_RDONLY) -#define PAGE_KERNEL_ROX __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_RDONLY) -#define PAGE_KERNEL_EXEC __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE) -#define PAGE_KERNEL_EXEC_CONT __pgprot(_PAGE_DEFAULT | PTE_UXN | PTE_DIRTY | PTE_WRITE | PTE_CONT) +#define PAGE_KERNEL __pgprot(PROT_NORMAL) +#define PAGE_KERNEL_RO __pgprot((PROT_NORMAL & ~PTE_WRITE) | PTE_RDONLY) +#define PAGE_KERNEL_ROX __pgprot((PROT_NORMAL & ~(PTE_WRITE | PTE_PXN)) | PTE_RDONLY) +#define PAGE_KERNEL_EXEC __pgprot(PROT_NORMAL & ~PTE_PXN) +#define PAGE_KERNEL_EXEC_CONT __pgprot((PROT_NORMAL & ~PTE_PXN) | PTE_CONT) #define PAGE_HYP __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_HYP_XN) #define PAGE_HYP_EXEC __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY) #define PAGE_HYP_RO __pgprot(_HYP_PAGE_DEFAULT | PTE_HYP | PTE_RDONLY | PTE_HYP_XN) #define PAGE_HYP_DEVICE __pgprot(PROT_DEVICE_nGnRE | PTE_HYP) -#define PAGE_S2 __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY) -#define PAGE_S2_DEVICE __pgprot(PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_UXN) +#define PAGE_S2 __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_NORMAL) | PTE_S2_RDONLY) +#define PAGE_S2_DEVICE __pgprot(_PROT_DEFAULT | PTE_S2_MEMATTR(MT_S2_DEVICE_nGnRE) | PTE_S2_RDONLY | PTE_UXN) #define PAGE_NONE __pgprot(((_PAGE_DEFAULT) & ~PTE_VALID) | PTE_PROT_NONE | PTE_RDONLY | PTE_NG | PTE_PXN | PTE_UXN) #define PAGE_SHARED __pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_WRITE) From 4e602056559633303d7e5bb2ff624778ca248f68 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 29 Jan 2018 11:59:54 +0000 Subject: [PATCH 182/237] arm64: mm: Permit transitioning from Global to Non-Global without BBM Break-before-make is not needed when transitioning from Global to Non-Global mappings, provided that the contiguous hint is not being used. Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/mm/mmu.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index b44992ec9643e5..fc7902bda02bce 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -118,6 +118,10 @@ static bool pgattr_change_is_safe(u64 old, u64 new) if ((old | new) & PTE_CONT) return false; + /* Transitioning from Global to Non-Global is safe */ + if (((old ^ new) == PTE_NG) && (new & PTE_NG)) + return true; + return ((old ^ new) & ~mask) == 0; } From f992b4dfd58be07e31a42bc940a53b3e4b282616 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 6 Feb 2018 22:22:50 +0000 Subject: [PATCH 183/237] arm64: kpti: Add ->enable callback to remap swapper using nG mappings Defaulting to global mappings for kernel space is generally good for performance and appears to be necessary for Cavium ThunderX. If we subsequently decide that we need to enable kpti, then we need to rewrite our existing page table entries to be non-global. This is fiddly, and made worse by the possible use of contiguous mappings, which require a strict break-before-make sequence. Since the enable callback runs on each online CPU from stop_machine context, we can have all CPUs enter the idmap, where secondaries can wait for the primary CPU to rewrite swapper with its MMU off. It's all fairly horrible, but at least it only runs once. Tested-by: Marc Zyngier Reviewed-by: Marc Zyngier Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/assembler.h | 10 ++ arch/arm64/kernel/cpufeature.c | 25 ++++ arch/arm64/mm/proc.S | 204 +++++++++++++++++++++++++++-- 3 files changed, 231 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 3873dd7b5a3274..5aae7a6e8ab93c 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -523,6 +523,16 @@ alternative_endif #endif .endm + .macro pte_to_phys, phys, pte +#ifdef CONFIG_ARM64_PA_BITS_52 + ubfiz \phys, \pte, #(48 - 16 - 12), #16 + bfxil \phys, \pte, #16, #32 + lsl \phys, \phys, #16 +#else + and \phys, \pte, #PTE_ADDR_MASK +#endif + .endm + /** * Errata workaround prior to disable MMU. Insert an ISB immediately prior * to executing the MSR that will change SCTLR_ELn[M] from a value of 1 to 0. diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 4b6f9051cf0c2b..cd9f46952db3c2 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -880,6 +880,30 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry, ID_AA64PFR0_CSV3_SHIFT); } +static int kpti_install_ng_mappings(void *__unused) +{ + typedef void (kpti_remap_fn)(int, int, phys_addr_t); + extern kpti_remap_fn idmap_kpti_install_ng_mappings; + kpti_remap_fn *remap_fn; + + static bool kpti_applied = false; + int cpu = smp_processor_id(); + + if (kpti_applied) + return 0; + + remap_fn = (void *)__pa_symbol(idmap_kpti_install_ng_mappings); + + cpu_install_idmap(); + remap_fn(cpu, num_online_cpus(), __pa_symbol(swapper_pg_dir)); + cpu_uninstall_idmap(); + + if (!cpu) + kpti_applied = true; + + return 0; +} + static int __init parse_kpti(char *str) { bool enabled; @@ -1003,6 +1027,7 @@ static const struct arm64_cpu_capabilities arm64_features[] = { .capability = ARM64_UNMAP_KERNEL_AT_EL0, .def_scope = SCOPE_SYSTEM, .matches = unmap_kernel_at_el0, + .enable = kpti_install_ng_mappings, }, #endif { diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index 9f177aac639027..ab8660eb55cad6 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -166,6 +166,17 @@ ENTRY(cpu_do_switch_mm) ENDPROC(cpu_do_switch_mm) .pushsection ".idmap.text", "ax" + +.macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2 + adrp \tmp1, empty_zero_page + phys_to_ttbr \tmp1, \tmp2 + msr ttbr1_el1, \tmp2 + isb + tlbi vmalle1 + dsb nsh + isb +.endm + /* * void idmap_cpu_replace_ttbr1(phys_addr_t new_pgd) * @@ -175,14 +186,7 @@ ENDPROC(cpu_do_switch_mm) ENTRY(idmap_cpu_replace_ttbr1) save_and_disable_daif flags=x2 - adrp x1, empty_zero_page - phys_to_ttbr x1, x3 - msr ttbr1_el1, x3 - isb - - tlbi vmalle1 - dsb nsh - isb + __idmap_cpu_set_reserved_ttbr1 x1, x3 phys_to_ttbr x0, x3 msr ttbr1_el1, x3 @@ -194,6 +198,190 @@ ENTRY(idmap_cpu_replace_ttbr1) ENDPROC(idmap_cpu_replace_ttbr1) .popsection +#ifdef CONFIG_UNMAP_KERNEL_AT_EL0 + .pushsection ".idmap.text", "ax" + + .macro __idmap_kpti_get_pgtable_ent, type + dc cvac, cur_\()\type\()p // Ensure any existing dirty + dmb sy // lines are written back before + ldr \type, [cur_\()\type\()p] // loading the entry + tbz \type, #0, next_\()\type // Skip invalid entries + .endm + + .macro __idmap_kpti_put_pgtable_ent_ng, type + orr \type, \type, #PTE_NG // Same bit for blocks and pages + str \type, [cur_\()\type\()p] // Update the entry and ensure it + dc civac, cur_\()\type\()p // is visible to all CPUs. + .endm + +/* + * void __kpti_install_ng_mappings(int cpu, int num_cpus, phys_addr_t swapper) + * + * Called exactly once from stop_machine context by each CPU found during boot. + */ +__idmap_kpti_flag: + .long 1 +ENTRY(idmap_kpti_install_ng_mappings) + cpu .req w0 + num_cpus .req w1 + swapper_pa .req x2 + swapper_ttb .req x3 + flag_ptr .req x4 + cur_pgdp .req x5 + end_pgdp .req x6 + pgd .req x7 + cur_pudp .req x8 + end_pudp .req x9 + pud .req x10 + cur_pmdp .req x11 + end_pmdp .req x12 + pmd .req x13 + cur_ptep .req x14 + end_ptep .req x15 + pte .req x16 + + mrs swapper_ttb, ttbr1_el1 + adr flag_ptr, __idmap_kpti_flag + + cbnz cpu, __idmap_kpti_secondary + + /* We're the boot CPU. Wait for the others to catch up */ + sevl +1: wfe + ldaxr w18, [flag_ptr] + eor w18, w18, num_cpus + cbnz w18, 1b + + /* We need to walk swapper, so turn off the MMU. */ + pre_disable_mmu_workaround + mrs x18, sctlr_el1 + bic x18, x18, #SCTLR_ELx_M + msr sctlr_el1, x18 + isb + + /* Everybody is enjoying the idmap, so we can rewrite swapper. */ + /* PGD */ + mov cur_pgdp, swapper_pa + add end_pgdp, cur_pgdp, #(PTRS_PER_PGD * 8) +do_pgd: __idmap_kpti_get_pgtable_ent pgd + tbnz pgd, #1, walk_puds + __idmap_kpti_put_pgtable_ent_ng pgd +next_pgd: + add cur_pgdp, cur_pgdp, #8 + cmp cur_pgdp, end_pgdp + b.ne do_pgd + + /* Publish the updated tables and nuke all the TLBs */ + dsb sy + tlbi vmalle1is + dsb ish + isb + + /* We're done: fire up the MMU again */ + mrs x18, sctlr_el1 + orr x18, x18, #SCTLR_ELx_M + msr sctlr_el1, x18 + isb + + /* Set the flag to zero to indicate that we're all done */ + str wzr, [flag_ptr] + ret + + /* PUD */ +walk_puds: + .if CONFIG_PGTABLE_LEVELS > 3 + pte_to_phys cur_pudp, pgd + add end_pudp, cur_pudp, #(PTRS_PER_PUD * 8) +do_pud: __idmap_kpti_get_pgtable_ent pud + tbnz pud, #1, walk_pmds + __idmap_kpti_put_pgtable_ent_ng pud +next_pud: + add cur_pudp, cur_pudp, 8 + cmp cur_pudp, end_pudp + b.ne do_pud + b next_pgd + .else /* CONFIG_PGTABLE_LEVELS <= 3 */ + mov pud, pgd + b walk_pmds +next_pud: + b next_pgd + .endif + + /* PMD */ +walk_pmds: + .if CONFIG_PGTABLE_LEVELS > 2 + pte_to_phys cur_pmdp, pud + add end_pmdp, cur_pmdp, #(PTRS_PER_PMD * 8) +do_pmd: __idmap_kpti_get_pgtable_ent pmd + tbnz pmd, #1, walk_ptes + __idmap_kpti_put_pgtable_ent_ng pmd +next_pmd: + add cur_pmdp, cur_pmdp, #8 + cmp cur_pmdp, end_pmdp + b.ne do_pmd + b next_pud + .else /* CONFIG_PGTABLE_LEVELS <= 2 */ + mov pmd, pud + b walk_ptes +next_pmd: + b next_pud + .endif + + /* PTE */ +walk_ptes: + pte_to_phys cur_ptep, pmd + add end_ptep, cur_ptep, #(PTRS_PER_PTE * 8) +do_pte: __idmap_kpti_get_pgtable_ent pte + __idmap_kpti_put_pgtable_ent_ng pte +next_pte: + add cur_ptep, cur_ptep, #8 + cmp cur_ptep, end_ptep + b.ne do_pte + b next_pmd + + /* Secondary CPUs end up here */ +__idmap_kpti_secondary: + /* Uninstall swapper before surgery begins */ + __idmap_cpu_set_reserved_ttbr1 x18, x17 + + /* Increment the flag to let the boot CPU we're ready */ +1: ldxr w18, [flag_ptr] + add w18, w18, #1 + stxr w17, w18, [flag_ptr] + cbnz w17, 1b + + /* Wait for the boot CPU to finish messing around with swapper */ + sevl +1: wfe + ldxr w18, [flag_ptr] + cbnz w18, 1b + + /* All done, act like nothing happened */ + msr ttbr1_el1, swapper_ttb + isb + ret + + .unreq cpu + .unreq num_cpus + .unreq swapper_pa + .unreq swapper_ttb + .unreq flag_ptr + .unreq cur_pgdp + .unreq end_pgdp + .unreq pgd + .unreq cur_pudp + .unreq end_pudp + .unreq pud + .unreq cur_pmdp + .unreq end_pmdp + .unreq pmd + .unreq cur_ptep + .unreq end_ptep + .unreq pte +ENDPROC(idmap_kpti_install_ng_mappings) + .popsection +#endif + /* * __cpu_setup * From 6dc52b15c4a48052ade2529d639eee401d76e469 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Mon, 29 Jan 2018 11:59:56 +0000 Subject: [PATCH 184/237] arm64: Force KPTI to be disabled on Cavium ThunderX Cavium ThunderX's erratum 27456 results in a corruption of icache entries that are loaded from memory that is mapped as non-global (i.e. ASID-tagged). As KPTI is based on memory being mapped non-global, let's prevent it from kicking in if this erratum is detected. Signed-off-by: Marc Zyngier [will: Update comment] Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/kernel/cpufeature.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index cd9f46952db3c2..0ff8ab79352c50 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -855,12 +855,23 @@ static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry, int __unused) { + char const *str = "command line option"; u64 pfr0 = read_sanitised_ftr_reg(SYS_ID_AA64PFR0_EL1); - /* Forced on command line? */ + /* + * For reasons that aren't entirely clear, enabling KPTI on Cavium + * ThunderX leads to apparent I-cache corruption of kernel text, which + * ends as well as you might imagine. Don't even try. + */ + if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_27456)) { + str = "ARM64_WORKAROUND_CAVIUM_27456"; + __kpti_forced = -1; + } + + /* Forced? */ if (__kpti_forced) { - pr_info_once("kernel page table isolation forced %s by command line option\n", - __kpti_forced > 0 ? "ON" : "OFF"); + pr_info_once("kernel page table isolation forced %s by %s\n", + __kpti_forced > 0 ? "ON" : "OFF", str); return __kpti_forced > 0; } From fa0465fc07c2f9f47bd1198ab368d341bd7c7e4e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 29 Jan 2018 11:59:57 +0000 Subject: [PATCH 185/237] arm64: assembler: Change order of macro arguments in phys_to_ttbr Since AArch64 assembly instructions take the destination register as their first operand, do the same thing for the phys_to_ttbr macro. Acked-by: Robin Murphy Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/assembler.h | 2 +- arch/arm64/kernel/head.S | 4 ++-- arch/arm64/kernel/hibernate-asm.S | 4 ++-- arch/arm64/kvm/hyp-init.S | 2 +- arch/arm64/mm/proc.S | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 5aae7a6e8ab93c..47555f632ffd9f 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -514,7 +514,7 @@ alternative_endif * phys: physical address, preserved * ttbr: returns the TTBR value */ - .macro phys_to_ttbr, phys, ttbr + .macro phys_to_ttbr, ttbr, phys #ifdef CONFIG_ARM64_PA_BITS_52 orr \ttbr, \phys, \phys, lsr #46 and \ttbr, \ttbr, #TTBR_BADDR_MASK_52 diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index ba3ab04788dc98..341649c08337d5 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -776,8 +776,8 @@ ENTRY(__enable_mmu) update_early_cpu_boot_status 0, x1, x2 adrp x1, idmap_pg_dir adrp x2, swapper_pg_dir - phys_to_ttbr x1, x3 - phys_to_ttbr x2, x4 + phys_to_ttbr x3, x1 + phys_to_ttbr x4, x2 msr ttbr0_el1, x3 // load TTBR0 msr ttbr1_el1, x4 // load TTBR1 isb diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernate-asm.S index 84f5d52fdddac5..dd14ab8c9f724f 100644 --- a/arch/arm64/kernel/hibernate-asm.S +++ b/arch/arm64/kernel/hibernate-asm.S @@ -34,12 +34,12 @@ * each stage of the walk. */ .macro break_before_make_ttbr_switch zero_page, page_table, tmp - phys_to_ttbr \zero_page, \tmp + phys_to_ttbr \tmp, \zero_page msr ttbr1_el1, \tmp isb tlbi vmalle1 dsb nsh - phys_to_ttbr \page_table, \tmp + phys_to_ttbr \tmp, \page_table msr ttbr1_el1, \tmp isb .endm diff --git a/arch/arm64/kvm/hyp-init.S b/arch/arm64/kvm/hyp-init.S index e086c6eff8c6b3..5aa9ccf6db9930 100644 --- a/arch/arm64/kvm/hyp-init.S +++ b/arch/arm64/kvm/hyp-init.S @@ -63,7 +63,7 @@ __do_hyp_init: cmp x0, #HVC_STUB_HCALL_NR b.lo __kvm_handle_stub_hvc - phys_to_ttbr x0, x4 + phys_to_ttbr x4, x0 msr ttbr0_el2, x4 mrs x4, tcr_el1 diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index ab8660eb55cad6..cfd22ba9b510e2 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -153,7 +153,7 @@ ENDPROC(cpu_do_resume) ENTRY(cpu_do_switch_mm) mrs x2, ttbr1_el1 mmid x1, x1 // get mm->context.id - phys_to_ttbr x0, x3 + phys_to_ttbr x3, x0 #ifdef CONFIG_ARM64_SW_TTBR0_PAN bfi x3, x1, #48, #16 // set the ASID field in TTBR0 #endif @@ -169,7 +169,7 @@ ENDPROC(cpu_do_switch_mm) .macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2 adrp \tmp1, empty_zero_page - phys_to_ttbr \tmp1, \tmp2 + phys_to_ttbr \tmp2, \tmp1 msr ttbr1_el1, \tmp2 isb tlbi vmalle1 @@ -188,7 +188,7 @@ ENTRY(idmap_cpu_replace_ttbr1) __idmap_cpu_set_reserved_ttbr1 x1, x3 - phys_to_ttbr x0, x3 + phys_to_ttbr x3, x0 msr ttbr1_el1, x3 isb From f167211a93ac41a65b7a0ab79d4479d0fb58c4f1 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 29 Jan 2018 11:59:58 +0000 Subject: [PATCH 186/237] arm64: entry: Reword comment about post_ttbr_update_workaround We don't fully understand the Cavium ThunderX erratum, but it appears that mapping the kernel as nG can lead to horrible consequences such as attempting to execute userspace from kernel context. Since kpti isn't enabled for these CPUs anyway, simplify the comment justifying the lack of post_ttbr_update_workaround in the exception trampoline. Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/kernel/entry.S | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index b34e717d75970c..9b8635d9d7ae43 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -1013,16 +1013,9 @@ alternative_else_nop_endif orr \tmp, \tmp, #USER_ASID_FLAG msr ttbr1_el1, \tmp /* - * We avoid running the post_ttbr_update_workaround here because the - * user and kernel ASIDs don't have conflicting mappings, so any - * "blessing" as described in: - * - * http://lkml.kernel.org/r/56BB848A.6060603@caviumnetworks.com - * - * will not hurt correctness. Whilst this may partially defeat the - * point of using split ASIDs in the first place, it avoids - * the hit of invalidating the entire I-cache on every return to - * userspace. + * We avoid running the post_ttbr_update_workaround here because + * it's only needed by Cavium ThunderX, which requires KPTI to be + * disabled. */ .endm From 79ddab3b05ca903f552fd5bf920efa055210322b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 29 Jan 2018 11:59:59 +0000 Subject: [PATCH 187/237] arm64: assembler: Align phys_to_pte with pte_to_phys pte_to_phys lives in assembler.h and takes its destination register as the first argument. Move phys_to_pte out of head.S to sit with its counterpart and rejig it to follow the same calling convention. Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/assembler.h | 13 +++++++++++++ arch/arm64/kernel/head.S | 24 ++---------------------- 2 files changed, 15 insertions(+), 22 deletions(-) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 47555f632ffd9f..544878a9f29e72 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -523,6 +523,19 @@ alternative_endif #endif .endm + .macro phys_to_pte, pte, phys +#ifdef CONFIG_ARM64_PA_BITS_52 + /* + * We assume \phys is 64K aligned and this is guaranteed by only + * supporting this configuration with 64K pages. + */ + orr \pte, \phys, \phys, lsr #36 + and \pte, \pte, #PTE_ADDR_MASK +#else + mov \pte, \phys +#endif + .endm + .macro pte_to_phys, phys, pte #ifdef CONFIG_ARM64_PA_BITS_52 ubfiz \phys, \pte, #(48 - 16 - 12), #16 diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 341649c08337d5..25f5b2e400fb3e 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -147,26 +147,6 @@ preserve_boot_args: b __inval_dcache_area // tail call ENDPROC(preserve_boot_args) -/* - * Macro to arrange a physical address in a page table entry, taking care of - * 52-bit addresses. - * - * Preserves: phys - * Returns: pte - */ - .macro phys_to_pte, phys, pte -#ifdef CONFIG_ARM64_PA_BITS_52 - /* - * We assume \phys is 64K aligned and this is guaranteed by only - * supporting this configuration with 64K pages. - */ - orr \pte, \phys, \phys, lsr #36 - and \pte, \pte, #PTE_ADDR_MASK -#else - mov \pte, \phys -#endif - .endm - /* * Macro to create a table entry to the next page. * @@ -181,7 +161,7 @@ ENDPROC(preserve_boot_args) */ .macro create_table_entry, tbl, virt, shift, ptrs, tmp1, tmp2 add \tmp1, \tbl, #PAGE_SIZE - phys_to_pte \tmp1, \tmp2 + phys_to_pte \tmp2, \tmp1 orr \tmp2, \tmp2, #PMD_TYPE_TABLE // address of next table and entry type lsr \tmp1, \virt, #\shift sub \ptrs, \ptrs, #1 @@ -207,7 +187,7 @@ ENDPROC(preserve_boot_args) * Returns: rtbl */ .macro populate_entries, tbl, rtbl, index, eindex, flags, inc, tmp1 -.Lpe\@: phys_to_pte \rtbl, \tmp1 +.Lpe\@: phys_to_pte \tmp1, \rtbl orr \tmp1, \tmp1, \flags // tmp1 = table entry str \tmp1, [\tbl, \index, lsl #3] add \rtbl, \rtbl, \inc // rtbl = pa next level From 439e70e27a51fe374806f460848066b237b0c10b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 29 Jan 2018 12:00:00 +0000 Subject: [PATCH 188/237] arm64: idmap: Use "awx" flags for .idmap.text .pushsection directives The identity map is mapped as both writeable and executable by the SWAPPER_MM_MMUFLAGS and this is relied upon by the kpti code to manage a synchronisation flag. Update the .pushsection flags to reflect the actual mapping attributes. Reported-by: Marc Zyngier Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/kernel/cpu-reset.S | 2 +- arch/arm64/kernel/head.S | 2 +- arch/arm64/kernel/sleep.S | 2 +- arch/arm64/mm/proc.S | 8 ++++---- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/arch/arm64/kernel/cpu-reset.S b/arch/arm64/kernel/cpu-reset.S index 2a752cb2a0f35a..8021b46c97431d 100644 --- a/arch/arm64/kernel/cpu-reset.S +++ b/arch/arm64/kernel/cpu-reset.S @@ -16,7 +16,7 @@ #include .text -.pushsection .idmap.text, "ax" +.pushsection .idmap.text, "awx" /* * __cpu_soft_restart(el2_switch, entry, arg0, arg1, arg2) - Helper for diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 25f5b2e400fb3e..2b6b8b24e5ab99 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -455,7 +455,7 @@ ENDPROC(__primary_switched) * end early head section, begin head code that is also used for * hotplug and needs to have the same protections as the text region */ - .section ".idmap.text","ax" + .section ".idmap.text","awx" ENTRY(kimage_vaddr) .quad _text - TEXT_OFFSET diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S index 10dd16d7902d28..bebec8ef9372af 100644 --- a/arch/arm64/kernel/sleep.S +++ b/arch/arm64/kernel/sleep.S @@ -96,7 +96,7 @@ ENTRY(__cpu_suspend_enter) ret ENDPROC(__cpu_suspend_enter) - .pushsection ".idmap.text", "ax" + .pushsection ".idmap.text", "awx" ENTRY(cpu_resume) bl el2_setup // if in EL2 drop to EL1 cleanly bl __cpu_setup diff --git a/arch/arm64/mm/proc.S b/arch/arm64/mm/proc.S index cfd22ba9b510e2..71baed7e592a49 100644 --- a/arch/arm64/mm/proc.S +++ b/arch/arm64/mm/proc.S @@ -90,7 +90,7 @@ ENDPROC(cpu_do_suspend) * * x0: Address of context pointer */ - .pushsection ".idmap.text", "ax" + .pushsection ".idmap.text", "awx" ENTRY(cpu_do_resume) ldp x2, x3, [x0] ldp x4, x5, [x0, #16] @@ -165,7 +165,7 @@ ENTRY(cpu_do_switch_mm) b post_ttbr_update_workaround // Back to C code... ENDPROC(cpu_do_switch_mm) - .pushsection ".idmap.text", "ax" + .pushsection ".idmap.text", "awx" .macro __idmap_cpu_set_reserved_ttbr1, tmp1, tmp2 adrp \tmp1, empty_zero_page @@ -199,7 +199,7 @@ ENDPROC(idmap_cpu_replace_ttbr1) .popsection #ifdef CONFIG_UNMAP_KERNEL_AT_EL0 - .pushsection ".idmap.text", "ax" + .pushsection ".idmap.text", "awx" .macro __idmap_kpti_get_pgtable_ent, type dc cvac, cur_\()\type\()p // Ensure any existing dirty @@ -388,7 +388,7 @@ ENDPROC(idmap_kpti_install_ng_mappings) * Initialise the processor for turning the MMU on. Return in x0 the * value of the SCTLR_EL1 register. */ - .pushsection ".idmap.text", "ax" + .pushsection ".idmap.text", "awx" ENTRY(__cpu_setup) tlbi vmalle1 // Invalidate local TLB dsb nsh From 669474e772b952b14f4de4845a1558fd4c0414a4 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 5 Feb 2018 15:34:16 +0000 Subject: [PATCH 189/237] arm64: barrier: Add CSDB macros to control data-value prediction For CPUs capable of data value prediction, CSDB waits for any outstanding predictions to architecturally resolve before allowing speculative execution to continue. Provide macros to expose it to the arch code. Reviewed-by: Mark Rutland Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/assembler.h | 7 +++++++ arch/arm64/include/asm/barrier.h | 1 + 2 files changed, 8 insertions(+) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 544878a9f29e72..1f44b4255a2877 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -115,6 +115,13 @@ hint #16 .endm +/* + * Value prediction barrier + */ + .macro csdb + hint #20 + .endm + /* * NOP sequence */ diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index 77651c49ef4419..c0a846d2c60223 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h @@ -32,6 +32,7 @@ #define dsb(opt) asm volatile("dsb " #opt : : : "memory") #define psb_csync() asm volatile("hint #17" : : : "memory") +#define csdb() asm volatile("hint #20" : : : "memory") #define mb() dsb(sy) #define rmb() dsb(ld) From 022620eed3d0bc4bf2027326f599f5ad71c2ea3f Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Mon, 5 Feb 2018 15:34:17 +0000 Subject: [PATCH 190/237] arm64: Implement array_index_mask_nospec() Provide an optimised, assembly implementation of array_index_mask_nospec() for arm64 so that the compiler is not in a position to transform the code in ways which affect its ability to inhibit speculation (e.g. by introducing conditional branches). This is similar to the sequence used by x86, modulo architectural differences in the carry/borrow flags. Reviewed-by: Mark Rutland Signed-off-by: Robin Murphy Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/barrier.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/arch/arm64/include/asm/barrier.h b/arch/arm64/include/asm/barrier.h index c0a846d2c60223..f11518af96a93a 100644 --- a/arch/arm64/include/asm/barrier.h +++ b/arch/arm64/include/asm/barrier.h @@ -41,6 +41,27 @@ #define dma_rmb() dmb(oshld) #define dma_wmb() dmb(oshst) +/* + * Generate a mask for array_index__nospec() that is ~0UL when 0 <= idx < sz + * and 0 otherwise. + */ +#define array_index_mask_nospec array_index_mask_nospec +static inline unsigned long array_index_mask_nospec(unsigned long idx, + unsigned long sz) +{ + unsigned long mask; + + asm volatile( + " cmp %1, %2\n" + " sbc %0, xzr, xzr\n" + : "=r" (mask) + : "r" (idx), "Ir" (sz) + : "cc"); + + csdb(); + return mask; +} + #define __smp_mb() dmb(ish) #define __smp_rmb() dmb(ishld) #define __smp_wmb() dmb(ishst) From 51369e398d0d33e8f524314e672b07e8cf870e79 Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Mon, 5 Feb 2018 15:34:18 +0000 Subject: [PATCH 191/237] arm64: Make USER_DS an inclusive limit Currently, USER_DS represents an exclusive limit while KERNEL_DS is inclusive. In order to do some clever trickery for speculation-safe masking, we need them both to behave equivalently - there aren't enough bits to make KERNEL_DS exclusive, so we have precisely one option. This also happens to correct a longstanding false negative for a range ending on the very top byte of kernel memory. Mark Rutland points out that we've actually got the semantics of addresses vs. segments muddled up in most of the places we need to amend, so shuffle the {USER,KERNEL}_DS definitions around such that we can correct those properly instead of just pasting "-1"s everywhere. Signed-off-by: Robin Murphy Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/processor.h | 3 ++ arch/arm64/include/asm/uaccess.h | 45 +++++++++++++++++------------- arch/arm64/kernel/entry.S | 4 +-- arch/arm64/mm/fault.c | 4 +-- 4 files changed, 33 insertions(+), 23 deletions(-) diff --git a/arch/arm64/include/asm/processor.h b/arch/arm64/include/asm/processor.h index cee4ae25a5d18a..dfefbf3fd9e3ff 100644 --- a/arch/arm64/include/asm/processor.h +++ b/arch/arm64/include/asm/processor.h @@ -21,6 +21,9 @@ #define TASK_SIZE_64 (UL(1) << VA_BITS) +#define KERNEL_DS UL(-1) +#define USER_DS (TASK_SIZE_64 - 1) + #ifndef __ASSEMBLY__ /* diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 59fda529293669..f2fc026cffb48c 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -35,10 +35,7 @@ #include #include -#define KERNEL_DS (-1UL) #define get_ds() (KERNEL_DS) - -#define USER_DS TASK_SIZE_64 #define get_fs() (current_thread_info()->addr_limit) static inline void set_fs(mm_segment_t fs) @@ -66,22 +63,32 @@ static inline void set_fs(mm_segment_t fs) * Returns 1 if the range is valid, 0 otherwise. * * This is equivalent to the following test: - * (u65)addr + (u65)size <= current->addr_limit - * - * This needs 65-bit arithmetic. + * (u65)addr + (u65)size <= (u65)current->addr_limit + 1 */ -#define __range_ok(addr, size) \ -({ \ - unsigned long __addr = (unsigned long)(addr); \ - unsigned long flag, roksum; \ - __chk_user_ptr(addr); \ - asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \ - : "=&r" (flag), "=&r" (roksum) \ - : "1" (__addr), "Ir" (size), \ - "r" (current_thread_info()->addr_limit) \ - : "cc"); \ - flag; \ -}) +static inline unsigned long __range_ok(unsigned long addr, unsigned long size) +{ + unsigned long limit = current_thread_info()->addr_limit; + + __chk_user_ptr(addr); + asm volatile( + // A + B <= C + 1 for all A,B,C, in four easy steps: + // 1: X = A + B; X' = X % 2^64 + " adds %0, %0, %2\n" + // 2: Set C = 0 if X > 2^64, to guarantee X' > C in step 4 + " csel %1, xzr, %1, hi\n" + // 3: Set X' = ~0 if X >= 2^64. For X == 2^64, this decrements X' + // to compensate for the carry flag being set in step 4. For + // X > 2^64, X' merely has to remain nonzero, which it does. + " csinv %0, %0, xzr, cc\n" + // 4: For X < 2^64, this gives us X' - C - 1 <= 0, where the -1 + // comes from the carry in being clear. Otherwise, we are + // testing X' - C == 0, subject to the previous adjustments. + " sbcs xzr, %0, %1\n" + " cset %0, ls\n" + : "+r" (addr), "+r" (limit) : "Ir" (size) : "cc"); + + return addr; +} /* * When dealing with data aborts, watchpoints, or instruction traps we may end @@ -90,7 +97,7 @@ static inline void set_fs(mm_segment_t fs) */ #define untagged_addr(addr) sign_extend64(addr, 55) -#define access_ok(type, addr, size) __range_ok(addr, size) +#define access_ok(type, addr, size) __range_ok((unsigned long)(addr), size) #define user_addr_max get_fs #define _ASM_EXTABLE(from, to) \ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 9b8635d9d7ae43..17c15f74178075 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -167,10 +167,10 @@ alternative_else_nop_endif .else add x21, sp, #S_FRAME_SIZE get_thread_info tsk - /* Save the task's original addr_limit and set USER_DS (TASK_SIZE_64) */ + /* Save the task's original addr_limit and set USER_DS */ ldr x20, [tsk, #TSK_TI_ADDR_LIMIT] str x20, [sp, #S_ORIG_ADDR_LIMIT] - mov x20, #TASK_SIZE_64 + mov x20, #USER_DS str x20, [tsk, #TSK_TI_ADDR_LIMIT] /* No need to reset PSTATE.UAO, hardware's already set it to 0 for us */ .endif /* \el == 0 */ diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 0e671ddf485562..af530eb9f2ed14 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -240,7 +240,7 @@ static inline bool is_permission_fault(unsigned int esr, struct pt_regs *regs, if (fsc_type == ESR_ELx_FSC_PERM) return true; - if (addr < USER_DS && system_uses_ttbr0_pan()) + if (addr < TASK_SIZE && system_uses_ttbr0_pan()) return fsc_type == ESR_ELx_FSC_FAULT && (regs->pstate & PSR_PAN_BIT); @@ -414,7 +414,7 @@ static int __kprobes do_page_fault(unsigned long addr, unsigned int esr, mm_flags |= FAULT_FLAG_WRITE; } - if (addr < USER_DS && is_permission_fault(esr, regs, addr)) { + if (addr < TASK_SIZE && is_permission_fault(esr, regs, addr)) { /* regs->orig_addr_limit may be 0 if we entered from EL0 */ if (regs->orig_addr_limit == KERNEL_DS) die("Accessing user space memory with fs=KERNEL_DS", regs, esr); From 4d8efc2d5ee4c9ccfeb29ee8afd47a8660d0c0ce Mon Sep 17 00:00:00 2001 From: Robin Murphy Date: Mon, 5 Feb 2018 15:34:19 +0000 Subject: [PATCH 192/237] arm64: Use pointer masking to limit uaccess speculation Similarly to x86, mitigate speculation past an access_ok() check by masking the pointer against the address limit before use. Even if we don't expect speculative writes per se, it is plausible that a CPU may still speculate at least as far as fetching a cache line for writing, hence we also harden put_user() and clear_user() for peace of mind. Signed-off-by: Robin Murphy Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/uaccess.h | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index f2fc026cffb48c..e49fe723d72d71 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -227,6 +227,26 @@ static inline void uaccess_enable_not_uao(void) __uaccess_enable(ARM64_ALT_PAN_NOT_UAO); } +/* + * Sanitise a uaccess pointer such that it becomes NULL if above the + * current addr_limit. + */ +#define uaccess_mask_ptr(ptr) (__typeof__(ptr))__uaccess_mask_ptr(ptr) +static inline void __user *__uaccess_mask_ptr(const void __user *ptr) +{ + void __user *safe_ptr; + + asm volatile( + " bics xzr, %1, %2\n" + " csel %0, %1, xzr, eq\n" + : "=&r" (safe_ptr) + : "r" (ptr), "r" (current_thread_info()->addr_limit) + : "cc"); + + csdb(); + return safe_ptr; +} + /* * The "__xxx" versions of the user access functions do not verify the address * space - it must have been done previously with a separate "access_ok()" @@ -297,7 +317,7 @@ do { \ __typeof__(*(ptr)) __user *__p = (ptr); \ might_fault(); \ access_ok(VERIFY_READ, __p, sizeof(*__p)) ? \ - __get_user((x), __p) : \ + __p = uaccess_mask_ptr(__p), __get_user((x), __p) : \ ((x) = 0, -EFAULT); \ }) @@ -361,7 +381,7 @@ do { \ __typeof__(*(ptr)) __user *__p = (ptr); \ might_fault(); \ access_ok(VERIFY_WRITE, __p, sizeof(*__p)) ? \ - __put_user((x), __p) : \ + __p = uaccess_mask_ptr(__p), __put_user((x), __p) : \ -EFAULT; \ }) @@ -377,7 +397,7 @@ extern unsigned long __must_check __clear_user(void __user *addr, unsigned long static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - n = __clear_user(to, n); + n = __clear_user(__uaccess_mask_ptr(to), n); return n; } From 6314d90e64936c584f300a52ef173603fb2461b5 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 5 Feb 2018 15:34:20 +0000 Subject: [PATCH 193/237] arm64: entry: Ensure branch through syscall table is bounded under speculation In a similar manner to array_index_mask_nospec, this patch introduces an assembly macro (mask_nospec64) which can be used to bound a value under speculation. This macro is then used to ensure that the indirect branch through the syscall table is bounded under speculation, with out-of-range addresses speculating as calls to sys_io_setup (0). Reviewed-by: Mark Rutland Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/assembler.h | 11 +++++++++++ arch/arm64/kernel/entry.S | 2 ++ 2 files changed, 13 insertions(+) diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h index 1f44b4255a2877..1241fb211293bd 100644 --- a/arch/arm64/include/asm/assembler.h +++ b/arch/arm64/include/asm/assembler.h @@ -122,6 +122,17 @@ hint #20 .endm +/* + * Sanitise a 64-bit bounded index wrt speculation, returning zero if out + * of bounds. + */ + .macro mask_nospec64, idx, limit, tmp + sub \tmp, \idx, \limit + bic \tmp, \tmp, \idx + and \idx, \idx, \tmp, asr #63 + csdb + .endm + /* * NOP sequence */ diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 17c15f74178075..4dd1b5a46642c9 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -378,6 +378,7 @@ alternative_insn eret, nop, ARM64_UNMAP_KERNEL_AT_EL0 * x7 is reserved for the system call number in 32-bit mode. */ wsc_nr .req w25 // number of system calls +xsc_nr .req x25 // number of system calls (zero-extended) wscno .req w26 // syscall number xscno .req x26 // syscall number (zero-extended) stbl .req x27 // syscall table pointer @@ -935,6 +936,7 @@ el0_svc_naked: // compat entry point b.ne __sys_trace cmp wscno, wsc_nr // check upper syscall limit b.hs ni_sys + mask_nospec64 xscno, xsc_nr, x19 // enforce bounds for syscall number ldr x16, [stbl, xscno, lsl #3] // address in the syscall table blr x16 // call sys_* routine b ret_fast_syscall From c2f0ad4fc089cff81cef6a13d04b399980ecbfcc Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 5 Feb 2018 15:34:21 +0000 Subject: [PATCH 194/237] arm64: uaccess: Prevent speculative use of the current addr_limit A mispredicted conditional call to set_fs could result in the wrong addr_limit being forwarded under speculation to a subsequent access_ok check, potentially forming part of a spectre-v1 attack using uaccess routines. This patch prevents this forwarding from taking place, but putting heavy barriers in set_fs after writing the addr_limit. Reviewed-by: Mark Rutland Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/uaccess.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index e49fe723d72d71..2057deed7697ab 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -42,6 +42,13 @@ static inline void set_fs(mm_segment_t fs) { current_thread_info()->addr_limit = fs; + /* + * Prevent a mispredicted conditional call to set_fs from forwarding + * the wrong address limit to access_ok under speculation. + */ + dsb(nsh); + isb(); + /* On user-mode return, check fs is correct */ set_thread_flag(TIF_FSCHECK); From 84624087dd7e3b482b7b11c170ebc1f329b3a218 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 5 Feb 2018 15:34:22 +0000 Subject: [PATCH 195/237] arm64: uaccess: Don't bother eliding access_ok checks in __{get, put}_user access_ok isn't an expensive operation once the addr_limit for the current thread has been loaded into the cache. Given that the initial access_ok check preceding a sequence of __{get,put}_user operations will take the brunt of the miss, we can make the __* variants identical to the full-fat versions, which brings with it the benefits of address masking. The likely cost in these sequences will be from toggling PAN/UAO, which we can address later by implementing the *_unsafe versions. Reviewed-by: Robin Murphy Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/uaccess.h | 54 +++++++++++++++++++------------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index 2057deed7697ab..e5002bc7130dbf 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -306,28 +306,33 @@ do { \ (x) = (__force __typeof__(*(ptr)))__gu_val; \ } while (0) -#define __get_user(x, ptr) \ +#define __get_user_check(x, ptr, err) \ ({ \ - int __gu_err = 0; \ - __get_user_err((x), (ptr), __gu_err); \ - __gu_err; \ + __typeof__(*(ptr)) __user *__p = (ptr); \ + might_fault(); \ + if (access_ok(VERIFY_READ, __p, sizeof(*__p))) { \ + __p = uaccess_mask_ptr(__p); \ + __get_user_err((x), __p, (err)); \ + } else { \ + (x) = 0; (err) = -EFAULT; \ + } \ }) #define __get_user_error(x, ptr, err) \ ({ \ - __get_user_err((x), (ptr), (err)); \ + __get_user_check((x), (ptr), (err)); \ (void)0; \ }) -#define get_user(x, ptr) \ +#define __get_user(x, ptr) \ ({ \ - __typeof__(*(ptr)) __user *__p = (ptr); \ - might_fault(); \ - access_ok(VERIFY_READ, __p, sizeof(*__p)) ? \ - __p = uaccess_mask_ptr(__p), __get_user((x), __p) : \ - ((x) = 0, -EFAULT); \ + int __gu_err = 0; \ + __get_user_check((x), (ptr), __gu_err); \ + __gu_err; \ }) +#define get_user __get_user + #define __put_user_asm(instr, alt_instr, reg, x, addr, err, feature) \ asm volatile( \ "1:"ALTERNATIVE(instr " " reg "1, [%2]\n", \ @@ -370,28 +375,33 @@ do { \ uaccess_disable_not_uao(); \ } while (0) -#define __put_user(x, ptr) \ +#define __put_user_check(x, ptr, err) \ ({ \ - int __pu_err = 0; \ - __put_user_err((x), (ptr), __pu_err); \ - __pu_err; \ + __typeof__(*(ptr)) __user *__p = (ptr); \ + might_fault(); \ + if (access_ok(VERIFY_WRITE, __p, sizeof(*__p))) { \ + __p = uaccess_mask_ptr(__p); \ + __put_user_err((x), __p, (err)); \ + } else { \ + (err) = -EFAULT; \ + } \ }) #define __put_user_error(x, ptr, err) \ ({ \ - __put_user_err((x), (ptr), (err)); \ + __put_user_check((x), (ptr), (err)); \ (void)0; \ }) -#define put_user(x, ptr) \ +#define __put_user(x, ptr) \ ({ \ - __typeof__(*(ptr)) __user *__p = (ptr); \ - might_fault(); \ - access_ok(VERIFY_WRITE, __p, sizeof(*__p)) ? \ - __p = uaccess_mask_ptr(__p), __put_user((x), __p) : \ - -EFAULT; \ + int __pu_err = 0; \ + __put_user_check((x), (ptr), __pu_err); \ + __pu_err; \ }) +#define put_user __put_user + extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n); #define raw_copy_from_user __arch_copy_from_user extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n); From f71c2ffcb20dd8626880747557014bb9a61eb90e Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 5 Feb 2018 15:34:23 +0000 Subject: [PATCH 196/237] arm64: uaccess: Mask __user pointers for __arch_{clear, copy_*}_user Like we've done for get_user and put_user, ensure that user pointers are masked before invoking the underlying __arch_{clear,copy_*}_user operations. Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/uaccess.h | 29 ++++++++++++++++++++++------- arch/arm64/kernel/arm64ksyms.c | 4 ++-- arch/arm64/lib/clear_user.S | 6 +++--- arch/arm64/lib/copy_in_user.S | 5 +++-- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index e5002bc7130dbf..543e11f0f657e9 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h @@ -403,20 +403,35 @@ do { \ #define put_user __put_user extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n); -#define raw_copy_from_user __arch_copy_from_user +#define raw_copy_from_user(to, from, n) \ +({ \ + __arch_copy_from_user((to), __uaccess_mask_ptr(from), (n)); \ +}) + extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n); -#define raw_copy_to_user __arch_copy_to_user -extern unsigned long __must_check raw_copy_in_user(void __user *to, const void __user *from, unsigned long n); -extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n); +#define raw_copy_to_user(to, from, n) \ +({ \ + __arch_copy_to_user(__uaccess_mask_ptr(to), (from), (n)); \ +}) + +extern unsigned long __must_check __arch_copy_in_user(void __user *to, const void __user *from, unsigned long n); +#define raw_copy_in_user(to, from, n) \ +({ \ + __arch_copy_in_user(__uaccess_mask_ptr(to), \ + __uaccess_mask_ptr(from), (n)); \ +}) + #define INLINE_COPY_TO_USER #define INLINE_COPY_FROM_USER -static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) +extern unsigned long __must_check __arch_clear_user(void __user *to, unsigned long n); +static inline unsigned long __must_check __clear_user(void __user *to, unsigned long n) { if (access_ok(VERIFY_WRITE, to, n)) - n = __clear_user(__uaccess_mask_ptr(to), n); + n = __arch_clear_user(__uaccess_mask_ptr(to), n); return n; } +#define clear_user __clear_user extern long strncpy_from_user(char *dest, const char __user *src, long count); @@ -430,7 +445,7 @@ extern unsigned long __must_check __copy_user_flushcache(void *to, const void __ static inline int __copy_from_user_flushcache(void *dst, const void __user *src, unsigned size) { kasan_check_write(dst, size); - return __copy_user_flushcache(dst, src, size); + return __copy_user_flushcache(dst, __uaccess_mask_ptr(src), size); } #endif diff --git a/arch/arm64/kernel/arm64ksyms.c b/arch/arm64/kernel/arm64ksyms.c index 67368c7329c03e..66be504edb6cf5 100644 --- a/arch/arm64/kernel/arm64ksyms.c +++ b/arch/arm64/kernel/arm64ksyms.c @@ -37,8 +37,8 @@ EXPORT_SYMBOL(clear_page); /* user mem (segment) */ EXPORT_SYMBOL(__arch_copy_from_user); EXPORT_SYMBOL(__arch_copy_to_user); -EXPORT_SYMBOL(__clear_user); -EXPORT_SYMBOL(raw_copy_in_user); +EXPORT_SYMBOL(__arch_clear_user); +EXPORT_SYMBOL(__arch_copy_in_user); /* physical memory */ EXPORT_SYMBOL(memstart_addr); diff --git a/arch/arm64/lib/clear_user.S b/arch/arm64/lib/clear_user.S index 3d69a8d41fa5e5..21ba0b29621b2f 100644 --- a/arch/arm64/lib/clear_user.S +++ b/arch/arm64/lib/clear_user.S @@ -21,7 +21,7 @@ .text -/* Prototype: int __clear_user(void *addr, size_t sz) +/* Prototype: int __arch_clear_user(void *addr, size_t sz) * Purpose : clear some user memory * Params : addr - user memory address to clear * : sz - number of bytes to clear @@ -29,7 +29,7 @@ * * Alignment fixed up by hardware. */ -ENTRY(__clear_user) +ENTRY(__arch_clear_user) uaccess_enable_not_uao x2, x3, x4 mov x2, x1 // save the size for fixup return subs x1, x1, #8 @@ -52,7 +52,7 @@ uao_user_alternative 9f, strb, sttrb, wzr, x0, 0 5: mov x0, #0 uaccess_disable_not_uao x2, x3 ret -ENDPROC(__clear_user) +ENDPROC(__arch_clear_user) .section .fixup,"ax" .align 2 diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S index fbb090f431a5c0..54b75deb1d1606 100644 --- a/arch/arm64/lib/copy_in_user.S +++ b/arch/arm64/lib/copy_in_user.S @@ -64,14 +64,15 @@ .endm end .req x5 -ENTRY(raw_copy_in_user) + +ENTRY(__arch_copy_in_user) uaccess_enable_not_uao x3, x4, x5 add end, x0, x2 #include "copy_template.S" uaccess_disable_not_uao x3, x4 mov x0, #0 ret -ENDPROC(raw_copy_in_user) +ENDPROC(__arch_copy_in_user) .section .fixup,"ax" .align 2 From 91b2d3442f6a44dce875670d702af22737ad5eff Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Mon, 5 Feb 2018 15:34:24 +0000 Subject: [PATCH 197/237] arm64: futex: Mask __user pointers prior to dereference The arm64 futex code has some explicit dereferencing of user pointers where performing atomic operations in response to a futex command. This patch uses masking to limit any speculative futex operations to within the user address space. Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/futex.h | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/arch/arm64/include/asm/futex.h b/arch/arm64/include/asm/futex.h index 5bb2fd4674e7c5..07fe2479d3105d 100644 --- a/arch/arm64/include/asm/futex.h +++ b/arch/arm64/include/asm/futex.h @@ -48,9 +48,10 @@ do { \ } while (0) static inline int -arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) +arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *_uaddr) { int oldval = 0, ret, tmp; + u32 __user *uaddr = __uaccess_mask_ptr(_uaddr); pagefault_disable(); @@ -88,15 +89,17 @@ arch_futex_atomic_op_inuser(int op, int oparg, int *oval, u32 __user *uaddr) } static inline int -futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, +futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *_uaddr, u32 oldval, u32 newval) { int ret = 0; u32 val, tmp; + u32 __user *uaddr; - if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))) + if (!access_ok(VERIFY_WRITE, _uaddr, sizeof(u32))) return -EFAULT; + uaddr = __uaccess_mask_ptr(_uaddr); uaccess_enable(); asm volatile("// futex_atomic_cmpxchg_inatomic\n" " prfm pstl1strm, %2\n" From 5dfc6ed27710c42cbc15db5c0d4475699991da0a Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 2 Feb 2018 17:31:39 +0000 Subject: [PATCH 198/237] arm64: entry: Apply BP hardening for high-priority synchronous exceptions Software-step and PC alignment fault exceptions have higher priority than instruction abort exceptions, so apply the BP hardening hooks there too if the user PC appears to reside in kernel space. Reported-by: Dan Hettena Reviewed-by: Marc Zyngier Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/kernel/entry.S | 5 ++++- arch/arm64/mm/fault.c | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 4dd1b5a46642c9..af22793103afdb 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -767,7 +767,10 @@ el0_sp_pc: * Stack or PC alignment exception handling */ mrs x26, far_el1 - enable_daif + enable_da_f +#ifdef CONFIG_TRACE_IRQFLAGS + bl trace_hardirqs_off +#endif ct_user_exit mov x0, x26 mov x1, x25 diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index af530eb9f2ed14..43b28a782ed467 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -732,6 +732,12 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr, struct siginfo info; struct task_struct *tsk = current; + if (user_mode(regs)) { + if (instruction_pointer(regs) > TASK_SIZE) + arm64_apply_bp_hardening(); + local_irq_enable(); + } + if (show_unhandled_signals && unhandled_signal(tsk, SIGBUS)) pr_info_ratelimited("%s[%d]: %s exception: pc=%p sp=%p\n", tsk->comm, task_pid_nr(tsk), @@ -791,6 +797,9 @@ asmlinkage int __exception do_debug_exception(unsigned long addr, if (interrupts_enabled(regs)) trace_hardirqs_off(); + if (user_mode(regs) && instruction_pointer(regs) > TASK_SIZE) + arm64_apply_bp_hardening(); + if (!inf->fn(addr, esr, regs)) { rv = 1; } else { From 30d88c0e3ace625a92eead9ca0ad94093a8f59fe Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 2 Feb 2018 17:31:40 +0000 Subject: [PATCH 199/237] arm64: entry: Apply BP hardening for suspicious interrupts from EL0 It is possible to take an IRQ from EL0 following a branch to a kernel address in such a way that the IRQ is prioritised over the instruction abort. Whilst an attacker would need to get the stars to align here, it might be sufficient with enough calibration so perform BP hardening in the rare case that we see a kernel address in the ELR when handling an IRQ from EL0. Reported-by: Dan Hettena Reviewed-by: Marc Zyngier Signed-off-by: Will Deacon Signed-off-by: Catalin Marinas --- arch/arm64/kernel/entry.S | 5 +++++ arch/arm64/mm/fault.c | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index af22793103afdb..25e022c3b6c444 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -828,6 +828,11 @@ el0_irq_naked: #endif ct_user_exit +#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR + tbz x22, #55, 1f + bl do_el0_irq_bp_hardening +1: +#endif irq_handler #ifdef CONFIG_TRACE_IRQFLAGS diff --git a/arch/arm64/mm/fault.c b/arch/arm64/mm/fault.c index 43b28a782ed467..8fd141233dec3f 100644 --- a/arch/arm64/mm/fault.c +++ b/arch/arm64/mm/fault.c @@ -708,6 +708,12 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr, arm64_notify_die("", regs, &info, esr); } +asmlinkage void __exception do_el0_irq_bp_hardening(void) +{ + /* PC has already been checked in entry.S */ + arm64_apply_bp_hardening(); +} + asmlinkage void __exception do_el0_ia_bp_hardening(unsigned long addr, unsigned int esr, struct pt_regs *regs) From c0938c72f8070aabb766b06edba85941ea7911da Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:05 +0000 Subject: [PATCH 200/237] arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls KVM doesn't follow the SMCCC when it comes to unimplemented calls, and inject an UNDEF instead of returning an error. Since firmware calls are now used for security mitigation, they are becoming more common, and the undef is counter productive. Instead, let's follow the SMCCC which states that -1 must be returned to the caller when getting an unknown function number. Signed-off-by: Marc Zyngier Signed-off-by: Christoffer Dall Signed-off-by: Catalin Marinas --- arch/arm64/kvm/handle_exit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index c09fc5a576c7df..520b0dad3c62bf 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -53,7 +53,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) ret = kvm_psci_call(vcpu); if (ret < 0) { - kvm_inject_undefined(vcpu); + vcpu_set_reg(vcpu, 0, ~0UL); return 1; } @@ -62,7 +62,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) { - kvm_inject_undefined(vcpu); + vcpu_set_reg(vcpu, 0, ~0UL); return 1; } From 20e8175d246e9f9deb377f2784b3e7dfb2ad3e86 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:06 +0000 Subject: [PATCH 201/237] arm: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls KVM doesn't follow the SMCCC when it comes to unimplemented calls, and inject an UNDEF instead of returning an error. Since firmware calls are now used for security mitigation, they are becoming more common, and the undef is counter productive. Instead, let's follow the SMCCC which states that -1 must be returned to the caller when getting an unknown function number. Cc: Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- arch/arm/kvm/handle_exit.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index cf8bf6bf87c4b8..a4bf0f6f024a4b 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c @@ -38,7 +38,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) ret = kvm_psci_call(vcpu); if (ret < 0) { - kvm_inject_undefined(vcpu); + vcpu_set_reg(vcpu, 0, ~0UL); return 1; } @@ -47,7 +47,16 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) { - kvm_inject_undefined(vcpu); + /* + * "If an SMC instruction executed at Non-secure EL1 is + * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a + * Trap exception, not a Secure Monitor Call exception [...]" + * + * We need to advance the PC after the trap, as it would + * otherwise return to the same address... + */ + vcpu_set_reg(vcpu, 0, ~0UL); + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); return 1; } From f5115e8869e1dfafac0e414b4f1664f3a84a4683 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:07 +0000 Subject: [PATCH 202/237] arm64: KVM: Increment PC after handling an SMC trap When handling an SMC trap, the "preferred return address" is set to that of the SMC, and not the next PC (which is a departure from the behaviour of an SMC that isn't trapped). Increment PC in the handler, as the guest is otherwise forever stuck... Cc: stable@vger.kernel.org Fixes: acfb3b883f6d ("arm64: KVM: Fix SMCCC handling of unimplemented SMC/HVC calls") Reviewed-by: Christoffer Dall Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- arch/arm64/kvm/handle_exit.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 520b0dad3c62bf..5493bbefbd0ded 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -62,7 +62,16 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run) { + /* + * "If an SMC instruction executed at Non-secure EL1 is + * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a + * Trap exception, not a Secure Monitor Call exception [...]" + * + * We need to advance the PC after the trap, as it would + * otherwise return to the same address... + */ vcpu_set_reg(vcpu, 0, ~0UL); + kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); return 1; } From 1a2fb94e6a771ff94f4afa22497a4695187b820c Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:08 +0000 Subject: [PATCH 203/237] arm/arm64: KVM: Consolidate the PSCI include files As we're about to update the PSCI support, and because I'm lazy, let's move the PSCI include file to include/kvm so that both ARM architectures can find it. Acked-by: Christoffer Dall Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- arch/arm/include/asm/kvm_psci.h | 27 ------------------- arch/arm/kvm/handle_exit.c | 2 +- arch/arm64/kvm/handle_exit.c | 3 ++- .../asm/kvm_psci.h => include/kvm/arm_psci.h | 6 ++--- virt/kvm/arm/arm.c | 2 +- virt/kvm/arm/psci.c | 3 ++- 6 files changed, 9 insertions(+), 34 deletions(-) delete mode 100644 arch/arm/include/asm/kvm_psci.h rename arch/arm64/include/asm/kvm_psci.h => include/kvm/arm_psci.h (89%) diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h deleted file mode 100644 index 6bda945d31fa8e..00000000000000 --- a/arch/arm/include/asm/kvm_psci.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2012 - ARM Ltd - * Author: Marc Zyngier - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef __ARM_KVM_PSCI_H__ -#define __ARM_KVM_PSCI_H__ - -#define KVM_ARM_PSCI_0_1 1 -#define KVM_ARM_PSCI_0_2 2 - -int kvm_psci_version(struct kvm_vcpu *vcpu); -int kvm_psci_call(struct kvm_vcpu *vcpu); - -#endif /* __ARM_KVM_PSCI_H__ */ diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index a4bf0f6f024a4b..230ae407910853 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #include #include "trace.h" diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 5493bbefbd0ded..588f910632a781 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -22,13 +22,14 @@ #include #include +#include + #include #include #include #include #include #include -#include #include #include diff --git a/arch/arm64/include/asm/kvm_psci.h b/include/kvm/arm_psci.h similarity index 89% rename from arch/arm64/include/asm/kvm_psci.h rename to include/kvm/arm_psci.h index bc39e557c56c83..2042bb909474a0 100644 --- a/arch/arm64/include/asm/kvm_psci.h +++ b/include/kvm/arm_psci.h @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -#ifndef __ARM64_KVM_PSCI_H__ -#define __ARM64_KVM_PSCI_H__ +#ifndef __KVM_ARM_PSCI_H__ +#define __KVM_ARM_PSCI_H__ #define KVM_ARM_PSCI_0_1 1 #define KVM_ARM_PSCI_0_2 2 @@ -24,4 +24,4 @@ int kvm_psci_version(struct kvm_vcpu *vcpu); int kvm_psci_call(struct kvm_vcpu *vcpu); -#endif /* __ARM64_KVM_PSCI_H__ */ +#endif /* __KVM_ARM_PSCI_H__ */ diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c index 15bf026eb18271..af3e98fc377ef5 100644 --- a/virt/kvm/arm/arm.c +++ b/virt/kvm/arm/arm.c @@ -31,6 +31,7 @@ #include #include #include +#include #define CREATE_TRACE_POINTS #include "trace.h" @@ -46,7 +47,6 @@ #include #include #include -#include #include #ifdef REQUIRES_VIRT diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index f1e363bab5e896..b322e46fd14212 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c @@ -21,9 +21,10 @@ #include #include -#include #include +#include + #include /* From d0a144f12a7ca8368933eae6583c096c363ec506 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:09 +0000 Subject: [PATCH 204/237] arm/arm64: KVM: Add PSCI_VERSION helper As we're about to trigger a PSCI version explosion, it doesn't hurt to introduce a PSCI_VERSION helper that is going to be used everywhere. Reviewed-by: Christoffer Dall Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- include/kvm/arm_psci.h | 6 ++++-- include/uapi/linux/psci.h | 3 +++ virt/kvm/arm/psci.c | 4 +--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h index 2042bb909474a0..5659343580a3e0 100644 --- a/include/kvm/arm_psci.h +++ b/include/kvm/arm_psci.h @@ -18,8 +18,10 @@ #ifndef __KVM_ARM_PSCI_H__ #define __KVM_ARM_PSCI_H__ -#define KVM_ARM_PSCI_0_1 1 -#define KVM_ARM_PSCI_0_2 2 +#include + +#define KVM_ARM_PSCI_0_1 PSCI_VERSION(0, 1) +#define KVM_ARM_PSCI_0_2 PSCI_VERSION(0, 2) int kvm_psci_version(struct kvm_vcpu *vcpu); int kvm_psci_call(struct kvm_vcpu *vcpu); diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h index 760e52a9640feb..b3bcabe380da8c 100644 --- a/include/uapi/linux/psci.h +++ b/include/uapi/linux/psci.h @@ -88,6 +88,9 @@ (((ver) & PSCI_VERSION_MAJOR_MASK) >> PSCI_VERSION_MAJOR_SHIFT) #define PSCI_VERSION_MINOR(ver) \ ((ver) & PSCI_VERSION_MINOR_MASK) +#define PSCI_VERSION(maj, min) \ + ((((maj) << PSCI_VERSION_MAJOR_SHIFT) & PSCI_VERSION_MAJOR_MASK) | \ + ((min) & PSCI_VERSION_MINOR_MASK)) /* PSCI features decoding (>=1.0) */ #define PSCI_1_0_FEATURES_CPU_SUSPEND_PF_SHIFT 1 diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index b322e46fd14212..999f94d6bb9824 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c @@ -25,8 +25,6 @@ #include -#include - /* * This is an implementation of the Power State Coordination Interface * as described in ARM document number ARM DEN 0022A. @@ -222,7 +220,7 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) * Bits[31:16] = Major Version = 0 * Bits[15:0] = Minor Version = 2 */ - val = 2; + val = KVM_ARM_PSCI_0_2; break; case PSCI_0_2_FN_CPU_SUSPEND: case PSCI_0_2_FN64_CPU_SUSPEND: From 84684fecd7ea381824a96634a027b7719587fb77 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:10 +0000 Subject: [PATCH 205/237] arm/arm64: KVM: Add smccc accessors to PSCI code Instead of open coding the accesses to the various registers, let's add explicit SMCCC accessors. Reviewed-by: Christoffer Dall Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- virt/kvm/arm/psci.c | 52 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 42 insertions(+), 10 deletions(-) diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index 999f94d6bb9824..c41553d3511038 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c @@ -32,6 +32,38 @@ #define AFFINITY_MASK(level) ~((0x1UL << ((level) * MPIDR_LEVEL_BITS)) - 1) +static u32 smccc_get_function(struct kvm_vcpu *vcpu) +{ + return vcpu_get_reg(vcpu, 0); +} + +static unsigned long smccc_get_arg1(struct kvm_vcpu *vcpu) +{ + return vcpu_get_reg(vcpu, 1); +} + +static unsigned long smccc_get_arg2(struct kvm_vcpu *vcpu) +{ + return vcpu_get_reg(vcpu, 2); +} + +static unsigned long smccc_get_arg3(struct kvm_vcpu *vcpu) +{ + return vcpu_get_reg(vcpu, 3); +} + +static void smccc_set_retval(struct kvm_vcpu *vcpu, + unsigned long a0, + unsigned long a1, + unsigned long a2, + unsigned long a3) +{ + vcpu_set_reg(vcpu, 0, a0); + vcpu_set_reg(vcpu, 1, a1); + vcpu_set_reg(vcpu, 2, a2); + vcpu_set_reg(vcpu, 3, a3); +} + static unsigned long psci_affinity_mask(unsigned long affinity_level) { if (affinity_level <= 3) @@ -77,7 +109,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) unsigned long context_id; phys_addr_t target_pc; - cpu_id = vcpu_get_reg(source_vcpu, 1) & MPIDR_HWID_BITMASK; + cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK; if (vcpu_mode_is_32bit(source_vcpu)) cpu_id &= ~((u32) 0); @@ -96,8 +128,8 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) return PSCI_RET_INVALID_PARAMS; } - target_pc = vcpu_get_reg(source_vcpu, 2); - context_id = vcpu_get_reg(source_vcpu, 3); + target_pc = smccc_get_arg2(source_vcpu); + context_id = smccc_get_arg3(source_vcpu); kvm_reset_vcpu(vcpu); @@ -116,7 +148,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) * NOTE: We always update r0 (or x0) because for PSCI v0.1 * the general puspose registers are undefined upon CPU_ON. */ - vcpu_set_reg(vcpu, 0, context_id); + smccc_set_retval(vcpu, context_id, 0, 0, 0); vcpu->arch.power_off = false; smp_mb(); /* Make sure the above is visible */ @@ -136,8 +168,8 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu) struct kvm *kvm = vcpu->kvm; struct kvm_vcpu *tmp; - target_affinity = vcpu_get_reg(vcpu, 1); - lowest_affinity_level = vcpu_get_reg(vcpu, 2); + target_affinity = smccc_get_arg1(vcpu); + lowest_affinity_level = smccc_get_arg2(vcpu); /* Determine target affinity mask */ target_affinity_mask = psci_affinity_mask(lowest_affinity_level); @@ -210,7 +242,7 @@ int kvm_psci_version(struct kvm_vcpu *vcpu) static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) { struct kvm *kvm = vcpu->kvm; - unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); + u32 psci_fn = smccc_get_function(vcpu); unsigned long val; int ret = 1; @@ -277,14 +309,14 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) break; } - vcpu_set_reg(vcpu, 0, val); + smccc_set_retval(vcpu, val, 0, 0, 0); return ret; } static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { struct kvm *kvm = vcpu->kvm; - unsigned long psci_fn = vcpu_get_reg(vcpu, 0) & ~((u32) 0); + u32 psci_fn = smccc_get_function(vcpu); unsigned long val; switch (psci_fn) { @@ -302,7 +334,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) break; } - vcpu_set_reg(vcpu, 0, val); + smccc_set_retval(vcpu, val, 0, 0, 0); return 1; } From 58e0b2239a4d997094ba63986ef4de29ddc91d87 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:11 +0000 Subject: [PATCH 206/237] arm/arm64: KVM: Implement PSCI 1.0 support PSCI 1.0 can be trivially implemented by providing the FEATURES call on top of PSCI 0.2 and returning 1.0 as the PSCI version. We happily ignore everything else, as they are either optional or are clarifications that do not require any additional change. PSCI 1.0 is now the default until we decide to add a userspace selection API. Reviewed-by: Christoffer Dall Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- include/kvm/arm_psci.h | 3 +++ virt/kvm/arm/psci.c | 45 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h index 5659343580a3e0..32360432cff507 100644 --- a/include/kvm/arm_psci.h +++ b/include/kvm/arm_psci.h @@ -22,6 +22,9 @@ #define KVM_ARM_PSCI_0_1 PSCI_VERSION(0, 1) #define KVM_ARM_PSCI_0_2 PSCI_VERSION(0, 2) +#define KVM_ARM_PSCI_1_0 PSCI_VERSION(1, 0) + +#define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_0 int kvm_psci_version(struct kvm_vcpu *vcpu); int kvm_psci_call(struct kvm_vcpu *vcpu); diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index c41553d3511038..3e7c63e15f04f0 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c @@ -234,7 +234,7 @@ static void kvm_psci_system_reset(struct kvm_vcpu *vcpu) int kvm_psci_version(struct kvm_vcpu *vcpu) { if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) - return KVM_ARM_PSCI_0_2; + return KVM_ARM_PSCI_LATEST; return KVM_ARM_PSCI_0_1; } @@ -313,6 +313,47 @@ static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) return ret; } +static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu) +{ + u32 psci_fn = smccc_get_function(vcpu); + u32 feature; + unsigned long val; + int ret = 1; + + switch(psci_fn) { + case PSCI_0_2_FN_PSCI_VERSION: + val = KVM_ARM_PSCI_1_0; + break; + case PSCI_1_0_FN_PSCI_FEATURES: + feature = smccc_get_arg1(vcpu); + switch(feature) { + case PSCI_0_2_FN_PSCI_VERSION: + case PSCI_0_2_FN_CPU_SUSPEND: + case PSCI_0_2_FN64_CPU_SUSPEND: + case PSCI_0_2_FN_CPU_OFF: + case PSCI_0_2_FN_CPU_ON: + case PSCI_0_2_FN64_CPU_ON: + case PSCI_0_2_FN_AFFINITY_INFO: + case PSCI_0_2_FN64_AFFINITY_INFO: + case PSCI_0_2_FN_MIGRATE_INFO_TYPE: + case PSCI_0_2_FN_SYSTEM_OFF: + case PSCI_0_2_FN_SYSTEM_RESET: + case PSCI_1_0_FN_PSCI_FEATURES: + val = 0; + break; + default: + val = PSCI_RET_NOT_SUPPORTED; + break; + } + break; + default: + return kvm_psci_0_2_call(vcpu); + } + + smccc_set_retval(vcpu, val, 0, 0, 0); + return ret; +} + static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) { struct kvm *kvm = vcpu->kvm; @@ -355,6 +396,8 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) int kvm_psci_call(struct kvm_vcpu *vcpu) { switch (kvm_psci_version(vcpu)) { + case KVM_ARM_PSCI_1_0: + return kvm_psci_1_0_call(vcpu); case KVM_ARM_PSCI_0_2: return kvm_psci_0_2_call(vcpu); case KVM_ARM_PSCI_0_1: From 09e6be12effdb33bf7210c8867bbd213b66a499e Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:12 +0000 Subject: [PATCH 207/237] arm/arm64: KVM: Advertise SMCCC v1.1 The new SMC Calling Convention (v1.1) allows for a reduced overhead when calling into the firmware, and provides a new feature discovery mechanism. Make it visible to KVM guests. Tested-by: Ard Biesheuvel Reviewed-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- arch/arm/kvm/handle_exit.c | 2 +- arch/arm64/kvm/handle_exit.c | 2 +- include/kvm/arm_psci.h | 2 +- include/linux/arm-smccc.h | 13 +++++++++++++ virt/kvm/arm/psci.c | 24 +++++++++++++++++++++++- 5 files changed, 39 insertions(+), 4 deletions(-) diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c index 230ae407910853..910bd8dabb3c03 100644 --- a/arch/arm/kvm/handle_exit.c +++ b/arch/arm/kvm/handle_exit.c @@ -36,7 +36,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) kvm_vcpu_hvc_get_imm(vcpu)); vcpu->stat.hvc_exit_stat++; - ret = kvm_psci_call(vcpu); + ret = kvm_hvc_call_handler(vcpu); if (ret < 0) { vcpu_set_reg(vcpu, 0, ~0UL); return 1; diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c index 588f910632a781..e5e741bfffe191 100644 --- a/arch/arm64/kvm/handle_exit.c +++ b/arch/arm64/kvm/handle_exit.c @@ -52,7 +52,7 @@ static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run) kvm_vcpu_hvc_get_imm(vcpu)); vcpu->stat.hvc_exit_stat++; - ret = kvm_psci_call(vcpu); + ret = kvm_hvc_call_handler(vcpu); if (ret < 0) { vcpu_set_reg(vcpu, 0, ~0UL); return 1; diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h index 32360432cff507..ed1dd8088f1cd7 100644 --- a/include/kvm/arm_psci.h +++ b/include/kvm/arm_psci.h @@ -27,6 +27,6 @@ #define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_0 int kvm_psci_version(struct kvm_vcpu *vcpu); -int kvm_psci_call(struct kvm_vcpu *vcpu); +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); #endif /* __KVM_ARM_PSCI_H__ */ diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index 4c5bca38c6533e..dc68aa5a7261c2 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -60,6 +60,19 @@ #define ARM_SMCCC_QUIRK_NONE 0 #define ARM_SMCCC_QUIRK_QCOM_A6 1 /* Save/restore register a6 */ +#define ARM_SMCCC_VERSION_1_0 0x10000 +#define ARM_SMCCC_VERSION_1_1 0x10001 + +#define ARM_SMCCC_VERSION_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0) + +#define ARM_SMCCC_ARCH_FEATURES_FUNC_ID \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 1) + #ifndef __ASSEMBLY__ #include diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index 3e7c63e15f04f0..46a98fee3ef50a 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #include #include @@ -339,6 +340,7 @@ static int kvm_psci_1_0_call(struct kvm_vcpu *vcpu) case PSCI_0_2_FN_SYSTEM_OFF: case PSCI_0_2_FN_SYSTEM_RESET: case PSCI_1_0_FN_PSCI_FEATURES: + case ARM_SMCCC_VERSION_FUNC_ID: val = 0; break; default: @@ -393,7 +395,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) * Errors: * -EINVAL: Unrecognized PSCI function */ -int kvm_psci_call(struct kvm_vcpu *vcpu) +static int kvm_psci_call(struct kvm_vcpu *vcpu) { switch (kvm_psci_version(vcpu)) { case KVM_ARM_PSCI_1_0: @@ -406,3 +408,23 @@ int kvm_psci_call(struct kvm_vcpu *vcpu) return -EINVAL; }; } + +int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) +{ + u32 func_id = smccc_get_function(vcpu); + u32 val = PSCI_RET_NOT_SUPPORTED; + + switch (func_id) { + case ARM_SMCCC_VERSION_FUNC_ID: + val = ARM_SMCCC_VERSION_1_1; + break; + case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: + /* Nothing supported yet */ + break; + default: + return kvm_psci_call(vcpu); + } + + smccc_set_retval(vcpu, val, 0, 0, 0); + return 1; +} From a4097b351118e821841941a79ec77d3ce3f1c5d9 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:13 +0000 Subject: [PATCH 208/237] arm/arm64: KVM: Turn kvm_psci_version into a static inline We're about to need kvm_psci_version in HYP too. So let's turn it into a static inline, and pass the kvm structure as a second parameter (so that HYP can do a kern_hyp_va on it). Tested-by: Ard Biesheuvel Reviewed-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- arch/arm64/kvm/hyp/switch.c | 20 ++++++++++++-------- include/kvm/arm_psci.h | 21 ++++++++++++++++++++- virt/kvm/arm/psci.c | 12 ++---------- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 036e1f3d77a6be..408c04d789a59e 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -19,6 +19,8 @@ #include #include +#include + #include #include #include @@ -350,14 +352,16 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) if (exit_code == ARM_EXCEPTION_TRAP && (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC64 || - kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC32) && - vcpu_get_reg(vcpu, 0) == PSCI_0_2_FN_PSCI_VERSION) { - u64 val = PSCI_RET_NOT_SUPPORTED; - if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) - val = 2; - - vcpu_set_reg(vcpu, 0, val); - goto again; + kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC32)) { + u32 val = vcpu_get_reg(vcpu, 0); + + if (val == PSCI_0_2_FN_PSCI_VERSION) { + val = kvm_psci_version(vcpu, kern_hyp_va(vcpu->kvm)); + if (unlikely(val == KVM_ARM_PSCI_0_1)) + val = PSCI_RET_NOT_SUPPORTED; + vcpu_set_reg(vcpu, 0, val); + goto again; + } } if (static_branch_unlikely(&vgic_v2_cpuif_trap) && diff --git a/include/kvm/arm_psci.h b/include/kvm/arm_psci.h index ed1dd8088f1cd7..e518e4e3dfb50a 100644 --- a/include/kvm/arm_psci.h +++ b/include/kvm/arm_psci.h @@ -18,6 +18,7 @@ #ifndef __KVM_ARM_PSCI_H__ #define __KVM_ARM_PSCI_H__ +#include #include #define KVM_ARM_PSCI_0_1 PSCI_VERSION(0, 1) @@ -26,7 +27,25 @@ #define KVM_ARM_PSCI_LATEST KVM_ARM_PSCI_1_0 -int kvm_psci_version(struct kvm_vcpu *vcpu); +/* + * We need the KVM pointer independently from the vcpu as we can call + * this from HYP, and need to apply kern_hyp_va on it... + */ +static inline int kvm_psci_version(struct kvm_vcpu *vcpu, struct kvm *kvm) +{ + /* + * Our PSCI implementation stays the same across versions from + * v0.2 onward, only adding the few mandatory functions (such + * as FEATURES with 1.0) that are required by newer + * revisions. It is thus safe to return the latest. + */ + if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) + return KVM_ARM_PSCI_LATEST; + + return KVM_ARM_PSCI_0_1; +} + + int kvm_hvc_call_handler(struct kvm_vcpu *vcpu); #endif /* __KVM_ARM_PSCI_H__ */ diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index 46a98fee3ef50a..e105c1153794b8 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c @@ -123,7 +123,7 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu) if (!vcpu) return PSCI_RET_INVALID_PARAMS; if (!vcpu->arch.power_off) { - if (kvm_psci_version(source_vcpu) != KVM_ARM_PSCI_0_1) + if (kvm_psci_version(source_vcpu, kvm) != KVM_ARM_PSCI_0_1) return PSCI_RET_ALREADY_ON; else return PSCI_RET_INVALID_PARAMS; @@ -232,14 +232,6 @@ static void kvm_psci_system_reset(struct kvm_vcpu *vcpu) kvm_prepare_system_event(vcpu, KVM_SYSTEM_EVENT_RESET); } -int kvm_psci_version(struct kvm_vcpu *vcpu) -{ - if (test_bit(KVM_ARM_VCPU_PSCI_0_2, vcpu->arch.features)) - return KVM_ARM_PSCI_LATEST; - - return KVM_ARM_PSCI_0_1; -} - static int kvm_psci_0_2_call(struct kvm_vcpu *vcpu) { struct kvm *kvm = vcpu->kvm; @@ -397,7 +389,7 @@ static int kvm_psci_0_1_call(struct kvm_vcpu *vcpu) */ static int kvm_psci_call(struct kvm_vcpu *vcpu) { - switch (kvm_psci_version(vcpu)) { + switch (kvm_psci_version(vcpu, vcpu->kvm)) { case KVM_ARM_PSCI_1_0: return kvm_psci_1_0_call(vcpu); case KVM_ARM_PSCI_0_2: From 6167ec5c9145cdf493722dfd80a5d48bafc4a18a Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:14 +0000 Subject: [PATCH 209/237] arm64: KVM: Report SMCCC_ARCH_WORKAROUND_1 BP hardening support A new feature of SMCCC 1.1 is that it offers firmware-based CPU workarounds. In particular, SMCCC_ARCH_WORKAROUND_1 provides BP hardening for CVE-2017-5715. If the host has some mitigation for this issue, report that we deal with it using SMCCC_ARCH_WORKAROUND_1, as we apply the host workaround on every guest exit. Tested-by: Ard Biesheuvel Reviewed-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- arch/arm/include/asm/kvm_host.h | 7 +++++++ arch/arm64/include/asm/kvm_host.h | 6 ++++++ include/linux/arm-smccc.h | 5 +++++ virt/kvm/arm/psci.c | 9 ++++++++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h index acbf9ec7b396e3..ef54013b5b9f1e 100644 --- a/arch/arm/include/asm/kvm_host.h +++ b/arch/arm/include/asm/kvm_host.h @@ -306,4 +306,11 @@ static inline void kvm_fpsimd_flush_cpu_state(void) {} static inline void kvm_arm_vhe_guest_enter(void) {} static inline void kvm_arm_vhe_guest_exit(void) {} + +static inline bool kvm_arm_harden_branch_predictor(void) +{ + /* No way to detect it yet, pretend it is not there. */ + return false; +} + #endif /* __ARM_KVM_HOST_H__ */ diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h index 4485ae8e98ded7..a73f63aca68e9e 100644 --- a/arch/arm64/include/asm/kvm_host.h +++ b/arch/arm64/include/asm/kvm_host.h @@ -415,4 +415,10 @@ static inline void kvm_arm_vhe_guest_exit(void) { local_daif_restore(DAIF_PROCCTX_NOIRQ); } + +static inline bool kvm_arm_harden_branch_predictor(void) +{ + return cpus_have_const_cap(ARM64_HARDEN_BRANCH_PREDICTOR); +} + #endif /* __ARM64_KVM_HOST_H__ */ diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index dc68aa5a7261c2..e1ef944ef1da9b 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -73,6 +73,11 @@ ARM_SMCCC_SMC_32, \ 0, 1) +#define ARM_SMCCC_ARCH_WORKAROUND_1 \ + ARM_SMCCC_CALL_VAL(ARM_SMCCC_FAST_CALL, \ + ARM_SMCCC_SMC_32, \ + 0, 0x8000) + #ifndef __ASSEMBLY__ #include diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c index e105c1153794b8..6919352cbf15e8 100644 --- a/virt/kvm/arm/psci.c +++ b/virt/kvm/arm/psci.c @@ -405,13 +405,20 @@ int kvm_hvc_call_handler(struct kvm_vcpu *vcpu) { u32 func_id = smccc_get_function(vcpu); u32 val = PSCI_RET_NOT_SUPPORTED; + u32 feature; switch (func_id) { case ARM_SMCCC_VERSION_FUNC_ID: val = ARM_SMCCC_VERSION_1_1; break; case ARM_SMCCC_ARCH_FEATURES_FUNC_ID: - /* Nothing supported yet */ + feature = smccc_get_arg1(vcpu); + switch(feature) { + case ARM_SMCCC_ARCH_WORKAROUND_1: + if (kvm_arm_harden_branch_predictor()) + val = 0; + break; + } break; default: return kvm_psci_call(vcpu); From f72af90c3783d924337624659b43e2d36f1b36b4 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:15 +0000 Subject: [PATCH 210/237] arm64: KVM: Add SMCCC_ARCH_WORKAROUND_1 fast handling We want SMCCC_ARCH_WORKAROUND_1 to be fast. As fast as possible. So let's intercept it as early as we can by testing for the function call number as soon as we've identified a HVC call coming from the guest. Tested-by: Ard Biesheuvel Reviewed-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- arch/arm64/kvm/hyp/hyp-entry.S | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index e4f37b9dd47c05..f36464bd57c5f2 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S @@ -15,6 +15,7 @@ * along with this program. If not, see . */ +#include #include #include @@ -64,10 +65,11 @@ alternative_endif lsr x0, x1, #ESR_ELx_EC_SHIFT cmp x0, #ESR_ELx_EC_HVC64 + ccmp x0, #ESR_ELx_EC_HVC32, #4, ne b.ne el1_trap - mrs x1, vttbr_el2 // If vttbr is valid, the 64bit guest - cbnz x1, el1_trap // called HVC + mrs x1, vttbr_el2 // If vttbr is valid, the guest + cbnz x1, el1_hvc_guest // called HVC /* Here, we're pretty sure the host called HVC. */ ldp x0, x1, [sp], #16 @@ -100,6 +102,20 @@ alternative_endif eret +el1_hvc_guest: + /* + * Fastest possible path for ARM_SMCCC_ARCH_WORKAROUND_1. + * The workaround has already been applied on the host, + * so let's quickly get back to the guest. We don't bother + * restoring x1, as it can be clobbered anyway. + */ + ldr x1, [sp] // Guest's x0 + eor w1, w1, #ARM_SMCCC_ARCH_WORKAROUND_1 + cbnz w1, el1_trap + mov x0, x1 + add sp, sp, #16 + eret + el1_trap: /* * x0: ESR_EC From 09a8d6d48499f93e2abde691f5800081cd858726 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:16 +0000 Subject: [PATCH 211/237] firmware/psci: Expose PSCI conduit In order to call into the firmware to apply workarounds, it is useful to find out whether we're using HVC or SMC. Let's expose this through the psci_ops. Acked-by: Lorenzo Pieralisi Reviewed-by: Robin Murphy Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- drivers/firmware/psci.c | 28 +++++++++++++++++++++++----- include/linux/psci.h | 7 +++++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index 8b25d31e84016b..e9493da2b111e6 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -59,7 +59,9 @@ bool psci_tos_resident_on(int cpu) return cpu == resident_cpu; } -struct psci_operations psci_ops; +struct psci_operations psci_ops = { + .conduit = PSCI_CONDUIT_NONE, +}; typedef unsigned long (psci_fn)(unsigned long, unsigned long, unsigned long, unsigned long); @@ -210,6 +212,22 @@ static unsigned long psci_migrate_info_up_cpu(void) 0, 0, 0); } +static void set_conduit(enum psci_conduit conduit) +{ + switch (conduit) { + case PSCI_CONDUIT_HVC: + invoke_psci_fn = __invoke_psci_fn_hvc; + break; + case PSCI_CONDUIT_SMC: + invoke_psci_fn = __invoke_psci_fn_smc; + break; + default: + WARN(1, "Unexpected PSCI conduit %d\n", conduit); + } + + psci_ops.conduit = conduit; +} + static int get_set_conduit_method(struct device_node *np) { const char *method; @@ -222,9 +240,9 @@ static int get_set_conduit_method(struct device_node *np) } if (!strcmp("hvc", method)) { - invoke_psci_fn = __invoke_psci_fn_hvc; + set_conduit(PSCI_CONDUIT_HVC); } else if (!strcmp("smc", method)) { - invoke_psci_fn = __invoke_psci_fn_smc; + set_conduit(PSCI_CONDUIT_SMC); } else { pr_warn("invalid \"method\" property: %s\n", method); return -EINVAL; @@ -654,9 +672,9 @@ int __init psci_acpi_init(void) pr_info("probing for conduit method from ACPI.\n"); if (acpi_psci_use_hvc()) - invoke_psci_fn = __invoke_psci_fn_hvc; + set_conduit(PSCI_CONDUIT_HVC); else - invoke_psci_fn = __invoke_psci_fn_smc; + set_conduit(PSCI_CONDUIT_SMC); return psci_probe(); } diff --git a/include/linux/psci.h b/include/linux/psci.h index f724fd8c78e826..f2679e5faa4fa7 100644 --- a/include/linux/psci.h +++ b/include/linux/psci.h @@ -25,6 +25,12 @@ bool psci_tos_resident_on(int cpu); int psci_cpu_init_idle(unsigned int cpu); int psci_cpu_suspend_enter(unsigned long index); +enum psci_conduit { + PSCI_CONDUIT_NONE, + PSCI_CONDUIT_SMC, + PSCI_CONDUIT_HVC, +}; + struct psci_operations { u32 (*get_version)(void); int (*cpu_suspend)(u32 state, unsigned long entry_point); @@ -34,6 +40,7 @@ struct psci_operations { int (*affinity_info)(unsigned long target_affinity, unsigned long lowest_affinity_level); int (*migrate_info_type)(void); + enum psci_conduit conduit; }; extern struct psci_operations psci_ops; From e78eef554a912ef6c1e0bbf97619dafbeae3339f Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:17 +0000 Subject: [PATCH 212/237] firmware/psci: Expose SMCCC version through psci_ops Since PSCI 1.0 allows the SMCCC version to be (indirectly) probed, let's do that at boot time, and expose the version of the calling convention as part of the psci_ops structure. Acked-by: Lorenzo Pieralisi Reviewed-by: Robin Murphy Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- drivers/firmware/psci.c | 27 +++++++++++++++++++++++++++ include/linux/psci.h | 6 ++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/firmware/psci.c b/drivers/firmware/psci.c index e9493da2b111e6..c80ec1d0327441 100644 --- a/drivers/firmware/psci.c +++ b/drivers/firmware/psci.c @@ -61,6 +61,7 @@ bool psci_tos_resident_on(int cpu) struct psci_operations psci_ops = { .conduit = PSCI_CONDUIT_NONE, + .smccc_version = SMCCC_VERSION_1_0, }; typedef unsigned long (psci_fn)(unsigned long, unsigned long, @@ -511,6 +512,31 @@ static void __init psci_init_migrate(void) pr_info("Trusted OS resident on physical CPU 0x%lx\n", cpuid); } +static void __init psci_init_smccc(void) +{ + u32 ver = ARM_SMCCC_VERSION_1_0; + int feature; + + feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID); + + if (feature != PSCI_RET_NOT_SUPPORTED) { + u32 ret; + ret = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0); + if (ret == ARM_SMCCC_VERSION_1_1) { + psci_ops.smccc_version = SMCCC_VERSION_1_1; + ver = ret; + } + } + + /* + * Conveniently, the SMCCC and PSCI versions are encoded the + * same way. No, this isn't accidental. + */ + pr_info("SMC Calling Convention v%d.%d\n", + PSCI_VERSION_MAJOR(ver), PSCI_VERSION_MINOR(ver)); + +} + static void __init psci_0_2_set_functions(void) { pr_info("Using standard PSCI v0.2 function IDs\n"); @@ -559,6 +585,7 @@ static int __init psci_probe(void) psci_init_migrate(); if (PSCI_VERSION_MAJOR(ver) >= 1) { + psci_init_smccc(); psci_init_cpu_suspend(); psci_init_system_suspend(); } diff --git a/include/linux/psci.h b/include/linux/psci.h index f2679e5faa4fa7..8b1b3b5935ab0f 100644 --- a/include/linux/psci.h +++ b/include/linux/psci.h @@ -31,6 +31,11 @@ enum psci_conduit { PSCI_CONDUIT_HVC, }; +enum smccc_version { + SMCCC_VERSION_1_0, + SMCCC_VERSION_1_1, +}; + struct psci_operations { u32 (*get_version)(void); int (*cpu_suspend)(u32 state, unsigned long entry_point); @@ -41,6 +46,7 @@ struct psci_operations { unsigned long lowest_affinity_level); int (*migrate_info_type)(void); enum psci_conduit conduit; + enum smccc_version smccc_version; }; extern struct psci_operations psci_ops; From ded4c39e93f3b72968fdb79baba27f3b83dad34c Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:18 +0000 Subject: [PATCH 213/237] arm/arm64: smccc: Make function identifiers an unsigned quantity Function identifiers are a 32bit, unsigned quantity. But we never tell so to the compiler, resulting in the following: 4ac: b26187e0 mov x0, #0xffffffff80000001 We thus rely on the firmware narrowing it for us, which is not always a reasonable expectation. Cc: stable@vger.kernel.org Reported-by: Ard Biesheuvel Acked-by: Ard Biesheuvel Reviewed-by: Robin Murphy Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- include/linux/arm-smccc.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index e1ef944ef1da9b..dd44d8458c04e4 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -14,14 +14,16 @@ #ifndef __LINUX_ARM_SMCCC_H #define __LINUX_ARM_SMCCC_H +#include + /* * This file provides common defines for ARM SMC Calling Convention as * specified in * http://infocenter.arm.com/help/topic/com.arm.doc.den0028a/index.html */ -#define ARM_SMCCC_STD_CALL 0 -#define ARM_SMCCC_FAST_CALL 1 +#define ARM_SMCCC_STD_CALL _AC(0,U) +#define ARM_SMCCC_FAST_CALL _AC(1,U) #define ARM_SMCCC_TYPE_SHIFT 31 #define ARM_SMCCC_SMC_32 0 From f2d3b2e8759a5833df6f022e42df2d581e6d843c Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:19 +0000 Subject: [PATCH 214/237] arm/arm64: smccc: Implement SMCCC v1.1 inline primitive One of the major improvement of SMCCC v1.1 is that it only clobbers the first 4 registers, both on 32 and 64bit. This means that it becomes very easy to provide an inline version of the SMC call primitive, and avoid performing a function call to stash the registers that would otherwise be clobbered by SMCCC v1.0. Reviewed-by: Robin Murphy Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- include/linux/arm-smccc.h | 141 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/include/linux/arm-smccc.h b/include/linux/arm-smccc.h index dd44d8458c04e4..a031897fca76b2 100644 --- a/include/linux/arm-smccc.h +++ b/include/linux/arm-smccc.h @@ -150,5 +150,146 @@ asmlinkage void __arm_smccc_hvc(unsigned long a0, unsigned long a1, #define arm_smccc_hvc_quirk(...) __arm_smccc_hvc(__VA_ARGS__) +/* SMCCC v1.1 implementation madness follows */ +#ifdef CONFIG_ARM64 + +#define SMCCC_SMC_INST "smc #0" +#define SMCCC_HVC_INST "hvc #0" + +#elif defined(CONFIG_ARM) +#include +#include + +#define SMCCC_SMC_INST __SMC(0) +#define SMCCC_HVC_INST __HVC(0) + +#endif + +#define ___count_args(_0, _1, _2, _3, _4, _5, _6, _7, _8, x, ...) x + +#define __count_args(...) \ + ___count_args(__VA_ARGS__, 7, 6, 5, 4, 3, 2, 1, 0) + +#define __constraint_write_0 \ + "+r" (r0), "=&r" (r1), "=&r" (r2), "=&r" (r3) +#define __constraint_write_1 \ + "+r" (r0), "+r" (r1), "=&r" (r2), "=&r" (r3) +#define __constraint_write_2 \ + "+r" (r0), "+r" (r1), "+r" (r2), "=&r" (r3) +#define __constraint_write_3 \ + "+r" (r0), "+r" (r1), "+r" (r2), "+r" (r3) +#define __constraint_write_4 __constraint_write_3 +#define __constraint_write_5 __constraint_write_4 +#define __constraint_write_6 __constraint_write_5 +#define __constraint_write_7 __constraint_write_6 + +#define __constraint_read_0 +#define __constraint_read_1 +#define __constraint_read_2 +#define __constraint_read_3 +#define __constraint_read_4 "r" (r4) +#define __constraint_read_5 __constraint_read_4, "r" (r5) +#define __constraint_read_6 __constraint_read_5, "r" (r6) +#define __constraint_read_7 __constraint_read_6, "r" (r7) + +#define __declare_arg_0(a0, res) \ + struct arm_smccc_res *___res = res; \ + register u32 r0 asm("r0") = a0; \ + register unsigned long r1 asm("r1"); \ + register unsigned long r2 asm("r2"); \ + register unsigned long r3 asm("r3") + +#define __declare_arg_1(a0, a1, res) \ + struct arm_smccc_res *___res = res; \ + register u32 r0 asm("r0") = a0; \ + register typeof(a1) r1 asm("r1") = a1; \ + register unsigned long r2 asm("r2"); \ + register unsigned long r3 asm("r3") + +#define __declare_arg_2(a0, a1, a2, res) \ + struct arm_smccc_res *___res = res; \ + register u32 r0 asm("r0") = a0; \ + register typeof(a1) r1 asm("r1") = a1; \ + register typeof(a2) r2 asm("r2") = a2; \ + register unsigned long r3 asm("r3") + +#define __declare_arg_3(a0, a1, a2, a3, res) \ + struct arm_smccc_res *___res = res; \ + register u32 r0 asm("r0") = a0; \ + register typeof(a1) r1 asm("r1") = a1; \ + register typeof(a2) r2 asm("r2") = a2; \ + register typeof(a3) r3 asm("r3") = a3 + +#define __declare_arg_4(a0, a1, a2, a3, a4, res) \ + __declare_arg_3(a0, a1, a2, a3, res); \ + register typeof(a4) r4 asm("r4") = a4 + +#define __declare_arg_5(a0, a1, a2, a3, a4, a5, res) \ + __declare_arg_4(a0, a1, a2, a3, a4, res); \ + register typeof(a5) r5 asm("r5") = a5 + +#define __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res) \ + __declare_arg_5(a0, a1, a2, a3, a4, a5, res); \ + register typeof(a6) r6 asm("r6") = a6 + +#define __declare_arg_7(a0, a1, a2, a3, a4, a5, a6, a7, res) \ + __declare_arg_6(a0, a1, a2, a3, a4, a5, a6, res); \ + register typeof(a7) r7 asm("r7") = a7 + +#define ___declare_args(count, ...) __declare_arg_ ## count(__VA_ARGS__) +#define __declare_args(count, ...) ___declare_args(count, __VA_ARGS__) + +#define ___constraints(count) \ + : __constraint_write_ ## count \ + : __constraint_read_ ## count \ + : "memory" +#define __constraints(count) ___constraints(count) + +/* + * We have an output list that is not necessarily used, and GCC feels + * entitled to optimise the whole sequence away. "volatile" is what + * makes it stick. + */ +#define __arm_smccc_1_1(inst, ...) \ + do { \ + __declare_args(__count_args(__VA_ARGS__), __VA_ARGS__); \ + asm volatile(inst "\n" \ + __constraints(__count_args(__VA_ARGS__))); \ + if (___res) \ + *___res = (typeof(*___res)){r0, r1, r2, r3}; \ + } while (0) + +/* + * arm_smccc_1_1_smc() - make an SMCCC v1.1 compliant SMC call + * + * This is a variadic macro taking one to eight source arguments, and + * an optional return structure. + * + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * + * This macro is used to make SMC calls following SMC Calling Convention v1.1. + * The content of the supplied param are copied to registers 0 to 7 prior + * to the SMC instruction. The return values are updated with the content + * from register 0 to 3 on return from the SMC instruction if not NULL. + */ +#define arm_smccc_1_1_smc(...) __arm_smccc_1_1(SMCCC_SMC_INST, __VA_ARGS__) + +/* + * arm_smccc_1_1_hvc() - make an SMCCC v1.1 compliant HVC call + * + * This is a variadic macro taking one to eight source arguments, and + * an optional return structure. + * + * @a0-a7: arguments passed in registers 0 to 7 + * @res: result values from registers 0 to 3 + * + * This macro is used to make HVC calls following SMC Calling Convention v1.1. + * The content of the supplied param are copied to registers 0 to 7 prior + * to the HVC instruction. The return values are updated with the content + * from register 0 to 3 on return from the HVC instruction if not NULL. + */ +#define arm_smccc_1_1_hvc(...) __arm_smccc_1_1(SMCCC_HVC_INST, __VA_ARGS__) + #endif /*__ASSEMBLY__*/ #endif /*__LINUX_ARM_SMCCC_H*/ From b092201e0020614127f495c092e0a12d26a2116e Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:20 +0000 Subject: [PATCH 215/237] arm64: Add ARM_SMCCC_ARCH_WORKAROUND_1 BP hardening support Add the detection and runtime code for ARM_SMCCC_ARCH_WORKAROUND_1. It is lovely. Really. Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- arch/arm64/kernel/bpi.S | 20 ++++++++++ arch/arm64/kernel/cpu_errata.c | 68 +++++++++++++++++++++++++++++++++- 2 files changed, 87 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S index 76225c2611eac5..fdeed629f2c6dd 100644 --- a/arch/arm64/kernel/bpi.S +++ b/arch/arm64/kernel/bpi.S @@ -17,6 +17,7 @@ */ #include +#include .macro ventry target .rept 31 @@ -85,3 +86,22 @@ ENTRY(__qcom_hyp_sanitize_link_stack_start) .endr ldp x29, x30, [sp], #16 ENTRY(__qcom_hyp_sanitize_link_stack_end) + +.macro smccc_workaround_1 inst + sub sp, sp, #(8 * 4) + stp x2, x3, [sp, #(8 * 0)] + stp x0, x1, [sp, #(8 * 2)] + mov w0, #ARM_SMCCC_ARCH_WORKAROUND_1 + \inst #0 + ldp x2, x3, [sp, #(8 * 0)] + ldp x0, x1, [sp, #(8 * 2)] + add sp, sp, #(8 * 4) +.endm + +ENTRY(__smccc_workaround_1_smc_start) + smccc_workaround_1 smc +ENTRY(__smccc_workaround_1_smc_end) + +ENTRY(__smccc_workaround_1_hvc_start) + smccc_workaround_1 hvc +ENTRY(__smccc_workaround_1_hvc_end) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index ed688188223175..9e77809a3b2307 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -70,6 +70,10 @@ DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[]; extern char __qcom_hyp_sanitize_link_stack_start[]; extern char __qcom_hyp_sanitize_link_stack_end[]; +extern char __smccc_workaround_1_smc_start[]; +extern char __smccc_workaround_1_smc_end[]; +extern char __smccc_workaround_1_hvc_start[]; +extern char __smccc_workaround_1_hvc_end[]; static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, const char *hyp_vecs_end) @@ -116,6 +120,10 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn, #define __psci_hyp_bp_inval_end NULL #define __qcom_hyp_sanitize_link_stack_start NULL #define __qcom_hyp_sanitize_link_stack_end NULL +#define __smccc_workaround_1_smc_start NULL +#define __smccc_workaround_1_smc_end NULL +#define __smccc_workaround_1_hvc_start NULL +#define __smccc_workaround_1_hvc_end NULL static void __install_bp_hardening_cb(bp_hardening_cb_t fn, const char *hyp_vecs_start, @@ -142,17 +150,75 @@ static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end); } +#include +#include #include +static void call_smc_arch_workaround_1(void) +{ + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); +} + +static void call_hvc_arch_workaround_1(void) +{ + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); +} + +static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) +{ + bp_hardening_cb_t cb; + void *smccc_start, *smccc_end; + struct arm_smccc_res res; + + if (!entry->matches(entry, SCOPE_LOCAL_CPU)) + return false; + + if (psci_ops.smccc_version == SMCCC_VERSION_1_0) + return false; + + switch (psci_ops.conduit) { + case PSCI_CONDUIT_HVC: + arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_1, &res); + if (res.a0) + return false; + cb = call_hvc_arch_workaround_1; + smccc_start = __smccc_workaround_1_hvc_start; + smccc_end = __smccc_workaround_1_hvc_end; + break; + + case PSCI_CONDUIT_SMC: + arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, + ARM_SMCCC_ARCH_WORKAROUND_1, &res); + if (res.a0) + return false; + cb = call_smc_arch_workaround_1; + smccc_start = __smccc_workaround_1_smc_start; + smccc_end = __smccc_workaround_1_smc_end; + break; + + default: + return false; + } + + install_bp_hardening_cb(entry, cb, smccc_start, smccc_end); + + return true; +} + static int enable_psci_bp_hardening(void *data) { const struct arm64_cpu_capabilities *entry = data; - if (psci_ops.get_version) + if (psci_ops.get_version) { + if (check_smccc_arch_workaround_1(entry)) + return 0; + install_bp_hardening_cb(entry, (bp_hardening_cb_t)psci_ops.get_version, __psci_hyp_bp_inval_start, __psci_hyp_bp_inval_end); + } return 0; } From 3a0a397ff5ff8b56ca9f7908b75dee6bf0b5fabb Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 6 Feb 2018 17:56:21 +0000 Subject: [PATCH 216/237] arm64: Kill PSCI_GET_VERSION as a variant-2 workaround Now that we've standardised on SMCCC v1.1 to perform the branch prediction invalidation, let's drop the previous band-aid. If vendors haven't updated their firmware to do SMCCC 1.1, they haven't updated PSCI either, so we don't loose anything. Tested-by: Ard Biesheuvel Signed-off-by: Marc Zyngier Signed-off-by: Catalin Marinas --- arch/arm64/kernel/bpi.S | 24 ------------------ arch/arm64/kernel/cpu_errata.c | 45 ++++++++++------------------------ arch/arm64/kvm/hyp/switch.c | 14 ----------- 3 files changed, 13 insertions(+), 70 deletions(-) diff --git a/arch/arm64/kernel/bpi.S b/arch/arm64/kernel/bpi.S index fdeed629f2c6dd..e5de33513b5d77 100644 --- a/arch/arm64/kernel/bpi.S +++ b/arch/arm64/kernel/bpi.S @@ -54,30 +54,6 @@ ENTRY(__bp_harden_hyp_vecs_start) vectors __kvm_hyp_vector .endr ENTRY(__bp_harden_hyp_vecs_end) -ENTRY(__psci_hyp_bp_inval_start) - sub sp, sp, #(8 * 18) - stp x16, x17, [sp, #(16 * 0)] - stp x14, x15, [sp, #(16 * 1)] - stp x12, x13, [sp, #(16 * 2)] - stp x10, x11, [sp, #(16 * 3)] - stp x8, x9, [sp, #(16 * 4)] - stp x6, x7, [sp, #(16 * 5)] - stp x4, x5, [sp, #(16 * 6)] - stp x2, x3, [sp, #(16 * 7)] - stp x0, x1, [sp, #(16 * 8)] - mov x0, #0x84000000 - smc #0 - ldp x16, x17, [sp, #(16 * 0)] - ldp x14, x15, [sp, #(16 * 1)] - ldp x12, x13, [sp, #(16 * 2)] - ldp x10, x11, [sp, #(16 * 3)] - ldp x8, x9, [sp, #(16 * 4)] - ldp x6, x7, [sp, #(16 * 5)] - ldp x4, x5, [sp, #(16 * 6)] - ldp x2, x3, [sp, #(16 * 7)] - ldp x0, x1, [sp, #(16 * 8)] - add sp, sp, #(8 * 18) -ENTRY(__psci_hyp_bp_inval_end) ENTRY(__qcom_hyp_sanitize_link_stack_start) stp x29, x30, [sp, #-16]! diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index 9e77809a3b2307..07823595b7f016 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -67,7 +67,6 @@ static int cpu_enable_trap_ctr_access(void *__unused) DEFINE_PER_CPU_READ_MOSTLY(struct bp_hardening_data, bp_hardening_data); #ifdef CONFIG_KVM -extern char __psci_hyp_bp_inval_start[], __psci_hyp_bp_inval_end[]; extern char __qcom_hyp_sanitize_link_stack_start[]; extern char __qcom_hyp_sanitize_link_stack_end[]; extern char __smccc_workaround_1_smc_start[]; @@ -116,8 +115,6 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn, spin_unlock(&bp_lock); } #else -#define __psci_hyp_bp_inval_start NULL -#define __psci_hyp_bp_inval_end NULL #define __qcom_hyp_sanitize_link_stack_start NULL #define __qcom_hyp_sanitize_link_stack_end NULL #define __smccc_workaround_1_smc_start NULL @@ -164,24 +161,25 @@ static void call_hvc_arch_workaround_1(void) arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_1, NULL); } -static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) +static int enable_smccc_arch_workaround_1(void *data) { + const struct arm64_cpu_capabilities *entry = data; bp_hardening_cb_t cb; void *smccc_start, *smccc_end; struct arm_smccc_res res; if (!entry->matches(entry, SCOPE_LOCAL_CPU)) - return false; + return 0; if (psci_ops.smccc_version == SMCCC_VERSION_1_0) - return false; + return 0; switch (psci_ops.conduit) { case PSCI_CONDUIT_HVC: arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_ARCH_WORKAROUND_1, &res); if (res.a0) - return false; + return 0; cb = call_hvc_arch_workaround_1; smccc_start = __smccc_workaround_1_hvc_start; smccc_end = __smccc_workaround_1_hvc_end; @@ -191,35 +189,18 @@ static bool check_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *e arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID, ARM_SMCCC_ARCH_WORKAROUND_1, &res); if (res.a0) - return false; + return 0; cb = call_smc_arch_workaround_1; smccc_start = __smccc_workaround_1_smc_start; smccc_end = __smccc_workaround_1_smc_end; break; default: - return false; + return 0; } install_bp_hardening_cb(entry, cb, smccc_start, smccc_end); - return true; -} - -static int enable_psci_bp_hardening(void *data) -{ - const struct arm64_cpu_capabilities *entry = data; - - if (psci_ops.get_version) { - if (check_smccc_arch_workaround_1(entry)) - return 0; - - install_bp_hardening_cb(entry, - (bp_hardening_cb_t)psci_ops.get_version, - __psci_hyp_bp_inval_start, - __psci_hyp_bp_inval_end); - } - return 0; } @@ -399,22 +380,22 @@ const struct arm64_cpu_capabilities arm64_errata[] = { { .capability = ARM64_HARDEN_BRANCH_PREDICTOR, MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), - .enable = enable_psci_bp_hardening, + .enable = enable_smccc_arch_workaround_1, }, { .capability = ARM64_HARDEN_BRANCH_PREDICTOR, MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), - .enable = enable_psci_bp_hardening, + .enable = enable_smccc_arch_workaround_1, }, { .capability = ARM64_HARDEN_BRANCH_PREDICTOR, MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), - .enable = enable_psci_bp_hardening, + .enable = enable_smccc_arch_workaround_1, }, { .capability = ARM64_HARDEN_BRANCH_PREDICTOR, MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), - .enable = enable_psci_bp_hardening, + .enable = enable_smccc_arch_workaround_1, }, { .capability = ARM64_HARDEN_BRANCH_PREDICTOR, @@ -428,12 +409,12 @@ const struct arm64_cpu_capabilities arm64_errata[] = { { .capability = ARM64_HARDEN_BRANCH_PREDICTOR, MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN), - .enable = enable_psci_bp_hardening, + .enable = enable_smccc_arch_workaround_1, }, { .capability = ARM64_HARDEN_BRANCH_PREDICTOR, MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), - .enable = enable_psci_bp_hardening, + .enable = enable_smccc_arch_workaround_1, }, #endif { diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 408c04d789a59e..cac6a05001624a 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c @@ -350,20 +350,6 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu) if (exit_code == ARM_EXCEPTION_TRAP && !__populate_fault_info(vcpu)) goto again; - if (exit_code == ARM_EXCEPTION_TRAP && - (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC64 || - kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_HVC32)) { - u32 val = vcpu_get_reg(vcpu, 0); - - if (val == PSCI_0_2_FN_PSCI_VERSION) { - val = kvm_psci_version(vcpu, kern_hyp_va(vcpu->kvm)); - if (unlikely(val == KVM_ARM_PSCI_0_1)) - val = PSCI_RET_NOT_SUPPORTED; - vcpu_set_reg(vcpu, 0, val); - goto again; - } - } - if (static_branch_unlikely(&vgic_v2_cpuif_trap) && exit_code == ARM_EXCEPTION_TRAP) { bool valid; From 890674343bb2d546825f713542b1e199f0728732 Mon Sep 17 00:00:00 2001 From: Shunyong Yang Date: Tue, 6 Feb 2018 14:37:12 +0800 Subject: [PATCH 217/237] ACPI / tables: Add IORT to injectable table list Loading IORT table from initrd can be used to fix severe firmware IORT defects temporarily before platform/BIOS vendor releases an upgraded BIOS binary. Moreover, it is very powerful to debug SMMU node/device probe, MSI allocation, stream id translation and IORT table from firmware. It is also very useful to enable SMMU and devices behind SMMU before firmware is ready. This patch adds ACPI_SIG_IORT to the table, which enables IORT from initrd to override which from firmware. Signed-off-by: Yang Shunyong Acked-by: Hanjun Guo Signed-off-by: Rafael J. Wysocki --- drivers/acpi/tables.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 80ce2a7d224b63..7bcb66ccccf3ee 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -456,7 +456,8 @@ static const char * const table_sigs[] = { ACPI_SIG_SLIC, ACPI_SIG_SPCR, ACPI_SIG_SPMI, ACPI_SIG_TCPA, ACPI_SIG_UEFI, ACPI_SIG_WAET, ACPI_SIG_WDAT, ACPI_SIG_WDDT, ACPI_SIG_WDRT, ACPI_SIG_DSDT, ACPI_SIG_FADT, ACPI_SIG_PSDT, - ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, NULL }; + ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, ACPI_SIG_IORT, + NULL }; #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) From b52f451105020677cad61a13b3b67af3fdedb91f Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 6 Feb 2018 17:36:17 -0600 Subject: [PATCH 218/237] ACPI / CPPC: Use 64-bit arithmetic instead of 32-bit Add suffix ULL to constant 500 in order to give the compiler complete information about the proper arithmetic to use. Notice that this constant is used in a context that expects an expression of type u64 (64 bits, unsigned). The expression NUM_RETRIES * cppc_ss->latency at line 578, which at preprocessing time translates to 500 * cppc_ss->latency is currently being evaluated using 32-bit arithmetic. Signed-off-by: Gustavo A. R. Silva Signed-off-by: Rafael J. Wysocki --- drivers/acpi/cppc_acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 06ea4749ebd982..0afbb2658cbc0d 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c @@ -119,7 +119,7 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr); * to PCC commands. Keeping it high enough to cover emulators where * the processors run painfully slow. */ -#define NUM_RETRIES 500 +#define NUM_RETRIES 500ULL struct cppc_attr { struct attribute attr; From 59a3b3a8db16621574cbac69f6f1eddb9c60e821 Mon Sep 17 00:00:00 2001 From: Akshu Agrawal Date: Thu, 18 Jan 2018 15:51:30 +0530 Subject: [PATCH 219/237] cpufreq: AMD: Ignore the check for ProcFeedback in ST/CZ In ST/CZ CPUID 8000_0007_EDX[11, ProcFeedbackInterface] is 0, but the mechanism is still available and can be used. Signed-off-by: Akshu Agrawal Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/amd_freq_sensitivity.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/amd_freq_sensitivity.c b/drivers/cpufreq/amd_freq_sensitivity.c index 042023bbbf6214..be926d9a66e574 100644 --- a/drivers/cpufreq/amd_freq_sensitivity.c +++ b/drivers/cpufreq/amd_freq_sensitivity.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -109,12 +110,18 @@ static unsigned int amd_powersave_bias_target(struct cpufreq_policy *policy, static int __init amd_freq_sensitivity_init(void) { u64 val; + struct pci_dev *pcidev; if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) return -ENODEV; - if (!static_cpu_has(X86_FEATURE_PROC_FEEDBACK)) - return -ENODEV; + pcidev = pci_get_device(PCI_VENDOR_ID_AMD, + PCI_DEVICE_ID_AMD_KERNCZ_SMBUS, NULL); + + if (!pcidev) { + if (!static_cpu_has(X86_FEATURE_PROC_FEEDBACK)) + return -ENODEV; + } if (rdmsrl_safe(MSR_AMD64_FREQ_SENSITIVITY_ACTUAL, &val)) return -ENODEV; From 0231d00082f61cfe03f2b7c27e5356f8cdf0312c Mon Sep 17 00:00:00 2001 From: Prarit Bhargava Date: Thu, 18 Jan 2018 10:09:51 -0500 Subject: [PATCH 220/237] ACPI: SPCR: Make SPCR available to x86 SPCR is currently only enabled or ARM64 and x86 can use SPCR to setup an early console. General fixes include updating Documentation & Kconfig (for x86), updating comments, and changing parse_spcr() to acpi_parse_spcr(), and earlycon_init_is_deferred to earlycon_acpi_spcr_enable to be more descriptive. On x86, many systems have a valid SPCR table but the table version is not 2 so the table version check must be a warning. On ARM64 when the kernel parameter earlycon is used both the early console and console are enabled. On x86, only the earlycon should be enabled by by default. Modify acpi_parse_spcr() to allow options for initializing the early console and console separately. Signed-off-by: Prarit Bhargava Acked-by: Ingo Molnar Reviewed-by: Mark Salter Tested-by: Mark Salter Signed-off-by: Rafael J. Wysocki --- .../admin-guide/kernel-parameters.txt | 9 ++++-- arch/arm64/kernel/acpi.c | 4 +-- arch/x86/kernel/acpi/boot.c | 3 ++ drivers/acpi/Kconfig | 7 ++++- drivers/acpi/spcr.c | 29 ++++++++++--------- drivers/tty/serial/earlycon.c | 15 ++++------ include/linux/acpi.h | 7 +++-- include/linux/serial_core.h | 4 +-- 8 files changed, 44 insertions(+), 34 deletions(-) diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt index 1bdcf572c2ac70..aecb1c8ef67523 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -917,9 +917,12 @@ earlycon= [KNL] Output early console device and options. - When used with no options, the early console is - determined by the stdout-path property in device - tree's chosen node. + [ARM64] The early console is determined by the + stdout-path property in device tree's chosen node, + or determined by the ACPI SPCR table. + + [X86] When used with no options the early console is + determined by the ACPI SPCR table. cdns,[,options] Start an early, polled-mode console on a Cadence diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c index b3162715ed78da..2aa5609def27a8 100644 --- a/arch/arm64/kernel/acpi.c +++ b/arch/arm64/kernel/acpi.c @@ -230,10 +230,10 @@ void __init acpi_boot_table_init(void) done: if (acpi_disabled) { - if (earlycon_init_is_deferred) + if (earlycon_acpi_spcr_enable) early_init_dt_scan_chosen_stdout(); } else { - parse_spcr(earlycon_init_is_deferred); + acpi_parse_spcr(earlycon_acpi_spcr_enable, true); if (IS_ENABLED(CONFIG_ACPI_BGRT)) acpi_table_parse(ACPI_SIG_BGRT, acpi_parse_bgrt); } diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index ec3a286163c37a..2aa92094b59d4f 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -1625,6 +1626,8 @@ int __init acpi_boot_init(void) if (!acpi_noirq) x86_init.pci.init = pci_acpi_init; + /* Do not enable ACPI SPCR console by default */ + acpi_parse_spcr(earlycon_acpi_spcr_enable, false); return 0; } diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 46505396869e61..ddcb5f40e8ee8f 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -79,7 +79,12 @@ config ACPI_DEBUGGER_USER endif config ACPI_SPCR_TABLE - bool + bool "ACPI Serial Port Console Redirection Support" + default y if X86 + help + Enable support for Serial Port Console Redirection (SPCR) Table. + This table provides information about the configuration of the + earlycon console. config ACPI_LPIT bool diff --git a/drivers/acpi/spcr.c b/drivers/acpi/spcr.c index 324b35bfe781d4..89e97d21a89ce2 100644 --- a/drivers/acpi/spcr.c +++ b/drivers/acpi/spcr.c @@ -21,7 +21,7 @@ * occasionally getting stuck as 1. To avoid the potential for a hang, check * TXFE == 0 instead of BUSY == 1. This may not be suitable for all UART * implementations, so only do so if an affected platform is detected in - * parse_spcr(). + * acpi_parse_spcr(). */ bool qdf2400_e44_present; EXPORT_SYMBOL(qdf2400_e44_present); @@ -74,19 +74,21 @@ static bool xgene_8250_erratum_present(struct acpi_table_spcr *tb) } /** - * parse_spcr() - parse ACPI SPCR table and add preferred console + * acpi_parse_spcr() - parse ACPI SPCR table and add preferred console * - * @earlycon: set up earlycon for the console specified by the table + * @enable_earlycon: set up earlycon for the console specified by the table + * @enable_console: setup the console specified by the table. * * For the architectures with support for ACPI, CONFIG_ACPI_SPCR_TABLE may be * defined to parse ACPI SPCR table. As a result of the parsing preferred - * console is registered and if @earlycon is true, earlycon is set up. + * console is registered and if @enable_earlycon is true, earlycon is set up. + * If @enable_console is true the system console is also configured. * * When CONFIG_ACPI_SPCR_TABLE is defined, this function should be called * from arch initialization code as soon as the DT/ACPI decision is made. * */ -int __init parse_spcr(bool earlycon) +int __init acpi_parse_spcr(bool enable_earlycon, bool enable_console) { static char opts[64]; struct acpi_table_spcr *table; @@ -105,11 +107,8 @@ int __init parse_spcr(bool earlycon) if (ACPI_FAILURE(status)) return -ENOENT; - if (table->header.revision < 2) { - err = -ENOENT; - pr_err("wrong table version\n"); - goto done; - } + if (table->header.revision < 2) + pr_info("SPCR table version %d\n", table->header.revision); if (table->serial_port.space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { switch (ACPI_ACCESS_BIT_WIDTH(( @@ -185,7 +184,7 @@ int __init parse_spcr(bool earlycon) */ if (qdf2400_erratum_44_present(&table->header)) { qdf2400_e44_present = true; - if (earlycon) + if (enable_earlycon) uart = "qdf2400_e44"; } @@ -205,11 +204,13 @@ int __init parse_spcr(bool earlycon) pr_info("console: %s\n", opts); - if (earlycon) + if (enable_earlycon) setup_earlycon(opts); - err = add_preferred_console(uart, 0, opts + strlen(uart) + 1); - + if (enable_console) + err = add_preferred_console(uart, 0, opts + strlen(uart) + 1); + else + err = 0; done: acpi_put_table((struct acpi_table_header *)table); return err; diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c index 4c8b80f1c688ca..870e84fb6e39eb 100644 --- a/drivers/tty/serial/earlycon.c +++ b/drivers/tty/serial/earlycon.c @@ -197,25 +197,20 @@ int __init setup_earlycon(char *buf) } /* - * When CONFIG_ACPI_SPCR_TABLE is defined, "earlycon" without parameters in - * command line does not start DT earlycon immediately, instead it defers - * starting it until DT/ACPI decision is made. At that time if ACPI is enabled - * call parse_spcr(), else call early_init_dt_scan_chosen_stdout() + * This defers the initialization of the early console until after ACPI has + * been initialized. */ -bool earlycon_init_is_deferred __initdata; +bool earlycon_acpi_spcr_enable __initdata; /* early_param wrapper for setup_earlycon() */ static int __init param_setup_earlycon(char *buf) { int err; - /* - * Just 'earlycon' is a valid param for devicetree earlycons; - * don't generate a warning from parse_early_params() in that case - */ + /* Just 'earlycon' is a valid param for devicetree and ACPI SPCR. */ if (!buf || !buf[0]) { if (IS_ENABLED(CONFIG_ACPI_SPCR_TABLE)) { - earlycon_init_is_deferred = true; + earlycon_acpi_spcr_enable = true; return 0; } else if (!buf) { return early_init_dt_scan_chosen_stdout(); diff --git a/include/linux/acpi.h b/include/linux/acpi.h index b8f4c3c776e5db..e6b98a32495f31 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1249,9 +1249,12 @@ static inline bool acpi_has_watchdog(void) { return false; } #ifdef CONFIG_ACPI_SPCR_TABLE extern bool qdf2400_e44_present; -int parse_spcr(bool earlycon); +int acpi_parse_spcr(bool enable_earlycon, bool enable_console); #else -static inline int parse_spcr(bool earlycon) { return 0; } +static inline int acpi_parse_spcr(bool enable_earlycon, bool enable_console) +{ + return 0; +} #endif #if IS_ENABLED(CONFIG_ACPI_GENERIC_GSI) diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 37b044e78333ab..aefd0e5115dae3 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -376,10 +376,10 @@ extern int of_setup_earlycon(const struct earlycon_id *match, const char *options); #ifdef CONFIG_SERIAL_EARLYCON -extern bool earlycon_init_is_deferred __initdata; +extern bool earlycon_acpi_spcr_enable __initdata; int setup_earlycon(char *buf); #else -static const bool earlycon_init_is_deferred; +static const bool earlycon_acpi_spcr_enable; static inline int setup_earlycon(char *buf) { return 0; } #endif From 3d70671667f15f4bae260541cd91330ef20d2f2e Mon Sep 17 00:00:00 2001 From: Corentin LABBE Date: Thu, 18 Jan 2018 21:02:02 +0100 Subject: [PATCH 221/237] cpufreq: remove at32ap-cpufreq Since AVR32 arch was removed, at32ap-cpufreq is useless. Remove this driver. Signed-off-by: Corentin Labbe Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/Kconfig | 10 --- drivers/cpufreq/Makefile | 1 - drivers/cpufreq/at32ap-cpufreq.c | 127 ------------------------------- 3 files changed, 138 deletions(-) delete mode 100644 drivers/cpufreq/at32ap-cpufreq.c diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index d8addbce40bcc4..608af20a34940d 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -239,16 +239,6 @@ if PPC32 || PPC64 source "drivers/cpufreq/Kconfig.powerpc" endif -if AVR32 -config AVR32_AT32AP_CPUFREQ - bool "CPU frequency driver for AT32AP" - depends on PLATFORM_AT32AP - default n - help - This enables the CPU frequency driver for AT32AP processors. - If in doubt, say N. -endif - if IA64 config IA64_ACPI_CPUFREQ tristate "ACPI Processor P-States driver" diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index e07715ce884406..c60c1e141d9d96 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -100,7 +100,6 @@ obj-$(CONFIG_POWERNV_CPUFREQ) += powernv-cpufreq.o ################################################################################## # Other platform drivers -obj-$(CONFIG_AVR32_AT32AP_CPUFREQ) += at32ap-cpufreq.o obj-$(CONFIG_BFIN_CPU_FREQ) += blackfin-cpufreq.o obj-$(CONFIG_BMIPS_CPUFREQ) += bmips-cpufreq.o obj-$(CONFIG_CRIS_MACH_ARTPEC3) += cris-artpec3-cpufreq.o diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c deleted file mode 100644 index 7b612c8bb09ea9..00000000000000 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright (C) 2004-2007 Atmel Corporation - * - * Based on MIPS implementation arch/mips/kernel/time.c - * Copyright 2001 MontaVista Software Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/*#define DEBUG*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static struct cpufreq_frequency_table *freq_table; - -static unsigned int ref_freq; -static unsigned long loops_per_jiffy_ref; - -static int at32_set_target(struct cpufreq_policy *policy, unsigned int index) -{ - unsigned int old_freq, new_freq; - - old_freq = policy->cur; - new_freq = freq_table[index].frequency; - - if (!ref_freq) { - ref_freq = old_freq; - loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy; - } - - if (old_freq < new_freq) - boot_cpu_data.loops_per_jiffy = cpufreq_scale( - loops_per_jiffy_ref, ref_freq, new_freq); - clk_set_rate(policy->clk, new_freq * 1000); - if (new_freq < old_freq) - boot_cpu_data.loops_per_jiffy = cpufreq_scale( - loops_per_jiffy_ref, ref_freq, new_freq); - - return 0; -} - -static int at32_cpufreq_driver_init(struct cpufreq_policy *policy) -{ - unsigned int frequency, rate, min_freq; - struct clk *cpuclk; - int retval, steps, i; - - if (policy->cpu != 0) - return -EINVAL; - - cpuclk = clk_get(NULL, "cpu"); - if (IS_ERR(cpuclk)) { - pr_debug("cpufreq: could not get CPU clk\n"); - retval = PTR_ERR(cpuclk); - goto out_err; - } - - min_freq = (clk_round_rate(cpuclk, 1) + 500) / 1000; - frequency = (clk_round_rate(cpuclk, ~0UL) + 500) / 1000; - policy->cpuinfo.transition_latency = 0; - - /* - * AVR32 CPU frequency rate scales in power of two between maximum and - * minimum, also add space for the table end marker. - * - * Further validate that the frequency is usable, and append it to the - * frequency table. - */ - steps = fls(frequency / min_freq) + 1; - freq_table = kzalloc(steps * sizeof(struct cpufreq_frequency_table), - GFP_KERNEL); - if (!freq_table) { - retval = -ENOMEM; - goto out_err_put_clk; - } - - for (i = 0; i < (steps - 1); i++) { - rate = clk_round_rate(cpuclk, frequency * 1000) / 1000; - - if (rate != frequency) - freq_table[i].frequency = CPUFREQ_ENTRY_INVALID; - else - freq_table[i].frequency = frequency; - - frequency /= 2; - } - - policy->clk = cpuclk; - freq_table[steps - 1].frequency = CPUFREQ_TABLE_END; - - retval = cpufreq_table_validate_and_show(policy, freq_table); - if (!retval) { - printk("cpufreq: AT32AP CPU frequency driver\n"); - return 0; - } - - kfree(freq_table); -out_err_put_clk: - clk_put(cpuclk); -out_err: - return retval; -} - -static struct cpufreq_driver at32_driver = { - .name = "at32ap", - .init = at32_cpufreq_driver_init, - .verify = cpufreq_generic_frequency_table_verify, - .target_index = at32_set_target, - .get = cpufreq_generic_get, - .flags = CPUFREQ_STICKY, -}; - -static int __init at32_cpufreq_init(void) -{ - return cpufreq_register_driver(&at32_driver); -} -late_initcall(at32_cpufreq_init); From eb85c50c24cf3e96f9aa01fd3e6219ad36845a96 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Mon, 22 Jan 2018 14:41:07 +0000 Subject: [PATCH 222/237] cpufreq: scpi: fix static checker warning cdev isn't an ERR_PTR Commit 343a8d17fa8d (cpufreq: scpi: remove arm_big_little dependency) leads to the following static checker warning: drivers/cpufreq/scpi-cpufreq.c:203 scpi_cpufreq_ready() warn: 'cdev' isn't an ERR_PTR of_cpufreq_cooling_register() returns NULL on error. This patch removes the incorrect IS_ERR check on the returned pointer. Fixes: 343a8d17fa8d (cpufreq: scpi: remove arm_big_little dependency) Reported-by: Dan Carpenter Signed-off-by: Sudeep Holla Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/scpi-cpufreq.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index 247fcbfa4cb5b6..efe32cbefa06be 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -197,11 +197,8 @@ static int scpi_cpufreq_exit(struct cpufreq_policy *policy) static void scpi_cpufreq_ready(struct cpufreq_policy *policy) { struct scpi_data *priv = policy->driver_data; - struct thermal_cooling_device *cdev; - cdev = of_cpufreq_cooling_register(policy); - if (!IS_ERR(cdev)) - priv->cdev = cdev; + priv->cdev = of_cpufreq_cooling_register(policy); } static struct cpufreq_driver scpi_cpufreq_driver = { From a3381e3a65cbaf612c8f584906c4dba27e84267c Mon Sep 17 00:00:00 2001 From: Ulf Hansson Date: Tue, 23 Jan 2018 21:43:08 +0100 Subject: [PATCH 223/237] PM / domains: Fix up domain-idle-states OF parsing Commit b539cc82d493 (PM / Domains: Ignore domain-idle-states that are not compatible), made it possible to ignore non-compatible domain-idle-states OF nodes. However, in case that happens while doing the OF parsing, the number of elements in the allocated array would exceed the numbers actually needed, thus wasting memory. Fix this by pre-iterating the genpd OF node and counting the number of compatible domain-idle-states nodes, before doing the allocation. While doing this, it makes sense to rework the code a bit to avoid open coding, of parts responsible for the OF node iteration. Let's also take the opportunity to clarify the function header for of_genpd_parse_idle_states(), about what is being returned in case of errors. Fixes: b539cc82d493 (PM / Domains: Ignore domain-idle-states that are not compatible) Signed-off-by: Ulf Hansson Reviewed-by: Lina Iyer Signed-off-by: Rafael J. Wysocki --- drivers/base/power/domain.c | 76 ++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 528b24149bc708..1ea0e2502e8ed4 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -2290,6 +2290,38 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state, return 0; } +static int genpd_iterate_idle_states(struct device_node *dn, + struct genpd_power_state *states) +{ + int ret; + struct of_phandle_iterator it; + struct device_node *np; + int i = 0; + + ret = of_count_phandle_with_args(dn, "domain-idle-states", NULL); + if (ret <= 0) + return ret; + + /* Loop over the phandles until all the requested entry is found */ + of_for_each_phandle(&it, ret, dn, "domain-idle-states", NULL, 0) { + np = it.node; + if (!of_match_node(idle_state_match, np)) + continue; + if (states) { + ret = genpd_parse_state(&states[i], np); + if (ret) { + pr_err("Parsing idle state node %pOF failed with err %d\n", + np, ret); + of_node_put(np); + return ret; + } + } + i++; + } + + return i; +} + /** * of_genpd_parse_idle_states: Return array of idle states for the genpd. * @@ -2299,49 +2331,31 @@ static int genpd_parse_state(struct genpd_power_state *genpd_state, * * Returns the device states parsed from the OF node. The memory for the states * is allocated by this function and is the responsibility of the caller to - * free the memory after use. + * free the memory after use. If no domain idle states is found it returns + * -EINVAL and in case of errors, a negative error code. */ int of_genpd_parse_idle_states(struct device_node *dn, struct genpd_power_state **states, int *n) { struct genpd_power_state *st; - struct device_node *np; - int i = 0; - int err, ret; - int count; - struct of_phandle_iterator it; - const struct of_device_id *match_id; + int ret; - count = of_count_phandle_with_args(dn, "domain-idle-states", NULL); - if (count <= 0) - return -EINVAL; + ret = genpd_iterate_idle_states(dn, NULL); + if (ret <= 0) + return ret < 0 ? ret : -EINVAL; - st = kcalloc(count, sizeof(*st), GFP_KERNEL); + st = kcalloc(ret, sizeof(*st), GFP_KERNEL); if (!st) return -ENOMEM; - /* Loop over the phandles until all the requested entry is found */ - of_for_each_phandle(&it, err, dn, "domain-idle-states", NULL, 0) { - np = it.node; - match_id = of_match_node(idle_state_match, np); - if (!match_id) - continue; - ret = genpd_parse_state(&st[i++], np); - if (ret) { - pr_err - ("Parsing idle state node %pOF failed with err %d\n", - np, ret); - of_node_put(np); - kfree(st); - return ret; - } + ret = genpd_iterate_idle_states(dn, st); + if (ret <= 0) { + kfree(st); + return ret < 0 ? ret : -EINVAL; } - *n = i; - if (!i) - kfree(st); - else - *states = st; + *states = st; + *n = ret; return 0; } From 168b6511e8e09de45bed272aaf76ef4d4ca3c05d Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 2 Feb 2018 15:56:18 +0100 Subject: [PATCH 224/237] x86: hibernate: fix swsusp_arch_resume() prototype The declaration for swsusp_arch_resume() marks it as 'asmlinkage', but the definition in x86-32 does not, and it fails to include the header with the declaration. This leads to a warning when building with link-time-optimizations: kernel/power/power.h:108:23: error: type of 'swsusp_arch_resume' does not match original declaration [-Werror=lto-type-mismatch] extern asmlinkage int swsusp_arch_resume(void); ^ arch/x86/power/hibernate_32.c:148:0: note: 'swsusp_arch_resume' was previously declared here int swsusp_arch_resume(void) This moves the declaration into a globally visible header file and fixes up both x86 definitions to match it. Signed-off-by: Arnd Bergmann Signed-off-by: Rafael J. Wysocki --- arch/x86/power/hibernate_32.c | 2 +- arch/x86/power/hibernate_64.c | 2 +- include/linux/suspend.h | 2 ++ kernel/power/power.h | 3 --- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/x86/power/hibernate_32.c b/arch/x86/power/hibernate_32.c index c35fdb585c6853..afc4ed7b157826 100644 --- a/arch/x86/power/hibernate_32.c +++ b/arch/x86/power/hibernate_32.c @@ -145,7 +145,7 @@ static inline void resume_init_first_level_page_table(pgd_t *pg_dir) #endif } -int swsusp_arch_resume(void) +asmlinkage int swsusp_arch_resume(void) { int error; diff --git a/arch/x86/power/hibernate_64.c b/arch/x86/power/hibernate_64.c index f910c514438f16..0ef5e520496891 100644 --- a/arch/x86/power/hibernate_64.c +++ b/arch/x86/power/hibernate_64.c @@ -174,7 +174,7 @@ static int relocate_restore_code(void) return 0; } -int swsusp_arch_resume(void) +asmlinkage int swsusp_arch_resume(void) { int error; diff --git a/include/linux/suspend.h b/include/linux/suspend.h index cc22a24516d699..440b62f7502ebe 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -384,6 +384,8 @@ extern int swsusp_page_is_forbidden(struct page *); extern void swsusp_set_page_free(struct page *); extern void swsusp_unset_page_free(struct page *); extern unsigned long get_safe_page(gfp_t gfp_mask); +extern asmlinkage int swsusp_arch_suspend(void); +extern asmlinkage int swsusp_arch_resume(void); extern void hibernation_set_ops(const struct platform_hibernation_ops *ops); extern int hibernate(void); diff --git a/kernel/power/power.h b/kernel/power/power.h index f29cd178df90a1..9e58bdc8a562b9 100644 --- a/kernel/power/power.h +++ b/kernel/power/power.h @@ -104,9 +104,6 @@ extern int in_suspend; extern dev_t swsusp_resume_device; extern sector_t swsusp_resume_block; -extern asmlinkage int swsusp_arch_suspend(void); -extern asmlinkage int swsusp_arch_resume(void); - extern int create_basic_memory_bitmaps(void); extern void free_basic_memory_bitmaps(void); extern int hibernate_preallocate_memory(void); From 6dd3104e78943685d5183efe883d83a5f2361bf1 Mon Sep 17 00:00:00 2001 From: Jani Nikula Date: Thu, 18 Jan 2018 17:33:10 +0200 Subject: [PATCH 225/237] drm/i915/bios: add DP max link rate to VBT child device struct Update VBT defs to reflect revision 216. While at it, default the expected child device struct size to sizeof the size rather than a hardcoded value. v2: Fix bit order (David) Cc: Rodrigo Vivi Signed-off-by: Jani Nikula Reviewed-by: Rodrigo Vivi Signed-off-by: Rodrigo Vivi Link: https://patchwork.freedesktop.org/patch/msgid/20180118153310.32437-1-jani.nikula@intel.com (cherry picked from commit c4fb60b9aba9f939d3f8575df23fd8d5958ec6ed) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_bios.c | 8 +++++--- drivers/gpu/drm/i915/intel_vbt_defs.h | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c index 4c42cc4b193b87..f7f771749e4809 100644 --- a/drivers/gpu/drm/i915/intel_bios.c +++ b/drivers/gpu/drm/i915/intel_bios.c @@ -1329,11 +1329,13 @@ parse_general_definitions(struct drm_i915_private *dev_priv, expected_size = LEGACY_CHILD_DEVICE_CONFIG_SIZE; } else if (bdb->version == 195) { expected_size = 37; - } else if (bdb->version <= 197) { + } else if (bdb->version <= 215) { expected_size = 38; + } else if (bdb->version <= 216) { + expected_size = 39; } else { - expected_size = 38; - BUILD_BUG_ON(sizeof(*child) < 38); + expected_size = sizeof(*child); + BUILD_BUG_ON(sizeof(*child) < 39); DRM_DEBUG_DRIVER("Expected child device config size for VBT version %u not known; assuming %u\n", bdb->version, expected_size); } diff --git a/drivers/gpu/drm/i915/intel_vbt_defs.h b/drivers/gpu/drm/i915/intel_vbt_defs.h index e3d7745a91518a..98dff6058d3c92 100644 --- a/drivers/gpu/drm/i915/intel_vbt_defs.h +++ b/drivers/gpu/drm/i915/intel_vbt_defs.h @@ -412,6 +412,8 @@ struct child_device_config { u16 dp_gpio_pin_num; /* 195 */ u8 dp_iboost_level:4; /* 196 */ u8 hdmi_iboost_level:4; /* 196 */ + u8 dp_max_link_rate:2; /* 216 CNL+ */ + u8 dp_max_link_rate_reserved:6; /* 216 */ } __packed; struct bdb_general_definitions { From 43cdd1b716b26f6af16da4e145b6578f98798bf6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 19 Jan 2018 10:06:03 +0100 Subject: [PATCH 226/237] ACPI: sbshc: remove raw pointer from printk() message There's no need to be printing a raw kernel pointer to the kernel log at every boot. So just remove it, and change the whole message to use the correct dev_info() call at the same time. Reported-by: Wang Qize Cc: All applicable Signed-off-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sbshc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index 2fa8304171e09b..7a3431018e0ab4 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c @@ -275,8 +275,8 @@ static int acpi_smbus_hc_add(struct acpi_device *device) device->driver_data = hc; acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc); - printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n", - hc->ec, hc->offset, hc->query_bit); + dev_info(&device->dev, "SBS HC: offset = 0x%0x, query_bit = 0x%0x\n", + hc->offset, hc->query_bit); return 0; } From 0725390da9fb5add90a6ee5d5bbe58b5f47b25ac Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 23 Jan 2018 02:09:02 +0000 Subject: [PATCH 227/237] cpufreq: scpi: fix error return code in scpi_cpufreq_init() Fix to return a negative error code from the clk_get() error handling case instead of 0, as done elsewhere in this function. Fixes: 343a8d17fa8d (cpufreq: scpi: remove arm_big_little dependency) Signed-off-by: Wei Yongjun Acked-by: Viresh Kumar Acked-by: Sudeep Holla Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/scpi-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index efe32cbefa06be..c32a833e1b0054 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -145,6 +145,7 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy) if (IS_ERR(priv->clk)) { dev_err(cpu_dev, "%s: Failed to get clk for cpu: %d\n", __func__, cpu_dev->id); + ret = PTR_ERR(priv->clk); goto out_free_cpufreq_table; } From 70f6bf2a3b7e40c3f802b0ea837762a8bc6c1430 Mon Sep 17 00:00:00 2001 From: Chen Yu Date: Mon, 29 Jan 2018 10:27:57 +0800 Subject: [PATCH 228/237] cpufreq: intel_pstate: Enable HWP during system resume on CPU0 When maxcpus=1 is in the kernel command line, the BP is responsible for re-enabling the HWP - because currently only the APs invoke intel_pstate_hwp_enable() during their online process - which might put the system into unstable state after resume. Fix this by enabling the HWP explicitly on BP during resume. Reported-by: Doug Smythies Suggested-by: Srinivas Pandruvada Signed-off-by: Yu Chen [ rjw: Subject/changelog, minor modifications ] Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/intel_pstate.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 7edf7a0e5a96ac..6d084c61ee2532 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -779,6 +779,8 @@ static int intel_pstate_hwp_save_state(struct cpufreq_policy *policy) return 0; } +static void intel_pstate_hwp_enable(struct cpudata *cpudata); + static int intel_pstate_resume(struct cpufreq_policy *policy) { if (!hwp_active) @@ -786,6 +788,9 @@ static int intel_pstate_resume(struct cpufreq_policy *policy) mutex_lock(&intel_pstate_limits_lock); + if (policy->cpu == 0) + intel_pstate_hwp_enable(all_cpu_data[policy->cpu]); + all_cpu_data[policy->cpu]->epp_policy = 0; intel_pstate_hwp_set(policy->cpu); From ffd81dcfef85a33729f90e4acd2f61a68e56b993 Mon Sep 17 00:00:00 2001 From: Dominik Brodowski Date: Tue, 30 Jan 2018 06:42:37 +0100 Subject: [PATCH 229/237] cpufreq: Add and use cpufreq_for_each_{valid_,}entry_idx() Pointer subtraction is slow and tedious. Therefore, replace all instances where cpufreq_for_each_{valid_,}entry loops contained such substractions with an iteration macro providing an index to the frequency_table entry. Suggested-by: Al Viro Link: http://lkml.kernel.org/r/20180120020237.GM13338@ZenIV.linux.org.uk Acked-by: Viresh Kumar Signed-off-by: Dominik Brodowski Signed-off-by: Rafael J. Wysocki --- Documentation/cpu-freq/cpu-drivers.txt | 4 + drivers/cpufreq/exynos5440-cpufreq.c | 7 +- drivers/cpufreq/freq_table.c | 8 +- drivers/cpufreq/longhaul.c | 4 +- drivers/cpufreq/pasemi-cpufreq.c | 6 +- drivers/sh/clk/core.c | 5 +- drivers/staging/irda/drivers/sh_sir.c | 4 +- include/linux/cpufreq.h | 125 ++++++++++++++++--------- 8 files changed, 100 insertions(+), 63 deletions(-) diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index 434c49cc7330aa..61546ac578d607 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -291,3 +291,7 @@ For example: /* Do something with pos */ pos->frequency = ... } + +If you need to work with the position of pos within driver_freq_table, +do not subtract the pointers, as it is quite costly. Instead, use the +macros cpufreq_for_each_entry_idx() and cpufreq_for_each_valid_entry_idx(). diff --git a/drivers/cpufreq/exynos5440-cpufreq.c b/drivers/cpufreq/exynos5440-cpufreq.c index b6b369c2227265..932caa386ecec4 100644 --- a/drivers/cpufreq/exynos5440-cpufreq.c +++ b/drivers/cpufreq/exynos5440-cpufreq.c @@ -115,10 +115,10 @@ static struct cpufreq_freqs freqs; static int init_div_table(void) { struct cpufreq_frequency_table *pos, *freq_tbl = dvfs_info->freq_table; - unsigned int tmp, clk_div, ema_div, freq, volt_id; + unsigned int tmp, clk_div, ema_div, freq, volt_id, idx; struct dev_pm_opp *opp; - cpufreq_for_each_entry(pos, freq_tbl) { + cpufreq_for_each_entry_idx(pos, freq_tbl, idx) { opp = dev_pm_opp_find_freq_exact(dvfs_info->dev, pos->frequency * 1000, true); if (IS_ERR(opp)) { @@ -154,8 +154,7 @@ static int init_div_table(void) tmp = (clk_div | ema_div | (volt_id << P0_7_VDD_SHIFT) | ((freq / FREQ_UNIT) << P0_7_FREQ_SHIFT)); - __raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * - (pos - freq_tbl)); + __raw_writel(tmp, dvfs_info->base + XMU_PMU_P0_7 + 4 * idx); dev_pm_opp_put(opp); } diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 3bbbf9e6960cdf..6d007f824ca74b 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -143,10 +143,9 @@ int cpufreq_table_index_unsorted(struct cpufreq_policy *policy, break; } - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, i) { freq = pos->frequency; - i = pos - table; if ((freq < policy->min) || (freq > policy->max)) continue; if (freq == target_freq) { @@ -211,15 +210,16 @@ int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, unsigned int freq) { struct cpufreq_frequency_table *pos, *table = policy->freq_table; + int idx; if (unlikely(!table)) { pr_debug("%s: Unable to find frequency table\n", __func__); return -ENOENT; } - cpufreq_for_each_valid_entry(pos, table) + cpufreq_for_each_valid_entry_idx(pos, table, idx) if (pos->frequency == freq) - return pos - table; + return idx; return -EINVAL; } diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 5faa37c5b0910e..942632a27b50fb 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -600,7 +600,7 @@ static void longhaul_setup_voltagescaling(void) /* Calculate kHz for one voltage step */ kHz_step = (highest_speed - min_vid_speed) / numvscales; - cpufreq_for_each_entry(freq_pos, longhaul_table) { + cpufreq_for_each_entry_idx(freq_pos, longhaul_table, j) { speed = freq_pos->frequency; if (speed > min_vid_speed) pos = (speed - min_vid_speed) / kHz_step + minvid.pos; @@ -609,7 +609,7 @@ static void longhaul_setup_voltagescaling(void) freq_pos->driver_data |= mV_vrm_table[pos] << 8; vid = vrm_mV_table[mV_vrm_table[pos]]; pr_info("f: %d kHz, index: %d, vid: %d mV\n", - speed, (int)(freq_pos - longhaul_table), vid.mV); + speed, j, vid.mV); } can_scale_voltage = 1; diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index b257fc7d520410..75dfbd2a58ea6f 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -139,7 +139,7 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) struct cpufreq_frequency_table *pos; const u32 *max_freqp; u32 max_freq; - int cur_astate; + int cur_astate, idx; struct resource res; struct device_node *cpu, *dn; int err = -ENODEV; @@ -198,9 +198,9 @@ static int pas_cpufreq_cpu_init(struct cpufreq_policy *policy) pr_debug("initializing frequency table\n"); /* initialize frequency table */ - cpufreq_for_each_entry(pos, pas_freqs) { + cpufreq_for_each_entry_idx(pos, pas_freqs, idx) { pos->frequency = get_astate_freq(pos->driver_data) * 100000; - pr_debug("%d: %d\n", (int)(pos - pas_freqs), pos->frequency); + pr_debug("%d: %d\n", idx, pos->frequency); } cur_astate = get_cur_astate(policy->cpu); diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c index 92863e3818e5c7..9475353f49d6c5 100644 --- a/drivers/sh/clk/core.c +++ b/drivers/sh/clk/core.c @@ -197,10 +197,11 @@ int clk_rate_table_find(struct clk *clk, unsigned long rate) { struct cpufreq_frequency_table *pos; + int idx; - cpufreq_for_each_valid_entry(pos, freq_table) + cpufreq_for_each_valid_entry_idx(pos, freq_table, idx) if (pos->frequency == rate) - return pos - freq_table; + return idx; return -ENOENT; } diff --git a/drivers/staging/irda/drivers/sh_sir.c b/drivers/staging/irda/drivers/sh_sir.c index fede6864c737bd..0d0687cc454abb 100644 --- a/drivers/staging/irda/drivers/sh_sir.c +++ b/drivers/staging/irda/drivers/sh_sir.c @@ -226,7 +226,7 @@ static u32 sh_sir_find_sclk(struct clk *irda_clk) clk_put(pclk); /* IrDA can not set over peripheral_clk */ - cpufreq_for_each_valid_entry(pos, freq_table) { + cpufreq_for_each_valid_entry_idx(pos, freq_table, index) { u32 freq = pos->frequency; /* IrDA should not over peripheral_clk */ @@ -236,7 +236,7 @@ static u32 sh_sir_find_sclk(struct clk *irda_clk) tmp = freq % SCLK_BASE; if (tmp < min) { min = tmp; - index = pos - freq_table; + break; } } diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 065f3a8eb48615..21e8d248d95645 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -628,6 +628,18 @@ static inline void dev_pm_opp_free_cpufreq_table(struct device *dev, #define cpufreq_for_each_entry(pos, table) \ for (pos = table; pos->frequency != CPUFREQ_TABLE_END; pos++) +/* + * cpufreq_for_each_entry_idx - iterate over a cpufreq_frequency_table + * with index + * @pos: the cpufreq_frequency_table * to use as a loop cursor. + * @table: the cpufreq_frequency_table * to iterate over. + * @idx: the table entry currently being processed + */ + +#define cpufreq_for_each_entry_idx(pos, table, idx) \ + for (pos = table, idx = 0; pos->frequency != CPUFREQ_TABLE_END; \ + pos++, idx++) + /* * cpufreq_for_each_valid_entry - iterate over a cpufreq_frequency_table * excluding CPUFREQ_ENTRY_INVALID frequencies. @@ -641,6 +653,21 @@ static inline void dev_pm_opp_free_cpufreq_table(struct device *dev, continue; \ else +/* + * cpufreq_for_each_valid_entry_idx - iterate with index over a cpufreq + * frequency_table excluding CPUFREQ_ENTRY_INVALID frequencies. + * @pos: the cpufreq_frequency_table * to use as a loop cursor. + * @table: the cpufreq_frequency_table * to iterate over. + * @idx: the table entry currently being processed + */ + +#define cpufreq_for_each_valid_entry_idx(pos, table, idx) \ + cpufreq_for_each_entry_idx(pos, table, idx) \ + if (pos->frequency == CPUFREQ_ENTRY_INVALID) \ + continue; \ + else + + int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table); @@ -667,19 +694,20 @@ static inline int cpufreq_table_find_index_al(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq >= target_freq) - return pos - table; + return idx; - best = pos; + best = idx; } - return best - table; + return best; } /* Find lowest freq at or above target in a table in descending order */ @@ -687,28 +715,29 @@ static inline int cpufreq_table_find_index_dl(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq == target_freq) - return pos - table; + return idx; if (freq > target_freq) { - best = pos; + best = idx; continue; } /* No freq found above target_freq */ - if (best == table - 1) - return pos - table; + if (best == -1) + return idx; - return best - table; + return best; } - return best - table; + return best; } /* Works only on sorted freq-tables */ @@ -728,28 +757,29 @@ static inline int cpufreq_table_find_index_ah(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq == target_freq) - return pos - table; + return idx; if (freq < target_freq) { - best = pos; + best = idx; continue; } /* No freq found below target_freq */ - if (best == table - 1) - return pos - table; + if (best == -1) + return idx; - return best - table; + return best; } - return best - table; + return best; } /* Find highest freq at or below target in a table in descending order */ @@ -757,19 +787,20 @@ static inline int cpufreq_table_find_index_dh(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq <= target_freq) - return pos - table; + return idx; - best = pos; + best = idx; } - return best - table; + return best; } /* Works only on sorted freq-tables */ @@ -789,32 +820,33 @@ static inline int cpufreq_table_find_index_ac(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq == target_freq) - return pos - table; + return idx; if (freq < target_freq) { - best = pos; + best = idx; continue; } /* No freq found below target_freq */ - if (best == table - 1) - return pos - table; + if (best == -1) + return idx; /* Choose the closest freq */ - if (target_freq - best->frequency > freq - target_freq) - return pos - table; + if (target_freq - table[best].frequency > freq - target_freq) + return idx; - return best - table; + return best; } - return best - table; + return best; } /* Find closest freq to target in a table in descending order */ @@ -822,32 +854,33 @@ static inline int cpufreq_table_find_index_dc(struct cpufreq_policy *policy, unsigned int target_freq) { struct cpufreq_frequency_table *table = policy->freq_table; - struct cpufreq_frequency_table *pos, *best = table - 1; + struct cpufreq_frequency_table *pos; unsigned int freq; + int idx, best = -1; - cpufreq_for_each_valid_entry(pos, table) { + cpufreq_for_each_valid_entry_idx(pos, table, idx) { freq = pos->frequency; if (freq == target_freq) - return pos - table; + return idx; if (freq > target_freq) { - best = pos; + best = idx; continue; } /* No freq found above target_freq */ - if (best == table - 1) - return pos - table; + if (best == -1) + return idx; /* Choose the closest freq */ - if (best->frequency - target_freq > target_freq - freq) - return pos - table; + if (table[best].frequency - target_freq > target_freq - freq) + return idx; - return best - table; + return best; } - return best - table; + return best; } /* Works only on sorted freq-tables */ From d0404738c687c0ecaa7d6b7c5c39e4c0dac791e6 Mon Sep 17 00:00:00 2001 From: Nicolas Chauvet Date: Tue, 30 Jan 2018 10:55:26 +0100 Subject: [PATCH 230/237] arm: imx: Add MODULE_ALIAS for cpufreq Without this, the imx6q-cpufreq driver isn't loaded automatically when built as a module Tested on wandboard quad with a fedora 27 kernel rpm Signed-off-by: Nicolas Chauvet Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/imx6q-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 741f22e5cee313..ff67859948b34e 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -504,6 +504,7 @@ static struct platform_driver imx6q_cpufreq_platdrv = { }; module_platform_driver(imx6q_cpufreq_platdrv); +MODULE_ALIAS("platform:imx6q-cpufreq"); MODULE_AUTHOR("Shawn Guo "); MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver"); MODULE_LICENSE("GPL"); From 6e0377212c4e45d7350cff018f6a95633937c031 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Tue, 6 Feb 2018 12:49:58 +0100 Subject: [PATCH 231/237] CRIS: Restore mistakenly cleared kernel Makefile Commit 0fbc0b67a89d7 ("cris: remove arch specific early DT functions") was a bit overzealous in removing the CRIS DT handling, and the complete contents of the Makefile was erased instead of just the line for the devicetree file. This lead to a complete link failure for all SoCs in the CRIS port due to missing symbols. Restore the contents except the line for the devicetree file. Signed-off-by: Jesper Nilsson Fixes: 0fbc0b67a89d7 --- arch/cris/kernel/Makefile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/cris/kernel/Makefile b/arch/cris/kernel/Makefile index e69de29bb2d1d6..f6bfee6c8c1bd6 100644 --- a/arch/cris/kernel/Makefile +++ b/arch/cris/kernel/Makefile @@ -0,0 +1,17 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Makefile for the CRIS port. +# + +CPPFLAGS_vmlinux.lds := -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE) +extra-y := vmlinux.lds + +obj-y := process.o traps.o irq.o ptrace.o setup.o time.o sys_cris.o +obj-y += stacktrace.o + +obj-$(CONFIG_MODULES) += crisksyms.o +obj-$(CONFIG_MODULES) += module.o +obj-$(CONFIG_SYSTEM_PROFILER) += profile.o + +clean: + From 0078117c6d9160031b866cfa1853514d4f6865d2 Mon Sep 17 00:00:00 2001 From: "J. Bruce Fields" Date: Wed, 15 Nov 2017 12:30:27 -0500 Subject: [PATCH 232/237] nfsd: return RESOURCE not GARBAGE_ARGS on too many ops A client that sends more than a hundred ops in a single compound currently gets an rpc-level GARBAGE_ARGS error. It would be more helpful to return NFS4ERR_RESOURCE, since that gives the client a better idea how to recover (for example by splitting up the compound into smaller compounds). This is all a bit academic since we've never actually seen a reason for clients to send such long compounds, but we may as well fix it. While we're there, just use NFSD4_MAX_OPS_PER_COMPOUND == 16, the constant we already use in the 4.1 case, instead of hard-coding 100. Chances anyone actually uses even 16 ops per compound are small enough that I think there's a neglible risk or any regression. This fixes pynfs test COMP6. Reported-by: "Lu, Xinyu" Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4proc.c | 3 +++ fs/nfsd/nfs4xdr.c | 9 +++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index effeeb4f556f64..a0bed2b2004db4 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -1703,6 +1703,9 @@ nfsd4_proc_compound(struct svc_rqst *rqstp) status = nfserr_minor_vers_mismatch; if (nfsd_minorversion(args->minorversion, NFSD_TEST) <= 0) goto out; + status = nfserr_resource; + if (args->opcnt > NFSD_MAX_OPS_PER_COMPOUND) + goto out; status = nfs41_check_op_ordering(args); if (status) { diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 2c61c6b8ae0976..5dcd7cb45b2d2b 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1918,8 +1918,13 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) if (argp->taglen > NFSD4_MAX_TAGLEN) goto xdr_error; - if (argp->opcnt > 100) - goto xdr_error; + /* + * NFS4ERR_RESOURCE is a more helpful error than GARBAGE_ARGS + * here, so we return success at the xdr level so that + * nfsd4_proc can handle this is an NFS-level error. + */ + if (argp->opcnt > NFSD_MAX_OPS_PER_COMPOUND) + return 0; if (argp->opcnt > ARRAY_SIZE(argp->iops)) { argp->ops = kzalloc(argp->opcnt * sizeof(*argp->ops), GFP_KERNEL); From 76c479480b9afff4c585a17e19a1efe3457a2d9b Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 3 Jan 2018 17:14:34 +0200 Subject: [PATCH 233/237] nfsd: encode stat->mtime for getattr instead of inode->i_mtime The values of stat->mtime and inode->i_mtime may differ for overlayfs and stat->mtime is the correct value to use when encoding getattr. This is also consistent with the fact that other attr times are also encoded from stat values. Both callers of lease_get_mtime() already have the value of stat->mtime, so the only needed change is that lease_get_mtime() will not overwrite this value with inode->i_mtime in case the inode does not have an exclusive lease. Signed-off-by: Amir Goldstein Reviewed-by: Jeff Layton Signed-off-by: J. Bruce Fields --- fs/locks.c | 6 ++---- fs/nfsd/nfsxdr.c | 1 + 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/locks.c b/fs/locks.c index 1bd71c4d663a8c..db374a02581122 100644 --- a/fs/locks.c +++ b/fs/locks.c @@ -1554,9 +1554,9 @@ int __break_lease(struct inode *inode, unsigned int mode, unsigned int type) EXPORT_SYMBOL(__break_lease); /** - * lease_get_mtime - get the last modified time of an inode + * lease_get_mtime - update modified time of an inode with exclusive lease * @inode: the inode - * @time: pointer to a timespec which will contain the last modified time + * @time: pointer to a timespec which contains the last modified time * * This is to force NFS clients to flush their caches for files with * exclusive leases. The justification is that if someone has an @@ -1580,8 +1580,6 @@ void lease_get_mtime(struct inode *inode, struct timespec *time) if (has_lease) *time = current_time(inode); - else - *time = inode->i_mtime; } EXPORT_SYMBOL(lease_get_mtime); diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index 644a0342f0e065..79b6064f8977a7 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -188,6 +188,7 @@ encode_fattr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, *p++ = htonl((u32) stat->ino); *p++ = htonl((u32) stat->atime.tv_sec); *p++ = htonl(stat->atime.tv_nsec ? stat->atime.tv_nsec / 1000 : 0); + time = stat->mtime; lease_get_mtime(d_inode(dentry), &time); *p++ = htonl((u32) time.tv_sec); *p++ = htonl(time.tv_nsec ? time.tv_nsec / 1000 : 0); From 39ca1bf624b6b82cc895b0217889eaaf572a7913 Mon Sep 17 00:00:00 2001 From: Amir Goldstein Date: Wed, 3 Jan 2018 17:14:35 +0200 Subject: [PATCH 234/237] nfsd: store stat times in fill_pre_wcc() instead of inode times The time values in stat and inode may differ for overlayfs and stat time values are the correct ones to use. This is also consistent with the fact that fill_post_wcc() also stores stat time values. This means introducing a stat call that could fail, where previously we were just copying values out of the inode. To be conservative about changing behavior, we fall back to copying values out of the inode in the error case. It might be better just to clear fh_pre_saved (though note the BUG_ON in set_change_info). Signed-off-by: Amir Goldstein Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs3xdr.c | 31 ++++++++++++++++++++++++++++++- fs/nfsd/nfs4xdr.c | 2 +- fs/nfsd/nfsfh.h | 28 ++++++---------------------- 3 files changed, 37 insertions(+), 24 deletions(-) diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 2758480555faa5..1a70581e1cb2b1 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -250,6 +250,34 @@ encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) return encode_post_op_attr(rqstp, p, fhp); } +/* + * Fill in the pre_op attr for the wcc data + */ +void fill_pre_wcc(struct svc_fh *fhp) +{ + struct inode *inode; + struct kstat stat; + __be32 err; + + if (fhp->fh_pre_saved) + return; + + inode = d_inode(fhp->fh_dentry); + err = fh_getattr(fhp, &stat); + if (err) { + /* Grab the times from inode anyway */ + stat.mtime = inode->i_mtime; + stat.ctime = inode->i_ctime; + stat.size = inode->i_size; + } + + fhp->fh_pre_mtime = stat.mtime; + fhp->fh_pre_ctime = stat.ctime; + fhp->fh_pre_size = stat.size; + fhp->fh_pre_change = nfsd4_change_attribute(&stat, inode); + fhp->fh_pre_saved = true; +} + /* * Fill in the post_op attr for the wcc data */ @@ -261,7 +289,8 @@ void fill_post_wcc(struct svc_fh *fhp) printk("nfsd: inode locked twice during operation.\n"); err = fh_getattr(fhp, &fhp->fh_post_attr); - fhp->fh_post_change = nfsd4_change_attribute(d_inode(fhp->fh_dentry)); + fhp->fh_post_change = nfsd4_change_attribute(&fhp->fh_post_attr, + d_inode(fhp->fh_dentry)); if (err) { fhp->fh_post_saved = false; /* Grab the ctime anyway - set_change_info might use it */ diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 5dcd7cb45b2d2b..e4395abd0f2b32 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1996,7 +1996,7 @@ static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode, *p++ = cpu_to_be32(convert_to_wallclock(exp->cd->flush_time)); *p++ = 0; } else if (IS_I_VERSION(inode)) { - p = xdr_encode_hyper(p, nfsd4_change_attribute(inode)); + p = xdr_encode_hyper(p, nfsd4_change_attribute(stat, inode)); } else { *p++ = cpu_to_be32(stat->ctime.tv_sec); *p++ = cpu_to_be32(stat->ctime.tv_nsec); diff --git a/fs/nfsd/nfsfh.h b/fs/nfsd/nfsfh.h index 43f31cf49bae3f..99be87b50ebed6 100644 --- a/fs/nfsd/nfsfh.h +++ b/fs/nfsd/nfsfh.h @@ -252,36 +252,20 @@ fh_clear_wcc(struct svc_fh *fhp) * By using both ctime and the i_version counter we guarantee that as * long as time doesn't go backwards we never reuse an old value. */ -static inline u64 nfsd4_change_attribute(struct inode *inode) +static inline u64 nfsd4_change_attribute(struct kstat *stat, + struct inode *inode) { u64 chattr; - chattr = inode->i_ctime.tv_sec; + chattr = stat->ctime.tv_sec; chattr <<= 30; - chattr += inode->i_ctime.tv_nsec; + chattr += stat->ctime.tv_nsec; chattr += inode->i_version; return chattr; } -/* - * Fill in the pre_op attr for the wcc data - */ -static inline void -fill_pre_wcc(struct svc_fh *fhp) -{ - struct inode *inode; - - inode = d_inode(fhp->fh_dentry); - if (!fhp->fh_pre_saved) { - fhp->fh_pre_mtime = inode->i_mtime; - fhp->fh_pre_ctime = inode->i_ctime; - fhp->fh_pre_size = inode->i_size; - fhp->fh_pre_change = nfsd4_change_attribute(inode); - fhp->fh_pre_saved = true; - } -} - -extern void fill_post_wcc(struct svc_fh *); +extern void fill_pre_wcc(struct svc_fh *fhp); +extern void fill_post_wcc(struct svc_fh *fhp); #else #define fh_clear_wcc(ignored) #define fill_pre_wcc(ignored) From 2285ae760de2cbe4b91a55c0a8033ec332fb8049 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Jan 2018 22:09:12 +0100 Subject: [PATCH 235/237] NFSD: hide unused svcxdr_dupstr() There is now only one caller left for svcxdr_dupstr() and this is inside of an #ifdef, so we can get a warning when the option is disabled: fs/nfsd/nfs4xdr.c:241:1: error: 'svcxdr_dupstr' defined but not used [-Werror=unused-function] This changes the remaining caller to use a nicer IS_ENABLED() check, which lets the compiler drop the unused code silently. Fixes: e40d99e6183e ("NFSD: Clean up symlink argument XDR decoders") Suggested-by: Rasmus Villemoes Signed-off-by: Arnd Bergmann Signed-off-by: J. Bruce Fields --- fs/nfsd/nfs4xdr.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index e4395abd0f2b32..e502fd16246b81 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -455,8 +455,8 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, } label->len = 0; -#ifdef CONFIG_NFSD_V4_SECURITY_LABEL - if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) { + if (IS_ENABLED(CONFIG_NFSD_V4_SECURITY_LABEL) && + bmval[2] & FATTR4_WORD2_SECURITY_LABEL) { READ_BUF(4); len += 4; dummy32 = be32_to_cpup(p++); /* lfs: we don't use it */ @@ -476,7 +476,6 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, if (!label->data) return nfserr_jukebox; } -#endif if (bmval[2] & FATTR4_WORD2_MODE_UMASK) { if (!umask) goto xdr_error; From 175e03101d36c3034f3c80038d4c28838351a7f2 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Fri, 2 Feb 2018 14:28:59 -0500 Subject: [PATCH 236/237] svcrdma: Fix Read chunk round-up A single NFSv4 WRITE compound can often have three operations: PUTFH, WRITE, then GETATTR. When the WRITE payload is sent in a Read chunk, the client places the GETATTR in the inline part of the RPC/RDMA message, just after the WRITE operation (sans payload). The position value in the Read chunk enables the receiver to insert the Read chunk at the correct place in the received XDR stream; that is between the WRITE and GETATTR. According to RFC 8166, an NFS/RDMA client does not have to add XDR round-up to the Read chunk that carries the WRITE payload. The receiver adds XDR round-up padding if it is absent and the receiver's XDR decoder requires it to be present. Commit 193bcb7b3719 ("svcrdma: Populate tail iovec when receiving") attempted to add support for receiving such a compound so that just the WRITE payload appears in rq_arg's page list, and the trailing GETATTR is placed in rq_arg's tail iovec. (TCP just strings the whole compound into the head iovec and page list, without regard to the alignment of the WRITE payload). The server transport logic also had to accommodate the optional XDR round-up of the Read chunk, which it did simply by lengthening the tail iovec when round-up was needed. This approach is adequate for the NFSv2 and NFSv3 WRITE decoders. Unfortunately it is not sufficient for nfsd4_decode_write. When the Read chunk length is a couple of bytes less than PAGE_SIZE, the computation at the end of nfsd4_decode_write allows argp->pagelen to go negative, which breaks the logic in read_buf that looks for the tail iovec. The result is that a WRITE operation whose payload length is just less than a multiple of a page succeeds, but the subsequent GETATTR in the same compound fails with NFS4ERR_OP_ILLEGAL because the XDR decoder can't find it. Clients ignore the error, but they must update their attribute cache via a separate round trip. As nfsd4_decode_write appears to expect the payload itself to always have appropriate XDR round-up, have svc_rdma_build_normal_read_chunk add the Read chunk XDR round-up to the page_len rather than lengthening the tail iovec. Reported-by: Olga Kornievskaia Fixes: 193bcb7b3719 ("svcrdma: Populate tail iovec when receiving") Signed-off-by: Chuck Lever Tested-by: Olga Kornievskaia Signed-off-by: J. Bruce Fields --- net/sunrpc/xprtrdma/svc_rdma_rw.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/net/sunrpc/xprtrdma/svc_rdma_rw.c b/net/sunrpc/xprtrdma/svc_rdma_rw.c index 9bd04549a1ad69..12b9a7e0b6d23a 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_rw.c +++ b/net/sunrpc/xprtrdma/svc_rdma_rw.c @@ -727,12 +727,16 @@ static int svc_rdma_build_normal_read_chunk(struct svc_rqst *rqstp, head->arg.head[0].iov_len - info->ri_position; head->arg.head[0].iov_len = info->ri_position; - /* Read chunk may need XDR roundup (see RFC 5666, s. 3.7). + /* Read chunk may need XDR roundup (see RFC 8166, s. 3.4.5.2). * - * NFSv2/3 write decoders need the length of the tail to - * contain the size of the roundup padding. + * If the client already rounded up the chunk length, the + * length does not change. Otherwise, the length of the page + * list is increased to include XDR round-up. + * + * Currently these chunks always start at page offset 0, + * thus the rounded-up length never crosses a page boundary. */ - head->arg.tail[0].iov_len += 4 - (info->ri_chunklen & 3); + info->ri_chunklen = XDR_QUADLEN(info->ri_chunklen) << 2; head->arg.page_len = info->ri_chunklen; head->arg.len += info->ri_chunklen; From a8c6db00bff2bdb466d80b7ec7ff25d327071f9b Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Wed, 7 Feb 2018 22:08:08 -0500 Subject: [PATCH 237/237] cramfs: better MTD dependency expression Commit b9f5fb1800d8 ("cramfs: fix MTD dependency") did what it says. Since commit 9059a3493efe ("kconfig: fix relational operators for bool and tristate symbols") it is possible to do it slightly better though. Signed-off-by: Nicolas Pitre Signed-off-by: Linus Torvalds --- fs/cramfs/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/cramfs/Kconfig b/fs/cramfs/Kconfig index 58e2fe40b2a044..5933f995309a32 100644 --- a/fs/cramfs/Kconfig +++ b/fs/cramfs/Kconfig @@ -33,8 +33,7 @@ config CRAMFS_BLOCKDEV config CRAMFS_MTD bool "Support CramFs image directly mapped in physical memory" - depends on CRAMFS && MTD - depends on CRAMFS=m || MTD=y + depends on CRAMFS && CRAMFS <= MTD default y if !CRAMFS_BLOCKDEV help This option allows the CramFs driver to load data directly from