From patchwork Fri Jul 9 19:08:30 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Asmaa Mnebhi X-Patchwork-Id: 1503334 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GM2lv4nBpz9sRN; Sat, 10 Jul 2021 05:09:47 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1m1vsa-0003j6-T7; Fri, 09 Jul 2021 19:09:41 +0000 Received: from mail-il-dmz.mellanox.com ([193.47.165.129] helo=mellanox.co.il) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1m1vs2-0003K1-4x for kernel-team@lists.ubuntu.com; Fri, 09 Jul 2021 19:09:06 +0000 Received: from Internal Mail-Server by MTLPINE1 (envelope-from asmaa@mellanox.com) with SMTP; 9 Jul 2021 22:09:01 +0300 Received: from farm-0002.mtbu.labs.mlnx (farm-0002.mtbu.labs.mlnx [10.15.2.32]) by mtbu-labmailer.labs.mlnx (8.14.4/8.14.4) with ESMTP id 169J90j6030262; Fri, 9 Jul 2021 15:09:00 -0400 Received: (from asmaa@localhost) by farm-0002.mtbu.labs.mlnx (8.14.7/8.13.8/Submit) id 169J90ri005476; Fri, 9 Jul 2021 15:09:00 -0400 From: Asmaa Mnebhi To: kernel-team@lists.ubuntu.com Subject: [SRU][F][PULL][PATCH v2 23/23] mlxbf-gige upstream effort: update gpio-mlxbf2.c and mlxbf-gige.c Date: Fri, 9 Jul 2021 15:08:30 -0400 Message-Id: <20210709190830.5405-24-asmaa@nvidia.com> X-Mailer: git-send-email 2.30.1 In-Reply-To: <20210709190830.5405-1-asmaa@nvidia.com> References: <20210709190830.5405-1-asmaa@nvidia.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: asmaa@nvidia.com, davthompson@nvidia.com Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" BugLink: https://bugs.launchpad.net/bugs/1934923 The upstreamed version of the mlxbf-gige driver removes dependencies on the gpio-mlxbf2 driver so the latter needs to be updated accordingly. Add the set_ring size function to mlxbf-gige which was left out from the upstreamed version. Signed-off-by: Asmaa Mnebhi Reviewed-by: David Thompson --- drivers/gpio/gpio-mlxbf2.c | 361 ++++++++++++------ .../mellanox/mlxbf_gige/mlxbf_gige_ethtool.c | 38 ++ .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 21 + 3 files changed, 295 insertions(+), 125 deletions(-) diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c index 0dc9747c79e4..905fe7766e19 100644 --- a/drivers/gpio/gpio-mlxbf2.c +++ b/drivers/gpio/gpio-mlxbf2.c @@ -1,25 +1,27 @@ // SPDX-License-Identifier: GPL-2.0-only or BSD-3-Clause /* - * Copyright (c) 2020 NVIDIA Corporation. + * Copyright (c) 2020-2021 NVIDIA Corporation. */ #include #include #include #include +#include #include #include #include #include -#include #include #include #include +#include #include #include #include -#include + +#define DRV_VERSION "1.4" /* * There are 3 YU GPIO blocks: @@ -30,6 +32,13 @@ */ #define MLXBF2_GPIO_MAX_PINS_PER_BLOCK 32 +typedef enum { + GPIO_BLOCK0 = 0, + GPIO_BLOCK1 = 1, + GPIO_BLOCK2 = 2, + GPIO_BLOCK16 = 16 +} yu_gpio_block; + /* * arm_gpio_lock register: * bit[31] lock status: active if set @@ -42,6 +51,9 @@ #define YU_ARM_GPIO_LOCK_ACQUIRE 0xd42f #define YU_ARM_GPIO_LOCK_RELEASE 0x0 +#define YU_CAUSE_GPIO_ADDR 0x2801530 +#define YU_CAUSE_GPIO_ADDR_SIZE 0x4 + /* * gpio[x] block registers and their offset */ @@ -50,6 +62,8 @@ #define YU_GPIO_MODE0 0x0c #define YU_GPIO_DATASET 0x14 #define YU_GPIO_DATACLEAR 0x18 +#define YU_GPIO_FUNCTIONAL_ENABLE1 0x24 +#define YU_GPIO_FUNCTIONAL_ENABLE0 0x28 #define YU_GPIO_CAUSE_RISE_EN 0x44 #define YU_GPIO_CAUSE_FALL_EN 0x48 #define YU_GPIO_MODE1_CLEAR 0x50 @@ -59,16 +73,6 @@ #define YU_GPIO_CAUSE_OR_CAUSE_EVTEN0 0x80 #define YU_GPIO_CAUSE_OR_EVTEN0 0x94 #define YU_GPIO_CAUSE_OR_CLRCAUSE 0x98 -#define YU_GPIO16_LOW_PWR_BIT 0 -#define YU_GPIO0_RST_BIT 7 -#define YU_GPIO_CAUSE_OR_CAUSE_EVTEN0_MASK(gpio_bit) BIT(gpio_bit) -#define YU_GPIO_CAUSE_OR_EVTEN0_MASK(gpio_bit) BIT(gpio_bit) -#define YU_GPIO_CAUSE_RISE_EN_MASK(gpio_bit) BIT(gpio_bit) -#define YU_GPIO_CAUSE_FALL_EN_MASK(gpio_bit) BIT(gpio_bit) -#define YU_GPIO_CAUSE_OR_CLRCAUSE_MASK(gpio_bit) BIT(gpio_bit) -#define YU_CAUSE_RSH_COALESCE0_GPIO_CAUSE_MASK 0x10 -#define YU_GPIO_CAUSE_IRQ_IS_SET(val) \ - (val & YU_CAUSE_RSH_COALESCE0_GPIO_CAUSE_MASK) #ifdef CONFIG_PM struct mlxbf2_gpio_context_save_regs { @@ -77,28 +81,25 @@ struct mlxbf2_gpio_context_save_regs { }; #endif -#define RST_GPIO_PIN 7 -#define LOW_PWR_GPIO_PIN 71 -#define MAX_HOST_GPIOS LOW_PWR_GPIO_PIN - /* BlueField-2 gpio block context structure. */ struct mlxbf2_gpio_context { struct gpio_chip gc; + struct irq_chip irq_chip; /* YU GPIO blocks address */ void __iomem *gpio_io; - /* GPIO pin responsible for low power mode */ + /* YU cause gpio arm coalesce0 address */ + void __iomem *cause_gpio_arm_coalesce0_io; + + /* YU GPIO pin responsible for low power mode */ unsigned long low_pwr_pin; - /* GPIO pin responsible for soft reset */ + /* YU GPIO pin responsible for soft reset */ unsigned long rst_pin; - /* - * Bit within the YU GPIO block that's conifgued - * as an interrupt. - */ - u32 gpio_int_bit; + /* YU GPIO block interrupt mask */ + u32 gpio_int_mask; /* Worker function */ struct work_struct send_work; @@ -128,6 +129,19 @@ static struct mlxbf2_gpio_param yu_arm_gpio_lock_param = { .lock = &yu_arm_gpio_lock_mutex, }; +static struct resource yu_cause_gpio_res = { + .start = YU_CAUSE_GPIO_ADDR, + .end = YU_CAUSE_GPIO_ADDR + YU_CAUSE_GPIO_ADDR_SIZE - 1, + .name = "YU_CAUSE_GPIO", +}; + +static DEFINE_MUTEX(yu_cause_gpio_mutex); + +static struct mlxbf2_gpio_param yu_cause_gpio_param = { + .res = &yu_cause_gpio_res, + .lock = &yu_cause_gpio_mutex, +}; + /* Request memory region and map yu_arm_gpio_lock resource */ static int mlxbf2_gpio_get_lock_res(struct platform_device *pdev) { @@ -151,8 +165,8 @@ static int mlxbf2_gpio_get_lock_res(struct platform_device *pdev) } yu_arm_gpio_lock_param.io = devm_ioremap(dev, res->start, size); - if (IS_ERR(yu_arm_gpio_lock_param.io)) - ret = PTR_ERR(yu_arm_gpio_lock_param.io); + if (!yu_arm_gpio_lock_param.io) + ret = -ENOMEM; exit: mutex_unlock(yu_arm_gpio_lock_param.lock); @@ -160,6 +174,38 @@ static int mlxbf2_gpio_get_lock_res(struct platform_device *pdev) return ret; } +/* Request memory region and map yu cause_gpio_arm.coalesce0 resource */ +static int mlxbf2_gpio_get_yu_cause_gpio_res(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + resource_size_t size; + int ret = 0; + + mutex_lock(yu_cause_gpio_param.lock); + + /* Check if the memory map already exists */ + if (yu_cause_gpio_param.io) + goto exit; + + res = yu_cause_gpio_param.res; + size = resource_size(res); + + if (!devm_request_mem_region(dev, res->start, size, res->name)) { + ret = -EFAULT; + goto exit; + } + + yu_cause_gpio_param.io = devm_ioremap(dev, res->start, size); + if (!yu_cause_gpio_param.io) + ret = -ENOMEM; + +exit: + mutex_unlock(yu_cause_gpio_param.lock); + + return ret; +} + /* * Acquire the YU arm_gpio_lock to be able to change the direction * mode. If the lock_active bit is already set, return an error. @@ -191,6 +237,8 @@ static int mlxbf2_gpio_lock_acquire(struct mlxbf2_gpio_context *gs) * Release the YU arm_gpio_lock after changing the direction mode. */ static void mlxbf2_gpio_lock_release(struct mlxbf2_gpio_context *gs) + __releases(&gs->gc.bgpio_lock) + __releases(yu_arm_gpio_lock_param.lock) { writel(YU_ARM_GPIO_LOCK_RELEASE, yu_arm_gpio_lock_param.io); spin_unlock(&gs->gc.bgpio_lock); @@ -247,6 +295,7 @@ static int mlxbf2_gpio_direction_output(struct gpio_chip *chip, { struct mlxbf2_gpio_context *gs = gpiochip_get_data(chip); int ret = 0; + u32 val; /* * Although the arm_gpio_lock was set in the probe function, @@ -260,115 +309,152 @@ static int mlxbf2_gpio_direction_output(struct gpio_chip *chip, writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE1_CLEAR); writel(BIT(offset), gs->gpio_io + YU_GPIO_MODE0_SET); + /* + * Set {functional_enable1,functional_enable0}={0,0} + * to give control to software over these GPIOs. + */ + val = readl(gs->gpio_io + YU_GPIO_FUNCTIONAL_ENABLE1); + val &= ~BIT(offset); + writel(val, gs->gpio_io + YU_GPIO_FUNCTIONAL_ENABLE1); + val = readl(gs->gpio_io + YU_GPIO_FUNCTIONAL_ENABLE0); + val &= ~BIT(offset); + writel(val, gs->gpio_io + YU_GPIO_FUNCTIONAL_ENABLE0); + mlxbf2_gpio_lock_release(gs); return ret; } -static void mlxbf2_gpio_irq_disable(struct mlxbf2_gpio_context *gs) +static void mlxbf2_gpio_send_work(struct work_struct *work) +{ +#ifdef CONFIG_ACPI + acpi_bus_generate_netlink_event("button/power.*", "Power Button", + 0x80, 1); +#endif +} + +static u32 mlxbf2_gpio_get_int_mask(struct mlxbf2_gpio_context *gs) { - u32 val; + u32 gpio_int_mask = 0; - spin_lock(&gs->gc.bgpio_lock); - val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); - if (!val) { - spin_unlock(&gs->gc.bgpio_lock); - /* There is no enabled interrupt */ - return; - } + /* + * Determine bit mask within the yu gpio block. + */ + if (gs->rst_pin != MLXBF2_GPIO_MAX_PINS_PER_BLOCK) + gpio_int_mask |= BIT(gs->rst_pin); + if (gs->low_pwr_pin != MLXBF2_GPIO_MAX_PINS_PER_BLOCK) + gpio_int_mask = BIT(gs->low_pwr_pin); - val &= ~YU_GPIO_CAUSE_OR_EVTEN0_MASK(gs->gpio_int_bit); - writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); - spin_unlock(&gs->gc.bgpio_lock); + return gpio_int_mask; } -static void mlxbf2_gpio_irq_set_type(struct mlxbf2_gpio_context *gs) +static irqreturn_t mlxbf2_gpio_irq_handler(int irq, void *ptr) { - u32 val; + struct mlxbf2_gpio_context *gs = ptr; + unsigned long gpio_pin; + u32 gpio_block, val; + unsigned long flags; - spin_lock(&gs->gc.bgpio_lock); + spin_lock_irqsave(&gs->gc.bgpio_lock, flags); /* - * The power state gpio interrupt should be detected at rising - * and falling edges. - * - * In the case of low power mode interrupt: - * When it goes from 0 to 1, system should go into low power state - * When it goes from 1 to 0, system should revert to normal state - * - * In the case of soft reset interrupt, trigger interrupt off - * falling edge since it is active low. + * Determine which yu gpio block this interrupt is for. + * Return if the interrupt is not for gpio block 0 or + * gpio block 16. */ - if (gs->low_pwr_pin == LOW_PWR_GPIO_PIN) { - val = readl(gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); - val |= YU_GPIO_CAUSE_RISE_EN_MASK(gs->gpio_int_bit); - writel(val, gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); + gpio_block = readl(yu_cause_gpio_param.io); + if (!(gpio_block & BIT(GPIO_BLOCK0)) && + !(gpio_block & BIT(GPIO_BLOCK16))) { + spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + return IRQ_NONE; } - val = readl(gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); - val |= YU_GPIO_CAUSE_FALL_EN_MASK(gs->gpio_int_bit); - writel(val, gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); + /* + * Check if the interrupt signaled by this yu gpio block is supported. + */ + gpio_pin = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CAUSE_EVTEN0); + if (!(gpio_pin & gs->gpio_int_mask)) { + spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); + return IRQ_NONE; + } - spin_unlock(&gs->gc.bgpio_lock); -} + /* + * Clear interrupt when done, otherwise, no further interrupt + * will be triggered. + */ + val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); + val |= gpio_pin; + writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); -static void mlxbf2_gpio_irq_enable(struct mlxbf2_gpio_context *gs) -{ - u32 val; + spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); - spin_lock(&gs->gc.bgpio_lock); + if (gpio_block & BIT(GPIO_BLOCK16)) { + if (gpio_pin & BIT(gs->low_pwr_pin)) + schedule_work(&gs->send_work); + } - /* - * Setting the priority for the GPIO interrupt enables the - * interrupt as well - */ - val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); - val |= YU_GPIO_CAUSE_OR_EVTEN0_MASK(gs->gpio_int_bit); - writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); + if (gpio_block & BIT(GPIO_BLOCK0)) { + if (gpio_pin & BIT(gs->rst_pin)) + emergency_restart(); + } - spin_unlock(&gs->gc.bgpio_lock); + return IRQ_HANDLED; } -static void mlxbf2_gpio_send_work(struct work_struct *work) +static void mlxbf2_gpio_irq_unmask(struct irq_data *data) { - struct mlxbf2_gpio_context *gs; - - gs = container_of(work, struct mlxbf2_gpio_context, send_work); +} - acpi_bus_generate_netlink_event("button/power.*", "Power Button", 0x80, 1); +static void mlxbf2_gpio_irq_mask(struct irq_data *data) +{ } -static irqreturn_t mlxbf2_gpio_irq_handler(int irq, void *ptr) +static int mlxbf2_gpio_init_hw(struct gpio_chip *gc) { - struct mlxbf2_gpio_context *gs = ptr; + struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc); unsigned long flags; u32 val; spin_lock_irqsave(&gs->gc.bgpio_lock, flags); - /* - * Check if this interrupt is for bit 0 of yu.gpio[16] - * or bit 7 of yu.gpio[0]. - * Return if it is not. - */ - val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CAUSE_EVTEN0); - if (!(val & YU_GPIO_CAUSE_OR_CAUSE_EVTEN0_MASK(gs->gpio_int_bit))) { - spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); - return IRQ_NONE; + /* Clear all interrupts */ + val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); + val |= gs->gpio_int_mask; + writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); + + if (gs->low_pwr_pin != MLXBF2_GPIO_MAX_PINS_PER_BLOCK) { + val = readl(gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); + val |= gs->gpio_int_mask; + writel(val, gs->gpio_io + YU_GPIO_CAUSE_RISE_EN); } + val = readl(gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); + val |= gs->gpio_int_mask; + writel(val, gs->gpio_io + YU_GPIO_CAUSE_FALL_EN); + /* - * Clear interrupt when done, otherwise, no further interrupt - * will be triggered. + * Setting the priority for the GPIO interrupt enables the + * interrupt as well */ - val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); - val |= YU_GPIO_CAUSE_OR_CLRCAUSE_MASK(gs->gpio_int_bit); - writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_CLRCAUSE); + val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); + val |= gs->gpio_int_mask; + writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); + spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); - schedule_work(&gs->send_work); + return 0; +} - return IRQ_HANDLED; +static void mlxbf2_gpio_disable_int(struct mlxbf2_gpio_context *gs) +{ + unsigned long flags; + u32 val; + + spin_lock_irqsave(&gs->gc.bgpio_lock, flags); + val = readl(gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); + val &= ~gs->gpio_int_mask; + writel(val, gs->gpio_io + YU_GPIO_CAUSE_OR_EVTEN0); + spin_unlock_irqrestore(&gs->gc.bgpio_lock, flags); } /* BlueField-2 GPIO driver initialization routine. */ @@ -377,18 +463,21 @@ mlxbf2_gpio_probe(struct platform_device *pdev) { struct mlxbf2_gpio_context *gs; struct device *dev = &pdev->dev; + struct gpio_irq_chip *girq; unsigned int low_pwr_pin; unsigned int rst_pin; struct gpio_chip *gc; struct resource *res; unsigned int npins; + const char *name; int ret, irq; + name = dev_name(dev); + gs = devm_kzalloc(dev, sizeof(*gs), GFP_KERNEL); if (!gs) return -ENOMEM; - spin_lock_init(&gs->gc.bgpio_lock); INIT_WORK(&gs->send_work, mlxbf2_gpio_send_work); /* YU GPIO block address */ @@ -406,6 +495,12 @@ mlxbf2_gpio_probe(struct platform_device *pdev) return ret; } + ret = mlxbf2_gpio_get_yu_cause_gpio_res(pdev); + if (ret) { + dev_err(dev, "Failed to get yu cause_gpio_arm.coalesce0 resource\n"); + return ret; + } + if (device_property_read_u32(dev, "npins", &npins)) npins = MLXBF2_GPIO_MAX_PINS_PER_BLOCK; @@ -419,55 +514,68 @@ mlxbf2_gpio_probe(struct platform_device *pdev) NULL, 0); + if (ret) { + dev_err(dev, "bgpio_init failed\n"); + return ret; + } + gc->direction_input = mlxbf2_gpio_direction_input; gc->direction_output = mlxbf2_gpio_direction_output; gc->ngpio = npins; gc->owner = THIS_MODULE; - ret = devm_gpiochip_add_data(dev, &gs->gc, gs); - if (ret) { - dev_err(dev, "Failed adding memory mapped gpiochip\n"); - return ret; - } - platform_set_drvdata(pdev, gs); - /* - * OCP3.0 supports the AUX power mode interrupt on bit 0 of yu.gpio[16]. - * BlueSphere and the PRIS boards support the rebooot interrupt on bit - * 7 of yu.gpio[0]. + * OCP3.0 supports the low power mode interrupt. */ ret = device_property_read_u32(dev, "low-pwr-pin", &low_pwr_pin); if (ret < 0) - low_pwr_pin = MAX_HOST_GPIOS + 1; + low_pwr_pin = MLXBF2_GPIO_MAX_PINS_PER_BLOCK; + /* + * BlueSphere and the PRIS boards support the reset interrupt. + */ ret = device_property_read_u32(dev, "rst-pin", &rst_pin); if (ret < 0) - rst_pin = MAX_HOST_GPIOS + 1; + rst_pin = MLXBF2_GPIO_MAX_PINS_PER_BLOCK; gs->low_pwr_pin = low_pwr_pin; gs->rst_pin = rst_pin; - - if ((low_pwr_pin == LOW_PWR_GPIO_PIN) || (rst_pin == RST_GPIO_PIN)) { - if (rst_pin == RST_GPIO_PIN) - gs->gpio_int_bit = YU_GPIO0_RST_BIT; - else - gs->gpio_int_bit = YU_GPIO16_LOW_PWR_BIT; + gs->gpio_int_mask = mlxbf2_gpio_get_int_mask(gs); + + if (gs->gpio_int_mask) { + gs->irq_chip.name = name; + gs->irq_chip.irq_mask = mlxbf2_gpio_irq_mask; + gs->irq_chip.irq_unmask = mlxbf2_gpio_irq_unmask; + + girq = &gs->gc.irq; + girq->chip = &gs->irq_chip; + /* This will let us handle the parent IRQ in the driver */ + girq->parent_handler = NULL; + girq->num_parents = 0; + girq->parents = NULL; + girq->default_type = IRQ_TYPE_NONE; + girq->handler = handle_simple_irq; + girq->init_hw = mlxbf2_gpio_init_hw; irq = platform_get_irq(pdev, 0); - /* - * For now, no need to check if interrupt was previously allocated - * by another gpio block. - */ + if (irq < 0) + return irq; ret = devm_request_irq(dev, irq, mlxbf2_gpio_irq_handler, - IRQF_ONESHOT | IRQF_SHARED | IRQF_PROBE_SHARED, dev_name(dev), gs); + IRQF_ONESHOT | IRQF_SHARED, name, gs); if (ret) { - dev_err(dev, "IRQ handler registering failed (%d)\n", ret); + dev_err(dev, "failed to request IRQ"); return ret; } - mlxbf2_gpio_irq_set_type(gs); - mlxbf2_gpio_irq_enable(gs); } + ret = devm_gpiochip_add_data(dev, &gs->gc, gs); + if (ret) { + dev_err(dev, "Failed adding memory mapped gpiochip\n"); + return ret; + } + platform_set_drvdata(pdev, gs); + + return 0; } @@ -477,8 +585,10 @@ mlxbf2_gpio_remove(struct platform_device *pdev) struct mlxbf2_gpio_context *gs; gs = platform_get_drvdata(pdev); - if ((gs->low_pwr_pin == LOW_PWR_GPIO_PIN) || (gs->rst_pin == RST_GPIO_PIN)) { - mlxbf2_gpio_irq_disable(gs); + + if ((gs->low_pwr_pin != MLXBF2_GPIO_MAX_PINS_PER_BLOCK) || + (gs->rst_pin != MLXBF2_GPIO_MAX_PINS_PER_BLOCK)) { + mlxbf2_gpio_disable_int(gs); flush_work(&gs->send_work); } @@ -512,7 +622,7 @@ static int mlxbf2_gpio_resume(struct platform_device *pdev) } #endif -static const struct acpi_device_id mlxbf2_gpio_acpi_match[] = { +static const struct acpi_device_id __maybe_unused mlxbf2_gpio_acpi_match[] = { { "MLNXBF22", 0 }, {}, }; @@ -534,5 +644,6 @@ static struct platform_driver mlxbf2_gpio_driver = { module_platform_driver(mlxbf2_gpio_driver); MODULE_DESCRIPTION("Mellanox BlueField-2 GPIO Driver"); -MODULE_AUTHOR("Mellanox Technologies"); +MODULE_AUTHOR("Asmaa Mnebhi "); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(DRV_VERSION); diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c index 92b798f8e73a..24a32ffee4e4 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_ethtool.c @@ -44,6 +44,43 @@ static void mlxbf_gige_get_ringparam(struct net_device *netdev, ering->tx_pending = priv->tx_q_entries; } +static int mlxbf_gige_set_ringparam(struct net_device *netdev, + struct ethtool_ringparam *ering) +{ + const struct net_device_ops *ops = netdev->netdev_ops; + struct mlxbf_gige *priv = netdev_priv(netdev); + int new_rx_q_entries, new_tx_q_entries; + + /* Device does not have separate queues for small/large frames */ + if (ering->rx_mini_pending || ering->rx_jumbo_pending) + return -EINVAL; + + /* Round up to supported values */ + new_rx_q_entries = roundup_pow_of_two(ering->rx_pending); + new_tx_q_entries = roundup_pow_of_two(ering->tx_pending); + + /* Check against min values, core checks against max values */ + if (new_tx_q_entries < MLXBF_GIGE_MIN_TXQ_SZ || + new_rx_q_entries < MLXBF_GIGE_MIN_RXQ_SZ) + return -EINVAL; + + /* If queue sizes did not change, exit now */ + if (new_rx_q_entries == priv->rx_q_entries && + new_tx_q_entries == priv->tx_q_entries) + return 0; + + if (netif_running(netdev)) + ops->ndo_stop(netdev); + + priv->rx_q_entries = new_rx_q_entries; + priv->tx_q_entries = new_tx_q_entries; + + if (netif_running(netdev)) + ops->ndo_open(netdev); + + return 0; +} + static const struct { const char string[ETH_GSTRING_LEN]; } mlxbf_gige_ethtool_stats_keys[] = { @@ -126,6 +163,7 @@ static void mlxbf_gige_get_pauseparam(struct net_device *netdev, const struct ethtool_ops mlxbf_gige_ethtool_ops = { .get_link = ethtool_op_get_link, .get_ringparam = mlxbf_gige_get_ringparam, + .set_ringparam = mlxbf_gige_set_ringparam, .get_regs_len = mlxbf_gige_get_regs_len, .get_regs = mlxbf_gige_get_regs, .get_strings = mlxbf_gige_get_strings, diff --git a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c index a0a059e0154f..7caa1ca4461f 100644 --- a/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +++ b/drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c @@ -20,6 +20,12 @@ #include "mlxbf_gige_regs.h" #define DRV_NAME "mlxbf_gige" +#define DRV_VERSION 1.24 + +/* This setting defines the version of the ACPI table + * content that is compatible with this driver version. + */ +#define MLXBF_GIGE_ACPI_TABLE_VERSION 2 /* Allocate SKB whose payload pointer aligns with the Bluefield * hardware DMA limitation, i.e. DMA operation can't cross @@ -276,10 +282,24 @@ static int mlxbf_gige_probe(struct platform_device *pdev) void __iomem *llu_base; void __iomem *plu_base; void __iomem *base; + u32 version; u64 control; int addr; int err; + version = 0; + err = device_property_read_u32(&pdev->dev, "version", &version); + if (err) { + dev_err(&pdev->dev, "ACPI table version not found\n"); + return -EINVAL; + } + + if (version != MLXBF_GIGE_ACPI_TABLE_VERSION) { + dev_err(&pdev->dev, "ACPI table version mismatch: expected %d found %d\n", + MLXBF_GIGE_ACPI_TABLE_VERSION, version); + return -EINVAL; + } + mac_res = platform_get_resource(pdev, IORESOURCE_MEM, MLXBF_GIGE_RES_MAC); if (!mac_res) return -ENXIO; @@ -450,3 +470,4 @@ MODULE_DESCRIPTION("Mellanox BlueField SoC Gigabit Ethernet Driver"); MODULE_AUTHOR("David Thompson "); MODULE_AUTHOR("Asmaa Mnebhi "); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_VERSION(__stringify(DRV_VERSION));