From: Sasha Levin Date: Sat, 9 Dec 2023 02:36:59 +0000 (-0500) Subject: Fixes for 5.4 X-Git-Tag: v6.6.6~51 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f12c6abc6ea9e96496a67f5b10a4ffda1ec560a6;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 5.4 Signed-off-by: Sasha Levin --- diff --git a/queue-5.4/acpi-iort-make-iort_get_device_domain-irq-domain-agn.patch b/queue-5.4/acpi-iort-make-iort_get_device_domain-irq-domain-agn.patch new file mode 100644 index 00000000000..6a178ec85dd --- /dev/null +++ b/queue-5.4/acpi-iort-make-iort_get_device_domain-irq-domain-agn.patch @@ -0,0 +1,137 @@ +From 923ff2cab90e59991db251dfcf3029e878f6c8f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2020 09:20:03 +0100 +Subject: ACPI/IORT: Make iort_get_device_domain IRQ domain agnostic + +From: Lorenzo Pieralisi + +[ Upstream commit d1718a1b7a86743b9c517bf9521695ba909c734f ] + +iort_get_device_domain() is PCI specific but it need not be, +since it can be used to retrieve IRQ domain nexus of any kind +by adding an irq_domain_bus_token input to it. + +Make it PCI agnostic by also renaming the requestor ID input +to a more generic ID name. + +Signed-off-by: Lorenzo Pieralisi +Acked-by: Bjorn Helgaas # pci/msi.c +Cc: Will Deacon +Cc: Hanjun Guo +Cc: Bjorn Helgaas +Cc: Sudeep Holla +Cc: Robin Murphy +Cc: "Rafael J. Wysocki" +Link: https://lore.kernel.org/r/20200619082013.13661-3-lorenzo.pieralisi@arm.com +Signed-off-by: Catalin Marinas +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/acpi/arm64/iort.c | 14 +++++++------- + drivers/pci/msi.c | 3 ++- + include/linux/acpi_iort.h | 7 ++++--- + 3 files changed, 13 insertions(+), 11 deletions(-) + +diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c +index 09eb170f26d27..0428e74b6002b 100644 +--- a/drivers/acpi/arm64/iort.c ++++ b/drivers/acpi/arm64/iort.c +@@ -503,7 +503,6 @@ static struct acpi_iort_node *iort_find_dev_node(struct device *dev) + node = iort_get_iort_node(dev->fwnode); + if (node) + return node; +- + /* + * if not, then it should be a platform device defined in + * DSDT/SSDT (with Named Component node in IORT) +@@ -594,13 +593,13 @@ static int __maybe_unused iort_find_its_base(u32 its_id, phys_addr_t *base) + /** + * iort_dev_find_its_id() - Find the ITS identifier for a device + * @dev: The device. +- * @req_id: Device's requester ID ++ * @id: Device's ID + * @idx: Index of the ITS identifier list. + * @its_id: ITS identifier. + * + * Returns: 0 on success, appropriate error value otherwise + */ +-static int iort_dev_find_its_id(struct device *dev, u32 req_id, ++static int iort_dev_find_its_id(struct device *dev, u32 id, + unsigned int idx, int *its_id) + { + struct acpi_iort_its_group *its; +@@ -610,7 +609,7 @@ static int iort_dev_find_its_id(struct device *dev, u32 req_id, + if (!node) + return -ENXIO; + +- node = iort_node_map_id(node, req_id, NULL, IORT_MSI_TYPE); ++ node = iort_node_map_id(node, id, NULL, IORT_MSI_TYPE); + if (!node) + return -ENXIO; + +@@ -633,19 +632,20 @@ static int iort_dev_find_its_id(struct device *dev, u32 req_id, + * + * Returns: the MSI domain for this device, NULL otherwise + */ +-struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id) ++struct irq_domain *iort_get_device_domain(struct device *dev, u32 id, ++ enum irq_domain_bus_token bus_token) + { + struct fwnode_handle *handle; + int its_id; + +- if (iort_dev_find_its_id(dev, req_id, 0, &its_id)) ++ if (iort_dev_find_its_id(dev, id, 0, &its_id)) + return NULL; + + handle = iort_find_domain_token(its_id); + if (!handle) + return NULL; + +- return irq_find_matching_fwnode(handle, DOMAIN_BUS_PCI_MSI); ++ return irq_find_matching_fwnode(handle, bus_token); + } + + static void iort_set_device_domain(struct device *dev, +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 715c85d4e688d..6336316c37932 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -1626,7 +1626,8 @@ struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev) + pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid); + dom = of_msi_map_get_device_domain(&pdev->dev, rid); + if (!dom) +- dom = iort_get_device_domain(&pdev->dev, rid); ++ dom = iort_get_device_domain(&pdev->dev, rid, ++ DOMAIN_BUS_PCI_MSI); + return dom; + } + #endif /* CONFIG_PCI_MSI_IRQ_DOMAIN */ +diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h +index 64f700254ca0f..6bf603a4e6d2c 100644 +--- a/include/linux/acpi_iort.h ++++ b/include/linux/acpi_iort.h +@@ -30,7 +30,8 @@ struct fwnode_handle *iort_find_domain_token(int trans_id); + #ifdef CONFIG_ACPI_IORT + void acpi_iort_init(void); + u32 iort_msi_map_rid(struct device *dev, u32 req_id); +-struct irq_domain *iort_get_device_domain(struct device *dev, u32 req_id); ++struct irq_domain *iort_get_device_domain(struct device *dev, u32 id, ++ enum irq_domain_bus_token bus_token); + void acpi_configure_pmsi_domain(struct device *dev); + int iort_pmsi_get_dev_id(struct device *dev, u32 *dev_id); + /* IOMMU interface */ +@@ -41,8 +42,8 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head); + static inline void acpi_iort_init(void) { } + static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id) + { return req_id; } +-static inline struct irq_domain *iort_get_device_domain(struct device *dev, +- u32 req_id) ++static inline struct irq_domain *iort_get_device_domain( ++ struct device *dev, u32 id, enum irq_domain_bus_token bus_token) + { return NULL; } + static inline void acpi_configure_pmsi_domain(struct device *dev) { } + /* IOMMU interface */ +-- +2.42.0 + diff --git a/queue-5.4/acpi-iort-make-iort_msi_map_rid-pci-agnostic.patch b/queue-5.4/acpi-iort-make-iort_msi_map_rid-pci-agnostic.patch new file mode 100644 index 00000000000..f1dc7e07a8f --- /dev/null +++ b/queue-5.4/acpi-iort-make-iort_msi_map_rid-pci-agnostic.patch @@ -0,0 +1,105 @@ +From bba4d6d770955f88463130f210fbd3a408693f27 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2020 09:20:04 +0100 +Subject: ACPI/IORT: Make iort_msi_map_rid() PCI agnostic + +From: Lorenzo Pieralisi + +[ Upstream commit 39c3cf566ceafa7c1ae331a5f26fbb685d670001 ] + +There is nothing PCI specific in iort_msi_map_rid(). + +Rename the function using a bus protocol agnostic name, +iort_msi_map_id(), and convert current callers to it. + +Signed-off-by: Lorenzo Pieralisi +Acked-by: Bjorn Helgaas +Cc: Will Deacon +Cc: Hanjun Guo +Cc: Bjorn Helgaas +Cc: Sudeep Holla +Cc: Robin Murphy +Cc: "Rafael J. Wysocki" +Link: https://lore.kernel.org/r/20200619082013.13661-4-lorenzo.pieralisi@arm.com +Signed-off-by: Catalin Marinas +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/acpi/arm64/iort.c | 12 ++++++------ + drivers/pci/msi.c | 2 +- + include/linux/acpi_iort.h | 6 +++--- + 3 files changed, 10 insertions(+), 10 deletions(-) + +diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c +index 0428e74b6002b..13ae2ce9f50dd 100644 +--- a/drivers/acpi/arm64/iort.c ++++ b/drivers/acpi/arm64/iort.c +@@ -521,22 +521,22 @@ static struct acpi_iort_node *iort_find_dev_node(struct device *dev) + } + + /** +- * iort_msi_map_rid() - Map a MSI requester ID for a device ++ * iort_msi_map_id() - Map a MSI input ID for a device + * @dev: The device for which the mapping is to be done. +- * @req_id: The device requester ID. ++ * @input_id: The device input ID. + * +- * Returns: mapped MSI RID on success, input requester ID otherwise ++ * Returns: mapped MSI ID on success, input ID otherwise + */ +-u32 iort_msi_map_rid(struct device *dev, u32 req_id) ++u32 iort_msi_map_id(struct device *dev, u32 input_id) + { + struct acpi_iort_node *node; + u32 dev_id; + + node = iort_find_dev_node(dev); + if (!node) +- return req_id; ++ return input_id; + +- iort_node_map_id(node, req_id, &dev_id, IORT_MSI_TYPE); ++ iort_node_map_id(node, input_id, &dev_id, IORT_MSI_TYPE); + return dev_id; + } + +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 6336316c37932..cc863cdd5cc74 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -1604,7 +1604,7 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev) + + of_node = irq_domain_get_of_node(domain); + rid = of_node ? of_msi_map_rid(&pdev->dev, of_node, rid) : +- iort_msi_map_rid(&pdev->dev, rid); ++ iort_msi_map_id(&pdev->dev, rid); + + return rid; + } +diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h +index 6bf603a4e6d2c..cce2cbd4f3018 100644 +--- a/include/linux/acpi_iort.h ++++ b/include/linux/acpi_iort.h +@@ -29,7 +29,7 @@ void iort_deregister_domain_token(int trans_id); + struct fwnode_handle *iort_find_domain_token(int trans_id); + #ifdef CONFIG_ACPI_IORT + void acpi_iort_init(void); +-u32 iort_msi_map_rid(struct device *dev, u32 req_id); ++u32 iort_msi_map_id(struct device *dev, u32 id); + struct irq_domain *iort_get_device_domain(struct device *dev, u32 id, + enum irq_domain_bus_token bus_token); + void acpi_configure_pmsi_domain(struct device *dev); +@@ -40,8 +40,8 @@ const struct iommu_ops *iort_iommu_configure(struct device *dev); + int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head); + #else + static inline void acpi_iort_init(void) { } +-static inline u32 iort_msi_map_rid(struct device *dev, u32 req_id) +-{ return req_id; } ++static inline u32 iort_msi_map_id(struct device *dev, u32 id) ++{ return id; } + static inline struct irq_domain *iort_get_device_domain( + struct device *dev, u32 id, enum irq_domain_bus_token bus_token) + { return NULL; } +-- +2.42.0 + diff --git a/queue-5.4/arcnet-restoring-support-for-multiple-sohard-arcnet-.patch b/queue-5.4/arcnet-restoring-support-for-multiple-sohard-arcnet-.patch new file mode 100644 index 00000000000..3844bdf54bb --- /dev/null +++ b/queue-5.4/arcnet-restoring-support-for-multiple-sohard-arcnet-.patch @@ -0,0 +1,216 @@ +From 10654aa2b57ab75495499ab3d2c94a9b2a763f53 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Nov 2023 12:35:03 +0100 +Subject: arcnet: restoring support for multiple Sohard Arcnet cards + +From: Thomas Reichinger + +[ Upstream commit 6b17a597fc2f13aaaa0a2780eb7edb9ae7ac9aea ] + +Probe of Sohard Arcnet cards fails, +if 2 or more cards are installed in a system. +See kernel log: +[ 2.759203] arcnet: arcnet loaded +[ 2.763648] arcnet:com20020: COM20020 chipset support (by David Woodhouse et al.) +[ 2.770585] arcnet:com20020_pci: COM20020 PCI support +[ 2.772295] com20020 0000:02:00.0: enabling device (0000 -> 0003) +[ 2.772354] (unnamed net_device) (uninitialized): PLX-PCI Controls +... +[ 3.071301] com20020 0000:02:00.0 arc0-0 (uninitialized): PCI COM20020: station FFh found at F080h, IRQ 101. +[ 3.071305] com20020 0000:02:00.0 arc0-0 (uninitialized): Using CKP 64 - data rate 2.5 Mb/s +[ 3.071534] com20020 0000:07:00.0: enabling device (0000 -> 0003) +[ 3.071581] (unnamed net_device) (uninitialized): PLX-PCI Controls +... +[ 3.369501] com20020 0000:07:00.0: Led pci:green:tx:0-0 renamed to pci:green:tx:0-0_1 due to name collision +[ 3.369535] com20020 0000:07:00.0: Led pci:red:recon:0-0 renamed to pci:red:recon:0-0_1 due to name collision +[ 3.370586] com20020 0000:07:00.0 arc0-0 (uninitialized): PCI COM20020: station E1h found at C000h, IRQ 35. +[ 3.370589] com20020 0000:07:00.0 arc0-0 (uninitialized): Using CKP 64 - data rate 2.5 Mb/s +[ 3.370608] com20020: probe of 0000:07:00.0 failed with error -5 + +commit 5ef216c1f848 ("arcnet: com20020-pci: add rotary index support") +changes the device name of all COM20020 based PCI cards, +even if only some cards support this: + snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i); + +The error happens because all Sohard Arcnet cards would be called arc0-0, +since the Sohard Arcnet cards don't have a PLX rotary coder. +I.e. EAE Arcnet cards have a PLX rotary coder, +which sets the first decimal, ensuring unique devices names. + +This patch adds two new card feature flags to indicate +which cards support LEDs and the PLX rotary coder. +For EAE based cards the names still depend on the PLX rotary coder +(untested, since missing EAE hardware). +For Sohard based cards, this patch will result in devices +being called arc0, arc1, ... (tested). + +Signed-off-by: Thomas Reichinger +Fixes: 5ef216c1f848 ("arcnet: com20020-pci: add rotary index support") +Link: https://lore.kernel.org/r/20231130113503.6812-1-thomas.reichinger@sohard.de +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/arcnet/arcdevice.h | 2 + + drivers/net/arcnet/com20020-pci.c | 89 ++++++++++++++++--------------- + 2 files changed, 48 insertions(+), 43 deletions(-) + +diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h +index 7178f5349fa8f..7b783ee918346 100644 +--- a/drivers/net/arcnet/arcdevice.h ++++ b/drivers/net/arcnet/arcdevice.h +@@ -186,6 +186,8 @@ do { \ + #define ARC_IS_5MBIT 1 /* card default speed is 5MBit */ + #define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit, + but default is 2.5MBit. */ ++#define ARC_HAS_LED 4 /* card has software controlled LEDs */ ++#define ARC_HAS_ROTARY 8 /* card has rotary encoder */ + + /* information needed to define an encapsulation driver */ + struct ArcProto { +diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c +index 28dccbc0e8d8f..9d9e4200064f9 100644 +--- a/drivers/net/arcnet/com20020-pci.c ++++ b/drivers/net/arcnet/com20020-pci.c +@@ -213,12 +213,13 @@ static int com20020pci_probe(struct pci_dev *pdev, + if (!strncmp(ci->name, "EAE PLX-PCI FB2", 15)) + lp->backplane = 1; + +- /* Get the dev_id from the PLX rotary coder */ +- if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15)) +- dev_id_mask = 0x3; +- dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask; +- +- snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i); ++ if (ci->flags & ARC_HAS_ROTARY) { ++ /* Get the dev_id from the PLX rotary coder */ ++ if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15)) ++ dev_id_mask = 0x3; ++ dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask; ++ snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i); ++ } + + if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) { + pr_err("IO address %Xh is empty!\n", ioaddr); +@@ -230,6 +231,10 @@ static int com20020pci_probe(struct pci_dev *pdev, + goto err_free_arcdev; + } + ++ ret = com20020_found(dev, IRQF_SHARED); ++ if (ret) ++ goto err_free_arcdev; ++ + card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev), + GFP_KERNEL); + if (!card) { +@@ -239,41 +244,39 @@ static int com20020pci_probe(struct pci_dev *pdev, + + card->index = i; + card->pci_priv = priv; +- card->tx_led.brightness_set = led_tx_set; +- card->tx_led.default_trigger = devm_kasprintf(&pdev->dev, +- GFP_KERNEL, "arc%d-%d-tx", +- dev->dev_id, i); +- card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, +- "pci:green:tx:%d-%d", +- dev->dev_id, i); +- +- card->tx_led.dev = &dev->dev; +- card->recon_led.brightness_set = led_recon_set; +- card->recon_led.default_trigger = devm_kasprintf(&pdev->dev, +- GFP_KERNEL, "arc%d-%d-recon", +- dev->dev_id, i); +- card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, +- "pci:red:recon:%d-%d", +- dev->dev_id, i); +- card->recon_led.dev = &dev->dev; +- card->dev = dev; +- +- ret = devm_led_classdev_register(&pdev->dev, &card->tx_led); +- if (ret) +- goto err_free_arcdev; + +- ret = devm_led_classdev_register(&pdev->dev, &card->recon_led); +- if (ret) +- goto err_free_arcdev; +- +- dev_set_drvdata(&dev->dev, card); +- +- ret = com20020_found(dev, IRQF_SHARED); +- if (ret) +- goto err_free_arcdev; +- +- devm_arcnet_led_init(dev, dev->dev_id, i); ++ if (ci->flags & ARC_HAS_LED) { ++ card->tx_led.brightness_set = led_tx_set; ++ card->tx_led.default_trigger = devm_kasprintf(&pdev->dev, ++ GFP_KERNEL, "arc%d-%d-tx", ++ dev->dev_id, i); ++ card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "pci:green:tx:%d-%d", ++ dev->dev_id, i); ++ ++ card->tx_led.dev = &dev->dev; ++ card->recon_led.brightness_set = led_recon_set; ++ card->recon_led.default_trigger = devm_kasprintf(&pdev->dev, ++ GFP_KERNEL, "arc%d-%d-recon", ++ dev->dev_id, i); ++ card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "pci:red:recon:%d-%d", ++ dev->dev_id, i); ++ card->recon_led.dev = &dev->dev; ++ ++ ret = devm_led_classdev_register(&pdev->dev, &card->tx_led); ++ if (ret) ++ goto err_free_arcdev; ++ ++ ret = devm_led_classdev_register(&pdev->dev, &card->recon_led); ++ if (ret) ++ goto err_free_arcdev; ++ ++ dev_set_drvdata(&dev->dev, card); ++ devm_arcnet_led_init(dev, dev->dev_id, i); ++ } + ++ card->dev = dev; + list_add(&card->list, &priv->list_dev); + continue; + +@@ -329,7 +332,7 @@ static struct com20020_pci_card_info card_info_5mbit = { + }; + + static struct com20020_pci_card_info card_info_sohard = { +- .name = "PLX-PCI", ++ .name = "SOHARD SH ARC-PCI", + .devcount = 1, + /* SOHARD needs PCI base addr 4 */ + .chan_map_tbl = { +@@ -364,7 +367,7 @@ static struct com20020_pci_card_info card_info_eae_arc1 = { + }, + }, + .rotary = 0x0, +- .flags = ARC_CAN_10MBIT, ++ .flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT, + }; + + static struct com20020_pci_card_info card_info_eae_ma1 = { +@@ -396,7 +399,7 @@ static struct com20020_pci_card_info card_info_eae_ma1 = { + }, + }, + .rotary = 0x0, +- .flags = ARC_CAN_10MBIT, ++ .flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT, + }; + + static struct com20020_pci_card_info card_info_eae_fb2 = { +@@ -421,7 +424,7 @@ static struct com20020_pci_card_info card_info_eae_fb2 = { + }, + }, + .rotary = 0x0, +- .flags = ARC_CAN_10MBIT, ++ .flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT, + }; + + static const struct pci_device_id com20020pci_id_table[] = { +-- +2.42.0 + diff --git a/queue-5.4/bpf-sockmap-updating-the-sg-structure-should-also-up.patch b/queue-5.4/bpf-sockmap-updating-the-sg-structure-should-also-up.patch new file mode 100644 index 00000000000..d4a2962e9da --- /dev/null +++ b/queue-5.4/bpf-sockmap-updating-the-sg-structure-should-also-up.patch @@ -0,0 +1,74 @@ +From f25918361336972575caf2fbee637ec22cb475a8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Dec 2023 15:27:06 -0800 +Subject: bpf: sockmap, updating the sg structure should also update curr + +From: John Fastabend + +[ Upstream commit bb9aefde5bbaf6c168c77ba635c155b4980c2287 ] + +Curr pointer should be updated when the sg structure is shifted. + +Fixes: 7246d8ed4dcce ("bpf: helper to pop data from messages") +Signed-off-by: John Fastabend +Link: https://lore.kernel.org/r/20231206232706.374377-3-john.fastabend@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/filter.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/net/core/filter.c b/net/core/filter.c +index d866e1c5970cc..3c4dcdc7217e0 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2219,6 +2219,22 @@ BPF_CALL_2(bpf_msg_cork_bytes, struct sk_msg *, msg, u32, bytes) + return 0; + } + ++static void sk_msg_reset_curr(struct sk_msg *msg) ++{ ++ u32 i = msg->sg.start; ++ u32 len = 0; ++ ++ do { ++ len += sk_msg_elem(msg, i)->length; ++ sk_msg_iter_var_next(i); ++ if (len >= msg->sg.size) ++ break; ++ } while (i != msg->sg.end); ++ ++ msg->sg.curr = i; ++ msg->sg.copybreak = 0; ++} ++ + static const struct bpf_func_proto bpf_msg_cork_bytes_proto = { + .func = bpf_msg_cork_bytes, + .gpl_only = false, +@@ -2338,6 +2354,7 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_msg *, msg, u32, start, + msg->sg.end - shift + NR_MSG_FRAG_IDS : + msg->sg.end - shift; + out: ++ sk_msg_reset_curr(msg); + msg->data = sg_virt(&msg->sg.data[first_sge]) + start - offset; + msg->data_end = msg->data + bytes; + return 0; +@@ -2471,6 +2488,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start, + msg->sg.data[new] = rsge; + } + ++ sk_msg_reset_curr(msg); + sk_msg_compute_data_pointers(msg); + return 0; + } +@@ -2642,6 +2660,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, + + sk_mem_uncharge(msg->sk, len - pop); + msg->sg.size -= (len - pop); ++ sk_msg_reset_curr(msg); + sk_msg_compute_data_pointers(msg); + return 0; + } +-- +2.42.0 + diff --git a/queue-5.4/hv_netvsc-rndis_filter-needs-to-select-nls.patch b/queue-5.4/hv_netvsc-rndis_filter-needs-to-select-nls.patch new file mode 100644 index 00000000000..76f8da41973 --- /dev/null +++ b/queue-5.4/hv_netvsc-rndis_filter-needs-to-select-nls.patch @@ -0,0 +1,44 @@ +From 25c4f058b04a5cfe78869fb292c86b1ee324be73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Nov 2023 21:58:53 -0800 +Subject: hv_netvsc: rndis_filter needs to select NLS + +From: Randy Dunlap + +[ Upstream commit 6c89f49964375c904cea33c0247467873f4daf2c ] + +rndis_filter uses utf8s_to_utf16s() which is provided by setting +NLS, so select NLS to fix the build error: + +ERROR: modpost: "utf8s_to_utf16s" [drivers/net/hyperv/hv_netvsc.ko] undefined! + +Fixes: 1ce09e899d28 ("hyperv: Add support for setting MAC from within guests") +Signed-off-by: Randy Dunlap +Cc: Haiyang Zhang +Cc: K. Y. Srinivasan +Cc: Wei Liu +Cc: Dexuan Cui +Reviewed-by: Simon Horman +Tested-by: Simon Horman # build-tested +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20231130055853.19069-1-rdunlap@infradead.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/hyperv/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/hyperv/Kconfig b/drivers/net/hyperv/Kconfig +index ca7bf7f897d36..c8cbd85adcf99 100644 +--- a/drivers/net/hyperv/Kconfig ++++ b/drivers/net/hyperv/Kconfig +@@ -3,5 +3,6 @@ config HYPERV_NET + tristate "Microsoft Hyper-V virtual network driver" + depends on HYPERV + select UCS2_STRING ++ select NLS + help + Select this option to enable the Hyper-V virtual network driver. +-- +2.42.0 + diff --git a/queue-5.4/ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch b/queue-5.4/ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch new file mode 100644 index 00000000000..296324250a9 --- /dev/null +++ b/queue-5.4/ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch @@ -0,0 +1,58 @@ +From 3eb8cb022ac5e64bf5a872ede5079c0b753f355f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Dec 2023 01:14:41 +0900 +Subject: ipv4: ip_gre: Avoid skb_pull() failure in ipgre_xmit() + +From: Shigeru Yoshida + +[ Upstream commit 80d875cfc9d3711a029f234ef7d680db79e8fa4b ] + +In ipgre_xmit(), skb_pull() may fail even if pskb_inet_may_pull() returns +true. For example, applications can use PF_PACKET to create a malformed +packet with no IP header. This type of packet causes a problem such as +uninit-value access. + +This patch ensures that skb_pull() can pull the required size by checking +the skb with pskb_network_may_pull() before skb_pull(). + +Fixes: c54419321455 ("GRE: Refactor GRE tunneling code.") +Signed-off-by: Shigeru Yoshida +Reviewed-by: Eric Dumazet +Reviewed-by: Suman Ghosh +Link: https://lore.kernel.org/r/20231202161441.221135-1-syoshida@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_gre.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index f8f008344273e..db48dec61f305 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -607,15 +607,18 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + } + + if (dev->header_ops) { ++ int pull_len = tunnel->hlen + sizeof(struct iphdr); ++ + if (skb_cow_head(skb, 0)) + goto free_skb; + + tnl_params = (const struct iphdr *)skb->data; + +- /* Pull skb since ip_tunnel_xmit() needs skb->data pointing +- * to gre header. +- */ +- skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); ++ if (!pskb_network_may_pull(skb, pull_len)) ++ goto free_skb; ++ ++ /* ip_tunnel_xmit() needs skb->data pointing to gre header. */ ++ skb_pull(skb, pull_len); + skb_reset_mac_header(skb); + + if (skb->ip_summed == CHECKSUM_PARTIAL && +-- +2.42.0 + diff --git a/queue-5.4/ipv6-fix-potential-null-deref-in-fib6_add.patch b/queue-5.4/ipv6-fix-potential-null-deref-in-fib6_add.patch new file mode 100644 index 00000000000..db0c53bf883 --- /dev/null +++ b/queue-5.4/ipv6-fix-potential-null-deref-in-fib6_add.patch @@ -0,0 +1,79 @@ +From 2712197797e463a75a003b549c3c252c3a47e073 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Nov 2023 16:06:30 +0000 +Subject: ipv6: fix potential NULL deref in fib6_add() + +From: Eric Dumazet + +[ Upstream commit 75475bb51e78a3f54ad2f69380f2a1c985e85f2d ] + +If fib6_find_prefix() returns NULL, we should silently fallback +using fib6_null_entry regardless of RT6_DEBUG value. + +syzbot reported: + +WARNING: CPU: 0 PID: 5477 at net/ipv6/ip6_fib.c:1516 fib6_add+0x310d/0x3fa0 net/ipv6/ip6_fib.c:1516 +Modules linked in: +CPU: 0 PID: 5477 Comm: syz-executor.0 Not tainted 6.7.0-rc2-syzkaller-00029-g9b6de136b5f0 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/10/2023 +RIP: 0010:fib6_add+0x310d/0x3fa0 net/ipv6/ip6_fib.c:1516 +Code: 00 48 8b 54 24 68 e8 42 22 00 00 48 85 c0 74 14 49 89 c6 e8 d5 d3 c2 f7 eb 5d e8 ce d3 c2 f7 e9 ca 00 00 00 e8 c4 d3 c2 f7 90 <0f> 0b 90 48 b8 00 00 00 00 00 fc ff df 48 8b 4c 24 38 80 3c 01 00 +RSP: 0018:ffffc90005067740 EFLAGS: 00010293 +RAX: ffffffff89cba5bc RBX: ffffc90005067ab0 RCX: ffff88801a2e9dc0 +RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000000 +RBP: ffffc90005067980 R08: ffffffff89cbca85 R09: 1ffff110040d4b85 +R10: dffffc0000000000 R11: ffffed10040d4b86 R12: 00000000ffffffff +R13: 1ffff110051c3904 R14: ffff8880206a5c00 R15: ffff888028e1c820 +FS: 00007f763783c6c0(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f763783bff8 CR3: 000000007f74d000 CR4: 00000000003506f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + +__ip6_ins_rt net/ipv6/route.c:1303 [inline] +ip6_route_add+0x88/0x120 net/ipv6/route.c:3847 +ipv6_route_ioctl+0x525/0x7b0 net/ipv6/route.c:4467 +inet6_ioctl+0x21a/0x270 net/ipv6/af_inet6.c:575 +sock_do_ioctl+0x152/0x460 net/socket.c:1220 +sock_ioctl+0x615/0x8c0 net/socket.c:1339 +vfs_ioctl fs/ioctl.c:51 [inline] +__do_sys_ioctl fs/ioctl.c:871 [inline] +__se_sys_ioctl+0xf8/0x170 fs/ioctl.c:857 +do_syscall_x64 arch/x86/entry/common.c:51 [inline] +do_syscall_64+0x45/0x110 arch/x86/entry/common.c:82 + +Fixes: 7bbfe00e0252 ("ipv6: fix general protection fault in fib6_add()") +Reported-by: syzbot +Signed-off-by: Eric Dumazet +Cc: Wei Wang +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20231129160630.3509216-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_fib.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index ef55489651f87..d74a825c50f0c 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1433,13 +1433,9 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt, + if (!pn_leaf && !(pn->fn_flags & RTN_RTINFO)) { + pn_leaf = fib6_find_prefix(info->nl_net, table, + pn); +-#if RT6_DEBUG >= 2 +- if (!pn_leaf) { +- WARN_ON(!pn_leaf); ++ if (!pn_leaf) + pn_leaf = + info->nl_net->ipv6.fib6_null_entry; +- } +-#endif + fib6_info_hold(pn_leaf); + rcu_assign_pointer(pn->leaf, pn_leaf); + } +-- +2.42.0 + diff --git a/queue-5.4/net-arcnet-com20020-fix-error-handling.patch b/queue-5.4/net-arcnet-com20020-fix-error-handling.patch new file mode 100644 index 00000000000..4246d0beec6 --- /dev/null +++ b/queue-5.4/net-arcnet-com20020-fix-error-handling.patch @@ -0,0 +1,137 @@ +From c33a40189dcbd1ac546ce01ec12faf78bc6e8e0d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 14 Mar 2021 14:08:36 -0400 +Subject: net: arcnet: com20020 fix error handling + +From: Tong Zhang + +[ Upstream commit 6577b9a551aedb86bca6d4438c28386361845108 ] + +There are two issues when handling error case in com20020pci_probe() + +1. priv might be not initialized yet when calling com20020pci_remove() +from com20020pci_probe(), since the priv is set at the very last but it +can jump to error handling in the middle and priv remains NULL. +2. memory leak - the net device is allocated in alloc_arcdev but not +properly released if error happens in the middle of the big for loop + +[ 1.529110] BUG: kernel NULL pointer dereference, address: 0000000000000008 +[ 1.531447] RIP: 0010:com20020pci_remove+0x15/0x60 [com20020_pci] +[ 1.536805] Call Trace: +[ 1.536939] com20020pci_probe+0x3f2/0x48c [com20020_pci] +[ 1.537226] local_pci_probe+0x48/0x80 +[ 1.539918] com20020pci_init+0x3f/0x1000 [com20020_pci] + +Signed-off-by: Tong Zhang +Signed-off-by: David S. Miller +Stable-dep-of: 6b17a597fc2f ("arcnet: restoring support for multiple Sohard Arcnet cards") +Signed-off-by: Sasha Levin +--- + drivers/net/arcnet/com20020-pci.c | 34 +++++++++++++++++-------------- + 1 file changed, 19 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c +index b4f8798d8c509..28dccbc0e8d8f 100644 +--- a/drivers/net/arcnet/com20020-pci.c ++++ b/drivers/net/arcnet/com20020-pci.c +@@ -127,6 +127,8 @@ static int com20020pci_probe(struct pci_dev *pdev, + int i, ioaddr, ret; + struct resource *r; + ++ ret = 0; ++ + if (pci_enable_device(pdev)) + return -EIO; + +@@ -142,6 +144,8 @@ static int com20020pci_probe(struct pci_dev *pdev, + priv->ci = ci; + mm = &ci->misc_map; + ++ pci_set_drvdata(pdev, priv); ++ + INIT_LIST_HEAD(&priv->list_dev); + + if (mm->size) { +@@ -164,7 +168,7 @@ static int com20020pci_probe(struct pci_dev *pdev, + dev = alloc_arcdev(device); + if (!dev) { + ret = -ENOMEM; +- goto out_port; ++ break; + } + dev->dev_port = i; + +@@ -181,7 +185,7 @@ static int com20020pci_probe(struct pci_dev *pdev, + pr_err("IO region %xh-%xh already allocated\n", + ioaddr, ioaddr + cm->size - 1); + ret = -EBUSY; +- goto out_port; ++ goto err_free_arcdev; + } + + /* Dummy access after Reset +@@ -219,18 +223,18 @@ static int com20020pci_probe(struct pci_dev *pdev, + if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) { + pr_err("IO address %Xh is empty!\n", ioaddr); + ret = -EIO; +- goto out_port; ++ goto err_free_arcdev; + } + if (com20020_check(dev)) { + ret = -EIO; +- goto out_port; ++ goto err_free_arcdev; + } + + card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev), + GFP_KERNEL); + if (!card) { + ret = -ENOMEM; +- goto out_port; ++ goto err_free_arcdev; + } + + card->index = i; +@@ -256,29 +260,29 @@ static int com20020pci_probe(struct pci_dev *pdev, + + ret = devm_led_classdev_register(&pdev->dev, &card->tx_led); + if (ret) +- goto out_port; ++ goto err_free_arcdev; + + ret = devm_led_classdev_register(&pdev->dev, &card->recon_led); + if (ret) +- goto out_port; ++ goto err_free_arcdev; + + dev_set_drvdata(&dev->dev, card); + + ret = com20020_found(dev, IRQF_SHARED); + if (ret) +- goto out_port; ++ goto err_free_arcdev; + + devm_arcnet_led_init(dev, dev->dev_id, i); + + list_add(&card->list, &priv->list_dev); +- } ++ continue; + +- pci_set_drvdata(pdev, priv); +- +- return 0; +- +-out_port: +- com20020pci_remove(pdev); ++err_free_arcdev: ++ free_arcdev(dev); ++ break; ++ } ++ if (ret) ++ com20020pci_remove(pdev); + return ret; + } + +-- +2.42.0 + diff --git a/queue-5.4/net-arcnet-fix-reset-flag-handling.patch b/queue-5.4/net-arcnet-fix-reset-flag-handling.patch new file mode 100644 index 00000000000..db9af0c0890 --- /dev/null +++ b/queue-5.4/net-arcnet-fix-reset-flag-handling.patch @@ -0,0 +1,315 @@ +From fd32bea442d3d892bb83f873fc7e5a5bf1fffca2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Jan 2021 20:48:02 +0100 +Subject: net: arcnet: Fix RESET flag handling + +From: Ahmed S. Darwish + +[ Upstream commit 01365633bd1c836240f9bbf86bbeee749795480a ] + +The main arcnet interrupt handler calls arcnet_close() then +arcnet_open(), if the RESET status flag is encountered. + +This is invalid: + + 1) In general, interrupt handlers should never call ->ndo_stop() and + ->ndo_open() functions. They are usually full of blocking calls and + other methods that are expected to be called only from drivers + init and exit code paths. + + 2) arcnet_close() contains a del_timer_sync(). If the irq handler + interrupts the to-be-deleted timer, del_timer_sync() will just loop + forever. + + 3) arcnet_close() also calls tasklet_kill(), which has a warning if + called from irq context. + + 4) For device reset, the sequence "arcnet_close(); arcnet_open();" is + not complete. Some children arcnet drivers have special init/exit + code sequences, which then embed a call to arcnet_open() and + arcnet_close() accordingly. Check drivers/net/arcnet/com20020.c. + +Run the device RESET sequence from a scheduled workqueue instead. + +Signed-off-by: Ahmed S. Darwish +Signed-off-by: Sebastian Andrzej Siewior +Link: https://lore.kernel.org/r/20210128194802.727770-1-a.darwish@linutronix.de +Signed-off-by: Jakub Kicinski +Stable-dep-of: 6b17a597fc2f ("arcnet: restoring support for multiple Sohard Arcnet cards") +Signed-off-by: Sasha Levin +--- + drivers/net/arcnet/arc-rimi.c | 4 +- + drivers/net/arcnet/arcdevice.h | 6 +++ + drivers/net/arcnet/arcnet.c | 66 +++++++++++++++++++++++++++++-- + drivers/net/arcnet/com20020-isa.c | 4 +- + drivers/net/arcnet/com20020-pci.c | 2 +- + drivers/net/arcnet/com20020_cs.c | 2 +- + drivers/net/arcnet/com90io.c | 4 +- + drivers/net/arcnet/com90xx.c | 4 +- + 8 files changed, 78 insertions(+), 14 deletions(-) + +diff --git a/drivers/net/arcnet/arc-rimi.c b/drivers/net/arcnet/arc-rimi.c +index 14a5fb3781453..313b636edf239 100644 +--- a/drivers/net/arcnet/arc-rimi.c ++++ b/drivers/net/arcnet/arc-rimi.c +@@ -332,7 +332,7 @@ static int __init arc_rimi_init(void) + dev->irq = 9; + + if (arcrimi_probe(dev)) { +- free_netdev(dev); ++ free_arcdev(dev); + return -EIO; + } + +@@ -349,7 +349,7 @@ static void __exit arc_rimi_exit(void) + iounmap(lp->mem_start); + release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); + free_irq(dev->irq, dev); +- free_netdev(dev); ++ free_arcdev(dev); + } + + #ifndef MODULE +diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h +index b0f5bc07aef5b..7178f5349fa8f 100644 +--- a/drivers/net/arcnet/arcdevice.h ++++ b/drivers/net/arcnet/arcdevice.h +@@ -298,6 +298,10 @@ struct arcnet_local { + + int excnak_pending; /* We just got an excesive nak interrupt */ + ++ /* RESET flag handling */ ++ int reset_in_progress; ++ struct work_struct reset_work; ++ + struct { + uint16_t sequence; /* sequence number (incs with each packet) */ + __be16 aborted_seq; +@@ -350,7 +354,9 @@ void arcnet_dump_skb(struct net_device *dev, struct sk_buff *skb, char *desc) + + void arcnet_unregister_proto(struct ArcProto *proto); + irqreturn_t arcnet_interrupt(int irq, void *dev_id); ++ + struct net_device *alloc_arcdev(const char *name); ++void free_arcdev(struct net_device *dev); + + int arcnet_open(struct net_device *dev); + int arcnet_close(struct net_device *dev); +diff --git a/drivers/net/arcnet/arcnet.c b/drivers/net/arcnet/arcnet.c +index 2b112d3d85409..cf652c76af85e 100644 +--- a/drivers/net/arcnet/arcnet.c ++++ b/drivers/net/arcnet/arcnet.c +@@ -387,10 +387,44 @@ static void arcnet_timer(struct timer_list *t) + struct arcnet_local *lp = from_timer(lp, t, timer); + struct net_device *dev = lp->dev; + +- if (!netif_carrier_ok(dev)) { ++ spin_lock_irq(&lp->lock); ++ ++ if (!lp->reset_in_progress && !netif_carrier_ok(dev)) { + netif_carrier_on(dev); + netdev_info(dev, "link up\n"); + } ++ ++ spin_unlock_irq(&lp->lock); ++} ++ ++static void reset_device_work(struct work_struct *work) ++{ ++ struct arcnet_local *lp; ++ struct net_device *dev; ++ ++ lp = container_of(work, struct arcnet_local, reset_work); ++ dev = lp->dev; ++ ++ /* Do not bring the network interface back up if an ifdown ++ * was already done. ++ */ ++ if (!netif_running(dev) || !lp->reset_in_progress) ++ return; ++ ++ rtnl_lock(); ++ ++ /* Do another check, in case of an ifdown that was triggered in ++ * the small race window between the exit condition above and ++ * acquiring RTNL. ++ */ ++ if (!netif_running(dev) || !lp->reset_in_progress) ++ goto out; ++ ++ dev_close(dev); ++ dev_open(dev, NULL); ++ ++out: ++ rtnl_unlock(); + } + + static void arcnet_reply_tasklet(unsigned long data) +@@ -452,12 +486,25 @@ struct net_device *alloc_arcdev(const char *name) + lp->dev = dev; + spin_lock_init(&lp->lock); + timer_setup(&lp->timer, arcnet_timer, 0); ++ INIT_WORK(&lp->reset_work, reset_device_work); + } + + return dev; + } + EXPORT_SYMBOL(alloc_arcdev); + ++void free_arcdev(struct net_device *dev) ++{ ++ struct arcnet_local *lp = netdev_priv(dev); ++ ++ /* Do not cancel this at ->ndo_close(), as the workqueue itself ++ * indirectly calls the ifdown path through dev_close(). ++ */ ++ cancel_work_sync(&lp->reset_work); ++ free_netdev(dev); ++} ++EXPORT_SYMBOL(free_arcdev); ++ + /* Open/initialize the board. This is called sometime after booting when + * the 'ifconfig' program is run. + * +@@ -587,6 +634,10 @@ int arcnet_close(struct net_device *dev) + + /* shut down the card */ + lp->hw.close(dev); ++ ++ /* reset counters */ ++ lp->reset_in_progress = 0; ++ + module_put(lp->hw.owner); + return 0; + } +@@ -820,6 +871,9 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) + + spin_lock_irqsave(&lp->lock, flags); + ++ if (lp->reset_in_progress) ++ goto out; ++ + /* RESET flag was enabled - if device is not running, we must + * clear it right away (but nothing else). + */ +@@ -852,11 +906,14 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) + if (status & RESETflag) { + arc_printk(D_NORMAL, dev, "spurious reset (status=%Xh)\n", + status); +- arcnet_close(dev); +- arcnet_open(dev); ++ ++ lp->reset_in_progress = 1; ++ netif_stop_queue(dev); ++ netif_carrier_off(dev); ++ schedule_work(&lp->reset_work); + + /* get out of the interrupt handler! */ +- break; ++ goto out; + } + /* RX is inhibited - we must have received something. + * Prepare to receive into the next buffer. +@@ -1052,6 +1109,7 @@ irqreturn_t arcnet_interrupt(int irq, void *dev_id) + udelay(1); + lp->hw.intmask(dev, lp->intmask); + ++out: + spin_unlock_irqrestore(&lp->lock, flags); + return retval; + } +diff --git a/drivers/net/arcnet/com20020-isa.c b/drivers/net/arcnet/com20020-isa.c +index cd27fdc1059b9..141b05451252e 100644 +--- a/drivers/net/arcnet/com20020-isa.c ++++ b/drivers/net/arcnet/com20020-isa.c +@@ -169,7 +169,7 @@ static int __init com20020_init(void) + dev->irq = 9; + + if (com20020isa_probe(dev)) { +- free_netdev(dev); ++ free_arcdev(dev); + return -EIO; + } + +@@ -182,7 +182,7 @@ static void __exit com20020_exit(void) + unregister_netdev(my_dev); + free_irq(my_dev->irq, my_dev); + release_region(my_dev->base_addr, ARCNET_TOTAL_SIZE); +- free_netdev(my_dev); ++ free_arcdev(my_dev); + } + + #ifndef MODULE +diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c +index 9f44e2e458df1..b4f8798d8c509 100644 +--- a/drivers/net/arcnet/com20020-pci.c ++++ b/drivers/net/arcnet/com20020-pci.c +@@ -294,7 +294,7 @@ static void com20020pci_remove(struct pci_dev *pdev) + + unregister_netdev(dev); + free_irq(dev->irq, dev); +- free_netdev(dev); ++ free_arcdev(dev); + } + } + +diff --git a/drivers/net/arcnet/com20020_cs.c b/drivers/net/arcnet/com20020_cs.c +index cf607ffcf358e..9cc5eb6a8e905 100644 +--- a/drivers/net/arcnet/com20020_cs.c ++++ b/drivers/net/arcnet/com20020_cs.c +@@ -177,7 +177,7 @@ static void com20020_detach(struct pcmcia_device *link) + dev = info->dev; + if (dev) { + dev_dbg(&link->dev, "kfree...\n"); +- free_netdev(dev); ++ free_arcdev(dev); + } + dev_dbg(&link->dev, "kfree2...\n"); + kfree(info); +diff --git a/drivers/net/arcnet/com90io.c b/drivers/net/arcnet/com90io.c +index 186bbf87bc849..5843b8976fd19 100644 +--- a/drivers/net/arcnet/com90io.c ++++ b/drivers/net/arcnet/com90io.c +@@ -396,7 +396,7 @@ static int __init com90io_init(void) + err = com90io_probe(dev); + + if (err) { +- free_netdev(dev); ++ free_arcdev(dev); + return err; + } + +@@ -419,7 +419,7 @@ static void __exit com90io_exit(void) + + free_irq(dev->irq, dev); + release_region(dev->base_addr, ARCNET_TOTAL_SIZE); +- free_netdev(dev); ++ free_arcdev(dev); + } + + module_init(com90io_init) +diff --git a/drivers/net/arcnet/com90xx.c b/drivers/net/arcnet/com90xx.c +index bd75d06ad7dfc..5e40ecf189b15 100644 +--- a/drivers/net/arcnet/com90xx.c ++++ b/drivers/net/arcnet/com90xx.c +@@ -554,7 +554,7 @@ static int __init com90xx_found(int ioaddr, int airq, u_long shmem, + err_release_mem: + release_mem_region(dev->mem_start, dev->mem_end - dev->mem_start + 1); + err_free_dev: +- free_netdev(dev); ++ free_arcdev(dev); + return -EIO; + } + +@@ -672,7 +672,7 @@ static void __exit com90xx_exit(void) + release_region(dev->base_addr, ARCNET_TOTAL_SIZE); + release_mem_region(dev->mem_start, + dev->mem_end - dev->mem_start + 1); +- free_netdev(dev); ++ free_arcdev(dev); + } + } + +-- +2.42.0 + diff --git a/queue-5.4/net-hns-fix-fake-link-up-on-xge-port.patch b/queue-5.4/net-hns-fix-fake-link-up-on-xge-port.patch new file mode 100644 index 00000000000..e7be31858b2 --- /dev/null +++ b/queue-5.4/net-hns-fix-fake-link-up-on-xge-port.patch @@ -0,0 +1,74 @@ +From 825a0ae8dd0c9904ee7e26b1cbec0714451951f5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Dec 2023 22:32:32 +0800 +Subject: net: hns: fix fake link up on xge port + +From: Yonglong Liu + +[ Upstream commit f708aba40f9c1eeb9c7e93ed4863b5f85b09b288 ] + +If a xge port just connect with an optical module and no fiber, +it may have a fake link up because there may be interference on +the hardware. This patch adds an anti-shake to avoid the problem. +And the time of anti-shake is base on tests. + +Fixes: b917078c1c10 ("net: hns: Add ACPI support to check SFP present") +Signed-off-by: Yonglong Liu +Signed-off-by: Jijie Shao +Reviewed-by: Wojciech Drewek +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 29 +++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +index 8aace2de0cc91..e34245649057e 100644 +--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c ++++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +@@ -66,6 +66,27 @@ static enum mac_mode hns_get_enet_interface(const struct hns_mac_cb *mac_cb) + } + } + ++static u32 hns_mac_link_anti_shake(struct mac_driver *mac_ctrl_drv) ++{ ++#define HNS_MAC_LINK_WAIT_TIME 5 ++#define HNS_MAC_LINK_WAIT_CNT 40 ++ ++ u32 link_status = 0; ++ int i; ++ ++ if (!mac_ctrl_drv->get_link_status) ++ return link_status; ++ ++ for (i = 0; i < HNS_MAC_LINK_WAIT_CNT; i++) { ++ msleep(HNS_MAC_LINK_WAIT_TIME); ++ mac_ctrl_drv->get_link_status(mac_ctrl_drv, &link_status); ++ if (!link_status) ++ break; ++ } ++ ++ return link_status; ++} ++ + void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status) + { + struct mac_driver *mac_ctrl_drv; +@@ -83,6 +104,14 @@ void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status) + &sfp_prsnt); + if (!ret) + *link_status = *link_status && sfp_prsnt; ++ ++ /* for FIBER port, it may have a fake link up. ++ * when the link status changes from down to up, we need to do ++ * anti-shake. the anti-shake time is base on tests. ++ * only FIBER port need to do this. ++ */ ++ if (*link_status && !mac_cb->link) ++ *link_status = hns_mac_link_anti_shake(mac_ctrl_drv); + } + + mac_cb->link = *link_status; +-- +2.42.0 + diff --git a/queue-5.4/netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch b/queue-5.4/netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch new file mode 100644 index 00000000000..9961d95b3ae --- /dev/null +++ b/queue-5.4/netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch @@ -0,0 +1,71 @@ +From 7861d807c7bd847121a26b55cb66c30b62b3b718 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Dec 2023 21:58:12 +0100 +Subject: netfilter: xt_owner: Fix for unsafe access of sk->sk_socket + +From: Phil Sutter + +[ Upstream commit 7ae836a3d630e146b732fe8ef7d86b243748751f ] + +A concurrently running sock_orphan() may NULL the sk_socket pointer in +between check and deref. Follow other users (like nft_meta.c for +instance) and acquire sk_callback_lock before dereferencing sk_socket. + +Fixes: 0265ab44bacc ("[NETFILTER]: merge ipt_owner/ip6t_owner in xt_owner") +Reported-by: Jann Horn +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/xt_owner.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c +index e85ce69924aee..50332888c8d23 100644 +--- a/net/netfilter/xt_owner.c ++++ b/net/netfilter/xt_owner.c +@@ -76,18 +76,23 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) + */ + return false; + +- filp = sk->sk_socket->file; +- if (filp == NULL) ++ read_lock_bh(&sk->sk_callback_lock); ++ filp = sk->sk_socket ? sk->sk_socket->file : NULL; ++ if (filp == NULL) { ++ read_unlock_bh(&sk->sk_callback_lock); + return ((info->match ^ info->invert) & + (XT_OWNER_UID | XT_OWNER_GID)) == 0; ++ } + + if (info->match & XT_OWNER_UID) { + kuid_t uid_min = make_kuid(net->user_ns, info->uid_min); + kuid_t uid_max = make_kuid(net->user_ns, info->uid_max); + if ((uid_gte(filp->f_cred->fsuid, uid_min) && + uid_lte(filp->f_cred->fsuid, uid_max)) ^ +- !(info->invert & XT_OWNER_UID)) ++ !(info->invert & XT_OWNER_UID)) { ++ read_unlock_bh(&sk->sk_callback_lock); + return false; ++ } + } + + if (info->match & XT_OWNER_GID) { +@@ -112,10 +117,13 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) + } + } + +- if (match ^ !(info->invert & XT_OWNER_GID)) ++ if (match ^ !(info->invert & XT_OWNER_GID)) { ++ read_unlock_bh(&sk->sk_callback_lock); + return false; ++ } + } + ++ read_unlock_bh(&sk->sk_callback_lock); + return true; + } + +-- +2.42.0 + diff --git a/queue-5.4/of-add-missing-return-section-in-kerneldoc-comments.patch b/queue-5.4/of-add-missing-return-section-in-kerneldoc-comments.patch new file mode 100644 index 00000000000..9108c512e0e --- /dev/null +++ b/queue-5.4/of-add-missing-return-section-in-kerneldoc-comments.patch @@ -0,0 +1,812 @@ +From 0d4adf4c5580c4abf8fd489ba7f9585ea7ce9271 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Mar 2021 10:47:12 -0600 +Subject: of: Add missing 'Return' section in kerneldoc comments + +From: Rob Herring + +[ Upstream commit 8c8239c2c1fb82f171cb22a707f3bb88a2f22109 ] + +Many of the DT kerneldoc comments are lacking a 'Return' section. Let's +add the section in cases we have a description of return values. There's +still some cases where the return values are not documented. + +Cc: Frank Rowand +Cc: Mauro Carvalho Chehab +Signed-off-by: Rob Herring +Reviewed-by: Mauro Carvalho Chehab +Link: https://lore.kernel.org/r/20210325164713.1296407-8-robh@kernel.org +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/of/base.c | 39 +++++++++++++------------ + drivers/of/dynamic.c | 19 ++++++++----- + drivers/of/fdt.c | 8 +++--- + drivers/of/irq.c | 14 ++++----- + drivers/of/overlay.c | 16 +++++------ + drivers/of/platform.c | 10 +++---- + drivers/of/property.c | 66 +++++++++++++++++++++++++++---------------- + include/linux/of.h | 63 ++++++++++++++++++++++++++--------------- + 8 files changed, 140 insertions(+), 95 deletions(-) + +diff --git a/drivers/of/base.c b/drivers/of/base.c +index c4c64ef5fb7a8..c8af9a65f98b0 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -306,7 +306,7 @@ struct device_node *__of_find_all_nodes(struct device_node *prev) + * @prev: Previous node or NULL to start iteration + * of_node_put() will be called on it + * +- * Returns a node pointer with refcount incremented, use ++ * Return: A node pointer with refcount incremented, use + * of_node_put() on it when done. + */ + struct device_node *of_find_all_nodes(struct device_node *prev) +@@ -436,7 +436,7 @@ bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, + * before booting secondary cores. This function uses arch_match_cpu_phys_id + * which can be overridden by architecture specific implementation. + * +- * Returns a node pointer for the logical cpu with refcount incremented, use ++ * Return: A node pointer for the logical cpu with refcount incremented, use + * of_node_put() on it when done. Returns NULL if not found. + */ + struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) +@@ -456,8 +456,8 @@ EXPORT_SYMBOL(of_get_cpu_node); + * + * @cpu_node: Pointer to the device_node for CPU. + * +- * Returns the logical CPU number of the given CPU device_node. +- * Returns -ENODEV if the CPU is not found. ++ * Return: The logical CPU number of the given CPU device_node or -ENODEV if the ++ * CPU is not found. + */ + int of_cpu_node_to_id(struct device_node *cpu_node) + { +@@ -489,7 +489,7 @@ EXPORT_SYMBOL(of_cpu_node_to_id); + * bindings. This function check for both and returns the idle state node for + * the requested index. + * +- * In case an idle state node is found at @index, the refcount is incremented ++ * Return: An idle state node if found at @index. The refcount is incremented + * for it, so call of_node_put() on it when done. Returns NULL if not found. + */ + struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, +@@ -623,7 +623,7 @@ int of_device_compatible_match(struct device_node *device, + * of_machine_is_compatible - Test root of device tree for a given compatible value + * @compat: compatible string to look for in root node's compatible property. + * +- * Returns a positive integer if the root node has the given value in its ++ * Return: A positive integer if the root node has the given value in its + * compatible property. + */ + int of_machine_is_compatible(const char *compat) +@@ -645,7 +645,7 @@ EXPORT_SYMBOL(of_machine_is_compatible); + * + * @device: Node to check for availability, with locks already held + * +- * Returns true if the status property is absent or set to "okay" or "ok", ++ * Return: True if the status property is absent or set to "okay" or "ok", + * false otherwise + */ + static bool __of_device_is_available(const struct device_node *device) +@@ -673,7 +673,7 @@ static bool __of_device_is_available(const struct device_node *device) + * + * @device: Node to check for availability + * +- * Returns true if the status property is absent or set to "okay" or "ok", ++ * Return: True if the status property is absent or set to "okay" or "ok", + * false otherwise + */ + bool of_device_is_available(const struct device_node *device) +@@ -694,7 +694,7 @@ EXPORT_SYMBOL(of_device_is_available); + * + * @device: Node to check for endianness + * +- * Returns true if the device has a "big-endian" property, or if the kernel ++ * Return: True if the device has a "big-endian" property, or if the kernel + * was compiled for BE *and* the device has a "native-endian" property. + * Returns false otherwise. + * +@@ -878,7 +878,7 @@ EXPORT_SYMBOL(of_get_next_cpu_node); + * Lookup child node whose compatible property contains the given compatible + * string. + * +- * Returns a node pointer with refcount incremented, use of_node_put() on it ++ * Return: a node pointer with refcount incremented, use of_node_put() on it + * when done; or NULL if not found. + */ + struct device_node *of_get_compatible_child(const struct device_node *parent, +@@ -1232,7 +1232,7 @@ EXPORT_SYMBOL(of_find_matching_node_and_match); + * It does this by stripping the manufacturer prefix (as delimited by a ',') + * from the first entry in the compatible list property. + * +- * This routine returns 0 on success, <0 on failure. ++ * Return: This routine returns 0 on success, <0 on failure. + */ + int of_modalias_node(struct device_node *node, char *modalias, int len) + { +@@ -1252,7 +1252,7 @@ EXPORT_SYMBOL_GPL(of_modalias_node); + * of_find_node_by_phandle - Find a node given a phandle + * @handle: phandle of the node to find + * +- * Returns a node pointer with refcount incremented, use ++ * Return: A node pointer with refcount incremented, use + * of_node_put() on it when done. + */ + struct device_node *of_find_node_by_phandle(phandle handle) +@@ -1505,7 +1505,7 @@ static int __of_parse_phandle_with_args(const struct device_node *np, + * @index: For properties holding a table of phandles, this is the index into + * the table + * +- * Returns the device_node pointer with refcount incremented. Use ++ * Return: The device_node pointer with refcount incremented. Use + * of_node_put() on it when done. + */ + struct device_node *of_parse_phandle(const struct device_node *np, +@@ -1805,7 +1805,7 @@ EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * +- * Returns the number of phandle + argument tuples within a property. It ++ * Return: The number of phandle + argument tuples within a property. It + * is a typical pattern to encode a list of phandle and variable + * arguments into a single property. The number of arguments is encoded + * by a property in the phandle-target node. For example, a gpios +@@ -2104,7 +2104,9 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) + * @stem: Alias stem of the given device_node + * + * The function travels the lookup table to get the alias id for the given +- * device_node and alias stem. It returns the alias id if found. ++ * device_node and alias stem. ++ * ++ * Return: The alias id if found. + */ + int of_alias_get_id(struct device_node *np, const char *stem) + { +@@ -2213,8 +2215,9 @@ EXPORT_SYMBOL_GPL(of_alias_get_highest_id); + * @index: Index to use for preferred console. + * + * Check if the given device node matches the stdout-path property in the +- * /chosen node. If it does then register it as the preferred console and return +- * TRUE. Otherwise return FALSE. ++ * /chosen node. If it does then register it as the preferred console. ++ * ++ * Return: TRUE if console successfully setup. Otherwise return FALSE. + */ + bool of_console_check(struct device_node *dn, char *name, int index) + { +@@ -2265,7 +2268,7 @@ struct device_node *of_find_next_cache_node(const struct device_node *np) + * + * @cpu: cpu number(logical index) for which the last cache level is needed + * +- * Returns the the level at which the last cache is present. It is exactly ++ * Return: The the level at which the last cache is present. It is exactly + * same as the total number of cache levels for the given logical cpu. + */ + int of_find_last_cache_level(unsigned int cpu) +diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c +index 49b16f76d78e8..92ee15be78d43 100644 +--- a/drivers/of/dynamic.c ++++ b/drivers/of/dynamic.c +@@ -27,7 +27,7 @@ static struct device_node *kobj_to_device_node(struct kobject *kobj) + * @node: Node to inc refcount, NULL is supported to simplify writing of + * callers + * +- * Returns node. ++ * Return: The node with refcount incremented. + */ + struct device_node *of_node_get(struct device_node *node) + { +@@ -104,7 +104,8 @@ int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p) + * @arg - argument of the of notifier + * + * Returns the new state of a device based on the notifier used. +- * Returns 0 on device going from enabled to disabled, 1 on device ++ * ++ * Return: 0 on device going from enabled to disabled, 1 on device + * going from disabled to enabled and -1 on no change. + */ + int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr) +@@ -372,7 +373,8 @@ void of_node_release(struct kobject *kobj) + * property structure and the property name & contents. The property's + * flags have the OF_DYNAMIC bit set so that we can differentiate between + * dynamically allocated properties and not. +- * Returns the newly allocated property or NULL on out of memory error. ++ * ++ * Return: The newly allocated property or NULL on out of memory error. + */ + struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) + { +@@ -415,7 +417,7 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) + * another node. The node data are dynamically allocated and all the node + * flags have the OF_DYNAMIC & OF_DETACHED bits set. + * +- * Returns the newly allocated node or NULL on out of memory error. ++ * Return: The newly allocated node or NULL on out of memory error. + */ + struct device_node *__of_node_dup(const struct device_node *np, + const char *full_name) +@@ -781,7 +783,8 @@ static int __of_changeset_apply(struct of_changeset *ocs) + * Any side-effects of live tree state changes are applied here on + * success, like creation/destruction of devices and side-effects + * like creation of sysfs properties and directories. +- * Returns 0 on success, a negative error value in case of an error. ++ * ++ * Return: 0 on success, a negative error value in case of an error. + * On error the partially applied effects are reverted. + */ + int of_changeset_apply(struct of_changeset *ocs) +@@ -875,7 +878,8 @@ static int __of_changeset_revert(struct of_changeset *ocs) + * was before the application. + * Any side-effects like creation/destruction of devices and + * removal of sysfs properties and directories are applied. +- * Returns 0 on success, a negative error value in case of an error. ++ * ++ * Return: 0 on success, a negative error value in case of an error. + */ + int of_changeset_revert(struct of_changeset *ocs) + { +@@ -903,7 +907,8 @@ EXPORT_SYMBOL_GPL(of_changeset_revert); + * + OF_RECONFIG_ADD_PROPERTY + * + OF_RECONFIG_REMOVE_PROPERTY, + * + OF_RECONFIG_UPDATE_PROPERTY +- * Returns 0 on success, a negative error value in case of an error. ++ * ++ * Return: 0 on success, a negative error value in case of an error. + */ + int of_changeset_action(struct of_changeset *ocs, unsigned long action, + struct device_node *np, struct property *prop) +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index 09a98668e7db0..1db951f433538 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -282,7 +282,7 @@ static void reverse_nodes(struct device_node *parent) + * @dad: Parent struct device_node + * @nodepp: The device_node tree created by the call + * +- * It returns the size of unflattened device tree or error code ++ * Return: The size of unflattened device tree or error code + */ + static int unflatten_dt_nodes(const void *blob, + void *mem, +@@ -360,7 +360,7 @@ static int unflatten_dt_nodes(const void *blob, + * fills the "name" and "type" pointers of the nodes so the normal device-tree + * walking functions can be used. + * +- * Returns NULL on failure or the memory chunk containing the unflattened ++ * Return: NULL on failure or the memory chunk containing the unflattened + * device tree on success. + */ + void *__unflatten_device_tree(const void *blob, +@@ -441,7 +441,7 @@ static DEFINE_MUTEX(of_fdt_unflatten_mutex); + * pointers of the nodes so the normal device-tree walking functions + * can be used. + * +- * Returns NULL on failure or the memory chunk containing the unflattened ++ * Return: NULL on failure or the memory chunk containing the unflattened + * device tree on success. + */ + void *of_fdt_unflatten_tree(const unsigned long *blob, +@@ -719,7 +719,7 @@ const void *__init of_get_flat_dt_prop(unsigned long node, const char *name, + * @node: node to test + * @compat: compatible string to compare with compatible list. + * +- * On match, returns a non-zero value with smaller values returned for more ++ * Return: a non-zero value on match with smaller values returned for more + * specific compatible values. + */ + static int of_fdt_is_compatible(const void *blob, +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index 25d17b8a1a1aa..352e14b007e78 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -48,7 +48,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); + * of_irq_find_parent - Given a device node, find its interrupt parent node + * @child: pointer to device node + * +- * Returns a pointer to the interrupt parent node, or NULL if the interrupt ++ * Return: A pointer to the interrupt parent node, or NULL if the interrupt + * parent could not be determined. + */ + struct device_node *of_irq_find_parent(struct device_node *child) +@@ -81,14 +81,14 @@ EXPORT_SYMBOL_GPL(of_irq_find_parent); + * @addr: address specifier (start of "reg" property of the device) in be32 format + * @out_irq: structure of_phandle_args updated by this function + * +- * Returns 0 on success and a negative number on error +- * + * This function is a low-level interrupt tree walking function. It + * can be used to do a partial walk with synthetized reg and interrupts + * properties, for example when resolving PCI interrupts when no device + * node exist for the parent. It takes an interrupt specifier structure as + * input, walks the tree looking for any interrupt-map properties, translates + * the specifier for each map, and then returns the translated map. ++ * ++ * Return: 0 on success and a negative number on error + */ + int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) + { +@@ -380,7 +380,7 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource); + * @dev: pointer to device tree node + * @index: zero-based index of the IRQ + * +- * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or ++ * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or + * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case + * of any other failure. + */ +@@ -407,7 +407,7 @@ EXPORT_SYMBOL_GPL(of_irq_get); + * @dev: pointer to device tree node + * @name: IRQ name + * +- * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or ++ * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or + * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case + * of any other failure. + */ +@@ -447,7 +447,7 @@ int of_irq_count(struct device_node *dev) + * @res: array of resources to fill in + * @nr_irqs: the number of IRQs (and upper bound for num of @res elements) + * +- * Returns the size of the filled in table (up to @nr_irqs). ++ * Return: The size of the filled in table (up to @nr_irqs). + */ + int of_irq_to_resource_table(struct device_node *dev, struct resource *res, + int nr_irqs) +@@ -602,7 +602,7 @@ static u32 __of_msi_map_id(struct device *dev, struct device_node **np, + * Walk up the device hierarchy looking for devices with a "msi-map" + * property. If found, apply the mapping to @id_in. + * +- * Returns the mapped MSI ID. ++ * Return: The mapped MSI ID. + */ + u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in) + { +diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c +index dc298775f7620..b551fe44f2f95 100644 +--- a/drivers/of/overlay.c ++++ b/drivers/of/overlay.c +@@ -296,7 +296,7 @@ static struct property *dup_and_fixup_symbol_prop( + * + * Update of property in symbols node is not allowed. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if ++ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay. + */ + static int add_changeset_property(struct overlay_changeset *ovcs, +@@ -401,7 +401,7 @@ static int add_changeset_property(struct overlay_changeset *ovcs, + * + * NOTE_2: Multiple mods of created nodes not supported. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if ++ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay. + */ + static int add_changeset_node(struct overlay_changeset *ovcs, +@@ -473,7 +473,7 @@ static int add_changeset_node(struct overlay_changeset *ovcs, + * + * Do not allow symbols node to have any children. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if ++ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay_node. + */ + static int build_changeset_next_level(struct overlay_changeset *ovcs, +@@ -604,7 +604,7 @@ static int find_dup_cset_prop(struct overlay_changeset *ovcs, + * the same node or duplicate {add, delete, or update} properties entries + * for the same property. + * +- * Returns 0 on success, or -EINVAL if duplicate changeset entry found. ++ * Return: 0 on success, or -EINVAL if duplicate changeset entry found. + */ + static int changeset_dup_entry_check(struct overlay_changeset *ovcs) + { +@@ -628,7 +628,7 @@ static int changeset_dup_entry_check(struct overlay_changeset *ovcs) + * any portions of the changeset that were successfully created will remain + * in @ovcs->cset. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if ++ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid overlay in @ovcs->fragments[]. + */ + static int build_changeset(struct overlay_changeset *ovcs) +@@ -724,7 +724,7 @@ static struct device_node *find_target(struct device_node *info_node) + * the top level of @tree. The relevant top level nodes are the fragment + * nodes and the __symbols__ node. Any other top level node will be ignored. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error ++ * Return: 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error + * detected in @tree, or -ENOSPC if idr_alloc() error. + */ + static int init_overlay_changeset(struct overlay_changeset *ovcs, +@@ -1180,7 +1180,7 @@ static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs) + * If an error is returned by an overlay changeset post-remove notifier + * then no further overlay changeset post-remove notifier will be called. + * +- * Returns 0 on success, or a negative error number. *ovcs_id is set to ++ * Return: 0 on success, or a negative error number. *ovcs_id is set to + * zero after reverting the changeset, even if a subsequent error occurs. + */ + int of_overlay_remove(int *ovcs_id) +@@ -1267,7 +1267,7 @@ EXPORT_SYMBOL_GPL(of_overlay_remove); + * + * Removes all overlays from the system in the correct order. + * +- * Returns 0 on success, or a negative error number ++ * Return: 0 on success, or a negative error number + */ + int of_overlay_remove_all(void) + { +diff --git a/drivers/of/platform.c b/drivers/of/platform.c +index b47a2292fe8e8..cf5dbc9536f20 100644 +--- a/drivers/of/platform.c ++++ b/drivers/of/platform.c +@@ -44,7 +44,7 @@ static const struct of_device_id of_skipped_node_table[] = { + * Takes a reference to the embedded struct device which needs to be dropped + * after use. + * +- * Returns platform_device pointer, or NULL if not found ++ * Return: platform_device pointer, or NULL if not found + */ + struct platform_device *of_find_device_by_node(struct device_node *np) + { +@@ -160,7 +160,7 @@ EXPORT_SYMBOL(of_device_alloc); + * @platform_data: pointer to populate platform_data pointer with + * @parent: Linux device model parent device. + * +- * Returns pointer to created platform device, or NULL if a device was not ++ * Return: Pointer to created platform device, or NULL if a device was not + * registered. Unavailable devices will not get registered. + */ + static struct platform_device *of_platform_device_create_pdata( +@@ -204,7 +204,7 @@ static struct platform_device *of_platform_device_create_pdata( + * @bus_id: name to assign device + * @parent: Linux device model parent device. + * +- * Returns pointer to created platform device, or NULL if a device was not ++ * Return: Pointer to created platform device, or NULL if a device was not + * registered. Unavailable devices will not get registered. + */ + struct platform_device *of_platform_device_create(struct device_node *np, +@@ -463,7 +463,7 @@ EXPORT_SYMBOL(of_platform_bus_probe); + * New board support should be using this function instead of + * of_platform_bus_probe(). + * +- * Returns 0 on success, < 0 on failure. ++ * Return: 0 on success, < 0 on failure. + */ + int of_platform_populate(struct device_node *root, + const struct of_device_id *matches, +@@ -594,7 +594,7 @@ static void devm_of_platform_populate_release(struct device *dev, void *res) + * Similar to of_platform_populate(), but will automatically call + * of_platform_depopulate() when the device is unbound from the bus. + * +- * Returns 0 on success, < 0 on failure. ++ * Return: 0 on success, < 0 on failure. + */ + int devm_of_platform_populate(struct device *dev) + { +diff --git a/drivers/of/property.c b/drivers/of/property.c +index f6010ec0f67b1..28ea326d102f9 100644 +--- a/drivers/of/property.c ++++ b/drivers/of/property.c +@@ -36,9 +36,11 @@ + * @elem_size: size of the individual element + * + * Search for a property in a device node and count the number of elements of +- * size elem_size in it. Returns number of elements on sucess, -EINVAL if the +- * property does not exist or its length does not match a multiple of elem_size +- * and -ENODATA if the property does not have a value. ++ * size elem_size in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does not ++ * exist or its length does not match a multiple of elem_size and -ENODATA if ++ * the property does not have a value. + */ + int of_property_count_elems_of_size(const struct device_node *np, + const char *propname, int elem_size) +@@ -70,8 +72,9 @@ EXPORT_SYMBOL_GPL(of_property_count_elems_of_size); + * @len: if !=NULL, actual length is written to here + * + * Search for a property in a device node and valid the requested size. +- * Returns the property value on success, -EINVAL if the property does not +- * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the ++ * ++ * Return: The property value on success, -EINVAL if the property does not ++ * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data is too small or too large. + * + */ +@@ -104,7 +107,9 @@ static void *of_find_property_value_of_size(const struct device_node *np, + * @out_value: pointer to return value, modified only if no error. + * + * Search for a property in a device node and read nth 32-bit value from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -136,7 +141,9 @@ EXPORT_SYMBOL_GPL(of_property_read_u32_index); + * @out_value: pointer to return value, modified only if no error. + * + * Search for a property in a device node and read nth 64-bit value from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -171,12 +178,14 @@ EXPORT_SYMBOL_GPL(of_property_read_u64_index); + * sz_min will be read. + * + * Search for a property in a device node and read 8-bit value(s) from +- * it. Returns number of elements read on success, -EINVAL if the property +- * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW +- * if the property data is smaller than sz_min or longer than sz_max. ++ * it. + * + * dts entry of array should be like: +- * property = /bits/ 8 <0x50 0x60 0x70>; ++ * ``property = /bits/ 8 <0x50 0x60 0x70>;`` ++ * ++ * Return: The number of elements read on success, -EINVAL if the property ++ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW ++ * if the property data is smaller than sz_min or longer than sz_max. + * + * The out_values is modified only if a valid u8 value can be decoded. + */ +@@ -219,12 +228,14 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u8_array); + * sz_min will be read. + * + * Search for a property in a device node and read 16-bit value(s) from +- * it. Returns number of elements read on success, -EINVAL if the property +- * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW +- * if the property data is smaller than sz_min or longer than sz_max. ++ * it. + * + * dts entry of array should be like: +- * property = /bits/ 16 <0x5000 0x6000 0x7000>; ++ * ``property = /bits/ 16 <0x5000 0x6000 0x7000>;`` ++ * ++ * Return: The number of elements read on success, -EINVAL if the property ++ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW ++ * if the property data is smaller than sz_min or longer than sz_max. + * + * The out_values is modified only if a valid u16 value can be decoded. + */ +@@ -267,7 +278,9 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u16_array); + * sz_min will be read. + * + * Search for a property in a device node and read 32-bit value(s) from +- * it. Returns number of elements read on success, -EINVAL if the property ++ * it. ++ * ++ * Return: The number of elements read on success, -EINVAL if the property + * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW + * if the property data is smaller than sz_min or longer than sz_max. + * +@@ -306,7 +319,9 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u32_array); + * @out_value: pointer to return value, modified only if return value is 0. + * + * Search for a property in a device node and read a 64-bit value from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -341,7 +356,9 @@ EXPORT_SYMBOL_GPL(of_property_read_u64); + * sz_min will be read. + * + * Search for a property in a device node and read 64-bit value(s) from +- * it. Returns number of elements read on success, -EINVAL if the property ++ * it. ++ * ++ * Return: The number of elements read on success, -EINVAL if the property + * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW + * if the property data is smaller than sz_min or longer than sz_max. + * +@@ -383,10 +400,11 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u64_array); + * return value is 0. + * + * Search for a property in a device tree node and retrieve a null +- * terminated string value (pointer to data, not a copy). Returns 0 on +- * success, -EINVAL if the property does not exist, -ENODATA if property +- * does not have a value, and -EILSEQ if the string is not null-terminated +- * within the length of the property data. ++ * terminated string value (pointer to data, not a copy). ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if ++ * property does not have a value, and -EILSEQ if the string is not ++ * null-terminated within the length of the property data. + * + * The out_string pointer is modified only if a valid string can be decoded. + */ +@@ -750,7 +768,7 @@ EXPORT_SYMBOL(of_graph_get_remote_port_parent); + * @node: pointer to a local endpoint device_node + * + * Return: Remote port node associated with remote endpoint node linked +- * to @node. Use of_node_put() on it when done. ++ * to @node. Use of_node_put() on it when done. + */ + struct device_node *of_graph_get_remote_port(const struct device_node *node) + { +@@ -783,7 +801,7 @@ EXPORT_SYMBOL(of_graph_get_endpoint_count); + * @endpoint: identifier (value of reg property) of the endpoint node + * + * Return: Remote device node associated with remote endpoint node linked +- * to @node. Use of_node_put() on it when done. ++ * to @node. Use of_node_put() on it when done. + */ + struct device_node *of_graph_get_remote_node(const struct device_node *node, + u32 port, u32 endpoint) +diff --git a/include/linux/of.h b/include/linux/of.h +index e070c5ed62a09..8681277af9c6f 100644 +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -424,12 +424,14 @@ extern int of_detach_node(struct device_node *); + * @sz: number of array elements to read + * + * Search for a property in a device node and read 8-bit value(s) from +- * it. Returns 0 on success, -EINVAL if the property does not exist, +- * -ENODATA if property does not have a value, and -EOVERFLOW if the +- * property data isn't large enough. ++ * it. + * + * dts entry of array should be like: +- * property = /bits/ 8 <0x50 0x60 0x70>; ++ * ``property = /bits/ 8 <0x50 0x60 0x70>;`` ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, ++ * -ENODATA if property does not have a value, and -EOVERFLOW if the ++ * property data isn't large enough. + * + * The out_values is modified only if a valid u8 value can be decoded. + */ +@@ -454,12 +456,14 @@ static inline int of_property_read_u8_array(const struct device_node *np, + * @sz: number of array elements to read + * + * Search for a property in a device node and read 16-bit value(s) from +- * it. Returns 0 on success, -EINVAL if the property does not exist, +- * -ENODATA if property does not have a value, and -EOVERFLOW if the +- * property data isn't large enough. ++ * it. + * + * dts entry of array should be like: +- * property = /bits/ 16 <0x5000 0x6000 0x7000>; ++ * ``property = /bits/ 16 <0x5000 0x6000 0x7000>;`` ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, ++ * -ENODATA if property does not have a value, and -EOVERFLOW if the ++ * property data isn't large enough. + * + * The out_values is modified only if a valid u16 value can be decoded. + */ +@@ -485,7 +489,9 @@ static inline int of_property_read_u16_array(const struct device_node *np, + * @sz: number of array elements to read + * + * Search for a property in a device node and read 32-bit value(s) from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -513,7 +519,9 @@ static inline int of_property_read_u32_array(const struct device_node *np, + * @sz: number of array elements to read + * + * Search for a property in a device node and read 64-bit value(s) from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -1046,7 +1054,9 @@ static inline bool of_node_is_type(const struct device_node *np, const char *typ + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u8 elements +- * in it. Returns number of elements on sucess, -EINVAL if the property does ++ * in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u8 and -ENODATA if the + * property does not have a value. + */ +@@ -1063,7 +1073,9 @@ static inline int of_property_count_u8_elems(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u16 elements +- * in it. Returns number of elements on sucess, -EINVAL if the property does ++ * in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u16 and -ENODATA if the + * property does not have a value. + */ +@@ -1080,7 +1092,9 @@ static inline int of_property_count_u16_elems(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u32 elements +- * in it. Returns number of elements on sucess, -EINVAL if the property does ++ * in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u32 and -ENODATA if the + * property does not have a value. + */ +@@ -1097,7 +1111,9 @@ static inline int of_property_count_u32_elems(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u64 elements +- * in it. Returns number of elements on sucess, -EINVAL if the property does ++ * in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u64 and -ENODATA if the + * property does not have a value. + */ +@@ -1118,7 +1134,7 @@ static inline int of_property_count_u64_elems(const struct device_node *np, + * Search for a property in a device tree node and retrieve a list of + * terminated string values (pointer to data, not a copy) in that property. + * +- * If @out_strs is NULL, the number of strings in the property is returned. ++ * Return: If @out_strs is NULL, the number of strings in the property is returned. + */ + static inline int of_property_read_string_array(const struct device_node *np, + const char *propname, const char **out_strs, +@@ -1134,10 +1150,11 @@ static inline int of_property_read_string_array(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device tree node and retrieve the number of null +- * terminated string contain in it. Returns the number of strings on +- * success, -EINVAL if the property does not exist, -ENODATA if property +- * does not have a value, and -EILSEQ if the string is not null-terminated +- * within the length of the property data. ++ * terminated string contain in it. ++ * ++ * Return: The number of strings on success, -EINVAL if the property does not ++ * exist, -ENODATA if property does not have a value, and -EILSEQ if the string ++ * is not null-terminated within the length of the property data. + */ + static inline int of_property_count_strings(const struct device_node *np, + const char *propname) +@@ -1157,7 +1174,8 @@ static inline int of_property_count_strings(const struct device_node *np, + * Search for a property in a device tree node and retrieve a null + * terminated string value (pointer to data, not a copy) in the list of strings + * contained in that property. +- * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if + * property does not have a value, and -EILSEQ if the string is not + * null-terminated within the length of the property data. + * +@@ -1177,7 +1195,8 @@ static inline int of_property_read_string_index(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device node. +- * Returns true if the property exists false otherwise. ++ * ++ * Return: true if the property exists false otherwise. + */ + static inline bool of_property_read_bool(const struct device_node *np, + const char *propname) +@@ -1423,7 +1442,7 @@ static inline int of_reconfig_get_state_change(unsigned long action, + * of_device_is_system_power_controller - Tells if system-power-controller is found for device_node + * @np: Pointer to the given device_node + * +- * return true if present false otherwise ++ * Return: true if present false otherwise + */ + static inline bool of_device_is_system_power_controller(const struct device_node *np) + { +-- +2.42.0 + diff --git a/queue-5.4/of-base-add-of_get_cpu_state_node-to-get-idle-states.patch b/queue-5.4/of-base-add-of_get_cpu_state_node-to-get-idle-states.patch new file mode 100644 index 00000000000..5819f720e4b --- /dev/null +++ b/queue-5.4/of-base-add-of_get_cpu_state_node-to-get-idle-states.patch @@ -0,0 +1,116 @@ +From e8f906090506040660495eb0f530a35318533ba6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 10 Oct 2019 12:01:48 +0200 +Subject: of: base: Add of_get_cpu_state_node() to get idle states for a CPU + node + +From: Ulf Hansson + +[ Upstream commit b9f8c26afc405a4a616e765e949bdd551151e41d ] + +The CPU's idle state nodes are currently parsed at the common cpuidle DT +library, but also when initializing data for specific CPU idle operations, +as in the PSCI cpuidle driver case and qcom-spm cpuidle case. + +To avoid open-coding, let's introduce of_get_cpu_state_node(), which takes +the device node for the CPU and the index to the requested idle state node, +as in-parameters. In case a corresponding idle state node is found, it +returns the node with the refcount incremented for it, else it returns +NULL. + +Moreover, for PSCI there are two options to describe the CPU's idle states +[1], either via a flattened description or a hierarchical layout. Hence, +let's take both options into account. + +[1] Documentation/devicetree/bindings/arm/psci.yaml + +Suggested-by: Sudeep Holla +Co-developed-by: Lina Iyer +Signed-off-by: Lina Iyer +Reviewed-by: Rob Herring +Reviewed-by: Daniel Lezcano +Signed-off-by: Ulf Hansson +Reviewed-by: Sudeep Holla +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/of/base.c | 36 ++++++++++++++++++++++++++++++++++++ + include/linux/of.h | 8 ++++++++ + 2 files changed, 44 insertions(+) + +diff --git a/drivers/of/base.c b/drivers/of/base.c +index b5c84607a74bf..3f13b982e8b53 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -477,6 +477,42 @@ int of_cpu_node_to_id(struct device_node *cpu_node) + } + EXPORT_SYMBOL(of_cpu_node_to_id); + ++/** ++ * of_get_cpu_state_node - Get CPU's idle state node at the given index ++ * ++ * @cpu_node: The device node for the CPU ++ * @index: The index in the list of the idle states ++ * ++ * Two generic methods can be used to describe a CPU's idle states, either via ++ * a flattened description through the "cpu-idle-states" binding or via the ++ * hierarchical layout, using the "power-domains" and the "domain-idle-states" ++ * bindings. This function check for both and returns the idle state node for ++ * the requested index. ++ * ++ * In case an idle state node is found at @index, the refcount is incremented ++ * for it, so call of_node_put() on it when done. Returns NULL if not found. ++ */ ++struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, ++ int index) ++{ ++ struct of_phandle_args args; ++ int err; ++ ++ err = of_parse_phandle_with_args(cpu_node, "power-domains", ++ "#power-domain-cells", 0, &args); ++ if (!err) { ++ struct device_node *state_node = ++ of_parse_phandle(args.np, "domain-idle-states", index); ++ ++ of_node_put(args.np); ++ if (state_node) ++ return state_node; ++ } ++ ++ return of_parse_phandle(cpu_node, "cpu-idle-states", index); ++} ++EXPORT_SYMBOL(of_get_cpu_state_node); ++ + /** + * __of_device_is_compatible() - Check if the node matches given constraints + * @device: pointer to node +diff --git a/include/linux/of.h b/include/linux/of.h +index a7621e2b440ad..e29b341598e99 100644 +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -351,6 +351,8 @@ extern const void *of_get_property(const struct device_node *node, + int *lenp); + extern struct device_node *of_get_cpu_node(int cpu, unsigned int *thread); + extern struct device_node *of_get_next_cpu_node(struct device_node *prev); ++extern struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, ++ int index); + + #define for_each_property_of_node(dn, pp) \ + for (pp = dn->properties; pp != NULL; pp = pp->next) +@@ -765,6 +767,12 @@ static inline struct device_node *of_get_next_cpu_node(struct device_node *prev) + return NULL; + } + ++static inline struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, ++ int index) ++{ ++ return NULL; ++} ++ + static inline int of_n_addr_cells(struct device_node *np) + { + return 0; +-- +2.42.0 + diff --git a/queue-5.4/of-base-fix-some-formatting-issues-and-provide-missi.patch b/queue-5.4/of-base-fix-some-formatting-issues-and-provide-missi.patch new file mode 100644 index 00000000000..2b95831aeec --- /dev/null +++ b/queue-5.4/of-base-fix-some-formatting-issues-and-provide-missi.patch @@ -0,0 +1,105 @@ +From 538e78aea655244d2819a4745898f149e1b99a98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Mar 2021 10:40:30 +0000 +Subject: of: base: Fix some formatting issues and provide missing descriptions + +From: Lee Jones + +[ Upstream commit 3637d49e11219512920aca8b8ccd0994be33fa8b ] + +Fixes the following W=1 kernel build warning(s): + + drivers/of/base.c:315: warning: Function parameter or member 'cpun' not described in '__of_find_n_match_cpu_property' + drivers/of/base.c:315: warning: Function parameter or member 'prop_name' not described in '__of_find_n_match_cpu_property' + drivers/of/base.c:315: warning: Function parameter or member 'cpu' not described in '__of_find_n_match_cpu_property' + drivers/of/base.c:315: warning: Function parameter or member 'thread' not described in '__of_find_n_match_cpu_property' + drivers/of/base.c:315: warning: expecting prototype for property holds the physical id of the(). Prototype was for __of_find_n_match_cpu_property() instead + drivers/of/base.c:1139: warning: Function parameter or member 'match' not described in 'of_find_matching_node_and_match' + drivers/of/base.c:1779: warning: Function parameter or member 'np' not described in '__of_add_property' + drivers/of/base.c:1779: warning: Function parameter or member 'prop' not described in '__of_add_property' + drivers/of/base.c:1800: warning: Function parameter or member 'np' not described in 'of_add_property' + drivers/of/base.c:1800: warning: Function parameter or member 'prop' not described in 'of_add_property' + drivers/of/base.c:1849: warning: Function parameter or member 'np' not described in 'of_remove_property' + drivers/of/base.c:1849: warning: Function parameter or member 'prop' not described in 'of_remove_property' + drivers/of/base.c:2137: warning: Function parameter or member 'dn' not described in 'of_console_check' + drivers/of/base.c:2137: warning: Function parameter or member 'name' not described in 'of_console_check' + drivers/of/base.c:2137: warning: Function parameter or member 'index' not described in 'of_console_check' + +Cc: Rob Herring +Cc: Frank Rowand +Cc: "David S. Miller" +Cc: devicetree@vger.kernel.org +Signed-off-by: Lee Jones +Signed-off-by: Rob Herring +Link: https://lore.kernel.org/r/20210318104036.3175910-5-lee.jones@linaro.org +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/of/base.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 5c97366628b13..4032814133fe6 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -367,7 +367,7 @@ bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) + return (u32)phys_id == cpu; + } + +-/** ++/* + * Checks if the given "prop_name" property holds the physical id of the + * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not + * NULL, local thread number within the core is returned in it. +@@ -1190,7 +1190,7 @@ EXPORT_SYMBOL(of_match_node); + * will; typically, you pass what the previous call + * returned. of_node_put() will be called on it + * @matches: array of of device match structures to search in +- * @match Updated to point at the matches entry which matched ++ * @match: Updated to point at the matches entry which matched + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. +@@ -1853,6 +1853,8 @@ EXPORT_SYMBOL(of_count_phandle_with_args); + + /** + * __of_add_property - Add a property to a node without lock operations ++ * @np: Caller's Device Node ++ * @prob: Property to add + */ + int __of_add_property(struct device_node *np, struct property *prop) + { +@@ -1874,6 +1876,8 @@ int __of_add_property(struct device_node *np, struct property *prop) + + /** + * of_add_property - Add a property to a node ++ * @np: Caller's Device Node ++ * @prob: Property to add + */ + int of_add_property(struct device_node *np, struct property *prop) + { +@@ -1918,6 +1922,8 @@ int __of_remove_property(struct device_node *np, struct property *prop) + + /** + * of_remove_property - Remove a property from a node. ++ * @np: Caller's Device Node ++ * @prob: Property to remove + * + * Note that we don't actually remove it, since we have given out + * who-knows-how-many pointers to the data using get-property. +@@ -2203,9 +2209,9 @@ EXPORT_SYMBOL_GPL(of_alias_get_highest_id); + + /** + * of_console_check() - Test and setup console for DT setup +- * @dn - Pointer to device node +- * @name - Name to use for preferred console without index. ex. "ttyS" +- * @index - Index to use for preferred console. ++ * @dn: Pointer to device node ++ * @name: Name to use for preferred console without index. ex. "ttyS" ++ * @index: Index to use for preferred console. + * + * Check if the given device node matches the stdout-path property in the + * /chosen node. If it does then register it as the preferred console and return +-- +2.42.0 + diff --git a/queue-5.4/of-dynamic-fix-of_reconfig_get_state_change-return-v.patch b/queue-5.4/of-dynamic-fix-of_reconfig_get_state_change-return-v.patch new file mode 100644 index 00000000000..d261538ee1e --- /dev/null +++ b/queue-5.4/of-dynamic-fix-of_reconfig_get_state_change-return-v.patch @@ -0,0 +1,41 @@ +From 8cf8ba72543852f7312e8388fc5f22a995d5eba3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Nov 2023 15:47:18 +0100 +Subject: of: dynamic: Fix of_reconfig_get_state_change() return value + documentation + +From: Luca Ceresoli + +[ Upstream commit d79972789d17499b6091ded2fc0c6763c501a5ba ] + +The documented numeric return values do not match the actual returned +values. Fix them by using the enum names instead of raw numbers. + +Fixes: b53a2340d0d3 ("of/reconfig: Add of_reconfig_get_state_change() of notifier helper.") +Signed-off-by: Luca Ceresoli +Link: https://lore.kernel.org/r/20231123-fix-of_reconfig_get_state_change-docs-v1-1-f51892050ff9@bootlin.com +Signed-off-by: Rob Herring +Signed-off-by: Sasha Levin +--- + drivers/of/dynamic.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c +index 92ee15be78d43..ae969630958cd 100644 +--- a/drivers/of/dynamic.c ++++ b/drivers/of/dynamic.c +@@ -105,8 +105,9 @@ int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p) + * + * Returns the new state of a device based on the notifier used. + * +- * Return: 0 on device going from enabled to disabled, 1 on device +- * going from disabled to enabled and -1 on no change. ++ * Return: OF_RECONFIG_CHANGE_REMOVE on device going from enabled to ++ * disabled, OF_RECONFIG_CHANGE_ADD on device going from disabled to ++ * enabled and OF_RECONFIG_NO_CHANGE on no change. + */ + int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr) + { +-- +2.42.0 + diff --git a/queue-5.4/of-fix-kerneldoc-output-formatting.patch b/queue-5.4/of-fix-kerneldoc-output-formatting.patch new file mode 100644 index 00000000000..56030825501 --- /dev/null +++ b/queue-5.4/of-fix-kerneldoc-output-formatting.patch @@ -0,0 +1,500 @@ +From 19c581a873796822ddf355a4544dfa6550739ede Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Mar 2021 13:26:06 -0600 +Subject: of: Fix kerneldoc output formatting + +From: Rob Herring + +[ Upstream commit 62f026f082e4d762a47b43ea693b38f025122332 ] + +The indentation of the kerneldoc comments affects the output formatting. +Leading tabs in particular don't work, sections need to be indented +under the section header, and several code blocks are reformatted. + +Cc: Frank Rowand +Cc: Mauro Carvalho Chehab +Signed-off-by: Rob Herring +Reviewed-by: Mauro Carvalho Chehab +Link: https://lore.kernel.org/r/20210326192606.3702739-1-robh@kernel.org +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/of/base.c | 275 +++++++++++++++++++++++----------------------- + drivers/of/fdt.c | 9 +- + 2 files changed, 141 insertions(+), 143 deletions(-) + +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 4032814133fe6..c4c64ef5fb7a8 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -713,11 +713,11 @@ bool of_device_is_big_endian(const struct device_node *device) + EXPORT_SYMBOL(of_device_is_big_endian); + + /** +- * of_get_parent - Get a node's parent if any +- * @node: Node to get parent ++ * of_get_parent - Get a node's parent if any ++ * @node: Node to get parent + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_get_parent(const struct device_node *node) + { +@@ -735,15 +735,15 @@ struct device_node *of_get_parent(const struct device_node *node) + EXPORT_SYMBOL(of_get_parent); + + /** +- * of_get_next_parent - Iterate to a node's parent +- * @node: Node to get parent of ++ * of_get_next_parent - Iterate to a node's parent ++ * @node: Node to get parent of + * +- * This is like of_get_parent() except that it drops the +- * refcount on the passed node, making it suitable for iterating +- * through a node's parents. ++ * This is like of_get_parent() except that it drops the ++ * refcount on the passed node, making it suitable for iterating ++ * through a node's parents. + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_get_next_parent(struct device_node *node) + { +@@ -781,13 +781,13 @@ static struct device_node *__of_get_next_child(const struct device_node *node, + child = __of_get_next_child(parent, child)) + + /** +- * of_get_next_child - Iterate a node childs +- * @node: parent node +- * @prev: previous child of the parent node, or NULL to get first ++ * of_get_next_child - Iterate a node childs ++ * @node: parent node ++ * @prev: previous child of the parent node, or NULL to get first + * +- * Returns a node pointer with refcount incremented, use of_node_put() on +- * it when done. Returns NULL when prev is the last child. Decrements the +- * refcount of prev. ++ * Return: A node pointer with refcount incremented, use of_node_put() on ++ * it when done. Returns NULL when prev is the last child. Decrements the ++ * refcount of prev. + */ + struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev) +@@ -803,12 +803,12 @@ struct device_node *of_get_next_child(const struct device_node *node, + EXPORT_SYMBOL(of_get_next_child); + + /** +- * of_get_next_available_child - Find the next available child node +- * @node: parent node +- * @prev: previous child of the parent node, or NULL to get first ++ * of_get_next_available_child - Find the next available child node ++ * @node: parent node ++ * @prev: previous child of the parent node, or NULL to get first + * +- * This function is like of_get_next_child(), except that it +- * automatically skips any disabled nodes (i.e. status = "disabled"). ++ * This function is like of_get_next_child(), except that it ++ * automatically skips any disabled nodes (i.e. status = "disabled"). + */ + struct device_node *of_get_next_available_child(const struct device_node *node, + struct device_node *prev) +@@ -834,12 +834,12 @@ struct device_node *of_get_next_available_child(const struct device_node *node, + EXPORT_SYMBOL(of_get_next_available_child); + + /** +- * of_get_next_cpu_node - Iterate on cpu nodes +- * @prev: previous child of the /cpus node, or NULL to get first ++ * of_get_next_cpu_node - Iterate on cpu nodes ++ * @prev: previous child of the /cpus node, or NULL to get first + * +- * Returns a cpu node pointer with refcount incremented, use of_node_put() +- * on it when done. Returns NULL when prev is the last child. Decrements +- * the refcount of prev. ++ * Return: A cpu node pointer with refcount incremented, use of_node_put() ++ * on it when done. Returns NULL when prev is the last child. Decrements ++ * the refcount of prev. + */ + struct device_node *of_get_next_cpu_node(struct device_node *prev) + { +@@ -896,15 +896,15 @@ struct device_node *of_get_compatible_child(const struct device_node *parent, + EXPORT_SYMBOL(of_get_compatible_child); + + /** +- * of_get_child_by_name - Find the child node by name for a given parent +- * @node: parent node +- * @name: child name to look for. ++ * of_get_child_by_name - Find the child node by name for a given parent ++ * @node: parent node ++ * @name: child name to look for. + * +- * This function looks for child node for given matching name ++ * This function looks for child node for given matching name + * +- * Returns a node pointer if found, with refcount incremented, use +- * of_node_put() on it when done. +- * Returns NULL if node is not found. ++ * Return: A node pointer if found, with refcount incremented, use ++ * of_node_put() on it when done. ++ * Returns NULL if node is not found. + */ + struct device_node *of_get_child_by_name(const struct device_node *node, + const char *name) +@@ -955,22 +955,22 @@ struct device_node *__of_find_node_by_full_path(struct device_node *node, + } + + /** +- * of_find_node_opts_by_path - Find a node matching a full OF path +- * @path: Either the full path to match, or if the path does not +- * start with '/', the name of a property of the /aliases +- * node (an alias). In the case of an alias, the node +- * matching the alias' value will be returned. +- * @opts: Address of a pointer into which to store the start of +- * an options string appended to the end of the path with +- * a ':' separator. +- * +- * Valid paths: +- * /foo/bar Full path +- * foo Valid alias +- * foo/bar Valid alias + relative path +- * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * of_find_node_opts_by_path - Find a node matching a full OF path ++ * @path: Either the full path to match, or if the path does not ++ * start with '/', the name of a property of the /aliases ++ * node (an alias). In the case of an alias, the node ++ * matching the alias' value will be returned. ++ * @opts: Address of a pointer into which to store the start of ++ * an options string appended to the end of the path with ++ * a ':' separator. ++ * ++ * Valid paths: ++ * * /foo/bar Full path ++ * * foo Valid alias ++ * * foo/bar Valid alias + relative path ++ * ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_node_opts_by_path(const char *path, const char **opts) + { +@@ -1020,15 +1020,15 @@ struct device_node *of_find_node_opts_by_path(const char *path, const char **opt + EXPORT_SYMBOL(of_find_node_opts_by_path); + + /** +- * of_find_node_by_name - Find a node by its "name" property +- * @from: The node to start searching from or NULL; the node ++ * of_find_node_by_name - Find a node by its "name" property ++ * @from: The node to start searching from or NULL; the node + * you pass will not be searched, only the next one + * will. Typically, you pass what the previous call + * returned. of_node_put() will be called on @from. +- * @name: The name string to match against ++ * @name: The name string to match against + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +@@ -1047,16 +1047,16 @@ struct device_node *of_find_node_by_name(struct device_node *from, + EXPORT_SYMBOL(of_find_node_by_name); + + /** +- * of_find_node_by_type - Find a node by its "device_type" property +- * @from: The node to start searching from, or NULL to start searching ++ * of_find_node_by_type - Find a node by its "device_type" property ++ * @from: The node to start searching from, or NULL to start searching + * the entire device tree. The node you pass will not be + * searched, only the next one will; typically, you pass + * what the previous call returned. of_node_put() will be + * called on from for you. +- * @type: The type string to match against ++ * @type: The type string to match against + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) +@@ -1075,18 +1075,18 @@ struct device_node *of_find_node_by_type(struct device_node *from, + EXPORT_SYMBOL(of_find_node_by_type); + + /** +- * of_find_compatible_node - Find a node based on type and one of the ++ * of_find_compatible_node - Find a node based on type and one of the + * tokens in its "compatible" property +- * @from: The node to start searching from or NULL, the node +- * you pass will not be searched, only the next one +- * will; typically, you pass what the previous call +- * returned. of_node_put() will be called on it +- * @type: The type string to match "device_type" or NULL to ignore +- * @compatible: The string to match to one of the tokens in the device +- * "compatible" list. +- * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * @from: The node to start searching from or NULL, the node ++ * you pass will not be searched, only the next one ++ * will; typically, you pass what the previous call ++ * returned. of_node_put() will be called on it ++ * @type: The type string to match "device_type" or NULL to ignore ++ * @compatible: The string to match to one of the tokens in the device ++ * "compatible" list. ++ * ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +@@ -1106,16 +1106,16 @@ struct device_node *of_find_compatible_node(struct device_node *from, + EXPORT_SYMBOL(of_find_compatible_node); + + /** +- * of_find_node_with_property - Find a node which has a property with +- * the given name. +- * @from: The node to start searching from or NULL, the node +- * you pass will not be searched, only the next one +- * will; typically, you pass what the previous call +- * returned. of_node_put() will be called on it +- * @prop_name: The name of the property to look for. +- * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * of_find_node_with_property - Find a node which has a property with ++ * the given name. ++ * @from: The node to start searching from or NULL, the node ++ * you pass will not be searched, only the next one ++ * will; typically, you pass what the previous call ++ * returned. of_node_put() will be called on it ++ * @prop_name: The name of the property to look for. ++ * ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_node_with_property(struct device_node *from, + const char *prop_name) +@@ -1164,10 +1164,10 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches, + + /** + * of_match_node - Tell if a device_node has a matching of_match structure +- * @matches: array of of device match structures to search in +- * @node: the of device structure to match against ++ * @matches: array of of device match structures to search in ++ * @node: the of device structure to match against + * +- * Low level utility function used by device matching. ++ * Low level utility function used by device matching. + */ + const struct of_device_id *of_match_node(const struct of_device_id *matches, + const struct device_node *node) +@@ -1183,17 +1183,17 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, + EXPORT_SYMBOL(of_match_node); + + /** +- * of_find_matching_node_and_match - Find a node based on an of_device_id +- * match table. +- * @from: The node to start searching from or NULL, the node +- * you pass will not be searched, only the next one +- * will; typically, you pass what the previous call +- * returned. of_node_put() will be called on it +- * @matches: array of of device match structures to search in +- * @match: Updated to point at the matches entry which matched +- * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * of_find_matching_node_and_match - Find a node based on an of_device_id ++ * match table. ++ * @from: The node to start searching from or NULL, the node ++ * you pass will not be searched, only the next one ++ * will; typically, you pass what the previous call ++ * returned. of_node_put() will be called on it ++ * @matches: array of of device match structures to search in ++ * @match: Updated to point at the matches entry which matched ++ * ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_matching_node_and_match(struct device_node *from, + const struct of_device_id *matches, +@@ -1539,21 +1539,21 @@ EXPORT_SYMBOL(of_parse_phandle); + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * +- * Example: ++ * Example:: + * +- * phandle1: node1 { ++ * phandle1: node1 { + * #list-cells = <2>; +- * } ++ * }; + * +- * phandle2: node2 { ++ * phandle2: node2 { + * #list-cells = <1>; +- * } ++ * }; + * +- * node3 { ++ * node3 { + * list = <&phandle1 1 2 &phandle2 3>; +- * } ++ * }; + * +- * To get a device_node of the `node2' node you may call this: ++ * To get a device_node of the ``node2`` node you may call this: + * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); + */ + int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, +@@ -1591,29 +1591,29 @@ EXPORT_SYMBOL(of_parse_phandle_with_args); + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * +- * Example: ++ * Example:: + * +- * phandle1: node1 { +- * #list-cells = <2>; +- * } ++ * phandle1: node1 { ++ * #list-cells = <2>; ++ * }; + * +- * phandle2: node2 { +- * #list-cells = <1>; +- * } ++ * phandle2: node2 { ++ * #list-cells = <1>; ++ * }; + * +- * phandle3: node3 { +- * #list-cells = <1>; +- * list-map = <0 &phandle2 3>, +- * <1 &phandle2 2>, +- * <2 &phandle1 5 1>; +- * list-map-mask = <0x3>; +- * }; ++ * phandle3: node3 { ++ * #list-cells = <1>; ++ * list-map = <0 &phandle2 3>, ++ * <1 &phandle2 2>, ++ * <2 &phandle1 5 1>; ++ * list-map-mask = <0x3>; ++ * }; + * +- * node4 { +- * list = <&phandle1 1 2 &phandle3 0>; +- * } ++ * node4 { ++ * list = <&phandle1 1 2 &phandle3 0>; ++ * }; + * +- * To get a device_node of the `node2' node you may call this: ++ * To get a device_node of the ``node2`` node you may call this: + * of_parse_phandle_with_args(node4, "list", "list", 1, &args); + */ + int of_parse_phandle_with_args_map(const struct device_node *np, +@@ -1773,19 +1773,19 @@ EXPORT_SYMBOL(of_parse_phandle_with_args_map); + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * +- * Example: ++ * Example:: + * +- * phandle1: node1 { +- * } ++ * phandle1: node1 { ++ * }; + * +- * phandle2: node2 { +- * } ++ * phandle2: node2 { ++ * }; + * +- * node3 { +- * list = <&phandle1 0 2 &phandle2 2 3>; +- * } ++ * node3 { ++ * list = <&phandle1 0 2 &phandle2 2 3>; ++ * }; + * +- * To get a device_node of the `node2' node you may call this: ++ * To get a device_node of the ``node2`` node you may call this: + * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args); + */ + int of_parse_phandle_with_fixed_args(const struct device_node *np, +@@ -2030,13 +2030,12 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np, + + /** + * of_alias_scan - Scan all properties of the 'aliases' node ++ * @dt_alloc: An allocator that provides a virtual address to memory ++ * for storing the resulting tree + * + * The function scans all the properties of the 'aliases' node and populates + * the global lookup table with the properties. It returns the + * number of alias properties found, or an error code in case of failure. +- * +- * @dt_alloc: An allocator that provides a virtual address to memory +- * for storing the resulting tree + */ + void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) + { +@@ -2231,12 +2230,12 @@ bool of_console_check(struct device_node *dn, char *name, int index) + EXPORT_SYMBOL_GPL(of_console_check); + + /** +- * of_find_next_cache_node - Find a node's subsidiary cache +- * @np: node of type "cpu" or "cache" ++ * of_find_next_cache_node - Find a node's subsidiary cache ++ * @np: node of type "cpu" or "cache" + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. Caller should hold a reference +- * to np. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. Caller should hold a reference ++ * to np. + */ + struct device_node *of_find_next_cache_node(const struct device_node *np) + { +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index 6d519ef3c5da4..09a98668e7db0 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -349,11 +349,6 @@ static int unflatten_dt_nodes(const void *blob, + + /** + * __unflatten_device_tree - create tree of device_nodes from flat blob +- * +- * unflattens a device-tree, creating the +- * tree of struct device_node. It also fills the "name" and "type" +- * pointers of the nodes so the normal device-tree walking functions +- * can be used. + * @blob: The blob to expand + * @dad: Parent device node + * @mynodes: The device_node tree created by the call +@@ -361,6 +356,10 @@ static int unflatten_dt_nodes(const void *blob, + * for the resulting tree + * @detached: if true set OF_DETACHED on @mynodes + * ++ * unflattens a device-tree, creating the tree of struct device_node. It also ++ * fills the "name" and "type" pointers of the nodes so the normal device-tree ++ * walking functions can be used. ++ * + * Returns NULL on failure or the memory chunk containing the unflattened + * device tree on success. + */ +-- +2.42.0 + diff --git a/queue-5.4/of-iommu-make-of_map_rid-pci-agnostic.patch b/queue-5.4/of-iommu-make-of_map_rid-pci-agnostic.patch new file mode 100644 index 00000000000..8e799fcfed0 --- /dev/null +++ b/queue-5.4/of-iommu-make-of_map_rid-pci-agnostic.patch @@ -0,0 +1,200 @@ +From 2b931bcceb369affc55fb9f9c80d13f8be41ed1c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2020 09:20:07 +0100 +Subject: of/iommu: Make of_map_rid() PCI agnostic + +From: Lorenzo Pieralisi + +[ Upstream commit 746a71d02b5d15817fcb13c956ba999a87773952 ] + +There is nothing PCI specific (other than the RID - requester ID) +in the of_map_rid() implementation, so the same function can be +reused for input/output IDs mapping for other busses just as well. + +Rename the RID instances/names to a generic "id" tag. + +No functionality change intended. + +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Rob Herring +Acked-by: Joerg Roedel +Cc: Rob Herring +Cc: Joerg Roedel +Cc: Robin Murphy +Cc: Marc Zyngier +Link: https://lore.kernel.org/r/20200619082013.13661-7-lorenzo.pieralisi@arm.com +Signed-off-by: Catalin Marinas +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/iommu/of_iommu.c | 4 ++-- + drivers/of/base.c | 42 ++++++++++++++++++++-------------------- + drivers/of/irq.c | 2 +- + include/linux/of.h | 4 ++-- + 4 files changed, 26 insertions(+), 26 deletions(-) + +diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c +index 614a93aa5305a..656939ed842e7 100644 +--- a/drivers/iommu/of_iommu.c ++++ b/drivers/iommu/of_iommu.c +@@ -121,7 +121,7 @@ static int of_pci_iommu_init(struct pci_dev *pdev, u16 alias, void *data) + struct of_phandle_args iommu_spec = { .args_count = 1 }; + int err; + +- err = of_map_rid(info->np, alias, "iommu-map", "iommu-map-mask", ++ err = of_map_id(info->np, alias, "iommu-map", "iommu-map-mask", + &iommu_spec.np, iommu_spec.args); + if (err) + return err == -ENODEV ? NO_IOMMU : err; +@@ -137,7 +137,7 @@ static int of_fsl_mc_iommu_init(struct fsl_mc_device *mc_dev, + struct of_phandle_args iommu_spec = { .args_count = 1 }; + int err; + +- err = of_map_rid(master_np, mc_dev->icid, "iommu-map", ++ err = of_map_id(master_np, mc_dev->icid, "iommu-map", + "iommu-map-mask", &iommu_spec.np, + iommu_spec.args); + if (err) +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 3f13b982e8b53..5c97366628b13 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -2280,15 +2280,15 @@ int of_find_last_cache_level(unsigned int cpu) + } + + /** +- * of_map_rid - Translate a requester ID through a downstream mapping. ++ * of_map_id - Translate an ID through a downstream mapping. + * @np: root complex device node. +- * @rid: device requester ID to map. ++ * @id: device ID to map. + * @map_name: property name of the map to use. + * @map_mask_name: optional property name of the mask to use. + * @target: optional pointer to a target device node. + * @id_out: optional pointer to receive the translated ID. + * +- * Given a device requester ID, look up the appropriate implementation-defined ++ * Given a device ID, look up the appropriate implementation-defined + * platform ID and/or the target device which receives transactions on that + * ID, as per the "iommu-map" and "msi-map" bindings. Either of @target or + * @id_out may be NULL if only the other is required. If @target points to +@@ -2298,11 +2298,11 @@ int of_find_last_cache_level(unsigned int cpu) + * + * Return: 0 on success or a standard error code on failure. + */ +-int of_map_rid(struct device_node *np, u32 rid, ++int of_map_id(struct device_node *np, u32 id, + const char *map_name, const char *map_mask_name, + struct device_node **target, u32 *id_out) + { +- u32 map_mask, masked_rid; ++ u32 map_mask, masked_id; + int map_len; + const __be32 *map = NULL; + +@@ -2314,7 +2314,7 @@ int of_map_rid(struct device_node *np, u32 rid, + if (target) + return -ENODEV; + /* Otherwise, no map implies no translation */ +- *id_out = rid; ++ *id_out = id; + return 0; + } + +@@ -2334,22 +2334,22 @@ int of_map_rid(struct device_node *np, u32 rid, + if (map_mask_name) + of_property_read_u32(np, map_mask_name, &map_mask); + +- masked_rid = map_mask & rid; ++ masked_id = map_mask & id; + for ( ; map_len > 0; map_len -= 4 * sizeof(*map), map += 4) { + struct device_node *phandle_node; +- u32 rid_base = be32_to_cpup(map + 0); ++ u32 id_base = be32_to_cpup(map + 0); + u32 phandle = be32_to_cpup(map + 1); + u32 out_base = be32_to_cpup(map + 2); +- u32 rid_len = be32_to_cpup(map + 3); ++ u32 id_len = be32_to_cpup(map + 3); + +- if (rid_base & ~map_mask) { +- pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores rid-base (0x%x)\n", ++ if (id_base & ~map_mask) { ++ pr_err("%pOF: Invalid %s translation - %s-mask (0x%x) ignores id-base (0x%x)\n", + np, map_name, map_name, +- map_mask, rid_base); ++ map_mask, id_base); + return -EFAULT; + } + +- if (masked_rid < rid_base || masked_rid >= rid_base + rid_len) ++ if (masked_id < id_base || masked_id >= id_base + id_len) + continue; + + phandle_node = of_find_node_by_phandle(phandle); +@@ -2367,20 +2367,20 @@ int of_map_rid(struct device_node *np, u32 rid, + } + + if (id_out) +- *id_out = masked_rid - rid_base + out_base; ++ *id_out = masked_id - id_base + out_base; + +- pr_debug("%pOF: %s, using mask %08x, rid-base: %08x, out-base: %08x, length: %08x, rid: %08x -> %08x\n", +- np, map_name, map_mask, rid_base, out_base, +- rid_len, rid, masked_rid - rid_base + out_base); ++ pr_debug("%pOF: %s, using mask %08x, id-base: %08x, out-base: %08x, length: %08x, id: %08x -> %08x\n", ++ np, map_name, map_mask, id_base, out_base, ++ id_len, id, masked_id - id_base + out_base); + return 0; + } + +- pr_info("%pOF: no %s translation for rid 0x%x on %pOF\n", np, map_name, +- rid, target && *target ? *target : NULL); ++ pr_info("%pOF: no %s translation for id 0x%x on %pOF\n", np, map_name, ++ id, target && *target ? *target : NULL); + + /* Bypasses translation */ + if (id_out) +- *id_out = rid; ++ *id_out = id; + return 0; + } +-EXPORT_SYMBOL_GPL(of_map_rid); ++EXPORT_SYMBOL_GPL(of_map_id); +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index a296eaf52a5b2..d632bc5b3a2de 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -587,7 +587,7 @@ static u32 __of_msi_map_rid(struct device *dev, struct device_node **np, + * "msi-map" property. + */ + for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) +- if (!of_map_rid(parent_dev->of_node, rid_in, "msi-map", ++ if (!of_map_id(parent_dev->of_node, rid_in, "msi-map", + "msi-map-mask", np, &rid_out)) + break; + return rid_out; +diff --git a/include/linux/of.h b/include/linux/of.h +index e29b341598e99..e070c5ed62a09 100644 +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -554,7 +554,7 @@ bool of_console_check(struct device_node *dn, char *name, int index); + + extern int of_cpu_node_to_id(struct device_node *np); + +-int of_map_rid(struct device_node *np, u32 rid, ++int of_map_id(struct device_node *np, u32 id, + const char *map_name, const char *map_mask_name, + struct device_node **target, u32 *id_out); + +@@ -978,7 +978,7 @@ static inline int of_cpu_node_to_id(struct device_node *np) + return -ENODEV; + } + +-static inline int of_map_rid(struct device_node *np, u32 rid, ++static inline int of_map_id(struct device_node *np, u32 id, + const char *map_name, const char *map_mask_name, + struct device_node **target, u32 *id_out) + { +-- +2.42.0 + diff --git a/queue-5.4/of-irq-make-of_msi_map_get_device_domain-bus-agnosti.patch b/queue-5.4/of-irq-make-of_msi_map_get_device_domain-bus-agnosti.patch new file mode 100644 index 00000000000..218ea1a49a5 --- /dev/null +++ b/queue-5.4/of-irq-make-of_msi_map_get_device_domain-bus-agnosti.patch @@ -0,0 +1,97 @@ +From de174d191aecc6a69cf5c44bec20c17a5dc931f8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2020 09:20:10 +0100 +Subject: of/irq: make of_msi_map_get_device_domain() bus agnostic + +From: Diana Craciun + +[ Upstream commit 6f881aba01109a01a43e4f135673c19190f61133 ] + +of_msi_map_get_device_domain() is PCI specific but it need not be and +can be easily changed to be bus agnostic in order to be used by other +busses by adding an IRQ domain bus token as an input parameter. + +Signed-off-by: Diana Craciun +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Rob Herring +Acked-by: Bjorn Helgaas # pci/msi.c +Cc: Bjorn Helgaas +Cc: Rob Herring +Cc: Marc Zyngier +Link: https://lore.kernel.org/r/20200619082013.13661-10-lorenzo.pieralisi@arm.com +Signed-off-by: Catalin Marinas +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/of/irq.c | 8 +++++--- + drivers/pci/msi.c | 2 +- + include/linux/of_irq.h | 5 +++-- + 3 files changed, 9 insertions(+), 6 deletions(-) + +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index d632bc5b3a2de..1005e4f349ef6 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -613,18 +613,20 @@ u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in) + * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain + * @dev: device for which the mapping is to be done. + * @rid: Requester ID for the device. ++ * @bus_token: Bus token + * + * Walk up the device hierarchy looking for devices with a "msi-map" + * property. + * + * Returns: the MSI domain for this device (or NULL on failure) + */ +-struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 rid) ++struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id, ++ u32 bus_token) + { + struct device_node *np = NULL; + +- __of_msi_map_rid(dev, &np, rid); +- return irq_find_matching_host(np, DOMAIN_BUS_PCI_MSI); ++ __of_msi_map_rid(dev, &np, id); ++ return irq_find_matching_host(np, bus_token); + } + + /** +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index cc863cdd5cc74..392d2ecf7dc89 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -1624,7 +1624,7 @@ struct irq_domain *pci_msi_get_device_domain(struct pci_dev *pdev) + u32 rid = pci_dev_id(pdev); + + pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid); +- dom = of_msi_map_get_device_domain(&pdev->dev, rid); ++ dom = of_msi_map_get_device_domain(&pdev->dev, rid, DOMAIN_BUS_PCI_MSI); + if (!dom) + dom = iort_get_device_domain(&pdev->dev, rid, + DOMAIN_BUS_PCI_MSI); +diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h +index 1214cabb22479..7142a37227584 100644 +--- a/include/linux/of_irq.h ++++ b/include/linux/of_irq.h +@@ -52,7 +52,8 @@ extern struct irq_domain *of_msi_get_domain(struct device *dev, + struct device_node *np, + enum irq_domain_bus_token token); + extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev, +- u32 rid); ++ u32 id, ++ u32 bus_token); + extern void of_msi_configure(struct device *dev, struct device_node *np); + u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in); + #else +@@ -85,7 +86,7 @@ static inline struct irq_domain *of_msi_get_domain(struct device *dev, + return NULL; + } + static inline struct irq_domain *of_msi_map_get_device_domain(struct device *dev, +- u32 rid) ++ u32 id, u32 bus_token) + { + return NULL; + } +-- +2.42.0 + diff --git a/queue-5.4/of-irq-make-of_msi_map_rid-pci-bus-agnostic.patch b/queue-5.4/of-irq-make-of_msi_map_rid-pci-bus-agnostic.patch new file mode 100644 index 00000000000..e5a7b159d95 --- /dev/null +++ b/queue-5.4/of-irq-make-of_msi_map_rid-pci-bus-agnostic.patch @@ -0,0 +1,145 @@ +From 43feea6bf296097366432b53034ab33b6901773a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 19 Jun 2020 09:20:11 +0100 +Subject: of/irq: Make of_msi_map_rid() PCI bus agnostic + +From: Lorenzo Pieralisi + +[ Upstream commit 2bcdd8f2c07f1aa1bfd34fa0dab8e06949e34846 ] + +There is nothing PCI bus specific in the of_msi_map_rid() +implementation other than the requester ID tag for the input +ID space. Rename requester ID to a more generic ID so that +the translation code can be used by all busses that require +input/output ID translations. + +No functional change intended. + +Signed-off-by: Lorenzo Pieralisi +Reviewed-by: Rob Herring +Cc: Bjorn Helgaas +Cc: Rob Herring +Cc: Marc Zyngier +Link: https://lore.kernel.org/r/20200619082013.13661-11-lorenzo.pieralisi@arm.com +Signed-off-by: Catalin Marinas +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/of/irq.c | 28 ++++++++++++++-------------- + drivers/pci/msi.c | 2 +- + include/linux/of_irq.h | 8 ++++---- + 3 files changed, 19 insertions(+), 19 deletions(-) + +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index 1005e4f349ef6..25d17b8a1a1aa 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -576,43 +576,43 @@ void __init of_irq_init(const struct of_device_id *matches) + } + } + +-static u32 __of_msi_map_rid(struct device *dev, struct device_node **np, +- u32 rid_in) ++static u32 __of_msi_map_id(struct device *dev, struct device_node **np, ++ u32 id_in) + { + struct device *parent_dev; +- u32 rid_out = rid_in; ++ u32 id_out = id_in; + + /* + * Walk up the device parent links looking for one with a + * "msi-map" property. + */ + for (parent_dev = dev; parent_dev; parent_dev = parent_dev->parent) +- if (!of_map_id(parent_dev->of_node, rid_in, "msi-map", +- "msi-map-mask", np, &rid_out)) ++ if (!of_map_id(parent_dev->of_node, id_in, "msi-map", ++ "msi-map-mask", np, &id_out)) + break; +- return rid_out; ++ return id_out; + } + + /** +- * of_msi_map_rid - Map a MSI requester ID for a device. ++ * of_msi_map_id - Map a MSI ID for a device. + * @dev: device for which the mapping is to be done. + * @msi_np: device node of the expected msi controller. +- * @rid_in: unmapped MSI requester ID for the device. ++ * @id_in: unmapped MSI ID for the device. + * + * Walk up the device hierarchy looking for devices with a "msi-map" +- * property. If found, apply the mapping to @rid_in. ++ * property. If found, apply the mapping to @id_in. + * +- * Returns the mapped MSI requester ID. ++ * Returns the mapped MSI ID. + */ +-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in) ++u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in) + { +- return __of_msi_map_rid(dev, &msi_np, rid_in); ++ return __of_msi_map_id(dev, &msi_np, id_in); + } + + /** + * of_msi_map_get_device_domain - Use msi-map to find the relevant MSI domain + * @dev: device for which the mapping is to be done. +- * @rid: Requester ID for the device. ++ * @id: Device ID. + * @bus_token: Bus token + * + * Walk up the device hierarchy looking for devices with a "msi-map" +@@ -625,7 +625,7 @@ struct irq_domain *of_msi_map_get_device_domain(struct device *dev, u32 id, + { + struct device_node *np = NULL; + +- __of_msi_map_rid(dev, &np, id); ++ __of_msi_map_id(dev, &np, id); + return irq_find_matching_host(np, bus_token); + } + +diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c +index 392d2ecf7dc89..c4f4a8a3bf8fa 100644 +--- a/drivers/pci/msi.c ++++ b/drivers/pci/msi.c +@@ -1603,7 +1603,7 @@ u32 pci_msi_domain_get_msi_rid(struct irq_domain *domain, struct pci_dev *pdev) + pci_for_each_dma_alias(pdev, get_msi_id_cb, &rid); + + of_node = irq_domain_get_of_node(domain); +- rid = of_node ? of_msi_map_rid(&pdev->dev, of_node, rid) : ++ rid = of_node ? of_msi_map_id(&pdev->dev, of_node, rid) : + iort_msi_map_id(&pdev->dev, rid); + + return rid; +diff --git a/include/linux/of_irq.h b/include/linux/of_irq.h +index 7142a37227584..e8b78139f78c5 100644 +--- a/include/linux/of_irq.h ++++ b/include/linux/of_irq.h +@@ -55,7 +55,7 @@ extern struct irq_domain *of_msi_map_get_device_domain(struct device *dev, + u32 id, + u32 bus_token); + extern void of_msi_configure(struct device *dev, struct device_node *np); +-u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in); ++u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in); + #else + static inline int of_irq_count(struct device_node *dev) + { +@@ -93,10 +93,10 @@ static inline struct irq_domain *of_msi_map_get_device_domain(struct device *dev + static inline void of_msi_configure(struct device *dev, struct device_node *np) + { + } +-static inline u32 of_msi_map_rid(struct device *dev, +- struct device_node *msi_np, u32 rid_in) ++static inline u32 of_msi_map_id(struct device *dev, ++ struct device_node *msi_np, u32 id_in) + { +- return rid_in; ++ return id_in; + } + #endif + +-- +2.42.0 + diff --git a/queue-5.4/series b/queue-5.4/series index 4e41304178e..3b048e56bc6 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -4,3 +4,23 @@ tg3-move-the-rt-x_dropped-counters-to-tg3_napi.patch tg3-increment-tx_dropped-in-tg3_tso_bug.patch kconfig-fix-memory-leak-from-range-properties.patch drm-amdgpu-correct-chunk_ptr-to-a-pointer-to-chunk.patch +of-base-add-of_get_cpu_state_node-to-get-idle-states.patch +acpi-iort-make-iort_get_device_domain-irq-domain-agn.patch +acpi-iort-make-iort_msi_map_rid-pci-agnostic.patch +of-iommu-make-of_map_rid-pci-agnostic.patch +of-irq-make-of_msi_map_get_device_domain-bus-agnosti.patch +of-irq-make-of_msi_map_rid-pci-bus-agnostic.patch +of-base-fix-some-formatting-issues-and-provide-missi.patch +of-fix-kerneldoc-output-formatting.patch +of-add-missing-return-section-in-kerneldoc-comments.patch +of-dynamic-fix-of_reconfig_get_state_change-return-v.patch +ipv6-fix-potential-null-deref-in-fib6_add.patch +hv_netvsc-rndis_filter-needs-to-select-nls.patch +net-arcnet-fix-reset-flag-handling.patch +net-arcnet-com20020-fix-error-handling.patch +arcnet-restoring-support-for-multiple-sohard-arcnet-.patch +ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch +net-hns-fix-fake-link-up-on-xge-port.patch +netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch +tcp-do-not-accept-ack-of-bytes-we-never-sent.patch +bpf-sockmap-updating-the-sg-structure-should-also-up.patch diff --git a/queue-5.4/tcp-do-not-accept-ack-of-bytes-we-never-sent.patch b/queue-5.4/tcp-do-not-accept-ack-of-bytes-we-never-sent.patch new file mode 100644 index 00000000000..d90550e51d1 --- /dev/null +++ b/queue-5.4/tcp-do-not-accept-ack-of-bytes-we-never-sent.patch @@ -0,0 +1,106 @@ +From 6ed64c74adf1266ed9d54c2d0ec702181db3072d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Dec 2023 16:18:41 +0000 +Subject: tcp: do not accept ACK of bytes we never sent + +From: Eric Dumazet + +[ Upstream commit 3d501dd326fb1c73f1b8206d4c6e1d7b15c07e27 ] + +This patch is based on a detailed report and ideas from Yepeng Pan +and Christian Rossow. + +ACK seq validation is currently following RFC 5961 5.2 guidelines: + + The ACK value is considered acceptable only if + it is in the range of ((SND.UNA - MAX.SND.WND) <= SEG.ACK <= + SND.NXT). All incoming segments whose ACK value doesn't satisfy the + above condition MUST be discarded and an ACK sent back. It needs to + be noted that RFC 793 on page 72 (fifth check) says: "If the ACK is a + duplicate (SEG.ACK < SND.UNA), it can be ignored. If the ACK + acknowledges something not yet sent (SEG.ACK > SND.NXT) then send an + ACK, drop the segment, and return". The "ignored" above implies that + the processing of the incoming data segment continues, which means + the ACK value is treated as acceptable. This mitigation makes the + ACK check more stringent since any ACK < SND.UNA wouldn't be + accepted, instead only ACKs that are in the range ((SND.UNA - + MAX.SND.WND) <= SEG.ACK <= SND.NXT) get through. + +This can be refined for new (and possibly spoofed) flows, +by not accepting ACK for bytes that were never sent. + +This greatly improves TCP security at a little cost. + +I added a Fixes: tag to make sure this patch will reach stable trees, +even if the 'blamed' patch was adhering to the RFC. + +tp->bytes_acked was added in linux-4.2 + +Following packetdrill test (courtesy of Yepeng Pan) shows +the issue at hand: + +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 ++0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 ++0 bind(3, ..., ...) = 0 ++0 listen(3, 1024) = 0 + +// ---------------- Handshake ------------------- // + +// when window scale is set to 14 the window size can be extended to +// 65535 * (2^14) = 1073725440. Linux would accept an ACK packet +// with ack number in (Server_ISN+1-1073725440. Server_ISN+1) +// ,though this ack number acknowledges some data never +// sent by the server. + ++0 < S 0:0(0) win 65535 ++0 > S. 0:0(0) ack 1 <...> ++0 < . 1:1(0) ack 1 win 65535 ++0 accept(3, ..., ...) = 4 + +// For the established connection, we send an ACK packet, +// the ack packet uses ack number 1 - 1073725300 + 2^32, +// where 2^32 is used to wrap around. +// Note: we used 1073725300 instead of 1073725440 to avoid possible +// edge cases. +// 1 - 1073725300 + 2^32 = 3221241997 + +// Oops, old kernels happily accept this packet. ++0 < . 1:1001(1000) ack 3221241997 win 65535 + +// After the kernel fix the following will be replaced by a challenge ACK, +// and prior malicious frame would be dropped. ++0 > . 1:1(0) ack 1001 + +Fixes: 354e4aa391ed ("tcp: RFC 5961 5.2 Blind Data Injection Attack Mitigation") +Signed-off-by: Eric Dumazet +Reported-by: Yepeng Pan +Reported-by: Christian Rossow +Acked-by: Neal Cardwell +Link: https://lore.kernel.org/r/20231205161841.2702925-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_input.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index fe5ef114beba5..982fe464156a4 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3657,8 +3657,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + * then we can probably ignore it. + */ + if (before(ack, prior_snd_una)) { ++ u32 max_window; ++ ++ /* do not accept ACK for bytes we never sent. */ ++ max_window = min_t(u64, tp->max_window, tp->bytes_acked); + /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ +- if (before(ack, prior_snd_una - tp->max_window)) { ++ if (before(ack, prior_snd_una - max_window)) { + if (!(flag & FLAG_NO_CHALLENGE_ACK)) + tcp_send_challenge_ack(sk, skb); + return -1; +-- +2.42.0 +