diff options
author | David S. Miller <davem@davemloft.net> | 2017-08-07 10:42:09 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-08-07 10:42:09 -0700 |
commit | fde6af4729b005dc9dc936b0ed9f1b27b5b2d0f4 (patch) | |
tree | fb52e170a7b2130b8a5266ac665d4314447fef95 /drivers | |
parent | 71feeef678056a640466a6d1faee3a7bcbbccab9 (diff) | |
parent | a8ffcc741acb3c7f3dcf4c7d001209aa0995a5f1 (diff) |
Merge tag 'mlx5-shared-2017-08-07' of git://git.kernel.org/pub/scm/linux/kernel/git/mellanox/linux
Saeed Mahameed says:
====================
mlx5-shared-2017-08-07
This series includes some mlx5 updates for both net-next and rdma trees.
From Saeed,
Core driver updates to allow selectively building the driver with
or without some large driver components, such as
- E-Switch (Ethernet SRIOV support).
- Multi-Physical Function Switch (MPFs) support.
For that we split E-Switch and MPFs functionalities into separate files.
From Erez,
Delay mlx5_core events when mlx5 interfaces, namely mlx5_ib, registration
is taking place and until it completes.
From Rabie,
Increase the maximum supported flow counters.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers')
149 files changed, 1804 insertions, 1398 deletions
diff --git a/drivers/acpi/acpi_apd.c b/drivers/acpi/acpi_apd.c index fc6c416f8724..d5999eb41c00 100644 --- a/drivers/acpi/acpi_apd.c +++ b/drivers/acpi/acpi_apd.c @@ -180,8 +180,8 @@ static const struct acpi_device_id acpi_apd_device_ids[] = { { "APMC0D0F", APD_ADDR(xgene_i2c_desc) }, { "BRCM900D", APD_ADDR(vulcan_spi_desc) }, { "CAV900D", APD_ADDR(vulcan_spi_desc) }, - { "HISI0A21", APD_ADDR(hip07_i2c_desc) }, - { "HISI0A22", APD_ADDR(hip08_i2c_desc) }, + { "HISI02A1", APD_ADDR(hip07_i2c_desc) }, + { "HISI02A2", APD_ADDR(hip08_i2c_desc) }, #endif { } }; diff --git a/drivers/acpi/acpi_lpss.c b/drivers/acpi/acpi_lpss.c index e51a1e98e62f..f88caf5aab76 100644 --- a/drivers/acpi/acpi_lpss.c +++ b/drivers/acpi/acpi_lpss.c @@ -85,6 +85,7 @@ static const struct lpss_device_desc lpss_dma_desc = { }; struct lpss_private_data { + struct acpi_device *adev; void __iomem *mmio_base; resource_size_t mmio_size; unsigned int fixed_clk_rate; @@ -155,6 +156,12 @@ static struct pwm_lookup byt_pwm_lookup[] = { static void byt_pwm_setup(struct lpss_private_data *pdata) { + struct acpi_device *adev = pdata->adev; + + /* Only call pwm_add_table for the first PWM controller */ + if (!adev->pnp.unique_id || strcmp(adev->pnp.unique_id, "1")) + return; + if (!acpi_dev_present("INT33FD", NULL, -1)) pwm_add_table(byt_pwm_lookup, ARRAY_SIZE(byt_pwm_lookup)); } @@ -180,6 +187,12 @@ static struct pwm_lookup bsw_pwm_lookup[] = { static void bsw_pwm_setup(struct lpss_private_data *pdata) { + struct acpi_device *adev = pdata->adev; + + /* Only call pwm_add_table for the first PWM controller */ + if (!adev->pnp.unique_id || strcmp(adev->pnp.unique_id, "1")) + return; + pwm_add_table(bsw_pwm_lookup, ARRAY_SIZE(bsw_pwm_lookup)); } @@ -456,6 +469,7 @@ static int acpi_lpss_create_device(struct acpi_device *adev, goto err_out; } + pdata->adev = adev; pdata->dev_desc = dev_desc; if (dev_desc->setup) diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c index 8c4e0a18460a..bf22c29d2517 100644 --- a/drivers/acpi/acpi_watchdog.c +++ b/drivers/acpi/acpi_watchdog.c @@ -86,7 +86,12 @@ void __init acpi_watchdog_init(void) found = false; resource_list_for_each_entry(rentry, &resource_list) { - if (resource_contains(rentry->res, &res)) { + if (rentry->res->flags == res.flags && + resource_overlaps(rentry->res, &res)) { + if (res.start < rentry->res->start) + rentry->res->start = res.start; + if (res.end > rentry->res->end) + rentry->res->end = res.end; found = true; break; } diff --git a/drivers/bus/uniphier-system-bus.c b/drivers/bus/uniphier-system-bus.c index 1e6e0269edcc..f76be6bd6eb3 100644 --- a/drivers/bus/uniphier-system-bus.c +++ b/drivers/bus/uniphier-system-bus.c @@ -256,10 +256,23 @@ static int uniphier_system_bus_probe(struct platform_device *pdev) uniphier_system_bus_set_reg(priv); + platform_set_drvdata(pdev, priv); + /* Now, the bus is configured. Populate platform_devices below it */ return of_platform_default_populate(dev->of_node, NULL, dev); } +static int __maybe_unused uniphier_system_bus_resume(struct device *dev) +{ + uniphier_system_bus_set_reg(dev_get_drvdata(dev)); + + return 0; +} + +static const struct dev_pm_ops uniphier_system_bus_pm_ops = { + SET_SYSTEM_SLEEP_PM_OPS(NULL, uniphier_system_bus_resume) +}; + static const struct of_device_id uniphier_system_bus_match[] = { { .compatible = "socionext,uniphier-system-bus" }, { /* sentinel */ } @@ -271,6 +284,7 @@ static struct platform_driver uniphier_system_bus_driver = { .driver = { .name = "uniphier-system-bus", .of_match_table = uniphier_system_bus_match, + .pm = &uniphier_system_bus_pm_ops, }, }; module_platform_driver(uniphier_system_bus_driver); diff --git a/drivers/clk/clk-gemini.c b/drivers/clk/clk-gemini.c index c391a49aaaff..b4cf2f699a21 100644 --- a/drivers/clk/clk-gemini.c +++ b/drivers/clk/clk-gemini.c @@ -237,6 +237,18 @@ static int gemini_reset(struct reset_controller_dev *rcdev, BIT(GEMINI_RESET_CPU1) | BIT(id)); } +static int gemini_reset_assert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return 0; +} + +static int gemini_reset_deassert(struct reset_controller_dev *rcdev, + unsigned long id) +{ + return 0; +} + static int gemini_reset_status(struct reset_controller_dev *rcdev, unsigned long id) { @@ -253,6 +265,8 @@ static int gemini_reset_status(struct reset_controller_dev *rcdev, static const struct reset_control_ops gemini_reset_ops = { .reset = gemini_reset, + .assert = gemini_reset_assert, + .deassert = gemini_reset_deassert, .status = gemini_reset_status, }; diff --git a/drivers/clk/keystone/sci-clk.c b/drivers/clk/keystone/sci-clk.c index 43b0f2f08df2..9cdf9d5050ac 100644 --- a/drivers/clk/keystone/sci-clk.c +++ b/drivers/clk/keystone/sci-clk.c @@ -22,6 +22,7 @@ #include <linux/platform_device.h> #include <linux/slab.h> #include <linux/soc/ti/ti_sci_protocol.h> +#include <linux/bsearch.h> #define SCI_CLK_SSC_ENABLE BIT(0) #define SCI_CLK_ALLOW_FREQ_CHANGE BIT(1) @@ -44,6 +45,7 @@ struct sci_clk_data { * @dev: Device pointer for the clock provider * @clk_data: Clock data * @clocks: Clocks array for this device + * @num_clocks: Total number of clocks for this provider */ struct sci_clk_provider { const struct ti_sci_handle *sci; @@ -51,6 +53,7 @@ struct sci_clk_provider { struct device *dev; const struct sci_clk_data *clk_data; struct clk_hw **clocks; + int num_clocks; }; /** @@ -58,7 +61,6 @@ struct sci_clk_provider { * @hw: Hardware clock cookie for common clock framework * @dev_id: Device index * @clk_id: Clock index - * @node: Clocks list link * @provider: Master clock provider * @flags: Flags for the clock */ @@ -66,7 +68,6 @@ struct sci_clk { struct clk_hw hw; u16 dev_id; u8 clk_id; - struct list_head node; struct sci_clk_provider *provider; u8 flags; }; @@ -367,6 +368,19 @@ err: return &sci_clk->hw; } +static int _cmp_sci_clk(const void *a, const void *b) +{ + const struct sci_clk *ca = a; + const struct sci_clk *cb = *(struct sci_clk **)b; + + if (ca->dev_id == cb->dev_id && ca->clk_id == cb->clk_id) + return 0; + if (ca->dev_id > cb->dev_id || + (ca->dev_id == cb->dev_id && ca->clk_id > cb->clk_id)) + return 1; + return -1; +} + /** * sci_clk_get - Xlate function for getting clock handles * @clkspec: device tree clock specifier @@ -380,29 +394,22 @@ err: static struct clk_hw *sci_clk_get(struct of_phandle_args *clkspec, void *data) { struct sci_clk_provider *provider = data; - u16 dev_id; - u8 clk_id; - const struct sci_clk_data *clks = provider->clk_data; - struct clk_hw **clocks = provider->clocks; + struct sci_clk **clk; + struct sci_clk key; if (clkspec->args_count != 2) return ERR_PTR(-EINVAL); - dev_id = clkspec->args[0]; - clk_id = clkspec->args[1]; + key.dev_id = clkspec->args[0]; + key.clk_id = clkspec->args[1]; - while (clks->num_clks) { - if (clks->dev == dev_id) { - if (clk_id >= clks->num_clks) - return ERR_PTR(-EINVAL); - - return clocks[clk_id]; - } + clk = bsearch(&key, provider->clocks, provider->num_clocks, + sizeof(clk), _cmp_sci_clk); - clks++; - } + if (!clk) + return ERR_PTR(-ENODEV); - return ERR_PTR(-ENODEV); + return &(*clk)->hw; } static int ti_sci_init_clocks(struct sci_clk_provider *p) @@ -410,18 +417,29 @@ static int ti_sci_init_clocks(struct sci_clk_provider *p) const struct sci_clk_data *data = p->clk_data; struct clk_hw *hw; int i; + int num_clks = 0; while (data->num_clks) { - p->clocks = devm_kcalloc(p->dev, data->num_clks, - sizeof(struct sci_clk), - GFP_KERNEL); - if (!p->clocks) - return -ENOMEM; + num_clks += data->num_clks; + data++; + } + p->num_clocks = num_clks; + + p->clocks = devm_kcalloc(p->dev, num_clks, sizeof(struct sci_clk), + GFP_KERNEL); + if (!p->clocks) + return -ENOMEM; + + num_clks = 0; + + data = p->clk_data; + + while (data->num_clks) { for (i = 0; i < data->num_clks; i++) { hw = _sci_clk_build(p, data->dev, i); if (!IS_ERR(hw)) { - p->clocks[i] = hw; + p->clocks[num_clks++] = hw; continue; } diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c index 39eab69fe51a..44a5a535ca63 100644 --- a/drivers/clk/meson/clk-mpll.c +++ b/drivers/clk/meson/clk-mpll.c @@ -161,6 +161,13 @@ static int mpll_set_rate(struct clk_hw *hw, reg = PARM_SET(p->width, p->shift, reg, 1); writel(reg, mpll->base + p->reg_off); + p = &mpll->ssen; + if (p->width != 0) { + reg = readl(mpll->base + p->reg_off); + reg = PARM_SET(p->width, p->shift, reg, 1); + writel(reg, mpll->base + p->reg_off); + } + p = &mpll->n2; reg = readl(mpll->base + p->reg_off); reg = PARM_SET(p->width, p->shift, reg, n2); diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h index d6feafe8bd6c..1629da9b4141 100644 --- a/drivers/clk/meson/clkc.h +++ b/drivers/clk/meson/clkc.h @@ -118,6 +118,7 @@ struct meson_clk_mpll { struct parm sdm_en; struct parm n2; struct parm en; + struct parm ssen; spinlock_t *lock; }; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index a897ea45327c..a7ea5f3da89d 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -528,6 +528,11 @@ static struct meson_clk_mpll gxbb_mpll0 = { .shift = 14, .width = 1, }, + .ssen = { + .reg_off = HHI_MPLL_CNTL, + .shift = 25, + .width = 1, + }, .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll0", diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index bb3f1de876b1..6ec512ad2598 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -267,6 +267,11 @@ static struct meson_clk_mpll meson8b_mpll0 = { .shift = 14, .width = 1, }, + .ssen = { + .reg_off = HHI_MPLL_CNTL, + .shift = 25, + .width = 1, + }, .lock = &clk_lock, .hw.init = &(struct clk_init_data){ .name = "mpll0", diff --git a/drivers/clk/samsung/clk-exynos5420.c b/drivers/clk/samsung/clk-exynos5420.c index 0748a0b333c5..9a6476aa7d81 100644 --- a/drivers/clk/samsung/clk-exynos5420.c +++ b/drivers/clk/samsung/clk-exynos5420.c @@ -1283,16 +1283,16 @@ static const struct samsung_pll_rate_table exynos5420_pll2550x_24mhz_tbl[] __ini static const struct samsung_pll_rate_table exynos5420_epll_24mhz_tbl[] = { PLL_36XX_RATE(600000000U, 100, 2, 1, 0), PLL_36XX_RATE(400000000U, 200, 3, 2, 0), - PLL_36XX_RATE(393216000U, 197, 3, 2, 25690), - PLL_36XX_RATE(361267200U, 301, 5, 2, 3671), + PLL_36XX_RATE(393216003U, 197, 3, 2, -25690), + PLL_36XX_RATE(361267218U, 301, 5, 2, 3671), PLL_36XX_RATE(200000000U, 200, 3, 3, 0), - PLL_36XX_RATE(196608000U, 197, 3, 3, -25690), - PLL_36XX_RATE(180633600U, 301, 5, 3, 3671), - PLL_36XX_RATE(131072000U, 131, 3, 3, 4719), + PLL_36XX_RATE(196608001U, 197, 3, 3, -25690), + PLL_36XX_RATE(180633609U, 301, 5, 3, 3671), + PLL_36XX_RATE(131072006U, 131, 3, 3, 4719), PLL_36XX_RATE(100000000U, 200, 3, 4, 0), - PLL_36XX_RATE(65536000U, 131, 3, 4, 4719), - PLL_36XX_RATE(49152000U, 197, 3, 5, 25690), - PLL_36XX_RATE(32768000U, 131, 3, 5, 4719), + PLL_36XX_RATE( 65536003U, 131, 3, 4, 4719), + PLL_36XX_RATE( 49152000U, 197, 3, 5, -25690), + PLL_36XX_RATE( 32768001U, 131, 3, 5, 4719), }; static struct samsung_pll_clock exynos5x_plls[nr_plls] __initdata = { diff --git a/drivers/clk/sunxi-ng/ccu-sun5i.c b/drivers/clk/sunxi-ng/ccu-sun5i.c index 5372bf8be5e6..31d7ffda9aab 100644 --- a/drivers/clk/sunxi-ng/ccu-sun5i.c +++ b/drivers/clk/sunxi-ng/ccu-sun5i.c @@ -184,7 +184,7 @@ static struct ccu_mux cpu_clk = { .hw.init = CLK_HW_INIT_PARENTS("cpu", cpu_parents, &ccu_mux_ops, - CLK_IS_CRITICAL), + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), } }; diff --git a/drivers/clk/x86/clk-pmc-atom.c b/drivers/clk/x86/clk-pmc-atom.c index f99abc1106f0..08ef69945ffb 100644 --- a/drivers/clk/x86/clk-pmc-atom.c +++ b/drivers/clk/x86/clk-pmc-atom.c @@ -186,6 +186,13 @@ static struct clk_plt *plt_clk_register(struct platform_device *pdev, int id, pclk->reg = base + PMC_CLK_CTL_OFFSET + id * PMC_CLK_CTL_SIZE; spin_lock_init(&pclk->lock); + /* + * If the clock was already enabled by the firmware mark it as critical + * to avoid it being gated by the clock framework if no driver owns it. + */ + if (plt_clk_is_enabled(&pclk->hw)) + init.flags |= CLK_IS_CRITICAL; + ret = devm_clk_hw_register(&pdev->dev, &pclk->hw); if (ret) { pclk = ERR_PTR(ret); diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 6cd503525638..0566455f233e 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -1922,13 +1922,6 @@ static int intel_pstate_init_cpu(unsigned int cpunum) return 0; } -static unsigned int intel_pstate_get(unsigned int cpu_num) -{ - struct cpudata *cpu = all_cpu_data[cpu_num]; - - return cpu ? get_avg_frequency(cpu) : 0; -} - static void intel_pstate_set_update_util_hook(unsigned int cpu_num) { struct cpudata *cpu = all_cpu_data[cpu_num]; @@ -2169,7 +2162,6 @@ static struct cpufreq_driver intel_pstate = { .setpolicy = intel_pstate_set_policy, .suspend = intel_pstate_hwp_save_state, .resume = intel_pstate_resume, - .get = intel_pstate_get, .init = intel_pstate_cpu_init, .exit = intel_pstate_cpu_exit, .stop_cpu = intel_pstate_stop_cpu, diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f235eae04c16..461d6fc3688b 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -504,6 +504,7 @@ config GPIO_XGENE_SB depends on ARCH_XGENE && OF_GPIO select GPIO_GENERIC select GPIOLIB_IRQCHIP + select IRQ_DOMAIN_HIERARCHY help This driver supports the GPIO block within the APM X-Gene Standby Domain. Say yes here to enable the GPIO functionality. diff --git a/drivers/gpio/gpio-exar.c b/drivers/gpio/gpio-exar.c index fb8d304cfa17..0ecd2369c2ca 100644 --- a/drivers/gpio/gpio-exar.c +++ b/drivers/gpio/gpio-exar.c @@ -132,7 +132,7 @@ static int gpio_exar_probe(struct platform_device *pdev) if (!p) return -ENOMEM; - ret = device_property_read_u32(&pdev->dev, "linux,first-pin", + ret = device_property_read_u32(&pdev->dev, "exar,first-pin", &first_pin); if (ret) return ret; diff --git a/drivers/gpio/gpio-lp87565.c b/drivers/gpio/gpio-lp87565.c index 6313c50bb91b..a121c8f10610 100644 --- a/drivers/gpio/gpio-lp87565.c +++ b/drivers/gpio/gpio-lp87565.c @@ -26,6 +26,27 @@ struct lp87565_gpio { struct regmap *map; }; +static int lp87565_gpio_get(struct gpio_chip *chip, unsigned int offset) +{ + struct lp87565_gpio *gpio = gpiochip_get_data(chip); + int ret, val; + + ret = regmap_read(gpio->map, LP87565_REG_GPIO_IN, &val); + if (ret < 0) + return ret; + + return !!(val & BIT(offset)); +} + +static void lp87565_gpio_set(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct lp87565_gpio *gpio = gpiochip_get_data(chip); + + regmap_update_bits(gpio->map, LP87565_REG_GPIO_OUT, + BIT(offset), value ? BIT(offset) : 0); +} + static int lp87565_gpio_get_direction(struct gpio_chip *chip, unsigned int offset) { @@ -54,30 +75,11 @@ static int lp87565_gpio_direction_output(struct gpio_chip *chip, { struct lp87565_gpio *gpio = gpiochip_get_data(chip); + lp87565_gpio_set(chip, offset, value); + return regmap_update_bits(gpio->map, LP87565_REG_GPIO_CONFIG, - BIT(offset), !value ? BIT(offset) : 0); -} - -static int lp87565_gpio_get(struct gpio_chip *chip, unsigned int offset) -{ - struct lp87565_gpio *gpio = gpiochip_get_data(chip); - int ret, val; - - ret = regmap_read(gpio->map, LP87565_REG_GPIO_IN, &val); - if (ret < 0) - return ret; - - return !!(val & BIT(offset)); -} - -static void lp87565_gpio_set(struct gpio_chip *chip, unsigned int offset, - int value) -{ - struct lp87565_gpio *gpio = gpiochip_get_data(chip); - - regmap_update_bits(gpio->map, LP87565_REG_GPIO_OUT, - BIT(offset), value ? BIT(offset) : 0); + BIT(offset), BIT(offset)); } static int lp87565_gpio_request(struct gpio_chip *gc, unsigned int offset) diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c index 3abea3f0b307..92692251ade1 100644 --- a/drivers/gpio/gpio-mxc.c +++ b/drivers/gpio/gpio-mxc.c @@ -424,6 +424,9 @@ static int mxc_gpio_probe(struct platform_device *pdev) return PTR_ERR(port->base); port->irq_high = platform_get_irq(pdev, 1); + if (port->irq_high < 0) + port->irq_high = 0; + port->irq = platform_get_irq(pdev, 0); if (port->irq < 0) return port->irq; diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 88529d3c06c9..506c6a67c5fc 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c @@ -360,7 +360,7 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc) { int port; int pin; - int unmasked = 0; + bool unmasked = false; int gpio; u32 lvl; unsigned long sta; @@ -384,8 +384,8 @@ static void tegra_gpio_irq_handler(struct irq_desc *desc) * before executing the handler so that we don't * miss edges */ - if (lvl & (0x100 << pin)) { - unmasked = 1; + if (!unmasked && lvl & (0x100 << pin)) { + unmasked = true; chained_irq_exit(chip, desc); } diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 9568708a550b..cd003b74512f 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -704,24 +704,23 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p) { struct lineevent_state *le = p; struct gpioevent_data ge; - int ret; + int ret, level; ge.timestamp = ktime_get_real_ns(); + level = gpiod_get_value_cansleep(le->desc); if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) { - int level = gpiod_get_value_cansleep(le->desc); - if (level) /* Emit low-to-high event */ ge.id = GPIOEVENT_EVENT_RISING_EDGE; else /* Emit high-to-low event */ ge.id = GPIOEVENT_EVENT_FALLING_EDGE; - } else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE) { + } else if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE && level) { /* Emit low-to-high event */ ge.id = GPIOEVENT_EVENT_RISING_EDGE; - } else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) { + } else if (le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE && !level) { /* Emit high-to-low event */ ge.id = GPIOEVENT_EVENT_FALLING_EDGE; } else { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c index 38f739fb727b..6558a3ed57a7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c @@ -359,7 +359,7 @@ void amdgpu_mn_unregister(struct amdgpu_bo *bo) head = bo->mn_list.next; bo->mn = NULL; - list_del(&bo->mn_list); + list_del_init(&bo->mn_list); if (list_empty(head)) { struct amdgpu_mn_node *node; diff --git a/drivers/gpu/drm/amd/amdgpu/clearstate_gfx9.h b/drivers/gpu/drm/amd/amdgpu/clearstate_gfx9.h index 18fd01f3e4b2..003a131bad47 100644 --- a/drivers/gpu/drm/amd/amdgpu/clearstate_gfx9.h +++ b/drivers/gpu/drm/amd/amdgpu/clearstate_gfx9.h @@ -1,24 +1,25 @@ - /* -*************************************************************************************************** -* -* Trade secret of Advanced Micro Devices, Inc. -* Copyright (c) 2010 Advanced Micro Devices, Inc. (unpublished) -* -* All rights reserved. This notice is intended as a precaution against inadvertent publication and -* does not imply publication or any waiver of confidentiality. The year included in the foregoing -* notice is the year of creation of the work. -* -*************************************************************************************************** -*/ -/** -*************************************************************************************************** -* @brief gfx9 Clearstate Definitions -*************************************************************************************************** -* -* Do not edit! This is a machine-generated file! -* -*/ + * Copyright 2017 Advanced Micro Devices, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ static const unsigned int gfx9_SECT_CONTEXT_def_1[] = { diff --git a/drivers/gpu/drm/amd/amdgpu/si.c b/drivers/gpu/drm/amd/amdgpu/si.c index f45fb0f022b3..4267fa417997 100644 --- a/drivers/gpu/drm/amd/amdgpu/si.c +++ b/drivers/gpu/drm/amd/amdgpu/si.c @@ -1385,6 +1385,7 @@ static void si_init_golden_registers(struct amdgpu_device *adev) amdgpu_program_register_sequence(adev, pitcairn_mgcg_cgcg_init, (const u32)ARRAY_SIZE(pitcairn_mgcg_cgcg_init)); + break; case CHIP_VERDE: amdgpu_program_register_sequence(adev, verde_golden_registers, @@ -1409,6 +1410,7 @@ static void si_init_golden_registers(struct amdgpu_device *adev) amdgpu_program_register_sequence(adev, oland_mgcg_cgcg_init, (const u32)ARRAY_SIZE(oland_mgcg_cgcg_init)); + break; case CHIP_HAINAN: amdgpu_program_register_sequence(adev, hainan_golden_registers, diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 688e77576e5a..354cbd6392cd 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c @@ -4452,6 +4452,7 @@ static int amd_ir_set_vcpu_affinity(struct irq_data *data, void *vcpu_info) /* Setting */ irte->hi.fields.ga_root_ptr = (pi_data->base >> 12); irte->hi.fields.vector = vcpu_pi_info->vector; + irte->lo.fields_vapic.ga_log_intr = 1; irte->lo.fields_vapic.guest_mode = 1; irte->lo.fields_vapic.ga_tag = pi_data->ga_tag; diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 5cc597b383c7..372303700566 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -2440,11 +2440,11 @@ static int __init state_next(void) break; case IOMMU_ACPI_FINISHED: early_enable_iommus(); - register_syscore_ops(&amd_iommu_syscore_ops); x86_platform.iommu_shutdown = disable_iommus; init_state = IOMMU_ENABLED; break; case IOMMU_ENABLED: + register_syscore_ops(&amd_iommu_syscore_ops); ret = amd_iommu_init_pci(); init_state = ret ? IOMMU_INIT_ERROR : IOMMU_PCI_INIT; enable_iommus_v2(); diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index bc89b4d6c043..b97188acc4f1 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -400,6 +400,8 @@ struct arm_smmu_device { u32 cavium_id_base; /* Specific to Cavium */ + spinlock_t global_sync_lock; + /* IOMMU core code handle */ struct iommu_device iommu; }; @@ -436,7 +438,7 @@ struct arm_smmu_domain { struct arm_smmu_cfg cfg; enum arm_smmu_domain_stage stage; struct mutex init_mutex; /* Protects smmu pointer */ - spinlock_t cb_lock; /* Serialises ATS1* ops */ + spinlock_t cb_lock; /* Serialises ATS1* ops and TLB syncs */ struct iommu_domain domain; }; @@ -602,9 +604,12 @@ static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu, static void arm_smmu_tlb_sync_global(struct arm_smmu_device *smmu) { void __iomem *base = ARM_SMMU_GR0(smmu); + unsigned long flags; + spin_lock_irqsave(&smmu->global_sync_lock, flags); __arm_smmu_tlb_sync(smmu, base + ARM_SMMU_GR0_sTLBGSYNC, base + ARM_SMMU_GR0_sTLBGSTATUS); + spin_unlock_irqrestore(&smmu->global_sync_lock, flags); } static void arm_smmu_tlb_sync_context(void *cookie) @@ -612,9 +617,12 @@ static void arm_smmu_tlb_sync_context(void *cookie) struct arm_smmu_domain *smmu_domain = cookie; struct arm_smmu_device *smmu = smmu_domain->smmu; void __iomem *base = ARM_SMMU_CB(smmu, smmu_domain->cfg.cbndx); + unsigned long flags; + spin_lock_irqsave(&smmu_domain->cb_lock, flags); __arm_smmu_tlb_sync(smmu, base + ARM_SMMU_CB_TLBSYNC, base + ARM_SMMU_CB_TLBSTATUS); + spin_unlock_irqrestore(&smmu_domain->cb_lock, flags); } static void arm_smmu_tlb_sync_vmid(void *cookie) @@ -1511,7 +1519,6 @@ static int arm_smmu_add_device(struct device *dev) if (using_legacy_binding) { ret = arm_smmu_register_legacy_master(dev, &smmu); - fwspec = dev->iommu_fwspec; if (ret) goto out_free; } else if (fwspec && fwspec->ops == &arm_smmu_ops) { @@ -1550,15 +1557,15 @@ static int arm_smmu_add_device(struct device *dev) ret = arm_smmu_master_alloc_smes(dev); if (ret) - goto out_free; + goto out_cfg_free; iommu_device_link(&smmu->iommu, dev); return 0; +out_cfg_free: + kfree(cfg); out_free: - if (fwspec) - kfree(fwspec->iommu_priv); iommu_fwspec_free(dev); return ret; } @@ -1925,6 +1932,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) smmu->num_mapping_groups = size; mutex_init(&smmu->stream_map_mutex); + spin_lock_init(&smmu->global_sync_lock); if (smmu->version < ARM_SMMU_V2 || !(id & ID0_PTFS_NO_AARCH32)) { smmu->features |= ARM_SMMU_FEAT_FMT_AARCH32_L; diff --git a/drivers/iommu/io-pgtable-arm-v7s.c b/drivers/iommu/io-pgtable-arm-v7s.c index af330f513653..d665d0dc16e8 100644 --- a/drivers/iommu/io-pgtable-arm-v7s.c +++ b/drivers/iommu/io-pgtable-arm-v7s.c @@ -479,6 +479,9 @@ static int arm_v7s_map(struct io_pgtable_ops *ops, unsigned long iova, if (!(prot & (IOMMU_READ | IOMMU_WRITE))) return 0; + if (WARN_ON(upper_32_bits(iova) || upper_32_bits(paddr))) + return -ERANGE; + ret = __arm_v7s_map(data, iova, paddr, size, prot, 1, data->pgd); /* * Synchronise all PTE updates for the new mapping before there's @@ -659,6 +662,9 @@ static int arm_v7s_unmap(struct io_pgtable_ops *ops, unsigned long iova, struct arm_v7s_io_pgtable *data = io_pgtable_ops_to_data(ops); size_t unmapped; + if (WARN_ON(upper_32_bits(iova))) + return 0; + unmapped = __arm_v7s_unmap(data, iova, size, 1, data->pgd); if (unmapped) io_pgtable_tlb_sync(&data->iop); diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c index b182039862c5..e8018a308868 100644 --- a/drivers/iommu/io-pgtable-arm.c +++ b/drivers/iommu/io-pgtable-arm.c @@ -452,6 +452,10 @@ static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova, if (!(iommu_prot & (IOMMU_READ | IOMMU_WRITE))) return 0; + if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias) || + paddr >= (1ULL << data->iop.cfg.oas))) + return -ERANGE; + prot = arm_lpae_prot_to_pte(data, iommu_prot); ret = __arm_lpae_map(data, iova, paddr, size, prot, lvl, ptep); /* @@ -610,6 +614,9 @@ static int arm_lpae_unmap(struct io_pgtable_ops *ops, unsigned long iova, arm_lpae_iopte *ptep = data->pgd; int lvl = ARM_LPAE_START_LVL(data); + if (WARN_ON(iova >= (1ULL << data->iop.cfg.ias))) + return 0; + unmapped = __arm_lpae_unmap(data, iova, size, lvl, ptep); if (unmapped) io_pgtable_tlb_sync(&data->iop); diff --git a/drivers/iommu/io-pgtable.h b/drivers/iommu/io-pgtable.h index 524263a7ae6f..a3e667077b14 100644 --- a/drivers/iommu/io-pgtable.h +++ b/drivers/iommu/io-pgtable.h @@ -158,14 +158,12 @@ void free_io_pgtable_ops(struct io_pgtable_ops *ops); * @fmt: The page table format. * @cookie: An opaque token provided by the IOMMU driver and passed back to * any callback routines. - * @tlb_sync_pending: Private flag for optimising out redundant syncs. * @cfg: A copy of the page table configuration. * @ops: The page table operations in use for this set of page tables. */ struct io_pgtable { enum io_pgtable_fmt fmt; void *cookie; - bool tlb_sync_pending; struct io_pgtable_cfg cfg; struct io_pgtable_ops ops; }; @@ -175,22 +173,17 @@ struct io_pgtable { static inline void io_pgtable_tlb_flush_all(struct io_pgtable *iop) { iop->cfg.tlb->tlb_flush_all(iop->cookie); - iop->tlb_sync_pending = true; } static inline void io_pgtable_tlb_add_flush(struct io_pgtable *iop, unsigned long iova, size_t size, size_t granule, bool leaf) { iop->cfg.tlb->tlb_add_flush(iova, size, granule, leaf, iop->cookie); - iop->tlb_sync_pending = true; } static inline void io_pgtable_tlb_sync(struct io_pgtable *iop) { - if (iop->tlb_sync_pending) { - iop->cfg.tlb->tlb_sync(iop->cookie); - iop->tlb_sync_pending = false; - } + iop->cfg.tlb->tlb_sync(iop->cookie); } /** diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c index 5d14cd15198d..91c6d367ab35 100644 --- a/drivers/iommu/mtk_iommu.c +++ b/drivers/iommu/mtk_iommu.c @@ -129,6 +129,7 @@ static void mtk_iommu_tlb_add_flush_nosync(unsigned long iova, size_t size, writel_relaxed(iova, data->base + REG_MMU_INVLD_START_A); writel_relaxed(iova + size - 1, data->base + REG_MMU_INVLD_END_A); writel_relaxed(F_MMU_INV_RANGE, data->base + REG_MMU_INVALIDATE); + data->tlb_flush_active = true; } static void mtk_iommu_tlb_sync(void *cookie) @@ -137,6 +138,10 @@ static void mtk_iommu_tlb_sync(void *cookie) int ret; u32 tmp; + /* Avoid timing out if there's nothing to wait for */ + if (!data->tlb_flush_active) + return; + ret = readl_poll_timeout_atomic(data->base + REG_MMU_CPE_DONE, tmp, tmp != 0, 10, 100000); if (ret) { @@ -146,6 +151,7 @@ static void mtk_iommu_tlb_sync(void *cookie) } /* Clear the CPE status */ writel_relaxed(0, data->base + REG_MMU_CPE_DONE); + data->tlb_flush_active = false; } static const struct iommu_gather_ops mtk_iommu_gather_ops = { diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h index 2a28eadeea0e..c06cc91b5d9a 100644 --- a/drivers/iommu/mtk_iommu.h +++ b/drivers/iommu/mtk_iommu.h @@ -47,6 +47,7 @@ struct mtk_iommu_data { struct iommu_group *m4u_group; struct mtk_smi_iommu smi_imu; /* SMI larb iommu info */ bool enable_4GB; + bool tlb_flush_active; struct iommu_device iommu; }; diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 89b09c51ab7c..38a5bb764c7b 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -1376,6 +1376,7 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) if (arg) { if (copy_from_user(bname, argp, sizeof(bname) - 1)) return -EFAULT; + bname[sizeof(bname)-1] = 0; } else return -EINVAL; ret = mutex_lock_interruptible(&dev->mtx); diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c index c151c6daa67e..f63a110b7bcb 100644 --- a/drivers/isdn/i4l/isdn_net.c +++ b/drivers/isdn/i4l/isdn_net.c @@ -2611,10 +2611,9 @@ isdn_net_newslave(char *parm) char newname[10]; if (p) { - /* Slave-Name MUST not be empty */ - if (!strlen(p + 1)) + /* Slave-Name MUST not be empty or overflow 'newname' */ + if (strscpy(newname, p + 1, sizeof(newname)) <= 0) return NULL; - strcpy(newname, p + 1); *p = 0; /* Master must already exist */ if (!(n = isdn_net_findif(parm))) diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c index ac91fd0d62c6..cbca5e51b975 100644 --- a/drivers/mailbox/pcc.c +++ b/drivers/mailbox/pcc.c @@ -92,7 +92,7 @@ static struct mbox_controller pcc_mbox_ctrl = {}; */ static struct mbox_chan *get_pcc_channel(int id) { - if (id < 0 || id > pcc_mbox_ctrl.num_chans) + if (id < 0 || id >= pcc_mbox_ctrl.num_chans) return ERR_PTR(-ENOENT); return &pcc_mbox_channels[id]; diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index bf45977b2823..d596b601ff42 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -559,7 +559,7 @@ EXPORT_SYMBOL_GPL(cec_transmit_done); void cec_transmit_attempt_done(struct cec_adapter *adap, u8 status) { - switch (status) { + switch (status & ~CEC_TX_STATUS_MAX_RETRIES) { case CEC_TX_STATUS_OK: cec_transmit_done(adap, status, 0, 0, 0, 0); return; diff --git a/drivers/media/cec/cec-notifier.c b/drivers/media/cec/cec-notifier.c index 74dc1c32080e..08b619d0ea1e 100644 --- a/drivers/media/cec/cec-notifier.c +++ b/drivers/media/cec/cec-notifier.c @@ -87,6 +87,9 @@ EXPORT_SYMBOL_GPL(cec_notifier_put); void cec_notifier_set_phys_addr(struct cec_notifier *n, u16 pa) { + if (n == NULL) + return; + mutex_lock(&n->lock); n->phys_addr = pa; if (n->callback) @@ -100,6 +103,9 @@ void cec_notifier_set_phys_addr_from_edid(struct cec_notifier *n, { u16 pa = CEC_PHYS_ADDR_INVALID; + if (n == NULL) + return; + if (edid && edid->extensions) pa = cec_get_edid_phys_addr((const u8 *)edid, EDID_LENGTH * (edid->extensions + 1), NULL); diff --git a/drivers/media/dvb-core/dvb_ca_en50221.c b/drivers/media/dvb-core/dvb_ca_en50221.c index af694f2066a2..17970cdd55fa 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.c +++ b/drivers/media/dvb-core/dvb_ca_en50221.c @@ -349,7 +349,8 @@ static int dvb_ca_en50221_link_init(struct dvb_ca_private *ca, int slot) /* read the buffer size from the CAM */ if ((ret = ca->pub->write_cam_control(ca->pub, slot, CTRLIF_COMMAND, IRQEN | CMDREG_SR)) != 0) return ret; - if ((ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ / 10)) != 0) + ret = dvb_ca_en50221_wait_if_status(ca, slot, STATUSREG_DA, HZ); + if (ret != 0) return ret; if ((ret = dvb_ca_en50221_read_data(ca, slot, buf, 2)) != 2) return -EIO; @@ -644,72 +645,101 @@ static int dvb_ca_en50221_read_data(struct dvb_ca_private *ca, int slot, } buf_free = dvb_ringbuffer_free(&ca->slot_info[slot].rx_buffer); - if (buf_free < (ca->slot_info[slot].link_buf_size + DVB_RINGBUFFER_PKTHDRSIZE)) { + if (buf_free < (ca->slot_info[slot].link_buf_size + + DVB_RINGBUFFER_PKTHDRSIZE)) { status = -EAGAIN; goto exit; } } - /* check if there is data available */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) - goto exit; - if (!(status & STATUSREG_DA)) { - /* no data */ - status = 0; - goto exit; - } - - /* read the amount of data */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_HIGH)) < 0) - goto exit; - bytes_read = status << 8; - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_SIZE_LOW)) < 0) - goto exit; - bytes_read |= status; + if (ca->pub->read_data && + (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_LINKINIT)) { + if (ebuf == NULL) + status = ca->pub->read_data(ca->pub, slot, buf, + sizeof(buf)); + else + status = ca->pub->read_data(ca->pub, slot, buf, ecount); + if (status < 0) + return status; + bytes_read = status; + if (status == 0) + goto exit; + } else { - /* check it will fit */ - if (ebuf == NULL) { - if (bytes_read > ca->slot_info[slot].link_buf_size) { - pr_err("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n", - ca->dvbdev->adapter->num, bytes_read, - ca->slot_info[slot].link_buf_size); - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; + /* check if there is data available */ + status = ca->pub->read_cam_control(ca->pub, slot, + CTRLIF_STATUS); + if (status < 0) goto exit; - } - if (bytes_read < 2) { - pr_err("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", - ca->dvbdev->adapter->num); - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; + if (!(status & STATUSREG_DA)) { + /* no data */ + status = 0; goto exit; } - } else { - if (bytes_read > ecount) { - pr_err("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", - ca->dvbdev->adapter->num); - status = -EIO; + + /* read the amount of data */ + status = ca->pub->read_cam_control(ca->pub, slot, + CTRLIF_SIZE_HIGH); + if (status < 0) + goto exit; + bytes_read = status << 8; + status = ca->pub->read_cam_control(ca->pub, slot, + CTRLIF_SIZE_LOW); + if (status < 0) goto exit; + bytes_read |= status; + + /* check it will fit */ + if (ebuf == NULL) { + if (bytes_read > ca->slot_info[slot].link_buf_size) { + pr_err("dvb_ca adapter %d: CAM tried to send a buffer larger than the link buffer size (%i > %i)!\n", + ca->dvbdev->adapter->num, bytes_read, + ca->slot_info[slot].link_buf_size); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } + if (bytes_read < 2) { + pr_err("dvb_ca adapter %d: CAM sent a buffer that was less than 2 bytes!\n", + ca->dvbdev->adapter->num); + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } + } else { + if (bytes_read > ecount) { + pr_err("dvb_ca adapter %d: CAM tried to send a buffer larger than the ecount size!\n", + ca->dvbdev->adapter->num); + status = -EIO; + goto exit; + } } - } - /* fill the buffer */ - for (i = 0; i < bytes_read; i++) { - /* read byte and check */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_DATA)) < 0) - goto exit; + /* fill the buffer */ + for (i = 0; i < bytes_read; i++) { + /* read byte and check */ + status = ca->pub->read_cam_control(ca->pub, slot, + CTRLIF_DATA); + if (status < 0) + goto exit; - /* OK, store it in the buffer */ - buf[i] = status; - } + /* OK, store it in the buffer */ + buf[i] = status; + } - /* check for read error (RE should now be 0) */ - if ((status = ca->pub->read_cam_control(ca->pub, slot, CTRLIF_STATUS)) < 0) - goto exit; - if (status & STATUSREG_RE) { - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_LINKINIT; - status = -EIO; - goto exit; + /* check for read error (RE should now be 0) */ + status = ca->pub->read_cam_control(ca->pub, slot, + CTRLIF_STATUS); + if (status < 0) + goto exit; + if (status & STATUSREG_RE) { + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_LINKINIT; + status = -EIO; + goto exit; + } } /* OK, add it to the receive buffer, or copy into external buffer if supplied */ @@ -762,6 +792,10 @@ static int dvb_ca_en50221_write_data(struct dvb_ca_private *ca, int slot, if (bytes_write > ca->slot_info[slot].link_buf_size) return -EINVAL; + if (ca->pub->write_data && + (ca->slot_info[slot].slot_state != DVB_CA_SLOTSTATE_LINKINIT)) + return ca->pub->write_data(ca->pub, slot, buf, bytes_write); + /* it is possible we are dealing with a single buffer implementation, thus if there is data available for read or if there is even a read already in progress, we do nothing but awake the kernel thread to @@ -1176,7 +1210,8 @@ static int dvb_ca_en50221_thread(void *data) pr_err("dvb_ca adapter %d: DVB CAM link initialisation failed :(\n", ca->dvbdev->adapter->num); - ca->slot_info[slot].slot_state = DVB_CA_SLOTSTATE_INVALID; + ca->slot_info[slot].slot_state = + DVB_CA_SLOTSTATE_UNINITIALISED; dvb_ca_en50221_thread_update_delay(ca); break; } diff --git a/drivers/media/dvb-core/dvb_ca_en50221.h b/drivers/media/dvb-core/dvb_ca_en50221.h index 1e4bbbd34d91..82617bac0875 100644 --- a/drivers/media/dvb-core/dvb_ca_en50221.h +++ b/drivers/media/dvb-core/dvb_ca_en50221.h @@ -41,6 +41,8 @@ * @write_attribute_mem: function for writing attribute memory on the CAM * @read_cam_control: function for reading the control interface on the CAM * @write_cam_control: function for reading the control interface on the CAM + * @read_data: function for reading data (block mode) + * @write_data: function for writing data (block mode) * @slot_reset: function to reset the CAM slot * @slot_shutdown: function to shutdown a CAM slot * @slot_ts_enable: function to enable the Transport Stream on a CAM slot @@ -66,6 +68,11 @@ struct dvb_ca_en50221 { int (*write_cam_control)(struct dvb_ca_en50221 *ca, int slot, u8 address, u8 value); + int (*read_data)(struct dvb_ca_en50221 *ca, + int slot, u8 *ebuf, int ecount); + int (*write_data)(struct dvb_ca_en50221 *ca, + int slot, u8 *ebuf, int ecount); + int (*slot_reset)(struct dvb_ca_en50221 *ca, int slot); int (*slot_shutdown)(struct dvb_ca_en50221 *ca, int slot); int (*slot_ts_enable)(struct dvb_ca_en50221 *ca, int slot); diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c index 08f67d60a7d9..12bff778c97f 100644 --- a/drivers/media/dvb-frontends/cxd2841er.c +++ b/drivers/media/dvb-frontends/cxd2841er.c @@ -3279,7 +3279,10 @@ static int cxd2841er_get_frontend(struct dvb_frontend *fe, else if (priv->state == STATE_ACTIVE_TC) cxd2841er_read_status_tc(fe, &status); - cxd2841er_read_signal_strength(fe); + if (priv->state == STATE_ACTIVE_TC || priv->state == STATE_ACTIVE_S) + cxd2841er_read_signal_strength(fe); + else + p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; if (status & FE_HAS_LOCK) { cxd2841er_read_snr(fe); diff --git a/drivers/media/dvb-frontends/drx39xyj/drx_driver.h b/drivers/media/dvb-frontends/drx39xyj/drx_driver.h index 4442e478db72..cd69e187ba7a 100644 --- a/drivers/media/dvb-frontends/drx39xyj/drx_driver.h +++ b/drivers/media/dvb-frontends/drx39xyj/drx_driver.h @@ -307,7 +307,7 @@ int drxbsp_tuner_default_i2c_write_read(struct tuner_instance *tuner, * \def DRX_UNKNOWN * \brief Generic UNKNOWN value for DRX enumerated types. * -* Used to indicate that the parameter value is unknown or not yet initalized. +* Used to indicate that the parameter value is unknown or not yet initialized. */ #ifndef DRX_UNKNOWN #define DRX_UNKNOWN (254) @@ -450,19 +450,6 @@ MACROS ((u8)((((u16)x)>>8)&0xFF)) /** -* \brief Macro to sign extend signed 9 bit value to signed 16 bit value -*/ -#define DRX_S9TOS16(x) ((((u16)x)&0x100) ? ((s16)((u16)(x)|0xFF00)) : (x)) - -/** -* \brief Macro to sign extend signed 9 bit value to signed 16 bit value -*/ -#define DRX_S24TODRXFREQ(x) ((((u32) x) & 0x00800000UL) ? \ - ((s32) \ - (((u32) x) | 0xFF000000)) : \ - ((s32) x)) - -/** * \brief Macro to convert 16 bit register value to a s32 */ #define DRX_U16TODRXFREQ(x) ((x & 0x8000) ? \ diff --git a/drivers/media/dvb-frontends/lnbh25.c b/drivers/media/dvb-frontends/lnbh25.c index ef3021e964be..cb486e879fdd 100644 --- a/drivers/media/dvb-frontends/lnbh25.c +++ b/drivers/media/dvb-frontends/lnbh25.c @@ -76,8 +76,8 @@ static int lnbh25_read_vmon(struct lnbh25_priv *priv) return ret; } } - print_hex_dump_bytes("lnbh25_read_vmon: ", - DUMP_PREFIX_OFFSET, status, sizeof(status)); + dev_dbg(&priv->i2c->dev, "%s(): %*ph\n", + __func__, (int) sizeof(status), status); if ((status[0] & (LNBH25_STATUS_OFL | LNBH25_STATUS_VMON)) != 0) { dev_err(&priv->i2c->dev, "%s(): voltage in failure state, status reg 0x%x\n", @@ -178,7 +178,7 @@ struct dvb_frontend *lnbh25_attach(struct dvb_frontend *fe, fe->ops.release_sec = lnbh25_release; fe->ops.set_voltage = lnbh25_set_voltage; - dev_err(&i2c->dev, "%s(): attached at I2C addr 0x%02x\n", + dev_info(&i2c->dev, "%s(): attached at I2C addr 0x%02x\n", __func__, priv->i2c_address); return fe; } diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c index e726c2e00460..8ac0f598978d 100644 --- a/drivers/media/dvb-frontends/stv0367.c +++ b/drivers/media/dvb-frontends/stv0367.c @@ -25,6 +25,8 @@ #include <linux/slab.h> #include <linux/i2c.h> +#include "dvb_math.h" + #include "stv0367.h" #include "stv0367_defs.h" #include "stv0367_regs.h" @@ -1437,7 +1439,7 @@ static int stv0367ter_get_frontend(struct dvb_frontend *fe, return 0; } -static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr) +static u32 stv0367ter_snr_readreg(struct dvb_frontend *fe) { struct stv0367_state *state = fe->demodulator_priv; u32 snru32 = 0; @@ -1453,10 +1455,16 @@ static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr) cpt++; } - snru32 /= 10;/*average on 10 values*/ - *snr = snru32 / 1000; + return snru32; +} + +static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + u32 snrval = stv0367ter_snr_readreg(fe); + + *snr = snrval / 1000; return 0; } @@ -1501,7 +1509,8 @@ static int stv0367ter_read_status(struct dvb_frontend *fe, *status = 0; if (stv0367_readbits(state, F367TER_LK)) { - *status |= FE_HAS_LOCK; + *status = FE_HAS_SIGNAL | FE_HAS_CARRIER | FE_HAS_VITERBI + | FE_HAS_SYNC | FE_HAS_LOCK; dprintk("%s: stv0367 has locked\n", __func__); } @@ -2149,6 +2158,18 @@ static int stv0367cab_read_status(struct dvb_frontend *fe, *status = 0; + if (state->cab_state->state > FE_CAB_NOSIGNAL) + *status |= FE_HAS_SIGNAL; + + if (state->cab_state->state > FE_CAB_NOCARRIER) + *status |= FE_HAS_CARRIER; + + if (state->cab_state->state >= FE_CAB_DEMODOK) + *status |= FE_HAS_VITERBI; + + if (state->cab_state->state >= FE_CAB_DATAOK) + *status |= FE_HAS_SYNC; + if (stv0367_readbits(state, (state->cab_state->qamfec_status_reg ? state->cab_state->qamfec_status_reg : F367CAB_QAMFEC_LOCK))) { *status |= FE_HAS_LOCK; @@ -2702,51 +2723,61 @@ static int stv0367cab_read_strength(struct dvb_frontend *fe, u16 *strength) return 0; } -static int stv0367cab_read_snr(struct dvb_frontend *fe, u16 *snr) +static int stv0367cab_snr_power(struct dvb_frontend *fe) { struct stv0367_state *state = fe->demodulator_priv; - u32 noisepercentage; enum stv0367cab_mod QAMSize; - u32 regval = 0, temp = 0; - int power, i; QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE); switch (QAMSize) { case FE_CAB_MOD_QAM4: - power = 21904; - break; + return 21904; case FE_CAB_MOD_QAM16: - power = 20480; - break; + return 20480; case FE_CAB_MOD_QAM32: - power = 23040; - break; + return 23040; case FE_CAB_MOD_QAM64: - power = 21504; - break; + return 21504; case FE_CAB_MOD_QAM128: - power = 23616; - break; + return 23616; case FE_CAB_MOD_QAM256: - power = 21760; - break; - case FE_CAB_MOD_QAM512: - power = 1; - break; + return 21760; case FE_CAB_MOD_QAM1024: - power = 21280; - break; + return 21280; default: - power = 1; break; } + return 1; +} + +static int stv0367cab_snr_readreg(struct dvb_frontend *fe, int avgdiv) +{ + struct stv0367_state *state = fe->demodulator_priv; + u32 regval = 0; + int i; + for (i = 0; i < 10; i++) { regval += (stv0367_readbits(state, F367CAB_SNR_LO) + 256 * stv0367_readbits(state, F367CAB_SNR_HI)); } - regval /= 10; /*for average over 10 times in for loop above*/ + if (avgdiv) + regval /= 10; + + return regval; +} + +static int stv0367cab_read_snr(struct dvb_frontend *fe, u16 *snr) +{ + struct stv0367_state *state = fe->demodulator_priv; + u32 noisepercentage; + u32 regval = 0, temp = 0; + int power; + + power = stv0367cab_snr_power(fe); + regval = stv0367cab_snr_readreg(fe, 1); + if (regval != 0) { temp = power * (1 << (3 + stv0367_readbits(state, F367CAB_SNR_PER))); @@ -2980,21 +3011,117 @@ static int stv0367ddb_set_frontend(struct dvb_frontend *fe) return -EINVAL; } +static void stv0367ddb_read_signal_strength(struct dvb_frontend *fe) +{ + struct stv0367_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + s32 signalstrength; + + switch (state->activedemod) { + case demod_cab: + signalstrength = stv0367cab_get_rf_lvl(state) * 1000; + break; + default: + p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return; + } + + p->strength.stat[0].scale = FE_SCALE_DECIBEL; + p->strength.stat[0].uvalue = signalstrength; +} + +static void stv0367ddb_read_snr(struct dvb_frontend *fe) +{ + struct stv0367_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + int cab_pwr; + u32 regval, tmpval, snrval = 0; + + switch (state->activedemod) { + case demod_ter: + snrval = stv0367ter_snr_readreg(fe); + break; + case demod_cab: + cab_pwr = stv0367cab_snr_power(fe); + regval = stv0367cab_snr_readreg(fe, 0); + + /* prevent division by zero */ + if (!regval) { + snrval = 0; + break; + } + + tmpval = (cab_pwr * 320) / regval; + snrval = ((tmpval != 0) ? (intlog2(tmpval) / 5581) : 0); + break; + default: + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return; + } + + p->cnr.stat[0].scale = FE_SCALE_DECIBEL; + p->cnr.stat[0].uvalue = snrval; +} + +static void stv0367ddb_read_ucblocks(struct dvb_frontend *fe) +{ + struct stv0367_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + u32 ucblocks = 0; + + switch (state->activedemod) { + case demod_ter: + stv0367ter_read_ucblocks(fe, &ucblocks); + break; + case demod_cab: + stv0367cab_read_ucblcks(fe, &ucblocks); + break; + default: + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return; + } + + p->block_error.stat[0].scale = FE_SCALE_COUNTER; + p->block_error.stat[0].uvalue = ucblocks; +} + static int stv0367ddb_read_status(struct dvb_frontend *fe, enum fe_status *status) { struct stv0367_state *state = fe->demodulator_priv; + struct dtv_frontend_properties *p = &fe->dtv_property_cache; + int ret; switch (state->activedemod) { case demod_ter: - return stv0367ter_read_status(fe, status); + ret = stv0367ter_read_status(fe, status); + break; case demod_cab: - return stv0367cab_read_status(fe, status); - default: + ret = stv0367cab_read_status(fe, status); break; + default: + return 0; } - return -EINVAL; + /* stop and report on *_read_status failure */ + if (ret) + return ret; + + stv0367ddb_read_signal_strength(fe); + + /* read carrier/noise when a carrier is detected */ + if (*status & FE_HAS_CARRIER) + stv0367ddb_read_snr(fe); + else + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + + /* read uncorrected blocks on FE_HAS_LOCK */ + if (*status & FE_HAS_LOCK) + stv0367ddb_read_ucblocks(fe); + else + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + + return 0; } static int stv0367ddb_get_frontend(struct dvb_frontend *fe, @@ -3035,6 +3162,7 @@ static int stv0367ddb_sleep(struct dvb_frontend *fe) static int stv0367ddb_init(struct stv0367_state *state) { struct stv0367ter_state *ter_state = state->ter_state; + struct dtv_frontend_properties *p = &state->fe.dtv_property_cache; stv0367_writereg(state, R367TER_TOPCTRL, 0x10); @@ -3109,6 +3237,13 @@ static int stv0367ddb_init(struct stv0367_state *state) ter_state->first_lock = 0; ter_state->unlock_counter = 2; + p->strength.len = 1; + p->strength.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->cnr.len = 1; + p->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + p->block_error.len = 1; + p->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE; + return 0; } @@ -3126,15 +3261,12 @@ static const struct dvb_frontend_ops stv0367ddb_ops = { 0x400 |/* FE_CAN_QAM_4 */ FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 | FE_CAN_QAM_128 | - FE_CAN_QAM_256 | FE_CAN_FEC_AUTO | + FE_CAN_QAM_256 | FE_CAN_QAM_AUTO | /* DVB-T */ - FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | - FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | - FE_CAN_FEC_AUTO | - FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | - FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO | - FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER | - FE_CAN_INVERSION_AUTO | + FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | + FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_QPSK | FE_CAN_TRANSMISSION_MODE_AUTO | + FE_CAN_RECOVER | FE_CAN_INVERSION_AUTO | FE_CAN_MUTE_TS }, .release = stv0367_release, diff --git a/drivers/media/i2c/et8ek8/et8ek8_driver.c b/drivers/media/i2c/et8ek8/et8ek8_driver.c index 6e313d5243a0..f39f5179dd95 100644 --- a/drivers/media/i2c/et8ek8/et8ek8_driver.c +++ b/drivers/media/i2c/et8ek8/et8ek8_driver.c @@ -1496,7 +1496,6 @@ MODULE_DEVICE_TABLE(i2c, et8ek8_id_table); static const struct dev_pm_ops et8ek8_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(et8ek8_suspend, et8ek8_resume) }; -MODULE_DEVICE_TABLE(of, et8ek8_of_table); static struct i2c_driver et8ek8_i2c_driver = { .driver = { diff --git a/drivers/media/i2c/tvp5150.c b/drivers/media/i2c/tvp5150.c index 9da4bf4f2c7a..7b79a7498751 100644 --- a/drivers/media/i2c/tvp5150.c +++ b/drivers/media/i2c/tvp5150.c @@ -659,7 +659,7 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd, struct tvp5150 *decoder = to_tvp5150(sd); v4l2_std_id std = decoder->norm; u8 reg; - int pos=0; + int pos = 0; if (std == V4L2_STD_ALL) { dev_err(sd->dev, "VBI can't be configured without knowing number of lines\n"); @@ -669,33 +669,30 @@ static int tvp5150_set_vbi(struct v4l2_subdev *sd, line += 3; } - if (line<6||line>27) + if (line < 6 || line > 27) return 0; - while (regs->reg != (u16)-1 ) { + while (regs->reg != (u16)-1) { if ((type & regs->type.vbi_type) && - (line>=regs->type.ini_line) && - (line<=regs->type.end_line)) { - type=regs->type.vbi_type; + (line >= regs->type.ini_line) && + (line <= regs->type.end_line)) break; - } regs++; pos++; } + if (regs->reg == (u16)-1) return 0; - type=pos | (flags & 0xf0); - reg=((line-6)<<1)+TVP5150_LINE_MODE_INI; + type = pos | (flags & 0xf0); + reg = ((line - 6) << 1) + TVP5150_LINE_MODE_INI; - if (fields&1) { + if (fields & 1) tvp5150_write(sd, reg, type); - } - if (fields&2) { - tvp5150_write(sd, reg+1, type); - } + if (fields & 2) + tvp5150_write(sd, reg + 1, type); return type; } diff --git a/drivers/media/pci/ddbridge/ddbridge-core.c b/drivers/media/pci/ddbridge/ddbridge-core.c index 9420479bee9a..cd1723e79a07 100644 --- a/drivers/media/pci/ddbridge/ddbridge-core.c +++ b/drivers/media/pci/ddbridge/ddbridge-core.c @@ -17,6 +17,8 @@ * http://www.gnu.org/copyleft/gpl.html */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/interrupt.h> @@ -114,6 +116,19 @@ static int i2c_write_reg(struct i2c_adapter *adap, u8 adr, return i2c_write(adap, adr, msg, 2); } +static inline u32 safe_ddbreadl(struct ddb *dev, u32 adr) +{ + u32 val = ddbreadl(adr); + + /* (ddb)readl returns (uint)-1 (all bits set) on failure, catch that */ + if (val == ~0) { + dev_err(&dev->pdev->dev, "ddbreadl failure, adr=%08x\n", adr); + return 0; + } + + return val; +} + static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) { struct ddb *dev = i2c->dev; @@ -124,10 +139,10 @@ static int ddb_i2c_cmd(struct ddb_i2c *i2c, u32 adr, u32 cmd) ddbwritel((adr << 9) | cmd, i2c->regs + I2C_COMMAND); stat = wait_event_timeout(i2c->wq, i2c->done == 1, HZ); if (stat == 0) { - printk(KERN_ERR "I2C timeout\n"); + dev_err(&dev->pdev->dev, "I2C timeout\n"); { /* MSI debugging*/ u32 istat = ddbreadl(INTERRUPT_STATUS); - printk(KERN_ERR "IRS %08x\n", istat); + dev_err(&dev->pdev->dev, "IRS %08x\n", istat); ddbwritel(istat, INTERRUPT_ACK); } return -EIO; @@ -533,7 +548,7 @@ static u32 ddb_input_avail(struct ddb_input *input) off = (stat & 0x7ff) << 7; if (ctrl & 4) { - printk(KERN_ERR "IA %d %d %08x\n", idx, off, ctrl); + dev_err(&dev->pdev->dev, "IA %d %d %08x\n", idx, off, ctrl); ddbwritel(input->stat, DMA_BUFFER_ACK(input->nr)); return 0; } @@ -611,6 +626,7 @@ static int demod_attach_drxk(struct ddb_input *input) struct i2c_adapter *i2c = &input->port->i2c->adap; struct dvb_frontend *fe; struct drxk_config config; + struct device *dev = &input->port->dev->pdev->dev; memset(&config, 0, sizeof(config)); config.microcode_name = "drxk_a3.mc"; @@ -619,7 +635,7 @@ static int demod_attach_drxk(struct ddb_input *input) fe = input->fe = dvb_attach(drxk_attach, &config, i2c); if (!input->fe) { - printk(KERN_ERR "No DRXK found!\n"); + dev_err(dev, "No DRXK found!\n"); return -ENODEV; } fe->sec_priv = input; @@ -632,12 +648,13 @@ static int tuner_attach_tda18271(struct ddb_input *input) { struct i2c_adapter *i2c = &input->port->i2c->adap; struct dvb_frontend *fe; + struct device *dev = &input->port->dev->pdev->dev; if (input->fe->ops.i2c_gate_ctrl) input->fe->ops.i2c_gate_ctrl(input->fe, 1); fe = dvb_attach(tda18271c2dd_attach, input->fe, i2c, 0x60); if (!fe) { - printk(KERN_ERR "No TDA18271 found!\n"); + dev_err(dev, "No TDA18271 found!\n"); return -ENODEV; } if (input->fe->ops.i2c_gate_ctrl) @@ -670,13 +687,14 @@ static struct stv0367_config ddb_stv0367_config[] = { static int demod_attach_stv0367(struct ddb_input *input) { struct i2c_adapter *i2c = &input->port->i2c->adap; + struct device *dev = &input->port->dev->pdev->dev; /* attach frontend */ input->fe = dvb_attach(stv0367ddb_attach, &ddb_stv0367_config[(input->nr & 1)], i2c); if (!input->fe) { - printk(KERN_ERR "stv0367ddb_attach failed (not found?)\n"); + dev_err(dev, "stv0367ddb_attach failed (not found?)\n"); return -ENODEV; } @@ -690,17 +708,19 @@ static int demod_attach_stv0367(struct ddb_input *input) static int tuner_tda18212_ping(struct ddb_input *input, unsigned short adr) { struct i2c_adapter *adapter = &input->port->i2c->adap; + struct device *dev = &input->port->dev->pdev->dev; + u8 tda_id[2]; u8 subaddr = 0x00; - printk(KERN_DEBUG "stv0367-tda18212 tuner ping\n"); + dev_dbg(dev, "stv0367-tda18212 tuner ping\n"); if (input->fe->ops.i2c_gate_ctrl) input->fe->ops.i2c_gate_ctrl(input->fe, 1); if (i2c_read_regs(adapter, adr, subaddr, tda_id, sizeof(tda_id)) < 0) - printk(KERN_DEBUG "tda18212 ping 1 fail\n"); + dev_dbg(dev, "tda18212 ping 1 fail\n"); if (i2c_read_regs(adapter, adr, subaddr, tda_id, sizeof(tda_id)) < 0) - printk(KERN_DEBUG "tda18212 ping 2 fail\n"); + dev_warn(dev, "tda18212 ping failed, expect problems\n"); if (input->fe->ops.i2c_gate_ctrl) input->fe->ops.i2c_gate_ctrl(input->fe, 0); @@ -711,6 +731,7 @@ static int tuner_tda18212_ping(struct ddb_input *input, unsigned short adr) static int demod_attach_cxd28xx(struct ddb_input *input, int par, int osc24) { struct i2c_adapter *i2c = &input->port->i2c->adap; + struct device *dev = &input->port->dev->pdev->dev; struct cxd2841er_config cfg; /* the cxd2841er driver expects 8bit/shifted I2C addresses */ @@ -728,7 +749,7 @@ static int demod_attach_cxd28xx(struct ddb_input *input, int par, int osc24) input->fe = dvb_attach(cxd2841er_attach_t_c, &cfg, i2c); if (!input->fe) { - printk(KERN_ERR "No Sony CXD28xx found!\n"); + dev_err(dev, "No Sony CXD28xx found!\n"); return -ENODEV; } @@ -742,6 +763,7 @@ static int demod_attach_cxd28xx(struct ddb_input *input, int par, int osc24) static int tuner_attach_tda18212(struct ddb_input *input, u32 porttype) { struct i2c_adapter *adapter = &input->port->i2c->adap; + struct device *dev = &input->port->dev->pdev->dev; struct i2c_client *client; struct tda18212_config config = { .fe = input->fe, @@ -786,7 +808,7 @@ static int tuner_attach_tda18212(struct ddb_input *input, u32 porttype) return 0; err: - printk(KERN_INFO "TDA18212 tuner not found. Device is not fully operational.\n"); + dev_warn(dev, "TDA18212 tuner not found. Device is not fully operational.\n"); return -ENODEV; } @@ -847,19 +869,20 @@ static struct stv6110x_config stv6110b = { static int demod_attach_stv0900(struct ddb_input *input, int type) { struct i2c_adapter *i2c = &input->port->i2c->adap; + struct device *dev = &input->port->dev->pdev->dev; struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; input->fe = dvb_attach(stv090x_attach, feconf, i2c, (input->nr & 1) ? STV090x_DEMODULATOR_1 : STV090x_DEMODULATOR_0); if (!input->fe) { - printk(KERN_ERR "No STV0900 found!\n"); + dev_err(dev, "No STV0900 found!\n"); return -ENODEV; } if (!dvb_attach(lnbh24_attach, input->fe, i2c, 0, 0, (input->nr & 1) ? (0x09 - type) : (0x0b - type))) { - printk(KERN_ERR "No LNBH24 found!\n"); + dev_err(dev, "No LNBH24 found!\n"); return -ENODEV; } return 0; @@ -868,6 +891,7 @@ static int demod_attach_stv0900(struct ddb_input *input, int type) static int tuner_attach_stv6110(struct ddb_input *input, int type) { struct i2c_adapter *i2c = &input->port->i2c->adap; + struct device *dev = &input->port->dev->pdev->dev; struct stv090x_config *feconf = type ? &stv0900_aa : &stv0900; struct stv6110x_config *tunerconf = (input->nr & 1) ? &stv6110b : &stv6110a; @@ -875,10 +899,10 @@ static int tuner_attach_stv6110(struct ddb_input *input, int type) ctl = dvb_attach(stv6110x_attach, input->fe, tunerconf, i2c); if (!ctl) { - printk(KERN_ERR "No STV6110X found!\n"); + dev_err(dev, "No STV6110X found!\n"); return -ENODEV; } - printk(KERN_INFO "attach tuner input %d adr %02x\n", + dev_info(dev, "attach tuner input %d adr %02x\n", input->nr, tunerconf->addr); feconf->tuner_init = ctl->tuner_init; @@ -1009,13 +1033,14 @@ static int dvb_input_attach(struct ddb_input *input) struct ddb_port *port = input->port; struct dvb_adapter *adap = &input->adap; struct dvb_demux *dvbdemux = &input->demux; + struct device *dev = &input->port->dev->pdev->dev; int sony_osc24 = 0, sony_tspar = 0; ret = dvb_register_adapter(adap, "DDBridge", THIS_MODULE, &input->port->dev->pdev->dev, adapter_nr); if (ret < 0) { - printk(KERN_ERR "ddbridge: Could not register adapter.Check if you enabled enough adapters in dvb-core!\n"); + dev_err(dev, "Could not register adapter. Check if you enabled enough adapters in dvb-core!\n"); return ret; } input->attached = 1; @@ -1241,9 +1266,9 @@ static void input_tasklet(unsigned long data) if (input->port->class == DDB_PORT_TUNER) { if (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr))) - printk(KERN_ERR "Overflow input %d\n", input->nr); + dev_err(&dev->pdev->dev, "Overflow input %d\n", input->nr); while (input->cbuf != ((input->stat >> 11) & 0x1f) - || (4&ddbreadl(DMA_BUFFER_CONTROL(input->nr)))) { + || (4 & safe_ddbreadl(dev, DMA_BUFFER_CONTROL(input->nr)))) { dvb_dmx_swfilter_packets(&input->demux, input->vbuf[input->cbuf], input->dma_buf_size / 188); @@ -1280,6 +1305,7 @@ static struct cxd2099_cfg cxd_cfg = { .adr = 0x40, .polarity = 1, .clock_mode = 1, + .max_i2c = 512, }; static int ddb_ci_attach(struct ddb_port *port) @@ -1310,6 +1336,7 @@ static int ddb_ci_attach(struct ddb_port *port) static int ddb_port_attach(struct ddb_port *port) { + struct device *dev = &port->dev->pdev->dev; int ret = 0; switch (port->class) { @@ -1326,7 +1353,7 @@ static int ddb_port_attach(struct ddb_port *port) break; } if (ret < 0) - printk(KERN_ERR "port_attach on port %d failed\n", port->nr); + dev_err(dev, "port_attach on port %d failed\n", port->nr); return ret; } @@ -1377,6 +1404,7 @@ static void ddb_ports_detach(struct ddb *dev) static int init_xo2(struct ddb_port *port) { struct i2c_adapter *i2c = &port->i2c->adap; + struct device *dev = &port->dev->pdev->dev; u8 val, data[2]; int res; @@ -1385,7 +1413,7 @@ static int init_xo2(struct ddb_port *port) return res; if (data[0] != 0x01) { - pr_info("Port %d: invalid XO2\n", port->nr); + dev_info(dev, "Port %d: invalid XO2\n", port->nr); return -1; } @@ -1511,7 +1539,7 @@ static void ddb_port_probe(struct ddb_port *port) port->class = DDB_PORT_CI; ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); } else if (port_has_xo2(port, &xo2_type, &xo2_id)) { - printk(KERN_INFO "Port %d (TAB %d): XO2 type: %d, id: %d\n", + dev_dbg(&dev->pdev->dev, "Port %d (TAB %d): XO2 type: %d, id: %d\n", port->nr, port->nr+1, xo2_type, xo2_id); ddbwritel(I2C_SPEED_400, port->i2c->regs + I2C_TIMING); @@ -1556,10 +1584,10 @@ static void ddb_port_probe(struct ddb_port *port) } break; case DDB_XO2_TYPE_CI: - printk(KERN_INFO "DuoFlex CI modules not supported\n"); + dev_info(&dev->pdev->dev, "DuoFlex CI modules not supported\n"); break; default: - printk(KERN_INFO "Unknown XO2 DuoFlex module\n"); + dev_info(&dev->pdev->dev, "Unknown XO2 DuoFlex module\n"); break; } } else if (port_has_cxd28xx(port, &cxd_id)) { @@ -1611,7 +1639,7 @@ static void ddb_port_probe(struct ddb_port *port) ddbwritel(I2C_SPEED_100, port->i2c->regs + I2C_TIMING); } - printk(KERN_INFO "Port %d (TAB %d): %s\n", + dev_info(&dev->pdev->dev, "Port %d (TAB %d): %s\n", port->nr, port->nr+1, modname); } @@ -1765,7 +1793,7 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) wbuf += 4; wlen -= 4; ddbwritel(data, SPI_DATA); - while (ddbreadl(SPI_CONTROL) & 0x0004) + while (safe_ddbreadl(dev, SPI_CONTROL) & 0x0004) ; } @@ -1785,7 +1813,7 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) if (shift) data <<= shift; ddbwritel(data, SPI_DATA); - while (ddbreadl(SPI_CONTROL) & 0x0004) + while (safe_ddbreadl(dev, SPI_CONTROL) & 0x0004) ; if (!rlen) { @@ -1797,7 +1825,7 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) while (rlen > 4) { ddbwritel(0xffffffff, SPI_DATA); - while (ddbreadl(SPI_CONTROL) & 0x0004) + while (safe_ddbreadl(dev, SPI_CONTROL) & 0x0004) ; data = ddbreadl(SPI_DATA); *(u32 *) rbuf = swab32(data); @@ -1806,7 +1834,7 @@ static int flashio(struct ddb *dev, u8 *wbuf, u32 wlen, u8 *rbuf, u32 rlen) } ddbwritel(0x0003 | ((rlen << (8 + 3)) & 0x1F00), SPI_CONTROL); ddbwritel(0xffffffff, SPI_DATA); - while (ddbreadl(SPI_CONTROL) & 0x0004) + while (safe_ddbreadl(dev, SPI_CONTROL) & 0x0004) ; data = ddbreadl(SPI_DATA); @@ -1993,7 +2021,7 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) dev->pdev = pdev; pci_set_drvdata(pdev, dev); dev->info = (struct ddb_info *) id->driver_data; - printk(KERN_INFO "DDBridge driver detected: %s\n", dev->info->name); + dev_info(&pdev->dev, "Detected %s\n", dev->info->name); dev->regs = ioremap(pci_resource_start(dev->pdev, 0), pci_resource_len(dev->pdev, 0)); @@ -2001,13 +2029,13 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) stat = -ENOMEM; goto fail; } - printk(KERN_INFO "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4)); + dev_info(&pdev->dev, "HW %08x FW %08x\n", ddbreadl(0), ddbreadl(4)); #ifdef CONFIG_PCI_MSI if (pci_msi_enabled()) stat = pci_enable_msi(dev->pdev); if (stat) { - printk(KERN_INFO ": MSI not available.\n"); + dev_info(&pdev->dev, "MSI not available.\n"); } else { irq_flag = 0; dev->msi = 1; @@ -2040,7 +2068,7 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto fail1; ddb_ports_init(dev); if (ddb_buffers_alloc(dev) < 0) { - printk(KERN_INFO ": Could not allocate buffer memory\n"); + dev_err(&pdev->dev, "Could not allocate buffer memory\n"); goto fail2; } if (ddb_ports_attach(dev) < 0) @@ -2050,19 +2078,19 @@ static int ddb_probe(struct pci_dev *pdev, const struct pci_device_id *id) fail3: ddb_ports_detach(dev); - printk(KERN_ERR "fail3\n"); + dev_err(&pdev->dev, "fail3\n"); ddb_ports_release(dev); fail2: - printk(KERN_ERR "fail2\n"); + dev_err(&pdev->dev, "fail2\n"); ddb_buffers_free(dev); fail1: - printk(KERN_ERR "fail1\n"); + dev_err(&pdev->dev, "fail1\n"); if (dev->msi) pci_disable_msi(dev->pdev); if (stat == 0) free_irq(dev->pdev->irq, dev); fail: - printk(KERN_ERR "fail\n"); + dev_err(&pdev->dev, "fail\n"); ddb_unmap(dev); pci_set_drvdata(pdev, NULL); pci_disable_device(pdev); @@ -2242,7 +2270,7 @@ static __init int module_init_ddbridge(void) { int ret; - printk(KERN_INFO "Digital Devices PCIE bridge driver, Copyright (C) 2010-11 Digital Devices GmbH\n"); + pr_info("Digital Devices PCIE bridge driver, Copyright (C) 2010-11 Digital Devices GmbH\n"); ret = ddb_class_create(); if (ret < 0) diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c index ce69e648b663..8c92cb7f7e72 100644 --- a/drivers/media/pci/ngene/ngene-core.c +++ b/drivers/media/pci/ngene/ngene-core.c @@ -336,9 +336,9 @@ int ngene_command(struct ngene *dev, struct ngene_command *com) { int result; - down(&dev->cmd_mutex); + mutex_lock(&dev->cmd_mutex); result = ngene_command_mutex(dev, com); - up(&dev->cmd_mutex); + mutex_unlock(&dev->cmd_mutex); return result; } @@ -560,7 +560,6 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream, u16 BsSPI = ((stream & 1) ? 0x9800 : 0x9700); u16 BsSDO = 0x9B00; - down(&dev->stream_mutex); memset(&com, 0, sizeof(com)); com.cmd.hdr.Opcode = CMD_CONTROL; com.cmd.hdr.Length = sizeof(struct FW_STREAM_CONTROL) - 2; @@ -586,17 +585,13 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream, chan->State = KSSTATE_ACQUIRE; chan->HWState = HWSTATE_STOP; spin_unlock_irq(&chan->state_lock); - if (ngene_command(dev, &com) < 0) { - up(&dev->stream_mutex); + if (ngene_command(dev, &com) < 0) return -1; - } /* clear_buffers(chan); */ flush_buffers(chan); - up(&dev->stream_mutex); return 0; } spin_unlock_irq(&chan->state_lock); - up(&dev->stream_mutex); return 0; } @@ -692,11 +687,9 @@ static int ngene_command_stream_control(struct ngene *dev, u8 stream, chan->HWState = HWSTATE_STARTUP; spin_unlock_irq(&chan->state_lock); - if (ngene_command(dev, &com) < 0) { - up(&dev->stream_mutex); + if (ngene_command(dev, &com) < 0) return -1; - } - up(&dev->stream_mutex); + return 0; } @@ -750,8 +743,11 @@ void set_transfer(struct ngene_channel *chan, int state) /* else printk(KERN_INFO DEVICE_NAME ": lock=%08x\n", ngreadl(0x9310)); */ + mutex_lock(&dev->stream_mutex); ret = ngene_command_stream_control(dev, chan->number, control, mode, flags); + mutex_unlock(&dev->stream_mutex); + if (!ret) chan->running = state; else @@ -1283,7 +1279,7 @@ static int ngene_load_firm(struct ngene *dev) static void ngene_stop(struct ngene *dev) { - down(&dev->cmd_mutex); + mutex_destroy(&dev->cmd_mutex); i2c_del_adapter(&(dev->channel[0].i2c_adapter)); i2c_del_adapter(&(dev->channel[1].i2c_adapter)); ngwritel(0, NGENE_INT_ENABLE); @@ -1346,10 +1342,10 @@ static int ngene_start(struct ngene *dev) init_waitqueue_head(&dev->cmd_wq); init_waitqueue_head(&dev->tx_wq); init_waitqueue_head(&dev->rx_wq); - sema_init(&dev->cmd_mutex, 1); - sema_init(&dev->stream_mutex, 1); + mutex_init(&dev->cmd_mutex); + mutex_init(&dev->stream_mutex); sema_init(&dev->pll_mutex, 1); - sema_init(&dev->i2c_switch_mutex, 1); + mutex_init(&dev->i2c_switch_mutex); spin_lock_init(&dev->cmd_lock); for (i = 0; i < MAX_STREAM; i++) spin_lock_init(&dev->channel[i].state_lock); @@ -1606,10 +1602,10 @@ static void ngene_unlink(struct ngene *dev) com.in_len = 3; com.out_len = 1; - down(&dev->cmd_mutex); + mutex_lock(&dev->cmd_mutex); ngwritel(0, NGENE_INT_ENABLE); ngene_command_mutex(dev, &com); - up(&dev->cmd_mutex); + mutex_unlock(&dev->cmd_mutex); } void ngene_shutdown(struct pci_dev *pdev) diff --git a/drivers/media/pci/ngene/ngene-i2c.c b/drivers/media/pci/ngene/ngene-i2c.c index cf39fcf54adf..fbf36353c701 100644 --- a/drivers/media/pci/ngene/ngene-i2c.c +++ b/drivers/media/pci/ngene/ngene-i2c.c @@ -118,7 +118,7 @@ static int ngene_i2c_master_xfer(struct i2c_adapter *adapter, (struct ngene_channel *)i2c_get_adapdata(adapter); struct ngene *dev = chan->dev; - down(&dev->i2c_switch_mutex); + mutex_lock(&dev->i2c_switch_mutex); ngene_i2c_set_bus(dev, chan->number); if (num == 2 && msg[1].flags & I2C_M_RD && !(msg[0].flags & I2C_M_RD)) @@ -136,11 +136,11 @@ static int ngene_i2c_master_xfer(struct i2c_adapter *adapter, msg[0].buf, msg[0].len, 0)) goto done; - up(&dev->i2c_switch_mutex); + mutex_unlock(&dev->i2c_switch_mutex); return -EIO; done: - up(&dev->i2c_switch_mutex); + mutex_unlock(&dev->i2c_switch_mutex); return num; } diff --git a/drivers/media/pci/ngene/ngene.h b/drivers/media/pci/ngene/ngene.h index 10d8f74c4f0a..7c7cd217333d 100644 --- a/drivers/media/pci/ngene/ngene.h +++ b/drivers/media/pci/ngene/ngene.h @@ -762,10 +762,10 @@ struct ngene { wait_queue_head_t cmd_wq; int cmd_done; - struct semaphore cmd_mutex; - struct semaphore stream_mutex; + struct mutex cmd_mutex; + struct mutex stream_mutex; struct semaphore pll_mutex; - struct semaphore i2c_switch_mutex; + struct mutex i2c_switch_mutex; int i2c_current_channel; int i2c_current_bus; spinlock_t cmd_lock; diff --git a/drivers/media/pci/tw5864/tw5864-video.c b/drivers/media/pci/tw5864/tw5864-video.c index 2a044be729da..e7bd2b8484e3 100644 --- a/drivers/media/pci/tw5864/tw5864-video.c +++ b/drivers/media/pci/tw5864/tw5864-video.c @@ -545,6 +545,7 @@ static int tw5864_fmt_vid_cap(struct file *file, void *priv, switch (input->std) { default: WARN_ON_ONCE(1); + return -EINVAL; case STD_NTSC: f->fmt.pix.height = 480; break; diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 1313cd533436..fb1fa0b82077 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -475,8 +475,8 @@ config VIDEO_QCOM_VENUS tristate "Qualcomm Venus V4L2 encoder/decoder driver" depends on VIDEO_DEV && VIDEO_V4L2 && HAS_DMA depends on (ARCH_QCOM && IOMMU_DMA) || COMPILE_TEST - select QCOM_MDT_LOADER if (ARM || ARM64) - select QCOM_SCM if (ARM || ARM64) + select QCOM_MDT_LOADER if ARCH_QCOM + select QCOM_SCM if ARCH_QCOM select VIDEOBUF2_DMA_SG select V4L2_MEM2MEM_DEV ---help--- diff --git a/drivers/media/platform/coda/coda-bit.c b/drivers/media/platform/coda/coda-bit.c index 25cbf9e5ac5a..bba1eb43b5d8 100644 --- a/drivers/media/platform/coda/coda-bit.c +++ b/drivers/media/platform/coda/coda-bit.c @@ -393,8 +393,8 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, int ret; int i; - if (ctx->codec && (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 || - ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264)) { + if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 || + ctx->codec->dst_fourcc == V4L2_PIX_FMT_H264) { width = round_up(q_data->width, 16); height = round_up(q_data->height, 16); } else { @@ -2198,7 +2198,7 @@ static void coda_finish_decode(struct coda_ctx *ctx) ctx->display_idx = display_idx; } -static void coda_error_decode(struct coda_ctx *ctx) +static void coda_decode_timeout(struct coda_ctx *ctx) { struct vb2_v4l2_buffer *dst_buf; @@ -2223,7 +2223,7 @@ const struct coda_context_ops coda_bit_decode_ops = { .start_streaming = coda_start_decoding, .prepare_run = coda_prepare_decode, .finish_run = coda_finish_decode, - .error_run = coda_error_decode, + .run_timeout = coda_decode_timeout, .seq_end_work = coda_seq_end_work, .release = coda_bit_release, }; diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c index f92cc7df58fb..829c7895a98a 100644 --- a/drivers/media/platform/coda/coda-common.c +++ b/drivers/media/platform/coda/coda-common.c @@ -1164,8 +1164,8 @@ static void coda_pic_run_work(struct work_struct *work) coda_hw_reset(ctx); - if (ctx->ops->error_run) - ctx->ops->error_run(ctx); + if (ctx->ops->run_timeout) + ctx->ops->run_timeout(ctx); } else if (!ctx->aborting) { ctx->ops->finish_run(ctx); } diff --git a/drivers/media/platform/coda/coda.h b/drivers/media/platform/coda/coda.h index 40fe22f0d757..c5f504d8cf67 100644 --- a/drivers/media/platform/coda/coda.h +++ b/drivers/media/platform/coda/coda.h @@ -183,7 +183,7 @@ struct coda_context_ops { int (*start_streaming)(struct coda_ctx *ctx); int (*prepare_run)(struct coda_ctx *ctx); void (*finish_run)(struct coda_ctx *ctx); - void (*error_run)(struct coda_ctx *ctx); + void (*run_timeout)(struct coda_ctx *ctx); void (*seq_end_work)(struct work_struct *work); void (*release)(struct coda_ctx *ctx); }; diff --git a/drivers/media/platform/davinci/ccdc_hw_device.h b/drivers/media/platform/davinci/ccdc_hw_device.h index 8f6688a7a111..f1b521045d64 100644 --- a/drivers/media/platform/davinci/ccdc_hw_device.h +++ b/drivers/media/platform/davinci/ccdc_hw_device.h @@ -42,16 +42,6 @@ struct ccdc_hw_ops { int (*set_hw_if_params) (struct vpfe_hw_if_param *param); /* get interface parameters */ int (*get_hw_if_params) (struct vpfe_hw_if_param *param); - /* - * Pointer to function to set parameters. Used - * for implementing VPFE_S_CCDC_PARAMS - */ - int (*set_params) (void *params); - /* - * Pointer to function to get parameter. Used - * for implementing VPFE_G_CCDC_PARAMS - */ - int (*get_params) (void *params); /* Pointer to function to configure ccdc */ int (*configure) (void); diff --git a/drivers/media/platform/davinci/dm355_ccdc.c b/drivers/media/platform/davinci/dm355_ccdc.c index 73db166dc338..6d492dc4c3a9 100644 --- a/drivers/media/platform/davinci/dm355_ccdc.c +++ b/drivers/media/platform/davinci/dm355_ccdc.c @@ -17,12 +17,7 @@ * This module is for configuring DM355 CCD controller of VPFE to capture * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules * such as Defect Pixel Correction, Color Space Conversion etc to - * pre-process the Bayer RGB data, before writing it to SDRAM. This - * module also allows application to configure individual - * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL. - * To do so, application include dm355_ccdc.h and vpfe_capture.h header - * files. The setparams() API is called by vpfe_capture driver - * to configure module parameters + * pre-process the Bayer RGB data, before writing it to SDRAM. * * TODO: 1) Raw bayer parameter settings and bayer capture * 2) Split module parameter structure to module specific ioctl structs @@ -260,90 +255,6 @@ static void ccdc_setwin(struct v4l2_rect *image_win, dev_dbg(ccdc_cfg.dev, "\nEnd of ccdc_setwin..."); } -static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) -{ - if (ccdcparam->datasft < CCDC_DATA_NO_SHIFT || - ccdcparam->datasft > CCDC_DATA_SHIFT_6BIT) { - dev_dbg(ccdc_cfg.dev, "Invalid value of data shift\n"); - return -EINVAL; - } - - if (ccdcparam->mfilt1 < CCDC_NO_MEDIAN_FILTER1 || - ccdcparam->mfilt1 > CCDC_MEDIAN_FILTER1) { - dev_dbg(ccdc_cfg.dev, "Invalid value of median filter1\n"); - return -EINVAL; - } - - if (ccdcparam->mfilt2 < CCDC_NO_MEDIAN_FILTER2 || - ccdcparam->mfilt2 > CCDC_MEDIAN_FILTER2) { - dev_dbg(ccdc_cfg.dev, "Invalid value of median filter2\n"); - return -EINVAL; - } - - if ((ccdcparam->med_filt_thres < 0) || - (ccdcparam->med_filt_thres > CCDC_MED_FILT_THRESH)) { - dev_dbg(ccdc_cfg.dev, - "Invalid value of median filter threshold\n"); - return -EINVAL; - } - - if (ccdcparam->data_sz < CCDC_DATA_16BITS || - ccdcparam->data_sz > CCDC_DATA_8BITS) { - dev_dbg(ccdc_cfg.dev, "Invalid value of data size\n"); - return -EINVAL; - } - - if (ccdcparam->alaw.enable) { - if (ccdcparam->alaw.gamma_wd < CCDC_GAMMA_BITS_13_4 || - ccdcparam->alaw.gamma_wd > CCDC_GAMMA_BITS_09_0) { - dev_dbg(ccdc_cfg.dev, "Invalid value of ALAW\n"); - return -EINVAL; - } - } - - if (ccdcparam->blk_clamp.b_clamp_enable) { - if (ccdcparam->blk_clamp.sample_pixel < CCDC_SAMPLE_1PIXELS || - ccdcparam->blk_clamp.sample_pixel > CCDC_SAMPLE_16PIXELS) { - dev_dbg(ccdc_cfg.dev, - "Invalid value of sample pixel\n"); - return -EINVAL; - } - if (ccdcparam->blk_clamp.sample_ln < CCDC_SAMPLE_1LINES || - ccdcparam->blk_clamp.sample_ln > CCDC_SAMPLE_16LINES) { - dev_dbg(ccdc_cfg.dev, - "Invalid value of sample lines\n"); - return -EINVAL; - } - } - return 0; -} - -/* Parameter operations */ -static int ccdc_set_params(void __user *params) -{ - struct ccdc_config_params_raw ccdc_raw_params; - int x; - - /* only raw module parameters can be set through the IOCTL */ - if (ccdc_cfg.if_type != VPFE_RAW_BAYER) - return -EINVAL; - - x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); - if (x) { - dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copying ccdcparams, %d\n", - x); - return -EFAULT; - } - - if (!validate_ccdc_param(&ccdc_raw_params)) { - memcpy(&ccdc_cfg.bayer.config_params, - &ccdc_raw_params, - sizeof(ccdc_raw_params)); - return 0; - } - return -EINVAL; -} - /* This function will configure CCDC for YCbCr video capture */ static void ccdc_config_ycbcr(void) { @@ -939,7 +850,6 @@ static struct ccdc_hw_device ccdc_hw_dev = { .enable = ccdc_enable, .enable_out_to_sdram = ccdc_enable_output_to_sdram, .set_hw_if_params = ccdc_set_hw_if_params, - .set_params = ccdc_set_params, .configure = ccdc_configure, .set_buftype = ccdc_set_buftype, .get_buftype = ccdc_get_buftype, diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c index 740fbc7a8c14..3b2d8a9317b8 100644 --- a/drivers/media/platform/davinci/dm644x_ccdc.c +++ b/drivers/media/platform/davinci/dm644x_ccdc.c @@ -17,13 +17,9 @@ * This module is for configuring CCD controller of DM6446 VPFE to capture * Raw yuv or Bayer RGB data from a decoder. CCDC has several modules * such as Defect Pixel Correction, Color Space Conversion etc to - * pre-process the Raw Bayer RGB data, before writing it to SDRAM. This - * module also allows application to configure individual - * module parameters through VPFE_CMD_S_CCDC_RAW_PARAMS IOCTL. - * To do so, application includes dm644x_ccdc.h and vpfe_capture.h header - * files. The setparams() API is called by vpfe_capture driver - * to configure module parameters. This file is named DM644x so that other - * variants such DM6443 may be supported using the same module. + * pre-process the Raw Bayer RGB data, before writing it to SDRAM. + * This file is named DM644x so that other variants such DM6443 + * may be supported using the same module. * * TODO: Test Raw bayer parameter settings and bayer capture * Split module parameter structure to module specific ioctl structs @@ -216,96 +212,8 @@ static void ccdc_readregs(void) dev_notice(ccdc_cfg.dev, "\nReading 0x%x to VERT_LINES...\n", val); } -static int validate_ccdc_param(struct ccdc_config_params_raw *ccdcparam) -{ - if (ccdcparam->alaw.enable) { - u8 max_gamma = ccdc_gamma_width_max_bit(ccdcparam->alaw.gamma_wd); - u8 max_data = ccdc_data_size_max_bit(ccdcparam->data_sz); - - if ((ccdcparam->alaw.gamma_wd > CCDC_GAMMA_BITS_09_0) || - (ccdcparam->alaw.gamma_wd < CCDC_GAMMA_BITS_15_6) || - (max_gamma > max_data)) { - dev_dbg(ccdc_cfg.dev, "\nInvalid data line select"); - return -1; - } - } - return 0; -} - -static int ccdc_update_raw_params(struct ccdc_config_params_raw *raw_params) -{ - struct ccdc_config_params_raw *config_params = - &ccdc_cfg.bayer.config_params; - unsigned int *fpc_virtaddr = NULL; - unsigned int *fpc_physaddr = NULL; - - memcpy(config_params, raw_params, sizeof(*raw_params)); - /* - * allocate memory for fault pixel table and copy the user - * values to the table - */ - if (!config_params->fault_pxl.enable) - return 0; - - fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; - fpc_virtaddr = (unsigned int *)phys_to_virt( - (unsigned long)fpc_physaddr); - /* - * Allocate memory for FPC table if current - * FPC table buffer is not big enough to - * accommodate FPC Number requested - */ - if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) { - if (fpc_physaddr != NULL) { - free_pages((unsigned long)fpc_virtaddr, - get_order - (config_params->fault_pxl.fp_num * - FP_NUM_BYTES)); - } - - /* Allocate memory for FPC table */ - fpc_virtaddr = - (unsigned int *)__get_free_pages(GFP_KERNEL | GFP_DMA, - get_order(raw_params-> - fault_pxl.fp_num * - FP_NUM_BYTES)); - - if (fpc_virtaddr == NULL) { - dev_dbg(ccdc_cfg.dev, - "\nUnable to allocate memory for FPC"); - return -EFAULT; - } - fpc_physaddr = - (unsigned int *)virt_to_phys((void *)fpc_virtaddr); - } - - /* Copy number of fault pixels and FPC table */ - config_params->fault_pxl.fp_num = raw_params->fault_pxl.fp_num; - if (copy_from_user(fpc_virtaddr, - (void __user *)raw_params->fault_pxl.fpc_table_addr, - config_params->fault_pxl.fp_num * FP_NUM_BYTES)) { - dev_dbg(ccdc_cfg.dev, "\n copy_from_user failed"); - return -EFAULT; - } - config_params->fault_pxl.fpc_table_addr = (unsigned long)fpc_physaddr; - return 0; -} - static int ccdc_close(struct device *dev) { - struct ccdc_config_params_raw *config_params = - &ccdc_cfg.bayer.config_params; - unsigned int *fpc_physaddr = NULL, *fpc_virtaddr = NULL; - - fpc_physaddr = (unsigned int *)config_params->fault_pxl.fpc_table_addr; - - if (fpc_physaddr != NULL) { - fpc_virtaddr = (unsigned int *) - phys_to_virt((unsigned long)fpc_physaddr); - free_pages((unsigned long)fpc_virtaddr, - get_order(config_params->fault_pxl.fp_num * - FP_NUM_BYTES)); - } return 0; } @@ -339,29 +247,6 @@ static void ccdc_sbl_reset(void) vpss_clear_wbl_overflow(VPSS_PCR_CCDC_WBL_O); } -/* Parameter operations */ -static int ccdc_set_params(void __user *params) -{ - struct ccdc_config_params_raw ccdc_raw_params; - int x; - - if (ccdc_cfg.if_type != VPFE_RAW_BAYER) - return -EINVAL; - - x = copy_from_user(&ccdc_raw_params, params, sizeof(ccdc_raw_params)); - if (x) { - dev_dbg(ccdc_cfg.dev, "ccdc_set_params: error in copyingccdc params, %d\n", - x); - return -EFAULT; - } - - if (!validate_ccdc_param(&ccdc_raw_params)) { - if (!ccdc_update_raw_params(&ccdc_raw_params)) - return 0; - } - return -EINVAL; -} - /* * ccdc_config_ycbcr() * This function will configure CCDC for YCbCr video capture @@ -489,32 +374,6 @@ static void ccdc_config_black_compense(struct ccdc_black_compensation *bcomp) regw(val, CCDC_BLKCMP); } -static void ccdc_config_fpc(struct ccdc_fault_pixel *fpc) -{ - u32 val; - - /* Initially disable FPC */ - val = CCDC_FPC_DISABLE; - regw(val, CCDC_FPC); - - if (!fpc->enable) - return; - - /* Configure Fault pixel if needed */ - regw(fpc->fpc_table_addr, CCDC_FPC_ADDR); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%lx to FPC_ADDR...\n", - (fpc->fpc_table_addr)); - /* Write the FPC params with FPC disable */ - val = fpc->fp_num & CCDC_FPC_FPC_NUM_MASK; - regw(val, CCDC_FPC); - - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val); - /* read the FPC register */ - val = regr(CCDC_FPC) | CCDC_FPC_ENABLE; - regw(val, CCDC_FPC); - dev_dbg(ccdc_cfg.dev, "\nWriting 0x%x to FPC...\n", val); -} - /* * ccdc_config_raw() * This function will configure CCDC for Raw capture mode @@ -569,9 +428,6 @@ static void ccdc_config_raw(void) /* Configure Black level compensation */ ccdc_config_black_compense(&config_params->blk_comp); - /* Configure Fault Pixel Correction */ - ccdc_config_fpc(&config_params->fault_pxl); - /* If data size is 8 bit then pack the data */ if ((config_params->data_sz == CCDC_DATA_8BITS) || config_params->alaw.enable) @@ -929,7 +785,6 @@ static struct ccdc_hw_device ccdc_hw_dev = { .reset = ccdc_sbl_reset, .enable = ccdc_enable, .set_hw_if_params = ccdc_set_hw_if_params, - .set_params = ccdc_set_params, .configure = ccdc_configure, .set_buftype = ccdc_set_buftype, .get_buftype = ccdc_get_buftype, diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c index e3fe3e0635aa..b1bf4a7e8eb7 100644 --- a/drivers/media/platform/davinci/vpfe_capture.c +++ b/drivers/media/platform/davinci/vpfe_capture.c @@ -281,45 +281,6 @@ void vpfe_unregister_ccdc_device(struct ccdc_hw_device *dev) EXPORT_SYMBOL(vpfe_unregister_ccdc_device); /* - * vpfe_get_ccdc_image_format - Get image parameters based on CCDC settings - */ -static int vpfe_get_ccdc_image_format(struct vpfe_device *vpfe_dev, - struct v4l2_format *f) -{ - struct v4l2_rect image_win; - enum ccdc_buftype buf_type; - enum ccdc_frmfmt frm_fmt; - - memset(f, 0, sizeof(*f)); - f->type = V4L2_BUF_TYPE_VIDEO_OUTPUT; - ccdc_dev->hw_ops.get_image_window(&image_win); - f->fmt.pix.width = image_win.width; - f->fmt.pix.height = image_win.height; - f->fmt.pix.bytesperline = ccdc_dev->hw_ops.get_line_length(); - f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * - f->fmt.pix.height; - buf_type = ccdc_dev->hw_ops.get_buftype(); - f->fmt.pix.pixelformat = ccdc_dev->hw_ops.get_pixel_format(); - frm_fmt = ccdc_dev->hw_ops.get_frame_format(); - if (frm_fmt == CCDC_FRMFMT_PROGRESSIVE) - f->fmt.pix.field = V4L2_FIELD_NONE; - else if (frm_fmt == CCDC_FRMFMT_INTERLACED) { - if (buf_type == CCDC_BUFTYPE_FLD_INTERLEAVED) - f->fmt.pix.field = V4L2_FIELD_INTERLACED; - else if (buf_type == CCDC_BUFTYPE_FLD_SEPARATED) - f->fmt.pix.field = V4L2_FIELD_SEQ_TB; - else { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf_type\n"); - return -EINVAL; - } - } else { - v4l2_err(&vpfe_dev->v4l2_dev, "Invalid frm_fmt\n"); - return -EINVAL; - } - return 0; -} - -/* * vpfe_config_ccdc_image_format() * For a pix format, configure ccdc to setup the capture */ @@ -1697,59 +1658,6 @@ unlock_out: return ret; } - -static long vpfe_param_handler(struct file *file, void *priv, - bool valid_prio, unsigned int cmd, void *param) -{ - struct vpfe_device *vpfe_dev = video_drvdata(file); - int ret; - - v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n"); - - if (vpfe_dev->started) { - /* only allowed if streaming is not started */ - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "device already started\n"); - return -EBUSY; - } - - ret = mutex_lock_interruptible(&vpfe_dev->lock); - if (ret) - return ret; - - switch (cmd) { - case VPFE_CMD_S_CCDC_RAW_PARAMS: - v4l2_warn(&vpfe_dev->v4l2_dev, - "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); - if (ccdc_dev->hw_ops.set_params) { - ret = ccdc_dev->hw_ops.set_params(param); - if (ret) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "Error setting parameters in CCDC\n"); - goto unlock_out; - } - ret = vpfe_get_ccdc_image_format(vpfe_dev, - &vpfe_dev->fmt); - if (ret < 0) { - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "Invalid image format at CCDC\n"); - goto unlock_out; - } - } else { - ret = -EINVAL; - v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, - "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n"); - } - break; - default: - ret = -ENOTTY; - } -unlock_out: - mutex_unlock(&vpfe_dev->lock); - return ret; -} - - /* vpfe capture ioctl operations */ static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { .vidioc_querycap = vpfe_querycap, @@ -1772,7 +1680,6 @@ static const struct v4l2_ioctl_ops vpfe_ioctl_ops = { .vidioc_cropcap = vpfe_cropcap, .vidioc_g_selection = vpfe_g_selection, .vidioc_s_selection = vpfe_s_selection, - .vidioc_default = vpfe_param_handler, }; static struct vpfe_device *vpfe_initialize(void) diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c index d78580f9e431..4be6554c56c5 100644 --- a/drivers/media/platform/davinci/vpif_capture.c +++ b/drivers/media/platform/davinci/vpif_capture.c @@ -1719,7 +1719,6 @@ vpif_unregister: */ static int vpif_remove(struct platform_device *device) { - struct common_obj *common; struct channel_obj *ch; int i; @@ -1730,7 +1729,6 @@ static int vpif_remove(struct platform_device *device) for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) { /* Get the pointer to the channel object */ ch = vpif_obj.dev[i]; - common = &ch->common[VPIF_VIDEO_INDEX]; /* Unregister video device */ video_unregister_device(&ch->video_dev); kfree(vpif_obj.dev[i]); diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c index b5ac6ce626b3..bf982bf86542 100644 --- a/drivers/media/platform/davinci/vpif_display.c +++ b/drivers/media/platform/davinci/vpif_display.c @@ -1339,7 +1339,6 @@ vpif_unregister: */ static int vpif_remove(struct platform_device *device) { - struct common_obj *common; struct channel_obj *ch; int i; @@ -1350,7 +1349,6 @@ static int vpif_remove(struct platform_device *device) for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) { /* Get the pointer to the channel object */ ch = vpif_obj.dev[i]; - common = &ch->common[VPIF_VIDEO_INDEX]; /* Unregister video device */ video_unregister_device(&ch->video_dev); kfree(vpif_obj.dev[i]); diff --git a/drivers/media/platform/omap/omap_vout_vrfb.c b/drivers/media/platform/omap/omap_vout_vrfb.c index 92c4e1826356..45a553d4f5b2 100644 --- a/drivers/media/platform/omap/omap_vout_vrfb.c +++ b/drivers/media/platform/omap/omap_vout_vrfb.c @@ -16,7 +16,6 @@ #include <media/videobuf-dma-contig.h> #include <media/v4l2-device.h> -#include <linux/omap-dma.h> #include <video/omapvrfb.h> #include "omap_voutdef.h" @@ -63,7 +62,7 @@ static int omap_vout_allocate_vrfb_buffers(struct omap_vout_device *vout, /* * Wakes up the application once the DMA transfer to VRFB space is completed. */ -static void omap_vout_vrfb_dma_tx_callback(int lch, u16 ch_status, void *data) +static void omap_vout_vrfb_dma_tx_callback(void *data) { struct vid_vrfb_dma *t = (struct vid_vrfb_dma *) data; @@ -94,6 +93,7 @@ int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num, int ret = 0, i, j; struct omap_vout_device *vout; struct video_device *vfd; + dma_cap_mask_t mask; int image_width, image_height; int vrfb_num_bufs = VRFB_NUM_BUFS; struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev); @@ -131,18 +131,27 @@ int omap_vout_setup_vrfb_bufs(struct platform_device *pdev, int vid_num, /* * Request and Initialize DMA, for DMA based VRFB transfer */ - vout->vrfb_dma_tx.dev_id = OMAP_DMA_NO_DEVICE; - vout->vrfb_dma_tx.dma_ch = -1; - vout->vrfb_dma_tx.req_status = DMA_CHAN_ALLOTED; - ret = omap_request_dma(vout->vrfb_dma_tx.dev_id, "VRFB DMA TX", - omap_vout_vrfb_dma_tx_callback, - (void *) &vout->vrfb_dma_tx, &vout->vrfb_dma_tx.dma_ch); - if (ret < 0) { + dma_cap_zero(mask); + dma_cap_set(DMA_INTERLEAVE, mask); + vout->vrfb_dma_tx.chan = dma_request_chan_by_mask(&mask); + if (IS_ERR(vout->vrfb_dma_tx.chan)) { vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; + } else { + size_t xt_size = sizeof(struct dma_interleaved_template) + + sizeof(struct data_chunk); + + vout->vrfb_dma_tx.xt = kzalloc(xt_size, GFP_KERNEL); + if (!vout->vrfb_dma_tx.xt) { + dma_release_channel(vout->vrfb_dma_tx.chan); + vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; + } + } + + if (vout->vrfb_dma_tx.req_status == DMA_CHAN_NOT_ALLOTED) dev_info(&pdev->dev, ": failed to allocate DMA Channel for video%d\n", vfd->minor); - } + init_waitqueue_head(&vout->vrfb_dma_tx.wait); /* statically allocated the VRFB buffer is done through @@ -177,7 +186,9 @@ void omap_vout_release_vrfb(struct omap_vout_device *vout) if (vout->vrfb_dma_tx.req_status == DMA_CHAN_ALLOTED) { vout->vrfb_dma_tx.req_status = DMA_CHAN_NOT_ALLOTED; - omap_free_dma(vout->vrfb_dma_tx.dma_ch); + kfree(vout->vrfb_dma_tx.xt); + dmaengine_terminate_sync(vout->vrfb_dma_tx.chan); + dma_release_channel(vout->vrfb_dma_tx.chan); } } @@ -219,70 +230,84 @@ int omap_vout_vrfb_buffer_setup(struct omap_vout_device *vout, } int omap_vout_prepare_vrfb(struct omap_vout_device *vout, - struct videobuf_buffer *vb) + struct videobuf_buffer *vb) { - dma_addr_t dmabuf; - struct vid_vrfb_dma *tx; + struct dma_async_tx_descriptor *tx; + enum dma_ctrl_flags flags; + struct dma_chan *chan = vout->vrfb_dma_tx.chan; + struct dma_device *dmadev = chan->device; + struct dma_interleaved_template *xt = vout->vrfb_dma_tx.xt; + dma_cookie_t cookie; + enum dma_status status; enum dss_rotation rotation; - u32 dest_frame_index = 0, src_element_index = 0; - u32 dest_element_index = 0, src_frame_index = 0; - u32 elem_count = 0, frame_count = 0, pixsize = 2; + size_t dst_icg; + u32 pixsize; if (!is_rotation_enabled(vout)) return 0; - dmabuf = vout->buf_phy_addr[vb->i]; /* If rotation is enabled, copy input buffer into VRFB * memory space using DMA. We are copying input buffer * into VRFB memory space of desired angle and DSS will * read image VRFB memory for 0 degree angle */ + pixsize = vout->bpp * vout->vrfb_bpp; - /* - * DMA transfer in double index mode - */ + dst_icg = ((MAX_PIXELS_PER_LINE * pixsize) - + (vout->pix.width * vout->bpp)) + 1; + + xt->src_start = vout->buf_phy_addr[vb->i]; + xt->dst_start = vout->vrfb_context[vb->i].paddr[0]; + + xt->numf = vout->pix.height; + xt->frame_size = 1; + xt->sgl[0].size = vout->pix.width * vout->bpp; + xt->sgl[0].icg = dst_icg; + + xt->dir = DMA_MEM_TO_MEM; + xt->src_sgl = false; + xt->src_inc = true; + xt->dst_sgl = true; + xt->dst_inc = true; + + tx = dmadev->device_prep_interleaved_dma(chan, xt, flags); + if (tx == NULL) { + pr_err("%s: DMA interleaved prep error\n", __func__); + return -EINVAL; + } - /* Frame index */ - dest_frame_index = ((MAX_PIXELS_PER_LINE * pixsize) - - (vout->pix.width * vout->bpp)) + 1; - - /* Source and destination parameters */ - src_element_index = 0; - src_frame_index = 0; - dest_element_index = 1; - /* Number of elements per frame */ - elem_count = vout->pix.width * vout->bpp; - frame_count = vout->pix.height; - tx = &vout->vrfb_dma_tx; - tx->tx_status = 0; - omap_set_dma_transfer_params(tx->dma_ch, OMAP_DMA_DATA_TYPE_S32, - (elem_count / 4), frame_count, OMAP_DMA_SYNC_ELEMENT, - tx->dev_id, 0x0); - /* src_port required only for OMAP1 */ - omap_set_dma_src_params(tx->dma_ch, 0, OMAP_DMA_AMODE_POST_INC, - dmabuf, src_element_index, src_frame_index); - /*set dma source burst mode for VRFB */ - omap_set_dma_src_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); - rotation = calc_rotation(vout); + tx->callback = omap_vout_vrfb_dma_tx_callback; + tx->callback_param = &vout->vrfb_dma_tx; + + cookie = dmaengine_submit(tx); + if (dma_submit_error(cookie)) { + pr_err("%s: dmaengine_submit failed (%d)\n", __func__, cookie); + return -EINVAL; + } - /* dest_port required only for OMAP1 */ - omap_set_dma_dest_params(tx->dma_ch, 0, OMAP_DMA_AMODE_DOUBLE_IDX, - vout->vrfb_context[vb->i].paddr[0], dest_element_index, - dest_frame_index); - /*set dma dest burst mode for VRFB */ - omap_set_dma_dest_burst_mode(tx->dma_ch, OMAP_DMA_DATA_BURST_16); - omap_dma_set_global_params(DMA_DEFAULT_ARB_RATE, 0x20, 0); + vout->vrfb_dma_tx.tx_status = 0; + dma_async_issue_pending(chan); - omap_start_dma(tx->dma_ch); - wait_event_interruptible_timeout(tx->wait, tx->tx_status == 1, + wait_event_interruptible_timeout(vout->vrfb_dma_tx.wait, + vout->vrfb_dma_tx.tx_status == 1, VRFB_TX_TIMEOUT); - if (tx->tx_status == 0) { - omap_stop_dma(tx->dma_ch); + status = dma_async_is_tx_complete(chan, cookie, NULL, NULL); + + if (vout->vrfb_dma_tx.tx_status == 0) { + pr_err("%s: Timeout while waiting for DMA\n", __func__); + dmaengine_terminate_sync(chan); + return -EINVAL; + } else if (status != DMA_COMPLETE) { + pr_err("%s: DMA completion %s status\n", __func__, + status == DMA_ERROR ? "error" : "busy"); + dmaengine_terminate_sync(chan); return -EINVAL; } + /* Store buffers physical address into an array. Addresses * from this array will be used to configure DSS */ + rotation = calc_rotation(vout); vout->queued_buf_addr[vb->i] = (u8 *) vout->vrfb_context[vb->i].paddr[rotation]; return 0; diff --git a/drivers/media/platform/omap/omap_voutdef.h b/drivers/media/platform/omap/omap_voutdef.h index 80c79fabdf95..56b630b1c8b4 100644 --- a/drivers/media/platform/omap/omap_voutdef.h +++ b/drivers/media/platform/omap/omap_voutdef.h @@ -14,6 +14,7 @@ #include <media/v4l2-ctrls.h> #include <video/omapfb_dss.h> #include <video/omapvrfb.h> +#include <linux/dmaengine.h> #define YUYV_BPP 2 #define RGB565_BPP 2 @@ -81,8 +82,9 @@ enum vout_rotaion_type { * for VRFB hidden buffer */ struct vid_vrfb_dma { - int dev_id; - int dma_ch; + struct dma_chan *chan; + struct dma_interleaved_template *xt; + int req_status; int tx_status; wait_queue_head_t wait; diff --git a/drivers/media/platform/qcom/venus/core.c b/drivers/media/platform/qcom/venus/core.c index 776d2bae6979..41eef376eb2d 100644 --- a/drivers/media/platform/qcom/venus/core.c +++ b/drivers/media/platform/qcom/venus/core.c @@ -76,7 +76,7 @@ static void venus_sys_error_handler(struct work_struct *work) hfi_core_deinit(core, true); hfi_destroy(core); mutex_lock(&core->lock); - venus_shutdown(&core->dev_fw); + venus_shutdown(core->dev); pm_runtime_put_sync(core->dev); @@ -84,7 +84,7 @@ static void venus_sys_error_handler(struct work_struct *work) pm_runtime_get_sync(core->dev); - ret |= venus_boot(core->dev, &core->dev_fw, core->res->fwname); + ret |= venus_boot(core->dev, core->res->fwname); ret |= hfi_core_resume(core, true); @@ -137,7 +137,7 @@ static int venus_clks_enable(struct venus_core *core) return 0; err: - while (--i) + while (i--) clk_disable_unprepare(core->clks[i]); return ret; @@ -207,7 +207,7 @@ static int venus_probe(struct platform_device *pdev) if (ret < 0) goto err_runtime_disable; - ret = venus_boot(dev, &core->dev_fw, core->res->fwname); + ret = venus_boot(dev, core->res->fwname); if (ret) goto err_runtime_disable; @@ -238,7 +238,7 @@ err_dev_unregister: err_core_deinit: hfi_core_deinit(core, false); err_venus_shutdown: - venus_shutdown(&core->dev_fw); + venus_shutdown(dev); err_runtime_disable: pm_runtime_set_suspended(dev); pm_runtime_disable(dev); @@ -259,7 +259,7 @@ static int venus_remove(struct platform_device *pdev) WARN_ON(ret); hfi_destroy(core); - venus_shutdown(&core->dev_fw); + venus_shutdown(dev); of_platform_depopulate(dev); pm_runtime_put_sync(dev); @@ -270,8 +270,7 @@ static int venus_remove(struct platform_device *pdev) return ret; } -#ifdef CONFIG_PM -static int venus_runtime_suspend(struct device *dev) +static __maybe_unused int venus_runtime_suspend(struct device *dev) { struct venus_core *core = dev_get_drvdata(dev); int ret; @@ -283,7 +282,7 @@ static int venus_runtime_suspend(struct device *dev) return ret; } -static int venus_runtime_resume(struct device *dev) +static __maybe_unused int venus_runtime_resume(struct device *dev) { struct venus_core *core = dev_get_drvdata(dev); int ret; @@ -302,7 +301,6 @@ err_clks_disable: venus_clks_disable(core); return ret; } -#endif static const struct dev_pm_ops venus_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, diff --git a/drivers/media/platform/qcom/venus/core.h b/drivers/media/platform/qcom/venus/core.h index e542700eee32..cba092bcb76d 100644 --- a/drivers/media/platform/qcom/venus/core.h +++ b/drivers/media/platform/qcom/venus/core.h @@ -101,7 +101,6 @@ struct venus_core { struct device *dev; struct device *dev_dec; struct device *dev_enc; - struct device dev_fw; struct mutex lock; struct list_head instances; atomic_t insts_count; diff --git a/drivers/media/platform/qcom/venus/firmware.c b/drivers/media/platform/qcom/venus/firmware.c index 1b1a4f355918..521d4b36c090 100644 --- a/drivers/media/platform/qcom/venus/firmware.c +++ b/drivers/media/platform/qcom/venus/firmware.c @@ -12,97 +12,87 @@ * */ -#include <linux/dma-mapping.h> +#include <linux/device.h> #include <linux/firmware.h> #include <linux/kernel.h> +#include <linux/io.h> #include <linux/of.h> -#include <linux/of_reserved_mem.h> -#include <linux/slab.h> +#include <linux/of_address.h> #include <linux/qcom_scm.h> +#include <linux/sizes.h> #include <linux/soc/qcom/mdt_loader.h> #include "firmware.h" #define VENUS_PAS_ID 9 -#define VENUS_FW_MEM_SIZE SZ_8M +#define VENUS_FW_MEM_SIZE (6 * SZ_1M) -static void device_release_dummy(struct device *dev) -{ - of_reserved_mem_device_release(dev); -} - -int venus_boot(struct device *parent, struct device *fw_dev, const char *fwname) +int venus_boot(struct device *dev, const char *fwname) { const struct firmware *mdt; + struct device_node *node; phys_addr_t mem_phys; + struct resource r; ssize_t fw_size; size_t mem_size; void *mem_va; int ret; - if (!qcom_scm_is_available()) + if (!IS_ENABLED(CONFIG_QCOM_MDT_LOADER) || !qcom_scm_is_available()) return -EPROBE_DEFER; - fw_dev->parent = parent; - fw_dev->release = device_release_dummy; + node = of_parse_phandle(dev->of_node, "memory-region", 0); + if (!node) { + dev_err(dev, "no memory-region specified\n"); + return -EINVAL; + } - ret = dev_set_name(fw_dev, "%s:%s", dev_name(parent), "firmware"); + ret = of_address_to_resource(node, 0, &r); if (ret) return ret; - ret = device_register(fw_dev); - if (ret < 0) - return ret; + mem_phys = r.start; + mem_size = resource_size(&r); - ret = of_reserved_mem_device_init_by_idx(fw_dev, parent->of_node, 0); - if (ret) - goto err_unreg_device; + if (mem_size < VENUS_FW_MEM_SIZE) + return -EINVAL; - mem_size = VENUS_FW_MEM_SIZE; - - mem_va = dmam_alloc_coherent(fw_dev, mem_size, &mem_phys, GFP_KERNEL); + mem_va = memremap(r.start, mem_size, MEMREMAP_WC); if (!mem_va) { - ret = -ENOMEM; - goto err_unreg_device; + dev_err(dev, "unable to map memory region: %pa+%zx\n", + &r.start, mem_size); + return -ENOMEM; } - ret = request_firmware(&mdt, fwname, fw_dev); + ret = request_firmware(&mdt, fwname, dev); if (ret < 0) - goto err_unreg_device; + goto err_unmap; fw_size = qcom_mdt_get_size(mdt); if (fw_size < 0) { ret = fw_size; release_firmware(mdt); - goto err_unreg_device; + goto err_unmap; } - ret = qcom_mdt_load(fw_dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys, + ret = qcom_mdt_load(dev, mdt, fwname, VENUS_PAS_ID, mem_va, mem_phys, mem_size); release_firmware(mdt); if (ret) - goto err_unreg_device; + goto err_unmap; ret = qcom_scm_pas_auth_and_reset(VENUS_PAS_ID); if (ret) - goto err_unreg_device; - - return 0; + goto err_unmap; -err_unreg_device: - device_unregister(fw_dev); +err_unmap: + memunmap(mem_va); return ret; } -int venus_shutdown(struct device *fw_dev) +int venus_shutdown(struct device *dev) { - int ret; - - ret = qcom_scm_pas_shutdown(VENUS_PAS_ID); - device_unregister(fw_dev); - memset(fw_dev, 0, sizeof(*fw_dev)); - - return ret; + return qcom_scm_pas_shutdown(VENUS_PAS_ID); } diff --git a/drivers/media/platform/qcom/venus/firmware.h b/drivers/media/platform/qcom/venus/firmware.h index f81a98979798..428efb56d339 100644 --- a/drivers/media/platform/qcom/venus/firmware.h +++ b/drivers/media/platform/qcom/venus/firmware.h @@ -16,8 +16,7 @@ struct device; -int venus_boot(struct device *parent, struct device *fw_dev, - const char *fwname); -int venus_shutdown(struct device *fw_dev); +int venus_boot(struct device *dev, const char *fwname); +int venus_shutdown(struct device *dev); #endif diff --git a/drivers/media/platform/qcom/venus/hfi_msgs.c b/drivers/media/platform/qcom/venus/hfi_msgs.c index f8841713e417..a681ae5381d6 100644 --- a/drivers/media/platform/qcom/venus/hfi_msgs.c +++ b/drivers/media/platform/qcom/venus/hfi_msgs.c @@ -239,11 +239,12 @@ static void hfi_sys_init_done(struct venus_core *core, struct venus_inst *inst, break; } - if (!error) { - rem_bytes -= read_bytes; - data += read_bytes; - num_properties--; - } + if (error) + break; + + rem_bytes -= read_bytes; + data += read_bytes; + num_properties--; } err_no_prop: diff --git a/drivers/media/platform/sti/bdisp/bdisp-debug.c b/drivers/media/platform/sti/bdisp/bdisp-debug.c index 7af66860d624..2cc289e4dea1 100644 --- a/drivers/media/platform/sti/bdisp/bdisp-debug.c +++ b/drivers/media/platform/sti/bdisp/bdisp-debug.c @@ -104,7 +104,7 @@ static void bdisp_dbg_dump_ins(struct seq_file *s, u32 val) if (val & BLT_INS_IRQ) seq_puts(s, "IRQ - "); - seq_puts(s, "\n"); + seq_putc(s, '\n'); } static void bdisp_dbg_dump_tty(struct seq_file *s, u32 val) @@ -153,7 +153,7 @@ static void bdisp_dbg_dump_tty(struct seq_file *s, u32 val) if (val & BLT_TTY_BIG_END) seq_puts(s, "BigEndian - "); - seq_puts(s, "\n"); + seq_putc(s, '\n'); } static void bdisp_dbg_dump_xy(struct seq_file *s, u32 val, char *name) @@ -230,7 +230,7 @@ static void bdisp_dbg_dump_sty(struct seq_file *s, seq_puts(s, "BigEndian - "); done: - seq_puts(s, "\n"); + seq_putc(s, '\n'); } static void bdisp_dbg_dump_fctl(struct seq_file *s, u32 val) @@ -247,7 +247,7 @@ static void bdisp_dbg_dump_fctl(struct seq_file *s, u32 val) else if ((val & BLT_FCTL_HV_SCALE) == BLT_FCTL_HV_SAMPLE) seq_puts(s, "Sample Chroma"); - seq_puts(s, "\n"); + seq_putc(s, '\n'); } static void bdisp_dbg_dump_rsf(struct seq_file *s, u32 val, char *name) @@ -266,7 +266,7 @@ static void bdisp_dbg_dump_rsf(struct seq_file *s, u32 val, char *name) seq_printf(s, "V: %d(6.10) / scale~%dx0.1", inc, 1024 * 10 / inc); done: - seq_puts(s, "\n"); + seq_putc(s, '\n'); } static void bdisp_dbg_dump_rzi(struct seq_file *s, u32 val, char *name) @@ -281,7 +281,7 @@ static void bdisp_dbg_dump_rzi(struct seq_file *s, u32 val, char *name) seq_printf(s, "V: init=%d repeat=%d", val & 0x3FF, (val >> 12) & 7); done: - seq_puts(s, "\n"); + seq_putc(s, '\n'); } static void bdisp_dbg_dump_ivmx(struct seq_file *s, @@ -293,7 +293,7 @@ static void bdisp_dbg_dump_ivmx(struct seq_file *s, seq_printf(s, "IVMX3\t0x%08X\t", c3); if (!c0 && !c1 && !c2 && !c3) { - seq_puts(s, "\n"); + seq_putc(s, '\n'); return; } diff --git a/drivers/media/platform/vimc/vimc-capture.c b/drivers/media/platform/vimc/vimc-capture.c index 14cb32e21130..88a1e5670c72 100644 --- a/drivers/media/platform/vimc/vimc-capture.c +++ b/drivers/media/platform/vimc/vimc-capture.c @@ -517,21 +517,22 @@ static int vimc_cap_remove(struct platform_device *pdev) return 0; } +static const struct platform_device_id vimc_cap_driver_ids[] = { + { + .name = VIMC_CAP_DRV_NAME, + }, + { } +}; + static struct platform_driver vimc_cap_pdrv = { .probe = vimc_cap_probe, .remove = vimc_cap_remove, + .id_table = vimc_cap_driver_ids, .driver = { .name = VIMC_CAP_DRV_NAME, }, }; -static const struct platform_device_id vimc_cap_driver_ids[] = { - { - .name = VIMC_CAP_DRV_NAME, - }, - { } -}; - module_platform_driver(vimc_cap_pdrv); MODULE_DEVICE_TABLE(platform, vimc_cap_driver_ids); diff --git a/drivers/media/platform/vimc/vimc-debayer.c b/drivers/media/platform/vimc/vimc-debayer.c index 35b15bd4d61d..033a131f67af 100644 --- a/drivers/media/platform/vimc/vimc-debayer.c +++ b/drivers/media/platform/vimc/vimc-debayer.c @@ -577,21 +577,22 @@ static int vimc_deb_remove(struct platform_device *pdev) return 0; } +static const struct platform_device_id vimc_deb_driver_ids[] = { + { + .name = VIMC_DEB_DRV_NAME, + }, + { } +}; + static struct platform_driver vimc_deb_pdrv = { .probe = vimc_deb_probe, .remove = vimc_deb_remove, + .id_table = vimc_deb_driver_ids, .driver = { .name = VIMC_DEB_DRV_NAME, }, }; -static const struct platform_device_id vimc_deb_driver_ids[] = { - { - .name = VIMC_DEB_DRV_NAME, - }, - { } -}; - module_platform_driver(vimc_deb_pdrv); MODULE_DEVICE_TABLE(platform, vimc_deb_driver_ids); diff --git a/drivers/media/platform/vimc/vimc-scaler.c b/drivers/media/platform/vimc/vimc-scaler.c index fe77505d2679..0a3e086e12f3 100644 --- a/drivers/media/platform/vimc/vimc-scaler.c +++ b/drivers/media/platform/vimc/vimc-scaler.c @@ -431,21 +431,22 @@ static int vimc_sca_remove(struct platform_device *pdev) return 0; } +static const struct platform_device_id vimc_sca_driver_ids[] = { + { + .name = VIMC_SCA_DRV_NAME, + }, + { } +}; + static struct platform_driver vimc_sca_pdrv = { .probe = vimc_sca_probe, .remove = vimc_sca_remove, + .id_table = vimc_sca_driver_ids, .driver = { .name = VIMC_SCA_DRV_NAME, }, }; -static const struct platform_device_id vimc_sca_driver_ids[] = { - { - .name = VIMC_SCA_DRV_NAME, - }, - { } -}; - module_platform_driver(vimc_sca_pdrv); MODULE_DEVICE_TABLE(platform, vimc_sca_driver_ids); diff --git a/drivers/media/platform/vimc/vimc-sensor.c b/drivers/media/platform/vimc/vimc-sensor.c index ebdbbe8c05ed..615c2b18dcfc 100644 --- a/drivers/media/platform/vimc/vimc-sensor.c +++ b/drivers/media/platform/vimc/vimc-sensor.c @@ -365,21 +365,22 @@ static int vimc_sen_remove(struct platform_device *pdev) return 0; } +static const struct platform_device_id vimc_sen_driver_ids[] = { + { + .name = VIMC_SEN_DRV_NAME, + }, + { } +}; + static struct platform_driver vimc_sen_pdrv = { .probe = vimc_sen_probe, .remove = vimc_sen_remove, + .id_table = vimc_sen_driver_ids, .driver = { .name = VIMC_SEN_DRV_NAME, }, }; -static const struct platform_device_id vimc_sen_driver_ids[] = { - { - .name = VIMC_SEN_DRV_NAME, - }, - { } -}; - module_platform_driver(vimc_sen_pdrv); MODULE_DEVICE_TABLE(platform, vimc_sen_driver_ids); diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index 7240223dc15a..17e82a9a0109 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c @@ -610,10 +610,21 @@ static int wl1273_fm_start(struct wl1273_device *radio, int new_mode) } } - if (radio->rds_on) + if (radio->rds_on) { r = core->write(core, WL1273_RDS_DATA_ENB, 1); - else + if (r) { + dev_err(dev, "%s: RDS_DATA_ENB ON fails\n", + __func__); + goto fail; + } + } else { r = core->write(core, WL1273_RDS_DATA_ENB, 0); + if (r) { + dev_err(dev, "%s: RDS_DATA_ENB OFF fails\n", + __func__); + goto fail; + } + } } else { dev_warn(dev, "%s: Illegal mode.\n", __func__); } diff --git a/drivers/media/rc/ir-lirc-codec.c b/drivers/media/rc/ir-lirc-codec.c index a30af91710fe..d2223c04e9ad 100644 --- a/drivers/media/rc/ir-lirc-codec.c +++ b/drivers/media/rc/ir-lirc-codec.c @@ -266,7 +266,7 @@ static long ir_lirc_ioctl(struct file *filep, unsigned int cmd, if (!dev->rx_resolution) return -ENOTTY; - val = dev->rx_resolution; + val = dev->rx_resolution / 1000; break; case LIRC_SET_WIDEBAND_RECEIVER: diff --git a/drivers/media/tuners/fc0011.c b/drivers/media/tuners/fc0011.c index 192b1c7740df..145407dee3db 100644 --- a/drivers/media/tuners/fc0011.c +++ b/drivers/media/tuners/fc0011.c @@ -342,6 +342,7 @@ static int fc0011_set_params(struct dvb_frontend *fe) switch (vco_sel) { default: WARN_ON(1); + return -EINVAL; case 0: if (vco_cal < 8) { regs[FC11_REG_VCOSEL] &= ~(FC11_VCOSEL_1 | FC11_VCOSEL_2); diff --git a/drivers/media/tuners/mxl5005s.c b/drivers/media/tuners/mxl5005s.c index 353744fee053..dd59c2c0e4a5 100644 --- a/drivers/media/tuners/mxl5005s.c +++ b/drivers/media/tuners/mxl5005s.c @@ -2737,8 +2737,6 @@ static u16 MXL_TuneRF(struct dvb_frontend *fe, u32 RF_Freq) status += MXL_ControlWrite(fe, TG_LO_DIVVAL, 0x0); status += MXL_ControlWrite(fe, TG_LO_SELVAL, 0x7); divider_val = 2 ; - Fmax = FmaxBin ; - Fmin = FminBin ; } /* TG_DIV_VAL */ diff --git a/drivers/media/usb/au0828/au0828-input.c b/drivers/media/usb/au0828/au0828-input.c index 9ec919c68482..9d82ec0a4b64 100644 --- a/drivers/media/usb/au0828/au0828-input.c +++ b/drivers/media/usb/au0828/au0828-input.c @@ -351,7 +351,7 @@ int au0828_rc_register(struct au0828_dev *dev) if (err) goto error; - pr_info("Remote controller %s initalized\n", ir->name); + pr_info("Remote controller %s initialized\n", ir->name); return 0; diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c index 594360a63c18..a91fdad8f8d4 100644 --- a/drivers/media/usb/dvb-usb-v2/lmedm04.c +++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c @@ -207,15 +207,13 @@ static int lme2510_stream_restart(struct dvb_usb_device *d) struct lme2510_state *st = d->priv; u8 all_pids[] = LME_ALL_PIDS; u8 stream_on[] = LME_ST_ON_W; - int ret; u8 rbuff[1]; if (st->pid_off) - ret = lme2510_usb_talk(d, all_pids, sizeof(all_pids), - rbuff, sizeof(rbuff)); + lme2510_usb_talk(d, all_pids, sizeof(all_pids), + rbuff, sizeof(rbuff)); /*Restart Stream Command*/ - ret = lme2510_usb_talk(d, stream_on, sizeof(stream_on), - rbuff, sizeof(rbuff)); - return ret; + return lme2510_usb_talk(d, stream_on, sizeof(stream_on), + rbuff, sizeof(rbuff)); } static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out) diff --git a/drivers/media/usb/dvb-usb/dib0700_core.c b/drivers/media/usb/dvb-usb/dib0700_core.c index 08acdd32e412..bea1b4764a66 100644 --- a/drivers/media/usb/dvb-usb/dib0700_core.c +++ b/drivers/media/usb/dvb-usb/dib0700_core.c @@ -215,13 +215,14 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, USB_CTRL_GET_TIMEOUT); if (result < 0) { deb_info("i2c read error (status = %d)\n", result); - break; + goto unlock; } if (msg[i].len > sizeof(st->buf)) { deb_info("buffer too small to fit %d bytes\n", msg[i].len); - return -EIO; + result = -EIO; + goto unlock; } memcpy(msg[i].buf, st->buf, msg[i].len); @@ -233,8 +234,8 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, /* Write request */ if (mutex_lock_interruptible(&d->usb_mutex) < 0) { err("could not acquire lock"); - mutex_unlock(&d->i2c_mutex); - return -EINTR; + result = -EINTR; + goto unlock; } st->buf[0] = REQUEST_NEW_I2C_WRITE; st->buf[1] = msg[i].addr << 1; @@ -247,7 +248,9 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, if (msg[i].len > sizeof(st->buf) - 4) { deb_info("i2c message to big: %d\n", msg[i].len); - return -EIO; + mutex_unlock(&d->usb_mutex); + result = -EIO; + goto unlock; } /* The Actual i2c payload */ @@ -269,8 +272,11 @@ static int dib0700_i2c_xfer_new(struct i2c_adapter *adap, struct i2c_msg *msg, } } } + result = i; + +unlock: mutex_unlock(&d->i2c_mutex); - return i; + return result; } /* @@ -281,7 +287,7 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, { struct dvb_usb_device *d = i2c_get_adapdata(adap); struct dib0700_state *st = d->priv; - int i,len; + int i, len, result; if (mutex_lock_interruptible(&d->i2c_mutex) < 0) return -EINTR; @@ -298,7 +304,8 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, if (msg[i].len > sizeof(st->buf) - 2) { deb_info("i2c xfer to big: %d\n", msg[i].len); - return -EIO; + result = -EIO; + goto unlock; } memcpy(&st->buf[2], msg[i].buf, msg[i].len); @@ -313,13 +320,15 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, if (len <= 0) { deb_info("I2C read failed on address 0x%02x\n", msg[i].addr); - break; + result = -EIO; + goto unlock; } if (msg[i + 1].len > sizeof(st->buf)) { deb_info("i2c xfer buffer to small for %d\n", msg[i].len); - return -EIO; + result = -EIO; + goto unlock; } memcpy(msg[i + 1].buf, st->buf, msg[i + 1].len); @@ -328,14 +337,17 @@ static int dib0700_i2c_xfer_legacy(struct i2c_adapter *adap, i++; } else { st->buf[0] = REQUEST_I2C_WRITE; - if (dib0700_ctrl_wr(d, st->buf, msg[i].len + 2) < 0) - break; + result = dib0700_ctrl_wr(d, st->buf, msg[i].len + 2); + if (result < 0) + goto unlock; } } + result = i; +unlock: mutex_unlock(&d->usb_mutex); mutex_unlock(&d->i2c_mutex); - return i; + return result; } static int dib0700_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c index 146341aeb782..4c57fd7929cb 100644 --- a/drivers/media/usb/em28xx/em28xx-cards.c +++ b/drivers/media/usb/em28xx/em28xx-cards.c @@ -1193,6 +1193,22 @@ struct em28xx_board em28xx_boards[] = { .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | EM28XX_I2C_FREQ_400_KHZ, }, + [EM2884_BOARD_TERRATEC_H6] = { + .name = "Terratec Cinergy H6 rev. 2", + .has_dvb = 1, + .ir_codes = RC_MAP_NEC_TERRATEC_CINERGY_XS, +#if 0 + .tuner_type = TUNER_PHILIPS_TDA8290, + .tuner_addr = 0x41, + .dvb_gpio = terratec_h5_digital, /* FIXME: probably wrong */ + .tuner_gpio = terratec_h5_gpio, +#else + .tuner_type = TUNER_ABSENT, +#endif + .def_i2c_bus = 1, + .i2c_speed = EM28XX_I2C_CLK_WAIT_ENABLE | + EM28XX_I2C_FREQ_400_KHZ, + }, [EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C] = { .name = "Hauppauge WinTV HVR 930C", .has_dvb = 1, @@ -2496,6 +2512,8 @@ struct usb_device_id em28xx_id_table[] = { .driver_info = EM2884_BOARD_TERRATEC_H5 }, { USB_DEVICE(0x0ccd, 0x10b6), /* H5 Rev. 3 */ .driver_info = EM2884_BOARD_TERRATEC_H5 }, + { USB_DEVICE(0x0ccd, 0x10b2), /* H6 */ + .driver_info = EM2884_BOARD_TERRATEC_H6 }, { USB_DEVICE(0x0ccd, 0x0084), .driver_info = EM2860_BOARD_TERRATEC_AV350 }, { USB_DEVICE(0x0ccd, 0x0096), diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c index 82edd37f0d73..4a7db623fe29 100644 --- a/drivers/media/usb/em28xx/em28xx-dvb.c +++ b/drivers/media/usb/em28xx/em28xx-dvb.c @@ -1522,6 +1522,7 @@ static int em28xx_dvb_init(struct em28xx *dev) break; case EM2884_BOARD_ELGATO_EYETV_HYBRID_2008: case EM2884_BOARD_CINERGY_HTC_STICK: + case EM2884_BOARD_TERRATEC_H6: terratec_htc_stick_init(dev); /* attach demodulator */ diff --git a/drivers/media/usb/em28xx/em28xx-i2c.c b/drivers/media/usb/em28xx/em28xx-i2c.c index 8c472d5adb50..60b195c157b8 100644 --- a/drivers/media/usb/em28xx/em28xx-i2c.c +++ b/drivers/media/usb/em28xx/em28xx-i2c.c @@ -982,8 +982,6 @@ int em28xx_i2c_register(struct em28xx *dev, unsigned bus, dev_err(&dev->intf->dev, "%s: em28xx_i2_eeprom failed! retval [%d]\n", __func__, retval); - - return retval; } } diff --git a/drivers/media/usb/em28xx/em28xx-input.c b/drivers/media/usb/em28xx/em28xx-input.c index eba75736e654..ca9673917ad5 100644 --- a/drivers/media/usb/em28xx/em28xx-input.c +++ b/drivers/media/usb/em28xx/em28xx-input.c @@ -821,7 +821,7 @@ static int em28xx_ir_init(struct em28xx *dev) if (err) goto error; - dev_info(&dev->intf->dev, "Input extension successfully initalized\n"); + dev_info(&dev->intf->dev, "Input extension successfully initialized\n"); return 0; diff --git a/drivers/media/usb/em28xx/em28xx.h b/drivers/media/usb/em28xx/em28xx.h index e8d97d5ec161..88084f24f033 100644 --- a/drivers/media/usb/em28xx/em28xx.h +++ b/drivers/media/usb/em28xx/em28xx.h @@ -148,6 +148,7 @@ #define EM28178_BOARD_PLEX_PX_BCUD 98 #define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_DVB 99 #define EM28174_BOARD_HAUPPAUGE_WINTV_DUALHD_01595 100 +#define EM2884_BOARD_TERRATEC_H6 101 /* Limits minimum and default number of buffers */ #define EM28XX_MIN_BUF 4 diff --git a/drivers/media/usb/pulse8-cec/pulse8-cec.c b/drivers/media/usb/pulse8-cec/pulse8-cec.c index c843070f24c1..f9ed9c950247 100644 --- a/drivers/media/usb/pulse8-cec/pulse8-cec.c +++ b/drivers/media/usb/pulse8-cec/pulse8-cec.c @@ -51,7 +51,7 @@ MODULE_DESCRIPTION("Pulse Eight HDMI CEC driver"); MODULE_LICENSE("GPL"); static int debug; -static int persistent_config = 1; +static int persistent_config; module_param(debug, int, 0644); module_param(persistent_config, int, 0644); MODULE_PARM_DESC(debug, "debug level (0-1)"); diff --git a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c index f203699e9c1b..65692576690f 100644 --- a/drivers/media/usb/rainshadow-cec/rainshadow-cec.c +++ b/drivers/media/usb/rainshadow-cec/rainshadow-cec.c @@ -116,21 +116,19 @@ static void rain_irq_work_handler(struct work_struct *work) while (true) { unsigned long flags; - bool exit_loop = false; char data; spin_lock_irqsave(&rain->buf_lock, flags); - if (rain->buf_len) { - data = rain->buf[rain->buf_rd_idx]; - rain->buf_len--; - rain->buf_rd_idx = (rain->buf_rd_idx + 1) & 0xff; - } else { - exit_loop = true; + if (!rain->buf_len) { + spin_unlock_irqrestore(&rain->buf_lock, flags); + break; } - spin_unlock_irqrestore(&rain->buf_lock, flags); - if (exit_loop) - break; + data = rain->buf[rain->buf_rd_idx]; + rain->buf_len--; + rain->buf_rd_idx = (rain->buf_rd_idx + 1) & 0xff; + + spin_unlock_irqrestore(&rain->buf_lock, flags); if (!rain->cmd_started && data != '?') continue; diff --git a/drivers/media/usb/stkwebcam/stk-sensor.c b/drivers/media/usb/stkwebcam/stk-sensor.c index 985af9933c7e..c1d4505f84ea 100644 --- a/drivers/media/usb/stkwebcam/stk-sensor.c +++ b/drivers/media/usb/stkwebcam/stk-sensor.c @@ -41,6 +41,8 @@ /* It seems the i2c bus is controlled with these registers */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include "stk-webcam.h" #define STK_IIC_BASE (0x0200) @@ -239,8 +241,8 @@ static int stk_sensor_outb(struct stk_camera *dev, u8 reg, u8 val) } while (tmpval == 0 && i < MAX_RETRIES); if (tmpval != STK_IIC_STAT_TX_OK) { if (tmpval) - STK_ERROR("stk_sensor_outb failed, status=0x%02x\n", - tmpval); + pr_err("stk_sensor_outb failed, status=0x%02x\n", + tmpval); return 1; } else return 0; @@ -262,8 +264,8 @@ static int stk_sensor_inb(struct stk_camera *dev, u8 reg, u8 *val) } while (tmpval == 0 && i < MAX_RETRIES); if (tmpval != STK_IIC_STAT_RX_OK) { if (tmpval) - STK_ERROR("stk_sensor_inb failed, status=0x%02x\n", - tmpval); + pr_err("stk_sensor_inb failed, status=0x%02x\n", + tmpval); return 1; } @@ -366,29 +368,29 @@ int stk_sensor_init(struct stk_camera *dev) if (stk_camera_write_reg(dev, STK_IIC_ENABLE, STK_IIC_ENABLE_YES) || stk_camera_write_reg(dev, STK_IIC_ADDR, SENSOR_ADDRESS) || stk_sensor_outb(dev, REG_COM7, COM7_RESET)) { - STK_ERROR("Sensor resetting failed\n"); + pr_err("Sensor resetting failed\n"); return -ENODEV; } msleep(10); /* Read the manufacturer ID: ov = 0x7FA2 */ if (stk_sensor_inb(dev, REG_MIDH, &idh) || stk_sensor_inb(dev, REG_MIDL, &idl)) { - STK_ERROR("Strange error reading sensor ID\n"); + pr_err("Strange error reading sensor ID\n"); return -ENODEV; } if (idh != 0x7f || idl != 0xa2) { - STK_ERROR("Huh? you don't have a sensor from ovt\n"); + pr_err("Huh? you don't have a sensor from ovt\n"); return -ENODEV; } if (stk_sensor_inb(dev, REG_PID, &idh) || stk_sensor_inb(dev, REG_VER, &idl)) { - STK_ERROR("Could not read sensor model\n"); + pr_err("Could not read sensor model\n"); return -ENODEV; } stk_sensor_write_regvals(dev, ov_initvals); msleep(10); - STK_INFO("OmniVision sensor detected, id %02X%02X at address %x\n", - idh, idl, SENSOR_ADDRESS); + pr_info("OmniVision sensor detected, id %02X%02X at address %x\n", + idh, idl, SENSOR_ADDRESS); return 0; } @@ -520,7 +522,8 @@ int stk_sensor_configure(struct stk_camera *dev) case MODE_SXGA: com7 = COM7_FMT_SXGA; dummylines = 0; break; - default: STK_ERROR("Unsupported mode %d\n", dev->vsettings.mode); + default: + pr_err("Unsupported mode %d\n", dev->vsettings.mode); return -EFAULT; } switch (dev->vsettings.palette) { @@ -544,7 +547,8 @@ int stk_sensor_configure(struct stk_camera *dev) com7 |= COM7_PBAYER; rv = ov_fmt_bayer; break; - default: STK_ERROR("Unsupported colorspace\n"); + default: + pr_err("Unsupported colorspace\n"); return -EFAULT; } /*FIXME sometimes the sensor go to a bad state @@ -564,7 +568,7 @@ int stk_sensor_configure(struct stk_camera *dev) switch (dev->vsettings.mode) { case MODE_VGA: if (stk_sensor_set_hw(dev, 302, 1582, 6, 486)) - STK_ERROR("stk_sensor_set_hw failed (VGA)\n"); + pr_err("stk_sensor_set_hw failed (VGA)\n"); break; case MODE_SXGA: case MODE_CIF: @@ -572,7 +576,7 @@ int stk_sensor_configure(struct stk_camera *dev) case MODE_QCIF: /*FIXME These settings seem ignored by the sensor if (stk_sensor_set_hw(dev, 220, 1500, 10, 1034)) - STK_ERROR("stk_sensor_set_hw failed (SXGA)\n"); + pr_err("stk_sensor_set_hw failed (SXGA)\n"); */ break; } diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c index 6e7fc36b658f..90d4a08cda31 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.c +++ b/drivers/media/usb/stkwebcam/stk-webcam.c @@ -18,6 +18,8 @@ * GNU General Public License for more details. */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> @@ -175,15 +177,15 @@ static int stk_start_stream(struct stk_camera *dev) if (!is_present(dev)) return -ENODEV; if (!is_memallocd(dev) || !is_initialised(dev)) { - STK_ERROR("FIXME: Buffers are not allocated\n"); + pr_err("FIXME: Buffers are not allocated\n"); return -EFAULT; } ret = usb_set_interface(dev->udev, 0, 5); if (ret < 0) - STK_ERROR("usb_set_interface failed !\n"); + pr_err("usb_set_interface failed !\n"); if (stk_sensor_wakeup(dev)) - STK_ERROR("error awaking the sensor\n"); + pr_err("error awaking the sensor\n"); stk_camera_read_reg(dev, 0x0116, &value_116); stk_camera_read_reg(dev, 0x0117, &value_117); @@ -224,9 +226,9 @@ static int stk_stop_stream(struct stk_camera *dev) unset_streaming(dev); if (usb_set_interface(dev->udev, 0, 0)) - STK_ERROR("usb_set_interface failed !\n"); + pr_err("usb_set_interface failed !\n"); if (stk_sensor_sleep(dev)) - STK_ERROR("error suspending the sensor\n"); + pr_err("error suspending the sensor\n"); } return 0; } @@ -313,7 +315,7 @@ static void stk_isoc_handler(struct urb *urb) dev = (struct stk_camera *) urb->context; if (dev == NULL) { - STK_ERROR("isoc_handler called with NULL device !\n"); + pr_err("isoc_handler called with NULL device !\n"); return; } @@ -326,14 +328,13 @@ static void stk_isoc_handler(struct urb *urb) spin_lock_irqsave(&dev->spinlock, flags); if (urb->status != -EINPROGRESS && urb->status != 0) { - STK_ERROR("isoc_handler: urb->status == %d\n", urb->status); + pr_err("isoc_handler: urb->status == %d\n", urb->status); goto resubmit; } if (list_empty(&dev->sio_avail)) { /*FIXME Stop streaming after a while */ - (void) (printk_ratelimit() && - STK_ERROR("isoc_handler without available buffer!\n")); + pr_err_ratelimited("isoc_handler without available buffer!\n"); goto resubmit; } fb = list_first_entry(&dev->sio_avail, @@ -343,8 +344,8 @@ static void stk_isoc_handler(struct urb *urb) for (i = 0; i < urb->number_of_packets; i++) { if (urb->iso_frame_desc[i].status != 0) { if (urb->iso_frame_desc[i].status != -EXDEV) - STK_ERROR("Frame %d has error %d\n", i, - urb->iso_frame_desc[i].status); + pr_err("Frame %d has error %d\n", + i, urb->iso_frame_desc[i].status); continue; } framelen = urb->iso_frame_desc[i].actual_length; @@ -368,9 +369,8 @@ static void stk_isoc_handler(struct urb *urb) /* This marks a new frame */ if (fb->v4lbuf.bytesused != 0 && fb->v4lbuf.bytesused != dev->frame_size) { - (void) (printk_ratelimit() && - STK_ERROR("frame %d, bytesused=%d, skipping\n", - i, fb->v4lbuf.bytesused)); + pr_err_ratelimited("frame %d, bytesused=%d, skipping\n", + i, fb->v4lbuf.bytesused); fb->v4lbuf.bytesused = 0; fill = fb->buffer; } else if (fb->v4lbuf.bytesused == dev->frame_size) { @@ -395,8 +395,7 @@ static void stk_isoc_handler(struct urb *urb) /* Our buffer is full !!! */ if (framelen + fb->v4lbuf.bytesused > dev->frame_size) { - (void) (printk_ratelimit() && - STK_ERROR("Frame buffer overflow, lost sync\n")); + pr_err_ratelimited("Frame buffer overflow, lost sync\n"); /*FIXME Do something here? */ continue; } @@ -414,8 +413,8 @@ resubmit: urb->dev = dev->udev; ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret != 0) { - STK_ERROR("Error (%d) re-submitting urb in stk_isoc_handler.\n", - ret); + pr_err("Error (%d) re-submitting urb in stk_isoc_handler\n", + ret); } } @@ -433,32 +432,31 @@ static int stk_prepare_iso(struct stk_camera *dev) udev = dev->udev; if (dev->isobufs) - STK_ERROR("isobufs already allocated. Bad\n"); + pr_err("isobufs already allocated. Bad\n"); else dev->isobufs = kcalloc(MAX_ISO_BUFS, sizeof(*dev->isobufs), GFP_KERNEL); if (dev->isobufs == NULL) { - STK_ERROR("Unable to allocate iso buffers\n"); + pr_err("Unable to allocate iso buffers\n"); return -ENOMEM; } for (i = 0; i < MAX_ISO_BUFS; i++) { if (dev->isobufs[i].data == NULL) { kbuf = kzalloc(ISO_BUFFER_SIZE, GFP_KERNEL); if (kbuf == NULL) { - STK_ERROR("Failed to allocate iso buffer %d\n", - i); + pr_err("Failed to allocate iso buffer %d\n", i); goto isobufs_out; } dev->isobufs[i].data = kbuf; } else - STK_ERROR("isobuf data already allocated\n"); + pr_err("isobuf data already allocated\n"); if (dev->isobufs[i].urb == NULL) { urb = usb_alloc_urb(ISO_FRAMES_PER_DESC, GFP_KERNEL); if (urb == NULL) goto isobufs_out; dev->isobufs[i].urb = urb; } else { - STK_ERROR("Killing URB\n"); + pr_err("Killing URB\n"); usb_kill_urb(dev->isobufs[i].urb); urb = dev->isobufs[i].urb; } @@ -567,7 +565,7 @@ static int stk_prepare_sio_buffers(struct stk_camera *dev, unsigned n_sbufs) { int i; if (dev->sio_bufs != NULL) - STK_ERROR("sio_bufs already allocated\n"); + pr_err("sio_bufs already allocated\n"); else { dev->sio_bufs = kzalloc(n_sbufs * sizeof(struct stk_sio_buffer), GFP_KERNEL); @@ -690,7 +688,7 @@ static ssize_t stk_read(struct file *fp, char __user *buf, spin_lock_irqsave(&dev->spinlock, flags); if (list_empty(&dev->sio_full)) { spin_unlock_irqrestore(&dev->spinlock, flags); - STK_ERROR("BUG: No siobufs ready\n"); + pr_err("BUG: No siobufs ready\n"); return 0; } sbuf = list_first_entry(&dev->sio_full, struct stk_sio_buffer, list); @@ -907,7 +905,7 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp, stk_sizes[i].m != dev->vsettings.mode; i++) ; if (i == ARRAY_SIZE(stk_sizes)) { - STK_ERROR("ERROR: mode invalid\n"); + pr_err("ERROR: mode invalid\n"); return -EINVAL; } pix_format->width = stk_sizes[i].w; @@ -985,7 +983,7 @@ static int stk_setup_format(struct stk_camera *dev) stk_sizes[i].m != dev->vsettings.mode) i++; if (i == ARRAY_SIZE(stk_sizes)) { - STK_ERROR("Something is broken in %s\n", __func__); + pr_err("Something is broken in %s\n", __func__); return -EFAULT; } /* This registers controls some timings, not sure of what. */ @@ -1241,7 +1239,7 @@ static void stk_v4l_dev_release(struct video_device *vd) struct stk_camera *dev = vdev_to_camera(vd); if (dev->sio_bufs != NULL || dev->isobufs != NULL) - STK_ERROR("We are leaking memory\n"); + pr_err("We are leaking memory\n"); usb_put_intf(dev->interface); kfree(dev); } @@ -1264,10 +1262,10 @@ static int stk_register_video_device(struct stk_camera *dev) video_set_drvdata(&dev->vdev, dev); err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1); if (err) - STK_ERROR("v4l registration failed\n"); + pr_err("v4l registration failed\n"); else - STK_INFO("Syntek USB2.0 Camera is now controlling device %s\n", - video_device_node_name(&dev->vdev)); + pr_info("Syntek USB2.0 Camera is now controlling device %s\n", + video_device_node_name(&dev->vdev)); return err; } @@ -1288,7 +1286,7 @@ static int stk_camera_probe(struct usb_interface *interface, dev = kzalloc(sizeof(struct stk_camera), GFP_KERNEL); if (dev == NULL) { - STK_ERROR("Out of memory !\n"); + pr_err("Out of memory !\n"); return -ENOMEM; } err = v4l2_device_register(&interface->dev, &dev->v4l2_dev); @@ -1352,7 +1350,7 @@ static int stk_camera_probe(struct usb_interface *interface, } } if (!dev->isoc_ep) { - STK_ERROR("Could not find isoc-in endpoint"); + pr_err("Could not find isoc-in endpoint\n"); err = -ENODEV; goto error; } @@ -1387,8 +1385,8 @@ static void stk_camera_disconnect(struct usb_interface *interface) wake_up_interruptible(&dev->wait_frame); - STK_INFO("Syntek USB2.0 Camera release resources device %s\n", - video_device_node_name(&dev->vdev)); + pr_info("Syntek USB2.0 Camera release resources device %s\n", + video_device_node_name(&dev->vdev)); video_unregister_device(&dev->vdev); v4l2_ctrl_handler_free(&dev->hdl); diff --git a/drivers/media/usb/stkwebcam/stk-webcam.h b/drivers/media/usb/stkwebcam/stk-webcam.h index 0284120ce246..5cecbdc97573 100644 --- a/drivers/media/usb/stkwebcam/stk-webcam.h +++ b/drivers/media/usb/stkwebcam/stk-webcam.h @@ -31,12 +31,6 @@ #define ISO_MAX_FRAME_SIZE 3 * 1024 #define ISO_BUFFER_SIZE (ISO_FRAMES_PER_DESC * ISO_MAX_FRAME_SIZE) - -#define PREFIX "stkwebcam: " -#define STK_INFO(str, args...) printk(KERN_INFO PREFIX str, ##args) -#define STK_ERROR(str, args...) printk(KERN_ERR PREFIX str, ##args) -#define STK_WARNING(str, args...) printk(KERN_WARNING PREFIX str, ##args) - struct stk_iso_buf { void *data; int length; diff --git a/drivers/media/v4l2-core/tuner-core.c b/drivers/media/v4l2-core/tuner-core.c index e48b7c032c95..8db45dfc271b 100644 --- a/drivers/media/v4l2-core/tuner-core.c +++ b/drivers/media/v4l2-core/tuner-core.c @@ -43,8 +43,6 @@ #define UNSET (-1U) -#define PREFIX (t->i2c->dev.driver->name) - /* * Driver modprobe parameters */ diff --git a/drivers/mmc/core/block.c b/drivers/mmc/core/block.c index 8ac59dc80f23..e5938c791330 100644 --- a/drivers/mmc/core/block.c +++ b/drivers/mmc/core/block.c @@ -2170,6 +2170,7 @@ static void mmc_blk_remove_req(struct mmc_blk_data *md) * from being accepted. */ card = md->queue.card; + queue_flag_set(QUEUE_FLAG_BYPASS, md->queue.queue); blk_set_queue_dying(md->queue.queue); mmc_cleanup_queue(&md->queue); if (md->disk->flags & GENHD_FL_UP) { diff --git a/drivers/mmc/host/sdhci-of-at91.c b/drivers/mmc/host/sdhci-of-at91.c index 7611fd679f1a..1485530c3592 100644 --- a/drivers/mmc/host/sdhci-of-at91.c +++ b/drivers/mmc/host/sdhci-of-at91.c @@ -31,6 +31,7 @@ #define SDMMC_MC1R 0x204 #define SDMMC_MC1R_DDR BIT(3) +#define SDMMC_MC1R_FCD BIT(7) #define SDMMC_CACR 0x230 #define SDMMC_CACR_CAPWREN BIT(0) #define SDMMC_CACR_KEY (0x46 << 8) @@ -43,6 +44,15 @@ struct sdhci_at91_priv { struct clk *mainck; }; +static void sdhci_at91_set_force_card_detect(struct sdhci_host *host) +{ + u8 mc1r; + + mc1r = readb(host->ioaddr + SDMMC_MC1R); + mc1r |= SDMMC_MC1R_FCD; + writeb(mc1r, host->ioaddr + SDMMC_MC1R); +} + static void sdhci_at91_set_clock(struct sdhci_host *host, unsigned int clock) { u16 clk; @@ -110,10 +120,18 @@ void sdhci_at91_set_uhs_signaling(struct sdhci_host *host, unsigned int timing) sdhci_set_uhs_signaling(host, timing); } +static void sdhci_at91_reset(struct sdhci_host *host, u8 mask) +{ + sdhci_reset(host, mask); + + if (host->mmc->caps & MMC_CAP_NONREMOVABLE) + sdhci_at91_set_force_card_detect(host); +} + static const struct sdhci_ops sdhci_at91_sama5d2_ops = { .set_clock = sdhci_at91_set_clock, .set_bus_width = sdhci_set_bus_width, - .reset = sdhci_reset, + .reset = sdhci_at91_reset, .set_uhs_signaling = sdhci_at91_set_uhs_signaling, .set_power = sdhci_at91_set_power, }; @@ -324,6 +342,21 @@ static int sdhci_at91_probe(struct platform_device *pdev) host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION; } + /* + * If the device attached to the MMC bus is not removable, it is safer + * to set the Force Card Detect bit. People often don't connect the + * card detect signal and use this pin for another purpose. If the card + * detect pin is not muxed to SDHCI controller, a default value is + * used. This value can be different from a SoC revision to another + * one. Problems come when this default value is not card present. To + * avoid this case, if the device is non removable then the card + * detection procedure using the SDMCC_CD signal is bypassed. + * This bit is reset when a software reset for all command is performed + * so we need to implement our own reset function to set back this bit. + */ + if (host->mmc->caps & MMC_CAP_NONREMOVABLE) + sdhci_at91_set_force_card_detect(host); + pm_runtime_put_autosuspend(&pdev->dev); return 0; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig index 5aee05992f27..fdaef00465d7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Kconfig +++ b/drivers/net/ethernet/mellanox/mlx5/core/Kconfig @@ -34,6 +34,27 @@ config MLX5_CORE_EN ---help--- Ethernet support in Mellanox Technologies ConnectX-4 NIC. +config MLX5_MPFS + bool "Mellanox Technologies MLX5 MPFS support" + depends on MLX5_CORE_EN + default y + ---help--- + Mellanox Technologies Ethernet Multi-Physical Function Switch (MPFS) + support in ConnectX NIC. MPFs is required for when multi-PF configuration + is enabled to allow passing user configured unicast MAC addresses to the + requesting PF. + +config MLX5_ESWITCH + bool "Mellanox Technologies MLX5 SRIOV E-Switch support" + depends on MLX5_CORE_EN + default y + ---help--- + Mellanox Technologies Ethernet SRIOV E-Switch support in ConnectX NIC. + E-Switch provides internal SRIOV packet steering and switching for the + enabled VFs and PF in two available modes: + Legacy SRIOV mode (L2 mac vlan steering based). + Switchdev mode (eswitch offloads). + config MLX5_CORE_EN_DCB bool "Data Center Bridging (DCB) Support" default y diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile index 9d17e4e76d3a..22ed657d263a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile +++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile @@ -11,10 +11,13 @@ mlx5_core-$(CONFIG_MLX5_ACCEL) += accel/ipsec.o mlx5_core-$(CONFIG_MLX5_FPGA) += fpga/cmd.o fpga/core.o fpga/conn.o fpga/sdk.o \ fpga/ipsec.o -mlx5_core-$(CONFIG_MLX5_CORE_EN) += eswitch.o eswitch_offloads.o \ - en_main.o en_common.o en_fs.o en_ethtool.o en_tx.o \ - en_rx.o en_rx_am.o en_txrx.o en_clock.o vxlan.o \ - en_tc.o en_arfs.o en_rep.o en_fs_ethtool.o en_selftest.o +mlx5_core-$(CONFIG_MLX5_CORE_EN) += en_main.o en_common.o en_fs.o en_ethtool.o \ + en_tx.o en_rx.o en_rx_am.o en_txrx.o en_clock.o vxlan.o \ + en_arfs.o en_fs_ethtool.o en_selftest.o + +mlx5_core-$(CONFIG_MLX5_MPFS) += lib/mpfs.o + +mlx5_core-$(CONFIG_MLX5_ESWITCH) += eswitch.o eswitch_offloads.o en_rep.o en_tc.o mlx5_core-$(CONFIG_MLX5_CORE_EN_DCB) += en_dcbnl.o diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c index a62f4b6a21a5..ff60cf7342ca 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c @@ -45,11 +45,70 @@ struct mlx5_device_context { unsigned long state; }; +struct mlx5_delayed_event { + struct list_head list; + struct mlx5_core_dev *dev; + enum mlx5_dev_event event; + unsigned long param; +}; + enum { MLX5_INTERFACE_ADDED, MLX5_INTERFACE_ATTACHED, }; +static void add_delayed_event(struct mlx5_priv *priv, + struct mlx5_core_dev *dev, + enum mlx5_dev_event event, + unsigned long param) +{ + struct mlx5_delayed_event *delayed_event; + + delayed_event = kzalloc(sizeof(*delayed_event), GFP_ATOMIC); + if (!delayed_event) { + mlx5_core_err(dev, "event %d is missed\n", event); + return; + } + + mlx5_core_dbg(dev, "Accumulating event %d\n", event); + delayed_event->dev = dev; + delayed_event->event = event; + delayed_event->param = param; + list_add_tail(&delayed_event->list, &priv->waiting_events_list); +} + +static void fire_delayed_event_locked(struct mlx5_device_context *dev_ctx, + struct mlx5_core_dev *dev, + struct mlx5_priv *priv) +{ + struct mlx5_delayed_event *de; + struct mlx5_delayed_event *n; + + /* stop delaying events */ + priv->is_accum_events = false; + + /* fire all accumulated events before new event comes */ + list_for_each_entry_safe(de, n, &priv->waiting_events_list, list) { + dev_ctx->intf->event(dev, dev_ctx->context, de->event, de->param); + list_del(&de->list); + kfree(de); + } +} + +static void cleanup_delayed_evets(struct mlx5_priv *priv) +{ + struct mlx5_delayed_event *de; + struct mlx5_delayed_event *n; + + spin_lock_irq(&priv->ctx_lock); + priv->is_accum_events = false; + list_for_each_entry_safe(de, n, &priv->waiting_events_list, list) { + list_del(&de->list); + kfree(de); + } + spin_unlock_irq(&priv->ctx_lock); +} + void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) { struct mlx5_device_context *dev_ctx; @@ -63,6 +122,12 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) return; dev_ctx->intf = intf; + /* accumulating events that can come after mlx5_ib calls to + * ib_register_device, till adding that interface to the events list. + */ + + priv->is_accum_events = true; + dev_ctx->context = intf->add(dev); set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state); if (intf->attach) @@ -71,6 +136,9 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) if (dev_ctx->context) { spin_lock_irq(&priv->ctx_lock); list_add_tail(&dev_ctx->list, &priv->ctx_list); + + fire_delayed_event_locked(dev_ctx, dev, priv); + #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING if (dev_ctx->intf->pfault) { if (priv->pfault) { @@ -84,6 +152,8 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv) spin_unlock_irq(&priv->ctx_lock); } else { kfree(dev_ctx); + /* delete all accumulated events */ + cleanup_delayed_evets(priv); } } @@ -341,6 +411,9 @@ void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event, spin_lock_irqsave(&priv->ctx_lock, flags); + if (priv->is_accum_events) + add_delayed_event(priv, dev, event, param); + list_for_each_entry(dev_ctx, &priv->ctx_list, list) if (dev_ctx->intf->event) dev_ctx->intf->event(dev, dev_ctx->context, event, param); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c index dfccb5305e9c..eecbc6d4f51f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_fs.c @@ -36,6 +36,7 @@ #include <linux/tcp.h> #include <linux/mlx5/fs.h> #include "en.h" +#include "lib/mpfs.h" static int mlx5e_add_l2_flow_rule(struct mlx5e_priv *priv, struct mlx5e_l2_rule *ai, int type); @@ -65,6 +66,7 @@ struct mlx5e_l2_hash_node { struct hlist_node hlist; u8 action; struct mlx5e_l2_rule ai; + bool mpfs; }; static inline int mlx5e_hash_l2(u8 *addr) @@ -362,17 +364,30 @@ static void mlx5e_del_vlan_rules(struct mlx5e_priv *priv) static void mlx5e_execute_l2_action(struct mlx5e_priv *priv, struct mlx5e_l2_hash_node *hn) { - switch (hn->action) { + u8 action = hn->action; + int l2_err = 0; + + switch (action) { case MLX5E_ACTION_ADD: mlx5e_add_l2_flow_rule(priv, &hn->ai, MLX5E_FULLMATCH); + if (!is_multicast_ether_addr(hn->ai.addr)) { + l2_err = mlx5_mpfs_add_mac(priv->mdev, hn->ai.addr); + hn->mpfs = !l2_err; + } hn->action = MLX5E_ACTION_NONE; break; case MLX5E_ACTION_DEL: + if (!is_multicast_ether_addr(hn->ai.addr) && hn->mpfs) + l2_err = mlx5_mpfs_del_mac(priv->mdev, hn->ai.addr); mlx5e_del_l2_flow_rule(priv, &hn->ai); mlx5e_del_l2_from_hash(hn); break; } + + if (l2_err) + netdev_warn(priv->netdev, "MPFS, failed to %s mac %pM, err(%d)\n", + action == MLX5E_ACTION_ADD ? "add" : "del", hn->ai.addr, l2_err); } static void mlx5e_sync_netdev_addr(struct mlx5e_priv *priv) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index ae0916238b7b..981f8415b546 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -2581,12 +2581,6 @@ static void mlx5e_build_channels_tx_maps(struct mlx5e_priv *priv) } } -static bool mlx5e_is_eswitch_vport_mngr(struct mlx5_core_dev *mdev) -{ - return (MLX5_CAP_GEN(mdev, vport_group_manager) && - MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH); -} - void mlx5e_activate_priv_channels(struct mlx5e_priv *priv) { int num_txqs = priv->channels.num * priv->channels.params.num_tc; @@ -2600,7 +2594,7 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv) mlx5e_activate_channels(&priv->channels); netif_tx_start_all_queues(priv->netdev); - if (mlx5e_is_eswitch_vport_mngr(priv->mdev)) + if (MLX5_VPORT_MANAGER(priv->mdev)) mlx5e_add_sqs_fwd_rules(priv); mlx5e_wait_channels_min_rx_wqes(&priv->channels); @@ -2611,7 +2605,7 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv) { mlx5e_redirect_rqts_to_drop(priv); - if (mlx5e_is_eswitch_vport_mngr(priv->mdev)) + if (MLX5_VPORT_MANAGER(priv->mdev)) mlx5e_remove_sqs_fwd_rules(priv); /* FIXME: This is a W/A only for tx timeout watch dog false alarm when @@ -3031,6 +3025,7 @@ out: return err; } +#ifdef CONFIG_MLX5_ESWITCH static int mlx5e_setup_tc_cls_flower(struct net_device *dev, struct tc_cls_flower_offload *cls_flower) { @@ -3051,13 +3046,16 @@ static int mlx5e_setup_tc_cls_flower(struct net_device *dev, return -EOPNOTSUPP; } } +#endif static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data) { switch (type) { +#ifdef CONFIG_MLX5_ESWITCH case TC_SETUP_CLSFLOWER: return mlx5e_setup_tc_cls_flower(dev, type_data); +#endif case TC_SETUP_MQPRIO: return mlx5e_setup_tc_mqprio(dev, type_data); default: @@ -3359,6 +3357,7 @@ static int mlx5e_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } } +#ifdef CONFIG_MLX5_ESWITCH static int mlx5e_set_vf_mac(struct net_device *dev, int vf, u8 *mac) { struct mlx5e_priv *priv = netdev_priv(dev); @@ -3461,6 +3460,7 @@ static int mlx5e_get_vf_stats(struct net_device *dev, return mlx5_eswitch_get_vport_stats(mdev->priv.eswitch, vf + 1, vf_stats); } +#endif static void mlx5e_add_vxlan_port(struct net_device *netdev, struct udp_tunnel_info *ti) @@ -3694,7 +3694,7 @@ static void mlx5e_netpoll(struct net_device *dev) } #endif -static const struct net_device_ops mlx5e_netdev_ops_basic = { +static const struct net_device_ops mlx5e_netdev_ops = { .ndo_open = mlx5e_open, .ndo_stop = mlx5e_close, .ndo_start_xmit = mlx5e_xmit, @@ -3709,6 +3709,9 @@ static const struct net_device_ops mlx5e_netdev_ops_basic = { .ndo_change_mtu = mlx5e_change_mtu, .ndo_do_ioctl = mlx5e_ioctl, .ndo_set_tx_maxrate = mlx5e_set_tx_maxrate, + .ndo_udp_tunnel_add = mlx5e_add_vxlan_port, + .ndo_udp_tunnel_del = mlx5e_del_vxlan_port, + .ndo_features_check = mlx5e_features_check, #ifdef CONFIG_RFS_ACCEL .ndo_rx_flow_steer = mlx5e_rx_flow_steer, #endif @@ -3717,29 +3720,8 @@ static const struct net_device_ops mlx5e_netdev_ops_basic = { #ifdef CONFIG_NET_POLL_CONTROLLER .ndo_poll_controller = mlx5e_netpoll, #endif -}; - -static const struct net_device_ops mlx5e_netdev_ops_sriov = { - .ndo_open = mlx5e_open, - .ndo_stop = mlx5e_close, - .ndo_start_xmit = mlx5e_xmit, - .ndo_setup_tc = mlx5e_setup_tc, - .ndo_select_queue = mlx5e_select_queue, - .ndo_get_stats64 = mlx5e_get_stats, - .ndo_set_rx_mode = mlx5e_set_rx_mode, - .ndo_set_mac_address = mlx5e_set_mac, - .ndo_vlan_rx_add_vid = mlx5e_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = mlx5e_vlan_rx_kill_vid, - .ndo_set_features = mlx5e_set_features, - .ndo_change_mtu = mlx5e_change_mtu, - .ndo_do_ioctl = mlx5e_ioctl, - .ndo_udp_tunnel_add = mlx5e_add_vxlan_port, - .ndo_udp_tunnel_del = mlx5e_del_vxlan_port, - .ndo_set_tx_maxrate = mlx5e_set_tx_maxrate, - .ndo_features_check = mlx5e_features_check, -#ifdef CONFIG_RFS_ACCEL - .ndo_rx_flow_steer = mlx5e_rx_flow_steer, -#endif +#ifdef CONFIG_MLX5_ESWITCH + /* SRIOV E-Switch NDOs */ .ndo_set_vf_mac = mlx5e_set_vf_mac, .ndo_set_vf_vlan = mlx5e_set_vf_vlan, .ndo_set_vf_spoofchk = mlx5e_set_vf_spoofchk, @@ -3748,13 +3730,9 @@ static const struct net_device_ops mlx5e_netdev_ops_sriov = { .ndo_get_vf_config = mlx5e_get_vf_config, .ndo_set_vf_link_state = mlx5e_set_vf_link_state, .ndo_get_vf_stats = mlx5e_get_vf_stats, - .ndo_tx_timeout = mlx5e_tx_timeout, - .ndo_xdp = mlx5e_xdp, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = mlx5e_netpoll, -#endif .ndo_has_offload_stats = mlx5e_has_offload_stats, .ndo_get_offload_stats = mlx5e_get_offload_stats, +#endif }; static int mlx5e_check_required_hca_cap(struct mlx5_core_dev *mdev) @@ -3984,9 +3962,11 @@ static void mlx5e_set_netdev_dev_addr(struct net_device *netdev) } } +#if IS_ENABLED(CONFIG_NET_SWITCHDEV) && IS_ENABLED(CONFIG_MLX5_ESWITCH) static const struct switchdev_ops mlx5e_switchdev_ops = { .switchdev_port_attr_get = mlx5e_attr_get, }; +#endif static void mlx5e_build_nic_netdev(struct net_device *netdev) { @@ -3997,15 +3977,12 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev) SET_NETDEV_DEV(netdev, &mdev->pdev->dev); - if (MLX5_CAP_GEN(mdev, vport_group_manager)) { - netdev->netdev_ops = &mlx5e_netdev_ops_sriov; + netdev->netdev_ops = &mlx5e_netdev_ops; + #ifdef CONFIG_MLX5_CORE_EN_DCB - if (MLX5_CAP_GEN(mdev, qos)) - netdev->dcbnl_ops = &mlx5e_dcbnl_ops; + if (MLX5_CAP_GEN(mdev, vport_group_manager) && MLX5_CAP_GEN(mdev, qos)) + netdev->dcbnl_ops = &mlx5e_dcbnl_ops; #endif - } else { - netdev->netdev_ops = &mlx5e_netdev_ops_basic; - } netdev->watchdog_timeo = 15 * HZ; @@ -4077,8 +4054,8 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev) mlx5e_set_netdev_dev_addr(netdev); -#ifdef CONFIG_NET_SWITCHDEV - if (MLX5_CAP_GEN(mdev, vport_group_manager)) +#if IS_ENABLED(CONFIG_NET_SWITCHDEV) && IS_ENABLED(CONFIG_MLX5_ESWITCH) + if (MLX5_VPORT_MANAGER(mdev)) netdev->switchdev_ops = &mlx5e_switchdev_ops; #endif @@ -4220,7 +4197,7 @@ static void mlx5e_nic_enable(struct mlx5e_priv *priv) mlx5e_enable_async_events(priv); - if (MLX5_CAP_GEN(mdev, vport_group_manager)) + if (MLX5_VPORT_MANAGER(priv->mdev)) mlx5e_register_vport_reps(priv); if (netdev->reg_state != NETREG_REGISTERED) @@ -4254,7 +4231,7 @@ static void mlx5e_nic_disable(struct mlx5e_priv *priv) queue_work(priv->wq, &priv->set_rx_mode_work); - if (MLX5_CAP_GEN(mdev, vport_group_manager)) + if (MLX5_VPORT_MANAGER(priv->mdev)) mlx5e_unregister_vport_reps(priv); mlx5e_disable_async_events(priv); @@ -4427,32 +4404,29 @@ static void mlx5e_detach(struct mlx5_core_dev *mdev, void *vpriv) static void *mlx5e_add(struct mlx5_core_dev *mdev) { - struct mlx5_eswitch *esw = mdev->priv.eswitch; - int total_vfs = MLX5_TOTAL_VPORTS(mdev); - struct mlx5e_rep_priv *rpriv = NULL; + struct net_device *netdev; + void *rpriv = NULL; void *priv; - int vport; int err; - struct net_device *netdev; err = mlx5e_check_required_hca_cap(mdev); if (err) return NULL; - if (MLX5_CAP_GEN(mdev, vport_group_manager)) { - rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL); +#ifdef CONFIG_MLX5_ESWITCH + if (MLX5_VPORT_MANAGER(mdev)) { + rpriv = mlx5e_alloc_nic_rep_priv(mdev); if (!rpriv) { - mlx5_core_warn(mdev, - "Not creating net device, Failed to alloc rep priv data\n"); + mlx5_core_warn(mdev, "Failed to alloc NIC rep priv data\n"); return NULL; } - rpriv->rep = &esw->offloads.vport_reps[0]; } +#endif netdev = mlx5e_create_netdev(mdev, &mlx5e_nic_profile, rpriv); if (!netdev) { mlx5_core_err(mdev, "mlx5e_create_netdev failed\n"); - goto err_unregister_reps; + goto err_free_rpriv; } priv = netdev_priv(netdev); @@ -4473,14 +4447,9 @@ static void *mlx5e_add(struct mlx5_core_dev *mdev) err_detach: mlx5e_detach(mdev, priv); - err_destroy_netdev: mlx5e_destroy_netdev(priv); - -err_unregister_reps: - for (vport = 1; vport < total_vfs; vport++) - mlx5_eswitch_unregister_vport_rep(esw, vport); - +err_free_rpriv: kfree(rpriv); return NULL; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index 3df994d1e173..f3c494a4ecdf 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1104,3 +1104,16 @@ void mlx5e_unregister_vport_reps(struct mlx5e_priv *priv) mlx5e_rep_unregister_vf_vports(priv); /* VFs vports */ mlx5_eswitch_unregister_vport_rep(esw, 0); /* UPLINK PF*/ } + +void *mlx5e_alloc_nic_rep_priv(struct mlx5_core_dev *mdev) +{ + struct mlx5_eswitch *esw = mdev->priv.eswitch; + struct mlx5e_rep_priv *rpriv; + + rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL); + if (!rpriv) + return NULL; + + rpriv->rep = &esw->offloads.vport_reps[0]; + return rpriv; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h index a0a1a7a1d6c0..5659ed9f51e6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.h @@ -38,6 +38,7 @@ #include "eswitch.h" #include "en.h" +#ifdef CONFIG_MLX5_ESWITCH struct mlx5e_neigh_update_table { struct rhashtable neigh_ht; /* Save the neigh hash entries in a list in addition to the hash table @@ -123,6 +124,7 @@ struct mlx5e_encap_entry { int encap_size; }; +void *mlx5e_alloc_nic_rep_priv(struct mlx5_core_dev *mdev); void mlx5e_register_vport_reps(struct mlx5e_priv *priv); void mlx5e_unregister_vport_reps(struct mlx5e_priv *priv); bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv); @@ -141,5 +143,12 @@ void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv, struct mlx5e_encap_entry *e); void mlx5e_rep_queue_neigh_stats_work(struct mlx5e_priv *priv); +#else /* CONFIG_MLX5_ESWITCH */ +static inline void mlx5e_register_vport_reps(struct mlx5e_priv *priv) {} +static inline void mlx5e_unregister_vport_reps(struct mlx5e_priv *priv) {} +static inline bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv) { return false; } +static inline int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv) { return 0; } +static inline void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv) {} +#endif #endif /* __MLX5E_REP_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 325b2c8c1c6d..8e224bcbc6a6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -857,6 +857,7 @@ wq_ll_pop: &wqe->next.next_wqe_index); } +#ifdef CONFIG_MLX5_ESWITCH void mlx5e_handle_rx_cqe_rep(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe) { struct net_device *netdev = rq->netdev; @@ -901,6 +902,7 @@ wq_ll_pop: mlx5_wq_ll_pop(&rq->wq, wqe_counter_be, &wqe->next.next_wqe_index); } +#endif static inline void mlx5e_mpwqe_fill_rx_skb(struct mlx5e_rq *rq, struct mlx5_cqe64 *cqe, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h index 2917d964ffc3..c14c263a739b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.h @@ -37,6 +37,7 @@ #define MLX5E_TC_FLOW_ID_MASK 0x0000ffff +#ifdef CONFIG_MLX5_ESWITCH int mlx5e_tc_init(struct mlx5e_priv *priv); void mlx5e_tc_cleanup(struct mlx5e_priv *priv); @@ -62,4 +63,10 @@ static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv) return atomic_read(&priv->fs.tc.ht.nelems); } +#else /* CONFIG_MLX5_ESWITCH */ +static inline int mlx5e_tc_init(struct mlx5e_priv *priv) { return 0; } +static inline void mlx5e_tc_cleanup(struct mlx5e_priv *priv) {} +static inline int mlx5e_tc_num_filters(struct mlx5e_priv *priv) { return 0; } +#endif + #endif /* __MLX5_EN_TC_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 52b9a64cd3a2..de704ff5619a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -36,9 +36,7 @@ #include <linux/mlx5/cmd.h> #include "mlx5_core.h" #include "fpga/core.h" -#ifdef CONFIG_MLX5_CORE_EN #include "eswitch.h" -#endif enum { MLX5_EQE_SIZE = sizeof(struct mlx5_eqe), @@ -467,11 +465,9 @@ static irqreturn_t mlx5_eq_int(int irq, void *eq_ptr) } break; -#ifdef CONFIG_MLX5_CORE_EN case MLX5_EVENT_TYPE_NIC_VPORT_CHANGE: mlx5_eswitch_vport_event(dev->priv.eswitch, eqe); break; -#endif case MLX5_EVENT_TYPE_PORT_MODULE_EVENT: mlx5_port_module_event(dev, eqe); @@ -688,9 +684,7 @@ int mlx5_start_eqs(struct mlx5_core_dev *dev) u64 async_event_mask = MLX5_ASYNC_EVENT_MASK; int err; - if (MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_ETH && - MLX5_CAP_GEN(dev, vport_group_manager) && - mlx5_core_is_pf(dev)) + if (MLX5_VPORT_MANAGER(dev)) async_event_mask |= (1ull << MLX5_EVENT_TYPE_NIC_VPORT_CHANGE); if (MLX5_CAP_GEN(dev, port_module_event)) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c index 8b18cc9ec026..fd51f0ea8df9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c @@ -46,19 +46,13 @@ enum { MLX5_ACTION_DEL = 2, }; -/* E-Switch UC L2 table hash node */ -struct esw_uc_addr { - struct l2addr_node node; - u32 table_index; - u32 vport; -}; - /* Vport UC/MC hash node */ struct vport_addr { struct l2addr_node node; u8 action; u32 vport; - struct mlx5_flow_handle *flow_rule; /* SRIOV only */ + struct mlx5_flow_handle *flow_rule; + bool mpfs; /* UC MAC was added to MPFs */ /* A flag indicating that mac was added due to mc promiscuous vport */ bool mc_promisc; }; @@ -154,81 +148,6 @@ static int modify_esw_vport_cvlan(struct mlx5_core_dev *dev, u32 vport, return modify_esw_vport_context_cmd(dev, vport, in, sizeof(in)); } -/* HW L2 Table (MPFS) management */ -static int set_l2_table_entry_cmd(struct mlx5_core_dev *dev, u32 index, - u8 *mac, u8 vlan_valid, u16 vlan) -{ - u32 in[MLX5_ST_SZ_DW(set_l2_table_entry_in)] = {0}; - u32 out[MLX5_ST_SZ_DW(set_l2_table_entry_out)] = {0}; - u8 *in_mac_addr; - - MLX5_SET(set_l2_table_entry_in, in, opcode, - MLX5_CMD_OP_SET_L2_TABLE_ENTRY); - MLX5_SET(set_l2_table_entry_in, in, table_index, index); - MLX5_SET(set_l2_table_entry_in, in, vlan_valid, vlan_valid); - MLX5_SET(set_l2_table_entry_in, in, vlan, vlan); - - in_mac_addr = MLX5_ADDR_OF(set_l2_table_entry_in, in, mac_address); - ether_addr_copy(&in_mac_addr[2], mac); - - return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); -} - -static int del_l2_table_entry_cmd(struct mlx5_core_dev *dev, u32 index) -{ - u32 in[MLX5_ST_SZ_DW(delete_l2_table_entry_in)] = {0}; - u32 out[MLX5_ST_SZ_DW(delete_l2_table_entry_out)] = {0}; - - MLX5_SET(delete_l2_table_entry_in, in, opcode, - MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY); - MLX5_SET(delete_l2_table_entry_in, in, table_index, index); - return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); -} - -static int alloc_l2_table_index(struct mlx5_l2_table *l2_table, u32 *ix) -{ - int err = 0; - - *ix = find_first_zero_bit(l2_table->bitmap, l2_table->size); - if (*ix >= l2_table->size) - err = -ENOSPC; - else - __set_bit(*ix, l2_table->bitmap); - - return err; -} - -static void free_l2_table_index(struct mlx5_l2_table *l2_table, u32 ix) -{ - __clear_bit(ix, l2_table->bitmap); -} - -static int set_l2_table_entry(struct mlx5_core_dev *dev, u8 *mac, - u8 vlan_valid, u16 vlan, - u32 *index) -{ - struct mlx5_l2_table *l2_table = &dev->priv.eswitch->l2_table; - int err; - - err = alloc_l2_table_index(l2_table, index); - if (err) - return err; - - err = set_l2_table_entry_cmd(dev, *index, mac, vlan_valid, vlan); - if (err) - free_l2_table_index(l2_table, *index); - - return err; -} - -static void del_l2_table_entry(struct mlx5_core_dev *dev, u32 index) -{ - struct mlx5_l2_table *l2_table = &dev->priv.eswitch->l2_table; - - del_l2_table_entry_cmd(dev, index); - free_l2_table_index(l2_table, index); -} - /* E-Switch FDB */ static struct mlx5_flow_handle * __esw_fdb_set_vport_rule(struct mlx5_eswitch *esw, u32 vport, bool rx_rule, @@ -455,65 +374,60 @@ typedef int (*vport_addr_action)(struct mlx5_eswitch *esw, static int esw_add_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) { - struct hlist_head *hash = esw->l2_table.l2_hash; - struct esw_uc_addr *esw_uc; u8 *mac = vaddr->node.addr; u32 vport = vaddr->vport; int err; - esw_uc = l2addr_hash_find(hash, mac, struct esw_uc_addr); - if (esw_uc) { + /* Skip mlx5_mpfs_add_mac for PFs, + * it is already done by the PF netdev in mlx5e_execute_l2_action + */ + if (!vport) + goto fdb_add; + + err = mlx5_mpfs_add_mac(esw->dev, mac); + if (err) { esw_warn(esw->dev, - "Failed to set L2 mac(%pM) for vport(%d), mac is already in use by vport(%d)\n", - mac, vport, esw_uc->vport); - return -EEXIST; + "Failed to add L2 table mac(%pM) for vport(%d), err(%d)\n", + mac, vport, err); + return err; } + vaddr->mpfs = true; - esw_uc = l2addr_hash_add(hash, mac, struct esw_uc_addr, GFP_KERNEL); - if (!esw_uc) - return -ENOMEM; - esw_uc->vport = vport; - - err = set_l2_table_entry(esw->dev, mac, 0, 0, &esw_uc->table_index); - if (err) - goto abort; - +fdb_add: /* SRIOV is enabled: Forward UC MAC to vport */ if (esw->fdb_table.fdb && esw->mode == SRIOV_LEGACY) vaddr->flow_rule = esw_fdb_set_vport_rule(esw, mac, vport); - esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM index:%d fr(%p)\n", - vport, mac, esw_uc->table_index, vaddr->flow_rule); - return err; -abort: - l2addr_hash_del(esw_uc); + esw_debug(esw->dev, "\tADDED UC MAC: vport[%d] %pM fr(%p)\n", + vport, mac, vaddr->flow_rule); + return err; } static int esw_del_uc_addr(struct mlx5_eswitch *esw, struct vport_addr *vaddr) { - struct hlist_head *hash = esw->l2_table.l2_hash; - struct esw_uc_addr *esw_uc; u8 *mac = vaddr->node.addr; u32 vport = vaddr->vport; + int err = 0; - esw_uc = l2addr_hash_find(hash, mac, struct esw_uc_addr); - if (!esw_uc || esw_uc->vport != vport) { - esw_debug(esw->dev, - "MAC(%pM) doesn't belong to vport (%d)\n", - mac, vport); - return -EINVAL; - } - esw_debug(esw->dev, "\tDELETE UC MAC: vport[%d] %pM index:%d fr(%p)\n", - vport, mac, esw_uc->table_index, vaddr->flow_rule); + /* Skip mlx5_mpfs_del_mac for PFs, + * it is already done by the PF netdev in mlx5e_execute_l2_action + */ + if (!vport || !vaddr->mpfs) + goto fdb_del; - del_l2_table_entry(esw->dev, esw_uc->table_index); + err = mlx5_mpfs_del_mac(esw->dev, mac); + if (err) + esw_warn(esw->dev, + "Failed to del L2 table mac(%pM) for vport(%d), err(%d)\n", + mac, vport, err); + vaddr->mpfs = false; +fdb_del: if (vaddr->flow_rule) mlx5_del_flow_rules(vaddr->flow_rule); vaddr->flow_rule = NULL; - l2addr_hash_del(esw_uc); return 0; } @@ -1611,13 +1525,14 @@ static void esw_disable_vport(struct mlx5_eswitch *esw, int vport_num) } /* Public E-Switch API */ +#define ESW_ALLOWED(esw) ((esw) && MLX5_VPORT_MANAGER((esw)->dev)) + int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) { int err; int i, enabled_events; - if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager) || - MLX5_CAP_GEN(esw->dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) + if (!ESW_ALLOWED(esw)) return 0; if (!MLX5_CAP_GEN(esw->dev, eswitch_flow_table) || @@ -1634,7 +1549,6 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) esw_info(esw->dev, "E-Switch enable SRIOV: nvfs(%d) mode (%d)\n", nvfs, mode); esw->mode = mode; - esw_disable_vport(esw, 0); if (mode == SRIOV_LEGACY) err = esw_create_legacy_fdb_table(esw, nvfs + 1); @@ -1647,7 +1561,11 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) if (err) esw_warn(esw->dev, "Failed to create eswitch TSAR"); - enabled_events = (mode == SRIOV_LEGACY) ? SRIOV_VPORT_EVENTS : UC_ADDR_CHANGE; + /* Don't enable vport events when in SRIOV_OFFLOADS mode, since: + * 1. L2 table (MPFS) is programmed by PF/VF representors netdevs set_rx_mode + * 2. FDB/Eswitch is programmed by user space tools + */ + enabled_events = (mode == SRIOV_LEGACY) ? SRIOV_VPORT_EVENTS : 0; for (i = 0; i <= nvfs; i++) esw_enable_vport(esw, i, enabled_events); @@ -1656,7 +1574,6 @@ int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) return 0; abort: - esw_enable_vport(esw, 0, UC_ADDR_CHANGE); esw->mode = SRIOV_NONE; return err; } @@ -1667,9 +1584,7 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) int nvports; int i; - if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager) || - MLX5_CAP_GEN(esw->dev, port_type) != MLX5_CAP_PORT_TYPE_ETH || - esw->mode == SRIOV_NONE) + if (!ESW_ALLOWED(esw) || esw->mode == SRIOV_NONE) return; esw_info(esw->dev, "disable SRIOV: active vports(%d) mode(%d)\n", @@ -1692,44 +1607,21 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) esw_offloads_cleanup(esw, nvports); esw->mode = SRIOV_NONE; - /* VPORT 0 (PF) must be enabled back with non-sriov configuration */ - esw_enable_vport(esw, 0, UC_ADDR_CHANGE); -} - -void mlx5_eswitch_attach(struct mlx5_eswitch *esw) -{ - if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager) || - MLX5_CAP_GEN(esw->dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) - return; - - esw_enable_vport(esw, 0, UC_ADDR_CHANGE); - /* VF Vports will be enabled when SRIOV is enabled */ -} - -void mlx5_eswitch_detach(struct mlx5_eswitch *esw) -{ - if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager) || - MLX5_CAP_GEN(esw->dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) - return; - - esw_disable_vport(esw, 0); } int mlx5_eswitch_init(struct mlx5_core_dev *dev) { - int l2_table_size = 1 << MLX5_CAP_GEN(dev, log_max_l2_table); int total_vports = MLX5_TOTAL_VPORTS(dev); struct mlx5_eswitch *esw; int vport_num; int err; - if (!MLX5_CAP_GEN(dev, vport_group_manager) || - MLX5_CAP_GEN(dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) + if (!MLX5_VPORT_MANAGER(dev)) return 0; esw_info(dev, - "Total vports %d, l2 table size(%d), per vport: max uc(%d) max mc(%d)\n", - total_vports, l2_table_size, + "Total vports %d, per vport: max uc(%d) max mc(%d)\n", + total_vports, MLX5_MAX_UC_PER_VPORT(dev), MLX5_MAX_MC_PER_VPORT(dev)); @@ -1739,14 +1631,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) esw->dev = dev; - esw->l2_table.bitmap = kcalloc(BITS_TO_LONGS(l2_table_size), - sizeof(uintptr_t), GFP_KERNEL); - if (!esw->l2_table.bitmap) { - err = -ENOMEM; - goto abort; - } - esw->l2_table.size = l2_table_size; - esw->work_queue = create_singlethread_workqueue("mlx5_esw_wq"); if (!esw->work_queue) { err = -ENOMEM; @@ -1797,7 +1681,6 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev) abort: if (esw->work_queue) destroy_workqueue(esw->work_queue); - kfree(esw->l2_table.bitmap); kfree(esw->vports); kfree(esw->offloads.vport_reps); kfree(esw); @@ -1806,15 +1689,13 @@ abort: void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) { - if (!esw || !MLX5_CAP_GEN(esw->dev, vport_group_manager) || - MLX5_CAP_GEN(esw->dev, port_type) != MLX5_CAP_PORT_TYPE_ETH) + if (!esw || !MLX5_VPORT_MANAGER(esw->dev)) return; esw_info(esw->dev, "cleanup\n"); esw->dev->priv.eswitch = NULL; destroy_workqueue(esw->work_queue); - kfree(esw->l2_table.bitmap); kfree(esw->offloads.vport_reps); kfree(esw->vports); kfree(esw); @@ -1838,8 +1719,6 @@ void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe) } /* Vport Administration */ -#define ESW_ALLOWED(esw) \ - (esw && MLX5_CAP_GEN(esw->dev, vport_group_manager) && mlx5_core_is_pf(esw->dev)) #define LEGAL_VPORT(esw, vport) (vport >= 0 && vport < esw->total_vports) int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h index 834a33050969..565c8b7a399a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h @@ -37,6 +37,15 @@ #include <linux/if_link.h> #include <net/devlink.h> #include <linux/mlx5/device.h> +#include "lib/mpfs.h" + +enum { + SRIOV_NONE, + SRIOV_LEGACY, + SRIOV_OFFLOADS +}; + +#ifdef CONFIG_MLX5_ESWITCH #define MLX5_MAX_UC_PER_VPORT(dev) \ (1 << MLX5_CAP_GEN(dev, log_max_current_uc_list)) @@ -44,9 +53,6 @@ #define MLX5_MAX_MC_PER_VPORT(dev) \ (1 << MLX5_CAP_GEN(dev, log_max_current_mc_list)) -#define MLX5_L2_ADDR_HASH_SIZE (BIT(BITS_PER_BYTE)) -#define MLX5_L2_ADDR_HASH(addr) (addr[5]) - #define FDB_UPLINK_VPORT 0xffff #define MLX5_MIN_BW_SHARE 1 @@ -54,48 +60,6 @@ #define MLX5_RATE_TO_BW_SHARE(rate, divider, limit) \ min_t(u32, max_t(u32, (rate) / (divider), MLX5_MIN_BW_SHARE), limit) -/* L2 -mac address based- hash helpers */ -struct l2addr_node { - struct hlist_node hlist; - u8 addr[ETH_ALEN]; -}; - -#define for_each_l2hash_node(hn, tmp, hash, i) \ - for (i = 0; i < MLX5_L2_ADDR_HASH_SIZE; i++) \ - hlist_for_each_entry_safe(hn, tmp, &hash[i], hlist) - -#define l2addr_hash_find(hash, mac, type) ({ \ - int ix = MLX5_L2_ADDR_HASH(mac); \ - bool found = false; \ - type *ptr = NULL; \ - \ - hlist_for_each_entry(ptr, &hash[ix], node.hlist) \ - if (ether_addr_equal(ptr->node.addr, mac)) {\ - found = true; \ - break; \ - } \ - if (!found) \ - ptr = NULL; \ - ptr; \ -}) - -#define l2addr_hash_add(hash, mac, type, gfp) ({ \ - int ix = MLX5_L2_ADDR_HASH(mac); \ - type *ptr = NULL; \ - \ - ptr = kzalloc(sizeof(type), gfp); \ - if (ptr) { \ - ether_addr_copy(ptr->node.addr, mac); \ - hlist_add_head(&ptr->node.hlist, &hash[ix]);\ - } \ - ptr; \ -}) - -#define l2addr_hash_del(ptr) ({ \ - hlist_del(&ptr->node.hlist); \ - kfree(ptr); \ -}) - struct vport_ingress { struct mlx5_flow_table *acl; struct mlx5_flow_group *allow_untagged_spoofchk_grp; @@ -150,12 +114,6 @@ struct mlx5_vport { u16 enabled_events; }; -struct mlx5_l2_table { - struct hlist_head l2_hash[MLX5_L2_ADDR_HASH_SIZE]; - u32 size; - unsigned long *bitmap; -}; - struct mlx5_eswitch_fdb { void *fdb; union { @@ -175,12 +133,6 @@ struct mlx5_eswitch_fdb { }; }; -enum { - SRIOV_NONE, - SRIOV_LEGACY, - SRIOV_OFFLOADS -}; - struct mlx5_esw_sq { struct mlx5_flow_handle *send_to_vport_rule; struct list_head list; @@ -222,7 +174,6 @@ struct esw_mc_addr { /* SRIOV only */ struct mlx5_eswitch { struct mlx5_core_dev *dev; - struct mlx5_l2_table l2_table; struct mlx5_eswitch_fdb fdb_table; struct hlist_head mc_table[MLX5_L2_ADDR_HASH_SIZE]; struct workqueue_struct *work_queue; @@ -250,8 +201,6 @@ int esw_offloads_init(struct mlx5_eswitch *esw, int nvports); /* E-Switch API */ int mlx5_eswitch_init(struct mlx5_core_dev *dev); void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw); -void mlx5_eswitch_attach(struct mlx5_eswitch *esw); -void mlx5_eswitch_detach(struct mlx5_eswitch *esw); void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe); int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode); void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw); @@ -345,4 +294,13 @@ int __mlx5_eswitch_set_vport_vlan(struct mlx5_eswitch *esw, #define esw_debug(dev, format, ...) \ mlx5_core_dbg_mask(dev, MLX5_DEBUG_ESWITCH_MASK, format, ##__VA_ARGS__) +#else /* CONFIG_MLX5_ESWITCH */ +/* eswitch API stubs */ +static inline int mlx5_eswitch_init(struct mlx5_core_dev *dev) { return 0; } +static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {} +static inline void mlx5_eswitch_vport_event(struct mlx5_eswitch *esw, struct mlx5_eqe *eqe) {} +static inline int mlx5_eswitch_enable_sriov(struct mlx5_eswitch *esw, int nvfs, int mode) { return 0; } +static inline void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw) {} +#endif /* CONFIG_MLX5_ESWITCH */ + #endif /* __MLX5_ESWITCH_H__ */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 95b64025ce36..e7c186b58579 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -433,6 +433,8 @@ static int esw_create_offloads_fast_fdb_table(struct mlx5_eswitch *esw) struct mlx5_flow_table *fdb = NULL; int esw_size, err = 0; u32 flags = 0; + u32 max_flow_counter = (MLX5_CAP_GEN(dev, max_flow_counter_31_16) << 16) | + MLX5_CAP_GEN(dev, max_flow_counter_15_0); root_ns = mlx5_get_flow_namespace(dev, MLX5_FLOW_NAMESPACE_FDB); if (!root_ns) { @@ -443,9 +445,9 @@ static int esw_create_offloads_fast_fdb_table(struct mlx5_eswitch *esw) esw_debug(dev, "Create offloads FDB table, min (max esw size(2^%d), max counters(%d)*groups(%d))\n", MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size), - MLX5_CAP_GEN(dev, max_flow_counter), ESW_OFFLOADS_NUM_GROUPS); + max_flow_counter, ESW_OFFLOADS_NUM_GROUPS); - esw_size = min_t(int, MLX5_CAP_GEN(dev, max_flow_counter) * ESW_OFFLOADS_NUM_GROUPS, + esw_size = min_t(int, max_flow_counter * ESW_OFFLOADS_NUM_GROUPS, 1 << MLX5_CAP_ESW_FLOWTABLE_FDB(dev, log_max_ft_size)); if (esw->offloads.encap != DEVLINK_ESWITCH_ENCAP_MODE_NONE) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c index e750f07793b8..16b32f31d691 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c @@ -359,7 +359,7 @@ int mlx5_cmd_delete_fte(struct mlx5_core_dev *dev, return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); } -int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u16 *id) +int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id) { u32 in[MLX5_ST_SZ_DW(alloc_flow_counter_in)] = {0}; u32 out[MLX5_ST_SZ_DW(alloc_flow_counter_out)] = {0}; @@ -374,7 +374,7 @@ int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u16 *id) return err; } -int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u16 id) +int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u32 id) { u32 in[MLX5_ST_SZ_DW(dealloc_flow_counter_in)] = {0}; u32 out[MLX5_ST_SZ_DW(dealloc_flow_counter_out)] = {0}; @@ -385,7 +385,7 @@ int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u16 id) return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); } -int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u16 id, +int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u32 id, u64 *packets, u64 *bytes) { u32 out[MLX5_ST_SZ_BYTES(query_flow_counter_out) + @@ -409,14 +409,14 @@ int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u16 id, } struct mlx5_cmd_fc_bulk { - u16 id; + u32 id; int num; int outlen; u32 out[0]; }; struct mlx5_cmd_fc_bulk * -mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, u16 id, int num) +mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, u32 id, int num) { struct mlx5_cmd_fc_bulk *b; int outlen = @@ -453,7 +453,7 @@ mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, struct mlx5_cmd_fc_bulk *b) } void mlx5_cmd_fc_bulk_get(struct mlx5_core_dev *dev, - struct mlx5_cmd_fc_bulk *b, u16 id, + struct mlx5_cmd_fc_bulk *b, u32 id, u64 *packets, u64 *bytes) { int index = id - b->id; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h index 0f98a7cf4877..c6d7bdf255b6 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.h @@ -74,20 +74,20 @@ int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev, struct mlx5_flow_table *ft, u32 underlay_qpn); -int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u16 *id); -int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u16 id); -int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u16 id, +int mlx5_cmd_fc_alloc(struct mlx5_core_dev *dev, u32 *id); +int mlx5_cmd_fc_free(struct mlx5_core_dev *dev, u32 id); +int mlx5_cmd_fc_query(struct mlx5_core_dev *dev, u32 id, u64 *packets, u64 *bytes); struct mlx5_cmd_fc_bulk; struct mlx5_cmd_fc_bulk * -mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, u16 id, int num); +mlx5_cmd_fc_bulk_alloc(struct mlx5_core_dev *dev, u32 id, int num); void mlx5_cmd_fc_bulk_free(struct mlx5_cmd_fc_bulk *b); int mlx5_cmd_fc_bulk_query(struct mlx5_core_dev *dev, struct mlx5_cmd_fc_bulk *b); void mlx5_cmd_fc_bulk_get(struct mlx5_core_dev *dev, - struct mlx5_cmd_fc_bulk *b, u16 id, + struct mlx5_cmd_fc_bulk *b, u32 id, u64 *packets, u64 *bytes); #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h index 990acee6fb09..9fb5a333df52 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.h @@ -136,7 +136,7 @@ struct mlx5_fc { u64 lastpackets; u64 lastbytes; - u16 id; + u32 id; bool deleted; bool aging; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c index 6507d8acc54d..89d1f8650033 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c @@ -38,6 +38,8 @@ #include "fs_cmd.h" #define MLX5_FC_STATS_PERIOD msecs_to_jiffies(1000) +/* Max number of counters to query in bulk read is 32K */ +#define MLX5_SW_MAX_COUNTERS_BULK BIT(15) /* locking scheme: * @@ -90,16 +92,21 @@ static void mlx5_fc_stats_insert(struct rb_root *root, struct mlx5_fc *counter) rb_insert_color(&counter->node, root); } +/* The function returns the last node that was queried so the caller + * function can continue calling it till all counters are queried. + */ static struct rb_node *mlx5_fc_stats_query(struct mlx5_core_dev *dev, struct mlx5_fc *first, - u16 last_id) + u32 last_id) { struct mlx5_cmd_fc_bulk *b; struct rb_node *node = NULL; - u16 afirst_id; + u32 afirst_id; int num; int err; - int max_bulk = 1 << MLX5_CAP_GEN(dev, log_max_flow_counter_bulk); + + int max_bulk = min_t(int, MLX5_SW_MAX_COUNTERS_BULK, + (1 << MLX5_CAP_GEN(dev, log_max_flow_counter_bulk))); /* first id must be aligned to 4 when using bulk query */ afirst_id = first->id & ~0x3; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c new file mode 100644 index 000000000000..7cb67122e8b5 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2017, Mellanox Technologies. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include <linux/etherdevice.h> +#include <linux/mlx5/driver.h> +#include <linux/mlx5/mlx5_ifc.h> +#include "mlx5_core.h" +#include "lib/mpfs.h" + +/* HW L2 Table (MPFS) management */ +static int set_l2table_entry_cmd(struct mlx5_core_dev *dev, u32 index, u8 *mac) +{ + u32 in[MLX5_ST_SZ_DW(set_l2_table_entry_in)] = {0}; + u32 out[MLX5_ST_SZ_DW(set_l2_table_entry_out)] = {0}; + u8 *in_mac_addr; + + MLX5_SET(set_l2_table_entry_in, in, opcode, MLX5_CMD_OP_SET_L2_TABLE_ENTRY); + MLX5_SET(set_l2_table_entry_in, in, table_index, index); + + in_mac_addr = MLX5_ADDR_OF(set_l2_table_entry_in, in, mac_address); + ether_addr_copy(&in_mac_addr[2], mac); + + return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); +} + +static int del_l2table_entry_cmd(struct mlx5_core_dev *dev, u32 index) +{ + u32 in[MLX5_ST_SZ_DW(delete_l2_table_entry_in)] = {0}; + u32 out[MLX5_ST_SZ_DW(delete_l2_table_entry_out)] = {0}; + + MLX5_SET(delete_l2_table_entry_in, in, opcode, MLX5_CMD_OP_DELETE_L2_TABLE_ENTRY); + MLX5_SET(delete_l2_table_entry_in, in, table_index, index); + return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); +} + +/* UC L2 table hash node */ +struct l2table_node { + struct l2addr_node node; + u32 index; /* index in HW l2 table */ +}; + +struct mlx5_mpfs { + struct hlist_head hash[MLX5_L2_ADDR_HASH_SIZE]; + struct mutex lock; /* Synchronize l2 table access */ + u32 size; + unsigned long *bitmap; +}; + +static int alloc_l2table_index(struct mlx5_mpfs *l2table, u32 *ix) +{ + int err = 0; + + *ix = find_first_zero_bit(l2table->bitmap, l2table->size); + if (*ix >= l2table->size) + err = -ENOSPC; + else + __set_bit(*ix, l2table->bitmap); + + return err; +} + +static void free_l2table_index(struct mlx5_mpfs *l2table, u32 ix) +{ + __clear_bit(ix, l2table->bitmap); +} + +int mlx5_mpfs_init(struct mlx5_core_dev *dev) +{ + int l2table_size = 1 << MLX5_CAP_GEN(dev, log_max_l2_table); + struct mlx5_mpfs *mpfs; + + if (!MLX5_VPORT_MANAGER(dev)) + return 0; + + mpfs = kzalloc(sizeof(*mpfs), GFP_KERNEL); + if (!mpfs) + return -ENOMEM; + + mutex_init(&mpfs->lock); + mpfs->size = l2table_size; + mpfs->bitmap = kcalloc(BITS_TO_LONGS(l2table_size), + sizeof(uintptr_t), GFP_KERNEL); + if (!mpfs->bitmap) { + kfree(mpfs); + return -ENOMEM; + } + + dev->priv.mpfs = mpfs; + return 0; +} + +void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev) +{ + struct mlx5_mpfs *mpfs = dev->priv.mpfs; + + if (!MLX5_VPORT_MANAGER(dev)) + return; + + WARN_ON(!hlist_empty(mpfs->hash)); + kfree(mpfs->bitmap); + kfree(mpfs); +} + +int mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac) +{ + struct mlx5_mpfs *mpfs = dev->priv.mpfs; + struct l2table_node *l2addr; + u32 index; + int err; + + if (!MLX5_VPORT_MANAGER(dev)) + return 0; + + mutex_lock(&mpfs->lock); + + l2addr = l2addr_hash_find(mpfs->hash, mac, struct l2table_node); + if (l2addr) { + err = -EEXIST; + goto abort; + } + + err = alloc_l2table_index(mpfs, &index); + if (err) + goto abort; + + l2addr = l2addr_hash_add(mpfs->hash, mac, struct l2table_node, GFP_KERNEL); + if (!l2addr) { + free_l2table_index(mpfs, index); + err = -ENOMEM; + goto abort; + } + + l2addr->index = index; + err = set_l2table_entry_cmd(dev, index, mac); + if (err) { + l2addr_hash_del(l2addr); + free_l2table_index(mpfs, index); + } + + mlx5_core_dbg(dev, "MPFS mac added %pM, index (%d)\n", mac, index); +abort: + mutex_unlock(&mpfs->lock); + return err; +} + +int mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac) +{ + struct mlx5_mpfs *mpfs = dev->priv.mpfs; + struct l2table_node *l2addr; + int err = 0; + u32 index; + + if (!MLX5_VPORT_MANAGER(dev)) + return 0; + + mutex_lock(&mpfs->lock); + + l2addr = l2addr_hash_find(mpfs->hash, mac, struct l2table_node); + if (!l2addr) { + err = -ENOENT; + goto unlock; + } + + index = l2addr->index; + del_l2table_entry_cmd(dev, index); + l2addr_hash_del(l2addr); + free_l2table_index(mpfs, index); + mlx5_core_dbg(dev, "MPFS mac deleted %pM, index (%d)\n", mac, index); +unlock: + mutex_unlock(&mpfs->lock); + return err; +} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.h b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.h new file mode 100644 index 000000000000..4a7b2c3203a7 --- /dev/null +++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/mpfs.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017, Mellanox Technologies, Ltd. All rights reserved. + * + * This software is available to you under a choice of one of two + * licenses. You may choose to be licensed under the terms of the GNU + * General Public License (GPL) Version 2, available from the file + * COPYING in the main directory of this source tree, or the + * OpenIB.org BSD license below: + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above + * copyright notice, this list of conditions and the following + * disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef __MLX5_MPFS_H__ +#define __MLX5_MPFS_H__ + +#include <linux/if_ether.h> +#include <linux/mlx5/device.h> + +/* L2 -mac address based- hash helpers */ +#define MLX5_L2_ADDR_HASH_SIZE (BIT(BITS_PER_BYTE)) +#define MLX5_L2_ADDR_HASH(addr) (addr[5]) + +struct l2addr_node { + struct hlist_node hlist; + u8 addr[ETH_ALEN]; +}; + +#define for_each_l2hash_node(hn, tmp, hash, i) \ + for (i = 0; i < MLX5_L2_ADDR_HASH_SIZE; i++) \ + hlist_for_each_entry_safe(hn, tmp, &(hash)[i], hlist) + +#define l2addr_hash_find(hash, mac, type) ({ \ + int ix = MLX5_L2_ADDR_HASH(mac); \ + bool found = false; \ + type *ptr = NULL; \ + \ + hlist_for_each_entry(ptr, &(hash)[ix], node.hlist) \ + if (ether_addr_equal(ptr->node.addr, mac)) {\ + found = true; \ + break; \ + } \ + if (!found) \ + ptr = NULL; \ + ptr; \ +}) + +#define l2addr_hash_add(hash, mac, type, gfp) ({ \ + int ix = MLX5_L2_ADDR_HASH(mac); \ + type *ptr = NULL; \ + \ + ptr = kzalloc(sizeof(type), gfp); \ + if (ptr) { \ + ether_addr_copy(ptr->node.addr, mac); \ + hlist_add_head(&ptr->node.hlist, &(hash)[ix]);\ + } \ + ptr; \ +}) + +#define l2addr_hash_del(ptr) ({ \ + hlist_del(&(ptr)->node.hlist); \ + kfree(ptr); \ +}) + +#ifdef CONFIG_MLX5_MPFS +int mlx5_mpfs_init(struct mlx5_core_dev *dev); +void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev); +int mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac); +int mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac); +#else /* #ifndef CONFIG_MLX5_MPFS */ +static inline int mlx5_mpfs_init(struct mlx5_core_dev *dev) { return 0; } +static inline void mlx5_mpfs_cleanup(struct mlx5_core_dev *dev) {} +static inline int mlx5_mpfs_add_mac(struct mlx5_core_dev *dev, u8 *mac) { return 0; } +static inline int mlx5_mpfs_del_mac(struct mlx5_core_dev *dev, u8 *mac) { return 0; } +#endif +#endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c index c065132b956d..6dbd637b4e66 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c @@ -53,9 +53,8 @@ #include <net/devlink.h> #include "mlx5_core.h" #include "fs_core.h" -#ifdef CONFIG_MLX5_CORE_EN +#include "lib/mpfs.h" #include "eswitch.h" -#endif #include "lib/mlx5.h" #include "fpga/core.h" #include "accel/ipsec.h" @@ -946,13 +945,17 @@ static int mlx5_init_once(struct mlx5_core_dev *dev, struct mlx5_priv *priv) goto err_tables_cleanup; } -#ifdef CONFIG_MLX5_CORE_EN + err = mlx5_mpfs_init(dev); + if (err) { + dev_err(&pdev->dev, "Failed to init l2 table %d\n", err); + goto err_rl_cleanup; + } + err = mlx5_eswitch_init(dev); if (err) { dev_err(&pdev->dev, "Failed to init eswitch %d\n", err); - goto err_rl_cleanup; + goto err_mpfs_cleanup; } -#endif err = mlx5_sriov_init(dev); if (err) { @@ -971,13 +974,11 @@ static int mlx5_init_once(struct mlx5_core_dev *dev, struct mlx5_priv *priv) err_sriov_cleanup: mlx5_sriov_cleanup(dev); err_eswitch_cleanup: -#ifdef CONFIG_MLX5_CORE_EN mlx5_eswitch_cleanup(dev->priv.eswitch); - +err_mpfs_cleanup: + mlx5_mpfs_cleanup(dev); err_rl_cleanup: -#endif mlx5_cleanup_rl_table(dev); - err_tables_cleanup: mlx5_cleanup_mkey_table(dev); mlx5_cleanup_srq_table(dev); @@ -995,9 +996,8 @@ static void mlx5_cleanup_once(struct mlx5_core_dev *dev) { mlx5_fpga_cleanup(dev); mlx5_sriov_cleanup(dev); -#ifdef CONFIG_MLX5_CORE_EN mlx5_eswitch_cleanup(dev->priv.eswitch); -#endif + mlx5_mpfs_cleanup(dev); mlx5_cleanup_rl_table(dev); mlx5_cleanup_reserved_gids(dev); mlx5_cleanup_mkey_table(dev); @@ -1155,10 +1155,6 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, goto err_fs; } -#ifdef CONFIG_MLX5_CORE_EN - mlx5_eswitch_attach(dev->priv.eswitch); -#endif - err = mlx5_sriov_attach(dev); if (err) { dev_err(&pdev->dev, "sriov init failed %d\n", err); @@ -1202,9 +1198,6 @@ err_fpga_start: mlx5_sriov_detach(dev); err_sriov: -#ifdef CONFIG_MLX5_CORE_EN - mlx5_eswitch_detach(dev->priv.eswitch); -#endif mlx5_cleanup_fs(dev); err_fs: @@ -1279,9 +1272,6 @@ static int mlx5_unload_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv, mlx5_fpga_device_stop(dev); mlx5_sriov_detach(dev); -#ifdef CONFIG_MLX5_CORE_EN - mlx5_eswitch_detach(dev->priv.eswitch); -#endif mlx5_cleanup_fs(dev); mlx5_irq_clear_affinity_hints(dev); free_comp_eqs(dev); @@ -1313,7 +1303,7 @@ struct mlx5_core_event_handler { }; static const struct devlink_ops mlx5_devlink_ops = { -#ifdef CONFIG_MLX5_CORE_EN +#ifdef CONFIG_MLX5_ESWITCH .eswitch_mode_set = mlx5_devlink_eswitch_mode_set, .eswitch_mode_get = mlx5_devlink_eswitch_mode_get, .eswitch_inline_mode_set = mlx5_devlink_eswitch_inline_mode_set, @@ -1353,6 +1343,9 @@ static int init_one(struct pci_dev *pdev, mutex_init(&dev->pci_status_mutex); mutex_init(&dev->intf_state_mutex); + INIT_LIST_HEAD(&priv->waiting_events_list); + priv->is_accum_events = false; + #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING err = init_srcu_struct(&priv->pfault_srcu); if (err) { diff --git a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h index 6a263e8d883a..d8da9240a00b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h @@ -43,6 +43,10 @@ #define DRIVER_VERSION "5.0-0" #define MLX5_TOTAL_VPORTS(mdev) (1 + pci_sriov_get_totalvfs(mdev->pdev)) +#define MLX5_VPORT_MANAGER(mdev) \ + (MLX5_CAP_GEN(mdev, vport_group_manager) && \ + (MLX5_CAP_GEN(mdev, port_type) == MLX5_CAP_PORT_TYPE_ETH) && \ + mlx5_core_is_pf(mdev)) extern uint mlx5_core_debug_mask; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c index bf99d40e30b4..5e7ffc9fad78 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/sriov.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/sriov.c @@ -33,9 +33,7 @@ #include <linux/pci.h> #include <linux/mlx5/driver.h> #include "mlx5_core.h" -#ifdef CONFIG_MLX5_CORE_EN #include "eswitch.h" -#endif bool mlx5_sriov_is_enabled(struct mlx5_core_dev *dev) { @@ -57,14 +55,12 @@ static int mlx5_device_enable_sriov(struct mlx5_core_dev *dev, int num_vfs) return -EBUSY; } -#ifdef CONFIG_MLX5_CORE_EN err = mlx5_eswitch_enable_sriov(dev->priv.eswitch, num_vfs, SRIOV_LEGACY); if (err) { mlx5_core_warn(dev, "failed to enable eswitch SRIOV (%d)\n", err); return err; } -#endif for (vf = 0; vf < num_vfs; vf++) { err = mlx5_core_enable_hca(dev, vf + 1); @@ -88,11 +84,7 @@ static void mlx5_device_disable_sriov(struct mlx5_core_dev *dev) int vf; if (!sriov->enabled_vfs) -#ifdef CONFIG_MLX5_CORE_EN - goto disable_sriov_resources; -#else - return; -#endif + goto out; for (vf = 0; vf < sriov->num_vfs; vf++) { if (!sriov->vfs_ctx[vf].enabled) @@ -106,10 +98,8 @@ static void mlx5_device_disable_sriov(struct mlx5_core_dev *dev) sriov->enabled_vfs--; } -#ifdef CONFIG_MLX5_CORE_EN -disable_sriov_resources: +out: mlx5_eswitch_disable_sriov(dev->priv.eswitch); -#endif if (mlx5_wait_for_vf_pages(dev)) mlx5_core_warn(dev, "timeout reclaiming VFs pages\n"); diff --git a/drivers/of/property.c b/drivers/of/property.c index eda50b4be934..067f9fab7b77 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -708,6 +708,15 @@ struct device_node *of_graph_get_port_parent(struct device_node *node) { unsigned int depth; + if (!node) + return NULL; + + /* + * Preserve usecount for passed in node as of_get_next_parent() + * will do of_node_put() on it. + */ + of_node_get(node); + /* Walk 3 levels up only if there is 'ports' node. */ for (depth = 3; depth && node; depth--) { node = of_get_next_parent(node); @@ -728,12 +737,16 @@ EXPORT_SYMBOL(of_graph_get_port_parent); struct device_node *of_graph_get_remote_port_parent( const struct device_node *node) { - struct device_node *np; + struct device_node *np, *pp; /* Get remote endpoint node. */ np = of_graph_get_remote_endpoint(node); - return of_graph_get_port_parent(np); + pp = of_graph_get_port_parent(np); + + of_node_put(np); + + return pp; } EXPORT_SYMBOL(of_graph_get_remote_port_parent); diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 7147aa53e9a2..b1ff46fe4547 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -333,11 +333,11 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun /* Update the symlink to the real device */ sysfs_remove_link(&entry->kobj, "device"); + write_unlock(&entry->rw_lock); + ret = sysfs_create_link(&entry->kobj, &entry->dev->kobj, "device"); WARN_ON(ret); - write_unlock(&entry->rw_lock); - printk(KERN_INFO PDCS_PREFIX ": changed \"%s\" path to \"%s\"\n", entry->name, buf); @@ -998,6 +998,7 @@ pdcs_register_pathentries(void) /* kobject is now registered */ write_lock(&entry->rw_lock); entry->ready = 2; + write_unlock(&entry->rw_lock); /* Add a nice symlink to the real device */ if (entry->dev) { @@ -1005,7 +1006,6 @@ pdcs_register_pathentries(void) WARN_ON(err); } - write_unlock(&entry->rw_lock); kobject_uevent(&entry->kobj, KOBJ_ADD); } diff --git a/drivers/pinctrl/stm32/Kconfig b/drivers/pinctrl/stm32/Kconfig index 3b8026fca057..7e1fe39a56a5 100644 --- a/drivers/pinctrl/stm32/Kconfig +++ b/drivers/pinctrl/stm32/Kconfig @@ -6,29 +6,30 @@ config PINCTRL_STM32 select PINMUX select GENERIC_PINCONF select GPIOLIB + select IRQ_DOMAIN_HIERARCHY select MFD_SYSCON config PINCTRL_STM32F429 bool "STMicroelectronics STM32F429 pin control" if COMPILE_TEST && !MACH_STM32F429 - depends on OF && IRQ_DOMAIN_HIERARCHY + depends on OF default MACH_STM32F429 select PINCTRL_STM32 config PINCTRL_STM32F469 bool "STMicroelectronics STM32F469 pin control" if COMPILE_TEST && !MACH_STM32F469 - depends on OF && IRQ_DOMAIN_HIERARCHY + depends on OF default MACH_STM32F469 select PINCTRL_STM32 config PINCTRL_STM32F746 bool "STMicroelectronics STM32F746 pin control" if COMPILE_TEST && !MACH_STM32F746 - depends on OF && IRQ_DOMAIN_HIERARCHY + depends on OF default MACH_STM32F746 select PINCTRL_STM32 config PINCTRL_STM32H743 bool "STMicroelectronics STM32H743 pin control" if COMPILE_TEST && !MACH_STM32H743 - depends on OF && IRQ_DOMAIN_HIERARCHY + depends on OF default MACH_STM32H743 select PINCTRL_STM32 endif diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index b04860703740..80b87954f6dd 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -675,6 +675,7 @@ config PEAQ_WMI tristate "PEAQ 2-in-1 WMI hotkey driver" depends on ACPI_WMI depends on INPUT + select INPUT_POLLDEV help Say Y here if you want to support WMI-based hotkeys on PEAQ 2-in-1s. diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index f8978464df31..dad8f4afa17c 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -626,7 +626,7 @@ static void dell_wmi_input_destroy(struct wmi_device *wdev) * WMI Interface Version 8 4 <version> * WMI buffer length 12 4 4096 */ -static int __init dell_wmi_check_descriptor_buffer(void) +static int dell_wmi_check_descriptor_buffer(void) { struct acpi_buffer out = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *obj; @@ -717,9 +717,15 @@ static int dell_wmi_events_set_enabled(bool enable) static int dell_wmi_probe(struct wmi_device *wdev) { + int err; + struct dell_wmi_priv *priv = devm_kzalloc( &wdev->dev, sizeof(struct dell_wmi_priv), GFP_KERNEL); + err = dell_wmi_check_descriptor_buffer(); + if (err) + return err; + dev_set_drvdata(&wdev->dev, priv); return dell_wmi_input_setup(wdev); @@ -749,10 +755,6 @@ static int __init dell_wmi_init(void) { int err; - err = dell_wmi_check_descriptor_buffer(); - if (err) - return err; - dmi_check_system(dell_wmi_smbios_list); if (wmi_requires_smbios_request) { diff --git a/drivers/platform/x86/intel-vbtn.c b/drivers/platform/x86/intel-vbtn.c index 61f106377661..480926786cb8 100644 --- a/drivers/platform/x86/intel-vbtn.c +++ b/drivers/platform/x86/intel-vbtn.c @@ -36,8 +36,8 @@ static const struct acpi_device_id intel_vbtn_ids[] = { /* In theory, these are HID usages. */ static const struct key_entry intel_vbtn_keymap[] = { - { KE_IGNORE, 0xC0, { KEY_POWER } }, /* power key press */ - { KE_KEY, 0xC1, { KEY_POWER } }, /* power key release */ + { KE_KEY, 0xC0, { KEY_POWER } }, /* power key press */ + { KE_IGNORE, 0xC1, { KEY_POWER } }, /* power key release */ { KE_KEY, 0xC4, { KEY_VOLUMEUP } }, /* volume-up key press */ { KE_IGNORE, 0xC5, { KEY_VOLUMEUP } }, /* volume-up key release */ { KE_KEY, 0xC6, { KEY_VOLUMEDOWN } }, /* volume-down key press */ diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 1a764e311e11..e32ba575e8d9 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -1252,12 +1252,12 @@ static int __init acpi_wmi_init(void) return 0; -err_unreg_class: - class_unregister(&wmi_bus_class); - err_unreg_bus: bus_unregister(&wmi_bus_type); +err_unreg_class: + class_unregister(&wmi_bus_class); + return error; } diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 04efed171c88..f32765d3cbd8 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -212,8 +212,8 @@ static int d7s_probe(struct platform_device *op) writeb(regs, p->regs); - printk(KERN_INFO PFX "7-Segment Display%s at [%s:0x%llx] %s\n", - op->dev.of_node->full_name, + printk(KERN_INFO PFX "7-Segment Display%pOF at [%s:0x%llx] %s\n", + op->dev.of_node, (regs & D7S_FLIP) ? " (FLIPPED)" : "", op->resource[0].start, sol_compat ? "in sol_compat mode" : ""); diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 216f923161d1..a610b8d3d11f 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c @@ -181,8 +181,8 @@ static int flash_probe(struct platform_device *op) } flash.busy = 0; - printk(KERN_INFO "%s: OBP Flash, RD %lx[%lx] WR %lx[%lx]\n", - op->dev.of_node->full_name, + printk(KERN_INFO "%pOF: OBP Flash, RD %lx[%lx] WR %lx[%lx]\n", + op->dev.of_node, flash.read_base, flash.read_size, flash.write_base, flash.write_size); diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 57696fc0b482..0a5013350acd 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c @@ -379,8 +379,8 @@ static int uctrl_probe(struct platform_device *op) } sbus_writel(UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK, &p->regs->uctrl_intr); - printk(KERN_INFO "%s: uctrl regs[0x%p] (irq %d)\n", - op->dev.of_node->full_name, p->regs, p->irq); + printk(KERN_INFO "%pOF: uctrl regs[0x%p] (irq %d)\n", + op->dev.of_node, p->regs, p->irq); uctrl_get_event_status(p); uctrl_get_external_status(p); diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index d384f4f86c26..f4538d7a3016 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -1230,6 +1230,8 @@ config SCSI_LPFC tristate "Emulex LightPulse Fibre Channel Support" depends on PCI && SCSI depends on SCSI_FC_ATTRS + depends on NVME_TARGET_FC || NVME_TARGET_FC=n + depends on NVME_FC || NVME_FC=n select CRC_T10DIF ---help--- This lpfc driver supports the Emulex LightPulse diff --git a/drivers/scsi/aic7xxx/Makefile b/drivers/scsi/aic7xxx/Makefile index 741d81861d17..07b60a780c06 100644 --- a/drivers/scsi/aic7xxx/Makefile +++ b/drivers/scsi/aic7xxx/Makefile @@ -55,9 +55,9 @@ aicasm-7xxx-opts-$(CONFIG_AIC7XXX_REG_PRETTY_PRINT) := \ ifeq ($(CONFIG_AIC7XXX_BUILD_FIRMWARE),y) $(obj)/aic7xxx_seq.h: $(src)/aic7xxx.seq $(src)/aic7xxx.reg $(obj)/aicasm/aicasm - $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic7xxx_reg.h \ + $(obj)/aicasm/aicasm -I$(srctree)/$(src) -r $(obj)/aic7xxx_reg.h \ $(aicasm-7xxx-opts-y) -o $(obj)/aic7xxx_seq.h \ - $(src)/aic7xxx.seq + $(srctree)/$(src)/aic7xxx.seq $(aic7xxx-gen-y): $(obj)/aic7xxx_seq.h else @@ -72,14 +72,14 @@ aicasm-79xx-opts-$(CONFIG_AIC79XX_REG_PRETTY_PRINT) := \ ifeq ($(CONFIG_AIC79XX_BUILD_FIRMWARE),y) $(obj)/aic79xx_seq.h: $(src)/aic79xx.seq $(src)/aic79xx.reg $(obj)/aicasm/aicasm - $(obj)/aicasm/aicasm -I$(src) -r $(obj)/aic79xx_reg.h \ + $(obj)/aicasm/aicasm -I$(srctree)/$(src) -r $(obj)/aic79xx_reg.h \ $(aicasm-79xx-opts-y) -o $(obj)/aic79xx_seq.h \ - $(src)/aic79xx.seq + $(srctree)/$(src)/aic79xx.seq $(aic79xx-gen-y): $(obj)/aic79xx_seq.h else $(obj)/aic79xx_reg_print.c: $(src)/aic79xx_reg_print.c_shipped endif -$(obj)/aicasm/aicasm: $(src)/aicasm/*.[chyl] - $(MAKE) -C $(src)/aicasm +$(obj)/aicasm/aicasm: $(srctree)/$(src)/aicasm/*.[chyl] + $(MAKE) -C $(srctree)/$(src)/aicasm OUTDIR=$(shell pwd)/$(obj)/aicasm/ diff --git a/drivers/scsi/aic7xxx/aicasm/Makefile b/drivers/scsi/aic7xxx/aicasm/Makefile index b98c5c1056c3..45e2d49c1fff 100644 --- a/drivers/scsi/aic7xxx/aicasm/Makefile +++ b/drivers/scsi/aic7xxx/aicasm/Makefile @@ -1,19 +1,21 @@ PROG= aicasm +OUTDIR ?= ./ + .SUFFIXES= .l .y .c .h CSRCS= aicasm.c aicasm_symbol.c YSRCS= aicasm_gram.y aicasm_macro_gram.y LSRCS= aicasm_scan.l aicasm_macro_scan.l -GENHDRS= aicdb.h $(YSRCS:.y=.h) -GENSRCS= $(YSRCS:.y=.c) $(LSRCS:.l=.c) +GENHDRS= $(addprefix ${OUTDIR}/,aicdb.h $(YSRCS:.y=.h)) +GENSRCS= $(addprefix ${OUTDIR}/,$(YSRCS:.y=.c) $(LSRCS:.l=.c)) SRCS= ${CSRCS} ${GENSRCS} LIBS= -ldb clean-files:= ${GENSRCS} ${GENHDRS} $(YSRCS:.y=.output) $(PROG) # Override default kernel CFLAGS. This is a userland app. -AICASM_CFLAGS:= -I/usr/include -I. +AICASM_CFLAGS:= -I/usr/include -I. -I$(OUTDIR) LEX= flex YACC= bison YFLAGS= -d @@ -32,22 +34,25 @@ YFLAGS+= -t -v LFLAGS= -d endif -$(PROG): ${GENHDRS} $(SRCS) - $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(PROG) $(LIBS) +$(PROG): $(OUTDIR) ${GENHDRS} $(SRCS) + $(AICASM_CC) $(AICASM_CFLAGS) $(SRCS) -o $(OUTDIR)/$(PROG) $(LIBS) + +$(OUTDIR): + mkdir -p $(OUTDIR) -aicdb.h: +$(OUTDIR)/aicdb.h: @if [ -e "/usr/include/db4/db_185.h" ]; then \ - echo "#include <db4/db_185.h>" > aicdb.h; \ + echo "#include <db4/db_185.h>" > $@; \ elif [ -e "/usr/include/db3/db_185.h" ]; then \ - echo "#include <db3/db_185.h>" > aicdb.h; \ + echo "#include <db3/db_185.h>" > $@; \ elif [ -e "/usr/include/db2/db_185.h" ]; then \ - echo "#include <db2/db_185.h>" > aicdb.h; \ + echo "#include <db2/db_185.h>" > $@; \ elif [ -e "/usr/include/db1/db_185.h" ]; then \ - echo "#include <db1/db_185.h>" > aicdb.h; \ + echo "#include <db1/db_185.h>" > $@; \ elif [ -e "/usr/include/db/db_185.h" ]; then \ - echo "#include <db/db_185.h>" > aicdb.h; \ + echo "#include <db/db_185.h>" > $@; \ elif [ -e "/usr/include/db_185.h" ]; then \ - echo "#include <db_185.h>" > aicdb.h; \ + echo "#include <db_185.h>" > $@; \ else \ echo "*** Install db development libraries"; \ fi @@ -58,23 +63,23 @@ clean: # Create a dependency chain in generated files # to avoid concurrent invocations of the single # rule that builds them all. -aicasm_gram.c: aicasm_gram.h -aicasm_gram.c aicasm_gram.h: aicasm_gram.y +$(OUTDIR)/aicasm_gram.c: $(OUTDIR)/aicasm_gram.h +$(OUTDIR)/aicasm_gram.c $(OUTDIR)/aicasm_gram.h: aicasm_gram.y $(YACC) $(YFLAGS) -b $(<:.y=) $< - mv $(<:.y=).tab.c $(<:.y=.c) - mv $(<:.y=).tab.h $(<:.y=.h) + mv $(<:.y=).tab.c $(OUTDIR)/$(<:.y=.c) + mv $(<:.y=).tab.h $(OUTDIR)/$(<:.y=.h) # Create a dependency chain in generated files # to avoid concurrent invocations of the single # rule that builds them all. -aicasm_macro_gram.c: aicasm_macro_gram.h -aicasm_macro_gram.c aicasm_macro_gram.h: aicasm_macro_gram.y +$(OUTDIR)/aicasm_macro_gram.c: $(OUTDIR)/aicasm_macro_gram.h +$(OUTDIR)/aicasm_macro_gram.c $(OUTDIR)/aicasm_macro_gram.h: aicasm_macro_gram.y $(YACC) $(YFLAGS) -b $(<:.y=) -p mm $< - mv $(<:.y=).tab.c $(<:.y=.c) - mv $(<:.y=).tab.h $(<:.y=.h) + mv $(<:.y=).tab.c $(OUTDIR)/$(<:.y=.c) + mv $(<:.y=).tab.h $(OUTDIR)/$(<:.y=.h) -aicasm_scan.c: aicasm_scan.l - $(LEX) $(LFLAGS) -o$@ $< +$(OUTDIR)/aicasm_scan.c: aicasm_scan.l + $(LEX) $(LFLAGS) -o $@ $< -aicasm_macro_scan.c: aicasm_macro_scan.l - $(LEX) $(LFLAGS) -Pmm -o$@ $< +$(OUTDIR)/aicasm_macro_scan.c: aicasm_macro_scan.l + $(LEX) $(LFLAGS) -Pmm -o $@ $< diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index e4c83b7c96a8..1a4cfa562a60 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -2128,6 +2128,13 @@ void cxgbi_cleanup_task(struct iscsi_task *task) struct iscsi_tcp_task *tcp_task = task->dd_data; struct cxgbi_task_data *tdata = iscsi_task_cxgbi_data(task); + if (!tcp_task || !tdata || (tcp_task->dd_data != tdata)) { + pr_info("task 0x%p,0x%p, tcp_task 0x%p, tdata 0x%p/0x%p.\n", + task, task->sc, tcp_task, + tcp_task ? tcp_task->dd_data : NULL, tdata); + return; + } + log_debug(1 << CXGBI_DBG_ISCSI, "task 0x%p, skb 0x%p, itt 0x%x.\n", task, tdata->skb, task->hdr_itt); diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index f990ab4d45e1..985510628f56 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -425,7 +425,7 @@ static int megasas_create_sg_sense_fusion(struct megasas_instance *instance) int megasas_alloc_cmdlist_fusion(struct megasas_instance *instance) { - u32 max_mpt_cmd, i; + u32 max_mpt_cmd, i, j; struct fusion_context *fusion; fusion = instance->ctrl_context; @@ -450,11 +450,15 @@ megasas_alloc_cmdlist_fusion(struct megasas_instance *instance) fusion->cmd_list[i] = kzalloc(sizeof(struct megasas_cmd_fusion), GFP_KERNEL); if (!fusion->cmd_list[i]) { + for (j = 0; j < i; j++) + kfree(fusion->cmd_list[j]); + kfree(fusion->cmd_list); dev_err(&instance->pdev->dev, "Failed from %s %d\n", __func__, __LINE__); return -ENOMEM; } } + return 0; } int diff --git a/drivers/scsi/qedi/Kconfig b/drivers/scsi/qedi/Kconfig index 21331453db7b..2ff753ce6e27 100644 --- a/drivers/scsi/qedi/Kconfig +++ b/drivers/scsi/qedi/Kconfig @@ -5,6 +5,7 @@ config QEDI select SCSI_ISCSI_ATTRS select QED_LL2 select QED_ISCSI + select ISCSI_BOOT_SYSFS ---help--- This driver supports iSCSI offload for the QLogic FastLinQ 41000 Series Converged Network Adapters. diff --git a/drivers/scsi/qedi/qedi_iscsi.c b/drivers/scsi/qedi/qedi_iscsi.c index 80edd28b635f..37da9a8b43b1 100644 --- a/drivers/scsi/qedi/qedi_iscsi.c +++ b/drivers/scsi/qedi/qedi_iscsi.c @@ -824,7 +824,7 @@ qedi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, u32 iscsi_cid = QEDI_CID_RESERVED; u16 len = 0; char *buf = NULL; - int ret; + int ret, tmp; if (!shost) { ret = -ENXIO; @@ -940,10 +940,10 @@ qedi_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr, ep_rel_conn: qedi->ep_tbl[iscsi_cid] = NULL; - ret = qedi_ops->release_conn(qedi->cdev, qedi_ep->handle); - if (ret) + tmp = qedi_ops->release_conn(qedi->cdev, qedi_ep->handle); + if (tmp) QEDI_WARN(&qedi->dbg_ctx, "release_conn returned %d\n", - ret); + tmp); ep_free_sq: qedi_free_sq(qedi, qedi_ep); ep_conn_exit: diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 7e24aa30c3b0..892fbd9800d9 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -1286,7 +1286,7 @@ store_fc_vport_delete(struct device *dev, struct device_attribute *attr, unsigned long flags; spin_lock_irqsave(shost->host_lock, flags); - if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING)) { + if (vport->flags & (FC_VPORT_DEL | FC_VPORT_CREATING | FC_VPORT_DELETING)) { spin_unlock_irqrestore(shost->host_lock, flags); return -EBUSY; } @@ -2430,8 +2430,10 @@ fc_remove_host(struct Scsi_Host *shost) spin_lock_irqsave(shost->host_lock, flags); /* Remove any vports */ - list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) + list_for_each_entry_safe(vport, next_vport, &fc_host->vports, peers) { + vport->flags |= FC_VPORT_DELETING; fc_queue_work(shost, &vport->vport_delete_work); + } /* Remove any remote ports */ list_for_each_entry_safe(rport, next_rport, diff --git a/drivers/soc/zte/Kconfig b/drivers/soc/zte/Kconfig index 20bde38ce2f9..e9d750c510cd 100644 --- a/drivers/soc/zte/Kconfig +++ b/drivers/soc/zte/Kconfig @@ -2,6 +2,7 @@ # ZTE SoC drivers # menuconfig SOC_ZTE + depends on ARCH_ZX || COMPILE_TEST bool "ZTE SoC driver support" if SOC_ZTE diff --git a/drivers/staging/media/atomisp/i2c/ap1302.h b/drivers/staging/media/atomisp/i2c/ap1302.h index 9341232c580d..4d0b181a9671 100644 --- a/drivers/staging/media/atomisp/i2c/ap1302.h +++ b/drivers/staging/media/atomisp/i2c/ap1302.h @@ -158,8 +158,8 @@ struct ap1302_res_struct { }; struct ap1302_context_res { - s32 res_num; - s32 cur_res; + u32 res_num; + u32 cur_res; struct ap1302_res_struct *res_table; }; diff --git a/drivers/staging/media/atomisp/i2c/gc0310.h b/drivers/staging/media/atomisp/i2c/gc0310.h index f31eb277f542..7d8a0aeecb6c 100644 --- a/drivers/staging/media/atomisp/i2c/gc0310.h +++ b/drivers/staging/media/atomisp/i2c/gc0310.h @@ -454,6 +454,6 @@ struct gc0310_resolution gc0310_res_video[] = { #define N_RES_VIDEO (ARRAY_SIZE(gc0310_res_video)) static struct gc0310_resolution *gc0310_res = gc0310_res_preview; -static int N_RES = N_RES_PREVIEW; +static unsigned long N_RES = N_RES_PREVIEW; #endif diff --git a/drivers/staging/media/atomisp/i2c/gc2235.h b/drivers/staging/media/atomisp/i2c/gc2235.h index ccbc757045a5..7c3d994180cc 100644 --- a/drivers/staging/media/atomisp/i2c/gc2235.h +++ b/drivers/staging/media/atomisp/i2c/gc2235.h @@ -668,5 +668,5 @@ struct gc2235_resolution gc2235_res_video[] = { #define N_RES_VIDEO (ARRAY_SIZE(gc2235_res_video)) static struct gc2235_resolution *gc2235_res = gc2235_res_preview; -static int N_RES = N_RES_PREVIEW; +static unsigned long N_RES = N_RES_PREVIEW; #endif diff --git a/drivers/staging/media/atomisp/i2c/imx/imx.h b/drivers/staging/media/atomisp/i2c/imx/imx.h index 36b3f3a5a41f..41b4133ca995 100644 --- a/drivers/staging/media/atomisp/i2c/imx/imx.h +++ b/drivers/staging/media/atomisp/i2c/imx/imx.h @@ -480,7 +480,7 @@ struct imx_device { struct imx_vcm *vcm_driver; struct imx_otp *otp_driver; const struct imx_resolution *curr_res_table; - int entries_curr_table; + unsigned long entries_curr_table; const struct firmware *fw; struct imx_reg_addr *reg_addr; const struct imx_reg *param_hold; diff --git a/drivers/staging/media/atomisp/i2c/ov2680.h b/drivers/staging/media/atomisp/i2c/ov2680.h index 944fe8e3bcbf..ab8907e6c9ef 100644 --- a/drivers/staging/media/atomisp/i2c/ov2680.h +++ b/drivers/staging/media/atomisp/i2c/ov2680.h @@ -934,7 +934,6 @@ static struct ov2680_resolution ov2680_res_video[] = { #define N_RES_VIDEO (ARRAY_SIZE(ov2680_res_video)) static struct ov2680_resolution *ov2680_res = ov2680_res_preview; -static int N_RES = N_RES_PREVIEW; - +static unsigned long N_RES = N_RES_PREVIEW; #endif diff --git a/drivers/staging/media/atomisp/i2c/ov2722.h b/drivers/staging/media/atomisp/i2c/ov2722.h index b0d40965d89e..73ecb1679718 100644 --- a/drivers/staging/media/atomisp/i2c/ov2722.h +++ b/drivers/staging/media/atomisp/i2c/ov2722.h @@ -1263,5 +1263,5 @@ struct ov2722_resolution ov2722_res_video[] = { #define N_RES_VIDEO (ARRAY_SIZE(ov2722_res_video)) static struct ov2722_resolution *ov2722_res = ov2722_res_preview; -static int N_RES = N_RES_PREVIEW; +static unsigned long N_RES = N_RES_PREVIEW; #endif diff --git a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h index d88ac1777d86..8c2e6794463b 100644 --- a/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h +++ b/drivers/staging/media/atomisp/i2c/ov5693/ov5693.h @@ -1377,5 +1377,5 @@ struct ov5693_resolution ov5693_res_video[] = { #define N_RES_VIDEO (ARRAY_SIZE(ov5693_res_video)) static struct ov5693_resolution *ov5693_res = ov5693_res_preview; -static int N_RES = N_RES_PREVIEW; +static unsigned long N_RES = N_RES_PREVIEW; #endif diff --git a/drivers/staging/media/atomisp/i2c/ov8858.h b/drivers/staging/media/atomisp/i2c/ov8858.h index 9be6a0e63861..d3fde200c013 100644 --- a/drivers/staging/media/atomisp/i2c/ov8858.h +++ b/drivers/staging/media/atomisp/i2c/ov8858.h @@ -266,7 +266,7 @@ struct ov8858_device { const struct ov8858_reg *regs; struct ov8858_vcm *vcm_driver; const struct ov8858_resolution *curr_res_table; - int entries_curr_table; + unsigned long entries_curr_table; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *run_mode; diff --git a/drivers/staging/media/atomisp/i2c/ov8858_btns.h b/drivers/staging/media/atomisp/i2c/ov8858_btns.h index 09e3cdc1a394..f9a3cf8fbf1a 100644 --- a/drivers/staging/media/atomisp/i2c/ov8858_btns.h +++ b/drivers/staging/media/atomisp/i2c/ov8858_btns.h @@ -266,7 +266,7 @@ struct ov8858_device { const struct ov8858_reg *regs; struct ov8858_vcm *vcm_driver; const struct ov8858_resolution *curr_res_table; - int entries_curr_table; + unsigned long entries_curr_table; struct v4l2_ctrl_handler ctrl_handler; struct v4l2_ctrl *run_mode; diff --git a/drivers/staging/media/atomisp/pci/atomisp2/Makefile b/drivers/staging/media/atomisp/pci/atomisp2/Makefile index 726eaa293c55..2bd98f0667ec 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/Makefile +++ b/drivers/staging/media/atomisp/pci/atomisp2/Makefile @@ -354,7 +354,9 @@ ccflags-y += $(INCLUDES) $(DEFINES) -fno-common # HACK! While this driver is in bad shape, don't enable several warnings # that would be otherwise enabled with W=1 -ccflags-y += -Wno-unused-const-variable -Wno-missing-prototypes \ - -Wno-unused-but-set-variable -Wno-missing-declarations \ - -Wno-suggest-attribute=format -Wno-missing-prototypes \ - -Wno-implicit-fallthrough +ccflags-y += $(call cc-disable-warning, implicit-fallthrough) +ccflags-y += $(call cc-disable-warning, missing-prototypes) +ccflags-y += $(call cc-disable-warning, missing-declarations) +ccflags-y += $(call cc-disable-warning, suggest-attribute=format) +ccflags-y += $(call cc-disable-warning, unused-const-variable) +ccflags-y += $(call cc-disable-warning, unused-but-set-variable) diff --git a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_internal.h index d3667132851b..c8e0c4fe3717 100644 --- a/drivers/staging/media/atomisp/pci/atomisp2/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp2/atomisp_internal.h @@ -275,7 +275,7 @@ struct atomisp_device { */ struct mutex streamoff_mutex; - int input_cnt; + unsigned int input_cnt; struct atomisp_input_subdev inputs[ATOM_ISP_MAX_INPUTS]; struct v4l2_subdev *flash; struct v4l2_subdev *motor; diff --git a/drivers/staging/media/cxd2099/cxd2099.c b/drivers/staging/media/cxd2099/cxd2099.c index 370ecb959543..f28916ea69f1 100644 --- a/drivers/staging/media/cxd2099/cxd2099.c +++ b/drivers/staging/media/cxd2099/cxd2099.c @@ -1,7 +1,7 @@ /* * cxd2099.c: Driver for the CXD2099AR Common Interface Controller * - * Copyright (C) 2010-2011 Digital Devices GmbH + * Copyright (C) 2010-2013 Digital Devices GmbH * * * This program is free software; you can redistribute it and/or @@ -33,7 +33,10 @@ #include "cxd2099.h" -#define MAX_BUFFER_SIZE 248 +/* comment this line to deactivate the cxd2099ar buffer mode */ +#define BUFFER_MODE 1 + +static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount); struct cxd { struct dvb_ca_en50221 en; @@ -48,6 +51,7 @@ struct cxd { int mode; int ready; int dr; + int write_busy; int slot_stat; u8 amem[1024]; @@ -55,6 +59,9 @@ struct cxd { int cammode; struct mutex lock; + + u8 rbuf[1028]; + u8 wbuf[1028]; }; static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr, @@ -73,7 +80,7 @@ static int i2c_write_reg(struct i2c_adapter *adapter, u8 adr, } static int i2c_write(struct i2c_adapter *adapter, u8 adr, - u8 *data, u8 len) + u8 *data, u16 len) { struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = data, .len = len}; @@ -100,12 +107,12 @@ static int i2c_read_reg(struct i2c_adapter *adapter, u8 adr, } static int i2c_read(struct i2c_adapter *adapter, u8 adr, - u8 reg, u8 *data, u8 n) + u8 reg, u8 *data, u16 n) { struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0, - .buf = ®, .len = 1}, - {.addr = adr, .flags = I2C_M_RD, - .buf = data, .len = n} }; + .buf = ®, .len = 1}, + {.addr = adr, .flags = I2C_M_RD, + .buf = data, .len = n} }; if (i2c_transfer(adapter, msgs, 2) != 2) { dev_err(&adapter->dev, "error in i2c_read\n"); @@ -114,14 +121,26 @@ static int i2c_read(struct i2c_adapter *adapter, u8 adr, return 0; } -static int read_block(struct cxd *ci, u8 adr, u8 *data, u8 n) +static int read_block(struct cxd *ci, u8 adr, u8 *data, u16 n) { - int status; + int status = 0; - status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); + if (ci->lastaddress != adr) + status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); if (!status) { ci->lastaddress = adr; - status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, n); + + while (n) { + int len = n; + + if (ci->cfg.max_i2c && (len > ci->cfg.max_i2c)) + len = ci->cfg.max_i2c; + status = i2c_read(ci->i2c, ci->cfg.adr, 1, data, len); + if (status) + return status; + data += len; + n -= len; + } } return status; } @@ -182,16 +201,16 @@ static int write_io(struct cxd *ci, u16 address, u8 val) static int write_regm(struct cxd *ci, u8 reg, u8 val, u8 mask) { - int status; + int status = 0; - status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg); + if (ci->lastaddress != reg) + status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, reg); if (!status && reg >= 6 && reg <= 8 && mask != 0xff) status = i2c_read_reg(ci->i2c, ci->cfg.adr, 1, &ci->regs[reg]); + ci->lastaddress = reg; ci->regs[reg] = (ci->regs[reg] & (~mask)) | val; - if (!status) { - ci->lastaddress = reg; + if (!status) status = i2c_write_reg(ci->i2c, ci->cfg.adr, 1, ci->regs[reg]); - } if (reg == 0x20) ci->regs[reg] &= 0x7f; return status; @@ -203,16 +222,29 @@ static int write_reg(struct cxd *ci, u8 reg, u8 val) } #ifdef BUFFER_MODE -static int write_block(struct cxd *ci, u8 adr, u8 *data, int n) +static int write_block(struct cxd *ci, u8 adr, u8 *data, u16 n) { - int status; - u8 buf[256] = {1}; - - status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); - if (!status) { - ci->lastaddress = adr; - memcpy(buf + 1, data, n); - status = i2c_write(ci->i2c, ci->cfg.adr, buf, n + 1); + int status = 0; + u8 *buf = ci->wbuf; + + if (ci->lastaddress != adr) + status = i2c_write_reg(ci->i2c, ci->cfg.adr, 0, adr); + if (status) + return status; + + ci->lastaddress = adr; + buf[0] = 1; + while (n) { + int len = n; + + if (ci->cfg.max_i2c && (len + 1 > ci->cfg.max_i2c)) + len = ci->cfg.max_i2c - 1; + memcpy(buf + 1, data, len); + status = i2c_write(ci->i2c, ci->cfg.adr, buf, len + 1); + if (status) + return status; + n -= len; + data += len; } return status; } @@ -238,6 +270,8 @@ static void set_mode(struct cxd *ci, int mode) static void cam_mode(struct cxd *ci, int mode) { + u8 dummy; + if (mode == ci->cammode) return; @@ -246,16 +280,15 @@ static void cam_mode(struct cxd *ci, int mode) write_regm(ci, 0x20, 0x80, 0x80); break; case 0x01: -#ifdef BUFFER_MODE if (!ci->en.read_data) return; + ci->write_busy = 0; dev_info(&ci->i2c->dev, "enable cam buffer mode\n"); - /* write_reg(ci, 0x0d, 0x00); */ - /* write_reg(ci, 0x0e, 0x01); */ + write_reg(ci, 0x0d, 0x00); + write_reg(ci, 0x0e, 0x01); write_regm(ci, 0x08, 0x40, 0x40); - /* read_reg(ci, 0x12, &dummy); */ + read_reg(ci, 0x12, &dummy); write_regm(ci, 0x08, 0x80, 0x80); -#endif break; default: break; @@ -325,7 +358,10 @@ static int init(struct cxd *ci) if (status < 0) break; - if (ci->cfg.clock_mode) { + if (ci->cfg.clock_mode == 2) { + /* bitrate*2^13/ 72000 */ + u32 reg = ((ci->cfg.bitrate << 13) + 71999) / 72000; + if (ci->cfg.polarity) { status = write_reg(ci, 0x09, 0x6f); if (status < 0) @@ -335,6 +371,25 @@ static int init(struct cxd *ci) if (status < 0) break; } + status = write_reg(ci, 0x20, 0x08); + if (status < 0) + break; + status = write_reg(ci, 0x21, (reg >> 8) & 0xff); + if (status < 0) + break; + status = write_reg(ci, 0x22, reg & 0xff); + if (status < 0) + break; + } else if (ci->cfg.clock_mode == 1) { + if (ci->cfg.polarity) { + status = write_reg(ci, 0x09, 0x6f); /* D */ + if (status < 0) + break; + } else { + status = write_reg(ci, 0x09, 0x6d); + if (status < 0) + break; + } status = write_reg(ci, 0x20, 0x68); if (status < 0) break; @@ -346,7 +401,7 @@ static int init(struct cxd *ci) break; } else { if (ci->cfg.polarity) { - status = write_reg(ci, 0x09, 0x4f); + status = write_reg(ci, 0x09, 0x4f); /* C */ if (status < 0) break; } else { @@ -354,7 +409,6 @@ static int init(struct cxd *ci) if (status < 0) break; } - status = write_reg(ci, 0x20, 0x28); if (status < 0) break; @@ -401,7 +455,6 @@ static int read_attribute_mem(struct dvb_ca_en50221 *ca, set_mode(ci, 1); read_pccard(ci, address, &val, 1); mutex_unlock(&ci->lock); - /* printk(KERN_INFO "%02x:%02x\n", address,val); */ return val; } @@ -446,6 +499,9 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) { struct cxd *ci = ca->data; + if (ci->cammode) + read_data(ca, slot, ci->rbuf, 0); + mutex_lock(&ci->lock); cam_mode(ci, 0); write_reg(ci, 0x00, 0x21); @@ -465,7 +521,6 @@ static int slot_reset(struct dvb_ca_en50221 *ca, int slot) } } mutex_unlock(&ci->lock); - /* msleep(500); */ return 0; } @@ -474,11 +529,19 @@ static int slot_shutdown(struct dvb_ca_en50221 *ca, int slot) struct cxd *ci = ca->data; dev_info(&ci->i2c->dev, "%s\n", __func__); + if (ci->cammode) + read_data(ca, slot, ci->rbuf, 0); mutex_lock(&ci->lock); + write_reg(ci, 0x00, 0x21); + write_reg(ci, 0x06, 0x1F); + msleep(300); + write_regm(ci, 0x09, 0x08, 0x08); write_regm(ci, 0x20, 0x80, 0x80); /* Reset CAM Mode */ write_regm(ci, 0x06, 0x07, 0x07); /* Clear IO Mode */ + ci->mode = -1; + ci->write_busy = 0; mutex_unlock(&ci->lock); return 0; } @@ -490,9 +553,7 @@ static int slot_ts_enable(struct dvb_ca_en50221 *ca, int slot) mutex_lock(&ci->lock); write_regm(ci, 0x09, 0x00, 0x08); set_mode(ci, 0); -#ifdef BUFFER_MODE cam_mode(ci, 1); -#endif mutex_unlock(&ci->lock); return 0; } @@ -506,12 +567,10 @@ static int campoll(struct cxd *ci) return 0; write_reg(ci, 0x05, istat); - if (istat & 0x40) { + if (istat & 0x40) ci->dr = 1; - dev_info(&ci->i2c->dev, "DR\n"); - } if (istat & 0x20) - dev_info(&ci->i2c->dev, "WC\n"); + ci->write_busy = 0; if (istat & 2) { u8 slotstat; @@ -519,7 +578,8 @@ static int campoll(struct cxd *ci) read_reg(ci, 0x01, &slotstat); if (!(2 & slotstat)) { if (!ci->slot_stat) { - ci->slot_stat = DVB_CA_EN50221_POLL_CAM_PRESENT; + ci->slot_stat |= + DVB_CA_EN50221_POLL_CAM_PRESENT; write_regm(ci, 0x03, 0x08, 0x08); } @@ -531,8 +591,8 @@ static int campoll(struct cxd *ci) ci->ready = 0; } } - if (istat & 8 && - ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT) { + if ((istat & 8) && + (ci->slot_stat == DVB_CA_EN50221_POLL_CAM_PRESENT)) { ci->ready = 1; ci->slot_stat |= DVB_CA_EN50221_POLL_CAM_READY; } @@ -553,7 +613,6 @@ static int poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) return ci->slot_stat; } -#ifdef BUFFER_MODE static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) { struct cxd *ci = ca->data; @@ -564,30 +623,38 @@ static int read_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) campoll(ci); mutex_unlock(&ci->lock); - dev_info(&ci->i2c->dev, "%s\n", __func__); if (!ci->dr) return 0; mutex_lock(&ci->lock); read_reg(ci, 0x0f, &msb); read_reg(ci, 0x10, &lsb); - len = (msb << 8) | lsb; + len = ((u16)msb << 8) | lsb; + if (len > ecount || len < 2) { + /* read it anyway or cxd may hang */ + read_block(ci, 0x12, ci->rbuf, len); + mutex_unlock(&ci->lock); + return -EIO; + } read_block(ci, 0x12, ebuf, len); ci->dr = 0; mutex_unlock(&ci->lock); - return len; } +#ifdef BUFFER_MODE + static int write_data(struct dvb_ca_en50221 *ca, int slot, u8 *ebuf, int ecount) { struct cxd *ci = ca->data; + if (ci->write_busy) + return -EAGAIN; mutex_lock(&ci->lock); - dev_info(&ci->i2c->dev, "%s %d\n", __func__, ecount); write_reg(ci, 0x0d, ecount >> 8); write_reg(ci, 0x0e, ecount & 0xff); write_block(ci, 0x11, ebuf, ecount); + ci->write_busy = 1; mutex_unlock(&ci->lock); return ecount; } diff --git a/drivers/staging/media/cxd2099/cxd2099.h b/drivers/staging/media/cxd2099/cxd2099.h index 0eb607c5b423..f4b29b1d6eb8 100644 --- a/drivers/staging/media/cxd2099/cxd2099.h +++ b/drivers/staging/media/cxd2099/cxd2099.h @@ -30,8 +30,10 @@ struct cxd2099_cfg { u32 bitrate; u8 adr; - u8 polarity:1; - u8 clock_mode:1; + u8 polarity; + u8 clock_mode; + + u32 max_i2c; }; #if defined(CONFIG_DVB_CXD2099) || \ diff --git a/drivers/thunderbolt/icm.c b/drivers/thunderbolt/icm.c index 8ee340290219..bdaac1ff00a5 100644 --- a/drivers/thunderbolt/icm.c +++ b/drivers/thunderbolt/icm.c @@ -904,7 +904,14 @@ static int icm_driver_ready(struct tb *tb) static int icm_suspend(struct tb *tb) { - return nhi_mailbox_cmd(tb->nhi, NHI_MAILBOX_SAVE_DEVS, 0); + int ret; + + ret = nhi_mailbox_cmd(tb->nhi, NHI_MAILBOX_SAVE_DEVS, 0); + if (ret) + tb_info(tb, "Ignoring mailbox command error (%d) in %s\n", + ret, __func__); + + return 0; } /* diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c index b5c98e5bf524..c6360fbdf808 100644 --- a/drivers/tty/serial/8250/8250_exar.c +++ b/drivers/tty/serial/8250/8250_exar.c @@ -261,7 +261,7 @@ __xr17v35x_register_gpio(struct pci_dev *pcidev, } static const struct property_entry exar_gpio_properties[] = { - PROPERTY_ENTRY_U32("linux,first-pin", 0), + PROPERTY_ENTRY_U32("exar,first-pin", 0), PROPERTY_ENTRY_U32("ngpios", 16), { } }; @@ -326,7 +326,7 @@ static int iot2040_rs485_config(struct uart_port *port, } static const struct property_entry iot2040_gpio_properties[] = { - PROPERTY_ENTRY_U32("linux,first-pin", 10), + PROPERTY_ENTRY_U32("exar,first-pin", 10), PROPERTY_ENTRY_U32("ngpios", 1), { } }; diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 063c1ce6fa42..f041b1a6cf66 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -226,7 +226,14 @@ static int vfio_pci_enable(struct vfio_pci_device *vdev) if (ret) return ret; - vdev->reset_works = (pci_reset_function(pdev) == 0); + /* If reset fails because of the device lock, fail this path entirely */ + ret = pci_try_reset_function(pdev); + if (ret == -EAGAIN) { + pci_disable_device(pdev); + return ret; + } + + vdev->reset_works = !ret; pci_save_state(pdev); vdev->pci_saved_state = pci_store_saved_state(pdev); if (!vdev->pci_saved_state) diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 330a57024cbc..5628fe114347 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c @@ -839,7 +839,7 @@ static int vfio_exp_config_write(struct vfio_pci_device *vdev, int pos, /* Permissions for PCI Express capability */ static int __init init_pci_cap_exp_perm(struct perm_bits *perm) { - /* Alloc larger of two possible sizes */ + /* Alloc largest of possible sizes */ if (alloc_perm_bits(perm, PCI_CAP_EXP_ENDPOINT_SIZEOF_V2)) return -ENOMEM; @@ -1243,11 +1243,16 @@ static int vfio_cap_len(struct vfio_pci_device *vdev, u8 cap, u8 pos) vdev->extended_caps = (dword != 0); } - /* length based on version */ - if ((pcie_caps_reg(pdev) & PCI_EXP_FLAGS_VERS) == 1) + /* length based on version and type */ + if ((pcie_caps_reg(pdev) & PCI_EXP_FLAGS_VERS) == 1) { + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END) + return 0xc; /* "All Devices" only, no link */ return PCI_CAP_EXP_ENDPOINT_SIZEOF_V1; - else + } else { + if (pci_pcie_type(pdev) == PCI_EXP_TYPE_RC_END) + return 0x2c; /* No link */ return PCI_CAP_EXP_ENDPOINT_SIZEOF_V2; + } case PCI_CAP_ID_HT: ret = pci_read_config_byte(pdev, pos + 3, &byte); if (ret) |