From 83c510568ec52f8eb00abf45bf35fbae9b97390e Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Tue, 31 Aug 2021 22:16:30 +0200 Subject: misc: rtsx: Remove usage of the deprecated "pci-dma-compat.h" API In [1], Christoph Hellwig has proposed to remove the wrappers in include/linux/pci-dma-compat.h. Some reasons why this API should be removed have been given by Julia Lawall in [2]. Finally, Arnd Bergmann reminded that the documentation was updated 11 years ago to only describe the modern linux/dma-mapping.h interfaces and mark the old bus-specific ones as no longer recommended, see commit 216bf58f4092 ("Documentation: convert PCI-DMA-mapping.txt to use the generic DMA API"). A coccinelle script has been used to perform the needed transformation Only relevant parts are given below. @@ expression e1, e2; @@ - pci_set_dma_mask(e1, e2) + dma_set_mask(&e1->dev, e2) [1]: https://lore.kernel.org/kernel-janitors/20200421081257.GA131897@infradead.org/ [2]: https://lore.kernel.org/kernel-janitors/alpine.DEB.2.22.394.2007120902170.2424@hadrien/ Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/95752079d0e2bb1613f0f3a53f13f642f5c72572.1630440769.git.christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/misc/cardreader/rtsx_pcr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/cardreader/rtsx_pcr.c b/drivers/misc/cardreader/rtsx_pcr.c index baf83594a01d..8c72eb590f79 100644 --- a/drivers/misc/cardreader/rtsx_pcr.c +++ b/drivers/misc/cardreader/rtsx_pcr.c @@ -1536,7 +1536,7 @@ static int rtsx_pci_probe(struct pci_dev *pcidev, pci_name(pcidev), (int)pcidev->vendor, (int)pcidev->device, (int)pcidev->revision); - ret = pci_set_dma_mask(pcidev, DMA_BIT_MASK(32)); + ret = dma_set_mask(&pcidev->dev, DMA_BIT_MASK(32)); if (ret < 0) return ret; -- cgit v1.2.3 From a34993a2791c507d6941582f37c9776257662523 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 3 Sep 2021 11:28:33 +0200 Subject: misc: hisi_hikey_usb: change the DT schema As there's no upstream DT bindings for this driver, let's update its DT schema, while it is not too late. While here, add error messages, in order to help discovering problems during probing time. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/746237a6bdbb84d4271a77994c82bccf524680c7.1630659949.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/hisi_hikey_usb.c | 119 ++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 56 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c index 989d7d129469..2165ec35a343 100644 --- a/drivers/misc/hisi_hikey_usb.c +++ b/drivers/misc/hisi_hikey_usb.c @@ -34,7 +34,6 @@ struct hisi_hikey_usb { struct device *dev; struct gpio_desc *otg_switch; struct gpio_desc *typec_vbus; - struct gpio_desc *hub_vbus; struct gpio_desc *reset; struct regulator *regulator; @@ -54,9 +53,6 @@ static void hub_power_ctrl(struct hisi_hikey_usb *hisi_hikey_usb, int value) { int ret, status; - if (hisi_hikey_usb->hub_vbus) - gpiod_set_value_cansleep(hisi_hikey_usb->hub_vbus, value); - if (!hisi_hikey_usb->regulator) return; @@ -147,75 +143,50 @@ static int hub_usb_role_switch_set(struct usb_role_switch *sw, enum usb_role rol return 0; } -static int hisi_hikey_usb_parse_kirin970(struct platform_device *pdev, +static int hisi_hikey_usb_of_role_switch(struct platform_device *pdev, struct hisi_hikey_usb *hisi_hikey_usb) -{ - struct regulator *regulator; - - regulator = devm_regulator_get(&pdev->dev, "hub-vdd"); - if (IS_ERR(regulator)) { - if (PTR_ERR(regulator) == -EPROBE_DEFER) { - dev_info(&pdev->dev, - "waiting for hub-vdd-supply to be probed\n"); - return PTR_ERR(regulator); - } - dev_err(&pdev->dev, - "get hub-vdd-supply failed with error %ld\n", - PTR_ERR(regulator)); - return PTR_ERR(regulator); - } - hisi_hikey_usb->regulator = regulator; - - hisi_hikey_usb->reset = devm_gpiod_get(&pdev->dev, "hub_reset_en_gpio", - GPIOD_OUT_HIGH); - return PTR_ERR_OR_ZERO(hisi_hikey_usb->reset); -} - -static int hisi_hikey_usb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct hisi_hikey_usb *hisi_hikey_usb; struct usb_role_switch_desc hub_role_switch = {NULL}; - int ret; - hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL); - if (!hisi_hikey_usb) - return -ENOMEM; - - hisi_hikey_usb->dev = &pdev->dev; + if (!device_property_read_bool(dev, "usb-role-switch")) + return 0; hisi_hikey_usb->otg_switch = devm_gpiod_get(dev, "otg-switch", GPIOD_OUT_HIGH); - if (IS_ERR(hisi_hikey_usb->otg_switch)) + if (IS_ERR(hisi_hikey_usb->otg_switch)) { + dev_err(dev, "get otg-switch failed with error %ld\n", + PTR_ERR(hisi_hikey_usb->otg_switch)); return PTR_ERR(hisi_hikey_usb->otg_switch); + } hisi_hikey_usb->typec_vbus = devm_gpiod_get(dev, "typec-vbus", GPIOD_OUT_LOW); - if (IS_ERR(hisi_hikey_usb->typec_vbus)) + if (IS_ERR(hisi_hikey_usb->typec_vbus)) { + dev_err(dev, "get typec-vbus failed with error %ld\n", + PTR_ERR(hisi_hikey_usb->typec_vbus)); return PTR_ERR(hisi_hikey_usb->typec_vbus); + } - /* Parse Kirin 970-specific OF data */ - if (of_device_is_compatible(pdev->dev.of_node, - "hisilicon,kirin970_hikey_usbhub")) { - ret = hisi_hikey_usb_parse_kirin970(pdev, hisi_hikey_usb); - if (ret) - return ret; - } else { - /* hub-vdd33-en is optional */ - hisi_hikey_usb->hub_vbus = devm_gpiod_get_optional(dev, "hub-vdd33-en", - GPIOD_OUT_HIGH); - if (IS_ERR(hisi_hikey_usb->hub_vbus)) - return PTR_ERR(hisi_hikey_usb->hub_vbus); + hisi_hikey_usb->reset = devm_gpiod_get_optional(dev, + "hub-reset-en", + GPIOD_OUT_HIGH); + if (IS_ERR(hisi_hikey_usb->reset)) { + dev_err(dev, "get hub-reset-en failed with error %ld\n", + PTR_ERR(hisi_hikey_usb->reset)); + return PTR_ERR(hisi_hikey_usb->reset); } hisi_hikey_usb->dev_role_sw = usb_role_switch_get(dev); if (!hisi_hikey_usb->dev_role_sw) return -EPROBE_DEFER; - if (IS_ERR(hisi_hikey_usb->dev_role_sw)) + if (IS_ERR(hisi_hikey_usb->dev_role_sw)) { + dev_err(dev, "get device role switch failed with error %ld\n", + PTR_ERR(hisi_hikey_usb->dev_role_sw)); return PTR_ERR(hisi_hikey_usb->dev_role_sw); + } INIT_WORK(&hisi_hikey_usb->work, relay_set_role_switch); - mutex_init(&hisi_hikey_usb->lock); hub_role_switch.fwnode = dev_fwnode(dev); hub_role_switch.set = hub_usb_role_switch_set; @@ -225,10 +196,44 @@ static int hisi_hikey_usb_probe(struct platform_device *pdev) &hub_role_switch); if (IS_ERR(hisi_hikey_usb->hub_role_sw)) { + dev_err(dev, + "failed to register hub role with error %ld\n", + PTR_ERR(hisi_hikey_usb->hub_role_sw)); usb_role_switch_put(hisi_hikey_usb->dev_role_sw); return PTR_ERR(hisi_hikey_usb->hub_role_sw); } + return 0; +} + +static int hisi_hikey_usb_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct hisi_hikey_usb *hisi_hikey_usb; + int ret; + + hisi_hikey_usb = devm_kzalloc(dev, sizeof(*hisi_hikey_usb), GFP_KERNEL); + if (!hisi_hikey_usb) + return -ENOMEM; + + hisi_hikey_usb->dev = &pdev->dev; + mutex_init(&hisi_hikey_usb->lock); + + hisi_hikey_usb->regulator = devm_regulator_get(dev, "hub-vdd"); + if (IS_ERR(hisi_hikey_usb->regulator)) { + if (PTR_ERR(hisi_hikey_usb->regulator) == -EPROBE_DEFER) { + dev_info(dev, "waiting for hub-vdd-supply\n"); + return PTR_ERR(hisi_hikey_usb->regulator); + } + dev_err(dev, "get hub-vdd-supply failed with error %ld\n", + PTR_ERR(hisi_hikey_usb->regulator)); + return PTR_ERR(hisi_hikey_usb->regulator); + } + + ret = hisi_hikey_usb_of_role_switch(pdev, hisi_hikey_usb); + if (ret) + return ret; + platform_set_drvdata(pdev, hisi_hikey_usb); return 0; @@ -238,18 +243,20 @@ static int hisi_hikey_usb_remove(struct platform_device *pdev) { struct hisi_hikey_usb *hisi_hikey_usb = platform_get_drvdata(pdev); - if (hisi_hikey_usb->hub_role_sw) + if (hisi_hikey_usb->hub_role_sw) { usb_role_switch_unregister(hisi_hikey_usb->hub_role_sw); - if (hisi_hikey_usb->dev_role_sw) - usb_role_switch_put(hisi_hikey_usb->dev_role_sw); + if (hisi_hikey_usb->dev_role_sw) + usb_role_switch_put(hisi_hikey_usb->dev_role_sw); + } else { + hub_power_ctrl(hisi_hikey_usb, HUB_VBUS_POWER_OFF); + } return 0; } static const struct of_device_id id_table_hisi_hikey_usb[] = { - { .compatible = "hisilicon,gpio_hubv1" }, - { .compatible = "hisilicon,kirin970_hikey_usbhub" }, + { .compatible = "hisilicon,usbhub" }, {} }; MODULE_DEVICE_TABLE(of, id_table_hisi_hikey_usb); -- cgit v1.2.3 From 33a430419456991480cde9d8889e5a27f6049df4 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 29 Aug 2021 15:43:52 +0300 Subject: pvpanic: Keep single style across modules We have different style on where we place module_*() and MODULE_*() macros. Inherit the style from the original module (now pvpanic-mmio.c). Reviewed-by: Mihai Carabas Link: https://lore.kernel.org/r/20210829124354.81653-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic/pvpanic-pci.c | 14 ++++++-------- drivers/misc/pvpanic/pvpanic.c | 3 +-- 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c index 741116b3d995..7d1220f4c95b 100644 --- a/drivers/misc/pvpanic/pvpanic-pci.c +++ b/drivers/misc/pvpanic/pvpanic-pci.c @@ -22,11 +22,6 @@ MODULE_AUTHOR("Mihai Carabas "); MODULE_DESCRIPTION("pvpanic device driver "); MODULE_LICENSE("GPL"); -static const struct pci_device_id pvpanic_pci_id_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_PVPANIC)}, - {} -}; - static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -99,6 +94,12 @@ static int pvpanic_pci_probe(struct pci_dev *pdev, return devm_pvpanic_probe(&pdev->dev, pi); } +static const struct pci_device_id pvpanic_pci_id_tbl[] = { + { PCI_DEVICE(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_REDHAT_PVPANIC)}, + {} +}; +MODULE_DEVICE_TABLE(pci, pvpanic_pci_id_tbl); + static struct pci_driver pvpanic_pci_driver = { .name = "pvpanic-pci", .id_table = pvpanic_pci_id_tbl, @@ -107,7 +108,4 @@ static struct pci_driver pvpanic_pci_driver = { .dev_groups = pvpanic_pci_dev_groups, }, }; - -MODULE_DEVICE_TABLE(pci, pvpanic_pci_id_tbl); - module_pci_driver(pvpanic_pci_driver); diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c index bb7aa6368538..f073c2efc3ae 100644 --- a/drivers/misc/pvpanic/pvpanic.c +++ b/drivers/misc/pvpanic/pvpanic.c @@ -101,6 +101,7 @@ static int pvpanic_init(void) return 0; } +module_init(pvpanic_init); static void pvpanic_exit(void) { @@ -108,6 +109,4 @@ static void pvpanic_exit(void) &pvpanic_panic_nb); } - -module_init(pvpanic_init); module_exit(pvpanic_exit); -- cgit v1.2.3 From cc5b392d0f94f27743583140d819fa35a46899db Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 29 Aug 2021 15:43:53 +0300 Subject: pvpanic: Fix typos in the comments Fix a few spelling typos in the comments. Reviewed-by: Mihai Carabas Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210829124354.81653-2-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic/pvpanic-mmio.c | 2 +- drivers/misc/pvpanic/pvpanic.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic/pvpanic-mmio.c b/drivers/misc/pvpanic/pvpanic-mmio.c index be4016084979..61dbff5f0065 100644 --- a/drivers/misc/pvpanic/pvpanic-mmio.c +++ b/drivers/misc/pvpanic/pvpanic-mmio.c @@ -100,7 +100,7 @@ static int pvpanic_mmio_probe(struct platform_device *pdev) pi->base = base; pi->capability = PVPANIC_PANICKED | PVPANIC_CRASH_LOADED; - /* initlize capability by RDPT */ + /* initialize capability by RDPT */ pi->capability &= ioread8(base); pi->events = pi->capability; diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c index f073c2efc3ae..6ffc8c2e5b04 100644 --- a/drivers/misc/pvpanic/pvpanic.c +++ b/drivers/misc/pvpanic/pvpanic.c @@ -58,7 +58,7 @@ pvpanic_panic_notify(struct notifier_block *nb, unsigned long code, static struct notifier_block pvpanic_panic_nb = { .notifier_call = pvpanic_panic_notify, - .priority = 1, /* let this called before broken drm_fb_helper */ + .priority = 1, /* let this called before broken drm_fb_helper() */ }; static void pvpanic_remove(void *param) -- cgit v1.2.3 From 84b0f12a953c4feff9994b1c4583ed18b441f482 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Sun, 29 Aug 2021 15:43:54 +0300 Subject: pvpanic: Indentation fixes here and there 1) replace double spaces with single; 2) relax line width limitation a bit. Reviewed-by: Mihai Carabas Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210829124354.81653-3-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/pvpanic/pvpanic-mmio.c | 7 +++---- drivers/misc/pvpanic/pvpanic-pci.c | 12 +++++------- drivers/misc/pvpanic/pvpanic.c | 11 ++++------- 3 files changed, 12 insertions(+), 18 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/pvpanic/pvpanic-mmio.c b/drivers/misc/pvpanic/pvpanic-mmio.c index 61dbff5f0065..eb97167c03fb 100644 --- a/drivers/misc/pvpanic/pvpanic-mmio.c +++ b/drivers/misc/pvpanic/pvpanic-mmio.c @@ -24,8 +24,7 @@ MODULE_AUTHOR("Hu Tao "); MODULE_DESCRIPTION("pvpanic-mmio device driver"); MODULE_LICENSE("GPL"); -static ssize_t capability_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pvpanic_instance *pi = dev_get_drvdata(dev); @@ -33,14 +32,14 @@ static ssize_t capability_show(struct device *dev, } static DEVICE_ATTR_RO(capability); -static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pvpanic_instance *pi = dev_get_drvdata(dev); return sysfs_emit(buf, "%x\n", pi->events); } -static ssize_t events_store(struct device *dev, struct device_attribute *attr, +static ssize_t events_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct pvpanic_instance *pi = dev_get_drvdata(dev); diff --git a/drivers/misc/pvpanic/pvpanic-pci.c b/drivers/misc/pvpanic/pvpanic-pci.c index 7d1220f4c95b..07eddb5ea30f 100644 --- a/drivers/misc/pvpanic/pvpanic-pci.c +++ b/drivers/misc/pvpanic/pvpanic-pci.c @@ -19,11 +19,10 @@ #define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011 MODULE_AUTHOR("Mihai Carabas "); -MODULE_DESCRIPTION("pvpanic device driver "); +MODULE_DESCRIPTION("pvpanic device driver"); MODULE_LICENSE("GPL"); -static ssize_t capability_show(struct device *dev, - struct device_attribute *attr, char *buf) +static ssize_t capability_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pvpanic_instance *pi = dev_get_drvdata(dev); @@ -31,14 +30,14 @@ static ssize_t capability_show(struct device *dev, } static DEVICE_ATTR_RO(capability); -static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf) +static ssize_t events_show(struct device *dev, struct device_attribute *attr, char *buf) { struct pvpanic_instance *pi = dev_get_drvdata(dev); return sysfs_emit(buf, "%x\n", pi->events); } -static ssize_t events_store(struct device *dev, struct device_attribute *attr, +static ssize_t events_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct pvpanic_instance *pi = dev_get_drvdata(dev); @@ -65,8 +64,7 @@ static struct attribute *pvpanic_pci_dev_attrs[] = { }; ATTRIBUTE_GROUPS(pvpanic_pci_dev); -static int pvpanic_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int pvpanic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { struct pvpanic_instance *pi; void __iomem *base; diff --git a/drivers/misc/pvpanic/pvpanic.c b/drivers/misc/pvpanic/pvpanic.c index 6ffc8c2e5b04..4b8f1c7d726d 100644 --- a/drivers/misc/pvpanic/pvpanic.c +++ b/drivers/misc/pvpanic/pvpanic.c @@ -23,7 +23,7 @@ #include "pvpanic.h" MODULE_AUTHOR("Mihai Carabas "); -MODULE_DESCRIPTION("pvpanic device driver "); +MODULE_DESCRIPTION("pvpanic device driver"); MODULE_LICENSE("GPL"); static struct list_head pvpanic_list; @@ -43,8 +43,7 @@ pvpanic_send_event(unsigned int event) } static int -pvpanic_panic_notify(struct notifier_block *nb, unsigned long code, - void *unused) +pvpanic_panic_notify(struct notifier_block *nb, unsigned long code, void *unused) { unsigned int event = PVPANIC_PANICKED; @@ -96,8 +95,7 @@ static int pvpanic_init(void) INIT_LIST_HEAD(&pvpanic_list); spin_lock_init(&pvpanic_lock); - atomic_notifier_chain_register(&panic_notifier_list, - &pvpanic_panic_nb); + atomic_notifier_chain_register(&panic_notifier_list, &pvpanic_panic_nb); return 0; } @@ -105,8 +103,7 @@ module_init(pvpanic_init); static void pvpanic_exit(void) { - atomic_notifier_chain_unregister(&panic_notifier_list, - &pvpanic_panic_nb); + atomic_notifier_chain_unregister(&panic_notifier_list, &pvpanic_panic_nb); } module_exit(pvpanic_exit); -- cgit v1.2.3 From aee1bbf66ba0343828fd8e62e59480314914b75e Mon Sep 17 00:00:00 2001 From: Len Baker Date: Sun, 5 Sep 2021 17:37:07 +0200 Subject: tifm: Prefer struct_size over open coded arithmetic As noted in the "Deprecated Interfaces, Language Features, Attributes, and Conventions" documentation [1], size calculations (especially multiplication) should not be performed in memory allocator (or similar) function arguments due to the risk of them overflowing. This could lead to values wrapping around and a smaller allocation being made than the caller was expecting. Using those allocations could lead to linear overflows of heap memory and other misbehaviors. So, use the struct_size() helper to do the arithmetic instead of the argument "size + size * count" in the kzalloc() function. [1] https://www.kernel.org/doc/html/v5.14/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments Signed-off-by: Len Baker Link: https://lore.kernel.org/r/20210905153707.9638-1-len.baker@gmx.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/tifm_core.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index 52656fc87e99..2bb46b1f4be3 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -176,8 +176,7 @@ struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets, { struct tifm_adapter *fm; - fm = kzalloc(sizeof(struct tifm_adapter) - + sizeof(struct tifm_dev*) * num_sockets, GFP_KERNEL); + fm = kzalloc(struct_size(fm, sockets, num_sockets), GFP_KERNEL); if (fm) { fm->dev.class = &tifm_adapter_class; fm->dev.parent = dev; -- cgit v1.2.3 From 5e87622c4bf3614155781daf5439cf4909adae9a Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 18 Sep 2021 07:20:28 +0200 Subject: misc: genwqe: Remove usage of the deprecated "pci-dma-compat.h" API In [1], Christoph Hellwig has proposed to remove the wrappers in include/linux/pci-dma-compat.h. Some reasons why this API should be removed have been given by Julia Lawall in [2]. Finally, Arnd Bergmann reminded that the documentation was updated 11 years ago to only describe the modern linux/dma-mapping.h interfaces and mark the old bus-specific ones as no longer recommended, see commit 216bf58f4092 ("Documentation: convert PCI-DMA-mapping.txt to use the generic DMA API"). A coccinelle script has been used to perform the needed transformation Only relevant parts are given below. @@ @@ - PCI_DMA_BIDIRECTIONAL + DMA_BIDIRECTIONAL@@ @@ expression e1, e2, e3, e4, e5; @@ - pci_map_page(e1, e2, e3, e4, e5) + dma_map_page(&e1->dev, e2, e3, e4, e5) @@ expression e1, e2, e3, e4; @@ - pci_unmap_page(e1, e2, e3, e4) + dma_unmap_page(&e1->dev, e2, e3, e4) @@ expression e1, e2; @@ - pci_dma_mapping_error(e1, e2) + dma_mapping_error(&e1->dev, e2) [1]: https://lore.kernel.org/kernel-janitors/20200421081257.GA131897@infradead.org/ [2]: https://lore.kernel.org/kernel-janitors/alpine.DEB.2.22.394.2007120902170.2424@hadrien/ Reviewed-by: Arnd Bergmann Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/590154f2ab113088346ae76c3f13f8b1cbebccbb.1631942274.git.christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/misc/genwqe/card_utils.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/genwqe/card_utils.c b/drivers/misc/genwqe/card_utils.c index 039b923d1d60..1167463f26fb 100644 --- a/drivers/misc/genwqe/card_utils.c +++ b/drivers/misc/genwqe/card_utils.c @@ -233,8 +233,8 @@ static void genwqe_unmap_pages(struct genwqe_dev *cd, dma_addr_t *dma_list, struct pci_dev *pci_dev = cd->pci_dev; for (i = 0; (i < num_pages) && (dma_list[i] != 0x0); i++) { - pci_unmap_page(pci_dev, dma_list[i], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); + dma_unmap_page(&pci_dev->dev, dma_list[i], PAGE_SIZE, + DMA_BIDIRECTIONAL); dma_list[i] = 0x0; } } @@ -251,12 +251,12 @@ static int genwqe_map_pages(struct genwqe_dev *cd, dma_addr_t daddr; dma_list[i] = 0x0; - daddr = pci_map_page(pci_dev, page_list[i], + daddr = dma_map_page(&pci_dev->dev, page_list[i], 0, /* map_offs */ PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); /* FIXME rd/rw */ + DMA_BIDIRECTIONAL); /* FIXME rd/rw */ - if (pci_dma_mapping_error(pci_dev, daddr)) { + if (dma_mapping_error(&pci_dev->dev, daddr)) { dev_err(&pci_dev->dev, "[%s] err: no dma addr daddr=%016llx!\n", __func__, (long long)daddr); -- cgit v1.2.3 From 639fd77e2f696269b3a5c7a1eb547e044e4dbc2b Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 18 Sep 2021 07:32:26 +0200 Subject: tifm: Remove usage of the deprecated "pci-dma-compat.h" API In [1], Christoph Hellwig has proposed to remove the wrappers in include/linux/pci-dma-compat.h. Some reasons why this API should be removed have been given by Julia Lawall in [2]. Finally, Arnd Bergmann reminded that the documentation was updated 11 years ago to only describe the modern linux/dma-mapping.h interfaces and mark the old bus-specific ones as no longer recommended, see commit 216bf58f4092 ("Documentation: convert PCI-DMA-mapping.txt to use the generic DMA API"). A coccinelle script has been used to perform the needed transformation Only relevant parts are given below. @@ expression e1, e2, e3, e4; @@ - pci_map_sg(e1, e2, e3, e4) + dma_map_sg(&e1->dev, e2, e3, e4) @@ expression e1, e2, e3, e4; @@ - pci_unmap_sg(e1, e2, e3, e4) + dma_unmap_sg(&e1->dev, e2, e3, e4) @@ expression e1, e2; @@ - pci_set_dma_mask(e1, e2) + dma_set_mask(&e1->dev, e2) [1]: https://lore.kernel.org/kernel-janitors/20200421081257.GA131897@infradead.org/ [2]: https://lore.kernel.org/kernel-janitors/alpine.DEB.2.22.394.2007120902170.2424@hadrien/ Reviewed-by: Arnd Bergmann Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/b5296677f92f7bace957e66479b3d57a5a824ca1.1631942796.git.christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/misc/tifm_7xx1.c | 2 +- drivers/misc/tifm_core.c | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 228f2eb1d476..017c2f7d6287 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c @@ -311,7 +311,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev, int pci_dev_busy = 0; int rc; - rc = pci_set_dma_mask(dev, DMA_BIT_MASK(32)); + rc = dma_set_mask(&dev->dev, DMA_BIT_MASK(32)); if (rc) return rc; diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index 2bb46b1f4be3..a3098fea3bf7 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c @@ -292,14 +292,15 @@ EXPORT_SYMBOL(tifm_has_ms_pif); int tifm_map_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents, int direction) { - return pci_map_sg(to_pci_dev(sock->dev.parent), sg, nents, direction); + return dma_map_sg(&to_pci_dev(sock->dev.parent)->dev, sg, nents, + direction); } EXPORT_SYMBOL(tifm_map_sg); void tifm_unmap_sg(struct tifm_dev *sock, struct scatterlist *sg, int nents, int direction) { - pci_unmap_sg(to_pci_dev(sock->dev.parent), sg, nents, direction); + dma_unmap_sg(&to_pci_dev(sock->dev.parent)->dev, sg, nents, direction); } EXPORT_SYMBOL(tifm_unmap_sg); -- cgit v1.2.3 From 54fa156bb33ad06077ec709dc2331a4d5ee446f3 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sat, 18 Sep 2021 07:36:42 +0200 Subject: mei: Remove usage of the deprecated "pci-dma-compat.h" API In [1], Christoph Hellwig has proposed to remove the wrappers in include/linux/pci-dma-compat.h. Some reasons why this API should be removed have been given by Julia Lawall in [2]. Finally, Arnd Bergmann reminded that the documentation was updated 11 years ago to only describe the modern linux/dma-mapping.h interfaces and mark the old bus-specific ones as no longer recommended, see commit 216bf58f4092 ("Documentation: convert PCI-DMA-mapping.txt to use the generic DMA API"). A coccinelle script has been used to perform the needed transformation Only relevant parts are given below. @@ expression e1, e2; @@ - pci_set_dma_mask(e1, e2) + dma_set_mask(&e1->dev, e2) [1]: https://lore.kernel.org/kernel-janitors/20200421081257.GA131897@infradead.org/ [2]: https://lore.kernel.org/kernel-janitors/alpine.DEB.2.22.394.2007120902170.2424@hadrien/ Reviewed-by: Arnd Bergmann Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/c6f280927835c5677cc0367fccdc0ef54b307bd8.1631943364.git.christophe.jaillet@wanadoo.fr Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/pci-txe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/mei/pci-txe.c b/drivers/misc/mei/pci-txe.c index aec0483b8e72..fa20d9a27813 100644 --- a/drivers/misc/mei/pci-txe.c +++ b/drivers/misc/mei/pci-txe.c @@ -69,9 +69,9 @@ static int mei_txe_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto end; } - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); + err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(36)); if (err) { - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); + err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); if (err) { dev_err(&pdev->dev, "No suitable DMA available.\n"); goto end; -- cgit v1.2.3 From 304b0ba0a21b216683bc887d18dc5ad8d7d94752 Mon Sep 17 00:00:00 2001 From: Jeya R Date: Mon, 20 Sep 2021 13:04:34 +0530 Subject: misc: fastrpc: Update number of max fastrpc sessions For latest chipsets, upto 13 fastrpc sessions can be supported. This includes 12 compute sessions and 1 cpz session. Not updating this might result to out of bounds memory access issues if more than 9 context bank nodes are added to the DT file. Reviewed-by: Srinivas Kandagatla Signed-off-by: Jeya R Link: https://lore.kernel.org/r/1632123274-32054-1-git-send-email-jeyr@codeaurora.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/fastrpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index beda610e6b30..bd7811e3f761 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -24,7 +24,7 @@ #define SDSP_DOMAIN_ID (2) #define CDSP_DOMAIN_ID (3) #define FASTRPC_DEV_MAX 4 /* adsp, mdsp, slpi, cdsp*/ -#define FASTRPC_MAX_SESSIONS 9 /*8 compute, 1 cpz*/ +#define FASTRPC_MAX_SESSIONS 13 /*12 compute, 1 cpz*/ #define FASTRPC_ALIGN 128 #define FASTRPC_MAX_FDLIST 16 #define FASTRPC_MAX_CRCLIST 64 -- cgit v1.2.3 From 847afd7bd5607ca974e562d7b2b8f800c4594fe6 Mon Sep 17 00:00:00 2001 From: Jeya R Date: Thu, 23 Sep 2021 14:07:52 +0530 Subject: misc: fastrpc: copy to user only for non-DMA-BUF heap buffers fastrpc_put_args is copying all the output buffers to user. For large number of output context buffers, this might cause performance degradation. Copying is not needed for DMA-BUF heap buffers. Signed-off-by: Jeya R Link: https://lore.kernel.org/r/1632386272-18139-1-git-send-email-jeyr@codeaurora.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/fastrpc.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index bd7811e3f761..e0d0c894c5fd 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -890,15 +890,17 @@ static int fastrpc_put_args(struct fastrpc_invoke_ctx *ctx, inbufs = REMOTE_SCALARS_INBUFS(ctx->sc); for (i = inbufs; i < ctx->nbufs; ++i) { - void *src = (void *)(uintptr_t)rpra[i].pv; - void *dst = (void *)(uintptr_t)ctx->args[i].ptr; - u64 len = rpra[i].len; + if (!ctx->maps[i]) { + void *src = (void *)(uintptr_t)rpra[i].pv; + void *dst = (void *)(uintptr_t)ctx->args[i].ptr; + u64 len = rpra[i].len; - if (!kernel) { - if (copy_to_user((void __user *)dst, src, len)) - return -EFAULT; - } else { - memcpy(dst, src, len); + if (!kernel) { + if (copy_to_user((void __user *)dst, src, len)) + return -EFAULT; + } else { + memcpy(dst, src, len); + } } } -- cgit v1.2.3 From 4df4946d26bb7866b71cbdf86abe285ed3a79cee Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 12 Oct 2021 17:39:37 +0200 Subject: misc: lis3lv02d: Make lis3lv02d_remove_fs() return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Up to now lis3lv02d_remove_fs() returns zero unconditionally. Make it return void instead which makes it easier to see in the callers that there is no error to handle. Also the return value of i2c and spi remove callbacks is ignored anyway. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20211012153945.2651412-13-u.kleine-koenig@pengutronix.de Reviewed-by: Hans de Goede Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lis3lv02d/lis3lv02d.c | 3 +-- drivers/misc/lis3lv02d/lis3lv02d.h | 2 +- drivers/misc/lis3lv02d/lis3lv02d_spi.c | 4 +++- drivers/platform/x86/hp_accel.c | 3 ++- 4 files changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/lis3lv02d/lis3lv02d.c b/drivers/misc/lis3lv02d/lis3lv02d.c index 70c5bb1e6f49..3a7808b796b1 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.c +++ b/drivers/misc/lis3lv02d/lis3lv02d.c @@ -878,7 +878,7 @@ static int lis3lv02d_add_fs(struct lis3lv02d *lis3) return sysfs_create_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group); } -int lis3lv02d_remove_fs(struct lis3lv02d *lis3) +void lis3lv02d_remove_fs(struct lis3lv02d *lis3) { sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group); platform_device_unregister(lis3->pdev); @@ -894,7 +894,6 @@ int lis3lv02d_remove_fs(struct lis3lv02d *lis3) pm_runtime_set_suspended(lis3->pm_dev); } kfree(lis3->reg_cache); - return 0; } EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs); diff --git a/drivers/misc/lis3lv02d/lis3lv02d.h b/drivers/misc/lis3lv02d/lis3lv02d.h index c394c0b08519..195bd2fd2eb5 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d.h +++ b/drivers/misc/lis3lv02d/lis3lv02d.h @@ -312,7 +312,7 @@ int lis3lv02d_joystick_enable(struct lis3lv02d *lis3); void lis3lv02d_joystick_disable(struct lis3lv02d *lis3); void lis3lv02d_poweroff(struct lis3lv02d *lis3); int lis3lv02d_poweron(struct lis3lv02d *lis3); -int lis3lv02d_remove_fs(struct lis3lv02d *lis3); +void lis3lv02d_remove_fs(struct lis3lv02d *lis3); int lis3lv02d_init_dt(struct lis3lv02d *lis3); extern struct lis3lv02d lis3_dev; diff --git a/drivers/misc/lis3lv02d/lis3lv02d_spi.c b/drivers/misc/lis3lv02d/lis3lv02d_spi.c index f664ed123730..9e40dfb60742 100644 --- a/drivers/misc/lis3lv02d/lis3lv02d_spi.c +++ b/drivers/misc/lis3lv02d/lis3lv02d_spi.c @@ -102,7 +102,9 @@ static int lis302dl_spi_remove(struct spi_device *spi) lis3lv02d_joystick_disable(lis3); lis3lv02d_poweroff(lis3); - return lis3lv02d_remove_fs(&lis3_dev); + lis3lv02d_remove_fs(&lis3_dev); + + return 0; } #ifdef CONFIG_PM_SLEEP diff --git a/drivers/platform/x86/hp_accel.c b/drivers/platform/x86/hp_accel.c index cc53f725c041..b183967ecfb7 100644 --- a/drivers/platform/x86/hp_accel.c +++ b/drivers/platform/x86/hp_accel.c @@ -349,7 +349,8 @@ static int lis3lv02d_remove(struct platform_device *device) led_classdev_unregister(&hpled_led.led_classdev); flush_work(&hpled_led.work); - return lis3lv02d_remove_fs(&lis3_dev); + lis3lv02d_remove_fs(&lis3_dev); + return 0; } #ifdef CONFIG_PM_SLEEP -- cgit v1.2.3 From 85385a51ceadfe79ae3b1eb5848fab6c3b917ea8 Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Tue, 12 Oct 2021 17:39:36 +0200 Subject: misc: ad525x_dpot: Make ad_dpot_remove() return void MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Up to now ad_dpot_remove() returns zero unconditionally. Make it return void instead which makes it easier to see in the callers that there is no error to handle. Also the return value of i2c and spi remove callbacks is ignored anyway. Signed-off-by: Uwe Kleine-König Link: https://lore.kernel.org/r/20211012153945.2651412-12-u.kleine-koenig@pengutronix.de Acked-by: Michael Hennerich Signed-off-by: Greg Kroah-Hartman --- drivers/misc/ad525x_dpot-i2c.c | 3 ++- drivers/misc/ad525x_dpot-spi.c | 3 ++- drivers/misc/ad525x_dpot.c | 4 +--- drivers/misc/ad525x_dpot.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/ad525x_dpot-i2c.c b/drivers/misc/ad525x_dpot-i2c.c index bd869ec5edba..0ee0c6d808c3 100644 --- a/drivers/misc/ad525x_dpot-i2c.c +++ b/drivers/misc/ad525x_dpot-i2c.c @@ -69,7 +69,8 @@ static int ad_dpot_i2c_probe(struct i2c_client *client, static int ad_dpot_i2c_remove(struct i2c_client *client) { - return ad_dpot_remove(&client->dev); + ad_dpot_remove(&client->dev); + return 0; } static const struct i2c_device_id ad_dpot_id[] = { diff --git a/drivers/misc/ad525x_dpot-spi.c b/drivers/misc/ad525x_dpot-spi.c index aea931dd272e..a9e75d80ad36 100644 --- a/drivers/misc/ad525x_dpot-spi.c +++ b/drivers/misc/ad525x_dpot-spi.c @@ -92,7 +92,8 @@ static int ad_dpot_spi_probe(struct spi_device *spi) static int ad_dpot_spi_remove(struct spi_device *spi) { - return ad_dpot_remove(&spi->dev); + ad_dpot_remove(&spi->dev); + return 0; } static const struct spi_device_id ad_dpot_spi_id[] = { diff --git a/drivers/misc/ad525x_dpot.c b/drivers/misc/ad525x_dpot.c index 5d8f3f6a95f2..756ef6912b5a 100644 --- a/drivers/misc/ad525x_dpot.c +++ b/drivers/misc/ad525x_dpot.c @@ -743,7 +743,7 @@ exit: } EXPORT_SYMBOL(ad_dpot_probe); -int ad_dpot_remove(struct device *dev) +void ad_dpot_remove(struct device *dev) { struct dpot_data *data = dev_get_drvdata(dev); int i; @@ -753,8 +753,6 @@ int ad_dpot_remove(struct device *dev) ad_dpot_remove_files(dev, data->feat, i); kfree(data); - - return 0; } EXPORT_SYMBOL(ad_dpot_remove); diff --git a/drivers/misc/ad525x_dpot.h b/drivers/misc/ad525x_dpot.h index ee8dc9f5a45a..72a9d6801937 100644 --- a/drivers/misc/ad525x_dpot.h +++ b/drivers/misc/ad525x_dpot.h @@ -209,6 +209,6 @@ struct ad_dpot_bus_data { int ad_dpot_probe(struct device *dev, struct ad_dpot_bus_data *bdata, unsigned long devid, const char *name); -int ad_dpot_remove(struct device *dev); +void ad_dpot_remove(struct device *dev); #endif -- cgit v1.2.3 From 4be9fb53039ab1327f058e09039404ad33926adb Mon Sep 17 00:00:00 2001 From: Ofir Bitton Date: Thu, 2 Sep 2021 10:18:01 +0300 Subject: habanalabs: add debugfs node for configuring CS timeout Command submission timeout is currently determined during driver loading time. As some environments requires this timeout to be modified in runtime, we introduce a new debugfs node that controls the timeout value without the need to reload the driver. Signed-off-by: Ofir Bitton Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- .../ABI/testing/debugfs-driver-habanalabs | 6 +++ drivers/misc/habanalabs/common/debugfs.c | 51 ++++++++++++++++++++++ 2 files changed, 57 insertions(+) (limited to 'drivers/misc') diff --git a/Documentation/ABI/testing/debugfs-driver-habanalabs b/Documentation/ABI/testing/debugfs-driver-habanalabs index 284e2dfa61cd..63c46d9d538f 100644 --- a/Documentation/ABI/testing/debugfs-driver-habanalabs +++ b/Documentation/ABI/testing/debugfs-driver-habanalabs @@ -226,6 +226,12 @@ Description: Gets the state dump occurring on a CS timeout or failure. Writing an integer X discards X state dumps, so that the next read would return X+1-st newest state dump. +What: /sys/kernel/debug/habanalabs/hl/timeout_locked +Date: Sep 2021 +KernelVersion: 5.16 +Contact: obitton@habana.ai +Description: Sets the command submission timeout value in seconds. + What: /sys/kernel/debug/habanalabs/hl/stop_on_err Date: Mar 2020 KernelVersion: 5.6 diff --git a/drivers/misc/habanalabs/common/debugfs.c b/drivers/misc/habanalabs/common/debugfs.c index 985f1f3dbd20..1f2a3dc6c4e2 100644 --- a/drivers/misc/habanalabs/common/debugfs.c +++ b/drivers/misc/habanalabs/common/debugfs.c @@ -1167,6 +1167,45 @@ static ssize_t hl_state_dump_write(struct file *f, const char __user *buf, return count; } +static ssize_t hl_timeout_locked_read(struct file *f, char __user *buf, + size_t count, loff_t *ppos) +{ + struct hl_dbg_device_entry *entry = file_inode(f)->i_private; + struct hl_device *hdev = entry->hdev; + char tmp_buf[200]; + ssize_t rc; + + if (*ppos) + return 0; + + sprintf(tmp_buf, "%d\n", + jiffies_to_msecs(hdev->timeout_jiffies) / 1000); + rc = simple_read_from_buffer(buf, strlen(tmp_buf) + 1, ppos, tmp_buf, + strlen(tmp_buf) + 1); + + return rc; +} + +static ssize_t hl_timeout_locked_write(struct file *f, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct hl_dbg_device_entry *entry = file_inode(f)->i_private; + struct hl_device *hdev = entry->hdev; + u32 value; + ssize_t rc; + + rc = kstrtouint_from_user(buf, count, 10, &value); + if (rc) + return rc; + + if (value) + hdev->timeout_jiffies = msecs_to_jiffies(value * 1000); + else + hdev->timeout_jiffies = MAX_SCHEDULE_TIMEOUT; + + return count; +} + static const struct file_operations hl_data32b_fops = { .owner = THIS_MODULE, .read = hl_data_read32, @@ -1240,6 +1279,12 @@ static const struct file_operations hl_state_dump_fops = { .write = hl_state_dump_write }; +static const struct file_operations hl_timeout_locked_fops = { + .owner = THIS_MODULE, + .read = hl_timeout_locked_read, + .write = hl_timeout_locked_write +}; + static const struct hl_info_list hl_debugfs_list[] = { {"command_buffers", command_buffers_show, NULL}, {"command_submission", command_submission_show, NULL}, @@ -1421,6 +1466,12 @@ void hl_debugfs_add_device(struct hl_device *hdev) dev_entry, &hl_state_dump_fops); + debugfs_create_file("timeout_locked", + 0644, + dev_entry->root, + dev_entry, + &hl_timeout_locked_fops); + for (i = 0, entry = dev_entry->entry_arr ; i < count ; i++, entry++) { debugfs_create_file(hl_debugfs_list[i].name, 0444, -- cgit v1.2.3 From 7457269136043fdbb7ff28bbc82d9655ad6012d7 Mon Sep 17 00:00:00 2001 From: Rajaravi Krishna Katta Date: Tue, 24 Aug 2021 16:39:16 +0300 Subject: habanalabs: create static map of f/w hwmon enums Instead of using the Linux kernel HWMON enums definition when communicating with the firmware, use proprietary HWMON based enums i.e. map hwmon.h header enum to cpucp_if.h based enum while. This is needed because the HWMON enums are not forcing backward compatibility and therefore changes can break compatibility between newer driver and older firmware. The driver will check for CPU_BOOT_DEV_STS0_MAP_HWMON_EN bit to validate if f/w supports cpucp->hwmon enum mapping to support older firmware where this mapping won't be available. Signed-off-by: Rajaravi Krishna Katta Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/hwmon.c | 100 +++++++++++++++++++-- .../misc/habanalabs/include/common/hl_boot_if.h | 6 ++ 2 files changed, 97 insertions(+), 9 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/hwmon.c b/drivers/misc/habanalabs/common/hwmon.c index 6b421d76b311..8f12d99fda09 100644 --- a/drivers/misc/habanalabs/common/hwmon.c +++ b/drivers/misc/habanalabs/common/hwmon.c @@ -113,6 +113,9 @@ static int hl_read(struct device *dev, enum hwmon_sensor_types type, { struct hl_device *hdev = dev_get_drvdata(dev); int rc; + u32 cpucp_attr; + bool use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false; if (!hl_device_operational(hdev, NULL)) return -ENODEV; @@ -121,65 +124,117 @@ static int hl_read(struct device *dev, enum hwmon_sensor_types type, case hwmon_temp: switch (attr) { case hwmon_temp_input: + cpucp_attr = cpucp_temp_input; + break; case hwmon_temp_max: + cpucp_attr = cpucp_temp_max; + break; case hwmon_temp_crit: + cpucp_attr = cpucp_temp_crit; + break; case hwmon_temp_max_hyst: + cpucp_attr = cpucp_temp_max_hyst; + break; case hwmon_temp_crit_hyst: + cpucp_attr = cpucp_temp_crit_hyst; + break; case hwmon_temp_offset: + cpucp_attr = cpucp_temp_offset; + break; case hwmon_temp_highest: + cpucp_attr = cpucp_temp_highest; break; default: return -EINVAL; } - rc = hl_get_temperature(hdev, channel, attr, val); + if (use_cpucp_enum) + rc = hl_get_temperature(hdev, channel, cpucp_attr, val); + else + rc = hl_get_temperature(hdev, channel, attr, val); break; case hwmon_in: switch (attr) { case hwmon_in_input: + cpucp_attr = cpucp_in_input; + break; case hwmon_in_min: + cpucp_attr = cpucp_in_min; + break; case hwmon_in_max: + cpucp_attr = cpucp_in_max; + break; case hwmon_in_highest: + cpucp_attr = cpucp_in_highest; break; default: return -EINVAL; } - rc = hl_get_voltage(hdev, channel, attr, val); + if (use_cpucp_enum) + rc = hl_get_voltage(hdev, channel, cpucp_attr, val); + else + rc = hl_get_voltage(hdev, channel, attr, val); break; case hwmon_curr: switch (attr) { case hwmon_curr_input: + cpucp_attr = cpucp_curr_input; + break; case hwmon_curr_min: + cpucp_attr = cpucp_curr_min; + break; case hwmon_curr_max: + cpucp_attr = cpucp_curr_max; + break; case hwmon_curr_highest: + cpucp_attr = cpucp_curr_highest; break; default: return -EINVAL; } - rc = hl_get_current(hdev, channel, attr, val); + if (use_cpucp_enum) + rc = hl_get_current(hdev, channel, cpucp_attr, val); + else + rc = hl_get_current(hdev, channel, attr, val); break; case hwmon_fan: switch (attr) { case hwmon_fan_input: + cpucp_attr = cpucp_fan_input; + break; case hwmon_fan_min: + cpucp_attr = cpucp_fan_min; + break; case hwmon_fan_max: + cpucp_attr = cpucp_fan_max; break; default: return -EINVAL; } - rc = hl_get_fan_speed(hdev, channel, attr, val); + + if (use_cpucp_enum) + rc = hl_get_fan_speed(hdev, channel, cpucp_attr, val); + else + rc = hl_get_fan_speed(hdev, channel, attr, val); break; case hwmon_pwm: switch (attr) { case hwmon_pwm_input: + cpucp_attr = cpucp_pwm_input; + break; case hwmon_pwm_enable: + cpucp_attr = cpucp_pwm_enable; break; default: return -EINVAL; } - rc = hl_get_pwm_info(hdev, channel, attr, val); + + if (use_cpucp_enum) + rc = hl_get_pwm_info(hdev, channel, cpucp_attr, val); + else + rc = hl_get_pwm_info(hdev, channel, attr, val); break; default: return -EINVAL; @@ -191,6 +246,9 @@ static int hl_write(struct device *dev, enum hwmon_sensor_types type, u32 attr, int channel, long val) { struct hl_device *hdev = dev_get_drvdata(dev); + u32 cpucp_attr; + bool use_cpucp_enum = (hdev->asic_prop.fw_app_cpu_boot_dev_sts0 & + CPU_BOOT_DEV_STS0_MAP_HWMON_EN) ? true : false; if (!hl_device_operational(hdev, NULL)) return -ENODEV; @@ -199,40 +257,64 @@ static int hl_write(struct device *dev, enum hwmon_sensor_types type, case hwmon_temp: switch (attr) { case hwmon_temp_offset: + cpucp_attr = cpucp_temp_offset; + break; case hwmon_temp_reset_history: + cpucp_attr = cpucp_temp_reset_history; break; default: return -EINVAL; } - hl_set_temperature(hdev, channel, attr, val); + + if (use_cpucp_enum) + hl_set_temperature(hdev, channel, cpucp_attr, val); + else + hl_set_temperature(hdev, channel, attr, val); break; case hwmon_pwm: switch (attr) { case hwmon_pwm_input: + cpucp_attr = cpucp_pwm_input; + break; case hwmon_pwm_enable: + cpucp_attr = cpucp_pwm_enable; break; default: return -EINVAL; } - hl_set_pwm_info(hdev, channel, attr, val); + + if (use_cpucp_enum) + hl_set_pwm_info(hdev, channel, cpucp_attr, val); + else + hl_set_pwm_info(hdev, channel, attr, val); break; case hwmon_in: switch (attr) { case hwmon_in_reset_history: + cpucp_attr = cpucp_in_reset_history; break; default: return -EINVAL; } - hl_set_voltage(hdev, channel, attr, val); + + if (use_cpucp_enum) + hl_set_voltage(hdev, channel, cpucp_attr, val); + else + hl_set_voltage(hdev, channel, attr, val); break; case hwmon_curr: switch (attr) { case hwmon_curr_reset_history: + cpucp_attr = cpucp_curr_reset_history; break; default: return -EINVAL; } - hl_set_current(hdev, channel, attr, val); + + if (use_cpucp_enum) + hl_set_current(hdev, channel, cpucp_attr, val); + else + hl_set_current(hdev, channel, attr, val); break; default: return -EINVAL; diff --git a/drivers/misc/habanalabs/include/common/hl_boot_if.h b/drivers/misc/habanalabs/include/common/hl_boot_if.h index 3099653234e4..8837925b5d85 100644 --- a/drivers/misc/habanalabs/include/common/hl_boot_if.h +++ b/drivers/misc/habanalabs/include/common/hl_boot_if.h @@ -252,6 +252,11 @@ * where a bit is set if the engine is not idle. * Initialized in: linux * + * CPU_BOOT_DEV_STS0_MAP_HWMON_EN + * If set, means f/w supports proprietary + * HWMON enum mapping to cpucp enums. + * Initialized in: linux + * * CPU_BOOT_DEV_STS0_ENABLED Device status register enabled. * This is a main indication that the * running FW populates the device status @@ -287,6 +292,7 @@ #define CPU_BOOT_DEV_STS0_FW_NIC_STAT_XPCS91_EN (1 << 23) #define CPU_BOOT_DEV_STS0_FW_NIC_STAT_EXT_EN (1 << 24) #define CPU_BOOT_DEV_STS0_IS_IDLE_CHECK_EN (1 << 25) +#define CPU_BOOT_DEV_STS0_MAP_HWMON_EN (1 << 26) #define CPU_BOOT_DEV_STS0_ENABLED (1 << 31) #define CPU_BOOT_DEV_STS1_ENABLED (1 << 31) -- cgit v1.2.3 From 2ee58fee3f8c63a1c689ad6f2fc72821cabb7748 Mon Sep 17 00:00:00 2001 From: Alon Mizrahi Date: Wed, 1 Sep 2021 18:05:00 +0300 Subject: habanalabs: generalize COMMS message sending procedure Instead of having dedicated function per message that we want to send to the firmware in COMMS protocol, have a generic function that we can call to from other parts of the driver Signed-off-by: Alon Mizrahi Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/firmware_if.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/firmware_if.c b/drivers/misc/habanalabs/common/firmware_if.c index 8d2568c63f19..4e68fb9d2a6b 100644 --- a/drivers/misc/habanalabs/common/firmware_if.c +++ b/drivers/misc/habanalabs/common/firmware_if.c @@ -2162,18 +2162,17 @@ static void hl_fw_linux_update_state(struct hl_device *hdev, } /** - * hl_fw_dynamic_report_reset_cause - send a COMMS message with the cause - * of the newly triggered hard reset + * hl_fw_dynamic_send_msg - send a COMMS message with attached data * * @hdev: pointer to the habanalabs device structure * @fw_loader: managing structure for loading device's FW - * @reset_cause: enumerated cause for the recent hard reset + * @msg_type: message type + * @data: data to be sent * * @return 0 on success, otherwise non-zero error code */ -static int hl_fw_dynamic_report_reset_cause(struct hl_device *hdev, - struct fw_load_mgr *fw_loader, - enum comms_reset_cause reset_cause) +static int hl_fw_dynamic_send_msg(struct hl_device *hdev, + struct fw_load_mgr *fw_loader, u8 msg_type, void *data) { struct lkd_msg_comms msg; int rc; @@ -2181,11 +2180,20 @@ static int hl_fw_dynamic_report_reset_cause(struct hl_device *hdev, memset(&msg, 0, sizeof(msg)); /* create message to be sent */ - msg.header.type = HL_COMMS_RESET_CAUSE_TYPE; + msg.header.type = msg_type; msg.header.size = cpu_to_le16(sizeof(struct comms_msg_header)); msg.header.magic = cpu_to_le32(HL_COMMS_MSG_MAGIC); - msg.reset_cause = reset_cause; + switch (msg_type) { + case HL_COMMS_RESET_CAUSE_TYPE: + msg.reset_cause = *(__u8 *) data; + break; + default: + dev_err(hdev->dev, + "Send COMMS message - invalid message type %u\n", + msg_type); + return -EINVAL; + } rc = hl_fw_dynamic_request_descriptor(hdev, fw_loader, sizeof(struct lkd_msg_comms)); @@ -2252,8 +2260,8 @@ static int hl_fw_dynamic_init_cpu(struct hl_device *hdev, goto protocol_err; if (hdev->curr_reset_cause) { - rc = hl_fw_dynamic_report_reset_cause(hdev, fw_loader, - hdev->curr_reset_cause); + rc = hl_fw_dynamic_send_msg(hdev, fw_loader, + HL_COMMS_RESET_CAUSE_TYPE, &hdev->curr_reset_cause); if (rc) goto protocol_err; -- cgit v1.2.3 From 2b28485d0a3bf8aa220af4644eb186b5034ff830 Mon Sep 17 00:00:00 2001 From: Rajaravi Krishna Katta Date: Wed, 18 Aug 2021 08:12:41 +0300 Subject: habanalabs: enable power info via HWMON framework Add support to retrieve following power info via HWMON: - instantaneous power value - highest value since last reset - reset the highest place holder Signed-off-by: Rajaravi Krishna Katta Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/habanalabs.h | 4 + drivers/misc/habanalabs/common/hwmon.c | 94 +++++++++++++++++++++++ drivers/misc/habanalabs/include/common/cpucp_if.h | 10 +++ 3 files changed, 108 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index bebebcb163ee..f8e23ca18a57 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -2956,6 +2956,10 @@ int hl_set_voltage(struct hl_device *hdev, int sensor_index, u32 attr, long value); int hl_set_current(struct hl_device *hdev, int sensor_index, u32 attr, long value); +int hl_set_power(struct hl_device *hdev, + int sensor_index, u32 attr, long value); +int hl_get_power(struct hl_device *hdev, + int sensor_index, u32 attr, long *value); void hw_sob_get(struct hl_hw_sob *hw_sob); void hw_sob_put(struct hl_hw_sob *hw_sob); void hl_encaps_handle_do_release(struct kref *ref); diff --git a/drivers/misc/habanalabs/common/hwmon.c b/drivers/misc/habanalabs/common/hwmon.c index 8f12d99fda09..e33f65be8a00 100644 --- a/drivers/misc/habanalabs/common/hwmon.c +++ b/drivers/misc/habanalabs/common/hwmon.c @@ -236,6 +236,23 @@ static int hl_read(struct device *dev, enum hwmon_sensor_types type, else rc = hl_get_pwm_info(hdev, channel, attr, val); break; + case hwmon_power: + switch (attr) { + case hwmon_power_input: + cpucp_attr = CPUCP_POWER_INPUT; + break; + case hwmon_power_input_highest: + cpucp_attr = CPUCP_POWER_INPUT_HIGHEST; + break; + default: + return -EINVAL; + } + + if (use_cpucp_enum) + rc = hl_get_power(hdev, channel, cpucp_attr, val); + else + rc = hl_get_power(hdev, channel, attr, val); + break; default: return -EINVAL; } @@ -316,6 +333,20 @@ static int hl_write(struct device *dev, enum hwmon_sensor_types type, else hl_set_current(hdev, channel, attr, val); break; + case hwmon_power: + switch (attr) { + case hwmon_power_reset_history: + cpucp_attr = CPUCP_POWER_RESET_INPUT_HISTORY; + break; + default: + return -EINVAL; + } + + if (use_cpucp_enum) + hl_set_power(hdev, channel, cpucp_attr, val); + else + hl_set_power(hdev, channel, attr, val); + break; default: return -EINVAL; } @@ -378,6 +409,15 @@ static umode_t hl_is_visible(const void *data, enum hwmon_sensor_types type, return 0644; } break; + case hwmon_power: + switch (attr) { + case hwmon_power_input: + case hwmon_power_input_highest: + return 0444; + case hwmon_power_reset_history: + return 0200; + } + break; default: break; } @@ -633,6 +673,60 @@ int hl_set_current(struct hl_device *hdev, return rc; } +int hl_set_power(struct hl_device *hdev, + int sensor_index, u32 attr, long value) +{ + struct cpucp_packet pkt; + int rc; + + memset(&pkt, 0, sizeof(pkt)); + + pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET << + CPUCP_PKT_CTL_OPCODE_SHIFT); + pkt.sensor_index = __cpu_to_le16(sensor_index); + pkt.type = __cpu_to_le16(attr); + pkt.value = __cpu_to_le64(value); + + rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), + 0, NULL); + + if (rc) + dev_err(hdev->dev, + "Failed to set power of sensor %d, error %d\n", + sensor_index, rc); + + return rc; +} + +int hl_get_power(struct hl_device *hdev, + int sensor_index, u32 attr, long *value) +{ + struct cpucp_packet pkt; + u64 result; + int rc; + + memset(&pkt, 0, sizeof(pkt)); + + pkt.ctl = cpu_to_le32(CPUCP_PACKET_POWER_GET << + CPUCP_PKT_CTL_OPCODE_SHIFT); + pkt.sensor_index = __cpu_to_le16(sensor_index); + pkt.type = __cpu_to_le16(attr); + + rc = hdev->asic_funcs->send_cpu_message(hdev, (u32 *) &pkt, sizeof(pkt), + 0, &result); + + *value = (long) result; + + if (rc) { + dev_err(hdev->dev, + "Failed to get power of sensor %d, error %d\n", + sensor_index, rc); + *value = 0; + } + + return rc; +} + int hl_hwmon_init(struct hl_device *hdev) { struct device *dev = hdev->pdev ? &hdev->pdev->dev : hdev->dev; diff --git a/drivers/misc/habanalabs/include/common/cpucp_if.h b/drivers/misc/habanalabs/include/common/cpucp_if.h index 9ff6a448f0d4..a6fa1cfa38a5 100644 --- a/drivers/misc/habanalabs/include/common/cpucp_if.h +++ b/drivers/misc/habanalabs/include/common/cpucp_if.h @@ -598,6 +598,16 @@ enum cpucp_pll_type_attributes { cpucp_pll_pci, }; +/* + * cpucp_power_type aligns with hwmon_power_attributes + * defined in Linux kernel hwmon.h file + */ +enum cpucp_power_type { + CPUCP_POWER_INPUT = 8, + CPUCP_POWER_INPUT_HIGHEST = 9, + CPUCP_POWER_RESET_INPUT_HISTORY = 11 +}; + /* * MSI type enumeration table for all ASICs and future SW versions. * For future ASIC-LKD compatibility, we can only add new enumerations. -- cgit v1.2.3 From 027d53b03ca1fe55ea9356ffdb7296432d236e59 Mon Sep 17 00:00:00 2001 From: Ofir Bitton Date: Mon, 13 Sep 2021 10:55:02 +0300 Subject: habanalabs: remove redundant cs validity checks During TDR handling, we check multiple times if CS is valid. No need to perform this check as CS must be valid at all time during the TDR handling. Signed-off-by: Ofir Bitton Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/command_submission.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index 6dafff375f1c..a344928363c8 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -431,11 +431,10 @@ static void cs_handle_tdr(struct hl_device *hdev, struct hl_cs *cs) /* Don't cancel TDR in case this CS was timedout because we might be * running from the TDR context */ - if (cs && (cs->timedout || - hdev->timeout_jiffies == MAX_SCHEDULE_TIMEOUT)) + if (cs->timedout || hdev->timeout_jiffies == MAX_SCHEDULE_TIMEOUT) return; - if (cs && cs->tdr_active) + if (cs->tdr_active) cancel_delayed_work_sync(&cs->work_tdr); spin_lock(&hdev->cs_mirror_lock); -- cgit v1.2.3 From d62b9a6976cdac30a3af745de1f935ffe246fcdd Mon Sep 17 00:00:00 2001 From: Ofir Bitton Date: Thu, 23 Sep 2021 12:02:23 +0300 Subject: habanalabs: add support for a long interrupt target value In order to avoid user target value wraparound, we modify the current interface so user will be able to wait for an 8-byte target value rather than a 4-byte value. Signed-off-by: Ofir Bitton Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/command_submission.c | 8 ++++---- include/uapi/misc/habanalabs.h | 13 +++++++------ 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index a344928363c8..44bab01cd033 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -2739,13 +2739,13 @@ static int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data) static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, u32 timeout_us, u64 user_address, - u32 target_value, u16 interrupt_offset, + u64 target_value, u16 interrupt_offset, enum hl_cs_wait_status *status) { struct hl_user_pending_interrupt *pend; struct hl_user_interrupt *interrupt; unsigned long timeout, flags; - u32 completion_value; + u64 completion_value; long completion_rc; int rc = 0; @@ -2779,7 +2779,7 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, /* We check for completion value as interrupt could have been received * before we added the node to the wait list */ - if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 4)) { + if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 8)) { dev_err(hdev->dev, "Failed to copy completion value from user\n"); rc = -EFAULT; goto remove_pending_user_interrupt; @@ -2811,7 +2811,7 @@ wait_again: reinit_completion(&pend->fence.completion); spin_unlock_irqrestore(&interrupt->wait_list_lock, flags); - if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 4)) { + if (copy_from_user(&completion_value, u64_to_user_ptr(user_address), 8)) { dev_err(hdev->dev, "Failed to copy completion value from user\n"); rc = -EFAULT; diff --git a/include/uapi/misc/habanalabs.h b/include/uapi/misc/habanalabs.h index ccfcb4d188fc..fe73630e1a05 100644 --- a/include/uapi/misc/habanalabs.h +++ b/include/uapi/misc/habanalabs.h @@ -897,11 +897,7 @@ struct hl_wait_cs_in { */ __u64 addr; /* Target value for completion comparison */ - __u32 target; - /* Absolute timeout to wait for interrupt - * in microseconds - */ - __u32 interrupt_timeout_us; + __u64 target; }; }; @@ -917,7 +913,12 @@ struct hl_wait_cs_in { /* Multi CS API info- valid entries in multi-CS array */ __u8 seq_arr_len; - __u8 pad[7]; + __u8 pad[3]; + + /* Absolute timeout to wait for an interrupt in microseconds. + * Relevant only when HL_WAIT_CS_FLAGS_INTERRUPT is set + */ + __u32 interrupt_timeout_us; }; #define HL_WAIT_CS_STATUS_COMPLETED 0 -- cgit v1.2.3 From dd08335fb909e62bd290117f34490ef4e577b554 Mon Sep 17 00:00:00 2001 From: Yuri Nudelman Date: Thu, 30 Sep 2021 11:18:01 +0300 Subject: habanalabs: fix debugfs device memory MMU VA translation The translation in debugfs of device memory MMU virtual addresses was wrong as it did not take into consideration the fact that the page sizes there can be not power of 2. Signed-off-by: Yuri Nudelman Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/mmu/mmu.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/mmu/mmu.c b/drivers/misc/habanalabs/common/mmu/mmu.c index 792d25b79ea6..aa96917f62e5 100644 --- a/drivers/misc/habanalabs/common/mmu/mmu.c +++ b/drivers/misc/habanalabs/common/mmu/mmu.c @@ -501,23 +501,25 @@ static void hl_mmu_pa_page_with_offset(struct hl_ctx *ctx, u64 virt_addr, if ((hops->range_type == HL_VA_RANGE_TYPE_DRAM) && !is_power_of_2(prop->dram_page_size)) { - unsigned long dram_page_size = prop->dram_page_size; - u64 page_offset_mask; - u64 phys_addr_mask; - u32 bit; + u64 dram_page_size, dram_base, abs_phys_addr, abs_virt_addr, + page_id, page_start; + u32 page_off; /* - * find last set bit in page_size to cover all bits of page - * offset. note that 1 has to be added to bit index. - * note that the internal ulong variable is used to avoid - * alignment issue. + * Bit arithmetics cannot be used for non power of two page + * sizes. In addition, since bit arithmetics is not used, + * we cannot ignore dram base. All that shall be considerd. */ - bit = find_last_bit(&dram_page_size, - sizeof(dram_page_size) * BITS_PER_BYTE) + 1; - page_offset_mask = (BIT_ULL(bit) - 1); - phys_addr_mask = ~page_offset_mask; - *phys_addr = (tmp_phys_addr & phys_addr_mask) | - (virt_addr & page_offset_mask); + + dram_page_size = prop->dram_page_size; + dram_base = prop->dram_base_address; + abs_phys_addr = tmp_phys_addr - dram_base; + abs_virt_addr = virt_addr - dram_base; + page_id = DIV_ROUND_DOWN_ULL(abs_phys_addr, dram_page_size); + page_start = page_id * dram_page_size; + div_u64_rem(abs_virt_addr, dram_page_size, &page_off); + + *phys_addr = page_start + page_off + dram_base; } else { /* * find the correct hop shift field in hl_mmu_properties -- cgit v1.2.3 From a00f1f571e50eb33c5b89db8ac7cd2d684da2943 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Thu, 30 Sep 2021 11:36:07 +0300 Subject: habanalabs: define soft-reset as inference op Soft-reset is the procedure where we reset only the compute/DMA engines of the device, without requiring the current user-space process to release the device. This type of reset can happen if TDR event occurred (a workload got stuck) or by a root request through sysfs. This is only relevant for inference ASICs, as there is no real-world use-case to do that in training, because training runs on multiple devices. In addition, we also do (in certain ASICs) a reset upon device release. That reset uses the same code as the soft-reset. Therefore, to better differentiate between the two resets, it is better to rename the soft-reset support as "inference soft-reset", to make the code more self-explanatory. Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/device.c | 2 +- drivers/misc/habanalabs/common/habanalabs.h | 10 +++++++--- drivers/misc/habanalabs/common/sysfs.c | 6 +++--- drivers/misc/habanalabs/goya/goya.c | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c index 97c7c86580e6..8f96f2bb14ec 100644 --- a/drivers/misc/habanalabs/common/device.c +++ b/drivers/misc/habanalabs/common/device.c @@ -954,7 +954,7 @@ int hl_device_reset(struct hl_device *hdev, u32 flags) goto do_reset; } - if (!hard_reset && !hdev->allow_external_soft_reset) { + if (!hard_reset && !hdev->allow_inference_soft_reset) { hard_instead_soft = true; hard_reset = true; } diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index f8e23ca18a57..99de80915eed 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -2440,8 +2440,12 @@ struct multi_cs_data { * @collective_mon_idx: helper index for collective initialization * @supports_coresight: is CoreSight supported. * @supports_soft_reset: is soft reset supported. - * @allow_external_soft_reset: true if soft reset initiated by user or TDR is - * allowed. + * @allow_inference_soft_reset: true if the ASIC supports soft reset that is + * initiated by user or TDR. This is only true + * in inference ASICs, as there is no real-world + * use-case of doing soft-reset in training (due + * to the fact that training runs on multiple + * devices) * @supports_cb_mapping: is mapping a CB to the device's MMU supported. * @needs_reset: true if reset_on_lockup is false and device should be reset * due to lockup. @@ -2572,7 +2576,7 @@ struct hl_device { u8 collective_mon_idx; u8 supports_coresight; u8 supports_soft_reset; - u8 allow_external_soft_reset; + u8 allow_inference_soft_reset; u8 supports_cb_mapping; u8 needs_reset; u8 process_kill_trial_cnt; diff --git a/drivers/misc/habanalabs/common/sysfs.c b/drivers/misc/habanalabs/common/sysfs.c index 34f9f2779962..42c1769ad25d 100644 --- a/drivers/misc/habanalabs/common/sysfs.c +++ b/drivers/misc/habanalabs/common/sysfs.c @@ -206,12 +206,12 @@ static ssize_t soft_reset_store(struct device *dev, goto out; } - if (!hdev->allow_external_soft_reset) { - dev_err(hdev->dev, "Device does not support soft-reset\n"); + if (!hdev->allow_inference_soft_reset) { + dev_err(hdev->dev, "Device does not support inference soft-reset\n"); goto out; } - dev_warn(hdev->dev, "Soft-Reset requested through sysfs\n"); + dev_warn(hdev->dev, "Inference Soft-Reset requested through sysfs\n"); hl_device_reset(hdev, 0); diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index 031c1849da14..ef67e2586ede 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -959,7 +959,7 @@ static int goya_sw_init(struct hl_device *hdev) spin_lock_init(&goya->hw_queues_lock); hdev->supports_coresight = true; hdev->supports_soft_reset = true; - hdev->allow_external_soft_reset = true; + hdev->allow_inference_soft_reset = true; hdev->supports_wait_for_multi_cs = false; hdev->asic_funcs->set_pci_memory_regions(hdev); -- cgit v1.2.3 From 1282dbbd292e9525cc5659ae1409188b76869c4c Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Thu, 30 Sep 2021 11:53:37 +0300 Subject: habanalabs: refactor reset log message Reset to the device is not necessarily due to an error, so print it as info instead of error. In addition, print the type of reset we are doing: - reset of the entire device (aka hard reset) - reset of the device after user have released it (less than hard reset) - lighter reset of an inference device (aka soft reset) Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/device.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c index 8f96f2bb14ec..be18ad0c1bfc 100644 --- a/drivers/misc/habanalabs/common/device.c +++ b/drivers/misc/habanalabs/common/device.c @@ -1018,7 +1018,14 @@ do_reset: take_release_locks(hdev); - dev_err(hdev->dev, "Going to RESET device!\n"); + if (hard_reset) + dev_info(hdev->dev, "Going to reset device\n"); + else if (flags & HL_RESET_DEVICE_RELEASE) + dev_info(hdev->dev, + "Going to reset device after it was released by user\n"); + else + dev_info(hdev->dev, + "Going to reset compute engines of inference device\n"); } again: -- cgit v1.2.3 From c1904127ce8d1b37154c1a1d1fc5836a0ef6c830 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Thu, 30 Sep 2021 11:22:32 +0300 Subject: habanalabs: prevent race between fd close/open The driver allows only a single process to open a device's FD at any single time. This is done by checking "hdev->compute_ctx" under mutex. Therefore, to prevent a race between the moment a user closes it's FD and when another user tries to open the device, we need to make sure that clearing this variable is the very last thing that is done in the code of the FD's release. I'm moving the idle check before clearing this variable and the "reset on device release". btw, if the reset happens it will prevent any other user from opening the device until the reset is finished. An important thing to note is that we need to remove the user process that is closing the device from the process list BEFORE calling the reset function. That is to prevent a case where the reset code will try to kill that user process and it is unnecessary as the process doesn't hold any device/driver resources anymore. Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/device.c | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c index be18ad0c1bfc..e1949b087ae3 100644 --- a/drivers/misc/habanalabs/common/device.c +++ b/drivers/misc/habanalabs/common/device.c @@ -69,13 +69,6 @@ static void hpriv_release(struct kref *ref) mutex_destroy(&hpriv->restore_phase_mutex); - mutex_lock(&hdev->fpriv_list_lock); - list_del(&hpriv->dev_node); - hdev->compute_ctx = NULL; - mutex_unlock(&hdev->fpriv_list_lock); - - kfree(hpriv); - if ((!hdev->pldm) && (hdev->pdev) && (!hdev->asic_funcs->is_device_idle(hdev, idle_mask, @@ -87,9 +80,32 @@ static void hpriv_release(struct kref *ref) device_is_idle = false; } + /* We need to remove the user from the list to make sure the reset process won't + * try to kill the user process. Because, if we got here, it means there are no + * more driver/device resources that the user process is occupying so there is + * no need to kill it + * + * However, we can't set the compute_ctx to NULL at this stage. This is to prevent + * a race between the release and opening the device again. We don't want to let + * a user open the device while there a reset is about to happen. + */ + mutex_lock(&hdev->fpriv_list_lock); + list_del(&hpriv->dev_node); + mutex_unlock(&hdev->fpriv_list_lock); + if ((hdev->reset_if_device_not_idle && !device_is_idle) || hdev->reset_upon_device_release) hl_device_reset(hdev, HL_RESET_DEVICE_RELEASE); + + /* Now we can mark the compute_ctx as empty. Even if a reset is running in a different + * thread, we don't care because the in_reset is marked so if a user will try to open + * the device it will fail on that, even if compute_ctx is NULL. + */ + mutex_lock(&hdev->fpriv_list_lock); + hdev->compute_ctx = NULL; + mutex_unlock(&hdev->fpriv_list_lock); + + kfree(hpriv); } void hl_hpriv_get(struct hl_fpriv *hpriv) -- cgit v1.2.3 From f05d17b226dbb5e2f21b724918b263cba57f2ad8 Mon Sep 17 00:00:00 2001 From: Yuri Nudelman Date: Thu, 23 Sep 2021 17:40:14 +0300 Subject: habanalabs: take timestamp on wait for interrupt Taking an accurate timestamp in a close proximity of the interrupt is required for user side statistics management. Signed-off-by: Yuri Nudelman Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/command_submission.c | 17 +++++++++++++++-- drivers/misc/habanalabs/common/habanalabs.h | 2 ++ drivers/misc/habanalabs/common/irq.c | 5 ++++- 3 files changed, 21 insertions(+), 3 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index 44bab01cd033..4bc24852a283 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -2740,7 +2740,8 @@ static int hl_cs_wait_ioctl(struct hl_fpriv *hpriv, void *data) static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, u32 timeout_us, u64 user_address, u64 target_value, u16 interrupt_offset, - enum hl_cs_wait_status *status) + enum hl_cs_wait_status *status, + bool take_timestamp, u64 *timestamp) { struct hl_user_pending_interrupt *pend; struct hl_user_interrupt *interrupt; @@ -2764,6 +2765,8 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, hl_fence_init(&pend->fence, ULONG_MAX); + pend->fence.take_timestamp = take_timestamp; + if (interrupt_offset == HL_COMMON_USER_INTERRUPT_ID) interrupt = &hdev->common_user_interrupt; else @@ -2838,6 +2841,8 @@ remove_pending_user_interrupt: list_del(&pend->wait_list_node); spin_unlock_irqrestore(&interrupt->wait_list_lock, flags); + *timestamp = ktime_to_ns(pend->fence.timestamp); + kfree(pend); hl_ctx_put(ctx); @@ -2851,6 +2856,7 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data) struct asic_fixed_properties *prop; union hl_wait_cs_args *args = data; enum hl_cs_wait_status status; + u64 timestamp; int rc; prop = &hdev->asic_prop; @@ -2880,7 +2886,9 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data) rc = _hl_interrupt_wait_ioctl(hdev, hpriv->ctx, args->in.interrupt_timeout_us, args->in.addr, - args->in.target, interrupt_offset, &status); + args->in.target, interrupt_offset, &status, + args->in.flags & HL_CS_FLAGS_TIMESTAMP, + ×tamp); if (rc) { if (rc != -EINTR) @@ -2892,6 +2900,11 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data) memset(args, 0, sizeof(*args)); + if (timestamp) { + args->out.timestamp_nsec = timestamp; + args->out.flags |= HL_WAIT_CS_STATUS_FLAG_TIMESTAMP_VLD; + } + switch (status) { case CS_WAIT_STATUS_COMPLETED: args->out.status = HL_WAIT_CS_STATUS_COMPLETED; diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index 99de80915eed..2d9edd734d1c 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -601,6 +601,7 @@ struct asic_fixed_properties { * masters QIDs that multi cs is waiting on * @error: mark this fence with error * @timestamp: timestamp upon completion + * @take_timestamp: timestamp shall be taken upon completion */ struct hl_fence { struct completion completion; @@ -609,6 +610,7 @@ struct hl_fence { u32 stream_master_qid_map; int error; ktime_t timestamp; + u8 take_timestamp; }; /** diff --git a/drivers/misc/habanalabs/common/irq.c b/drivers/misc/habanalabs/common/irq.c index 39b14a933393..0dd00ffd1809 100644 --- a/drivers/misc/habanalabs/common/irq.c +++ b/drivers/misc/habanalabs/common/irq.c @@ -143,8 +143,11 @@ static void handle_user_cq(struct hl_device *hdev, struct hl_user_pending_interrupt *pend; spin_lock(&user_cq->wait_list_lock); - list_for_each_entry(pend, &user_cq->wait_list_head, wait_list_node) + list_for_each_entry(pend, &user_cq->wait_list_head, wait_list_node) { + if (pend->fence.take_timestamp) + pend->fence.timestamp = ktime_get(); complete_all(&pend->fence.completion); + } spin_unlock(&user_cq->wait_list_lock); } -- cgit v1.2.3 From 10cab81d1cf92b1b62234540efba34ccaf7079e8 Mon Sep 17 00:00:00 2001 From: Bharat Jauhari Date: Mon, 21 Jun 2021 09:57:19 +0300 Subject: habanalabs: bypass reset for continuous h/w error event There may be a situation where drivers receives continuous fatal H/W error events from FW immediately post reset cycle. This may be due to some fault on the silicon itself. In such case its better to bypass reset cycle so we won't be stuck in endless loop of resets. This commit bypasses reset request in case driver received two back to back FW fatal error before first occurrence of heartbeat event. Signed-off-by: Bharat Jauhari Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/device.c | 118 +++++++++++++++++------- drivers/misc/habanalabs/common/habanalabs.h | 14 +++ drivers/misc/habanalabs/common/habanalabs_drv.c | 1 + drivers/misc/habanalabs/gaudi/gaudi.c | 8 +- drivers/misc/habanalabs/goya/goya.c | 6 ++ 5 files changed, 111 insertions(+), 36 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/device.c b/drivers/misc/habanalabs/common/device.c index e1949b087ae3..2022e5d7b3ad 100644 --- a/drivers/misc/habanalabs/common/device.c +++ b/drivers/misc/habanalabs/common/device.c @@ -546,6 +546,19 @@ static void hl_device_heartbeat(struct work_struct *work) return; reschedule: + /* + * prev_reset_trigger tracks consecutive fatal h/w errors until first + * heartbeat immediately post reset. + * If control reached here, then at least one heartbeat work has been + * scheduled since last reset/init cycle. + * So if the device is not already in reset cycle, reset the flag + * prev_reset_trigger as no reset occurred with HL_RESET_FW_FATAL_ERR + * status for at least one heartbeat. From this point driver restarts + * tracking future consecutive fatal errors. + */ + if (!(atomic_read(&hdev->in_reset))) + hdev->prev_reset_trigger = HL_RESET_TRIGGER_DEFAULT; + schedule_delayed_work(&hdev->work_heartbeat, usecs_to_jiffies(HL_HEARTBEAT_PER_USEC)); } @@ -925,6 +938,65 @@ static void device_disable_open_processes(struct hl_device *hdev) mutex_unlock(&hdev->fpriv_list_lock); } +static void handle_reset_trigger(struct hl_device *hdev, u32 flags) +{ + u32 cur_reset_trigger = HL_RESET_TRIGGER_DEFAULT; + + /* + * 'reset cause' is being updated here, because getting here + * means that it's the 1st time and the last time we're here + * ('in_reset' makes sure of it). This makes sure that + * 'reset_cause' will continue holding its 1st recorded reason! + */ + if (flags & HL_RESET_HEARTBEAT) { + hdev->curr_reset_cause = HL_RESET_CAUSE_HEARTBEAT; + cur_reset_trigger = HL_RESET_HEARTBEAT; + } else if (flags & HL_RESET_TDR) { + hdev->curr_reset_cause = HL_RESET_CAUSE_TDR; + cur_reset_trigger = HL_RESET_TDR; + } else if (flags & HL_RESET_FW_FATAL_ERR) { + hdev->curr_reset_cause = HL_RESET_CAUSE_UNKNOWN; + cur_reset_trigger = HL_RESET_FW_FATAL_ERR; + } else { + hdev->curr_reset_cause = HL_RESET_CAUSE_UNKNOWN; + } + + /* + * If reset cause is same twice, then reset_trigger_repeated + * is set and if this reset is due to a fatal FW error + * device is set to an unstable state. + */ + if (hdev->prev_reset_trigger != cur_reset_trigger) { + hdev->prev_reset_trigger = cur_reset_trigger; + hdev->reset_trigger_repeated = 0; + } else { + hdev->reset_trigger_repeated = 1; + } + + /* If reset is due to heartbeat, device CPU is no responsive in + * which case no point sending PCI disable message to it. + * + * If F/W is performing the reset, no need to send it a message to disable + * PCI access + */ + if ((flags & HL_RESET_HARD) && + !(flags & (HL_RESET_HEARTBEAT | HL_RESET_FW))) { + /* Disable PCI access from device F/W so he won't send + * us additional interrupts. We disable MSI/MSI-X at + * the halt_engines function and we can't have the F/W + * sending us interrupts after that. We need to disable + * the access here because if the device is marked + * disable, the message won't be send. Also, in case + * of heartbeat, the device CPU is marked as disable + * so this message won't be sent + */ + if (hl_fw_send_pci_access_msg(hdev, + CPUCP_PACKET_DISABLE_PCI_ACCESS)) + dev_warn(hdev->dev, + "Failed to disable PCI access by F/W\n"); + } +} + /* * hl_device_reset - reset the device * @@ -994,40 +1066,7 @@ do_reset: if (rc) return 0; - /* - * 'reset cause' is being updated here, because getting here - * means that it's the 1st time and the last time we're here - * ('in_reset' makes sure of it). This makes sure that - * 'reset_cause' will continue holding its 1st recorded reason! - */ - if (flags & HL_RESET_HEARTBEAT) - hdev->curr_reset_cause = HL_RESET_CAUSE_HEARTBEAT; - else if (flags & HL_RESET_TDR) - hdev->curr_reset_cause = HL_RESET_CAUSE_TDR; - else - hdev->curr_reset_cause = HL_RESET_CAUSE_UNKNOWN; - - /* If reset is due to heartbeat, device CPU is no responsive in - * which case no point sending PCI disable message to it. - * - * If F/W is performing the reset, no need to send it a message to disable - * PCI access - */ - if (hard_reset && !(flags & (HL_RESET_HEARTBEAT | HL_RESET_FW))) { - /* Disable PCI access from device F/W so he won't send - * us additional interrupts. We disable MSI/MSI-X at - * the halt_engines function and we can't have the F/W - * sending us interrupts after that. We need to disable - * the access here because if the device is marked - * disable, the message won't be send. Also, in case - * of heartbeat, the device CPU is marked as disable - * so this message won't be sent - */ - if (hl_fw_send_pci_access_msg(hdev, - CPUCP_PACKET_DISABLE_PCI_ACCESS)) - dev_warn(hdev->dev, - "Failed to disable PCI access by F/W\n"); - } + handle_reset_trigger(hdev, flags); /* This also blocks future CS/VM/JOB completion operations */ hdev->disabled = true; @@ -1131,6 +1170,17 @@ kill_processes: hdev->device_cpu_disabled = false; hdev->hard_reset_pending = false; + if (hdev->reset_trigger_repeated && + (hdev->prev_reset_trigger == HL_RESET_FW_FATAL_ERR)) { + /* if there 2 back to back resets from FW, + * ensure driver puts the driver in a unusable state + */ + dev_crit(hdev->dev, + "Consecutive FW fatal errors received, stopping hard reset\n"); + rc = -EIO; + goto out_err; + } + if (hdev->kernel_ctx) { dev_crit(hdev->dev, "kernel ctx was alive during hard reset, something is terribly wrong\n"); diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index 2d9edd734d1c..a06135155b57 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -68,6 +68,9 @@ #define HL_STATE_DUMP_HIST_LEN 5 +/* Default value for device reset trigger , an invalid value */ +#define HL_RESET_TRIGGER_DEFAULT 0xFF + #define OBJ_NAMES_HASH_TABLE_BITS 7 /* 1 << 7 buckets */ #define SYNC_TO_ENGINE_HASH_TABLE_BITS 7 /* 1 << 7 buckets */ @@ -132,13 +135,18 @@ enum hl_mmu_page_table_location { * - HL_RESET_FW * F/W will perform the reset. No need to ask it to reset the device. This is relevant * only when running with secured f/w + * + * - HL_RESET_FW_FATAL_ERR + * Set if reset is due to a fatal error from FW */ + #define HL_RESET_HARD (1 << 0) #define HL_RESET_FROM_RESET_THREAD (1 << 1) #define HL_RESET_HEARTBEAT (1 << 2) #define HL_RESET_TDR (1 << 3) #define HL_RESET_DEVICE_RELEASE (1 << 4) #define HL_RESET_FW (1 << 5) +#define HL_RESET_FW_FATAL_ERR (1 << 6) #define HL_MAX_SOBS_PER_MONITOR 8 @@ -2458,6 +2466,10 @@ struct multi_cs_data { * @supports_staged_submission: true if staged submissions are supported * @curr_reset_cause: saves an enumerated reset cause when a hard reset is * triggered, and cleared after it is shared with preboot. + * @prev_reset_trigger: saves the previous trigger which caused a reset, overidden + * with a new value on next reset + * @reset_trigger_repeated: set if device reset is triggered more than once with + * same cause. * @skip_reset_on_timeout: Skip device reset if CS has timed out, wait for it to * complete instead. * @device_cpu_is_halted: Flag to indicate whether the device CPU was already @@ -2585,6 +2597,8 @@ struct hl_device { u8 device_fini_pending; u8 supports_staged_submission; u8 curr_reset_cause; + u8 prev_reset_trigger; + u8 reset_trigger_repeated; u8 skip_reset_on_timeout; u8 device_cpu_is_halted; u8 supports_wait_for_multi_cs; diff --git a/drivers/misc/habanalabs/common/habanalabs_drv.c b/drivers/misc/habanalabs/common/habanalabs_drv.c index a75e4fceb9d8..1da56069750a 100644 --- a/drivers/misc/habanalabs/common/habanalabs_drv.c +++ b/drivers/misc/habanalabs/common/habanalabs_drv.c @@ -339,6 +339,7 @@ int create_hdev(struct hl_device **dev, struct pci_dev *pdev, set_driver_behavior_per_device(hdev); hdev->curr_reset_cause = HL_RESET_CAUSE_UNKNOWN; + hdev->prev_reset_trigger = HL_RESET_TRIGGER_DEFAULT; if (timeout_locked) hdev->timeout_jiffies = msecs_to_jiffies(timeout_locked * 1000); diff --git a/drivers/misc/habanalabs/gaudi/gaudi.c b/drivers/misc/habanalabs/gaudi/gaudi.c index 14da87b38e83..70a668951ec4 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi.c +++ b/drivers/misc/habanalabs/gaudi/gaudi.c @@ -7932,6 +7932,7 @@ static void gaudi_handle_eqe(struct hl_device *hdev, { struct gaudi_device *gaudi = hdev->asic_specific; u32 ctl = le32_to_cpu(eq_entry->hdr.ctl); + u32 fw_fatal_err_flag = 0; u16 event_type = ((ctl & EQ_CTL_EVENT_TYPE_MASK) >> EQ_CTL_EVENT_TYPE_SHIFT); bool reset_required; @@ -7972,6 +7973,7 @@ static void gaudi_handle_eqe(struct hl_device *hdev, case GAUDI_EVENT_NIC0_CS_DBG_DERR ... GAUDI_EVENT_NIC4_CS_DBG_DERR: gaudi_print_irq_info(hdev, event_type, true); gaudi_handle_ecc_event(hdev, event_type, &eq_entry->ecc_data); + fw_fatal_err_flag = HL_RESET_FW_FATAL_ERR; goto reset_device; case GAUDI_EVENT_GIC500: @@ -7979,6 +7981,7 @@ static void gaudi_handle_eqe(struct hl_device *hdev, case GAUDI_EVENT_L2_RAM_ECC: case GAUDI_EVENT_PLL0 ... GAUDI_EVENT_PLL17: gaudi_print_irq_info(hdev, event_type, false); + fw_fatal_err_flag = HL_RESET_FW_FATAL_ERR; goto reset_device; case GAUDI_EVENT_HBM0_SPI_0: @@ -7989,6 +7992,7 @@ static void gaudi_handle_eqe(struct hl_device *hdev, gaudi_hbm_read_interrupts(hdev, gaudi_hbm_event_to_dev(event_type), &eq_entry->hbm_ecc_data); + fw_fatal_err_flag = HL_RESET_FW_FATAL_ERR; goto reset_device; case GAUDI_EVENT_HBM0_SPI_1: @@ -8171,9 +8175,9 @@ static void gaudi_handle_eqe(struct hl_device *hdev, reset_device: if (hdev->asic_prop.fw_security_enabled) - hl_device_reset(hdev, HL_RESET_HARD | HL_RESET_FW); + hl_device_reset(hdev, HL_RESET_HARD | HL_RESET_FW | fw_fatal_err_flag); else if (hdev->hard_reset_on_fw_events) - hl_device_reset(hdev, HL_RESET_HARD); + hl_device_reset(hdev, HL_RESET_HARD | fw_fatal_err_flag); else hl_fw_unmask_irq(hdev, event_type); } diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index ef67e2586ede..78cf35879680 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -4829,6 +4829,12 @@ void goya_handle_eqe(struct hl_device *hdev, struct hl_eq_entry *eq_entry) case GOYA_ASYNC_EVENT_ID_PLL0 ... GOYA_ASYNC_EVENT_ID_PLL6: case GOYA_ASYNC_EVENT_ID_AXI_ECC: case GOYA_ASYNC_EVENT_ID_L2_RAM_ECC: + goya_print_irq_info(hdev, event_type, false); + if (hdev->hard_reset_on_fw_events) + hl_device_reset(hdev, (HL_RESET_HARD | + HL_RESET_FW_FATAL_ERR)); + break; + case GOYA_ASYNC_EVENT_ID_PSOC_GPIO_05_SW_RESET: goya_print_irq_info(hdev, event_type, false); if (hdev->hard_reset_on_fw_events) -- cgit v1.2.3 From efc6b04b869bcbcbe64da5d58eb1208599fb8041 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Tue, 5 Oct 2021 17:46:42 +0300 Subject: habanalabs: update firmware files Update the firmware headers to the latest version Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/include/common/cpucp_if.h | 12 +- .../misc/habanalabs/include/common/hl_boot_if.h | 185 +++++++++++++-------- .../misc/habanalabs/include/gaudi/gaudi_fw_if.h | 10 +- .../misc/habanalabs/include/gaudi/gaudi_reg_map.h | 1 + 4 files changed, 130 insertions(+), 78 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/include/common/cpucp_if.h b/drivers/misc/habanalabs/include/common/cpucp_if.h index a6fa1cfa38a5..ae13231fda94 100644 --- a/drivers/misc/habanalabs/include/common/cpucp_if.h +++ b/drivers/misc/habanalabs/include/common/cpucp_if.h @@ -542,11 +542,14 @@ enum cpucp_packet_rc { */ enum cpucp_temp_type { cpucp_temp_input, + cpucp_temp_min = 4, + cpucp_temp_min_hyst, cpucp_temp_max = 6, cpucp_temp_max_hyst, cpucp_temp_crit, cpucp_temp_crit_hyst, cpucp_temp_offset = 19, + cpucp_temp_lowest = 21, cpucp_temp_highest = 22, cpucp_temp_reset_history = 23 }; @@ -555,6 +558,7 @@ enum cpucp_in_attributes { cpucp_in_input, cpucp_in_min, cpucp_in_max, + cpucp_in_lowest = 6, cpucp_in_highest = 7, cpucp_in_reset_history }; @@ -563,6 +567,7 @@ enum cpucp_curr_attributes { cpucp_curr_input, cpucp_curr_min, cpucp_curr_max, + cpucp_curr_lowest = 6, cpucp_curr_highest = 7, cpucp_curr_reset_history }; @@ -741,6 +746,9 @@ struct cpucp_security_info { * @pll_map: Bit map of supported PLLs for current ASIC version. * @mme_binning_mask: MME binning mask, * (0 = functional, 1 = binned) + * @dram_binning_mask: DRAM binning mask, 1 bit per dram instance + * (0 = functional 1 = binned) + * @memory_repair_flag: eFuse flag indicating memory repair */ struct cpucp_info { struct cpucp_sensor sensors[CPUCP_MAX_SENSORS]; @@ -759,7 +767,9 @@ struct cpucp_info { __le64 reserved3; __le64 reserved4; __u8 reserved5; - __u8 pad[7]; + __u8 dram_binning_mask; + __u8 memory_repair_flag; + __u8 pad[5]; struct cpucp_security_info sec_info; __le32 reserved6; __u8 pll_map[PLL_MAP_LEN]; diff --git a/drivers/misc/habanalabs/include/common/hl_boot_if.h b/drivers/misc/habanalabs/include/common/hl_boot_if.h index 8837925b5d85..2626df6ef3ef 100644 --- a/drivers/misc/habanalabs/include/common/hl_boot_if.h +++ b/drivers/misc/habanalabs/include/common/hl_boot_if.h @@ -15,6 +15,28 @@ #define VERSION_MAX_LEN 128 +enum cpu_boot_err { + CPU_BOOT_ERR_DRAM_INIT_FAIL = 0, + CPU_BOOT_ERR_FIT_CORRUPTED = 1, + CPU_BOOT_ERR_TS_INIT_FAIL = 2, + CPU_BOOT_ERR_DRAM_SKIPPED = 3, + CPU_BOOT_ERR_BMC_WAIT_SKIPPED = 4, + CPU_BOOT_ERR_NIC_DATA_NOT_RDY = 5, + CPU_BOOT_ERR_NIC_FW_FAIL = 6, + CPU_BOOT_ERR_SECURITY_NOT_RDY = 7, + CPU_BOOT_ERR_SECURITY_FAIL = 8, + CPU_BOOT_ERR_EFUSE_FAIL = 9, + CPU_BOOT_ERR_PRI_IMG_VER_FAIL = 10, + CPU_BOOT_ERR_SEC_IMG_VER_FAIL = 11, + CPU_BOOT_ERR_PLL_FAIL = 12, + CPU_BOOT_ERR_DEVICE_UNUSABLE_FAIL = 13, + CPU_BOOT_ERR_BOOT_FW_CRIT_ERR = 18, + CPU_BOOT_ERR_BINNING_FAIL = 19, + CPU_BOOT_ERR_ENABLED = 31, + CPU_BOOT_ERR_SCND_EN = 63, + CPU_BOOT_ERR_LAST = 64 /* we have 2 registers of 32 bits */ +}; + /* * CPU error bits in BOOT_ERROR registers * @@ -78,25 +100,13 @@ * CPU_BOOT_ERR0_DEVICE_UNUSABLE_FAIL Device is unusable and customer support * should be contacted. * - * CPU_BOOT_ERR0_ARC0_HALT_ACK_NOT_RCVD HALT ACK from ARC0 is not received - * within specified retries after issuing - * HALT request. ARC0 appears to be in bad - * reset. - * - * CPU_BOOT_ERR0_ARC1_HALT_ACK_NOT_RCVD HALT ACK from ARC1 is not received - * within specified retries after issuing - * HALT request. ARC1 appears to be in bad - * reset. - * - * CPU_BOOT_ERR0_ARC0_RUN_ACK_NOT_RCVD RUN ACK from ARC0 is not received - * within specified timeout after issuing - * RUN request. ARC0 appears to be in bad - * reset. + * CPU_BOOT_ERR0_BOOT_FW_CRIT_ERR Critical error was detected during + * the execution of ppboot or preboot. + * for example: stack overflow. * - * CPU_BOOT_ERR0_ARC1_RUN_ACK_NOT_RCVD RUN ACK from ARC1 is not received - * within specified timeout after issuing - * RUN request. ARC1 appears to be in bad - * reset. + * CPU_BOOT_ERR0_BINNING_FAIL Binning settings failed, meaning + * malfunctioning components might still be + * in use. * * CPU_BOOT_ERR0_ENABLED Error registers enabled. * This is a main indication that the @@ -104,26 +114,57 @@ * registers. Meaning the error bits are * not garbage, but actual error statuses. */ -#define CPU_BOOT_ERR0_DRAM_INIT_FAIL (1 << 0) -#define CPU_BOOT_ERR0_FIT_CORRUPTED (1 << 1) -#define CPU_BOOT_ERR0_TS_INIT_FAIL (1 << 2) -#define CPU_BOOT_ERR0_DRAM_SKIPPED (1 << 3) -#define CPU_BOOT_ERR0_BMC_WAIT_SKIPPED (1 << 4) -#define CPU_BOOT_ERR0_NIC_DATA_NOT_RDY (1 << 5) -#define CPU_BOOT_ERR0_NIC_FW_FAIL (1 << 6) -#define CPU_BOOT_ERR0_SECURITY_NOT_RDY (1 << 7) -#define CPU_BOOT_ERR0_SECURITY_FAIL (1 << 8) -#define CPU_BOOT_ERR0_EFUSE_FAIL (1 << 9) -#define CPU_BOOT_ERR0_PRI_IMG_VER_FAIL (1 << 10) -#define CPU_BOOT_ERR0_SEC_IMG_VER_FAIL (1 << 11) -#define CPU_BOOT_ERR0_PLL_FAIL (1 << 12) -#define CPU_BOOT_ERR0_DEVICE_UNUSABLE_FAIL (1 << 13) -#define CPU_BOOT_ERR0_ARC0_HALT_ACK_NOT_RCVD (1 << 14) -#define CPU_BOOT_ERR0_ARC1_HALT_ACK_NOT_RCVD (1 << 15) -#define CPU_BOOT_ERR0_ARC0_RUN_ACK_NOT_RCVD (1 << 16) -#define CPU_BOOT_ERR0_ARC1_RUN_ACK_NOT_RCVD (1 << 17) -#define CPU_BOOT_ERR0_ENABLED (1 << 31) -#define CPU_BOOT_ERR1_ENABLED (1 << 31) +#define CPU_BOOT_ERR0_DRAM_INIT_FAIL (1 << CPU_BOOT_ERR_DRAM_INIT_FAIL) +#define CPU_BOOT_ERR0_FIT_CORRUPTED (1 << CPU_BOOT_ERR_FIT_CORRUPTED) +#define CPU_BOOT_ERR0_TS_INIT_FAIL (1 << CPU_BOOT_ERR_TS_INIT_FAIL) +#define CPU_BOOT_ERR0_DRAM_SKIPPED (1 << CPU_BOOT_ERR_DRAM_SKIPPED) +#define CPU_BOOT_ERR0_BMC_WAIT_SKIPPED (1 << CPU_BOOT_ERR_BMC_WAIT_SKIPPED) +#define CPU_BOOT_ERR0_NIC_DATA_NOT_RDY (1 << CPU_BOOT_ERR_NIC_DATA_NOT_RDY) +#define CPU_BOOT_ERR0_NIC_FW_FAIL (1 << CPU_BOOT_ERR_NIC_FW_FAIL) +#define CPU_BOOT_ERR0_SECURITY_NOT_RDY (1 << CPU_BOOT_ERR_SECURITY_NOT_RDY) +#define CPU_BOOT_ERR0_SECURITY_FAIL (1 << CPU_BOOT_ERR_SECURITY_FAIL) +#define CPU_BOOT_ERR0_EFUSE_FAIL (1 << CPU_BOOT_ERR_EFUSE_FAIL) +#define CPU_BOOT_ERR0_PRI_IMG_VER_FAIL (1 << CPU_BOOT_ERR_PRI_IMG_VER_FAIL) +#define CPU_BOOT_ERR0_SEC_IMG_VER_FAIL (1 << CPU_BOOT_ERR_SEC_IMG_VER_FAIL) +#define CPU_BOOT_ERR0_PLL_FAIL (1 << CPU_BOOT_ERR_PLL_FAIL) +#define CPU_BOOT_ERR0_DEVICE_UNUSABLE_FAIL (1 << CPU_BOOT_ERR_DEVICE_UNUSABLE_FAIL) +#define CPU_BOOT_ERR0_BOOT_FW_CRIT_ERR (1 << CPU_BOOT_ERR_BOOT_FW_CRIT_ERR) +#define CPU_BOOT_ERR0_BINNING_FAIL (1 << CPU_BOOT_ERR_BINNING_FAIL) +#define CPU_BOOT_ERR0_ENABLED (1 << CPU_BOOT_ERR_ENABLED) +#define CPU_BOOT_ERR1_ENABLED (1 << CPU_BOOT_ERR_ENABLED) + +enum cpu_boot_dev_sts { + CPU_BOOT_DEV_STS_SECURITY_EN = 0, + CPU_BOOT_DEV_STS_DEBUG_EN = 1, + CPU_BOOT_DEV_STS_WATCHDOG_EN = 2, + CPU_BOOT_DEV_STS_DRAM_INIT_EN = 3, + CPU_BOOT_DEV_STS_BMC_WAIT_EN = 4, + CPU_BOOT_DEV_STS_E2E_CRED_EN = 5, + CPU_BOOT_DEV_STS_HBM_CRED_EN = 6, + CPU_BOOT_DEV_STS_RL_EN = 7, + CPU_BOOT_DEV_STS_SRAM_SCR_EN = 8, + CPU_BOOT_DEV_STS_DRAM_SCR_EN = 9, + CPU_BOOT_DEV_STS_FW_HARD_RST_EN = 10, + CPU_BOOT_DEV_STS_PLL_INFO_EN = 11, + CPU_BOOT_DEV_STS_SP_SRAM_EN = 12, + CPU_BOOT_DEV_STS_CLK_GATE_EN = 13, + CPU_BOOT_DEV_STS_HBM_ECC_EN = 14, + CPU_BOOT_DEV_STS_PKT_PI_ACK_EN = 15, + CPU_BOOT_DEV_STS_FW_LD_COM_EN = 16, + CPU_BOOT_DEV_STS_FW_IATU_CONF_EN = 17, + CPU_BOOT_DEV_STS_FW_NIC_MAC_EN = 18, + CPU_BOOT_DEV_STS_DYN_PLL_EN = 19, + CPU_BOOT_DEV_STS_GIC_PRIVILEGED_EN = 20, + CPU_BOOT_DEV_STS_EQ_INDEX_EN = 21, + CPU_BOOT_DEV_STS_MULTI_IRQ_POLL_EN = 22, + CPU_BOOT_DEV_STS_FW_NIC_STAT_XPCS91_EN = 23, + CPU_BOOT_DEV_STS_FW_NIC_STAT_EXT_EN = 24, + CPU_BOOT_DEV_STS_IS_IDLE_CHECK_EN = 25, + CPU_BOOT_DEV_STS_MAP_HWMON_EN = 26, + CPU_BOOT_DEV_STS_ENABLED = 31, + CPU_BOOT_DEV_STS_SCND_EN = 63, + CPU_BOOT_DEV_STS_LAST = 64 /* we have 2 registers of 32 bits */ +}; /* * BOOT DEVICE STATUS bits in BOOT_DEVICE_STS registers @@ -233,7 +274,7 @@ * was not served before. * Initialized in: linux * - * CPU_BOOT_DEV_STS0_MULTI_IRQ_POLL_EN Use multiple scratchpad interfaces to + * CPU_BOOT_DEV_STS0_MULTI_IRQ_POLL_EN Use multiple scratchpad interfaces to * prevent IRQs overriding each other. * Initialized in: linux * @@ -266,35 +307,35 @@ * Initialized in: preboot * */ -#define CPU_BOOT_DEV_STS0_SECURITY_EN (1 << 0) -#define CPU_BOOT_DEV_STS0_DEBUG_EN (1 << 1) -#define CPU_BOOT_DEV_STS0_WATCHDOG_EN (1 << 2) -#define CPU_BOOT_DEV_STS0_DRAM_INIT_EN (1 << 3) -#define CPU_BOOT_DEV_STS0_BMC_WAIT_EN (1 << 4) -#define CPU_BOOT_DEV_STS0_E2E_CRED_EN (1 << 5) -#define CPU_BOOT_DEV_STS0_HBM_CRED_EN (1 << 6) -#define CPU_BOOT_DEV_STS0_RL_EN (1 << 7) -#define CPU_BOOT_DEV_STS0_SRAM_SCR_EN (1 << 8) -#define CPU_BOOT_DEV_STS0_DRAM_SCR_EN (1 << 9) -#define CPU_BOOT_DEV_STS0_FW_HARD_RST_EN (1 << 10) -#define CPU_BOOT_DEV_STS0_PLL_INFO_EN (1 << 11) -#define CPU_BOOT_DEV_STS0_SP_SRAM_EN (1 << 12) -#define CPU_BOOT_DEV_STS0_CLK_GATE_EN (1 << 13) -#define CPU_BOOT_DEV_STS0_HBM_ECC_EN (1 << 14) -#define CPU_BOOT_DEV_STS0_PKT_PI_ACK_EN (1 << 15) -#define CPU_BOOT_DEV_STS0_FW_LD_COM_EN (1 << 16) -#define CPU_BOOT_DEV_STS0_FW_IATU_CONF_EN (1 << 17) -#define CPU_BOOT_DEV_STS0_FW_NIC_MAC_EN (1 << 18) -#define CPU_BOOT_DEV_STS0_DYN_PLL_EN (1 << 19) -#define CPU_BOOT_DEV_STS0_GIC_PRIVILEGED_EN (1 << 20) -#define CPU_BOOT_DEV_STS0_EQ_INDEX_EN (1 << 21) -#define CPU_BOOT_DEV_STS0_MULTI_IRQ_POLL_EN (1 << 22) -#define CPU_BOOT_DEV_STS0_FW_NIC_STAT_XPCS91_EN (1 << 23) -#define CPU_BOOT_DEV_STS0_FW_NIC_STAT_EXT_EN (1 << 24) -#define CPU_BOOT_DEV_STS0_IS_IDLE_CHECK_EN (1 << 25) -#define CPU_BOOT_DEV_STS0_MAP_HWMON_EN (1 << 26) -#define CPU_BOOT_DEV_STS0_ENABLED (1 << 31) -#define CPU_BOOT_DEV_STS1_ENABLED (1 << 31) +#define CPU_BOOT_DEV_STS0_SECURITY_EN (1 << CPU_BOOT_DEV_STS_SECURITY_EN) +#define CPU_BOOT_DEV_STS0_DEBUG_EN (1 << CPU_BOOT_DEV_STS_DEBUG_EN) +#define CPU_BOOT_DEV_STS0_WATCHDOG_EN (1 << CPU_BOOT_DEV_STS_WATCHDOG_EN) +#define CPU_BOOT_DEV_STS0_DRAM_INIT_EN (1 << CPU_BOOT_DEV_STS_DRAM_INIT_EN) +#define CPU_BOOT_DEV_STS0_BMC_WAIT_EN (1 << CPU_BOOT_DEV_STS_BMC_WAIT_EN) +#define CPU_BOOT_DEV_STS0_E2E_CRED_EN (1 << CPU_BOOT_DEV_STS_E2E_CRED_EN) +#define CPU_BOOT_DEV_STS0_HBM_CRED_EN (1 << CPU_BOOT_DEV_STS_HBM_CRED_EN) +#define CPU_BOOT_DEV_STS0_RL_EN (1 << CPU_BOOT_DEV_STS_RL_EN) +#define CPU_BOOT_DEV_STS0_SRAM_SCR_EN (1 << CPU_BOOT_DEV_STS_SRAM_SCR_EN) +#define CPU_BOOT_DEV_STS0_DRAM_SCR_EN (1 << CPU_BOOT_DEV_STS_DRAM_SCR_EN) +#define CPU_BOOT_DEV_STS0_FW_HARD_RST_EN (1 << CPU_BOOT_DEV_STS_FW_HARD_RST_EN) +#define CPU_BOOT_DEV_STS0_PLL_INFO_EN (1 << CPU_BOOT_DEV_STS_PLL_INFO_EN) +#define CPU_BOOT_DEV_STS0_SP_SRAM_EN (1 << CPU_BOOT_DEV_STS_SP_SRAM_EN) +#define CPU_BOOT_DEV_STS0_CLK_GATE_EN (1 << CPU_BOOT_DEV_STS_CLK_GATE_EN) +#define CPU_BOOT_DEV_STS0_HBM_ECC_EN (1 << CPU_BOOT_DEV_STS_HBM_ECC_EN) +#define CPU_BOOT_DEV_STS0_PKT_PI_ACK_EN (1 << CPU_BOOT_DEV_STS_PKT_PI_ACK_EN) +#define CPU_BOOT_DEV_STS0_FW_LD_COM_EN (1 << CPU_BOOT_DEV_STS_FW_LD_COM_EN) +#define CPU_BOOT_DEV_STS0_FW_IATU_CONF_EN (1 << CPU_BOOT_DEV_STS_FW_IATU_CONF_EN) +#define CPU_BOOT_DEV_STS0_FW_NIC_MAC_EN (1 << CPU_BOOT_DEV_STS_FW_NIC_MAC_EN) +#define CPU_BOOT_DEV_STS0_DYN_PLL_EN (1 << CPU_BOOT_DEV_STS_DYN_PLL_EN) +#define CPU_BOOT_DEV_STS0_GIC_PRIVILEGED_EN (1 << CPU_BOOT_DEV_STS_GIC_PRIVILEGED_EN) +#define CPU_BOOT_DEV_STS0_EQ_INDEX_EN (1 << CPU_BOOT_DEV_STS_EQ_INDEX_EN) +#define CPU_BOOT_DEV_STS0_MULTI_IRQ_POLL_EN (1 << CPU_BOOT_DEV_STS_MULTI_IRQ_POLL_EN) +#define CPU_BOOT_DEV_STS0_FW_NIC_STAT_XPCS91_EN (1 << CPU_BOOT_DEV_STS_FW_NIC_STAT_XPCS91_EN) +#define CPU_BOOT_DEV_STS0_FW_NIC_STAT_EXT_EN (1 << CPU_BOOT_DEV_STS_FW_NIC_STAT_EXT_EN) +#define CPU_BOOT_DEV_STS0_IS_IDLE_CHECK_EN (1 << CPU_BOOT_DEV_STS_IS_IDLE_CHECK_EN) +#define CPU_BOOT_DEV_STS0_MAP_HWMON_EN (1 << CPU_BOOT_DEV_STS_MAP_HWMON_EN) +#define CPU_BOOT_DEV_STS0_ENABLED (1 << CPU_BOOT_DEV_STS_ENABLED) +#define CPU_BOOT_DEV_STS1_ENABLED (1 << CPU_BOOT_DEV_STS_ENABLED) enum cpu_boot_status { CPU_BOOT_STATUS_NA = 0, /* Default value after reset of chip */ @@ -411,6 +452,8 @@ struct cpu_dyn_regs { enum comms_msg_type { HL_COMMS_DESC_TYPE = 0, HL_COMMS_RESET_CAUSE_TYPE = 1, + HL_COMMS_FW_CFG_SKIP_TYPE = 2, + HL_COMMS_BINNING_CONF_TYPE = 3, }; /* TODO: remove this struct after the code is updated to use message */ @@ -470,6 +513,9 @@ struct lkd_fw_comms_msg { struct { __u8 reset_cause; }; + struct { + __u8 fw_cfg_skip; /* 1 - skip, 0 - don't skip */ + }; }; }; @@ -513,8 +559,6 @@ struct lkd_fw_comms_msg { * COMMS_SKIP_BMC Perform actions required for BMC-less servers. * Do not wait for BMC response. * - * COMMS_LOW_PLL_OPP Initialize PLLs for low OPP. - * * COMMS_PREP_DESC_ELBI Same as COMMS_PREP_DESC only that the memory * space is allocated in a ELBI access only * address range. @@ -530,7 +574,6 @@ enum comms_cmd { COMMS_RST_DEV = 6, COMMS_GOTO_WFE = 7, COMMS_SKIP_BMC = 8, - COMMS_LOW_PLL_OPP = 9, COMMS_PREP_DESC_ELBI = 10, COMMS_INVLD_LAST }; diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h b/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h index 34ca4fe50d91..2dba02757d37 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h +++ b/drivers/misc/habanalabs/include/gaudi/gaudi_fw_if.h @@ -8,8 +8,6 @@ #ifndef GAUDI_FW_IF_H #define GAUDI_FW_IF_H -#include - #define GAUDI_EVENT_QUEUE_MSI_IDX 8 #define GAUDI_NIC_PORT1_MSI_IDX 10 #define GAUDI_NIC_PORT3_MSI_IDX 12 @@ -78,13 +76,13 @@ struct gaudi_nic_status { __u32 high_ber_cnt; }; -struct gaudi_flops_2_data { +struct gaudi_cold_rst_data { union { struct { - __u32 spsram_init_done : 1; - __u32 reserved : 31; + u32 spsram_init_done : 1; + u32 reserved : 31; }; - __u32 data; + __le32 data; }; }; diff --git a/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h b/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h index b9bd5a7f71eb..92f25c2ae083 100644 --- a/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h +++ b/drivers/misc/habanalabs/include/gaudi/gaudi_reg_map.h @@ -33,6 +33,7 @@ #define mmRDWR_TEST mmPSOC_GLOBAL_CONF_SCRATCHPAD_30 #define mmBTL_ID mmPSOC_GLOBAL_CONF_SCRATCHPAD_31 #define mmPREBOOT_PCIE_EN mmPSOC_GLOBAL_CONF_COLD_RST_FLOPS_1 +#define mmCOLD_RST_DATA mmPSOC_GLOBAL_CONF_COLD_RST_FLOPS_2 #define mmUPD_PENDING_STS mmPSOC_GLOBAL_CONF_COLD_RST_FLOPS_3 #endif /* GAUDI_REG_MAP_H_ */ -- cgit v1.2.3 From 1d16a46b1a83ea44a73964fe28492656c70da831 Mon Sep 17 00:00:00 2001 From: Oded Gabbay Date: Tue, 5 Oct 2021 17:29:47 +0300 Subject: habanalabs: use only u32 In the kernel it is common to use u32 and not uint32_t. Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/gaudi/gaudi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/gaudi/gaudi.c b/drivers/misc/habanalabs/gaudi/gaudi.c index 70a668951ec4..654f7959c5ad 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi.c +++ b/drivers/misc/habanalabs/gaudi/gaudi.c @@ -2616,7 +2616,7 @@ static void gaudi_init_e2e(struct hl_device *hdev) static void gaudi_init_hbm_cred(struct hl_device *hdev) { - uint32_t hbm0_wr, hbm1_wr, hbm0_rd, hbm1_rd; + u32 hbm0_wr, hbm1_wr, hbm0_rd, hbm1_rd; if (hdev->asic_prop.fw_security_enabled) return; -- cgit v1.2.3 From ea6eb91c09cd4f2f92ba28ba277d2ecf63cdc237 Mon Sep 17 00:00:00 2001 From: Dani Liberman Date: Sun, 3 Oct 2021 15:57:44 +0300 Subject: habanalabs: fix race condition in multi CS completion Race condition occurs when CS fence completes and multi CS did not completed yet, while waiting for multi CS ends and returns indication to user that the CS completed. Next wait for multi CS may be triggered by previous multi CS completion without any current CS completed, causing an error. Example scenario : 1. User do multi CS wait for CSs 1 and 2 on master QID 0 2. CS 1 and 2 reached the "cs release" code. The thread of CS 1 completed both the CS and multi CS handling but the completion thread of CS 2 completed the CS but still did not executed complete_multi_cs (note that in CS completion the sequence is to first do complete all for the CS and then another complete all to signal the multi_cs) 3. User received indication that CS 1 and 2 completed (since we check the CS fence and both indicated as completed) and immediately waits on CS 3 and 4, also on master QID 0. 4. Completion thread of CS2 executed complete_multi_cs before completion of CS 3 and 4 and so will trigger the multi CS wait of CSs 3 and 4 as they wait on master QID 0. This will trigger multi CS completion although none of its current CS has been completed. Fixed by adding multi CS complete handling indication for each CS. CS will be marked to the user as completed only if its fence completed and multi CS handling is done. Signed-off-by: Dani Liberman Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/command_submission.c | 20 +++++++++++++++++++- drivers/misc/habanalabs/common/habanalabs.h | 4 ++++ 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index 4bc24852a283..8e4dc1441fff 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -143,6 +143,7 @@ static void hl_fence_init(struct hl_fence *fence, u64 sequence) fence->cs_sequence = sequence; fence->error = 0; fence->timestamp = ktime_set(0, 0); + fence->mcs_handling_done = false; init_completion(&fence->completion); } @@ -535,10 +536,21 @@ static void complete_multi_cs(struct hl_device *hdev, struct hl_cs *cs) mcs_compl->timestamp = ktime_to_ns(fence->timestamp); complete_all(&mcs_compl->completion); + + /* + * Setting mcs_handling_done inside the lock ensures + * at least one fence have mcs_handling_done set to + * true before wait for mcs finish. This ensures at + * least one CS will be set as completed when polling + * mcs fences. + */ + fence->mcs_handling_done = true; } spin_unlock(&mcs_compl->lock); } + /* In case CS completed without mcs completion initialized */ + fence->mcs_handling_done = true; } static inline void cs_release_sob_reset_handler(struct hl_device *hdev, @@ -2372,7 +2384,13 @@ static int hl_cs_poll_fences(struct multi_cs_data *mcs_data) mcs_data->stream_master_qid_map |= fence->stream_master_qid_map; - if (status == CS_WAIT_STATUS_BUSY) + /* + * Using mcs_handling_done to avoid possibility of mcs_data + * returns to user indicating CS completed before it finished + * all of its mcs handling, to avoid race the next time the + * user waits for mcs. + */ + if (status == CS_WAIT_STATUS_BUSY || !fence->mcs_handling_done) continue; mcs_data->completion_bitmap |= BIT(i); diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index a06135155b57..48f0e52cd5be 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -610,6 +610,9 @@ struct asic_fixed_properties { * @error: mark this fence with error * @timestamp: timestamp upon completion * @take_timestamp: timestamp shall be taken upon completion + * @mcs_handling_done: indicates that corresponding command submission has + * finished msc handling, this does not mean it was part + * of the mcs */ struct hl_fence { struct completion completion; @@ -619,6 +622,7 @@ struct hl_fence { int error; ktime_t timestamp; u8 take_timestamp; + u8 mcs_handling_done; }; /** -- cgit v1.2.3 From 81f8582ec404b2ab3ec1d412e33703e014fc3121 Mon Sep 17 00:00:00 2001 From: Dani Liberman Date: Wed, 6 Oct 2021 09:36:19 +0300 Subject: habanalabs: fix NULL pointer dereference When polling fences for multi CS, it is possible that fence is no longer exists (its corresponding CS completed and the fence was deleted) but we still accessing its parameters, causing NULL pointer dereference. Fixed by checking if fence exits before accessing its parameters. Signed-off-by: Dani Liberman Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/command_submission.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index 8e4dc1441fff..a3358cc3c877 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -2382,7 +2382,15 @@ static int hl_cs_poll_fences(struct multi_cs_data *mcs_data) break; } - mcs_data->stream_master_qid_map |= fence->stream_master_qid_map; + /* + * It is possible to get an old sequence numbers from user + * which related to already completed CSs and their fences + * already gone. In this case, no need to consider its QID for + * mcs completion. + */ + if (fence) + mcs_data->stream_master_qid_map |= + fence->stream_master_qid_map; /* * Using mcs_handling_done to avoid possibility of mcs_data @@ -2390,7 +2398,8 @@ static int hl_cs_poll_fences(struct multi_cs_data *mcs_data) * all of its mcs handling, to avoid race the next time the * user waits for mcs. */ - if (status == CS_WAIT_STATUS_BUSY || !fence->mcs_handling_done) + if (status == CS_WAIT_STATUS_BUSY || + (fence && !fence->mcs_handling_done)) continue; mcs_data->completion_bitmap |= BIT(i); -- cgit v1.2.3 From db1a8dd916aac986871f6b873a3aefad906f383a Mon Sep 17 00:00:00 2001 From: Tomer Tayar Date: Tue, 15 Jun 2021 10:55:43 +0300 Subject: habanalabs: add support for dma-buf exporter Implement the calls to the dma-buf kernel api to create a dma-buf object backed by FD. We block the option to mmap the DMA-BUF object because we don't support DIRECT_IO and implicit P2P. We only implement support for explicit P2P through importing the FD of the DMA-BUF. In the export phase, we provide to the DMA-BUF object an array of pages that represent the device's memory area. During the map callback, we convert the array of pages into an SGT. We split/merge the pages according to the dma max segment size of the importer. To get the DMA address of the PCI bar, we use the dma_map_resources() kernel API, because our device memory is not backed by page struct and this API doesn't need page struct to map the physical address to a DMA address. We set the orig_nents member of the SGT to be 0, to indicate to other drivers that we don't support CPU mappings. Note that in Habanalabs's ASICs, the device memory is pinned and immutable. Therefore, there is no need for dynamic mappings and pinning callbacks. Also note that in GAUDI we don't have an MMU towards the device memory and the user works on physical addresses. Therefore, the user doesn't pass through the kernel driver to allocate memory there. As a result, only for GAUDI we receive from the user a device memory physical address (instead of a handle) and a size. We check the p2p distance using pci_p2pdma_distance_many() and refusing to map dmabuf in case the distance doesn't allow p2p. Signed-off-by: Tomer Tayar Reviewed-by: Oded Gabbay Reviewed-by: Gal Pressman Reviewed-by: Greg Kroah-Hartman Acked-by: Daniel Vetter Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/Kconfig | 1 + drivers/misc/habanalabs/common/habanalabs.h | 22 ++ drivers/misc/habanalabs/common/memory.c | 513 +++++++++++++++++++++++++++- drivers/misc/habanalabs/gaudi/gaudi.c | 1 + drivers/misc/habanalabs/goya/goya.c | 1 + 5 files changed, 535 insertions(+), 3 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/Kconfig b/drivers/misc/habanalabs/Kconfig index 293d79811372..c82d2e7b2035 100644 --- a/drivers/misc/habanalabs/Kconfig +++ b/drivers/misc/habanalabs/Kconfig @@ -8,6 +8,7 @@ config HABANA_AI depends on PCI && HAS_IOMEM select GENERIC_ALLOCATOR select HWMON + select DMA_SHARED_BUFFER help Enables PCIe card driver for Habana's AI Processors (AIP) that are designed to accelerate Deep Learning inference and training workloads. diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index 48f0e52cd5be..eb1ccb5d3ce3 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -26,6 +26,7 @@ #include #include #include +#include #define HL_NAME "habanalabs" @@ -1366,6 +1367,23 @@ struct hl_cs_counters_atomic { atomic64_t validation_drop_cnt; }; +/** + * struct hl_dmabuf_priv - a dma-buf private object. + * @dmabuf: pointer to dma-buf object. + * @ctx: pointer to the dma-buf owner's context. + * @phys_pg_pack: pointer to physical page pack if the dma-buf was exported for + * memory allocation handle. + * @device_address: physical address of the device's memory. Relevant only + * if phys_pg_pack is NULL (dma-buf was exported from address). + * The total size can be taken from the dmabuf object. + */ +struct hl_dmabuf_priv { + struct dma_buf *dmabuf; + struct hl_ctx *ctx; + struct hl_vm_phys_pg_pack *phys_pg_pack; + uint64_t device_address; +}; + /** * struct hl_ctx - user/kernel context. * @mem_hash: holds mapping from virtual address to virtual memory area @@ -1676,6 +1694,7 @@ struct hl_vm_hw_block_list_node { * @npages: num physical pages in the pack. * @total_size: total size of all the pages in this list. * @mapping_cnt: number of shared mappings. + * @exporting_cnt: number of dma-buf exporting. * @asid: the context related to this list. * @page_size: size of each page in the pack. * @flags: HL_MEM_* flags related to this list. @@ -1690,6 +1709,7 @@ struct hl_vm_phys_pg_pack { u64 npages; u64 total_size; atomic_t mapping_cnt; + u32 exporting_cnt; u32 asid; u32 page_size; u32 flags; @@ -2410,6 +2430,7 @@ struct multi_cs_data { * the error will be ignored by the driver during * device initialization. Mainly used to debug and * workaround firmware bugs + * @dram_pci_bar_start: start bus address of PCIe bar towards DRAM. * @last_successful_open_jif: timestamp (jiffies) of the last successful * device open. * @last_open_session_duration_jif: duration (jiffies) of the last device open @@ -2559,6 +2580,7 @@ struct hl_device { u64 max_power; u64 clock_gating_mask; u64 boot_error_status_mask; + u64 dram_pci_bar_start; u64 last_successful_open_jif; u64 last_open_session_duration_jif; u64 open_counter; diff --git a/drivers/misc/habanalabs/common/memory.c b/drivers/misc/habanalabs/common/memory.c index 33986933aa9e..504973330e2e 100644 --- a/drivers/misc/habanalabs/common/memory.c +++ b/drivers/misc/habanalabs/common/memory.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright 2016-2019 HabanaLabs, Ltd. + * Copyright 2016-2021 HabanaLabs, Ltd. * All Rights Reserved. */ @@ -11,6 +11,7 @@ #include #include +#include #define HL_MMU_DEBUG 0 @@ -347,6 +348,12 @@ static int free_device_memory(struct hl_ctx *ctx, struct hl_mem_in *args) return -EINVAL; } + if (phys_pg_pack->exporting_cnt) { + dev_dbg(hdev->dev, "handle %u is exported, cannot free\n", handle); + spin_unlock(&vm->idr_lock); + return -EINVAL; + } + /* * must remove from idr before the freeing of the physical * pages as the refcount of the pool is also the trigger of the @@ -1487,13 +1494,487 @@ int hl_hw_block_mmap(struct hl_fpriv *hpriv, struct vm_area_struct *vma) return 0; } +static int set_dma_sg(struct scatterlist *sg, u64 bar_address, u64 chunk_size, + struct device *dev, enum dma_data_direction dir) +{ + dma_addr_t addr; + int rc; + + addr = dma_map_resource(dev, bar_address, chunk_size, dir, + DMA_ATTR_SKIP_CPU_SYNC); + rc = dma_mapping_error(dev, addr); + if (rc) + return rc; + + sg_set_page(sg, NULL, chunk_size, 0); + sg_dma_address(sg) = addr; + sg_dma_len(sg) = chunk_size; + + return 0; +} + +static struct sg_table *alloc_sgt_from_device_pages(struct hl_device *hdev, u64 *pages, u64 npages, + u64 page_size, struct device *dev, + enum dma_data_direction dir) +{ + u64 chunk_size, bar_address, dma_max_seg_size; + struct asic_fixed_properties *prop; + int rc, i, j, nents, cur_page; + struct scatterlist *sg; + struct sg_table *sgt; + + prop = &hdev->asic_prop; + + dma_max_seg_size = dma_get_max_seg_size(dev); + + /* We would like to align the max segment size to PAGE_SIZE, so the + * SGL will contain aligned addresses that can be easily mapped to + * an MMU + */ + dma_max_seg_size = ALIGN_DOWN(dma_max_seg_size, PAGE_SIZE); + if (dma_max_seg_size < PAGE_SIZE) { + dev_err_ratelimited(hdev->dev, + "dma_max_seg_size %llu can't be smaller than PAGE_SIZE\n", + dma_max_seg_size); + return ERR_PTR(-EINVAL); + } + + sgt = kzalloc(sizeof(*sgt), GFP_KERNEL); + if (!sgt) + return ERR_PTR(-ENOMEM); + + /* If the size of each page is larger than the dma max segment size, + * then we can't combine pages and the number of entries in the SGL + * will just be the + * * + */ + if (page_size > dma_max_seg_size) + nents = npages * DIV_ROUND_UP_ULL(page_size, dma_max_seg_size); + else + /* Get number of non-contiguous chunks */ + for (i = 1, nents = 1, chunk_size = page_size ; i < npages ; i++) { + if (pages[i - 1] + page_size != pages[i] || + chunk_size + page_size > dma_max_seg_size) { + nents++; + chunk_size = page_size; + continue; + } + + chunk_size += page_size; + } + + rc = sg_alloc_table(sgt, nents, GFP_KERNEL | __GFP_ZERO); + if (rc) + goto error_free; + + cur_page = 0; + + if (page_size > dma_max_seg_size) { + u64 size_left, cur_device_address = 0; + + size_left = page_size; + + /* Need to split each page into the number of chunks of + * dma_max_seg_size + */ + for_each_sgtable_dma_sg(sgt, sg, i) { + if (size_left == page_size) + cur_device_address = + pages[cur_page] - prop->dram_base_address; + else + cur_device_address += dma_max_seg_size; + + chunk_size = min(size_left, dma_max_seg_size); + + bar_address = hdev->dram_pci_bar_start + cur_device_address; + + rc = set_dma_sg(sg, bar_address, chunk_size, dev, dir); + if (rc) + goto error_unmap; + + if (size_left > dma_max_seg_size) { + size_left -= dma_max_seg_size; + } else { + cur_page++; + size_left = page_size; + } + } + } else { + /* Merge pages and put them into the scatterlist */ + for_each_sgtable_dma_sg(sgt, sg, i) { + chunk_size = page_size; + for (j = cur_page + 1 ; j < npages ; j++) { + if (pages[j - 1] + page_size != pages[j] || + chunk_size + page_size > dma_max_seg_size) + break; + + chunk_size += page_size; + } + + bar_address = hdev->dram_pci_bar_start + + (pages[cur_page] - prop->dram_base_address); + + rc = set_dma_sg(sg, bar_address, chunk_size, dev, dir); + if (rc) + goto error_unmap; + + cur_page = j; + } + } + + /* Because we are not going to include a CPU list we want to have some + * chance that other users will detect this by setting the orig_nents + * to 0 and using only nents (length of DMA list) when going over the + * sgl + */ + sgt->orig_nents = 0; + + return sgt; + +error_unmap: + for_each_sgtable_dma_sg(sgt, sg, i) { + if (!sg_dma_len(sg)) + continue; + + dma_unmap_resource(dev, sg_dma_address(sg), + sg_dma_len(sg), dir, + DMA_ATTR_SKIP_CPU_SYNC); + } + + sg_free_table(sgt); + +error_free: + kfree(sgt); + return ERR_PTR(rc); +} + +static int hl_dmabuf_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct hl_dmabuf_priv *hl_dmabuf; + struct hl_device *hdev; + int rc; + + hl_dmabuf = dmabuf->priv; + hdev = hl_dmabuf->ctx->hdev; + + rc = pci_p2pdma_distance_many(hdev->pdev, &attachment->dev, 1, true); + + if (rc < 0) + attachment->peer2peer = false; + return 0; +} + +static struct sg_table *hl_map_dmabuf(struct dma_buf_attachment *attachment, + enum dma_data_direction dir) +{ + struct dma_buf *dma_buf = attachment->dmabuf; + struct hl_vm_phys_pg_pack *phys_pg_pack; + struct hl_dmabuf_priv *hl_dmabuf; + struct hl_device *hdev; + struct sg_table *sgt; + + hl_dmabuf = dma_buf->priv; + hdev = hl_dmabuf->ctx->hdev; + phys_pg_pack = hl_dmabuf->phys_pg_pack; + + if (!attachment->peer2peer) { + dev_dbg(hdev->dev, "Failed to map dmabuf because p2p is disabled\n"); + return ERR_PTR(-EPERM); + } + + if (phys_pg_pack) + sgt = alloc_sgt_from_device_pages(hdev, + phys_pg_pack->pages, + phys_pg_pack->npages, + phys_pg_pack->page_size, + attachment->dev, + dir); + else + sgt = alloc_sgt_from_device_pages(hdev, + &hl_dmabuf->device_address, + 1, + hl_dmabuf->dmabuf->size, + attachment->dev, + dir); + + if (IS_ERR(sgt)) + dev_err(hdev->dev, "failed (%ld) to initialize sgt for dmabuf\n", PTR_ERR(sgt)); + + return sgt; +} + +static void hl_unmap_dmabuf(struct dma_buf_attachment *attachment, + struct sg_table *sgt, + enum dma_data_direction dir) +{ + struct scatterlist *sg; + int i; + + /* The memory behind the dma-buf has *always* resided on the device itself, i.e. it lives + * only in the 'device' domain (after all, it maps a PCI bar address which points to the + * device memory). + * + * Therefore, it was never in the 'CPU' domain and hence, there is no need to perform + * a sync of the memory to the CPU's cache, as it never resided inside that cache. + */ + for_each_sgtable_dma_sg(sgt, sg, i) + dma_unmap_resource(attachment->dev, sg_dma_address(sg), + sg_dma_len(sg), dir, + DMA_ATTR_SKIP_CPU_SYNC); + + /* Need to restore orig_nents because sg_free_table use that field */ + sgt->orig_nents = sgt->nents; + sg_free_table(sgt); + kfree(sgt); +} + +static void hl_release_dmabuf(struct dma_buf *dmabuf) +{ + struct hl_dmabuf_priv *hl_dmabuf = dmabuf->priv; + struct hl_ctx *ctx = hl_dmabuf->ctx; + struct hl_device *hdev = ctx->hdev; + struct hl_vm *vm = &hdev->vm; + + if (hl_dmabuf->phys_pg_pack) { + spin_lock(&vm->idr_lock); + hl_dmabuf->phys_pg_pack->exporting_cnt--; + spin_unlock(&vm->idr_lock); + } + + hl_ctx_put(hl_dmabuf->ctx); + + kfree(hl_dmabuf); +} + +static const struct dma_buf_ops habanalabs_dmabuf_ops = { + .attach = hl_dmabuf_attach, + .map_dma_buf = hl_map_dmabuf, + .unmap_dma_buf = hl_unmap_dmabuf, + .release = hl_release_dmabuf, +}; + +static int export_dmabuf_common(struct hl_ctx *ctx, + struct hl_dmabuf_priv *hl_dmabuf, + u64 total_size, int flags, int *dmabuf_fd) +{ + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct hl_device *hdev = ctx->hdev; + int rc, fd; + + exp_info.ops = &habanalabs_dmabuf_ops; + exp_info.size = total_size; + exp_info.flags = flags; + exp_info.priv = hl_dmabuf; + + hl_dmabuf->dmabuf = dma_buf_export(&exp_info); + if (IS_ERR(hl_dmabuf->dmabuf)) { + dev_err(hdev->dev, "failed to export dma-buf\n"); + return PTR_ERR(hl_dmabuf->dmabuf); + } + + fd = dma_buf_fd(hl_dmabuf->dmabuf, flags); + if (fd < 0) { + dev_err(hdev->dev, "failed to get a file descriptor for a dma-buf\n"); + rc = fd; + goto err_dma_buf_put; + } + + hl_dmabuf->ctx = ctx; + hl_ctx_get(hdev, hl_dmabuf->ctx); + + *dmabuf_fd = fd; + + return 0; + +err_dma_buf_put: + dma_buf_put(hl_dmabuf->dmabuf); + return rc; +} + +/** + * export_dmabuf_from_addr() - export a dma-buf object for the given memory + * address and size. + * @ctx: pointer to the context structure. + * @device_addr: device memory physical address. + * @size: size of device memory. + * @flags: DMA-BUF file/FD flags. + * @dmabuf_fd: pointer to result FD that represents the dma-buf object. + * + * Create and export a dma-buf object for an existing memory allocation inside + * the device memory, and return a FD which is associated with the dma-buf + * object. + * + * Return: 0 on success, non-zero for failure. + */ +static int export_dmabuf_from_addr(struct hl_ctx *ctx, u64 device_addr, + u64 size, int flags, int *dmabuf_fd) +{ + struct hl_dmabuf_priv *hl_dmabuf; + struct hl_device *hdev = ctx->hdev; + struct asic_fixed_properties *prop; + u64 bar_address; + int rc; + + prop = &hdev->asic_prop; + + if (!IS_ALIGNED(device_addr, PAGE_SIZE)) { + dev_dbg(hdev->dev, + "exported device memory address 0x%llx should be aligned to 0x%lx\n", + device_addr, PAGE_SIZE); + return -EINVAL; + } + + if (size < PAGE_SIZE) { + dev_dbg(hdev->dev, + "exported device memory size %llu should be equal to or greater than %lu\n", + size, PAGE_SIZE); + return -EINVAL; + } + + if (device_addr < prop->dram_user_base_address || + device_addr + size > prop->dram_end_address || + device_addr + size < device_addr) { + dev_dbg(hdev->dev, + "DRAM memory range 0x%llx (+0x%llx) is outside of DRAM boundaries\n", + device_addr, size); + return -EINVAL; + } + + bar_address = hdev->dram_pci_bar_start + + (device_addr - prop->dram_base_address); + + if (bar_address + size > + hdev->dram_pci_bar_start + prop->dram_pci_bar_size || + bar_address + size < bar_address) { + dev_dbg(hdev->dev, + "DRAM memory range 0x%llx (+0x%llx) is outside of PCI BAR boundaries\n", + device_addr, size); + return -EINVAL; + } + + hl_dmabuf = kzalloc(sizeof(*hl_dmabuf), GFP_KERNEL); + if (!hl_dmabuf) + return -ENOMEM; + + hl_dmabuf->device_address = device_addr; + + rc = export_dmabuf_common(ctx, hl_dmabuf, size, flags, dmabuf_fd); + if (rc) + goto err_free_dmabuf_wrapper; + + return 0; + +err_free_dmabuf_wrapper: + kfree(hl_dmabuf); + return rc; +} + +/** + * export_dmabuf_from_handle() - export a dma-buf object for the given memory + * handle. + * @ctx: pointer to the context structure. + * @handle: device memory allocation handle. + * @flags: DMA-BUF file/FD flags. + * @dmabuf_fd: pointer to result FD that represents the dma-buf object. + * + * Create and export a dma-buf object for an existing memory allocation inside + * the device memory, and return a FD which is associated with the dma-buf + * object. + * + * Return: 0 on success, non-zero for failure. + */ +static int export_dmabuf_from_handle(struct hl_ctx *ctx, u64 handle, int flags, + int *dmabuf_fd) +{ + struct hl_vm_phys_pg_pack *phys_pg_pack; + struct hl_dmabuf_priv *hl_dmabuf; + struct hl_device *hdev = ctx->hdev; + struct asic_fixed_properties *prop; + struct hl_vm *vm = &hdev->vm; + u64 bar_address; + int rc, i; + + prop = &hdev->asic_prop; + + if (upper_32_bits(handle)) { + dev_dbg(hdev->dev, "no match for handle 0x%llx\n", handle); + return -EINVAL; + } + + spin_lock(&vm->idr_lock); + + phys_pg_pack = idr_find(&vm->phys_pg_pack_handles, (u32) handle); + if (!phys_pg_pack) { + spin_unlock(&vm->idr_lock); + dev_dbg(hdev->dev, "no match for handle 0x%x\n", (u32) handle); + return -EINVAL; + } + + /* increment now to avoid freeing device memory while exporting */ + phys_pg_pack->exporting_cnt++; + + spin_unlock(&vm->idr_lock); + + if (phys_pg_pack->vm_type != VM_TYPE_PHYS_PACK) { + dev_dbg(hdev->dev, "handle 0x%llx does not represent DRAM memory\n", handle); + rc = -EINVAL; + goto err_dec_exporting_cnt; + } + + for (i = 0 ; i < phys_pg_pack->npages ; i++) { + + bar_address = hdev->dram_pci_bar_start + + (phys_pg_pack->pages[i] - + prop->dram_base_address); + + if (bar_address + phys_pg_pack->page_size > + hdev->dram_pci_bar_start + prop->dram_pci_bar_size || + bar_address + phys_pg_pack->page_size < bar_address) { + + dev_dbg(hdev->dev, + "DRAM memory range 0x%llx (+0x%x) is outside of PCI BAR boundaries\n", + phys_pg_pack->pages[i], + phys_pg_pack->page_size); + + rc = -EINVAL; + goto err_dec_exporting_cnt; + } + } + + hl_dmabuf = kzalloc(sizeof(*hl_dmabuf), GFP_KERNEL); + if (!hl_dmabuf) { + rc = -ENOMEM; + goto err_dec_exporting_cnt; + } + + hl_dmabuf->phys_pg_pack = phys_pg_pack; + + rc = export_dmabuf_common(ctx, hl_dmabuf, phys_pg_pack->total_size, + flags, dmabuf_fd); + if (rc) + goto err_free_dmabuf_wrapper; + + return 0; + +err_free_dmabuf_wrapper: + kfree(hl_dmabuf); + +err_dec_exporting_cnt: + spin_lock(&vm->idr_lock); + phys_pg_pack->exporting_cnt--; + spin_unlock(&vm->idr_lock); + + return rc; +} + static int mem_ioctl_no_mmu(struct hl_fpriv *hpriv, union hl_mem_args *args) { struct hl_device *hdev = hpriv->hdev; struct hl_ctx *ctx = hpriv->ctx; u64 block_handle, device_addr = 0; u32 handle = 0, block_size; - int rc; + int rc, dmabuf_fd = -EBADF; switch (args->in.op) { case HL_MEM_OP_ALLOC: @@ -1542,6 +2023,16 @@ static int mem_ioctl_no_mmu(struct hl_fpriv *hpriv, union hl_mem_args *args) args->out.block_size = block_size; break; + case HL_MEM_OP_EXPORT_DMABUF_FD: + rc = export_dmabuf_from_addr(ctx, + args->in.export_dmabuf_fd.handle, + args->in.export_dmabuf_fd.mem_size, + args->in.flags, + &dmabuf_fd); + memset(args, 0, sizeof(*args)); + args->out.fd = dmabuf_fd; + break; + default: dev_err(hdev->dev, "Unknown opcode for memory IOCTL\n"); rc = -ENOTTY; @@ -1560,7 +2051,7 @@ int hl_mem_ioctl(struct hl_fpriv *hpriv, void *data) struct hl_ctx *ctx = hpriv->ctx; u64 block_handle, device_addr = 0; u32 handle = 0, block_size; - int rc; + int rc, dmabuf_fd = -EBADF; if (!hl_device_operational(hdev, &status)) { dev_warn_ratelimited(hdev->dev, @@ -1651,6 +2142,22 @@ int hl_mem_ioctl(struct hl_fpriv *hpriv, void *data) args->out.block_size = block_size; break; + case HL_MEM_OP_EXPORT_DMABUF_FD: + if (hdev->asic_prop.dram_supports_virtual_memory) + rc = export_dmabuf_from_handle(ctx, + args->in.export_dmabuf_fd.handle, + args->in.flags, + &dmabuf_fd); + else + rc = export_dmabuf_from_addr(ctx, + args->in.export_dmabuf_fd.handle, + args->in.export_dmabuf_fd.mem_size, + args->in.flags, + &dmabuf_fd); + memset(args, 0, sizeof(*args)); + args->out.fd = dmabuf_fd; + break; + default: dev_err(hdev->dev, "Unknown opcode for memory IOCTL\n"); rc = -ENOTTY; diff --git a/drivers/misc/habanalabs/gaudi/gaudi.c b/drivers/misc/habanalabs/gaudi/gaudi.c index 654f7959c5ad..7a5bcc81f653 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi.c +++ b/drivers/misc/habanalabs/gaudi/gaudi.c @@ -795,6 +795,7 @@ static int gaudi_early_init(struct hl_device *hdev) } prop->dram_pci_bar_size = pci_resource_len(pdev, HBM_BAR_ID); + hdev->dram_pci_bar_start = pci_resource_start(pdev, HBM_BAR_ID); /* If FW security is enabled at this point it means no access to ELBI */ if (hdev->asic_prop.fw_security_enabled) { diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index 78cf35879680..ad00789348d9 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -622,6 +622,7 @@ static int goya_early_init(struct hl_device *hdev) } prop->dram_pci_bar_size = pci_resource_len(pdev, DDR_BAR_ID); + hdev->dram_pci_bar_start = pci_resource_start(pdev, DDR_BAR_ID); /* If FW security is enabled at this point it means no access to ELBI */ if (hdev->asic_prop.fw_security_enabled) { -- cgit v1.2.3 From f6fb34390cd047543ff00b34b8ad910bf76c8eb3 Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Mon, 11 Oct 2021 17:14:43 +0200 Subject: habanalabs: select CRC32 Fix the following build/link error by adding a dependency on the CRC32 routines: ld: drivers/misc/habanalabs/common/firmware_if.o: in function `hl_fw_dynamic_request_descriptor': firmware_if.c:(.text.unlikely+0xc89): undefined reference to `crc32_le' Fixes: 8a43c83fec12 ("habanalabs: load boot fit to device") Signed-off-by: Vegard Nossum Acked-by: Arnd Bergmann Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/Kconfig b/drivers/misc/habanalabs/Kconfig index c82d2e7b2035..861c81006c6d 100644 --- a/drivers/misc/habanalabs/Kconfig +++ b/drivers/misc/habanalabs/Kconfig @@ -9,6 +9,7 @@ config HABANA_AI select GENERIC_ALLOCATOR select HWMON select DMA_SHARED_BUFFER + select CRC32 help Enables PCIe card driver for Habana's AI Processors (AIP) that are designed to accelerate Deep Learning inference and training workloads. -- cgit v1.2.3 From 024b7b1d6dcd1960e9b669e981968ca4b6bf80cb Mon Sep 17 00:00:00 2001 From: Rajaravi Krishna Katta Date: Fri, 3 Sep 2021 08:01:30 +0300 Subject: habanalabs: Unify frequency set/get functionality Make the frequency set/get functionality common to all ASICs. This makes more code reusable when adding support for newer ASICs. Signed-off-by: Rajaravi Krishna Katta Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/Makefile | 2 +- drivers/misc/habanalabs/common/habanalabs.h | 10 +++ drivers/misc/habanalabs/common/hwmgr.c | 117 +++++++++++++++++++++++++++ drivers/misc/habanalabs/gaudi/Makefile | 2 +- drivers/misc/habanalabs/gaudi/gaudi.c | 11 +-- drivers/misc/habanalabs/gaudi/gaudiP.h | 4 - drivers/misc/habanalabs/gaudi/gaudi_hwmgr.c | 121 ---------------------------- drivers/misc/habanalabs/goya/goya.c | 4 +- drivers/misc/habanalabs/goya/goyaP.h | 1 - drivers/misc/habanalabs/goya/goya_hwmgr.c | 31 ------- 10 files changed, 138 insertions(+), 165 deletions(-) create mode 100644 drivers/misc/habanalabs/common/hwmgr.c delete mode 100644 drivers/misc/habanalabs/gaudi/gaudi_hwmgr.c (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/Makefile b/drivers/misc/habanalabs/common/Makefile index 6ebe3c7001ff..82c3824cad00 100644 --- a/drivers/misc/habanalabs/common/Makefile +++ b/drivers/misc/habanalabs/common/Makefile @@ -11,4 +11,4 @@ HL_COMMON_FILES := common/habanalabs_drv.o common/device.o common/context.o \ common/command_buffer.o common/hw_queue.o common/irq.o \ common/sysfs.o common/hwmon.o common/memory.o \ common/command_submission.o common/firmware_if.o \ - common/state_dump.o + common/state_dump.o common/hwmgr.o diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index eb1ccb5d3ce3..e7b3b121f24d 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -456,6 +456,9 @@ struct hl_hints_range { * for hints validity check. * device_dma_offset_for_host_access: the offset to add to host DMA addresses * to enable the device to access them. + * @max_freq_value: current max clk frequency. + * @clk_pll_index: clock PLL index that specify which PLL determines the clock + * we display to the user * @mmu_pgt_size: MMU page tables total size. * @mmu_pte_size: PTE size in MMU page tables. * @mmu_hop_table_size: MMU hop table size. @@ -552,6 +555,8 @@ struct asic_fixed_properties { u64 cb_va_end_addr; u64 dram_hints_align_mask; u64 device_dma_offset_for_host_access; + u64 max_freq_value; + u32 clk_pll_index; u32 mmu_pgt_size; u32 mmu_pte_size; u32 mmu_hop_table_size; @@ -3006,6 +3011,11 @@ int hl_set_power(struct hl_device *hdev, int sensor_index, u32 attr, long value); int hl_get_power(struct hl_device *hdev, int sensor_index, u32 attr, long *value); +int hl_get_clk_rate(struct hl_device *hdev, + u32 *cur_clk, u32 *max_clk); +void hl_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq); +void hl_add_device_attr(struct hl_device *hdev, + struct attribute_group *dev_attr_grp); void hw_sob_get(struct hl_hw_sob *hw_sob); void hw_sob_put(struct hl_hw_sob *hw_sob); void hl_encaps_handle_do_release(struct kref *ref); diff --git a/drivers/misc/habanalabs/common/hwmgr.c b/drivers/misc/habanalabs/common/hwmgr.c new file mode 100644 index 000000000000..5451019f143f --- /dev/null +++ b/drivers/misc/habanalabs/common/hwmgr.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* + * Copyright 2019-2021 HabanaLabs, Ltd. + * All Rights Reserved. + */ + +#include "habanalabs.h" + +void hl_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq) +{ + hl_set_frequency(hdev, hdev->asic_prop.clk_pll_index, + hdev->asic_prop.max_freq_value); +} + +int hl_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk) +{ + long value; + + if (!hl_device_operational(hdev, NULL)) + return -ENODEV; + + value = hl_get_frequency(hdev, hdev->asic_prop.clk_pll_index, false); + + if (value < 0) { + dev_err(hdev->dev, "Failed to retrieve device max clock %ld\n", + value); + return value; + } + + *max_clk = (value / 1000 / 1000); + + value = hl_get_frequency(hdev, hdev->asic_prop.clk_pll_index, true); + + if (value < 0) { + dev_err(hdev->dev, + "Failed to retrieve device current clock %ld\n", + value); + return value; + } + + *cur_clk = (value / 1000 / 1000); + + return 0; +} + +static ssize_t clk_max_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hl_device *hdev = dev_get_drvdata(dev); + long value; + + if (!hl_device_operational(hdev, NULL)) + return -ENODEV; + + value = hl_get_frequency(hdev, hdev->asic_prop.clk_pll_index, false); + + hdev->asic_prop.max_freq_value = value; + + return sprintf(buf, "%lu\n", (value / 1000 / 1000)); +} + +static ssize_t clk_max_freq_mhz_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct hl_device *hdev = dev_get_drvdata(dev); + int rc; + u64 value; + + if (!hl_device_operational(hdev, NULL)) { + count = -ENODEV; + goto fail; + } + + rc = kstrtoull(buf, 0, &value); + if (rc) { + count = -EINVAL; + goto fail; + } + + hdev->asic_prop.max_freq_value = value * 1000 * 1000; + + hl_set_frequency(hdev, hdev->asic_prop.clk_pll_index, + hdev->asic_prop.max_freq_value); + +fail: + return count; +} + +static ssize_t clk_cur_freq_mhz_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct hl_device *hdev = dev_get_drvdata(dev); + long value; + + if (!hl_device_operational(hdev, NULL)) + return -ENODEV; + + value = hl_get_frequency(hdev, hdev->asic_prop.clk_pll_index, true); + + return sprintf(buf, "%lu\n", (value / 1000 / 1000)); +} + +static DEVICE_ATTR_RW(clk_max_freq_mhz); +static DEVICE_ATTR_RO(clk_cur_freq_mhz); + +static struct attribute *hl_dev_attrs[] = { + &dev_attr_clk_max_freq_mhz.attr, + &dev_attr_clk_cur_freq_mhz.attr, + NULL, +}; + +void hl_add_device_attr(struct hl_device *hdev, + struct attribute_group *dev_attr_grp) +{ + dev_attr_grp->attrs = hl_dev_attrs; +} diff --git a/drivers/misc/habanalabs/gaudi/Makefile b/drivers/misc/habanalabs/gaudi/Makefile index c9f4703cff24..10577c33a816 100644 --- a/drivers/misc/habanalabs/gaudi/Makefile +++ b/drivers/misc/habanalabs/gaudi/Makefile @@ -1,3 +1,3 @@ # SPDX-License-Identifier: GPL-2.0-only -HL_GAUDI_FILES := gaudi/gaudi.o gaudi/gaudi_hwmgr.o gaudi/gaudi_security.o \ +HL_GAUDI_FILES := gaudi/gaudi.o gaudi/gaudi_security.o \ gaudi/gaudi_coresight.o diff --git a/drivers/misc/habanalabs/gaudi/gaudi.c b/drivers/misc/habanalabs/gaudi/gaudi.c index 7a5bcc81f653..825737dfe381 100644 --- a/drivers/misc/habanalabs/gaudi/gaudi.c +++ b/drivers/misc/habanalabs/gaudi/gaudi.c @@ -661,6 +661,9 @@ static int gaudi_set_fixed_properties(struct hl_device *hdev) prop->server_type = HL_SERVER_TYPE_UNKNOWN; + prop->clk_pll_index = HL_GAUDI_MME_PLL; + prop->max_freq_value = GAUDI_MAX_CLK_FREQ; + return 0; } @@ -1838,8 +1841,6 @@ static int gaudi_sw_init(struct hl_device *hdev) gaudi->cpucp_info_get = gaudi_cpucp_info_get; - gaudi->max_freq_value = GAUDI_MAX_CLK_FREQ; - hdev->asic_specific = gaudi; /* Create DMA pool for small allocations */ @@ -9444,9 +9445,9 @@ static const struct hl_asic_funcs gaudi_funcs = { .debugfs_read64 = gaudi_debugfs_read64, .debugfs_write64 = gaudi_debugfs_write64, .debugfs_read_dma = gaudi_debugfs_read_dma, - .add_device_attr = gaudi_add_device_attr, + .add_device_attr = hl_add_device_attr, .handle_eqe = gaudi_handle_eqe, - .set_pll_profile = gaudi_set_pll_profile, + .set_pll_profile = hl_set_pll_profile, .get_events_stat = gaudi_get_events_stat, .read_pte = gaudi_read_pte, .write_pte = gaudi_write_pte, @@ -9470,7 +9471,7 @@ static const struct hl_asic_funcs gaudi_funcs = { .halt_coresight = gaudi_halt_coresight, .ctx_init = gaudi_ctx_init, .ctx_fini = gaudi_ctx_fini, - .get_clk_rate = gaudi_get_clk_rate, + .get_clk_rate = hl_get_clk_rate, .get_queue_id_for_cq = gaudi_get_queue_id_for_cq, .load_firmware_to_device = gaudi_load_firmware_to_device, .load_boot_fit_to_device = gaudi_load_boot_fit_to_device, diff --git a/drivers/misc/habanalabs/gaudi/gaudiP.h b/drivers/misc/habanalabs/gaudi/gaudiP.h index bbbf1c343e75..f325e36a71e6 100644 --- a/drivers/misc/habanalabs/gaudi/gaudiP.h +++ b/drivers/misc/habanalabs/gaudi/gaudiP.h @@ -319,7 +319,6 @@ struct gaudi_internal_qman_info { * the actual number of internal queues because they are not in * consecutive order. * @hbm_bar_cur_addr: current address of HBM PCI bar. - * @max_freq_value: current max clk frequency. * @events: array that holds all event id's * @events_stat: array that holds histogram of all received events. * @events_stat_aggregate: same as events_stat but doesn't get cleared on reset @@ -345,7 +344,6 @@ struct gaudi_device { struct gaudi_collective_properties collective_props; u64 hbm_bar_cur_addr; - u64 max_freq_value; u32 events[GAUDI_EVENT_SIZE]; u32 events_stat[GAUDI_EVENT_SIZE]; @@ -359,10 +357,8 @@ void gaudi_init_security(struct hl_device *hdev); void gaudi_ack_protection_bits_errors(struct hl_device *hdev); void gaudi_add_device_attr(struct hl_device *hdev, struct attribute_group *dev_attr_grp); -void gaudi_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq); int gaudi_debug_coresight(struct hl_device *hdev, void *data); void gaudi_halt_coresight(struct hl_device *hdev); -int gaudi_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk); void gaudi_mmu_prepare_reg(struct hl_device *hdev, u64 reg, u32 asid); #endif /* GAUDIP_H_ */ diff --git a/drivers/misc/habanalabs/gaudi/gaudi_hwmgr.c b/drivers/misc/habanalabs/gaudi/gaudi_hwmgr.c deleted file mode 100644 index 9b60eadd4c35..000000000000 --- a/drivers/misc/habanalabs/gaudi/gaudi_hwmgr.c +++ /dev/null @@ -1,121 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 - -/* - * Copyright 2016-2018 HabanaLabs, Ltd. - * All Rights Reserved. - */ - -#include "gaudiP.h" -#include "../include/gaudi/gaudi_fw_if.h" - -void gaudi_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq) -{ - struct gaudi_device *gaudi = hdev->asic_specific; - - if (freq == PLL_LAST) - hl_set_frequency(hdev, HL_GAUDI_MME_PLL, gaudi->max_freq_value); -} - -int gaudi_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk) -{ - long value; - - if (!hl_device_operational(hdev, NULL)) - return -ENODEV; - - value = hl_get_frequency(hdev, HL_GAUDI_MME_PLL, false); - - if (value < 0) { - dev_err(hdev->dev, "Failed to retrieve device max clock %ld\n", - value); - return value; - } - - *max_clk = (value / 1000 / 1000); - - value = hl_get_frequency(hdev, HL_GAUDI_MME_PLL, true); - - if (value < 0) { - dev_err(hdev->dev, - "Failed to retrieve device current clock %ld\n", - value); - return value; - } - - *cur_clk = (value / 1000 / 1000); - - return 0; -} - -static ssize_t clk_max_freq_mhz_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hl_device *hdev = dev_get_drvdata(dev); - struct gaudi_device *gaudi = hdev->asic_specific; - long value; - - if (!hl_device_operational(hdev, NULL)) - return -ENODEV; - - value = hl_get_frequency(hdev, HL_GAUDI_MME_PLL, false); - - gaudi->max_freq_value = value; - - return sprintf(buf, "%lu\n", (value / 1000 / 1000)); -} - -static ssize_t clk_max_freq_mhz_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct hl_device *hdev = dev_get_drvdata(dev); - struct gaudi_device *gaudi = hdev->asic_specific; - int rc; - u64 value; - - if (!hl_device_operational(hdev, NULL)) { - count = -ENODEV; - goto fail; - } - - rc = kstrtoull(buf, 0, &value); - if (rc) { - count = -EINVAL; - goto fail; - } - - gaudi->max_freq_value = value * 1000 * 1000; - - hl_set_frequency(hdev, HL_GAUDI_MME_PLL, gaudi->max_freq_value); - -fail: - return count; -} - -static ssize_t clk_cur_freq_mhz_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct hl_device *hdev = dev_get_drvdata(dev); - long value; - - if (!hl_device_operational(hdev, NULL)) - return -ENODEV; - - value = hl_get_frequency(hdev, HL_GAUDI_MME_PLL, true); - - return sprintf(buf, "%lu\n", (value / 1000 / 1000)); -} - -static DEVICE_ATTR_RW(clk_max_freq_mhz); -static DEVICE_ATTR_RO(clk_cur_freq_mhz); - -static struct attribute *gaudi_dev_attrs[] = { - &dev_attr_clk_max_freq_mhz.attr, - &dev_attr_clk_cur_freq_mhz.attr, - NULL, -}; - -void gaudi_add_device_attr(struct hl_device *hdev, - struct attribute_group *dev_attr_grp) -{ - dev_attr_grp->attrs = gaudi_dev_attrs; -} diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c index ad00789348d9..5536e8c27bd5 100644 --- a/drivers/misc/habanalabs/goya/goya.c +++ b/drivers/misc/habanalabs/goya/goya.c @@ -471,6 +471,8 @@ int goya_set_fixed_properties(struct hl_device *hdev) prop->server_type = HL_SERVER_TYPE_UNKNOWN; + prop->clk_pll_index = HL_GOYA_MME_PLL; + return 0; } @@ -5656,7 +5658,7 @@ static const struct hl_asic_funcs goya_funcs = { .halt_coresight = goya_halt_coresight, .ctx_init = goya_ctx_init, .ctx_fini = goya_ctx_fini, - .get_clk_rate = goya_get_clk_rate, + .get_clk_rate = hl_get_clk_rate, .get_queue_id_for_cq = goya_get_queue_id_for_cq, .load_firmware_to_device = goya_load_firmware_to_device, .load_boot_fit_to_device = goya_load_boot_fit_to_device, diff --git a/drivers/misc/habanalabs/goya/goyaP.h b/drivers/misc/habanalabs/goya/goyaP.h index 0b05da614729..97add7b04f82 100644 --- a/drivers/misc/habanalabs/goya/goyaP.h +++ b/drivers/misc/habanalabs/goya/goyaP.h @@ -235,7 +235,6 @@ void goya_cpu_accessible_dma_pool_free(struct hl_device *hdev, size_t size, void *vaddr); void goya_mmu_remove_device_cpu_mappings(struct hl_device *hdev); -int goya_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk); u32 goya_get_queue_id_for_cq(struct hl_device *hdev, u32 cq_idx); u64 goya_get_device_time(struct hl_device *hdev); diff --git a/drivers/misc/habanalabs/goya/goya_hwmgr.c b/drivers/misc/habanalabs/goya/goya_hwmgr.c index 7d007125727f..59b2624ff81a 100644 --- a/drivers/misc/habanalabs/goya/goya_hwmgr.c +++ b/drivers/misc/habanalabs/goya/goya_hwmgr.c @@ -32,37 +32,6 @@ void goya_set_pll_profile(struct hl_device *hdev, enum hl_pll_frequency freq) } } -int goya_get_clk_rate(struct hl_device *hdev, u32 *cur_clk, u32 *max_clk) -{ - long value; - - if (!hl_device_operational(hdev, NULL)) - return -ENODEV; - - value = hl_get_frequency(hdev, HL_GOYA_MME_PLL, false); - - if (value < 0) { - dev_err(hdev->dev, "Failed to retrieve device max clock %ld\n", - value); - return value; - } - - *max_clk = (value / 1000 / 1000); - - value = hl_get_frequency(hdev, HL_GOYA_MME_PLL, true); - - if (value < 0) { - dev_err(hdev->dev, - "Failed to retrieve device current clock %ld\n", - value); - return value; - } - - *cur_clk = (value / 1000 / 1000); - - return 0; -} - static ssize_t mme_clk_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit v1.2.3 From 4a18dde5e4c6348d48e3021cfbb01ef699005f19 Mon Sep 17 00:00:00 2001 From: Moti Haimovski Date: Mon, 16 Aug 2021 14:39:46 +0300 Subject: habanalabs: initialize hpriv fields before adding new node When adding a new node to the hpriv list, the driver should initialize its fields before adding the new node. Otherwise, there may be some small chance of another thread traversing that list and accessing the new node's fields without them being initialized. Signed-off-by: Moti Haimovski Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/habanalabs_drv.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/habanalabs_drv.c b/drivers/misc/habanalabs/common/habanalabs_drv.c index 1da56069750a..949d1b5c5c41 100644 --- a/drivers/misc/habanalabs/common/habanalabs_drv.c +++ b/drivers/misc/habanalabs/common/habanalabs_drv.c @@ -225,6 +225,17 @@ int hl_device_open_ctrl(struct inode *inode, struct file *filp) if (!hpriv) return -ENOMEM; + /* Prevent other routines from reading partial hpriv data by + * initializing hpriv fields before inserting it to the list + */ + hpriv->hdev = hdev; + filp->private_data = hpriv; + hpriv->filp = filp; + hpriv->is_control = true; + nonseekable_open(inode, filp); + + hpriv->taskpid = find_get_pid(current->pid); + mutex_lock(&hdev->fpriv_list_lock); if (!hl_device_operational(hdev, NULL)) { @@ -238,19 +249,15 @@ int hl_device_open_ctrl(struct inode *inode, struct file *filp) list_add(&hpriv->dev_node, &hdev->fpriv_list); mutex_unlock(&hdev->fpriv_list_lock); - hpriv->hdev = hdev; - filp->private_data = hpriv; - hpriv->filp = filp; - hpriv->is_control = true; - nonseekable_open(inode, filp); - - hpriv->taskpid = find_get_pid(current->pid); - return 0; out_err: mutex_unlock(&hdev->fpriv_list_lock); + filp->private_data = NULL; + put_pid(hpriv->taskpid); + kfree(hpriv); + return rc; } -- cgit v1.2.3 From d2f5684b8f28da52b8df9ac92a84d0f1c6983f5f Mon Sep 17 00:00:00 2001 From: Yuri Nudelman Date: Wed, 6 Oct 2021 11:58:02 +0300 Subject: habanalabs: simplify wait for interrupt with timestamp flow Remove the flag that determines whether to take a timestamp once the interrupt arrives. Instead, always take the timestamp once per interrupt. This is a must for the user-space to measure its graph operations to evaluate the graph computation time. Signed-off-by: Yuri Nudelman Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/command_submission.c | 11 +++++------ drivers/misc/habanalabs/common/habanalabs.h | 2 -- drivers/misc/habanalabs/common/irq.c | 4 ++-- 3 files changed, 7 insertions(+), 10 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index a3358cc3c877..f94ac2350a9b 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -2768,7 +2768,7 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, u32 timeout_us, u64 user_address, u64 target_value, u16 interrupt_offset, enum hl_cs_wait_status *status, - bool take_timestamp, u64 *timestamp) + u64 *timestamp) { struct hl_user_pending_interrupt *pend; struct hl_user_interrupt *interrupt; @@ -2792,8 +2792,6 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, hl_fence_init(&pend->fence, ULONG_MAX); - pend->fence.take_timestamp = take_timestamp; - if (interrupt_offset == HL_COMMON_USER_INTERRUPT_ID) interrupt = &hdev->common_user_interrupt; else @@ -2815,9 +2813,11 @@ static int _hl_interrupt_wait_ioctl(struct hl_device *hdev, struct hl_ctx *ctx, goto remove_pending_user_interrupt; } - if (completion_value >= target_value) + if (completion_value >= target_value) { *status = CS_WAIT_STATUS_COMPLETED; - else + /* There was no interrupt, we assume the completion is now. */ + pend->fence.timestamp = ktime_get(); + } else *status = CS_WAIT_STATUS_BUSY; if (!timeout_us || (*status == CS_WAIT_STATUS_COMPLETED)) @@ -2914,7 +2914,6 @@ static int hl_interrupt_wait_ioctl(struct hl_fpriv *hpriv, void *data) rc = _hl_interrupt_wait_ioctl(hdev, hpriv->ctx, args->in.interrupt_timeout_us, args->in.addr, args->in.target, interrupt_offset, &status, - args->in.flags & HL_CS_FLAGS_TIMESTAMP, ×tamp); if (rc) { diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h index e7b3b121f24d..a2002cbf794b 100644 --- a/drivers/misc/habanalabs/common/habanalabs.h +++ b/drivers/misc/habanalabs/common/habanalabs.h @@ -615,7 +615,6 @@ struct asic_fixed_properties { * masters QIDs that multi cs is waiting on * @error: mark this fence with error * @timestamp: timestamp upon completion - * @take_timestamp: timestamp shall be taken upon completion * @mcs_handling_done: indicates that corresponding command submission has * finished msc handling, this does not mean it was part * of the mcs @@ -627,7 +626,6 @@ struct hl_fence { u32 stream_master_qid_map; int error; ktime_t timestamp; - u8 take_timestamp; u8 mcs_handling_done; }; diff --git a/drivers/misc/habanalabs/common/irq.c b/drivers/misc/habanalabs/common/irq.c index 0dd00ffd1809..96d82b682674 100644 --- a/drivers/misc/habanalabs/common/irq.c +++ b/drivers/misc/habanalabs/common/irq.c @@ -141,11 +141,11 @@ static void handle_user_cq(struct hl_device *hdev, struct hl_user_interrupt *user_cq) { struct hl_user_pending_interrupt *pend; + ktime_t now = ktime_get(); spin_lock(&user_cq->wait_list_lock); list_for_each_entry(pend, &user_cq->wait_list_head, wait_list_node) { - if (pend->fence.take_timestamp) - pend->fence.timestamp = ktime_get(); + pend->fence.timestamp = now; complete_all(&pend->fence.completion); } spin_unlock(&user_cq->wait_list_lock); -- cgit v1.2.3 From fae132632c55fdab81a81e0fd3d578d38ce43f78 Mon Sep 17 00:00:00 2001 From: Omer Shpigelman Date: Mon, 11 Oct 2021 10:03:44 +0300 Subject: habanalabs: context cleanup cosmetics No need to check the return value if the following action is the same for both cases. In addition, now that hl_ctx_free() doesn't print if the context is not released, its name can be misleading as the context might stay alive after it is executed with no indication for that. Hence we can discard it and simply put the refcount. Signed-off-by: Omer Shpigelman Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- drivers/misc/habanalabs/common/context.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/context.c b/drivers/misc/habanalabs/common/context.c index 22978303ad63..d0aaccd4df2c 100644 --- a/drivers/misc/habanalabs/common/context.c +++ b/drivers/misc/habanalabs/common/context.c @@ -181,12 +181,6 @@ out_err: return rc; } -void hl_ctx_free(struct hl_device *hdev, struct hl_ctx *ctx) -{ - if (kref_put(&ctx->refcount, hl_ctx_do_release) == 1) - return; -} - int hl_ctx_init(struct hl_device *hdev, struct hl_ctx *ctx, bool is_kernel_ctx) { int rc = 0; @@ -392,7 +386,7 @@ void hl_ctx_mgr_fini(struct hl_device *hdev, struct hl_ctx_mgr *mgr) idp = &mgr->ctx_handles; idr_for_each_entry(idp, ctx, id) - hl_ctx_free(hdev, ctx); + kref_put(&ctx->refcount, hl_ctx_do_release); idr_destroy(&mgr->ctx_handles); mutex_destroy(&mgr->ctx_lock); -- cgit v1.2.3 From b2faac3887df87a6e4bc3356280ea35dc7459c0b Mon Sep 17 00:00:00 2001 From: Dani Liberman Date: Tue, 12 Oct 2021 13:30:27 +0300 Subject: habanalabs: refactor fence handling in hl_cs_poll_fences To avoid checking if fence exists multipled times, changed fence handling to depend only on the fence status field: Busy, which means CS still did not completed : Add its QID so multi CS wait on its completion. Finished, which means CS completed and fence exists: Raise its completion bit if it finished mcs handling and update if necessary the earliest timestamp. Gone, which means CS already completed and fence deleted: Update multi CS data to ignore timestamp and raise its completion bit. Signed-off-by: Dani Liberman Reported-by: kernel test robot Reported-by: Dan Carpenter Reviewed-by: Oded Gabbay Signed-off-by: Oded Gabbay --- .../misc/habanalabs/common/command_submission.c | 71 +++++++++++----------- 1 file changed, 36 insertions(+), 35 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/habanalabs/common/command_submission.c b/drivers/misc/habanalabs/common/command_submission.c index f94ac2350a9b..4c8000fd246c 100644 --- a/drivers/misc/habanalabs/common/command_submission.c +++ b/drivers/misc/habanalabs/common/command_submission.c @@ -2382,47 +2382,48 @@ static int hl_cs_poll_fences(struct multi_cs_data *mcs_data) break; } - /* - * It is possible to get an old sequence numbers from user - * which related to already completed CSs and their fences - * already gone. In this case, no need to consider its QID for - * mcs completion. - */ - if (fence) + switch (status) { + case CS_WAIT_STATUS_BUSY: + /* CS did not finished, keep waiting on its QID*/ mcs_data->stream_master_qid_map |= fence->stream_master_qid_map; + break; + case CS_WAIT_STATUS_COMPLETED: + /* + * Using mcs_handling_done to avoid possibility of mcs_data + * returns to user indicating CS completed before it finished + * all of its mcs handling, to avoid race the next time the + * user waits for mcs. + */ + if (!fence->mcs_handling_done) + break; - /* - * Using mcs_handling_done to avoid possibility of mcs_data - * returns to user indicating CS completed before it finished - * all of its mcs handling, to avoid race the next time the - * user waits for mcs. - */ - if (status == CS_WAIT_STATUS_BUSY || - (fence && !fence->mcs_handling_done)) - continue; - - mcs_data->completion_bitmap |= BIT(i); - - /* - * best effort to extract timestamp. few notes: - * - if even single fence is gone we cannot extract timestamp - * (as fence not exist anymore) - * - for all completed CSs we take the earliest timestamp. - * for this we have to validate that: - * 1. given timestamp was indeed set - * 2. the timestamp is earliest of all timestamps so far - */ - - if (status == CS_WAIT_STATUS_GONE) { + mcs_data->completion_bitmap |= BIT(i); + /* + * For all completed CSs we take the earliest timestamp. + * For this we have to validate that the timestamp is + * earliest of all timestamps so far. + */ + if (mcs_data->update_ts && + (ktime_compare(fence->timestamp, first_cs_time) < 0)) + first_cs_time = fence->timestamp; + break; + case CS_WAIT_STATUS_GONE: mcs_data->update_ts = false; mcs_data->gone_cs = true; - } else if (mcs_data->update_ts && - (ktime_compare(fence->timestamp, - ktime_set(0, 0)) > 0) && - (ktime_compare(fence->timestamp, first_cs_time) < 0)) { - first_cs_time = fence->timestamp; + /* + * It is possible to get an old sequence numbers from user + * which related to already completed CSs and their fences + * already gone. In this case, CS set as completed but + * no need to consider its QID for mcs completion. + */ + mcs_data->completion_bitmap |= BIT(i); + break; + default: + dev_err(hdev->dev, "Invalid fence status\n"); + return -EINVAL; } + } hl_fences_put(mcs_data->fence_arr, arr_len); -- cgit v1.2.3 From 714f1af14bb0c829a33ad68c4ef7d622618ce702 Mon Sep 17 00:00:00 2001 From: Ye Guojin Date: Fri, 22 Oct 2021 09:06:04 +0000 Subject: misc: enclosure: replace snprintf in show functions with sysfs_emit coccicheck complains about the use of snprintf() in sysfs show functions: WARNING use scnprintf or sprintf Use sysfs_emit instead of scnprintf or sprintf makes more sense. Reported-by: Zeal Robot Signed-off-by: Ye Guojin Link: https://lore.kernel.org/r/20211022090604.1065367-1-ye.guojin@zte.com.cn Signed-off-by: Greg Kroah-Hartman --- drivers/misc/enclosure.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/misc/enclosure.c b/drivers/misc/enclosure.c index f950d0155876..1b010d9267c9 100644 --- a/drivers/misc/enclosure.c +++ b/drivers/misc/enclosure.c @@ -426,7 +426,7 @@ static ssize_t components_show(struct device *cdev, { struct enclosure_device *edev = to_enclosure_device(cdev); - return snprintf(buf, 40, "%d\n", edev->components); + return sysfs_emit(buf, "%d\n", edev->components); } static DEVICE_ATTR_RO(components); @@ -481,7 +481,7 @@ static ssize_t get_component_fault(struct device *cdev, if (edev->cb->get_fault) edev->cb->get_fault(edev, ecomp); - return snprintf(buf, 40, "%d\n", ecomp->fault); + return sysfs_emit(buf, "%d\n", ecomp->fault); } static ssize_t set_component_fault(struct device *cdev, @@ -505,7 +505,7 @@ static ssize_t get_component_status(struct device *cdev, if (edev->cb->get_status) edev->cb->get_status(edev, ecomp); - return snprintf(buf, 40, "%s\n", enclosure_status[ecomp->status]); + return sysfs_emit(buf, "%s\n", enclosure_status[ecomp->status]); } static ssize_t set_component_status(struct device *cdev, @@ -539,7 +539,7 @@ static ssize_t get_component_active(struct device *cdev, if (edev->cb->get_active) edev->cb->get_active(edev, ecomp); - return snprintf(buf, 40, "%d\n", ecomp->active); + return sysfs_emit(buf, "%d\n", ecomp->active); } static ssize_t set_component_active(struct device *cdev, @@ -563,7 +563,7 @@ static ssize_t get_component_locate(struct device *cdev, if (edev->cb->get_locate) edev->cb->get_locate(edev, ecomp); - return snprintf(buf, 40, "%d\n", ecomp->locate); + return sysfs_emit(buf, "%d\n", ecomp->locate); } static ssize_t set_component_locate(struct device *cdev, @@ -593,7 +593,7 @@ static ssize_t get_component_power_status(struct device *cdev, if (ecomp->power_status == -1) return (edev->cb->get_power_status) ? -EIO : -ENOTTY; - return snprintf(buf, 40, "%s\n", ecomp->power_status ? "on" : "off"); + return sysfs_emit(buf, "%s\n", ecomp->power_status ? "on" : "off"); } static ssize_t set_component_power_status(struct device *cdev, @@ -623,7 +623,7 @@ static ssize_t get_component_type(struct device *cdev, { struct enclosure_component *ecomp = to_enclosure_component(cdev); - return snprintf(buf, 40, "%s\n", enclosure_type[ecomp->type]); + return sysfs_emit(buf, "%s\n", enclosure_type[ecomp->type]); } static ssize_t get_component_slot(struct device *cdev, @@ -638,7 +638,7 @@ static ssize_t get_component_slot(struct device *cdev, else slot = ecomp->number; - return snprintf(buf, 40, "%d\n", slot); + return sysfs_emit(buf, "%d\n", slot); } static DEVICE_ATTR(fault, S_IRUGO | S_IWUSR, get_component_fault, -- cgit v1.2.3 From d46e58ef776bc6548b17b563ec4a8ed30c6643da Mon Sep 17 00:00:00 2001 From: Kees Cook Date: Fri, 22 Oct 2021 15:38:26 -0700 Subject: lkdtm/bugs: Check that a per-task stack canary exists Introduce REPORT_STACK_CANARY to check for differing stack canaries between two processes (i.e. that an architecture is correctly implementing per-task stack canaries), using the task_struct canary as the hint to locate in the stack. Requires that one of the processes being tested not be pid 1. Cc: Ard Biesheuvel Cc: Greg Kroah-Hartman Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20211022223826.330653-3-keescook@chromium.org Signed-off-by: Greg Kroah-Hartman --- drivers/misc/lkdtm/bugs.c | 77 +++++++++++++++++++++++++++++++++ drivers/misc/lkdtm/core.c | 1 + drivers/misc/lkdtm/lkdtm.h | 1 + tools/testing/selftests/lkdtm/config | 1 + tools/testing/selftests/lkdtm/tests.txt | 1 + 5 files changed, 81 insertions(+) (limited to 'drivers/misc') diff --git a/drivers/misc/lkdtm/bugs.c b/drivers/misc/lkdtm/bugs.c index 4282b625200f..f4cb94a9aa9c 100644 --- a/drivers/misc/lkdtm/bugs.c +++ b/drivers/misc/lkdtm/bugs.c @@ -151,6 +151,83 @@ void lkdtm_REPORT_STACK(void) pr_info("Stack offset: %d\n", (int)(stack_addr - (uintptr_t)&magic)); } +static pid_t stack_canary_pid; +static unsigned long stack_canary; +static unsigned long stack_canary_offset; + +static noinline void __lkdtm_REPORT_STACK_CANARY(void *stack) +{ + int i = 0; + pid_t pid = task_pid_nr(current); + unsigned long *canary = (unsigned long *)stack; + unsigned long current_offset = 0, init_offset = 0; + + /* Do our best to find the canary in a 16 word window ... */ + for (i = 1; i < 16; i++) { + canary = (unsigned long *)stack + i; +#ifdef CONFIG_STACKPROTECTOR + if (*canary == current->stack_canary) + current_offset = i; + if (*canary == init_task.stack_canary) + init_offset = i; +#endif + } + + if (current_offset == 0) { + /* + * If the canary doesn't match what's in the task_struct, + * we're either using a global canary or the stack frame + * layout changed. + */ + if (init_offset != 0) { + pr_err("FAIL: global stack canary found at offset %ld (canary for pid %d matches init_task's)!\n", + init_offset, pid); + } else { + pr_warn("FAIL: did not correctly locate stack canary :(\n"); + pr_expected_config(CONFIG_STACKPROTECTOR); + } + + return; + } else if (init_offset != 0) { + pr_warn("WARNING: found both current and init_task canaries nearby?!\n"); + } + + canary = (unsigned long *)stack + current_offset; + if (stack_canary_pid == 0) { + stack_canary = *canary; + stack_canary_pid = pid; + stack_canary_offset = current_offset; + pr_info("Recorded stack canary for pid %d at offset %ld\n", + stack_canary_pid, stack_canary_offset); + } else if (pid == stack_canary_pid) { + pr_warn("ERROR: saw pid %d again -- please use a new pid\n", pid); + } else { + if (current_offset != stack_canary_offset) { + pr_warn("ERROR: canary offset changed from %ld to %ld!?\n", + stack_canary_offset, current_offset); + return; + } + + if (*canary == stack_canary) { + pr_warn("FAIL: canary identical for pid %d and pid %d at offset %ld!\n", + stack_canary_pid, pid, current_offset); + } else { + pr_info("ok: stack canaries differ between pid %d and pid %d at offset %ld.\n", + stack_canary_pid, pid, current_offset); + /* Reset the test. */ + stack_canary_pid = 0; + } + } +} + +void lkdtm_REPORT_STACK_CANARY(void) +{ + /* Use default char array length that triggers stack protection. */ + char data[8] __aligned(sizeof(void *)) = { }; + + __lkdtm_REPORT_STACK_CANARY((void *)&data); +} + void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void) { static u8 data[5] __attribute__((aligned(4))) = {1, 2, 3, 4, 5}; diff --git a/drivers/misc/lkdtm/core.c b/drivers/misc/lkdtm/core.c index fe6fd34b8caf..609d9ee2acc0 100644 --- a/drivers/misc/lkdtm/core.c +++ b/drivers/misc/lkdtm/core.c @@ -111,6 +111,7 @@ static const struct crashtype crashtypes[] = { CRASHTYPE(CORRUPT_STACK), CRASHTYPE(CORRUPT_STACK_STRONG), CRASHTYPE(REPORT_STACK), + CRASHTYPE(REPORT_STACK_CANARY), CRASHTYPE(CORRUPT_LIST_ADD), CRASHTYPE(CORRUPT_LIST_DEL), CRASHTYPE(STACK_GUARD_PAGE_LEADING), diff --git a/drivers/misc/lkdtm/lkdtm.h b/drivers/misc/lkdtm/lkdtm.h index c212a253edde..d6137c70ebbe 100644 --- a/drivers/misc/lkdtm/lkdtm.h +++ b/drivers/misc/lkdtm/lkdtm.h @@ -69,6 +69,7 @@ void lkdtm_EXHAUST_STACK(void); void lkdtm_CORRUPT_STACK(void); void lkdtm_CORRUPT_STACK_STRONG(void); void lkdtm_REPORT_STACK(void); +void lkdtm_REPORT_STACK_CANARY(void); void lkdtm_UNALIGNED_LOAD_STORE_WRITE(void); void lkdtm_SOFTLOCKUP(void); void lkdtm_HARDLOCKUP(void); diff --git a/tools/testing/selftests/lkdtm/config b/tools/testing/selftests/lkdtm/config index 38edea25631b..a26a3fa9e925 100644 --- a/tools/testing/selftests/lkdtm/config +++ b/tools/testing/selftests/lkdtm/config @@ -8,3 +8,4 @@ CONFIG_RANDOMIZE_KSTACK_OFFSET_DEFAULT=y CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y CONFIG_UBSAN_BOUNDS=y CONFIG_UBSAN_TRAP=y +CONFIG_STACKPROTECTOR_STRONG=y diff --git a/tools/testing/selftests/lkdtm/tests.txt b/tools/testing/selftests/lkdtm/tests.txt index 09f7bfa383cc..6b36b7f5dcf9 100644 --- a/tools/testing/selftests/lkdtm/tests.txt +++ b/tools/testing/selftests/lkdtm/tests.txt @@ -12,6 +12,7 @@ CORRUPT_LIST_ADD list_add corruption CORRUPT_LIST_DEL list_del corruption STACK_GUARD_PAGE_LEADING STACK_GUARD_PAGE_TRAILING +REPORT_STACK_CANARY repeat:2 ok: stack canaries differ UNSET_SMEP pinned CR4 bits changed: DOUBLE_FAULT CORRUPT_PAC -- cgit v1.2.3 From 16b0314aa746be6c84c0bc6eca9dde0dce2e99df Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sun, 10 Oct 2021 14:46:28 +0200 Subject: dma-buf: move dma-buf symbols into the DMA_BUF module namespace MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In order to better track where in the kernel the dma-buf code is used, put the symbols in the namespace DMA_BUF and modify all users of the symbols to properly import the namespace to not break the build at the same time. Now the output of modinfo shows the use of these symbols, making it easier to watch for users over time: $ modinfo drivers/misc/fastrpc.ko | grep import import_ns: DMA_BUF Cc: "Pan, Xinhui" Cc: David Airlie Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Thomas Zimmermann Cc: Mauro Carvalho Chehab Cc: dri-devel@lists.freedesktop.org Acked-by: Daniel Vetter Acked-by: Christian König Acked-by: Arnd Bergmann Acked-by: Sumit Semwal Acked-by: Alex Deucher Link: https://lore.kernel.org/r/20211010124628.17691-1-gregkh@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/dma-buf/dma-buf.c | 34 +++++++++++----------- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 3 ++ drivers/gpu/drm/armada/armada_gem.c | 2 ++ drivers/gpu/drm/drm_gem_framebuffer_helper.c | 3 ++ drivers/gpu/drm/drm_prime.c | 3 ++ drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c | 3 ++ drivers/gpu/drm/exynos/exynos_drm_gem.c | 3 ++ drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c | 3 ++ drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c | 2 ++ drivers/gpu/drm/tegra/gem.c | 3 ++ drivers/gpu/drm/vmwgfx/ttm_object.c | 3 ++ drivers/infiniband/core/umem_dmabuf.c | 3 ++ drivers/media/common/videobuf2/videobuf2-core.c | 1 + .../media/common/videobuf2/videobuf2-dma-contig.c | 1 + drivers/media/common/videobuf2/videobuf2-dma-sg.c | 1 + drivers/media/common/videobuf2/videobuf2-vmalloc.c | 1 + drivers/misc/fastrpc.c | 1 + drivers/misc/habanalabs/common/memory.c | 2 ++ drivers/staging/media/tegra-vde/dmabuf-cache.c | 3 ++ drivers/tee/tee_shm.c | 3 ++ drivers/virtio/virtio_dma_buf.c | 1 + drivers/xen/gntdev-dmabuf.c | 3 ++ samples/vfio-mdev/mbochs.c | 1 + 23 files changed, 66 insertions(+), 17 deletions(-) (limited to 'drivers/misc') diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c index 63d32261b63f..6c2b5ea828a6 100644 --- a/drivers/dma-buf/dma-buf.c +++ b/drivers/dma-buf/dma-buf.c @@ -610,7 +610,7 @@ err_module: module_put(exp_info->owner); return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(dma_buf_export); +EXPORT_SYMBOL_NS_GPL(dma_buf_export, DMA_BUF); /** * dma_buf_fd - returns a file descriptor for the given struct dma_buf @@ -634,7 +634,7 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags) return fd; } -EXPORT_SYMBOL_GPL(dma_buf_fd); +EXPORT_SYMBOL_NS_GPL(dma_buf_fd, DMA_BUF); /** * dma_buf_get - returns the struct dma_buf related to an fd @@ -660,7 +660,7 @@ struct dma_buf *dma_buf_get(int fd) return file->private_data; } -EXPORT_SYMBOL_GPL(dma_buf_get); +EXPORT_SYMBOL_NS_GPL(dma_buf_get, DMA_BUF); /** * dma_buf_put - decreases refcount of the buffer @@ -679,7 +679,7 @@ void dma_buf_put(struct dma_buf *dmabuf) fput(dmabuf->file); } -EXPORT_SYMBOL_GPL(dma_buf_put); +EXPORT_SYMBOL_NS_GPL(dma_buf_put, DMA_BUF); static void mangle_sg_table(struct sg_table *sg_table) { @@ -810,7 +810,7 @@ err_unlock: dma_buf_detach(dmabuf, attach); return ERR_PTR(ret); } -EXPORT_SYMBOL_GPL(dma_buf_dynamic_attach); +EXPORT_SYMBOL_NS_GPL(dma_buf_dynamic_attach, DMA_BUF); /** * dma_buf_attach - Wrapper for dma_buf_dynamic_attach @@ -825,7 +825,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf, { return dma_buf_dynamic_attach(dmabuf, dev, NULL, NULL); } -EXPORT_SYMBOL_GPL(dma_buf_attach); +EXPORT_SYMBOL_NS_GPL(dma_buf_attach, DMA_BUF); static void __unmap_dma_buf(struct dma_buf_attachment *attach, struct sg_table *sg_table, @@ -871,7 +871,7 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach) kfree(attach); } -EXPORT_SYMBOL_GPL(dma_buf_detach); +EXPORT_SYMBOL_NS_GPL(dma_buf_detach, DMA_BUF); /** * dma_buf_pin - Lock down the DMA-buf @@ -901,7 +901,7 @@ int dma_buf_pin(struct dma_buf_attachment *attach) return ret; } -EXPORT_SYMBOL_GPL(dma_buf_pin); +EXPORT_SYMBOL_NS_GPL(dma_buf_pin, DMA_BUF); /** * dma_buf_unpin - Unpin a DMA-buf @@ -922,7 +922,7 @@ void dma_buf_unpin(struct dma_buf_attachment *attach) if (dmabuf->ops->unpin) dmabuf->ops->unpin(attach); } -EXPORT_SYMBOL_GPL(dma_buf_unpin); +EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, DMA_BUF); /** * dma_buf_map_attachment - Returns the scatterlist table of the attachment; @@ -1012,7 +1012,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach, #endif /* CONFIG_DMA_API_DEBUG */ return sg_table; } -EXPORT_SYMBOL_GPL(dma_buf_map_attachment); +EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, DMA_BUF); /** * dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might @@ -1048,7 +1048,7 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach, !IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY)) dma_buf_unpin(attach); } -EXPORT_SYMBOL_GPL(dma_buf_unmap_attachment); +EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, DMA_BUF); /** * dma_buf_move_notify - notify attachments that DMA-buf is moving @@ -1068,7 +1068,7 @@ void dma_buf_move_notify(struct dma_buf *dmabuf) if (attach->importer_ops) attach->importer_ops->move_notify(attach); } -EXPORT_SYMBOL_GPL(dma_buf_move_notify); +EXPORT_SYMBOL_NS_GPL(dma_buf_move_notify, DMA_BUF); /** * DOC: cpu access @@ -1212,7 +1212,7 @@ int dma_buf_begin_cpu_access(struct dma_buf *dmabuf, return ret; } -EXPORT_SYMBOL_GPL(dma_buf_begin_cpu_access); +EXPORT_SYMBOL_NS_GPL(dma_buf_begin_cpu_access, DMA_BUF); /** * dma_buf_end_cpu_access - Must be called after accessing a dma_buf from the @@ -1240,7 +1240,7 @@ int dma_buf_end_cpu_access(struct dma_buf *dmabuf, return ret; } -EXPORT_SYMBOL_GPL(dma_buf_end_cpu_access); +EXPORT_SYMBOL_NS_GPL(dma_buf_end_cpu_access, DMA_BUF); /** @@ -1282,7 +1282,7 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma, return dmabuf->ops->mmap(dmabuf, vma); } -EXPORT_SYMBOL_GPL(dma_buf_mmap); +EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF); /** * dma_buf_vmap - Create virtual mapping for the buffer object into kernel @@ -1336,7 +1336,7 @@ out_unlock: mutex_unlock(&dmabuf->lock); return ret; } -EXPORT_SYMBOL_GPL(dma_buf_vmap); +EXPORT_SYMBOL_NS_GPL(dma_buf_vmap, DMA_BUF); /** * dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap. @@ -1360,7 +1360,7 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, struct dma_buf_map *map) } mutex_unlock(&dmabuf->lock); } -EXPORT_SYMBOL_GPL(dma_buf_vunmap); +EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap, DMA_BUF); #ifdef CONFIG_DEBUG_FS static int dma_buf_debug_show(struct seq_file *s, void *unused) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 94126dc39688..4f03e0a2953e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -59,6 +60,8 @@ #include "amdgpu_res_cursor.h" #include "bif/bif_4_1_d.h" +MODULE_IMPORT_NS(DMA_BUF); + #define AMDGPU_TTM_VRAM_MAX_DW_READ (size_t)128 static int amdgpu_ttm_backend_bind(struct ttm_device *bdev, diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 21909642ee4c..711f0cca6f9c 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -15,6 +15,8 @@ #include "armada_gem.h" #include "armada_ioctlP.h" +MODULE_IMPORT_NS(DMA_BUF); + static vm_fault_t armada_gem_vm_fault(struct vm_fault *vmf) { struct drm_gem_object *gobj = vmf->vma->vm_private_data; diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index 3c75d79dbb65..746fd8c73845 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -6,6 +6,7 @@ */ #include +#include #include #include @@ -17,6 +18,8 @@ #include "drm_internal.h" +MODULE_IMPORT_NS(DMA_BUF); + #define AFBC_HEADER_SIZE 16 #define AFBC_TH_LAYOUT_ALIGNMENT 8 #define AFBC_HDR_ALIGN 64 diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index deb23dbec8b5..d8ba95744410 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,8 @@ #include "drm_internal.h" +MODULE_IMPORT_NS(DMA_BUF); + /** * DOC: overview and lifetime rules * diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index 6d8bed9c739d..6788ea8490d1 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -5,10 +5,13 @@ #include #include +#include #include "etnaviv_drv.h" #include "etnaviv_gem.h" +MODULE_IMPORT_NS(DMA_BUF); + static struct lock_class_key etnaviv_prime_lock_class; struct sg_table *etnaviv_gem_prime_get_sg_table(struct drm_gem_object *obj) diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 4396224227d1..0a0c042a3155 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -17,6 +18,8 @@ #include "exynos_drm_drv.h" #include "exynos_drm_gem.h" +MODULE_IMPORT_NS(DMA_BUF); + static int exynos_drm_alloc_buf(struct exynos_drm_gem *exynos_gem, bool kvmap) { struct drm_device *dev = exynos_gem->base.dev; diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index afa34111de02..abb854281347 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -7,11 +7,14 @@ #include #include #include +#include #include "i915_drv.h" #include "i915_gem_object.h" #include "i915_scatterlist.h" +MODULE_IMPORT_NS(DMA_BUF); + I915_SELFTEST_DECLARE(static bool force_different_devices;) static struct drm_i915_gem_object *dma_buf_to_obj(struct dma_buf *buf) diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index f4cde3a169d8..809f86cfc540 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c @@ -11,6 +11,8 @@ #include "omap_drv.h" +MODULE_IMPORT_NS(DMA_BUF); + /* ----------------------------------------------------------------------------- * DMABUF Export */ diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index 6ec598f5d5b3..d38fd7e12b57 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -20,6 +21,8 @@ #include "drm.h" #include "gem.h" +MODULE_IMPORT_NS(DMA_BUF); + static void tegra_bo_put(struct host1x_bo *bo) { struct tegra_bo *obj = host1x_to_tegra_bo(bo); diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c index 04789b2bb2a2..899945f54dc7 100644 --- a/drivers/gpu/drm/vmwgfx/ttm_object.c +++ b/drivers/gpu/drm/vmwgfx/ttm_object.c @@ -48,8 +48,11 @@ #include #include #include +#include #include "ttm_object.h" +MODULE_IMPORT_NS(DMA_BUF); + /** * struct ttm_object_file * diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c index e824baf4640d..2d14929543af 100644 --- a/drivers/infiniband/core/umem_dmabuf.c +++ b/drivers/infiniband/core/umem_dmabuf.c @@ -6,9 +6,12 @@ #include #include #include +#include #include "uverbs.h" +MODULE_IMPORT_NS(DMA_BUF); + int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf) { struct sg_table *sgt; diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c index 508ac295eb06..773c68dcd158 100644 --- a/drivers/media/common/videobuf2/videobuf2-core.c +++ b/drivers/media/common/videobuf2/videobuf2-core.c @@ -2978,3 +2978,4 @@ EXPORT_SYMBOL_GPL(vb2_thread_stop); MODULE_DESCRIPTION("Media buffer core framework"); MODULE_AUTHOR("Pawel Osciak , Marek Szyprowski"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(DMA_BUF); diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c index a7f61ba85440..9a1a9baca2e4 100644 --- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c +++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c @@ -755,3 +755,4 @@ EXPORT_SYMBOL_GPL(vb2_dma_contig_set_max_seg_size); MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2"); MODULE_AUTHOR("Pawel Osciak "); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(DMA_BUF); diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c index c5b06a509566..db90ebb8950f 100644 --- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c +++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c @@ -666,3 +666,4 @@ EXPORT_SYMBOL_GPL(vb2_dma_sg_memops); MODULE_DESCRIPTION("dma scatter/gather memory handling routines for videobuf2"); MODULE_AUTHOR("Andrzej Pietrasiewicz"); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(DMA_BUF); diff --git a/drivers/media/common/videobuf2/videobuf2-vmalloc.c b/drivers/media/common/videobuf2/videobuf2-vmalloc.c index 83f95258ec8c..fa983897d0e9 100644 --- a/drivers/media/common/videobuf2/videobuf2-vmalloc.c +++ b/drivers/media/common/videobuf2/videobuf2-vmalloc.c @@ -444,3 +444,4 @@ EXPORT_SYMBOL_GPL(vb2_vmalloc_memops); MODULE_DESCRIPTION("vmalloc memory handling routines for videobuf2"); MODULE_AUTHOR("Pawel Osciak "); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(DMA_BUF); diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c index 3b82d8ebe780..39aca7753719 100644 --- a/drivers/misc/fastrpc.c +++ b/drivers/misc/fastrpc.c @@ -1767,3 +1767,4 @@ static void fastrpc_exit(void) module_exit(fastrpc_exit); MODULE_LICENSE("GPL v2"); +MODULE_IMPORT_NS(DMA_BUF); diff --git a/drivers/misc/habanalabs/common/memory.c b/drivers/misc/habanalabs/common/memory.c index 504973330e2e..9bd626a00de3 100644 --- a/drivers/misc/habanalabs/common/memory.c +++ b/drivers/misc/habanalabs/common/memory.c @@ -13,6 +13,8 @@ #include #include +MODULE_IMPORT_NS(DMA_BUF); + #define HL_MMU_DEBUG 0 /* use small pages for supporting non-pow2 (32M/40M/48M) DRAM phys page sizes */ diff --git a/drivers/staging/media/tegra-vde/dmabuf-cache.c b/drivers/staging/media/tegra-vde/dmabuf-cache.c index a93b317885bf..a98d03419b8f 100644 --- a/drivers/staging/media/tegra-vde/dmabuf-cache.c +++ b/drivers/staging/media/tegra-vde/dmabuf-cache.c @@ -12,9 +12,12 @@ #include #include #include +#include #include "vde.h" +MODULE_IMPORT_NS(DMA_BUF); + struct tegra_vde_cache_entry { enum dma_data_direction dma_dir; struct dma_buf_attachment *a; diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c index 8a9384a64f3e..8a8deb95e918 100644 --- a/drivers/tee/tee_shm.c +++ b/drivers/tee/tee_shm.c @@ -10,8 +10,11 @@ #include #include #include +#include #include "tee_private.h" +MODULE_IMPORT_NS(DMA_BUF); + static void release_registered_pages(struct tee_shm *shm) { if (shm->pages) { diff --git a/drivers/virtio/virtio_dma_buf.c b/drivers/virtio/virtio_dma_buf.c index 5127a2f0c986..2521a75009c3 100644 --- a/drivers/virtio/virtio_dma_buf.c +++ b/drivers/virtio/virtio_dma_buf.c @@ -86,3 +86,4 @@ int virtio_dma_buf_get_uuid(struct dma_buf *dma_buf, EXPORT_SYMBOL(virtio_dma_buf_get_uuid); MODULE_LICENSE("GPL"); +MODULE_IMPORT_NS(DMA_BUF); diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c index 4c13cbc99896..12e380db7f55 100644 --- a/drivers/xen/gntdev-dmabuf.c +++ b/drivers/xen/gntdev-dmabuf.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -21,6 +22,8 @@ #include "gntdev-common.h" #include "gntdev-dmabuf.h" +MODULE_IMPORT_NS(DMA_BUF); + #ifndef GRANT_INVALID_REF /* * Note on usage of grant reference 0 as invalid grant reference: diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c index c313ab4d1f4e..a83be6cd162f 100644 --- a/samples/vfio-mdev/mbochs.c +++ b/samples/vfio-mdev/mbochs.c @@ -1493,5 +1493,6 @@ static void __exit mbochs_dev_exit(void) mbochs_class = NULL; } +MODULE_IMPORT_NS(DMA_BUF); module_init(mbochs_dev_init) module_exit(mbochs_dev_exit) -- cgit v1.2.3