[PATCH] ACPI / property: restore _DSD data subnodes GUID comment
Patch "5f5e4890d57a" removes the comment of _DSD data subnodes GUID. This patch restores it. Fixes: 5f5e4890d57a ("ACPI / property: Allow multiple property compatible _DSD entries") Cc: Joey Zheng Signed-off-by: Shunyong Yang --- drivers/acpi/property.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 77abe0ec4043..8832d0e13a72 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c @@ -44,6 +44,7 @@ static int acpi_data_get_property_array(const struct acpi_device_data *data, 0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89), }; +/* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */ static const guid_t ads_guid = GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6, 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b); -- 1.8.3.1
[PATCH v2 2/2] dmaengine: qcom_hidma: assign channel cookie correctly
When dma_cookie_complete() is called in hidma_process_completed(), dma_cookie_status() will return DMA_COMPLETE in hidma_tx_status(). Then, hidma_txn_is_success() will be called to use channel cookie mchan->last_success to do additional DMA status check. Current code assigns mchan->last_success after dma_cookie_complete(). This causes a race condition of dma_cookie_status() returns DMA_COMPLETE before mchan->last_success is assigned correctly. The race will cause hidma_tx_status() return DMA_ERROR but the transaction is actually a success. Moreover, in async_tx case, it will cause a timeout panic in async_tx_quiesce(). Kernel panic - not syncing: async_tx_quiesce: DMA error waiting for transaction ... Call trace: [] dump_backtrace+0x0/0x1f4 [] show_stack+0x24/0x2c [] dump_stack+0x84/0xa8 [] panic+0x12c/0x29c [] async_tx_quiesce+0xa4/0xc8 [async_tx] [] async_trigger_callback+0x70/0x1c0 [async_tx] [] raid_run_ops+0x86c/0x1540 [raid456] [] handle_stripe+0x5e8/0x1c7c [raid456] [] handle_active_stripes.isra.45+0x2d4/0x550 [raid456] [] raid5d+0x38c/0x5d0 [raid456] [] md_thread+0x108/0x168 [] kthread+0x10c/0x138 [] ret_from_fork+0x10/0x18 Cc: Joey Zheng Reviewed-by: Sinan Kaya Signed-off-by: Shunyong Yang --- v2: fix missing brace according to Vinod's feedback. add Reviewed-by: Sinan Kaya . --- drivers/dma/qcom/hidma.c | 17 + 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c index 9d639ed1955a..411f91fde734 100644 --- a/drivers/dma/qcom/hidma.c +++ b/drivers/dma/qcom/hidma.c @@ -138,24 +138,25 @@ static void hidma_process_completed(struct hidma_chan *mchan) desc = &mdesc->desc; last_cookie = desc->cookie; + llstat = hidma_ll_status(mdma->lldev, mdesc->tre_ch); + spin_lock_irqsave(&mchan->lock, irqflags); + if (llstat == DMA_COMPLETE) { + mchan->last_success = last_cookie; + result.result = DMA_TRANS_NOERROR; + } else { + result.result = DMA_TRANS_ABORTED; + } + dma_cookie_complete(desc); spin_unlock_irqrestore(&mchan->lock, irqflags); - llstat = hidma_ll_status(mdma->lldev, mdesc->tre_ch); dmaengine_desc_get_callback(desc, &cb); dma_run_dependencies(desc); spin_lock_irqsave(&mchan->lock, irqflags); list_move(&mdesc->node, &mchan->free); - - if (llstat == DMA_COMPLETE) { - mchan->last_success = last_cookie; - result.result = DMA_TRANS_NOERROR; - } else - result.result = DMA_TRANS_ABORTED; - spin_unlock_irqrestore(&mchan->lock, irqflags); dmaengine_desc_callback_invoke(&cb, &result); -- 1.8.3.1
[PATCH v2 1/2] dmaengine: qcom_hidma: initialize tx flags in hidma_prep_dma_*
In async_tx_test_ack(), it uses flags in struct dma_async_tx_descriptor to check the ACK status. As hidma reuses the descriptor in a free list when hidma_prep_dma_*(memcpy/memset) is called, the flag will keep ACKed if the descriptor has been used before. This will cause a BUG_ON in async_tx_quiesce(). kernel BUG at crypto/async_tx/async_tx.c:282! Internal error: Oops - BUG: 0 1 SMP ... task: 8017dd3ec000 task.stack: 8017dd3e8000 PC is at async_tx_quiesce+0x54/0x78 [async_tx] LR is at async_trigger_callback+0x98/0x110 [async_tx] This patch initializes flags in dma_async_tx_descriptor by the flags passed from the caller when hidma_prep_dma_*(memcpy/memset) is called. Cc: Joey Zheng Reviewed-by: Sinan Kaya Signed-off-by: Shunyong Yang --- v2: add Reviewed-by: Sinan Kaya --- drivers/dma/qcom/hidma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c index 43d4b00b8138..9d639ed1955a 100644 --- a/drivers/dma/qcom/hidma.c +++ b/drivers/dma/qcom/hidma.c @@ -415,6 +415,7 @@ static int hidma_alloc_chan_resources(struct dma_chan *dmach) if (!mdesc) return NULL; + mdesc->desc.flags = flags; hidma_ll_set_transfer_params(mdma->lldev, mdesc->tre_ch, src, dest, len, flags, HIDMA_TRE_MEMCPY); @@ -447,6 +448,7 @@ static int hidma_alloc_chan_resources(struct dma_chan *dmach) if (!mdesc) return NULL; + mdesc->desc.flags = flags; hidma_ll_set_transfer_params(mdma->lldev, mdesc->tre_ch, value, dest, len, flags, HIDMA_TRE_MEMSET); -- 1.8.3.1
[PATCH v2] ACPI / tables: table override from built-in initrd
In some scenario, we need to build initrd with kernel in a single image. This can simplify system deployment process by downloading the whole system once, such as in IC verification. This patch adds support to override ACPI tables from built-in initrd. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- v2: change "upgrade" to "override" as it's more accurate --- Documentation/acpi/initrd_table_override.txt | 4 drivers/acpi/Kconfig | 10 ++ drivers/acpi/tables.c| 12 ++-- include/linux/initrd.h | 3 +++ 4 files changed, 27 insertions(+), 2 deletions(-) diff --git a/Documentation/acpi/initrd_table_override.txt b/Documentation/acpi/initrd_table_override.txt index eb651a6aa285..324d5fb90a22 100644 --- a/Documentation/acpi/initrd_table_override.txt +++ b/Documentation/acpi/initrd_table_override.txt @@ -14,6 +14,10 @@ upgrade the ACPI execution environment that is defined by the ACPI tables via upgrading the ACPI tables provided by the BIOS with an instrumented, modified, more recent version one, or installing brand new ACPI tables. +When building initrd with kernel in a single image, option +ACPI_TABLE_OVERRIDE_VIA_BUILTIN_INITRD should also be true for this +purpose. + For a full list of ACPI tables that can be upgraded/installed, take a look at the char *table_sigs[MAX_ACPI_SIGNATURE]; definition in drivers/acpi/tables.c. diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 7cea769c37df..3b362a1c7685 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -357,6 +357,16 @@ config ACPI_TABLE_UPGRADE initrd, therefore it's safe to say Y. See Documentation/acpi/initrd_table_override.txt for details +config ACPI_TABLE_OVERRIDE_VIA_BUILTIN_INITRD + bool "Override ACPI tables from built-in initrd" + depends on ACPI_TABLE_UPGRADE + depends on INITRAMFS_SOURCE!="" && INITRAMFS_COMPRESSION="" + def_bool n + help + This option provides functionality to override arbitrary ACPI tables + from built-in uncompressed initrd. + See Documentation/acpi/initrd_table_override.txt for details + config ACPI_DEBUG bool "Debug Statements" help diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 61203eebf3a1..f6a2c5ebabcd 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -473,14 +473,22 @@ static u8 __init acpi_table_checksum(u8 *buffer, u32 length) void __init acpi_table_upgrade(void) { - void *data = (void *)initrd_start; - size_t size = initrd_end - initrd_start; + void *data; + size_t size; int sig, no, table_nr = 0, total_offset = 0; long offset = 0; struct acpi_table_header *table; char cpio_path[32] = "kernel/firmware/acpi/"; struct cpio_data file; + if (IS_ENABLED(CONFIG_ACPI_TABLE_OVERRIDE_VIA_BUILTIN_INITRD)) { + data = __initramfs_start; + size = __initramfs_size; + } else { + data = (void *)initrd_start; + size = initrd_end - initrd_start; + } + if (data == NULL || size == 0) return; diff --git a/include/linux/initrd.h b/include/linux/initrd.h index 84b423044088..02d94aae54c7 100644 --- a/include/linux/initrd.h +++ b/include/linux/initrd.h @@ -22,3 +22,6 @@ extern void free_initrd_mem(unsigned long, unsigned long); extern unsigned int real_root_dev; + +extern char __initramfs_start[]; +extern unsigned long __initramfs_size; -- 1.8.3.1
[PATCH] ACPI / tables: table upgrade from built-in initrd
In some scenario, we need to build initrd with kernel in a single image. This can simplify system deployment process by downloading the whole system once, such as in IC verification. This patch adds support to upgrade ACPI tables from built-in initrd. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- drivers/acpi/Kconfig | 9 + drivers/acpi/tables.c | 12 ++-- include/linux/initrd.h | 3 +++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 7cea769c37df..30976496fe77 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -357,6 +357,15 @@ config ACPI_TABLE_UPGRADE initrd, therefore it's safe to say Y. See Documentation/acpi/initrd_table_override.txt for details +config ACPI_TABLE_UPGRADE_VIA_BUILTIN_INITRD + bool "Upgrade ACPI tables from built-in initrd" + depends on ACPI_TABLE_UPGRADE + depends on INITRAMFS_SOURCE!="" && INITRAMFS_COMPRESSION="" + def_bool n + help + This option provides functionality to upgrade arbitrary ACPI tables + from built-in uncompressed initrd. + config ACPI_DEBUG bool "Debug Statements" help diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index 61203eebf3a1..88e3a34443da 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -473,14 +473,22 @@ static u8 __init acpi_table_checksum(u8 *buffer, u32 length) void __init acpi_table_upgrade(void) { - void *data = (void *)initrd_start; - size_t size = initrd_end - initrd_start; + void *data; + size_t size; int sig, no, table_nr = 0, total_offset = 0; long offset = 0; struct acpi_table_header *table; char cpio_path[32] = "kernel/firmware/acpi/"; struct cpio_data file; + if (IS_ENABLED(CONFIG_ACPI_TABLE_UPGRADE_VIA_BUILTIN_INITRD)) { + data = __initramfs_start; + size = __initramfs_size; + } else { + data = (void *)initrd_start; + size = initrd_end - initrd_start; + } + if (data == NULL || size == 0) return; diff --git a/include/linux/initrd.h b/include/linux/initrd.h index 84b423044088..02d94aae54c7 100644 --- a/include/linux/initrd.h +++ b/include/linux/initrd.h @@ -22,3 +22,6 @@ extern void free_initrd_mem(unsigned long, unsigned long); extern unsigned int real_root_dev; + +extern char __initramfs_start[]; +extern unsigned long __initramfs_size; -- 1.8.3.1
[PATCH 2/2] dmaengine: qcom_hidma: assign channel cookie correctly
When dma_cookie_complete() is called in hidma_process_completed(), dma_cookie_status() will return DMA_COMPLETE in hidma_tx_status(). Then, hidma_txn_is_success() will be called to use channel cookie mchan->last_success to do additional DMA status check. Current code assigns mchan->last_success after dma_cookie_complete(). This causes a race condition of dma_cookie_status() returns DMA_COMPLETE before mchan->last_success is assigned correctly. The race will cause hidma_tx_status() return DMA_ERROR but the transaction is actually a success. Moreover, in async_tx case, it will cause a timeout panic in async_tx_quiesce(). Kernel panic - not syncing: async_tx_quiesce: DMA error waiting for transaction ... Call trace: [] dump_backtrace+0x0/0x1f4 [] show_stack+0x24/0x2c [] dump_stack+0x84/0xa8 [] panic+0x12c/0x29c [] async_tx_quiesce+0xa4/0xc8 [async_tx] [] async_trigger_callback+0x70/0x1c0 [async_tx] [] raid_run_ops+0x86c/0x1540 [raid456] [] handle_stripe+0x5e8/0x1c7c [raid456] [] handle_active_stripes.isra.45+0x2d4/0x550 [raid456] [] raid5d+0x38c/0x5d0 [raid456] [] md_thread+0x108/0x168 [] kthread+0x10c/0x138 [] ret_from_fork+0x10/0x18 Cc: Joey Zheng Signed-off-by: Shunyong Yang --- drivers/dma/qcom/hidma.c | 16 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c index 9d639ed1955a..aa88bcceda20 100644 --- a/drivers/dma/qcom/hidma.c +++ b/drivers/dma/qcom/hidma.c @@ -138,24 +138,24 @@ static void hidma_process_completed(struct hidma_chan *mchan) desc = &mdesc->desc; last_cookie = desc->cookie; + llstat = hidma_ll_status(mdma->lldev, mdesc->tre_ch); + spin_lock_irqsave(&mchan->lock, irqflags); + if (llstat == DMA_COMPLETE) { + mchan->last_success = last_cookie; + result.result = DMA_TRANS_NOERROR; + } else + result.result = DMA_TRANS_ABORTED; + dma_cookie_complete(desc); spin_unlock_irqrestore(&mchan->lock, irqflags); - llstat = hidma_ll_status(mdma->lldev, mdesc->tre_ch); dmaengine_desc_get_callback(desc, &cb); dma_run_dependencies(desc); spin_lock_irqsave(&mchan->lock, irqflags); list_move(&mdesc->node, &mchan->free); - - if (llstat == DMA_COMPLETE) { - mchan->last_success = last_cookie; - result.result = DMA_TRANS_NOERROR; - } else - result.result = DMA_TRANS_ABORTED; - spin_unlock_irqrestore(&mchan->lock, irqflags); dmaengine_desc_callback_invoke(&cb, &result); -- 1.8.3.1
[PATCH 1/2] dmaengine: qcom_hidma: initialize tx flags in hidma_prep_dma_*
In async_tx_test_ack(), it uses flags in struct dma_async_tx_descriptor to check the ACK status. As hidma reuses the descriptor in a free list when hidma_prep_dma_*(memcpy/memset) is called, the flag will keep ACKed if the descriptor has been used before. This will cause a BUG_ON in async_tx_quiesce(). kernel BUG at crypto/async_tx/async_tx.c:282! Internal error: Oops - BUG: 0 1 SMP ... task: 8017dd3ec000 task.stack: 8017dd3e8000 PC is at async_tx_quiesce+0x54/0x78 [async_tx] LR is at async_trigger_callback+0x98/0x110 [async_tx] This patch initializes flags in dma_async_tx_descriptor by the flags passed from the caller when hidma_prep_dma_*(memcpy/memset) is called. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- drivers/dma/qcom/hidma.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/qcom/hidma.c b/drivers/dma/qcom/hidma.c index 43d4b00b8138..9d639ed1955a 100644 --- a/drivers/dma/qcom/hidma.c +++ b/drivers/dma/qcom/hidma.c @@ -415,6 +415,7 @@ static int hidma_alloc_chan_resources(struct dma_chan *dmach) if (!mdesc) return NULL; + mdesc->desc.flags = flags; hidma_ll_set_transfer_params(mdma->lldev, mdesc->tre_ch, src, dest, len, flags, HIDMA_TRE_MEMCPY); @@ -447,6 +448,7 @@ static int hidma_alloc_chan_resources(struct dma_chan *dmach) if (!mdesc) return NULL; + mdesc->desc.flags = flags; hidma_ll_set_transfer_params(mdma->lldev, mdesc->tre_ch, value, dest, len, flags, HIDMA_TRE_MEMSET); -- 1.8.3.1
[PATCH v2 1/2] PCI: Add HXT vendor ID and ACS quirk
Add the HXT vendor ID to pci_ids.h and use it in quirks. As the design of HXT SD4800 ACS feature is the same as QCOM QDF2xxx, pci_quirk_qcom_rp_acs() is reused for SD4800 quirk. cc: Joey Zheng Reviewed-by: Sinan Kaya Signed-off-by: Shunyong Yang --- v2: Add Reviewed-by: Sinan Kaya. v1: Initial version. --- diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4700d24e5d55..1e00ef6a88f4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4495,6 +4495,8 @@ static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags) /* QCOM QDF2xxx root ports */ { PCI_VENDOR_ID_QCOM, 0x0400, pci_quirk_qcom_rp_acs }, { PCI_VENDOR_ID_QCOM, 0x0401, pci_quirk_qcom_rp_acs }, + /* HXT SD4800 root ports. The ACS design is same as QCOM QDF2xxx */ + { PCI_VENDOR_ID_HXT, 0x0401, pci_quirk_qcom_rp_acs }, /* Intel PCH root ports */ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs }, { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_spt_pch_acs }, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 69f0abe1ba1a..e60a6bc38298 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2565,6 +2565,8 @@ #define PCI_VENDOR_ID_HYGON0x1d94 +#define PCI_VENDOR_ID_HXT 0x1dbf + #define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 -- 1.8.3.1
[PATCH v2 2/2] PCI: pciehp: Add HXT quirk for Command Completed errata
The HXT SD4800 PCI controller does not set the Command Completed bit unless writes to the Slot Command register change "Control" bits. This patch adds SD4800 to the quirk. Cc: Joey Zheng Signed-off-by: Shunyong Yang diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 7dd443aea5a5..91db67963aea 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -920,3 +920,5 @@ static void quirk_cmd_compl(struct pci_dev *pdev) PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl); DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_QCOM, 0x0401, PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl); +DECLARE_PCI_FIXUP_CLASS_EARLY(PCI_VENDOR_ID_HXT, 0x0401, + PCI_CLASS_BRIDGE_PCI, 8, quirk_cmd_compl); -- 1.8.3.1
[PATCH] PCI: Add HXT vendor ID and ACS quirk
Add the HXT vendor ID to pci_ids.h and use it in quirks. As the design of HXT SD4800 ACS feature is the same as QCOM QDF2xxx, pci_quirk_qcom_rp_acs() is reused for SD4800 quirk. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- drivers/pci/quirks.c| 2 ++ include/linux/pci_ids.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 4700d24e5d55..1e00ef6a88f4 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -4495,6 +4495,8 @@ static int pci_quirk_mf_endpoint_acs(struct pci_dev *dev, u16 acs_flags) /* QCOM QDF2xxx root ports */ { PCI_VENDOR_ID_QCOM, 0x0400, pci_quirk_qcom_rp_acs }, { PCI_VENDOR_ID_QCOM, 0x0401, pci_quirk_qcom_rp_acs }, + /* HXT SD4800 root ports. The ACS design is same as QCOM QDF2xxx */ + { PCI_VENDOR_ID_HXT, 0x0401, pci_quirk_qcom_rp_acs }, /* Intel PCH root ports */ { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_pch_acs }, { PCI_VENDOR_ID_INTEL, PCI_ANY_ID, pci_quirk_intel_spt_pch_acs }, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index f4e278493f5b..e3d7efb1442f 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2559,6 +2559,8 @@ #define PCI_VENDOR_ID_AMAZON 0x1d0f +#define PCI_VENDOR_ID_HXT 0x1dbf + #define PCI_VENDOR_ID_TEKRAM 0x1de1 #define PCI_DEVICE_ID_TEKRAM_DC290 0xdc29 -- 1.8.3.1
[PATCH v2] PCI: Unify pci and normal dma direction definition
Current DMA direction definitions in pci-dma-compat.h and dma-direction.h are mirrored in value. Unifying them to enhance readability and avoid possible inconsistency. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- v2: Remove unnecessary comments and braces according to Christoph's comments. --- include/linux/dma-direction.h | 6 ++ include/linux/pci-dma-compat.h | 8 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/include/linux/dma-direction.h b/include/linux/dma-direction.h index 3649a031893a..9c96e30e6a0b 100644 --- a/include/linux/dma-direction.h +++ b/include/linux/dma-direction.h @@ -1,14 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0 */ #ifndef _LINUX_DMA_DIRECTION_H #define _LINUX_DMA_DIRECTION_H -/* - * These definitions mirror those in pci.h, so they can be used - * interchangeably with their PCI_ counterparts. - */ + enum dma_data_direction { DMA_BIDIRECTIONAL = 0, DMA_TO_DEVICE = 1, DMA_FROM_DEVICE = 2, DMA_NONE = 3, }; + #endif diff --git a/include/linux/pci-dma-compat.h b/include/linux/pci-dma-compat.h index 0dd1a3f7b309..c3f1b44ade29 100644 --- a/include/linux/pci-dma-compat.h +++ b/include/linux/pci-dma-compat.h @@ -8,10 +8,10 @@ #include /* This defines the direction arg to the DMA mapping routines. */ -#define PCI_DMA_BIDIRECTIONAL 0 -#define PCI_DMA_TODEVICE 1 -#define PCI_DMA_FROMDEVICE 2 -#define PCI_DMA_NONE 3 +#define PCI_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL +#define PCI_DMA_TODEVICE DMA_TO_DEVICE +#define PCI_DMA_FROMDEVICE DMA_FROM_DEVICE +#define PCI_DMA_NONE DMA_NONE static inline void * pci_alloc_consistent(struct pci_dev *hwdev, size_t size, -- 1.8.3.1
[PATCH] PCI: Unify pci and normal dma direction definition
Current DMA direction definitions in pci-dma-compat.h and dma-direction.h are mirrored in value. Unify them to enhance readability and avoid possible inconsistency. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- include/linux/dma-direction.h | 2 +- include/linux/pci-dma-compat.h | 8 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/linux/dma-direction.h b/include/linux/dma-direction.h index 3649a031893a..9d52716e9218 100644 --- a/include/linux/dma-direction.h +++ b/include/linux/dma-direction.h @@ -2,7 +2,7 @@ #ifndef _LINUX_DMA_DIRECTION_H #define _LINUX_DMA_DIRECTION_H /* - * These definitions mirror those in pci.h, so they can be used + * These definitions mirror those in pci-dma-compat.h, so they can be used * interchangeably with their PCI_ counterparts. */ enum dma_data_direction { diff --git a/include/linux/pci-dma-compat.h b/include/linux/pci-dma-compat.h index 0dd1a3f7b309..c1c8d49b6072 100644 --- a/include/linux/pci-dma-compat.h +++ b/include/linux/pci-dma-compat.h @@ -8,10 +8,10 @@ #include /* This defines the direction arg to the DMA mapping routines. */ -#define PCI_DMA_BIDIRECTIONAL 0 -#define PCI_DMA_TODEVICE 1 -#define PCI_DMA_FROMDEVICE 2 -#define PCI_DMA_NONE 3 +#define PCI_DMA_BIDIRECTIONAL (DMA_BIDIRECTIONAL) +#define PCI_DMA_TODEVICE (DMA_TO_DEVICE) +#define PCI_DMA_FROMDEVICE (DMA_FROM_DEVICE) +#define PCI_DMA_NONE (DMA_NONE) static inline void * pci_alloc_consistent(struct pci_dev *hwdev, size_t size, -- 1.8.3.1
[RFC PATCH] arm64: topology: Map PPTT node offset to logic physical package id
As PPTT spec doesn't define the physical package id, find_acpi_cpu_topology_package() will return offset of the node with Physical package field set when querying physical package id. So, it returns 162(0xA2) in following example. [0A2h 0162 1]Subtable Type : 00 [Processor Hierarchy Node] [0A3h 0163 1] Length : 1C [0A4h 0164 2] Reserved : [0A6h 0166 4]Flags (decoded below) : 0003 Physical package : 1 ACPI Processor ID valid : 1 [0AAh 0170 4] Parent : [0AEh 0174 4]ACPI Processor ID : 1000 [0B2h 0178 4] Private Resource Number : 0002 [0B6h 0182 4] Private Resource : 006C [0BAh 0186 4] Private Resource : 0084 So, when "cat physical_package" in /sys/devices/system/cpu/cpu0/topology/, it will output 162(0xA2). And if some items are added before the node above, the output will change to other value. This patch maps the node offset to a logic package id. It maps the first node offset to 0, the second to 1, and so on. Then, it will not output a big value, such as 162 above. And it will not change when some nodes(Physical package not set) are added. And as long as the nodes with Physical package field set in PPTT keeps the real hardware order, the logic id can map to hardware package id to some extent. Hope to get feedback from you. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- arch/arm64/kernel/topology.c | 53 +++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c index f845a8617812..c219224b36e8 100644 --- a/arch/arm64/kernel/topology.c +++ b/arch/arm64/kernel/topology.c @@ -320,11 +320,59 @@ static void __init reset_cpu_topology(void) * Propagate the topology information of the processor_topology_node tree to the * cpu_topology array. */ + +struct package_id_map { + int topology_id; + int package_id; + struct list_head list; +}; + +static int map_package_id(int topology_id, int *max_package_id, + struct list_head *head) +{ + struct list_head *pos; + struct package_id_map *entry; + + list_for_each(pos, head) { + entry = container_of(pos, struct package_id_map, list); + if (entry->topology_id == topology_id) + goto done; + } + + /* topology_id not found in the list */ + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return topology_id; + + entry->topology_id = topology_id; + entry->package_id = *max_package_id; + list_add(&entry->list, head); + *max_package_id = *max_package_id + 1; + +done: + return entry->package_id; +} + +static void destroy_map(struct list_head *head) +{ + struct package_id_map *entry; + struct list_head *pos, *q; + + list_for_each_safe(pos, q, head) { + entry = container_of(pos, struct package_id_map, list); + list_del(pos); + kfree(entry); + } +} + static int __init parse_acpi_topology(void) { bool is_threaded; int cpu, topology_id; + struct list_head package_id_list; + int max_package_id = 0; + INIT_LIST_HEAD(&package_id_list); is_threaded = read_cpuid_mpidr() & MPIDR_MT_BITMASK; for_each_possible_cpu(cpu) { @@ -343,7 +391,9 @@ static int __init parse_acpi_topology(void) cpu_topology[cpu].core_id= topology_id; } topology_id = find_acpi_cpu_topology_package(cpu); - cpu_topology[cpu].package_id = topology_id; + cpu_topology[cpu].package_id = map_package_id(topology_id, + &max_package_id, + &package_id_list); i = acpi_find_last_cache_level(cpu); @@ -358,6 +408,7 @@ static int __init parse_acpi_topology(void) } } + destroy_map(&package_id_list); return 0; } -- 1.8.3.1
[tip:efi/core] efi/capsule-loader: Don't output reset log when reset flags are not set
Commit-ID: 83f0a7c7b265a56d757f7e3a80622e5b0b7ebc46 Gitweb: https://git.kernel.org/tip/83f0a7c7b265a56d757f7e3a80622e5b0b7ebc46 Author: Shunyong Yang AuthorDate: Fri, 4 May 2018 08:00:02 +0200 Committer: Ingo Molnar CommitDate: Mon, 14 May 2018 08:57:49 +0200 efi/capsule-loader: Don't output reset log when reset flags are not set When reset flags in capsule header are not set, it means firmware attempts to immediately process or launch the capsule. Moreover, reset is not needed in this case. The current code will output log to indicate reset. This patch adds a branch to avoid reset log output when the flags are not set. [ardb: use braces in multi-line 'if', clarify comment and commit log] Signed-off-by: Shunyong Yang Signed-off-by: Ard Biesheuvel Cc: Joey Zheng Cc: Linus Torvalds Cc: Matt Fleming Cc: Peter Zijlstra Cc: Thomas Gleixner Cc: linux-...@vger.kernel.org Link: http://lkml.kernel.org/r/20180504060003.19618-17-ard.biesheu...@linaro.org Signed-off-by: Ingo Molnar --- drivers/firmware/efi/capsule-loader.c | 14 ++ 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c index e456f4602df1..96688986da56 100644 --- a/drivers/firmware/efi/capsule-loader.c +++ b/drivers/firmware/efi/capsule-loader.c @@ -134,10 +134,16 @@ static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info) /* Indicate capsule binary uploading is done */ cap_info->index = NO_FURTHER_WRITE_ACTION; - pr_info("Successfully upload capsule file with reboot type '%s'\n", - !cap_info->reset_type ? "RESET_COLD" : - cap_info->reset_type == 1 ? "RESET_WARM" : - "RESET_SHUTDOWN"); + + if (cap_info->header.flags & EFI_CAPSULE_PERSIST_ACROSS_RESET) { + pr_info("Successfully uploaded capsule file with reboot type '%s'\n", + !cap_info->reset_type ? "RESET_COLD" : + cap_info->reset_type == 1 ? "RESET_WARM" : + "RESET_SHUTDOWN"); + } else { + pr_info("Successfully processed capsule file\n"); + } + return 0; }
[PATCH v2] efi/capsule-loader: Don't output reset log when reset flags are not set
It means firmware attempts to immediately process or launch the capsule when reset flags in capsule header are not set. Moreover, reset is not needed in this case. The current code will output log to indicate reset. This patch adds a branch to avoid reset log output when the flags are not set. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- Changes in v2: *Add EFI_CAPSULE_PERSIST_ACROSS_RESET check according to Ard's suggestion. --- drivers/firmware/efi/capsule-loader.c | 13 + 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c index e456f4602df1..344785ef8539 100644 --- a/drivers/firmware/efi/capsule-loader.c +++ b/drivers/firmware/efi/capsule-loader.c @@ -134,10 +134,15 @@ static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info) /* Indicate capsule binary uploading is done */ cap_info->index = NO_FURTHER_WRITE_ACTION; - pr_info("Successfully upload capsule file with reboot type '%s'\n", - !cap_info->reset_type ? "RESET_COLD" : - cap_info->reset_type == 1 ? "RESET_WARM" : - "RESET_SHUTDOWN"); + + if (cap_info->header.flags & EFI_CAPSULE_PERSIST_ACROSS_RESET) + pr_info("Successfully upload capsule file with reboot type '%s'\n", + !cap_info->reset_type ? "RESET_COLD" : + cap_info->reset_type == 1 ? "RESET_WARM" : + "RESET_SHUTDOWN"); + else + pr_info("Successfully upload, process and launch capsule file\n"); + return 0; } -- 1.8.3.1
[PATCH] efi/capsule-loader: Don't output reset log when header flags is not set
It means firmware attempts to immediately process or launch the capsule when flags in capsule header is not set. Moreover, reset is not needed in this case. Current code will output log to indicate reset. This patch adds a branch to avoid reset log output when the flags is not set. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- drivers/firmware/efi/capsule-loader.c | 13 + 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/firmware/efi/capsule-loader.c b/drivers/firmware/efi/capsule-loader.c index e456f4602df1..a63b8e5bde23 100644 --- a/drivers/firmware/efi/capsule-loader.c +++ b/drivers/firmware/efi/capsule-loader.c @@ -134,10 +134,15 @@ static ssize_t efi_capsule_submit_update(struct capsule_info *cap_info) /* Indicate capsule binary uploading is done */ cap_info->index = NO_FURTHER_WRITE_ACTION; - pr_info("Successfully upload capsule file with reboot type '%s'\n", - !cap_info->reset_type ? "RESET_COLD" : - cap_info->reset_type == 1 ? "RESET_WARM" : - "RESET_SHUTDOWN"); + + if (cap_info->header.flags) + pr_info("Successfully upload capsule file with reboot type '%s'\n", + !cap_info->reset_type ? "RESET_COLD" : + cap_info->reset_type == 1 ? "RESET_WARM" : + "RESET_SHUTDOWN"); + else + pr_info("Successfully upload, process and launch capsule file\n"); + return 0; } -- 1.8.3.1
[PATCH v3] cpufreq: cppc_cpufreq: Initialize shared cpu's perf capabilities
When multiple cpus are related in one cpufreq policy, the first online cpu will be chosen by default to handle cpufreq operations. Let's take cpu0 and cpu1 as an example. When cpu0 is offline, policy->cpu will be shifted to cpu1. Cpu1's perf capabilities should be initialized. Otherwise, perf capabilities are 0s and speed change can not take effect. This patch copies perf capabilities of the first online cpu to other shared cpus when policy shared type is CPUFREQ_SHARED_TYPE_ANY. Cc: Joey Zheng Acked-by: Viresh Kumar Signed-off-by: Shunyong Yang --- Changes in v3: -Remove unnecessary wrap per Kumar's comments. Changes in v2: -Add unlikely in cpu comparison per Kumar's comments. -Fix coding style per Kumar's comments. Changes in v1: -Drop RFC tag, The original RFC link, https://patchwork.kernel.org/patch/10299055/. This patch solves same issue as RFC above. Patch name is changed as code is too much different with RFC above. -Remove extra init() per Viresh Kumar's comments and only handle CPPC CPUFREQ_SHARED_TYPE_ANY case. --- drivers/cpufreq/cppc_cpufreq.c | 14 -- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 8300a9fcb80c..8b432d6e846d 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -167,9 +167,19 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) NSEC_PER_USEC; policy->shared_type = cpu->shared_type; - if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { + int i; + cpumask_copy(policy->cpus, cpu->shared_cpu_map); - else if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL) { + + for_each_cpu(i, policy->cpus) { + if (unlikely(i == policy->cpu)) + continue; + + memcpy(&all_cpu_data[i]->perf_caps, &cpu->perf_caps, + sizeof(cpu->perf_caps)); + } + } else if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL) { /* Support only SW_ANY for now. */ pr_debug("Unsupported CPU co-ord type\n"); return -EFAULT; -- 1.8.3.1
[PATCH v2] cpufreq: cppc_cpufreq: Initialize shared cpu's perf capabilities
When multiple cpus are related in one cpufreq policy, the first online cpu will be chosen by default to handle cpufreq operations. Let's take cpu0 and cpu1 as an example. When cpu0 is offline, policy->cpu will be shifted to cpu1. Cpu1's perf capabilities should be initialized. Otherwise, perf capabilities are 0s and speed change can not take effect. This patch copies perf capabilities of the first online cpu to other shared cpus when policy shared type is CPUFREQ_SHARED_TYPE_ANY. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- Changes in v2: -Add unlikely in cpu comparison per Kumar's comments. -Fix coding style per Kumar's comments. Changes in v1: -Drop RFC tag, The original RFC link, https://patchwork.kernel.org/patch/10299055/. This patch solves same issue as RFC above. Patch name is changed as code is too much different with RFC above. -Remove extra init() per Viresh Kumar's comments and only handle CPPC CPUFREQ_SHARED_TYPE_ANY case. --- drivers/cpufreq/cppc_cpufreq.c | 15 +-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 8f7b21a4d537..679e43b9c980 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -164,9 +164,20 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num); policy->shared_type = cpu->shared_type; - if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { + int i; + cpumask_copy(policy->cpus, cpu->shared_cpu_map); - else if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL) { + + for_each_cpu(i, policy->cpus) { + if (unlikely(i == policy->cpu)) + continue; + + memcpy(&all_cpu_data[i]->perf_caps, + &cpu->perf_caps, + sizeof(cpu->perf_caps)); + } + } else if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL) { /* Support only SW_ANY for now. */ pr_debug("Unsupported CPU co-ord type\n"); return -EFAULT; -- 1.8.3.1
[PATCH] cpufreq: cppc_cpufreq: Initialize shared cpu's perf capabilities
When multiple cpus are related in one cpufreq policy, the first online cpu will be chosen by default to handle cpufreq operations. Let's take cpu0 and cpu1 as an example. When cpu0 is offline, policy->cpu will be shifted to cpu1. Cpu1's should be initialized. Otherwise, perf capabilities are 0s and speed change can not take effect. This patch copies perf capabilities of the first online cpu to other shared cpus when policy shared type is CPUFREQ_SHARED_TYPE_ANY. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- The original RFC link, https://patchwork.kernel.org/patch/10299055/. This patch solves same issue as RFC above. Patch name is changed as code is too much different with RFC above. Remove extra init() per Viresh Kumar's comments and only handle CPPC CPUFREQ_SHARED_TYPE_ANY case. --- drivers/cpufreq/cppc_cpufreq.c | 12 +++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index 8f7b21a4d537..dc625a93a58e 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -164,8 +164,18 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) policy->cpuinfo.transition_latency = cppc_get_transition_latency(cpu_num); policy->shared_type = cpu->shared_type; - if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) + if (policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { + int i; + cpumask_copy(policy->cpus, cpu->shared_cpu_map); + + for_each_cpu(i, policy->cpus) { + if (i != policy->cpu) + memcpy(&all_cpu_data[i]->perf_caps, + &cpu->perf_caps, + sizeof(cpu->perf_caps)); + } + } else if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL) { /* Support only SW_ANY for now. */ pr_debug("Unsupported CPU co-ord type\n"); -- 1.8.3.1
[RFC PATCH] cpufreq: Calling init() of cpufreq_driver when policy inactive cpu online
When multiple cpus are related in one cpufreq policy, the first online cpu will be chosen by default to handle cpufreq operations. In a CPPC case, let's take two related cpus, cpu0 and cpu1 as an example. After system start, cpu0 is the first online cpu. Cpufreq policy will be allocated and init() in cpufreq_driver will be called to initialize cpu0's perf capabilities and policy parameters. When cpu1 is online, current code will not call init() in cpufreq_driver as policy has been allocated and activated by cpu0. So, cpu1's perf capabilities are not initialized (all 0s). When cpu0 is offline, policy->cpu will be shifted to cpu1. As cpu1's perf capabilities are 0s, speed change will not take effect when setting speed. This patch adds calling init() of cpufreq_driver when policy inactive cpu comes to online. Moreover, perf capabilities of all online cpus are initialized when init() is called. This patch is tested on CPPC enabled system. I am not sure it's influnce on other cpufreq_driver. So, this RFC is sent for comments. Cc: Wang Dongsheng Cc: Joey Zheng Signed-off-by: Shunyong Yang --- drivers/cpufreq/cppc_cpufreq.c | 45 ++ drivers/cpufreq/cpufreq.c | 18 - 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index a1c3025f9df7..f23a2007dd66 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c @@ -125,23 +125,12 @@ static void cppc_cpufreq_stop_cpu(struct cpufreq_policy *policy) cpu->perf_caps.lowest_perf, cpu_num, ret); } -static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) +static int cppc_cpufreq_update_policy(struct cpufreq_policy *policy, + struct cppc_cpudata *cpu) { - struct cppc_cpudata *cpu; unsigned int cpu_num = policy->cpu; int ret = 0; - cpu = all_cpu_data[policy->cpu]; - - cpu->cpu = cpu_num; - ret = cppc_get_perf_caps(policy->cpu, &cpu->perf_caps); - - if (ret) { - pr_debug("Err reading CPU%d perf capabilities. ret:%d\n", - cpu_num, ret); - return ret; - } - cppc_dmi_max_khz = cppc_get_dmi_max_khz(); /* @@ -186,6 +175,36 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) return ret; } +static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) +{ + struct cppc_cpudata *cpu; + unsigned int cpu_num; + int ret = 0; + + for_each_cpu(cpu_num, policy->cpus) { + cpu = all_cpu_data[cpu_num]; + + cpu->cpu = cpu_num; + ret = cppc_get_perf_caps(cpu_num, &cpu->perf_caps); + if (ret) { + pr_debug("Err reading CPU%d perf capabilities. ret:%d\n", + cpu_num, ret); + return ret; + } + + if (policy->cpu == cpu_num) { + ret = cppc_cpufreq_update_policy(policy, cpu); + if (ret) { + pr_debug("Err update CPU%d perf capabilities. ret:%d\n", + cpu_num, ret); + return ret; + } + } + } + + return ret; +} + static struct cpufreq_driver cppc_cpufreq_driver = { .flags = CPUFREQ_CONST_LOOPS, .verify = cppc_verify_policy, diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 239063fb6afc..3317c5e55e7f 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1192,8 +1192,24 @@ static int cpufreq_online(unsigned int cpu) policy = per_cpu(cpufreq_cpu_data, cpu); if (policy) { WARN_ON(!cpumask_test_cpu(cpu, policy->related_cpus)); - if (!policy_is_inactive(policy)) + if (!policy_is_inactive(policy)) { + /* +* Parameters of policy inactive CPU should be +* initialized here to make cpufreq work correctly +* when policy active CPU is switched to offline. +* When initialization failed, goto out_destroy_policy +* to destroy. +*/ + if (cpu != policy->cpu) { + ret = cpufreq_driver->init(policy); + if (ret) { + pr_debug("inactive cpu initialization failed\n"); + goto out_destroy_policy; + } + } + return cpufreq_add_poli
[PATCH] vfio-mdev/samples: change RDI interrupt condition
When FIFO mode is enabled, the receive data available interrupt (UART_IIR_RDI in code) should be triggered when the number of data in FIFO is equal or larger than interrupt trigger level. This patch changes the trigger level check to ensure multiple bytes received from upper layer can trigger RDI interrupt correctly. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- samples/vfio-mdev/mtty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/vfio-mdev/mtty.c b/samples/vfio-mdev/mtty.c index 09f255bdf3ac..7abb79d8313d 100644 --- a/samples/vfio-mdev/mtty.c +++ b/samples/vfio-mdev/mtty.c @@ -534,7 +534,7 @@ static void handle_bar_read(unsigned int index, struct mdev_state *mdev_state, /* Interrupt priority 2: Fifo trigger level reached */ if ((ier & UART_IER_RDI) && - (mdev_state->s[index].rxtx.count == + (mdev_state->s[index].rxtx.count >= mdev_state->s[index].intr_trigger_level)) *buf |= UART_IIR_RDI; -- 1.8.3.1
[RFC PATCH] KVM: arm/arm64: vgic: change condition for level interrupt resampling
When resampling irqfds is enabled, level interrupt should be de-asserted when resampling happens. On page 4-47 of GIC v3 specification IHI0069D, it said, "When the PE acknowledges an SGI, a PPI, or an SPI at the CPU interface, the IRI changes the status of the interrupt to active and pending if: • It is an edge-triggered interrupt, and another edge has been detected since the interrupt was acknowledged. • It is a level-sensitive interrupt, and the level has not been deasserted since the interrupt was acknowledged." GIC v2 specification IHI0048B.b has similar description on page 3-42 for state machine transition. When some VFIO device, like mtty(8250 VFIO mdev emulation driver in samples/vfio-mdev) triggers a level interrupt, the status transition in LR is pending-->active-->active and pending. Then it will wait resampling to de-assert the interrupt. Current design of lr_signals_eoi_mi() will return false if state in LR is not invalid(Inactive). It causes resampling will not happen in mtty case. This will cause interrupt fired continuously to guest even 8250 IIR has no interrupt. When 8250's interrupt is configured in shared mode, it will pass interrupt to other drivers to handle. However, there is no other driver involved. Then, a "nobody cared" kernel complaint occurs. / # cat /dev/ttyS0 [4.826836] random: crng init done [6.373620] irq 41: nobody cared (try booting with the "irqpoll" option) [6.376414] CPU: 0 PID: 1307 Comm: cat Not tainted 4.16.0-rc4 #4 [6.378927] Hardware name: linux,dummy-virt (DT) [6.380876] Call trace: [6.381937] dump_backtrace+0x0/0x180 [6.383495] show_stack+0x14/0x1c [6.384902] dump_stack+0x90/0xb4 [6.386312] __report_bad_irq+0x38/0xe0 [6.387944] note_interrupt+0x1f4/0x2b8 [6.389568] handle_irq_event_percpu+0x54/0x7c [6.391433] handle_irq_event+0x44/0x74 [6.393056] handle_fasteoi_irq+0x9c/0x154 [6.394784] generic_handle_irq+0x24/0x38 [6.396483] __handle_domain_irq+0x60/0xb4 [6.398207] gic_handle_irq+0x98/0x1b0 [6.399796] el1_irq+0xb0/0x128 [6.401138] _raw_spin_unlock_irqrestore+0x18/0x40 [6.403149] __setup_irq+0x41c/0x678 [6.404669] request_threaded_irq+0xe0/0x190 [6.406474] univ8250_setup_irq+0x208/0x234 [6.408250] serial8250_do_startup+0x1b4/0x754 [6.410123] serial8250_startup+0x20/0x28 [6.411826] uart_startup.part.21+0x78/0x144 [6.413633] uart_port_activate+0x50/0x68 [6.415328] tty_port_open+0x84/0xd4 [6.416851] uart_open+0x34/0x44 [6.418229] tty_open+0xec/0x3c8 [6.419610] chrdev_open+0xb0/0x198 [6.421093] do_dentry_open+0x200/0x310 [6.422714] vfs_open+0x54/0x84 [6.424054] path_openat+0x2dc/0xf04 [6.425569] do_filp_open+0x68/0xd8 [6.427044] do_sys_open+0x16c/0x224 [6.428563] SyS_openat+0x10/0x18 [6.429972] el0_svc_naked+0x30/0x34 [6.431494] handlers: [6.432479] [<0e9fb4bb>] serial8250_interrupt [6.434597] Disabling IRQ #41 This patch changes the lr state condition in lr_signals_eoi_mi() from invalid(Inactive) to active and pending to avoid this. I am not sure about the original design of the condition of invalid(active). So, This RFC is sent out for comments. Cc: Joey Zheng Signed-off-by: Shunyong Yang --- virt/kvm/arm/vgic/vgic-v2.c | 4 ++-- virt/kvm/arm/vgic/vgic-v3.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c index e9d840a75e7b..740ee9a5f551 100644 --- a/virt/kvm/arm/vgic/vgic-v2.c +++ b/virt/kvm/arm/vgic/vgic-v2.c @@ -46,8 +46,8 @@ void vgic_v2_set_underflow(struct kvm_vcpu *vcpu) static bool lr_signals_eoi_mi(u32 lr_val) { - return !(lr_val & GICH_LR_STATE) && (lr_val & GICH_LR_EOI) && - !(lr_val & GICH_LR_HW); + return !((lr_val & GICH_LR_STATE) ^ GICH_LR_STATE) && + (lr_val & GICH_LR_EOI) && !(lr_val & GICH_LR_HW); } /* diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c index 6b329414e57a..43111bba7af9 100644 --- a/virt/kvm/arm/vgic/vgic-v3.c +++ b/virt/kvm/arm/vgic/vgic-v3.c @@ -35,8 +35,8 @@ void vgic_v3_set_underflow(struct kvm_vcpu *vcpu) static bool lr_signals_eoi_mi(u64 lr_val) { - return !(lr_val & ICH_LR_STATE) && (lr_val & ICH_LR_EOI) && - !(lr_val & ICH_LR_HW); + return !((lr_val & ICH_LR_STATE) ^ ICH_LR_STATE) && + (lr_val & ICH_LR_EOI) && !(lr_val & ICH_LR_HW); } void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu) -- 1.8.3.1
[PATCH] vsprintf: replace space with readable '=' before crng is ready
Before crng is ready, output of "%p" composes of "(ptrval)" and left padding spaces for alignment as no random address can be generated. This seems a little strange when default string width is larger than strlen("(ptrval)"). For example, when irq domain names are built with "%p", the nodes under /sys/kernel/debug/irq/domains like this on AArch64 system, [root@y irq]# ls domains/ default irqchip@(ptrval)-2 irqchip@(ptrval)-4 \_SB_.TCS0.QIC1 \_SB_.TCS0.QIC3 irqchip@(ptrval) irqchip@(ptrval)-3 \_SB_.TCS0.QIC0 \_SB_.TCS0.QIC2 The name "irqchip@(ptrval)-2" is not so readable in console output. This patch replaces space with readable "=" when output needs padding. Following is the output after applying the patch, [root@y domains]# ls default irqchip@(ptrval)-2 irqchip@(ptrval)-4 \_SB_.TCS0.QIC1 \_SB_.TCS0.QIC3 irqchip@(ptrval) irqchip@(ptrval)-3 \_SB_.TCS0.QIC0 \_SB_.TCS0.QIC2 There is same problem in some subsystem's dmesg output. Moreover, someone may call "%p" in a similar case. In addition, the timing of crng initialization done may vary on different system. So, the change is made in vsprintf.c. Link: https://patchwork.kernel.org/patch/10185199/ Cc: Andy Shevchenko Cc: Joey Zheng Suggested-by: Rasmus Villemoes Signed-off-by: Shunyong Yang --- lib/vsprintf.c | 18 +- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 77ee6ced11b1..9fdc8376752a 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1700,9 +1700,25 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) const int default_width = 2 * sizeof(ptr); if (unlikely(!have_filled_random_ptr_key)) { + char *ptrval_str = "(ptrval)"; + char str[default_width + 1]; + int len = strlen(ptrval_str); + + if (default_width > len) { + int pos; + + pos = (default_width - len) / 2; + memset(str, '=', default_width); + memcpy(str + pos + 1, ptrval_str + 1, len - 2); + str[0] = '('; + str[default_width - 1] = ')'; + str[default_width] = 0; + ptrval_str = str; + } + spec.field_width = default_width; /* string length must be less than default_width */ - return string(buf, end, "(ptrval)", spec); + return string(buf, end, ptrval_str, spec); } #ifdef CONFIG_64BIT -- 1.8.3.1