diff options
author | Kevin Hilman <khilman@baylibre.com> | 2016-04-22 19:45:53 +0300 |
---|---|---|
committer | Kevin Hilman <khilman@baylibre.com> | 2016-04-22 19:45:53 +0300 |
commit | c0e309138be2e4ba1551dde76f7fa2479cd9198d (patch) | |
tree | 81d7681547f8717c5a5416315110050f1a2a4962 /drivers | |
parent | 2193a3fd7bc6ffd607c1a791d05d22a4a2282c57 (diff) | |
parent | 3d51ae172d759198b2e47e104c31a92d20d17927 (diff) | |
download | linux-c0e309138be2e4ba1551dde76f7fa2479cd9198d.tar.xz |
Merge tag 'omap-for-v4.6/fixes-rc2-v2-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into fixes
Merge "omap fixes against v4.6-rc2" from Tony Lindgren
Fixes for omaps against v4.6-rc2, mostly to fix suspend for beagle-x15
that broke when we added runtime based SoC revision detection earlier.
It seems suspend worked earlier as things were only partially initialized,
while now we initialize things properly for dra7.
Note that the "ARM: OMAP: Catch callers of revision information prior
to it being populated" had to be reverted as it caused bogus warnings
for other SoCs because omap initcalls bail out based on revision being
set to 0 for other SoCs. These initcalls will mostly just disappear
when we drop support for omap3 legacy booting.
Also included is a fix for dra7 sys_32k_ck clock source that is not
enabled on boot making system fall back to using emulated clock.
* tag 'omap-for-v4.6/fixes-rc2-v2-signed' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap: (198 commits)
Revert "ARM: OMAP: Catch callers of revision information prior to it being populated"
ARM: OMAP: Catch callers of revision information prior to it being populated
ARM: dts: dra7: Correct clock tree for sys_32k_ck
ARM: OMAP: DRA7: Provide proper class to omap2_set_globals_tap
ARM: OMAP: DRA7: wakeupgen: Skip SAR save for wakeupgen
Linux 4.6-rc2
v4l2-mc: avoid warning about unused variable
Convert straggling drivers to new six-argument get_user_pages()
.mailmap: add Christophe Ricard
Make CONFIG_FHANDLE default y
mm/page_isolation.c: fix the function comments
oom, oom_reaper: do not enqueue task if it is on the oom_reaper_list head
mm/page_isolation: fix tracepoint to mirror check function behavior
mm/rmap: batched invalidations should use existing api
x86/mm: TLB_REMOTE_SEND_IPI should count pages
mm: fix invalid node in alloc_migrate_target()
include/linux/huge_mm.h: return NULL instead of false for pmd_trans_huge_lock()
mm, kasan: fix compilation for CONFIG_SLAB
MAINTAINERS: orangefs mailing list is subscribers-only
net: mvneta: fix changing MTU when using per-cpu processing
...
Diffstat (limited to 'drivers')
93 files changed, 981 insertions, 801 deletions
diff --git a/drivers/acpi/acpi_processor.c b/drivers/acpi/acpi_processor.c index b5e54f2da53d..0d92d0f915e9 100644 --- a/drivers/acpi/acpi_processor.c +++ b/drivers/acpi/acpi_processor.c @@ -491,6 +491,58 @@ static void acpi_processor_remove(struct acpi_device *device) } #endif /* CONFIG_ACPI_HOTPLUG_CPU */ +#ifdef CONFIG_X86 +static bool acpi_hwp_native_thermal_lvt_set; +static acpi_status __init acpi_hwp_native_thermal_lvt_osc(acpi_handle handle, + u32 lvl, + void *context, + void **rv) +{ + u8 sb_uuid_str[] = "4077A616-290C-47BE-9EBD-D87058713953"; + u32 capbuf[2]; + struct acpi_osc_context osc_context = { + .uuid_str = sb_uuid_str, + .rev = 1, + .cap.length = 8, + .cap.pointer = capbuf, + }; + + if (acpi_hwp_native_thermal_lvt_set) + return AE_CTRL_TERMINATE; + + capbuf[0] = 0x0000; + capbuf[1] = 0x1000; /* set bit 12 */ + + if (ACPI_SUCCESS(acpi_run_osc(handle, &osc_context))) { + if (osc_context.ret.pointer && osc_context.ret.length > 1) { + u32 *capbuf_ret = osc_context.ret.pointer; + + if (capbuf_ret[1] & 0x1000) { + acpi_handle_info(handle, + "_OSC native thermal LVT Acked\n"); + acpi_hwp_native_thermal_lvt_set = true; + } + } + kfree(osc_context.ret.pointer); + } + + return AE_OK; +} + +void __init acpi_early_processor_osc(void) +{ + if (boot_cpu_has(X86_FEATURE_HWP)) { + acpi_walk_namespace(ACPI_TYPE_PROCESSOR, ACPI_ROOT_OBJECT, + ACPI_UINT32_MAX, + acpi_hwp_native_thermal_lvt_osc, + NULL, NULL, NULL); + acpi_get_devices(ACPI_PROCESSOR_DEVICE_HID, + acpi_hwp_native_thermal_lvt_osc, + NULL, NULL); + } +} +#endif + /* * The following ACPI IDs are known to be suitable for representing as * processor devices. diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 0e8567846f1a..c068c829b453 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -1019,6 +1019,9 @@ static int __init acpi_bus_init(void) goto error1; } + /* Set capability bits for _OSC under processor scope */ + acpi_early_processor_osc(); + /* * _OSC method may exist in module level code, * so it must be run after ACPI_FULL_INITIALIZATION diff --git a/drivers/acpi/internal.h b/drivers/acpi/internal.h index a37508ef66c1..7c188472d9c2 100644 --- a/drivers/acpi/internal.h +++ b/drivers/acpi/internal.h @@ -145,6 +145,12 @@ void acpi_early_processor_set_pdc(void); static inline void acpi_early_processor_set_pdc(void) {} #endif +#ifdef CONFIG_X86 +void acpi_early_processor_osc(void); +#else +static inline void acpi_early_processor_osc(void) {} +#endif + /* -------------------------------------------------------------------------- Embedded Controller -------------------------------------------------------------------------- */ diff --git a/drivers/clk/mediatek/reset.c b/drivers/clk/mediatek/reset.c index 9e9fe4b19ac4..309049d41f1b 100644 --- a/drivers/clk/mediatek/reset.c +++ b/drivers/clk/mediatek/reset.c @@ -57,7 +57,7 @@ static int mtk_reset(struct reset_controller_dev *rcdev, return mtk_reset_deassert(rcdev, id); } -static struct reset_control_ops mtk_reset_ops = { +static const struct reset_control_ops mtk_reset_ops = { .assert = mtk_reset_assert, .deassert = mtk_reset_deassert, .reset = mtk_reset, diff --git a/drivers/clk/mmp/reset.c b/drivers/clk/mmp/reset.c index b54da1fe73f0..b4e4d6aa2631 100644 --- a/drivers/clk/mmp/reset.c +++ b/drivers/clk/mmp/reset.c @@ -74,7 +74,7 @@ static int mmp_clk_reset_deassert(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops mmp_clk_reset_ops = { +static const struct reset_control_ops mmp_clk_reset_ops = { .assert = mmp_clk_reset_assert, .deassert = mmp_clk_reset_deassert, }; diff --git a/drivers/clk/qcom/gcc-ipq4019.c b/drivers/clk/qcom/gcc-ipq4019.c index 5428efb9fbf5..3cd1af0af0d9 100644 --- a/drivers/clk/qcom/gcc-ipq4019.c +++ b/drivers/clk/qcom/gcc-ipq4019.c @@ -129,20 +129,10 @@ static const char * const gcc_xo_ddr_500_200[] = { }; #define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) } -#define P_XO 0 -#define FE_PLL_200 1 -#define FE_PLL_500 2 -#define DDRC_PLL_666 3 - -#define DDRC_PLL_666_SDCC 1 -#define FE_PLL_125_DLY 1 - -#define FE_PLL_WCSS2G 1 -#define FE_PLL_WCSS5G 1 static const struct freq_tbl ftbl_gcc_audio_pwm_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(200000000, FE_PLL_200, 1, 0, 0), + F(200000000, P_FEPLL200, 1, 0, 0), { } }; @@ -334,15 +324,15 @@ static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = { }; static const struct freq_tbl ftbl_gcc_blsp1_uart1_2_apps_clk[] = { - F(1843200, FE_PLL_200, 1, 144, 15625), - F(3686400, FE_PLL_200, 1, 288, 15625), - F(7372800, FE_PLL_200, 1, 576, 15625), - F(14745600, FE_PLL_200, 1, 1152, 15625), - F(16000000, FE_PLL_200, 1, 2, 25), + F(1843200, P_FEPLL200, 1, 144, 15625), + F(3686400, P_FEPLL200, 1, 288, 15625), + F(7372800, P_FEPLL200, 1, 576, 15625), + F(14745600, P_FEPLL200, 1, 1152, 15625), + F(16000000, P_FEPLL200, 1, 2, 25), F(24000000, P_XO, 1, 1, 2), - F(32000000, FE_PLL_200, 1, 4, 25), - F(40000000, FE_PLL_200, 1, 1, 5), - F(46400000, FE_PLL_200, 1, 29, 125), + F(32000000, P_FEPLL200, 1, 4, 25), + F(40000000, P_FEPLL200, 1, 1, 5), + F(46400000, P_FEPLL200, 1, 29, 125), F(48000000, P_XO, 1, 0, 0), { } }; @@ -410,9 +400,9 @@ static struct clk_branch gcc_blsp1_uart2_apps_clk = { }; static const struct freq_tbl ftbl_gcc_gp_clk[] = { - F(1250000, FE_PLL_200, 1, 16, 0), - F(2500000, FE_PLL_200, 1, 8, 0), - F(5000000, FE_PLL_200, 1, 4, 0), + F(1250000, P_FEPLL200, 1, 16, 0), + F(2500000, P_FEPLL200, 1, 8, 0), + F(5000000, P_FEPLL200, 1, 4, 0), { } }; @@ -512,11 +502,11 @@ static struct clk_branch gcc_gp3_clk = { static const struct freq_tbl ftbl_gcc_sdcc1_apps_clk[] = { F(144000, P_XO, 1, 3, 240), F(400000, P_XO, 1, 1, 0), - F(20000000, FE_PLL_500, 1, 1, 25), - F(25000000, FE_PLL_500, 1, 1, 20), - F(50000000, FE_PLL_500, 1, 1, 10), - F(100000000, FE_PLL_500, 1, 1, 5), - F(193000000, DDRC_PLL_666_SDCC, 1, 0, 0), + F(20000000, P_FEPLL500, 1, 1, 25), + F(25000000, P_FEPLL500, 1, 1, 20), + F(50000000, P_FEPLL500, 1, 1, 10), + F(100000000, P_FEPLL500, 1, 1, 5), + F(193000000, P_DDRPLL, 1, 0, 0), { } }; @@ -536,9 +526,9 @@ static struct clk_rcg2 sdcc1_apps_clk_src = { static const struct freq_tbl ftbl_gcc_apps_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(200000000, FE_PLL_200, 1, 0, 0), - F(500000000, FE_PLL_500, 1, 0, 0), - F(626000000, DDRC_PLL_666, 1, 0, 0), + F(200000000, P_FEPLL200, 1, 0, 0), + F(500000000, P_FEPLL500, 1, 0, 0), + F(626000000, P_DDRPLLAPSS, 1, 0, 0), { } }; @@ -557,7 +547,7 @@ static struct clk_rcg2 apps_clk_src = { static const struct freq_tbl ftbl_gcc_apps_ahb_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(100000000, FE_PLL_200, 2, 0, 0), + F(100000000, P_FEPLL200, 2, 0, 0), { } }; @@ -940,7 +930,7 @@ static struct clk_branch gcc_usb2_mock_utmi_clk = { }; static const struct freq_tbl ftbl_gcc_usb30_mock_utmi_clk[] = { - F(2000000, FE_PLL_200, 10, 0, 0), + F(2000000, P_FEPLL200, 10, 0, 0), { } }; @@ -1007,7 +997,7 @@ static struct clk_branch gcc_usb3_mock_utmi_clk = { }; static const struct freq_tbl ftbl_gcc_fephy_dly_clk[] = { - F(125000000, FE_PLL_125_DLY, 1, 0, 0), + F(125000000, P_FEPLL125DLY, 1, 0, 0), { } }; @@ -1027,7 +1017,7 @@ static struct clk_rcg2 fephy_125m_dly_clk_src = { static const struct freq_tbl ftbl_gcc_wcss2g_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(250000000, FE_PLL_WCSS2G, 1, 0, 0), + F(250000000, P_FEPLLWCSS2G, 1, 0, 0), { } }; @@ -1097,7 +1087,7 @@ static struct clk_branch gcc_wcss2g_rtc_clk = { static const struct freq_tbl ftbl_gcc_wcss5g_clk[] = { F(48000000, P_XO, 1, 0, 0), - F(250000000, FE_PLL_WCSS5G, 1, 0, 0), + F(250000000, P_FEPLLWCSS5G, 1, 0, 0), { } }; @@ -1325,6 +1315,16 @@ MODULE_DEVICE_TABLE(of, gcc_ipq4019_match_table); static int gcc_ipq4019_probe(struct platform_device *pdev) { + struct device *dev = &pdev->dev; + + clk_register_fixed_rate(dev, "fepll125", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepll125dly", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepllwcss2g", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepllwcss5g", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepll200", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "fepll500", "xo", 0, 200000000); + clk_register_fixed_rate(dev, "ddrpllapss", "xo", 0, 666000000); + return qcom_cc_probe(pdev, &gcc_ipq4019_desc); } diff --git a/drivers/clk/qcom/reset.c b/drivers/clk/qcom/reset.c index 6c977d3a8590..0324d8daab9b 100644 --- a/drivers/clk/qcom/reset.c +++ b/drivers/clk/qcom/reset.c @@ -55,7 +55,7 @@ qcom_reset_deassert(struct reset_controller_dev *rcdev, unsigned long id) return regmap_update_bits(rst->regmap, map->reg, mask, 0); } -struct reset_control_ops qcom_reset_ops = { +const struct reset_control_ops qcom_reset_ops = { .reset = qcom_reset, .assert = qcom_reset_assert, .deassert = qcom_reset_deassert, diff --git a/drivers/clk/qcom/reset.h b/drivers/clk/qcom/reset.h index 0e11e2130f97..cda877927d43 100644 --- a/drivers/clk/qcom/reset.h +++ b/drivers/clk/qcom/reset.h @@ -32,6 +32,6 @@ struct qcom_reset_controller { #define to_qcom_reset_controller(r) \ container_of(r, struct qcom_reset_controller, rcdev); -extern struct reset_control_ops qcom_reset_ops; +extern const struct reset_control_ops qcom_reset_ops; #endif diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c index 552f7bb15bc5..21218987bbc3 100644 --- a/drivers/clk/rockchip/softrst.c +++ b/drivers/clk/rockchip/softrst.c @@ -81,7 +81,7 @@ static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops rockchip_softrst_ops = { +static const struct reset_control_ops rockchip_softrst_ops = { .assert = rockchip_softrst_assert, .deassert = rockchip_softrst_deassert, }; diff --git a/drivers/clk/sirf/clk-atlas7.c b/drivers/clk/sirf/clk-atlas7.c index 957aae63e7cc..d0c6c9a2d06a 100644 --- a/drivers/clk/sirf/clk-atlas7.c +++ b/drivers/clk/sirf/clk-atlas7.c @@ -1423,7 +1423,7 @@ static int atlas7_reset_module(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops atlas7_rst_ops = { +static const struct reset_control_ops atlas7_rst_ops = { .reset = atlas7_reset_module, }; diff --git a/drivers/clk/sunxi/clk-a10-ve.c b/drivers/clk/sunxi/clk-a10-ve.c index 044c1717b762..d9ea22ec4e25 100644 --- a/drivers/clk/sunxi/clk-a10-ve.c +++ b/drivers/clk/sunxi/clk-a10-ve.c @@ -85,7 +85,7 @@ static int sunxi_ve_of_xlate(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops sunxi_ve_reset_ops = { +static const struct reset_control_ops sunxi_ve_reset_ops = { .assert = sunxi_ve_reset_assert, .deassert = sunxi_ve_reset_deassert, }; diff --git a/drivers/clk/sunxi/clk-sun9i-mmc.c b/drivers/clk/sunxi/clk-sun9i-mmc.c index a9b176139aca..028dd832a39f 100644 --- a/drivers/clk/sunxi/clk-sun9i-mmc.c +++ b/drivers/clk/sunxi/clk-sun9i-mmc.c @@ -83,7 +83,7 @@ static int sun9i_mmc_reset_deassert(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops sun9i_mmc_reset_ops = { +static const struct reset_control_ops sun9i_mmc_reset_ops = { .assert = sun9i_mmc_reset_assert, .deassert = sun9i_mmc_reset_deassert, }; diff --git a/drivers/clk/sunxi/clk-usb.c b/drivers/clk/sunxi/clk-usb.c index 5432b1c198a4..fe0c3d169377 100644 --- a/drivers/clk/sunxi/clk-usb.c +++ b/drivers/clk/sunxi/clk-usb.c @@ -76,7 +76,7 @@ static int sunxi_usb_reset_deassert(struct reset_controller_dev *rcdev, return 0; } -static struct reset_control_ops sunxi_usb_reset_ops = { +static const struct reset_control_ops sunxi_usb_reset_ops = { .assert = sunxi_usb_reset_assert, .deassert = sunxi_usb_reset_deassert, }; diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index 2a3a4fe803d6..f60fe2e344ca 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c @@ -271,7 +271,7 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, } } -static struct reset_control_ops rst_ops = { +static const struct reset_control_ops rst_ops = { .assert = tegra_clk_rst_assert, .deassert = tegra_clk_rst_deassert, }; diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c index a68e199d579d..c5c9599a3a71 100644 --- a/drivers/gpio/gpio-menz127.c +++ b/drivers/gpio/gpio-menz127.c @@ -37,7 +37,6 @@ struct men_z127_gpio { void __iomem *reg_base; struct mcb_device *mdev; struct resource *mem; - spinlock_t lock; }; static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, @@ -69,7 +68,7 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, debounce /= 50; } - spin_lock(&priv->lock); + spin_lock(&gc->bgpio_lock); db_en = readl(priv->reg_base + MEN_Z127_DBER); @@ -84,7 +83,7 @@ static int men_z127_debounce(struct gpio_chip *gc, unsigned gpio, writel(db_en, priv->reg_base + MEN_Z127_DBER); writel(db_cnt, priv->reg_base + GPIO_TO_DBCNT_REG(gpio)); - spin_unlock(&priv->lock); + spin_unlock(&gc->bgpio_lock); return 0; } @@ -97,7 +96,7 @@ static int men_z127_request(struct gpio_chip *gc, unsigned gpio_pin) if (gpio_pin >= gc->ngpio) return -EINVAL; - spin_lock(&priv->lock); + spin_lock(&gc->bgpio_lock); od_en = readl(priv->reg_base + MEN_Z127_ODER); if (gpiochip_line_is_open_drain(gc, gpio_pin)) @@ -106,7 +105,7 @@ static int men_z127_request(struct gpio_chip *gc, unsigned gpio_pin) od_en &= ~BIT(gpio_pin); writel(od_en, priv->reg_base + MEN_Z127_ODER); - spin_unlock(&priv->lock); + spin_unlock(&gc->bgpio_lock); return 0; } diff --git a/drivers/gpio/gpio-xgene.c b/drivers/gpio/gpio-xgene.c index c0aa387664bf..0dc916191689 100644 --- a/drivers/gpio/gpio-xgene.c +++ b/drivers/gpio/gpio-xgene.c @@ -173,6 +173,11 @@ static int xgene_gpio_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + err = -EINVAL; + goto err; + } + gpio->base = devm_ioremap_nocache(&pdev->dev, res->start, resource_size(res)); if (!gpio->base) { diff --git a/drivers/gpu/drm/amd/acp/Kconfig b/drivers/gpu/drm/amd/acp/Kconfig index 0f734ee05274..ca77ec10147c 100644 --- a/drivers/gpu/drm/amd/acp/Kconfig +++ b/drivers/gpu/drm/amd/acp/Kconfig @@ -1,10 +1,14 @@ -menu "ACP Configuration" +menu "ACP (Audio CoProcessor) Configuration" config DRM_AMD_ACP - bool "Enable ACP IP support" + bool "Enable AMD Audio CoProcessor IP support" select MFD_CORE select PM_GENERIC_DOMAINS if PM help Choose this option to enable ACP IP support for AMD SOCs. + This adds the ACP (Audio CoProcessor) IP driver and wires + it up into the amdgpu driver. The ACP block provides the DMA + engine for the i2s-based ALSA driver. It is required for audio + on APUs which utilize an i2s codec. endmenu diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index 151a2d42c639..56d1458393cc 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -608,6 +608,10 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) if ((offset + size) <= adev->mc.visible_vram_size) return 0; + /* Can't move a pinned BO to visible VRAM */ + if (abo->pin_count > 0) + return -EINVAL; + /* hurrah the memory is not visible ! */ amdgpu_ttm_placement_from_domain(abo, AMDGPU_GEM_DOMAIN_VRAM); lpfn = adev->mc.visible_vram_size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index ab34190859a8..f1a55d1888cb 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -384,9 +384,15 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { struct amdgpu_device *adev; + struct amdgpu_bo *abo; struct ttm_mem_reg *old_mem = &bo->mem; int r; + /* Can't move a pinned BO */ + abo = container_of(bo, struct amdgpu_bo, tbo); + if (WARN_ON_ONCE(abo->pin_count > 0)) + return -EINVAL; + adev = amdgpu_get_adev(bo->bdev); if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { amdgpu_move_null(bo, new_mem); diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 7d58f594cffe..df64ed1c0139 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -179,7 +179,7 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, { struct drm_dp_aux_msg msg; unsigned int retry; - int err; + int err = 0; memset(&msg, 0, sizeof(msg)); msg.address = offset; @@ -187,6 +187,8 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, msg.buffer = buffer; msg.size = size; + mutex_lock(&aux->hw_mutex); + /* * The specification doesn't give any recommendation on how often to * retry native transactions. We used to retry 7 times like for @@ -195,25 +197,24 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, */ for (retry = 0; retry < 32; retry++) { - mutex_lock(&aux->hw_mutex); err = aux->transfer(aux, &msg); - mutex_unlock(&aux->hw_mutex); if (err < 0) { if (err == -EBUSY) continue; - return err; + goto unlock; } switch (msg.reply & DP_AUX_NATIVE_REPLY_MASK) { case DP_AUX_NATIVE_REPLY_ACK: if (err < size) - return -EPROTO; - return err; + err = -EPROTO; + goto unlock; case DP_AUX_NATIVE_REPLY_NACK: - return -EIO; + err = -EIO; + goto unlock; case DP_AUX_NATIVE_REPLY_DEFER: usleep_range(AUX_RETRY_INTERVAL, AUX_RETRY_INTERVAL + 100); @@ -222,7 +223,11 @@ static int drm_dp_dpcd_access(struct drm_dp_aux *aux, u8 request, } DRM_DEBUG_KMS("too many retries, giving up\n"); - return -EIO; + err = -EIO; + +unlock: + mutex_unlock(&aux->hw_mutex); + return err; } /** @@ -544,9 +549,7 @@ static int drm_dp_i2c_do_msg(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) int max_retries = max(7, drm_dp_i2c_retry_count(msg, dp_aux_i2c_speed_khz)); for (retry = 0, defer_i2c = 0; retry < (max_retries + defer_i2c); retry++) { - mutex_lock(&aux->hw_mutex); ret = aux->transfer(aux, msg); - mutex_unlock(&aux->hw_mutex); if (ret < 0) { if (ret == -EBUSY) continue; @@ -685,6 +688,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, memset(&msg, 0, sizeof(msg)); + mutex_lock(&aux->hw_mutex); + for (i = 0; i < num; i++) { msg.address = msgs[i].addr; drm_dp_i2c_msg_set_request(&msg, &msgs[i]); @@ -739,6 +744,8 @@ static int drm_dp_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs, msg.size = 0; (void)drm_dp_i2c_do_msg(aux, &msg); + mutex_unlock(&aux->hw_mutex); + return err; } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index b04a64664673..65428cf233ce 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -196,7 +196,7 @@ void __exit msm_hdmi_phy_driver_unregister(void); int msm_hdmi_pll_8960_init(struct platform_device *pdev); int msm_hdmi_pll_8996_init(struct platform_device *pdev); #else -static inline int msm_hdmi_pll_8960_init(struct platform_device *pdev); +static inline int msm_hdmi_pll_8960_init(struct platform_device *pdev) { return -ENODEV; } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index d52910e2c26c..c03b96709179 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -467,9 +467,6 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file) struct msm_file_private *ctx = file->driver_priv; struct msm_kms *kms = priv->kms; - if (kms) - kms->funcs->preclose(kms, file); - mutex_lock(&dev->struct_mutex); if (ctx == priv->lastctx) priv->lastctx = NULL; diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h index 9bcabaada179..e32222c3d44f 100644 --- a/drivers/gpu/drm/msm/msm_kms.h +++ b/drivers/gpu/drm/msm/msm_kms.h @@ -55,7 +55,6 @@ struct msm_kms_funcs { struct drm_encoder *slave_encoder, bool is_cmd_mode); /* cleanup: */ - void (*preclose)(struct msm_kms *kms, struct drm_file *file); void (*destroy)(struct msm_kms *kms); }; diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index dd46c38676db..2d901bf28a94 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -799,6 +799,10 @@ int radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo) if ((offset + size) <= rdev->mc.visible_vram_size) return 0; + /* Can't move a pinned BO to visible VRAM */ + if (rbo->pin_count > 0) + return -EINVAL; + /* hurrah the memory is not visible ! */ radeon_ttm_placement_from_domain(rbo, RADEON_GEM_DOMAIN_VRAM); lpfn = rdev->mc.visible_vram_size >> PAGE_SHIFT; diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 6d8c32377c6f..c008312e1bcd 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -397,9 +397,15 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem) { struct radeon_device *rdev; + struct radeon_bo *rbo; struct ttm_mem_reg *old_mem = &bo->mem; int r; + /* Can't move a pinned BO */ + rbo = container_of(bo, struct radeon_bo, tbo); + if (WARN_ON_ONCE(rbo->pin_count > 0)) + return -EINVAL; + rdev = radeon_get_rdev(bo->bdev); if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) { radeon_move_null(bo, new_mem); diff --git a/drivers/gpu/drm/radeon/si_dpm.c b/drivers/gpu/drm/radeon/si_dpm.c index cb75ab72098a..af4df81c4e0c 100644 --- a/drivers/gpu/drm/radeon/si_dpm.c +++ b/drivers/gpu/drm/radeon/si_dpm.c @@ -2926,9 +2926,11 @@ static struct si_dpm_quirk si_dpm_quirk_list[] = { /* PITCAIRN - https://bugs.freedesktop.org/show_bug.cgi?id=76490 */ { PCI_VENDOR_ID_ATI, 0x6810, 0x1462, 0x3036, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0xe271, 0, 120000 }, + { PCI_VENDOR_ID_ATI, 0x6811, 0x174b, 0x2015, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6810, 0x174b, 0xe271, 85000, 90000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x1462, 0x2015, 0, 120000 }, { PCI_VENDOR_ID_ATI, 0x6811, 0x1043, 0x2015, 0, 120000 }, + { PCI_VENDOR_ID_ATI, 0x6811, 0x148c, 0x2015, 0, 120000 }, { 0, 0, 0, 0 }, }; @@ -3008,6 +3010,10 @@ static void si_apply_state_adjust_rules(struct radeon_device *rdev, } ++p; } + /* limit mclk on all R7 370 parts for stability */ + if (rdev->pdev->device == 0x6811 && + rdev->pdev->revision == 0x81) + max_mclk = 120000; if (rps->vce_active) { rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index 3d3cf2f8891e..d5cfef75fc80 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -271,8 +271,6 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, if (!iores) return -ENXIO; - platform_set_drvdata(pdev, hdmi); - encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node); /* * If we failed to find the CRTC(s) which this encoder is @@ -293,7 +291,16 @@ static int dw_hdmi_rockchip_bind(struct device *dev, struct device *master, drm_encoder_init(drm, encoder, &dw_hdmi_rockchip_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); - return dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); + ret = dw_hdmi_bind(dev, master, data, encoder, iores, irq, plat_data); + + /* + * If dw_hdmi_bind() fails we'll never call dw_hdmi_unbind(), + * which would have called the encoder cleanup. Do it manually. + */ + if (ret) + drm_encoder_cleanup(encoder); + + return ret; } static void dw_hdmi_rockchip_unbind(struct device *dev, struct device *master, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 896da09e49ee..f556a8f4fde6 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -251,6 +251,27 @@ static int rockchip_drm_unload(struct drm_device *drm_dev) return 0; } +static void rockchip_drm_crtc_cancel_pending_vblank(struct drm_crtc *crtc, + struct drm_file *file_priv) +{ + struct rockchip_drm_private *priv = crtc->dev->dev_private; + int pipe = drm_crtc_index(crtc); + + if (pipe < ROCKCHIP_MAX_CRTC && + priv->crtc_funcs[pipe] && + priv->crtc_funcs[pipe]->cancel_pending_vblank) + priv->crtc_funcs[pipe]->cancel_pending_vblank(crtc, file_priv); +} + +static void rockchip_drm_preclose(struct drm_device *dev, + struct drm_file *file_priv) +{ + struct drm_crtc *crtc; + + list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) + rockchip_drm_crtc_cancel_pending_vblank(crtc, file_priv); +} + void rockchip_drm_lastclose(struct drm_device *dev) { struct rockchip_drm_private *priv = dev->dev_private; @@ -281,6 +302,7 @@ static struct drm_driver rockchip_drm_driver = { DRIVER_PRIME | DRIVER_ATOMIC, .load = rockchip_drm_load, .unload = rockchip_drm_unload, + .preclose = rockchip_drm_preclose, .lastclose = rockchip_drm_lastclose, .get_vblank_counter = drm_vblank_no_hw_counter, .enable_vblank = rockchip_drm_crtc_enable_vblank, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index 3529f692edb8..00d17d71aa4c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -40,6 +40,7 @@ struct rockchip_crtc_funcs { int (*enable_vblank)(struct drm_crtc *crtc); void (*disable_vblank)(struct drm_crtc *crtc); void (*wait_for_update)(struct drm_crtc *crtc); + void (*cancel_pending_vblank)(struct drm_crtc *crtc, struct drm_file *file_priv); }; struct rockchip_atomic_commit { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index fd370548d7d7..a619f120f801 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -499,10 +499,25 @@ err_disable_hclk: static void vop_crtc_disable(struct drm_crtc *crtc) { struct vop *vop = to_vop(crtc); + int i; if (!vop->is_enabled) return; + /* + * We need to make sure that all windows are disabled before we + * disable that crtc. Otherwise we might try to scan from a destroyed + * buffer later. + */ + for (i = 0; i < vop->data->win_size; i++) { + struct vop_win *vop_win = &vop->win[i]; + const struct vop_win_data *win = vop_win->data; + + spin_lock(&vop->reg_lock); + VOP_WIN_SET(vop, win, enable, 0); + spin_unlock(&vop->reg_lock); + } + drm_crtc_vblank_off(crtc); /* @@ -549,6 +564,7 @@ static int vop_plane_atomic_check(struct drm_plane *plane, struct drm_plane_state *state) { struct drm_crtc *crtc = state->crtc; + struct drm_crtc_state *crtc_state; struct drm_framebuffer *fb = state->fb; struct vop_win *vop_win = to_vop_win(plane); struct vop_plane_state *vop_plane_state = to_vop_plane_state(state); @@ -563,12 +579,13 @@ static int vop_plane_atomic_check(struct drm_plane *plane, int max_scale = win->phy->scl ? FRAC_16_16(8, 1) : DRM_PLANE_HELPER_NO_SCALING; - crtc = crtc ? crtc : plane->state->crtc; - /* - * Both crtc or plane->state->crtc can be null. - */ if (!crtc || !fb) goto out_disable; + + crtc_state = drm_atomic_get_existing_crtc_state(state->state, crtc); + if (WARN_ON(!crtc_state)) + return -EINVAL; + src->x1 = state->src_x; src->y1 = state->src_y; src->x2 = state->src_x + state->src_w; @@ -580,8 +597,8 @@ static int vop_plane_atomic_check(struct drm_plane *plane, clip.x1 = 0; clip.y1 = 0; - clip.x2 = crtc->mode.hdisplay; - clip.y2 = crtc->mode.vdisplay; + clip.x2 = crtc_state->adjusted_mode.hdisplay; + clip.y2 = crtc_state->adjusted_mode.vdisplay; ret = drm_plane_helper_check_update(plane, crtc, state->fb, src, dest, &clip, @@ -873,10 +890,30 @@ static void vop_crtc_wait_for_update(struct drm_crtc *crtc) WARN_ON(!wait_for_completion_timeout(&vop->wait_update_complete, 100)); } +static void vop_crtc_cancel_pending_vblank(struct drm_crtc *crtc, + struct drm_file *file_priv) +{ + struct drm_device *drm = crtc->dev; + struct vop *vop = to_vop(crtc); + struct drm_pending_vblank_event *e; + unsigned long flags; + + spin_lock_irqsave(&drm->event_lock, flags); + e = vop->event; + if (e && e->base.file_priv == file_priv) { + vop->event = NULL; + + e->base.destroy(&e->base); + file_priv->event_space += sizeof(e->event); + } + spin_unlock_irqrestore(&drm->event_lock, flags); +} + static const struct rockchip_crtc_funcs private_crtc_funcs = { .enable_vblank = vop_crtc_enable_vblank, .disable_vblank = vop_crtc_disable_vblank, .wait_for_update = vop_crtc_wait_for_update, + .cancel_pending_vblank = vop_crtc_cancel_pending_vblank, }; static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, @@ -885,9 +922,6 @@ static bool vop_crtc_mode_fixup(struct drm_crtc *crtc, { struct vop *vop = to_vop(crtc); - if (adjusted_mode->htotal == 0 || adjusted_mode->vtotal == 0) - return false; - adjusted_mode->clock = clk_round_rate(vop->dclk, mode->clock * 1000) / 1000; @@ -1108,7 +1142,7 @@ static int vop_create_crtc(struct vop *vop) const struct vop_data *vop_data = vop->data; struct device *dev = vop->dev; struct drm_device *drm_dev = vop->drm_dev; - struct drm_plane *primary = NULL, *cursor = NULL, *plane; + struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp; struct drm_crtc *crtc = &vop->crtc; struct device_node *port; int ret; @@ -1148,7 +1182,7 @@ static int vop_create_crtc(struct vop *vop) ret = drm_crtc_init_with_planes(drm_dev, crtc, primary, cursor, &vop_crtc_funcs, NULL); if (ret) - return ret; + goto err_cleanup_planes; drm_crtc_helper_add(crtc, &vop_crtc_helper_funcs); @@ -1181,6 +1215,7 @@ static int vop_create_crtc(struct vop *vop) if (!port) { DRM_ERROR("no port node found in %s\n", dev->of_node->full_name); + ret = -ENOENT; goto err_cleanup_crtc; } @@ -1194,7 +1229,8 @@ static int vop_create_crtc(struct vop *vop) err_cleanup_crtc: drm_crtc_cleanup(crtc); err_cleanup_planes: - list_for_each_entry(plane, &drm_dev->mode_config.plane_list, head) + list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, + head) drm_plane_cleanup(plane); return ret; } @@ -1202,9 +1238,28 @@ err_cleanup_planes: static void vop_destroy_crtc(struct vop *vop) { struct drm_crtc *crtc = &vop->crtc; + struct drm_device *drm_dev = vop->drm_dev; + struct drm_plane *plane, *tmp; rockchip_unregister_crtc_funcs(crtc); of_node_put(crtc->port); + + /* + * We need to cleanup the planes now. Why? + * + * The planes are "&vop->win[i].base". That means the memory is + * all part of the big "struct vop" chunk of memory. That memory + * was devm allocated and associated with this component. We need to + * free it ourselves before vop_unbind() finishes. + */ + list_for_each_entry_safe(plane, tmp, &drm_dev->mode_config.plane_list, + head) + vop_plane_destroy(plane); + + /* + * Destroy CRTC after vop_plane_destroy() since vop_disable_plane() + * references the CRTC. + */ drm_crtc_cleanup(crtc); } diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index 33239a2b264a..fd1eb9d03f0b 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -536,7 +536,7 @@ static int udlfb_create(struct drm_fb_helper *helper, out_destroy_fbi: drm_fb_helper_release_fbi(helper); out_gfree: - drm_gem_object_unreference(&ufbdev->ufb.obj->base); + drm_gem_object_unreference_unlocked(&ufbdev->ufb.obj->base); out: return ret; } diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index 2a0a784ab6ee..d7528e0d8442 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -52,7 +52,7 @@ udl_gem_create(struct drm_file *file, return ret; } - drm_gem_object_unreference(&obj->base); + drm_gem_object_unreference_unlocked(&obj->base); *handle_p = handle; return 0; } diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c index 36544c4f653c..303d0c9df907 100644 --- a/drivers/hwmon/max1111.c +++ b/drivers/hwmon/max1111.c @@ -85,6 +85,9 @@ static struct max1111_data *the_max1111; int max1111_read_channel(int channel) { + if (!the_max1111 || !the_max1111->spi) + return -ENODEV; + return max1111_read(&the_max1111->spi->dev, channel); } EXPORT_SYMBOL(max1111_read_channel); @@ -258,6 +261,9 @@ static int max1111_remove(struct spi_device *spi) { struct max1111_data *data = spi_get_drvdata(spi); +#ifdef CONFIG_SHARPSL_PM + the_max1111 = NULL; +#endif hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group); sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index 9f0a48e39b8a..80e933b296f6 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -451,7 +451,7 @@ err_free: return ret; } -static const struct ide_port_info icside_v6_port_info __initconst = { +static const struct ide_port_info icside_v6_port_info = { .init_dma = icside_dma_off_init, .port_ops = &icside_v6_no_dma_port_ops, .host_flags = IDE_HFLAG_SERIALIZE | IDE_HFLAG_MMIO, diff --git a/drivers/ide/palm_bk3710.c b/drivers/ide/palm_bk3710.c index 8012e43bf8f6..46427ea01753 100644 --- a/drivers/ide/palm_bk3710.c +++ b/drivers/ide/palm_bk3710.c @@ -325,6 +325,8 @@ static int __init palm_bk3710_probe(struct platform_device *pdev) clk_enable(clk); rate = clk_get_rate(clk); + if (!rate) + return -EINVAL; /* NOTE: round *down* to meet minimum timings; we count in clocks */ ideclk_period = 1000000000UL / rate; diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index 60b30d338a81..411e4464ca23 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c @@ -63,7 +63,6 @@ isert_rdma_accept(struct isert_conn *isert_conn); struct rdma_cm_id *isert_setup_id(struct isert_np *isert_np); static void isert_release_work(struct work_struct *work); -static void isert_wait4flush(struct isert_conn *isert_conn); static void isert_recv_done(struct ib_cq *cq, struct ib_wc *wc); static void isert_send_done(struct ib_cq *cq, struct ib_wc *wc); static void isert_login_recv_done(struct ib_cq *cq, struct ib_wc *wc); @@ -141,7 +140,7 @@ isert_create_qp(struct isert_conn *isert_conn, attr.qp_context = isert_conn; attr.send_cq = comp->cq; attr.recv_cq = comp->cq; - attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS; + attr.cap.max_send_wr = ISERT_QP_MAX_REQ_DTOS + 1; attr.cap.max_recv_wr = ISERT_QP_MAX_RECV_DTOS + 1; attr.cap.max_send_sge = device->ib_device->attrs.max_sge; isert_conn->max_sge = min(device->ib_device->attrs.max_sge, @@ -887,7 +886,7 @@ isert_disconnected_handler(struct rdma_cm_id *cma_id, break; case ISER_CONN_UP: isert_conn_terminate(isert_conn); - isert_wait4flush(isert_conn); + ib_drain_qp(isert_conn->qp); isert_handle_unbound_conn(isert_conn); break; case ISER_CONN_BOUND: @@ -3213,36 +3212,6 @@ isert_wait4cmds(struct iscsi_conn *conn) } } -static void -isert_beacon_done(struct ib_cq *cq, struct ib_wc *wc) -{ - struct isert_conn *isert_conn = wc->qp->qp_context; - - isert_print_wc(wc, "beacon"); - - isert_info("conn %p completing wait_comp_err\n", isert_conn); - complete(&isert_conn->wait_comp_err); -} - -static void -isert_wait4flush(struct isert_conn *isert_conn) -{ - struct ib_recv_wr *bad_wr; - static struct ib_cqe cqe = { .done = isert_beacon_done }; - - isert_info("conn %p\n", isert_conn); - - init_completion(&isert_conn->wait_comp_err); - isert_conn->beacon.wr_cqe = &cqe; - /* post an indication that all flush errors were consumed */ - if (ib_post_recv(isert_conn->qp, &isert_conn->beacon, &bad_wr)) { - isert_err("conn %p failed to post beacon", isert_conn); - return; - } - - wait_for_completion(&isert_conn->wait_comp_err); -} - /** * isert_put_unsol_pending_cmds() - Drop commands waiting for * unsolicitate dataout @@ -3288,7 +3257,7 @@ static void isert_wait_conn(struct iscsi_conn *conn) isert_conn_terminate(isert_conn); mutex_unlock(&isert_conn->mutex); - isert_wait4flush(isert_conn); + ib_drain_qp(isert_conn->qp); isert_put_unsol_pending_cmds(conn); isert_wait4cmds(conn); isert_wait4logout(isert_conn); @@ -3300,7 +3269,7 @@ static void isert_free_conn(struct iscsi_conn *conn) { struct isert_conn *isert_conn = conn->context; - isert_wait4flush(isert_conn); + ib_drain_qp(isert_conn->qp); isert_put_conn(isert_conn); } diff --git a/drivers/infiniband/ulp/isert/ib_isert.h b/drivers/infiniband/ulp/isert/ib_isert.h index 192788a4820c..147900cbb578 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.h +++ b/drivers/infiniband/ulp/isert/ib_isert.h @@ -209,14 +209,12 @@ struct isert_conn { struct ib_qp *qp; struct isert_device *device; struct mutex mutex; - struct completion wait_comp_err; struct kref kref; struct list_head fr_pool; int fr_pool_size; /* lock to protect fastreg pool */ spinlock_t pool_lock; struct work_struct release_work; - struct ib_recv_wr beacon; bool logout_posted; bool snd_w_inv; }; diff --git a/drivers/isdn/hisax/isac.c b/drivers/isdn/hisax/isac.c index 7fdf78f46433..df7e05ca8f9c 100644 --- a/drivers/isdn/hisax/isac.c +++ b/drivers/isdn/hisax/isac.c @@ -215,9 +215,11 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) if (count == 0) count = 32; isac_empty_fifo(cs, count); - if ((count = cs->rcvidx) > 0) { + count = cs->rcvidx; + if (count > 0) { cs->rcvidx = 0; - if (!(skb = alloc_skb(count, GFP_ATOMIC))) + skb = alloc_skb(count, GFP_ATOMIC); + if (!skb) printk(KERN_WARNING "HiSax: D receive out of memory\n"); else { memcpy(skb_put(skb, count), cs->rcvbuf, count); @@ -251,7 +253,8 @@ isac_interrupt(struct IsdnCardState *cs, u_char val) cs->tx_skb = NULL; } } - if ((cs->tx_skb = skb_dequeue(&cs->sq))) { + cs->tx_skb = skb_dequeue(&cs->sq); + if (cs->tx_skb) { cs->tx_cnt = 0; isac_fill_fifo(cs); } else @@ -313,7 +316,8 @@ afterXPR: #if ARCOFI_USE if (v1 & 0x08) { if (!cs->dc.isac.mon_rx) { - if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { + cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC); + if (!cs->dc.isac.mon_rx) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX out of memory!"); cs->dc.isac.mocr &= 0xf0; @@ -343,7 +347,8 @@ afterXPR: afterMONR0: if (v1 & 0x80) { if (!cs->dc.isac.mon_rx) { - if (!(cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC))) { + cs->dc.isac.mon_rx = kmalloc(MAX_MON_FRAME, GFP_ATOMIC); + if (!cs->dc.isac.mon_rx) { if (cs->debug & L1_DEB_WARN) debugl1(cs, "ISAC MON RX out of memory!"); cs->dc.isac.mocr &= 0x0f; diff --git a/drivers/media/v4l2-core/v4l2-mc.c b/drivers/media/v4l2-core/v4l2-mc.c index 2a7b79bc90fd..2228cd3a846e 100644 --- a/drivers/media/v4l2-core/v4l2-mc.c +++ b/drivers/media/v4l2-core/v4l2-mc.c @@ -34,7 +34,7 @@ int v4l2_mc_create_media_graph(struct media_device *mdev) { struct media_entity *entity; struct media_entity *if_vid = NULL, *if_aud = NULL; - struct media_entity *tuner = NULL, *decoder = NULL, *dtv_demod = NULL; + struct media_entity *tuner = NULL, *decoder = NULL; struct media_entity *io_v4l = NULL, *io_vbi = NULL, *io_swradio = NULL; bool is_webcam = false; u32 flags; diff --git a/drivers/net/dsa/mv88e6xxx.c b/drivers/net/dsa/mv88e6xxx.c index fa086e09d6b7..50454be86570 100644 --- a/drivers/net/dsa/mv88e6xxx.c +++ b/drivers/net/dsa/mv88e6xxx.c @@ -2264,6 +2264,57 @@ static void mv88e6xxx_bridge_work(struct work_struct *work) mutex_unlock(&ps->smi_mutex); } +static int _mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, + int reg, int val) +{ + int ret; + + ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); + if (ret < 0) + goto restore_page_0; + + ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val); +restore_page_0: + _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + + return ret; +} + +static int _mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, + int reg) +{ + int ret; + + ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); + if (ret < 0) + goto restore_page_0; + + ret = _mv88e6xxx_phy_read_indirect(ds, port, reg); +restore_page_0: + _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + + return ret; +} + +static int mv88e6xxx_power_on_serdes(struct dsa_switch *ds) +{ + int ret; + + ret = _mv88e6xxx_phy_page_read(ds, REG_FIBER_SERDES, PAGE_FIBER_SERDES, + MII_BMCR); + if (ret < 0) + return ret; + + if (ret & BMCR_PDOWN) { + ret &= ~BMCR_PDOWN; + ret = _mv88e6xxx_phy_page_write(ds, REG_FIBER_SERDES, + PAGE_FIBER_SERDES, MII_BMCR, + ret); + } + + return ret; +} + static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) { struct mv88e6xxx_priv_state *ps = ds_to_priv(ds); @@ -2367,6 +2418,23 @@ static int mv88e6xxx_setup_port(struct dsa_switch *ds, int port) goto abort; } + /* If this port is connected to a SerDes, make sure the SerDes is not + * powered down. + */ + if (mv88e6xxx_6352_family(ds)) { + ret = _mv88e6xxx_reg_read(ds, REG_PORT(port), PORT_STATUS); + if (ret < 0) + goto abort; + ret &= PORT_STATUS_CMODE_MASK; + if ((ret == PORT_STATUS_CMODE_100BASE_X) || + (ret == PORT_STATUS_CMODE_1000BASE_X) || + (ret == PORT_STATUS_CMODE_SGMII)) { + ret = mv88e6xxx_power_on_serdes(ds); + if (ret < 0) + goto abort; + } + } + /* Port Control 2: don't force a good FCS, set the maximum frame size to * 10240 bytes, disable 802.1q tags checking, don't discard tagged or * untagged frames on this port, do a destination address lookup on all @@ -2714,13 +2782,9 @@ int mv88e6xxx_phy_page_read(struct dsa_switch *ds, int port, int page, int reg) int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); - if (ret < 0) - goto error; - ret = _mv88e6xxx_phy_read_indirect(ds, port, reg); -error: - _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + ret = _mv88e6xxx_phy_page_read(ds, port, page, reg); mutex_unlock(&ps->smi_mutex); + return ret; } @@ -2731,14 +2795,9 @@ int mv88e6xxx_phy_page_write(struct dsa_switch *ds, int port, int page, int ret; mutex_lock(&ps->smi_mutex); - ret = _mv88e6xxx_phy_write_indirect(ds, port, 0x16, page); - if (ret < 0) - goto error; - - ret = _mv88e6xxx_phy_write_indirect(ds, port, reg, val); -error: - _mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0); + ret = _mv88e6xxx_phy_page_write(ds, port, page, reg, val); mutex_unlock(&ps->smi_mutex); + return ret; } diff --git a/drivers/net/dsa/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx.h index 9a038aba48fb..26a424acd10f 100644 --- a/drivers/net/dsa/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx.h @@ -28,6 +28,10 @@ #define SMI_CMD_OP_45_READ_DATA_INC ((3 << 10) | SMI_CMD_BUSY) #define SMI_DATA 0x01 +/* Fiber/SERDES Registers are located at SMI address F, page 1 */ +#define REG_FIBER_SERDES 0x0f +#define PAGE_FIBER_SERDES 0x01 + #define REG_PORT(p) (0x10 + (p)) #define PORT_STATUS 0x00 #define PORT_STATUS_PAUSE_EN BIT(15) @@ -45,6 +49,10 @@ #define PORT_STATUS_MGMII BIT(6) /* 6185 */ #define PORT_STATUS_TX_PAUSED BIT(5) #define PORT_STATUS_FLOW_CTRL BIT(4) +#define PORT_STATUS_CMODE_MASK 0x0f +#define PORT_STATUS_CMODE_100BASE_X 0x8 +#define PORT_STATUS_CMODE_1000BASE_X 0x9 +#define PORT_STATUS_CMODE_SGMII 0xa #define PORT_PCS_CTRL 0x01 #define PORT_PCS_CTRL_RGMII_DELAY_RXCLK BIT(15) #define PORT_PCS_CTRL_RGMII_DELAY_TXCLK BIT(14) diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index aabbd51db981..12a009d720cd 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -2653,7 +2653,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len, /* Write request msg to hwrm channel */ __iowrite32_copy(bp->bar0, data, msg_len / 4); - for (i = msg_len; i < HWRM_MAX_REQ_LEN; i += 4) + for (i = msg_len; i < BNXT_HWRM_MAX_REQ_LEN; i += 4) writel(0, bp->bar0 + i); /* currently supports only one outstanding message */ @@ -3391,11 +3391,11 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp) struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring; struct bnxt_ring_struct *ring = &cpr->cp_ring_struct; + cpr->cp_doorbell = bp->bar1 + i * 0x80; rc = hwrm_ring_alloc_send_msg(bp, ring, HWRM_RING_ALLOC_CMPL, i, INVALID_STATS_CTX_ID); if (rc) goto err_out; - cpr->cp_doorbell = bp->bar1 + i * 0x80; BNXT_CP_DB(cpr->cp_doorbell, cpr->cp_raw_cons); bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id; } @@ -3830,6 +3830,7 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp) struct hwrm_ver_get_input req = {0}; struct hwrm_ver_get_output *resp = bp->hwrm_cmd_resp_addr; + bp->hwrm_max_req_len = HWRM_MAX_REQ_LEN; bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_VER_GET, -1, -1); req.hwrm_intf_maj = HWRM_VERSION_MAJOR; req.hwrm_intf_min = HWRM_VERSION_MINOR; @@ -3855,6 +3856,9 @@ static int bnxt_hwrm_ver_get(struct bnxt *bp) if (!bp->hwrm_cmd_timeout) bp->hwrm_cmd_timeout = DFLT_HWRM_CMD_TIMEOUT; + if (resp->hwrm_intf_maj >= 1) + bp->hwrm_max_req_len = le16_to_cpu(resp->max_req_win_len); + hwrm_ver_get_exit: mutex_unlock(&bp->hwrm_cmd_lock); return rc; @@ -4555,7 +4559,7 @@ bnxt_hwrm_set_pause_common(struct bnxt *bp, struct hwrm_port_phy_cfg_input *req) if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_RX) req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; if (bp->link_info.req_flow_ctrl & BNXT_LINK_PAUSE_TX) - req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_RX; + req->auto_pause |= PORT_PHY_CFG_REQ_AUTO_PAUSE_TX; req->enables |= cpu_to_le32(PORT_PHY_CFG_REQ_ENABLES_AUTO_PAUSE); } else { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index ec04c47172b7..709b95b8fcba 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -477,6 +477,7 @@ struct rx_tpa_end_cmp_ext { #define RING_CMP(idx) ((idx) & bp->cp_ring_mask) #define NEXT_CMP(idx) RING_CMP(ADV_RAW_CMP(idx, 1)) +#define BNXT_HWRM_MAX_REQ_LEN (bp->hwrm_max_req_len) #define DFLT_HWRM_CMD_TIMEOUT 500 #define HWRM_CMD_TIMEOUT (bp->hwrm_cmd_timeout) #define HWRM_RESET_TIMEOUT ((HWRM_CMD_TIMEOUT) * 4) @@ -953,6 +954,7 @@ struct bnxt { dma_addr_t hw_tx_port_stats_map; int hw_port_stats_size; + u16 hwrm_max_req_len; int hwrm_cmd_timeout; struct mutex hwrm_cmd_lock; /* serialize hwrm messages */ struct hwrm_ver_get_output ver_resp; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 9ada1662b651..2e472f6dbf2d 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -855,10 +855,8 @@ static void bnxt_get_pauseparam(struct net_device *dev, if (BNXT_VF(bp)) return; epause->autoneg = !!(link_info->autoneg & BNXT_AUTONEG_FLOW_CTRL); - epause->rx_pause = - ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_RX) != 0); - epause->tx_pause = - ((link_info->auto_pause_setting & BNXT_LINK_PAUSE_TX) != 0); + epause->rx_pause = !!(link_info->req_flow_ctrl & BNXT_LINK_PAUSE_RX); + epause->tx_pause = !!(link_info->req_flow_ctrl & BNXT_LINK_PAUSE_TX); } static int bnxt_set_pauseparam(struct net_device *dev, diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 6746fd03cb3a..cf6445d148ca 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -1171,6 +1171,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, struct enet_cb *tx_cb_ptr; struct netdev_queue *txq; unsigned int pkts_compl = 0; + unsigned int bytes_compl = 0; unsigned int c_index; unsigned int txbds_ready; unsigned int txbds_processed = 0; @@ -1193,16 +1194,13 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, tx_cb_ptr = &priv->tx_cbs[ring->clean_ptr]; if (tx_cb_ptr->skb) { pkts_compl++; - dev->stats.tx_packets++; - dev->stats.tx_bytes += tx_cb_ptr->skb->len; + bytes_compl += GENET_CB(tx_cb_ptr->skb)->bytes_sent; dma_unmap_single(&dev->dev, dma_unmap_addr(tx_cb_ptr, dma_addr), dma_unmap_len(tx_cb_ptr, dma_len), DMA_TO_DEVICE); bcmgenet_free_cb(tx_cb_ptr); } else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) { - dev->stats.tx_bytes += - dma_unmap_len(tx_cb_ptr, dma_len); dma_unmap_page(&dev->dev, dma_unmap_addr(tx_cb_ptr, dma_addr), dma_unmap_len(tx_cb_ptr, dma_len), @@ -1220,6 +1218,9 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev, ring->free_bds += txbds_processed; ring->c_index = (ring->c_index + txbds_processed) & DMA_C_INDEX_MASK; + dev->stats.tx_packets += pkts_compl; + dev->stats.tx_bytes += bytes_compl; + if (ring->free_bds > (MAX_SKB_FRAGS + 1)) { txq = netdev_get_tx_queue(dev, ring->queue); if (netif_tx_queue_stopped(txq)) @@ -1296,7 +1297,7 @@ static int bcmgenet_xmit_single(struct net_device *dev, tx_cb_ptr->skb = skb; - skb_len = skb_headlen(skb) < ETH_ZLEN ? ETH_ZLEN : skb_headlen(skb); + skb_len = skb_headlen(skb); mapping = dma_map_single(kdev, skb->data, skb_len, DMA_TO_DEVICE); ret = dma_mapping_error(kdev, mapping); @@ -1464,6 +1465,11 @@ static netdev_tx_t bcmgenet_xmit(struct sk_buff *skb, struct net_device *dev) goto out; } + /* Retain how many bytes will be sent on the wire, without TSB inserted + * by transmit checksum offload + */ + GENET_CB(skb)->bytes_sent = skb->len; + /* set the SKB transmit checksum */ if (priv->desc_64b_en) { skb = bcmgenet_put_tx_csum(dev, skb); diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index 967367557309..1e2dc34d331a 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -531,6 +531,12 @@ struct bcmgenet_hw_params { u32 flags; }; +struct bcmgenet_skb_cb { + unsigned int bytes_sent; /* bytes on the wire (no TSB) */ +}; + +#define GENET_CB(skb) ((struct bcmgenet_skb_cb *)((skb)->cb)) + struct bcmgenet_tx_ring { spinlock_t lock; /* ring lock */ struct napi_struct napi; /* NAPI per tx queue */ diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 6619178ed77b..48a7d7dee846 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -917,7 +917,10 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, unsigned int frag_len = bp->rx_buffer_size; if (offset + frag_len > len) { - BUG_ON(frag != last_frag); + if (unlikely(frag != last_frag)) { + dev_kfree_skb_any(skb); + return -1; + } frag_len = len - offset; } skb_copy_to_linear_data_offset(skb, offset, @@ -945,8 +948,23 @@ static int macb_rx_frame(struct macb *bp, unsigned int first_frag, return 0; } +static inline void macb_init_rx_ring(struct macb *bp) +{ + dma_addr_t addr; + int i; + + addr = bp->rx_buffers_dma; + for (i = 0; i < RX_RING_SIZE; i++) { + bp->rx_ring[i].addr = addr; + bp->rx_ring[i].ctrl = 0; + addr += bp->rx_buffer_size; + } + bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); +} + static int macb_rx(struct macb *bp, int budget) { + bool reset_rx_queue = false; int received = 0; unsigned int tail; int first_frag = -1; @@ -972,10 +990,18 @@ static int macb_rx(struct macb *bp, int budget) if (ctrl & MACB_BIT(RX_EOF)) { int dropped; - BUG_ON(first_frag == -1); + + if (unlikely(first_frag == -1)) { + reset_rx_queue = true; + continue; + } dropped = macb_rx_frame(bp, first_frag, tail); first_frag = -1; + if (unlikely(dropped < 0)) { + reset_rx_queue = true; + continue; + } if (!dropped) { received++; budget--; @@ -983,6 +1009,26 @@ static int macb_rx(struct macb *bp, int budget) } } + if (unlikely(reset_rx_queue)) { + unsigned long flags; + u32 ctrl; + + netdev_err(bp->dev, "RX queue corruption: reset it\n"); + + spin_lock_irqsave(&bp->lock, flags); + + ctrl = macb_readl(bp, NCR); + macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE)); + + macb_init_rx_ring(bp); + macb_writel(bp, RBQP, bp->rx_ring_dma); + + macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); + + spin_unlock_irqrestore(&bp->lock, flags); + return received; + } + if (first_frag != -1) bp->rx_tail = first_frag; else @@ -1100,7 +1146,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) - macb_writel(bp, ISR, MACB_BIT(RXUBR)); + queue_writel(queue, ISR, MACB_BIT(RXUBR)); } if (status & MACB_BIT(ISR_ROVR)) { @@ -1523,15 +1569,8 @@ static void gem_init_rings(struct macb *bp) static void macb_init_rings(struct macb *bp) { int i; - dma_addr_t addr; - addr = bp->rx_buffers_dma; - for (i = 0; i < RX_RING_SIZE; i++) { - bp->rx_ring[i].addr = addr; - bp->rx_ring[i].ctrl = 0; - addr += bp->rx_buffer_size; - } - bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP); + macb_init_rx_ring(bp); for (i = 0; i < TX_RING_SIZE; i++) { bp->queues[0].tx_ring[i].addr = 0; @@ -2957,9 +2996,10 @@ static int macb_probe(struct platform_device *pdev) phy_node = of_get_next_available_child(np, NULL); if (phy_node) { int gpio = of_get_named_gpio(phy_node, "reset-gpios", 0); - if (gpio_is_valid(gpio)) + if (gpio_is_valid(gpio)) { bp->reset_gpio = gpio_to_desc(gpio); - gpiod_direction_output(bp->reset_gpio, 1); + gpiod_direction_output(bp->reset_gpio, 1); + } } of_node_put(phy_node); @@ -3029,7 +3069,8 @@ static int macb_remove(struct platform_device *pdev) mdiobus_free(bp->mii_bus); /* Shutdown the PHY if there is a GPIO reset */ - gpiod_set_value(bp->reset_gpio, 0); + if (bp->reset_gpio) + gpiod_set_value(bp->reset_gpio, 0); unregister_netdev(dev); clk_disable_unprepare(bp->tx_clk); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 37c081583084..08243c2ff4b4 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -943,8 +943,8 @@ fec_restart(struct net_device *ndev) else val &= ~FEC_RACC_OPTIONS; writel(val, fep->hwp + FEC_RACC); + writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL); } - writel(PKT_MAXBUF_SIZE, fep->hwp + FEC_FTRL); #endif /* diff --git a/drivers/net/ethernet/hisilicon/hns/hnae.h b/drivers/net/ethernet/hisilicon/hns/hnae.h index 37d0cce392be..e8d36aaea223 100644 --- a/drivers/net/ethernet/hisilicon/hns/hnae.h +++ b/drivers/net/ethernet/hisilicon/hns/hnae.h @@ -469,7 +469,7 @@ struct hnae_ae_ops { u32 *tx_usecs, u32 *rx_usecs); void (*get_rx_max_coalesced_frames)(struct hnae_handle *handle, u32 *tx_frames, u32 *rx_frames); - void (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout); + int (*set_coalesce_usecs)(struct hnae_handle *handle, u32 timeout); int (*set_coalesce_frames)(struct hnae_handle *handle, u32 coalesce_frames); void (*set_promisc_mode)(struct hnae_handle *handle, u32 en); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c index 285c893ab135..a1cb461ac45f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ae_adapt.c @@ -159,11 +159,6 @@ struct hnae_handle *hns_ae_get_handle(struct hnae_ae_dev *dev, ae_handle->qs[i]->tx_ring.q = ae_handle->qs[i]; ring_pair_cb->used_by_vf = 1; - if (port_idx < DSAF_SERVICE_PORT_NUM_PER_DSAF) - ring_pair_cb->port_id_in_dsa = port_idx; - else - ring_pair_cb->port_id_in_dsa = 0; - ring_pair_cb++; } @@ -453,59 +448,46 @@ static int hns_ae_set_pauseparam(struct hnae_handle *handle, static void hns_ae_get_coalesce_usecs(struct hnae_handle *handle, u32 *tx_usecs, u32 *rx_usecs) { - int port; - - port = hns_ae_map_eport_to_dport(handle->eport_id); + struct ring_pair_cb *ring_pair = + container_of(handle->qs[0], struct ring_pair_cb, q); - *tx_usecs = hns_rcb_get_coalesce_usecs( - hns_ae_get_dsaf_dev(handle->dev), - hns_dsaf_get_comm_idx_by_port(port)); - *rx_usecs = hns_rcb_get_coalesce_usecs( - hns_ae_get_dsaf_dev(handle->dev), - hns_dsaf_get_comm_idx_by_port(port)); + *tx_usecs = hns_rcb_get_coalesce_usecs(ring_pair->rcb_common, + ring_pair->port_id_in_comm); + *rx_usecs = hns_rcb_get_coalesce_usecs(ring_pair->rcb_common, + ring_pair->port_id_in_comm); } static void hns_ae_get_rx_max_coalesced_frames(struct hnae_handle *handle, u32 *tx_frames, u32 *rx_frames) { - int port; + struct ring_pair_cb *ring_pair = + container_of(handle->qs[0], struct ring_pair_cb, q); - assert(handle); - - port = hns_ae_map_eport_to_dport(handle->eport_id); - - *tx_frames = hns_rcb_get_coalesced_frames( - hns_ae_get_dsaf_dev(handle->dev), port); - *rx_frames = hns_rcb_get_coalesced_frames( - hns_ae_get_dsaf_dev(handle->dev), port); + *tx_frames = hns_rcb_get_coalesced_frames(ring_pair->rcb_common, + ring_pair->port_id_in_comm); + *rx_frames = hns_rcb_get_coalesced_frames(ring_pair->rcb_common, + ring_pair->port_id_in_comm); } -static void hns_ae_set_coalesce_usecs(struct hnae_handle *handle, - u32 timeout) +static int hns_ae_set_coalesce_usecs(struct hnae_handle *handle, + u32 timeout) { - int port; + struct ring_pair_cb *ring_pair = + container_of(handle->qs[0], struct ring_pair_cb, q); - assert(handle); - - port = hns_ae_map_eport_to_dport(handle->eport_id); - - hns_rcb_set_coalesce_usecs(hns_ae_get_dsaf_dev(handle->dev), - port, timeout); + return hns_rcb_set_coalesce_usecs( + ring_pair->rcb_common, ring_pair->port_id_in_comm, timeout); } static int hns_ae_set_coalesce_frames(struct hnae_handle *handle, u32 coalesce_frames) { - int port; - int ret; + struct ring_pair_cb *ring_pair = + container_of(handle->qs[0], struct ring_pair_cb, q); - assert(handle); - - port = hns_ae_map_eport_to_dport(handle->eport_id); - - ret = hns_rcb_set_coalesced_frames(hns_ae_get_dsaf_dev(handle->dev), - port, coalesce_frames); - return ret; + return hns_rcb_set_coalesced_frames( + ring_pair->rcb_common, + ring_pair->port_id_in_comm, coalesce_frames); } void hns_ae_update_stats(struct hnae_handle *handle, diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c index 6e2b76ede075..44abb08de155 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_gmac.c @@ -664,7 +664,8 @@ static void hns_gmac_get_strings(u32 stringset, u8 *data) return; for (i = 0; i < ARRAY_SIZE(g_gmac_stats_string); i++) { - snprintf(buff, ETH_GSTRING_LEN, g_gmac_stats_string[i].desc); + snprintf(buff, ETH_GSTRING_LEN, "%s", + g_gmac_stats_string[i].desc); buff = buff + ETH_GSTRING_LEN; } } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c index 5c1ac9ba1bf2..5978a5c8ef35 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c @@ -2219,17 +2219,17 @@ void hns_dsaf_get_regs(struct dsaf_device *ddev, u32 port, void *data) /* dsaf onode registers */ for (i = 0; i < DSAF_XOD_NUM; i++) { p[311 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_TSA_TC0_TC3_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_TSA_TC0_TC3_CFG_0_REG + i * 0x90); p[319 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_TSA_TC4_TC7_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_TSA_TC4_TC7_CFG_0_REG + i * 0x90); p[327 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_BW_TC0_TC3_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_BW_TC0_TC3_CFG_0_REG + i * 0x90); p[335 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_BW_TC4_TC7_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_BW_TC4_TC7_CFG_0_REG + i * 0x90); p[343 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_BW_OFFSET_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_BW_OFFSET_CFG_0_REG + i * 0x90); p[351 + i] = dsaf_read_dev(ddev, - DSAF_XOD_ETS_TOKEN_CFG_0_REG + j * 0x90); + DSAF_XOD_ETS_TOKEN_CFG_0_REG + i * 0x90); } p[359] = dsaf_read_dev(ddev, DSAF_XOD_PFS_CFG_0_0_REG + port * 0x90); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c index 607c3be42241..e69b02287c44 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c @@ -244,31 +244,35 @@ void hns_ppe_com_srst(struct ppe_common_cb *ppe_common, u32 val) */ phy_interface_t hns_mac_get_phy_if(struct hns_mac_cb *mac_cb) { - u32 hilink3_mode; - u32 hilink4_mode; + u32 mode; + u32 reg; + u32 shift; + bool is_ver1 = AE_IS_VER1(mac_cb->dsaf_dev->dsaf_ver); void __iomem *sys_ctl_vaddr = mac_cb->sys_ctl_vaddr; - int dev_id = mac_cb->mac_id; + int mac_id = mac_cb->mac_id; phy_interface_t phy_if = PHY_INTERFACE_MODE_NA; - hilink3_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK3_REG); - hilink4_mode = dsaf_read_reg(sys_ctl_vaddr, HNS_MAC_HILINK4_REG); - if (dev_id >= 0 && dev_id <= 3) { - if (hilink4_mode == 0) - phy_if = PHY_INTERFACE_MODE_SGMII; - else + if (is_ver1 && (mac_id >= 6 && mac_id <= 7)) { + phy_if = PHY_INTERFACE_MODE_SGMII; + } else if (mac_id >= 0 && mac_id <= 3) { + reg = is_ver1 ? HNS_MAC_HILINK4_REG : HNS_MAC_HILINK4V2_REG; + mode = dsaf_read_reg(sys_ctl_vaddr, reg); + /* mac_id 0, 1, 2, 3 ---> hilink4 lane 0, 1, 2, 3 */ + shift = is_ver1 ? 0 : mac_id; + if (dsaf_get_bit(mode, shift)) phy_if = PHY_INTERFACE_MODE_XGMII; - } else if (dev_id >= 4 && dev_id <= 5) { - if (hilink3_mode == 0) - phy_if = PHY_INTERFACE_MODE_SGMII; else + phy_if = PHY_INTERFACE_MODE_SGMII; + } else if (mac_id >= 4 && mac_id <= 7) { + reg = is_ver1 ? HNS_MAC_HILINK3_REG : HNS_MAC_HILINK3V2_REG; + mode = dsaf_read_reg(sys_ctl_vaddr, reg); + /* mac_id 4, 5, 6, 7 ---> hilink3 lane 2, 3, 0, 1 */ + shift = is_ver1 ? 0 : mac_id <= 5 ? mac_id - 2 : mac_id - 6; + if (dsaf_get_bit(mode, shift)) phy_if = PHY_INTERFACE_MODE_XGMII; - } else { - phy_if = PHY_INTERFACE_MODE_SGMII; + else + phy_if = PHY_INTERFACE_MODE_SGMII; } - - dev_dbg(mac_cb->dev, - "hilink3_mode=%d, hilink4_mode=%d dev_id=%d, phy_if=%d\n", - hilink3_mode, hilink4_mode, dev_id, phy_if); return phy_if; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c index 12188807468c..28ee26e5c478 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c @@ -215,9 +215,9 @@ static void hns_rcb_ring_init(struct ring_pair_cb *ring_pair, int ring_type) dsaf_write_dev(q, RCB_RING_RX_RING_BD_LEN_REG, bd_size_type); dsaf_write_dev(q, RCB_RING_RX_RING_BD_NUM_REG, - ring_pair->port_id_in_dsa); + ring_pair->port_id_in_comm); dsaf_write_dev(q, RCB_RING_RX_RING_PKTLINE_REG, - ring_pair->port_id_in_dsa); + ring_pair->port_id_in_comm); } else { dsaf_write_dev(q, RCB_RING_TX_RING_BASEADDR_L_REG, (u32)dma); @@ -227,9 +227,9 @@ static void hns_rcb_ring_init(struct ring_pair_cb *ring_pair, int ring_type) dsaf_write_dev(q, RCB_RING_TX_RING_BD_LEN_REG, bd_size_type); dsaf_write_dev(q, RCB_RING_TX_RING_BD_NUM_REG, - ring_pair->port_id_in_dsa); + ring_pair->port_id_in_comm); dsaf_write_dev(q, RCB_RING_TX_RING_PKTLINE_REG, - ring_pair->port_id_in_dsa); + ring_pair->port_id_in_comm); } } @@ -256,50 +256,16 @@ static void hns_rcb_set_port_desc_cnt(struct rcb_common_cb *rcb_common, desc_cnt); } -/** - *hns_rcb_set_port_coalesced_frames - set rcb port coalesced frames - *@rcb_common: rcb_common device - *@port_idx:port index - *@coalesced_frames:BD num for coalesced frames - */ -static int hns_rcb_set_port_coalesced_frames(struct rcb_common_cb *rcb_common, - u32 port_idx, - u32 coalesced_frames) -{ - if (coalesced_frames >= rcb_common->desc_num || - coalesced_frames > HNS_RCB_MAX_COALESCED_FRAMES) - return -EINVAL; - - dsaf_write_dev(rcb_common, RCB_CFG_PKTLINE_REG + port_idx * 4, - coalesced_frames); - return 0; -} - -/** - *hns_rcb_get_port_coalesced_frames - set rcb port coalesced frames - *@rcb_common: rcb_common device - *@port_idx:port index - * return coaleseced frames value - */ -static u32 hns_rcb_get_port_coalesced_frames(struct rcb_common_cb *rcb_common, - u32 port_idx) +static void hns_rcb_set_port_timeout( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 timeout) { - if (port_idx >= HNS_RCB_SERVICE_NW_ENGINE_NUM) - port_idx = 0; - - return dsaf_read_dev(rcb_common, - RCB_CFG_PKTLINE_REG + port_idx * 4); -} - -/** - *hns_rcb_set_timeout - set rcb port coalesced time_out - *@rcb_common: rcb_common device - *@time_out:time for coalesced time_out - */ -static void hns_rcb_set_timeout(struct rcb_common_cb *rcb_common, - u32 timeout) -{ - dsaf_write_dev(rcb_common, RCB_CFG_OVERTIME_REG, timeout); + if (AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) + dsaf_write_dev(rcb_common, RCB_CFG_OVERTIME_REG, + timeout * HNS_RCB_CLK_FREQ_MHZ); + else + dsaf_write_dev(rcb_common, + RCB_PORT_CFG_OVERTIME_REG + port_idx * 4, + timeout); } static int hns_rcb_common_get_port_num(struct rcb_common_cb *rcb_common) @@ -361,10 +327,11 @@ int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common) for (i = 0; i < port_num; i++) { hns_rcb_set_port_desc_cnt(rcb_common, i, rcb_common->desc_num); - (void)hns_rcb_set_port_coalesced_frames( - rcb_common, i, rcb_common->coalesced_frames); + (void)hns_rcb_set_coalesced_frames( + rcb_common, i, HNS_RCB_DEF_COALESCED_FRAMES); + hns_rcb_set_port_timeout( + rcb_common, i, HNS_RCB_DEF_COALESCED_USECS); } - hns_rcb_set_timeout(rcb_common, rcb_common->timeout); dsaf_write_dev(rcb_common, RCB_COM_CFG_ENDIAN_REG, HNS_RCB_COMMON_ENDIAN); @@ -460,7 +427,8 @@ static void hns_rcb_ring_pair_get_cfg(struct ring_pair_cb *ring_pair_cb) hns_rcb_ring_get_cfg(&ring_pair_cb->q, TX_RING); } -static int hns_rcb_get_port(struct rcb_common_cb *rcb_common, int ring_idx) +static int hns_rcb_get_port_in_comm( + struct rcb_common_cb *rcb_common, int ring_idx) { int comm_index = rcb_common->comm_index; int port; @@ -470,7 +438,7 @@ static int hns_rcb_get_port(struct rcb_common_cb *rcb_common, int ring_idx) q_num = (int)rcb_common->max_q_per_vf * rcb_common->max_vfn; port = ring_idx / q_num; } else { - port = HNS_RCB_SERVICE_NW_ENGINE_NUM + comm_index - 1; + port = 0; /* config debug-ports port_id_in_comm to 0*/ } return port; @@ -518,7 +486,8 @@ void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common) ring_pair_cb->index = i; ring_pair_cb->q.io_base = RCB_COMM_BASE_TO_RING_BASE(rcb_common->io_base, i); - ring_pair_cb->port_id_in_dsa = hns_rcb_get_port(rcb_common, i); + ring_pair_cb->port_id_in_comm = + hns_rcb_get_port_in_comm(rcb_common, i); ring_pair_cb->virq[HNS_RCB_IRQ_IDX_TX] = is_ver1 ? irq_of_parse_and_map(np, base_irq_idx + i * 2) : platform_get_irq(pdev, base_irq_idx + i * 3 + 1); @@ -534,82 +503,95 @@ void hns_rcb_get_cfg(struct rcb_common_cb *rcb_common) /** *hns_rcb_get_coalesced_frames - get rcb port coalesced frames *@rcb_common: rcb_common device - *@comm_index:port index - *return coalesced_frames + *@port_idx:port id in comm + * + *Returns: coalesced_frames */ -u32 hns_rcb_get_coalesced_frames(struct dsaf_device *dsaf_dev, int port) +u32 hns_rcb_get_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx) { - int comm_index = hns_dsaf_get_comm_idx_by_port(port); - struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; - - return hns_rcb_get_port_coalesced_frames(rcb_comm, port); + return dsaf_read_dev(rcb_common, RCB_CFG_PKTLINE_REG + port_idx * 4); } /** *hns_rcb_get_coalesce_usecs - get rcb port coalesced time_out *@rcb_common: rcb_common device - *@comm_index:port index - *return time_out + *@port_idx:port id in comm + * + *Returns: time_out */ -u32 hns_rcb_get_coalesce_usecs(struct dsaf_device *dsaf_dev, int comm_index) +u32 hns_rcb_get_coalesce_usecs( + struct rcb_common_cb *rcb_common, u32 port_idx) { - struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; - - return rcb_comm->timeout; + if (AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) + return dsaf_read_dev(rcb_common, RCB_CFG_OVERTIME_REG) / + HNS_RCB_CLK_FREQ_MHZ; + else + return dsaf_read_dev(rcb_common, + RCB_PORT_CFG_OVERTIME_REG + port_idx * 4); } /** *hns_rcb_set_coalesce_usecs - set rcb port coalesced time_out *@rcb_common: rcb_common device - *@comm_index: comm :index - *@etx_usecs:tx time for coalesced time_out - *@rx_usecs:rx time for coalesced time_out + *@port_idx:port id in comm + *@timeout:tx/rx time for coalesced time_out + * + * Returns: + * Zero for success, or an error code in case of failure */ -void hns_rcb_set_coalesce_usecs(struct dsaf_device *dsaf_dev, - int port, u32 timeout) +int hns_rcb_set_coalesce_usecs( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 timeout) { - int comm_index = hns_dsaf_get_comm_idx_by_port(port); - struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; + u32 old_timeout = hns_rcb_get_coalesce_usecs(rcb_common, port_idx); - if (rcb_comm->timeout == timeout) - return; + if (timeout == old_timeout) + return 0; - if (comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { - dev_err(dsaf_dev->dev, - "error: not support coalesce_usecs setting!\n"); - return; + if (AE_IS_VER1(rcb_common->dsaf_dev->dsaf_ver)) { + if (rcb_common->comm_index == HNS_DSAF_COMM_SERVICE_NW_IDX) { + dev_err(rcb_common->dsaf_dev->dev, + "error: not support coalesce_usecs setting!\n"); + return -EINVAL; + } } - rcb_comm->timeout = timeout; - hns_rcb_set_timeout(rcb_comm, rcb_comm->timeout); + if (timeout > HNS_RCB_MAX_COALESCED_USECS) { + dev_err(rcb_common->dsaf_dev->dev, + "error: not support coalesce %dus!\n", timeout); + return -EINVAL; + } + hns_rcb_set_port_timeout(rcb_common, port_idx, timeout); + return 0; } /** *hns_rcb_set_coalesced_frames - set rcb coalesced frames *@rcb_common: rcb_common device - *@tx_frames:tx BD num for coalesced frames - *@rx_frames:rx BD num for coalesced frames - *Return 0 on success, negative on failure + *@port_idx:port id in comm + *@coalesced_frames:tx/rx BD num for coalesced frames + * + * Returns: + * Zero for success, or an error code in case of failure */ -int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev, - int port, u32 coalesced_frames) +int hns_rcb_set_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 coalesced_frames) { - int comm_index = hns_dsaf_get_comm_idx_by_port(port); - struct rcb_common_cb *rcb_comm = dsaf_dev->rcb_common[comm_index]; - u32 coalesced_reg_val; - int ret; + u32 old_waterline = hns_rcb_get_coalesced_frames(rcb_common, port_idx); - coalesced_reg_val = hns_rcb_get_port_coalesced_frames(rcb_comm, port); - - if (coalesced_reg_val == coalesced_frames) + if (coalesced_frames == old_waterline) return 0; - if (coalesced_frames >= HNS_RCB_MIN_COALESCED_FRAMES) { - ret = hns_rcb_set_port_coalesced_frames(rcb_comm, port, - coalesced_frames); - return ret; - } else { + if (coalesced_frames >= rcb_common->desc_num || + coalesced_frames > HNS_RCB_MAX_COALESCED_FRAMES || + coalesced_frames < HNS_RCB_MIN_COALESCED_FRAMES) { + dev_err(rcb_common->dsaf_dev->dev, + "error: not support coalesce_frames setting!\n"); return -EINVAL; } + + dsaf_write_dev(rcb_common, RCB_CFG_PKTLINE_REG + port_idx * 4, + coalesced_frames); + return 0; } /** @@ -749,8 +731,6 @@ int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, rcb_common->dsaf_dev = dsaf_dev; rcb_common->desc_num = dsaf_dev->desc_num; - rcb_common->coalesced_frames = HNS_RCB_DEF_COALESCED_FRAMES; - rcb_common->timeout = HNS_RCB_MAX_TIME_OUT; hns_rcb_get_queue_mode(dsaf_mode, comm_index, &max_vfn, &max_q_per_vf); rcb_common->max_vfn = max_vfn; @@ -951,6 +931,10 @@ void hns_rcb_get_strings(int stringset, u8 *data, int index) void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_com, void *data) { u32 *regs = data; + bool is_ver1 = AE_IS_VER1(rcb_com->dsaf_dev->dsaf_ver); + bool is_dbg = (rcb_com->comm_index != HNS_DSAF_COMM_SERVICE_NW_IDX); + u32 reg_tmp; + u32 reg_num_tmp; u32 i = 0; /*rcb common registers */ @@ -1004,12 +988,16 @@ void hns_rcb_get_common_regs(struct rcb_common_cb *rcb_com, void *data) = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_REG + 4 * i); } - regs[70] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_REG); - regs[71] = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_INT_NUM_REG); - regs[72] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_INT_NUM_REG); + reg_tmp = is_ver1 ? RCB_CFG_OVERTIME_REG : RCB_PORT_CFG_OVERTIME_REG; + reg_num_tmp = (is_ver1 || is_dbg) ? 1 : 6; + for (i = 0; i < reg_num_tmp; i++) + regs[70 + i] = dsaf_read_dev(rcb_com, reg_tmp); + + regs[76] = dsaf_read_dev(rcb_com, RCB_CFG_PKTLINE_INT_NUM_REG); + regs[77] = dsaf_read_dev(rcb_com, RCB_CFG_OVERTIME_INT_NUM_REG); /* mark end of rcb common regs */ - for (i = 73; i < 80; i++) + for (i = 78; i < 80; i++) regs[i] = 0xcccccccc; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h index 81fe9f849973..eb61014ad615 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h @@ -38,7 +38,9 @@ struct rcb_common_cb; #define HNS_RCB_MAX_COALESCED_FRAMES 1023 #define HNS_RCB_MIN_COALESCED_FRAMES 1 #define HNS_RCB_DEF_COALESCED_FRAMES 50 -#define HNS_RCB_MAX_TIME_OUT 0x500 +#define HNS_RCB_CLK_FREQ_MHZ 350 +#define HNS_RCB_MAX_COALESCED_USECS 0x3ff +#define HNS_RCB_DEF_COALESCED_USECS 3 #define HNS_RCB_COMMON_ENDIAN 1 @@ -82,7 +84,7 @@ struct ring_pair_cb { int virq[HNS_RCB_IRQ_NUM_PER_QUEUE]; - u8 port_id_in_dsa; + u8 port_id_in_comm; u8 used_by_vf; struct hns_ring_hw_stats hw_stats; @@ -97,8 +99,6 @@ struct rcb_common_cb { u8 comm_index; u32 ring_num; - u32 coalesced_frames; /* frames threshold of rx interrupt */ - u32 timeout; /* time threshold of rx interrupt */ u32 desc_num; /* desc num per queue*/ struct ring_pair_cb ring_pair_cb[0]; @@ -125,13 +125,14 @@ void hns_rcbv2_int_clr_hw(struct hnae_queue *q, u32 flag); void hns_rcb_init_hw(struct ring_pair_cb *ring); void hns_rcb_reset_ring_hw(struct hnae_queue *q); void hns_rcb_wait_fbd_clean(struct hnae_queue **qs, int q_num, u32 flag); - -u32 hns_rcb_get_coalesced_frames(struct dsaf_device *dsaf_dev, int comm_index); -u32 hns_rcb_get_coalesce_usecs(struct dsaf_device *dsaf_dev, int comm_index); -void hns_rcb_set_coalesce_usecs(struct dsaf_device *dsaf_dev, - int comm_index, u32 timeout); -int hns_rcb_set_coalesced_frames(struct dsaf_device *dsaf_dev, - int comm_index, u32 coalesce_frames); +u32 hns_rcb_get_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx); +u32 hns_rcb_get_coalesce_usecs( + struct rcb_common_cb *rcb_common, u32 port_idx); +int hns_rcb_set_coalesce_usecs( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 timeout); +int hns_rcb_set_coalesced_frames( + struct rcb_common_cb *rcb_common, u32 port_idx, u32 coalesced_frames); void hns_rcb_update_stats(struct hnae_queue *queue); void hns_rcb_get_stats(struct hnae_queue *queue, u64 *data); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h index bf62687e5ea7..7d7204f45e78 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_reg.h @@ -103,6 +103,8 @@ /*serdes offset**/ #define HNS_MAC_HILINK3_REG DSAF_SUB_SC_HILINK3_CRG_CTRL0_REG #define HNS_MAC_HILINK4_REG DSAF_SUB_SC_HILINK4_CRG_CTRL0_REG +#define HNS_MAC_HILINK3V2_REG DSAF_SUB_SC_HILINK3_CRG_CTRL1_REG +#define HNS_MAC_HILINK4V2_REG DSAF_SUB_SC_HILINK4_CRG_CTRL1_REG #define HNS_MAC_LANE0_CTLEDFE_REG 0x000BFFCCULL #define HNS_MAC_LANE1_CTLEDFE_REG 0x000BFFBCULL #define HNS_MAC_LANE2_CTLEDFE_REG 0x000BFFACULL @@ -404,6 +406,7 @@ #define RCB_CFG_OVERTIME_REG 0x9300 #define RCB_CFG_PKTLINE_INT_NUM_REG 0x9304 #define RCB_CFG_OVERTIME_INT_NUM_REG 0x9308 +#define RCB_PORT_CFG_OVERTIME_REG 0x9430 #define RCB_RING_RX_RING_BASEADDR_L_REG 0x00000 #define RCB_RING_RX_RING_BASEADDR_H_REG 0x00004 diff --git a/drivers/net/ethernet/hisilicon/hns/hns_enet.c b/drivers/net/ethernet/hisilicon/hns/hns_enet.c index 71aa37b4b338..687204b780b0 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_enet.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_enet.c @@ -913,10 +913,7 @@ static int hns_nic_tx_poll_one(struct hns_nic_ring_data *ring_data, static void hns_nic_tx_fini_pro(struct hns_nic_ring_data *ring_data) { struct hnae_ring *ring = ring_data->ring; - int head = ring->next_to_clean; - - /* for hardware bug fixed */ - head = readl_relaxed(ring->io_base + RCB_REG_HEAD); + int head = readl_relaxed(ring->io_base + RCB_REG_HEAD); if (head != ring->next_to_clean) { ring_data->ring->q->handle->dev->ops->toggle_ring_irq( @@ -959,8 +956,8 @@ static int hns_nic_common_poll(struct napi_struct *napi, int budget) napi_complete(napi); ring_data->ring->q->handle->dev->ops->toggle_ring_irq( ring_data->ring, 0); - - ring_data->fini_process(ring_data); + if (ring_data->fini_process) + ring_data->fini_process(ring_data); return 0; } @@ -1723,6 +1720,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv) { struct hnae_handle *h = priv->ae_handle; struct hns_nic_ring_data *rd; + bool is_ver1 = AE_IS_VER1(priv->enet_ver); int i; if (h->q_num > NIC_MAX_Q_PER_VF) { @@ -1740,7 +1738,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv) rd->queue_index = i; rd->ring = &h->qs[i]->tx_ring; rd->poll_one = hns_nic_tx_poll_one; - rd->fini_process = hns_nic_tx_fini_pro; + rd->fini_process = is_ver1 ? hns_nic_tx_fini_pro : NULL; netif_napi_add(priv->netdev, &rd->napi, hns_nic_common_poll, NIC_TX_CLEAN_MAX_NUM); @@ -1752,7 +1750,7 @@ static int hns_nic_init_ring_data(struct hns_nic_priv *priv) rd->ring = &h->qs[i - h->q_num]->rx_ring; rd->poll_one = hns_nic_rx_poll_one; rd->ex_process = hns_nic_rx_up_pro; - rd->fini_process = hns_nic_rx_fini_pro; + rd->fini_process = is_ver1 ? hns_nic_rx_fini_pro : NULL; netif_napi_add(priv->netdev, &rd->napi, hns_nic_common_poll, NIC_RX_CLEAN_MAX_NUM); @@ -1816,7 +1814,7 @@ static int hns_nic_try_get_ae(struct net_device *ndev) h = hnae_get_handle(&priv->netdev->dev, priv->ae_node, priv->port_id, NULL); if (IS_ERR_OR_NULL(h)) { - ret = PTR_ERR(h); + ret = -ENODEV; dev_dbg(priv->dev, "has not handle, register notifier!\n"); goto out; } diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c index 9c3ba65988e1..3d746c887873 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c @@ -794,8 +794,10 @@ static int hns_set_coalesce(struct net_device *net_dev, (!ops->set_coalesce_frames)) return -ESRCH; - ops->set_coalesce_usecs(priv->ae_handle, - ec->rx_coalesce_usecs); + ret = ops->set_coalesce_usecs(priv->ae_handle, + ec->rx_coalesce_usecs); + if (ret) + return ret; ret = ops->set_coalesce_frames( priv->ae_handle, @@ -1013,8 +1015,8 @@ int hns_phy_led_set(struct net_device *netdev, int value) struct phy_device *phy_dev = priv->phy; retval = phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_LED); - retval = phy_write(phy_dev, HNS_LED_FC_REG, value); - retval = phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER); + retval |= phy_write(phy_dev, HNS_LED_FC_REG, value); + retval |= phy_write(phy_dev, HNS_PHY_PAGE_REG, HNS_PHY_PAGE_COPPER); if (retval) { netdev_err(netdev, "mdiobus_write fail !\n"); return retval; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 84fa28ceb200..e4949af7dd6b 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -661,9 +661,7 @@ struct ixgbe_adapter { #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 9) #define IXGBE_FLAG2_PTP_PPS_ENABLED (u32)(1 << 10) #define IXGBE_FLAG2_PHY_INTERRUPT (u32)(1 << 11) -#ifdef CONFIG_IXGBE_VXLAN #define IXGBE_FLAG2_VXLAN_REREG_NEEDED BIT(12) -#endif #define IXGBE_FLAG2_VLAN_PROMISC BIT(13) /* Tx fast path data */ @@ -675,6 +673,9 @@ struct ixgbe_adapter { int num_rx_queues; u16 rx_itr_setting; + /* Port number used to identify VXLAN traffic */ + __be16 vxlan_port; + /* TX */ struct ixgbe_ring *tx_ring[MAX_TX_QUEUES] ____cacheline_aligned_in_smp; @@ -782,9 +783,6 @@ struct ixgbe_adapter { u32 timer_event_accumulator; u32 vferr_refcount; struct ixgbe_mac_addr *mac_table; -#ifdef CONFIG_IXGBE_VXLAN - u16 vxlan_port; -#endif struct kobject *info_kobj; #ifdef CONFIG_IXGBE_HWMON struct hwmon_buff *ixgbe_hwmon_buff; @@ -879,6 +877,8 @@ extern const char ixgbe_driver_version[]; extern char ixgbe_default_device_descr[]; #endif /* IXGBE_FCOE */ +int ixgbe_open(struct net_device *netdev); +int ixgbe_close(struct net_device *netdev); void ixgbe_up(struct ixgbe_adapter *adapter); void ixgbe_down(struct ixgbe_adapter *adapter); void ixgbe_reinit_locked(struct ixgbe_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 726e0eeee63b..b3530e1e3ce1 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -2053,7 +2053,7 @@ static void ixgbe_diag_test(struct net_device *netdev, if (if_running) /* indicate we're in test mode */ - dev_close(netdev); + ixgbe_close(netdev); else ixgbe_reset(adapter); @@ -2091,7 +2091,7 @@ skip_loopback: /* clear testing bit and return adapter to previous state */ clear_bit(__IXGBE_TESTING, &adapter->state); if (if_running) - dev_open(netdev); + ixgbe_open(netdev); else if (hw->mac.ops.disable_tx_laser) hw->mac.ops.disable_tx_laser(hw); } else { diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 569cb0757c93..7df3fe29b210 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -4531,9 +4531,7 @@ static void ixgbe_clear_vxlan_port(struct ixgbe_adapter *adapter) case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: IXGBE_WRITE_REG(&adapter->hw, IXGBE_VXLANCTRL, 0); -#ifdef CONFIG_IXGBE_VXLAN adapter->vxlan_port = 0; -#endif break; default: break; @@ -5994,7 +5992,7 @@ static int ixgbe_change_mtu(struct net_device *netdev, int new_mtu) * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. **/ -static int ixgbe_open(struct net_device *netdev) +int ixgbe_open(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -6096,7 +6094,7 @@ static void ixgbe_close_suspend(struct ixgbe_adapter *adapter) * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. **/ -static int ixgbe_close(struct net_device *netdev) +int ixgbe_close(struct net_device *netdev) { struct ixgbe_adapter *adapter = netdev_priv(netdev); @@ -7560,11 +7558,10 @@ static void ixgbe_atr(struct ixgbe_ring *ring, struct ipv6hdr *ipv6; } hdr; struct tcphdr *th; + unsigned int hlen; struct sk_buff *skb; -#ifdef CONFIG_IXGBE_VXLAN - u8 encap = false; -#endif /* CONFIG_IXGBE_VXLAN */ __be16 vlan_id; + int l4_proto; /* if ring doesn't have a interrupt vector, cannot perform ATR */ if (!q_vector) @@ -7576,62 +7573,50 @@ static void ixgbe_atr(struct ixgbe_ring *ring, ring->atr_count++; + /* currently only IPv4/IPv6 with TCP is supported */ + if ((first->protocol != htons(ETH_P_IP)) && + (first->protocol != htons(ETH_P_IPV6))) + return; + /* snag network header to get L4 type and address */ skb = first->skb; hdr.network = skb_network_header(skb); - if (!skb->encapsulation) { - th = tcp_hdr(skb); - } else { #ifdef CONFIG_IXGBE_VXLAN + if (skb->encapsulation && + first->protocol == htons(ETH_P_IP) && + hdr.ipv4->protocol != IPPROTO_UDP) { struct ixgbe_adapter *adapter = q_vector->adapter; - if (!adapter->vxlan_port) - return; - if (first->protocol != htons(ETH_P_IP) || - hdr.ipv4->version != IPVERSION || - hdr.ipv4->protocol != IPPROTO_UDP) { - return; - } - if (ntohs(udp_hdr(skb)->dest) != adapter->vxlan_port) - return; - encap = true; - hdr.network = skb_inner_network_header(skb); - th = inner_tcp_hdr(skb); -#else - return; -#endif /* CONFIG_IXGBE_VXLAN */ + /* verify the port is recognized as VXLAN */ + if (adapter->vxlan_port && + udp_hdr(skb)->dest == adapter->vxlan_port) + hdr.network = skb_inner_network_header(skb); } +#endif /* CONFIG_IXGBE_VXLAN */ /* Currently only IPv4/IPv6 with TCP is supported */ switch (hdr.ipv4->version) { case IPVERSION: - if (hdr.ipv4->protocol != IPPROTO_TCP) - return; + /* access ihl as u8 to avoid unaligned access on ia64 */ + hlen = (hdr.network[0] & 0x0F) << 2; + l4_proto = hdr.ipv4->protocol; break; case 6: - if (likely((unsigned char *)th - hdr.network == - sizeof(struct ipv6hdr))) { - if (hdr.ipv6->nexthdr != IPPROTO_TCP) - return; - } else { - __be16 frag_off; - u8 l4_hdr; - - ipv6_skip_exthdr(skb, hdr.network - skb->data + - sizeof(struct ipv6hdr), - &l4_hdr, &frag_off); - if (unlikely(frag_off)) - return; - if (l4_hdr != IPPROTO_TCP) - return; - } + hlen = hdr.network - skb->data; + l4_proto = ipv6_find_hdr(skb, &hlen, IPPROTO_TCP, NULL, NULL); + hlen -= hdr.network - skb->data; break; default: return; } - /* skip this packet since it is invalid or the socket is closing */ - if (!th || th->fin) + if (l4_proto != IPPROTO_TCP) + return; + + th = (struct tcphdr *)(hdr.network + hlen); + + /* skip this packet since the socket is closing */ + if (th->fin) return; /* sample on all syn packets or once every atr sample count */ @@ -7682,10 +7667,8 @@ static void ixgbe_atr(struct ixgbe_ring *ring, break; } -#ifdef CONFIG_IXGBE_VXLAN - if (encap) + if (hdr.network != skb_network_header(skb)) input.formatted.flow_type |= IXGBE_ATR_L4TYPE_TUNNEL_MASK; -#endif /* CONFIG_IXGBE_VXLAN */ /* This assumes the Rx queue and Tx queue are bound to the same CPU */ ixgbe_fdir_add_signature_filter_82599(&q_vector->adapter->hw, @@ -8209,10 +8192,17 @@ int ixgbe_setup_tc(struct net_device *dev, u8 tc) static int ixgbe_delete_clsu32(struct ixgbe_adapter *adapter, struct tc_cls_u32_offload *cls) { + u32 uhtid = TC_U32_USERHTID(cls->knode.handle); + u32 loc; int err; + if ((uhtid != 0x800) && (uhtid >= IXGBE_MAX_LINK_HANDLE)) + return -EINVAL; + + loc = cls->knode.handle & 0xfffff; + spin_lock(&adapter->fdir_perfect_lock); - err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, cls->knode.handle); + err = ixgbe_update_ethtool_fdir_entry(adapter, NULL, loc); spin_unlock(&adapter->fdir_perfect_lock); return err; } @@ -8221,20 +8211,30 @@ static int ixgbe_configure_clsu32_add_hnode(struct ixgbe_adapter *adapter, __be16 protocol, struct tc_cls_u32_offload *cls) { + u32 uhtid = TC_U32_USERHTID(cls->hnode.handle); + + if (uhtid >= IXGBE_MAX_LINK_HANDLE) + return -EINVAL; + /* This ixgbe devices do not support hash tables at the moment * so abort when given hash tables. */ if (cls->hnode.divisor > 0) return -EINVAL; - set_bit(TC_U32_USERHTID(cls->hnode.handle), &adapter->tables); + set_bit(uhtid - 1, &adapter->tables); return 0; } static int ixgbe_configure_clsu32_del_hnode(struct ixgbe_adapter *adapter, struct tc_cls_u32_offload *cls) { - clear_bit(TC_U32_USERHTID(cls->hnode.handle), &adapter->tables); + u32 uhtid = TC_U32_USERHTID(cls->hnode.handle); + + if (uhtid >= IXGBE_MAX_LINK_HANDLE) + return -EINVAL; + + clear_bit(uhtid - 1, &adapter->tables); return 0; } @@ -8252,27 +8252,29 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, #endif int i, err = 0; u8 queue; - u32 handle; + u32 uhtid, link_uhtid; memset(&mask, 0, sizeof(union ixgbe_atr_input)); - handle = cls->knode.handle; + uhtid = TC_U32_USERHTID(cls->knode.handle); + link_uhtid = TC_U32_USERHTID(cls->knode.link_handle); - /* At the moment cls_u32 jumps to transport layer and skips past + /* At the moment cls_u32 jumps to network layer and skips past * L2 headers. The canonical method to match L2 frames is to use * negative values. However this is error prone at best but really * just broken because there is no way to "know" what sort of hdr - * is in front of the transport layer. Fix cls_u32 to support L2 + * is in front of the network layer. Fix cls_u32 to support L2 * headers when needed. */ if (protocol != htons(ETH_P_IP)) return -EINVAL; - if (cls->knode.link_handle || - cls->knode.link_handle >= IXGBE_MAX_LINK_HANDLE) { + if (link_uhtid) { struct ixgbe_nexthdr *nexthdr = ixgbe_ipv4_jumps; - u32 uhtid = TC_U32_USERHTID(cls->knode.link_handle); - if (!test_bit(uhtid, &adapter->tables)) + if (link_uhtid >= IXGBE_MAX_LINK_HANDLE) + return -EINVAL; + + if (!test_bit(link_uhtid - 1, &adapter->tables)) return -EINVAL; for (i = 0; nexthdr[i].jump; i++) { @@ -8288,10 +8290,7 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, nexthdr->mask != cls->knode.sel->keys[0].mask) return -EINVAL; - if (uhtid >= IXGBE_MAX_LINK_HANDLE) - return -EINVAL; - - adapter->jump_tables[uhtid] = nexthdr->jump; + adapter->jump_tables[link_uhtid] = nexthdr->jump; } return 0; } @@ -8308,13 +8307,13 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, * To add support for new nodes update ixgbe_model.h parse structures * this function _should_ be generic try not to hardcode values here. */ - if (TC_U32_USERHTID(handle) == 0x800) { + if (uhtid == 0x800) { field_ptr = adapter->jump_tables[0]; } else { - if (TC_U32_USERHTID(handle) >= ARRAY_SIZE(adapter->jump_tables)) + if (uhtid >= IXGBE_MAX_LINK_HANDLE) return -EINVAL; - field_ptr = adapter->jump_tables[TC_U32_USERHTID(handle)]; + field_ptr = adapter->jump_tables[uhtid]; } if (!field_ptr) @@ -8332,8 +8331,7 @@ static int ixgbe_configure_clsu32(struct ixgbe_adapter *adapter, int j; for (j = 0; field_ptr[j].val; j++) { - if (field_ptr[j].off == off && - field_ptr[j].mask == m) { + if (field_ptr[j].off == off) { field_ptr[j].val(input, &mask, val, m); input->filter.formatted.flow_type |= field_ptr[j].type; @@ -8393,8 +8391,8 @@ err_out: return -EINVAL; } -int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto, - struct tc_to_netdev *tc) +static int __ixgbe_setup_tc(struct net_device *dev, u32 handle, __be16 proto, + struct tc_to_netdev *tc) { struct ixgbe_adapter *adapter = netdev_priv(dev); @@ -8554,7 +8552,6 @@ static void ixgbe_add_vxlan_port(struct net_device *dev, sa_family_t sa_family, { struct ixgbe_adapter *adapter = netdev_priv(dev); struct ixgbe_hw *hw = &adapter->hw; - u16 new_port = ntohs(port); if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE)) return; @@ -8562,18 +8559,18 @@ static void ixgbe_add_vxlan_port(struct net_device *dev, sa_family_t sa_family, if (sa_family == AF_INET6) return; - if (adapter->vxlan_port == new_port) + if (adapter->vxlan_port == port) return; if (adapter->vxlan_port) { netdev_info(dev, "Hit Max num of VXLAN ports, not adding port %d\n", - new_port); + ntohs(port)); return; } - adapter->vxlan_port = new_port; - IXGBE_WRITE_REG(hw, IXGBE_VXLANCTRL, new_port); + adapter->vxlan_port = port; + IXGBE_WRITE_REG(hw, IXGBE_VXLANCTRL, ntohs(port)); } /** @@ -8586,7 +8583,6 @@ static void ixgbe_del_vxlan_port(struct net_device *dev, sa_family_t sa_family, __be16 port) { struct ixgbe_adapter *adapter = netdev_priv(dev); - u16 new_port = ntohs(port); if (!(adapter->flags & IXGBE_FLAG_VXLAN_OFFLOAD_CAPABLE)) return; @@ -8594,9 +8590,9 @@ static void ixgbe_del_vxlan_port(struct net_device *dev, sa_family_t sa_family, if (sa_family == AF_INET6) return; - if (adapter->vxlan_port != new_port) { + if (adapter->vxlan_port != port) { netdev_info(dev, "Port %d was not found, not deleting\n", - new_port); + ntohs(port)); return; } @@ -9265,17 +9261,6 @@ skip_sriov: netdev->priv_flags |= IFF_UNICAST_FLT; netdev->priv_flags |= IFF_SUPP_NOFCS; -#ifdef CONFIG_IXGBE_VXLAN - switch (adapter->hw.mac.type) { - case ixgbe_mac_X550: - case ixgbe_mac_X550EM_x: - netdev->hw_enc_features |= NETIF_F_RXCSUM; - break; - default: - break; - } -#endif /* CONFIG_IXGBE_VXLAN */ - #ifdef CONFIG_IXGBE_DCB netdev->dcbnl_ops = &dcbnl_ops; #endif @@ -9329,6 +9314,8 @@ skip_sriov: goto err_sw_init; } + /* Set hw->mac.addr to permanent MAC address */ + ether_addr_copy(hw->mac.addr, hw->mac.perm_addr); ixgbe_mac_set_default_filter(adapter); setup_timer(&adapter->service_timer, &ixgbe_service_timer, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h index ce48872d4782..74c53ad9d268 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_model.h @@ -32,7 +32,6 @@ struct ixgbe_mat_field { unsigned int off; - unsigned int mask; int (*val)(struct ixgbe_fdir_filter *input, union ixgbe_atr_input *mask, u32 val, u32 m); @@ -58,35 +57,27 @@ static inline int ixgbe_mat_prgm_dip(struct ixgbe_fdir_filter *input, } static struct ixgbe_mat_field ixgbe_ipv4_fields[] = { - { .off = 12, .mask = -1, .val = ixgbe_mat_prgm_sip, + { .off = 12, .val = ixgbe_mat_prgm_sip, .type = IXGBE_ATR_FLOW_TYPE_IPV4}, - { .off = 16, .mask = -1, .val = ixgbe_mat_prgm_dip, + { .off = 16, .val = ixgbe_mat_prgm_dip, .type = IXGBE_ATR_FLOW_TYPE_IPV4}, { .val = NULL } /* terminal node */ }; -static inline int ixgbe_mat_prgm_sport(struct ixgbe_fdir_filter *input, +static inline int ixgbe_mat_prgm_ports(struct ixgbe_fdir_filter *input, union ixgbe_atr_input *mask, u32 val, u32 m) { input->filter.formatted.src_port = val & 0xffff; mask->formatted.src_port = m & 0xffff; - return 0; -}; + input->filter.formatted.dst_port = val >> 16; + mask->formatted.dst_port = m >> 16; -static inline int ixgbe_mat_prgm_dport(struct ixgbe_fdir_filter *input, - union ixgbe_atr_input *mask, - u32 val, u32 m) -{ - input->filter.formatted.dst_port = val & 0xffff; - mask->formatted.dst_port = m & 0xffff; return 0; }; static struct ixgbe_mat_field ixgbe_tcp_fields[] = { - {.off = 0, .mask = 0xffff, .val = ixgbe_mat_prgm_sport, - .type = IXGBE_ATR_FLOW_TYPE_TCPV4}, - {.off = 2, .mask = 0xffff, .val = ixgbe_mat_prgm_dport, + {.off = 0, .val = ixgbe_mat_prgm_ports, .type = IXGBE_ATR_FLOW_TYPE_TCPV4}, { .val = NULL } /* terminal node */ }; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 87aca3f7c3de..68a9c646498e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -355,7 +355,7 @@ static s32 ixgbe_iosf_wait(struct ixgbe_hw *hw, u32 *ctrl) command = IXGBE_READ_REG(hw, IXGBE_SB_IOSF_INDIRECT_CTRL); if (!(command & IXGBE_SB_IOSF_CTRL_BUSY)) break; - usleep_range(10, 20); + udelay(10); } if (ctrl) *ctrl = command; diff --git a/drivers/net/ethernet/intel/ixgbevf/ethtool.c b/drivers/net/ethernet/intel/ixgbevf/ethtool.c index c48aef613b0a..d7aa4b203f40 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ethtool.c +++ b/drivers/net/ethernet/intel/ixgbevf/ethtool.c @@ -680,7 +680,7 @@ static void ixgbevf_diag_test(struct net_device *netdev, if (if_running) /* indicate we're in test mode */ - dev_close(netdev); + ixgbevf_close(netdev); else ixgbevf_reset(adapter); @@ -692,7 +692,7 @@ static void ixgbevf_diag_test(struct net_device *netdev, clear_bit(__IXGBEVF_TESTING, &adapter->state); if (if_running) - dev_open(netdev); + ixgbevf_open(netdev); } else { hw_dbg(&adapter->hw, "online testing starting\n"); /* Online tests */ diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h index 68ec7daa04fd..991eeae81473 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h @@ -486,6 +486,8 @@ extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops; extern const char ixgbevf_driver_name[]; extern const char ixgbevf_driver_version[]; +int ixgbevf_open(struct net_device *netdev); +int ixgbevf_close(struct net_device *netdev); void ixgbevf_up(struct ixgbevf_adapter *adapter); void ixgbevf_down(struct ixgbevf_adapter *adapter); void ixgbevf_reinit_locked(struct ixgbevf_adapter *adapter); diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index 0ea14c0a2e74..b0edae94d73d 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c @@ -3122,7 +3122,7 @@ static void ixgbevf_free_all_rx_resources(struct ixgbevf_adapter *adapter) * handler is registered with the OS, the watchdog timer is started, * and the stack is notified that the interface is ready. **/ -static int ixgbevf_open(struct net_device *netdev) +int ixgbevf_open(struct net_device *netdev) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; @@ -3205,7 +3205,7 @@ err_setup_reset: * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed. **/ -static int ixgbevf_close(struct net_device *netdev) +int ixgbevf_close(struct net_device *netdev) { struct ixgbevf_adapter *adapter = netdev_priv(netdev); @@ -3692,19 +3692,23 @@ static int ixgbevf_set_mac(struct net_device *netdev, void *p) struct ixgbevf_adapter *adapter = netdev_priv(netdev); struct ixgbe_hw *hw = &adapter->hw; struct sockaddr *addr = p; + int err; if (!is_valid_ether_addr(addr->sa_data)) return -EADDRNOTAVAIL; - ether_addr_copy(netdev->dev_addr, addr->sa_data); - ether_addr_copy(hw->mac.addr, addr->sa_data); - spin_lock_bh(&adapter->mbx_lock); - hw->mac.ops.set_rar(hw, 0, hw->mac.addr, 0); + err = hw->mac.ops.set_rar(hw, 0, addr->sa_data, 0); spin_unlock_bh(&adapter->mbx_lock); + if (err) + return -EPERM; + + ether_addr_copy(hw->mac.addr, addr->sa_data); + ether_addr_copy(netdev->dev_addr, addr->sa_data); + return 0; } diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c index 61a98f4c5746..4d613a4f2a7f 100644 --- a/drivers/net/ethernet/intel/ixgbevf/vf.c +++ b/drivers/net/ethernet/intel/ixgbevf/vf.c @@ -408,8 +408,10 @@ static s32 ixgbevf_set_rar_vf(struct ixgbe_hw *hw, u32 index, u8 *addr, /* if nacked the address was rejected, use "perm_addr" */ if (!ret_val && - (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_NACK))) + (msgbuf[0] == (IXGBE_VF_SET_MAC_ADDR | IXGBE_VT_MSGTYPE_NACK))) { ixgbevf_get_mac_addr_vf(hw, hw->mac.addr); + return IXGBE_ERR_MBX; + } return ret_val; } diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 577f7ca7deba..7fc490225da5 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -260,7 +260,6 @@ #define MVNETA_VLAN_TAG_LEN 4 -#define MVNETA_CPU_D_CACHE_LINE_SIZE 32 #define MVNETA_TX_CSUM_DEF_SIZE 1600 #define MVNETA_TX_CSUM_MAX_SIZE 9800 #define MVNETA_ACC_MODE_EXT1 1 @@ -300,7 +299,7 @@ #define MVNETA_RX_PKT_SIZE(mtu) \ ALIGN((mtu) + MVNETA_MH_SIZE + MVNETA_VLAN_TAG_LEN + \ ETH_HLEN + ETH_FCS_LEN, \ - MVNETA_CPU_D_CACHE_LINE_SIZE) + cache_line_size()) #define IS_TSO_HEADER(txq, addr) \ ((addr >= txq->tso_hdrs_phys) && \ @@ -2764,9 +2763,6 @@ static int mvneta_rxq_init(struct mvneta_port *pp, if (rxq->descs == NULL) return -ENOMEM; - BUG_ON(rxq->descs != - PTR_ALIGN(rxq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE)); - rxq->last_desc = rxq->size - 1; /* Set Rx descriptors queue starting address */ @@ -2837,10 +2833,6 @@ static int mvneta_txq_init(struct mvneta_port *pp, if (txq->descs == NULL) return -ENOMEM; - /* Make sure descriptor address is cache line size aligned */ - BUG_ON(txq->descs != - PTR_ALIGN(txq->descs, MVNETA_CPU_D_CACHE_LINE_SIZE)); - txq->last_desc = txq->size - 1; /* Set maximum bandwidth for enabled TXQs */ @@ -3050,6 +3042,20 @@ static int mvneta_check_mtu_valid(struct net_device *dev, int mtu) return mtu; } +static void mvneta_percpu_enable(void *arg) +{ + struct mvneta_port *pp = arg; + + enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE); +} + +static void mvneta_percpu_disable(void *arg) +{ + struct mvneta_port *pp = arg; + + disable_percpu_irq(pp->dev->irq); +} + /* Change the device mtu */ static int mvneta_change_mtu(struct net_device *dev, int mtu) { @@ -3074,6 +3080,7 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) * reallocation of the queues */ mvneta_stop_dev(pp); + on_each_cpu(mvneta_percpu_disable, pp, true); mvneta_cleanup_txqs(pp); mvneta_cleanup_rxqs(pp); @@ -3097,6 +3104,7 @@ static int mvneta_change_mtu(struct net_device *dev, int mtu) return ret; } + on_each_cpu(mvneta_percpu_enable, pp, true); mvneta_start_dev(pp); mvneta_port_up(pp); @@ -3250,20 +3258,6 @@ static void mvneta_mdio_remove(struct mvneta_port *pp) pp->phy_dev = NULL; } -static void mvneta_percpu_enable(void *arg) -{ - struct mvneta_port *pp = arg; - - enable_percpu_irq(pp->dev->irq, IRQ_TYPE_NONE); -} - -static void mvneta_percpu_disable(void *arg) -{ - struct mvneta_port *pp = arg; - - disable_percpu_irq(pp->dev->irq); -} - /* Electing a CPU must be done in an atomic way: it should be done * after or before the removal/insertion of a CPU and this function is * not reentrant. diff --git a/drivers/net/ethernet/marvell/mvpp2.c b/drivers/net/ethernet/marvell/mvpp2.c index c797971aefab..868a957f24bb 100644 --- a/drivers/net/ethernet/marvell/mvpp2.c +++ b/drivers/net/ethernet/marvell/mvpp2.c @@ -321,7 +321,6 @@ /* Lbtd 802.3 type */ #define MVPP2_IP_LBDT_TYPE 0xfffa -#define MVPP2_CPU_D_CACHE_LINE_SIZE 32 #define MVPP2_TX_CSUM_MAX_SIZE 9800 /* Timeout constants */ @@ -377,7 +376,7 @@ #define MVPP2_RX_PKT_SIZE(mtu) \ ALIGN((mtu) + MVPP2_MH_SIZE + MVPP2_VLAN_TAG_LEN + \ - ETH_HLEN + ETH_FCS_LEN, MVPP2_CPU_D_CACHE_LINE_SIZE) + ETH_HLEN + ETH_FCS_LEN, cache_line_size()) #define MVPP2_RX_BUF_SIZE(pkt_size) ((pkt_size) + NET_SKB_PAD) #define MVPP2_RX_TOTAL_SIZE(buf_size) ((buf_size) + MVPP2_SKB_SHINFO_SIZE) @@ -4493,10 +4492,6 @@ static int mvpp2_aggr_txq_init(struct platform_device *pdev, if (!aggr_txq->descs) return -ENOMEM; - /* Make sure descriptor address is cache line size aligned */ - BUG_ON(aggr_txq->descs != - PTR_ALIGN(aggr_txq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE)); - aggr_txq->last_desc = aggr_txq->size - 1; /* Aggr TXQ no reset WA */ @@ -4526,9 +4521,6 @@ static int mvpp2_rxq_init(struct mvpp2_port *port, if (!rxq->descs) return -ENOMEM; - BUG_ON(rxq->descs != - PTR_ALIGN(rxq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE)); - rxq->last_desc = rxq->size - 1; /* Zero occupied and non-occupied counters - direct access */ @@ -4616,10 +4608,6 @@ static int mvpp2_txq_init(struct mvpp2_port *port, if (!txq->descs) return -ENOMEM; - /* Make sure descriptor address is cache line size aligned */ - BUG_ON(txq->descs != - PTR_ALIGN(txq->descs, MVPP2_CPU_D_CACHE_LINE_SIZE)); - txq->last_desc = txq->size - 1; /* Set Tx descriptors queue starting address - indirect access */ @@ -6059,8 +6047,10 @@ static int mvpp2_port_init(struct mvpp2_port *port) /* Map physical Rx queue to port's logical Rx queue */ rxq = devm_kzalloc(dev, sizeof(*rxq), GFP_KERNEL); - if (!rxq) + if (!rxq) { + err = -ENOMEM; goto err_free_percpu; + } /* Map this Rx queue to a physical queue */ rxq->id = port->first_rxq + queue; rxq->port = port->id; diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index ffd0accc2ec9..2017b0121f5f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -2750,7 +2750,7 @@ void qed_int_igu_enable_int(struct qed_hwfn *p_hwfn, int qed_int_igu_enable(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, enum qed_int_mode int_mode) { - int rc; + int rc = 0; /* Configure AEU signal change to produce attentions */ qed_wr(p_hwfn, p_ptt, IGU_REG_ATTENTION_ENABLE, 0); diff --git a/drivers/net/ethernet/qlogic/qlge/qlge.h b/drivers/net/ethernet/qlogic/qlge/qlge.h index ef332708e5f2..6d31f92ef2b6 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge.h +++ b/drivers/net/ethernet/qlogic/qlge/qlge.h @@ -18,7 +18,7 @@ */ #define DRV_NAME "qlge" #define DRV_STRING "QLogic 10 Gigabit PCI-E Ethernet Driver " -#define DRV_VERSION "1.00.00.34" +#define DRV_VERSION "1.00.00.35" #define WQ_ADDR_ALIGN 0x3 /* 4 byte alignment */ diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index 4e1a7dba7c4a..087e14a3fba7 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1377,11 +1377,11 @@ static netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev) /* TAG and timestamp required flag */ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - skb_tx_timestamp(skb); desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR; desc->ds_tagl |= le16_to_cpu(ts_skb->tag << 12); } + skb_tx_timestamp(skb); /* Descriptor type must be set after all the above writes */ dma_wmb(); desc->die_dt = DT_FEND; diff --git a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c index b02eed12bfc5..73427e29df2a 100644 --- a/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c +++ b/drivers/net/ethernet/samsung/sxgbe/sxgbe_platform.c @@ -155,11 +155,11 @@ static int sxgbe_platform_probe(struct platform_device *pdev) return 0; err_rx_irq_unmap: - while (--i) + while (i--) irq_dispose_mapping(priv->rxq[i]->irq_no); i = SXGBE_TX_QUEUES; err_tx_irq_unmap: - while (--i) + while (i--) irq_dispose_mapping(priv->txq[i]->irq_no); irq_dispose_mapping(priv->irq); err_drv_remove: diff --git a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c index e13228f115f0..011386f6f24d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/norm_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/norm_desc.c @@ -199,11 +199,6 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, { unsigned int tdes1 = p->des1; - if (mode == STMMAC_CHAIN_MODE) - norm_set_tx_desc_len_on_chain(p, len); - else - norm_set_tx_desc_len_on_ring(p, len); - if (is_fs) tdes1 |= TDES1_FIRST_SEGMENT; else @@ -217,10 +212,15 @@ static void ndesc_prepare_tx_desc(struct dma_desc *p, int is_fs, int len, if (ls) tdes1 |= TDES1_LAST_SEGMENT; - if (tx_own) - tdes1 |= TDES0_OWN; - p->des1 = tdes1; + + if (mode == STMMAC_CHAIN_MODE) + norm_set_tx_desc_len_on_chain(p, len); + else + norm_set_tx_desc_len_on_ring(p, len); + + if (tx_own) + p->des0 |= TDES0_OWN; } static void ndesc_set_tx_ic(struct dma_desc *p) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 4c5ce9848ca9..78464fa7fe1f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -278,7 +278,6 @@ static void stmmac_eee_ctrl_timer(unsigned long arg) */ bool stmmac_eee_init(struct stmmac_priv *priv) { - char *phy_bus_name = priv->plat->phy_bus_name; unsigned long flags; bool ret = false; @@ -290,7 +289,7 @@ bool stmmac_eee_init(struct stmmac_priv *priv) goto out; /* Never init EEE in case of a switch is attached */ - if (phy_bus_name && (!strcmp(phy_bus_name, "fixed"))) + if (priv->phydev->is_pseudo_fixed_link) goto out; /* MAC core supports the EEE feature. */ @@ -827,12 +826,8 @@ static int stmmac_init_phy(struct net_device *dev) phydev = of_phy_connect(dev, priv->plat->phy_node, &stmmac_adjust_link, 0, interface); } else { - if (priv->plat->phy_bus_name) - snprintf(bus_id, MII_BUS_ID_SIZE, "%s-%x", - priv->plat->phy_bus_name, priv->plat->bus_id); - else - snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", - priv->plat->bus_id); + snprintf(bus_id, MII_BUS_ID_SIZE, "stmmac-%x", + priv->plat->bus_id); snprintf(phy_id_fmt, MII_BUS_ID_SIZE + 3, PHY_ID_FMT, bus_id, priv->plat->phy_addr); @@ -871,9 +866,8 @@ static int stmmac_init_phy(struct net_device *dev) } /* If attached to a switch, there is no reason to poll phy handler */ - if (priv->plat->phy_bus_name) - if (!strcmp(priv->plat->phy_bus_name, "fixed")) - phydev->irq = PHY_IGNORE_INTERRUPT; + if (phydev->is_pseudo_fixed_link) + phydev->irq = PHY_IGNORE_INTERRUPT; pr_debug("stmmac_init_phy: %s: attached to PHY (UID 0x%x)" " Link = %d\n", dev->name, phydev->phy_id, phydev->link); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index ea76129dafc2..06704ca6f9ca 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -198,20 +198,12 @@ int stmmac_mdio_register(struct net_device *ndev) struct mii_bus *new_bus; struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data; - int addr, found; struct device_node *mdio_node = priv->plat->mdio_node; + int addr, found; if (!mdio_bus_data) return 0; - if (IS_ENABLED(CONFIG_OF)) { - if (mdio_node) { - netdev_dbg(ndev, "FOUND MDIO subnode\n"); - } else { - netdev_warn(ndev, "No MDIO subnode found\n"); - } - } - new_bus = mdiobus_alloc(); if (new_bus == NULL) return -ENOMEM; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c index dcbd2a1601e8..cf37ea558ecc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c @@ -132,6 +132,69 @@ static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev) } /** + * stmmac_dt_phy - parse device-tree driver parameters to allocate PHY resources + * @plat: driver data platform structure + * @np: device tree node + * @dev: device pointer + * Description: + * The mdio bus will be allocated in case of a phy transceiver is on board; + * it will be NULL if the fixed-link is configured. + * If there is the "snps,dwmac-mdio" sub-node the mdio will be allocated + * in any case (for DSA, mdio must be registered even if fixed-link). + * The table below sums the supported configurations: + * ------------------------------- + * snps,phy-addr | Y + * ------------------------------- + * phy-handle | Y + * ------------------------------- + * fixed-link | N + * ------------------------------- + * snps,dwmac-mdio | + * even if | Y + * fixed-link | + * ------------------------------- + * + * It returns 0 in case of success otherwise -ENODEV. + */ +static int stmmac_dt_phy(struct plat_stmmacenet_data *plat, + struct device_node *np, struct device *dev) +{ + bool mdio = true; + + /* If phy-handle property is passed from DT, use it as the PHY */ + plat->phy_node = of_parse_phandle(np, "phy-handle", 0); + if (plat->phy_node) + dev_dbg(dev, "Found phy-handle subnode\n"); + + /* If phy-handle is not specified, check if we have a fixed-phy */ + if (!plat->phy_node && of_phy_is_fixed_link(np)) { + if ((of_phy_register_fixed_link(np) < 0)) + return -ENODEV; + + dev_dbg(dev, "Found fixed-link subnode\n"); + plat->phy_node = of_node_get(np); + mdio = false; + } + + /* If snps,dwmac-mdio is passed from DT, always register the MDIO */ + for_each_child_of_node(np, plat->mdio_node) { + if (of_device_is_compatible(plat->mdio_node, "snps,dwmac-mdio")) + break; + } + + if (plat->mdio_node) { + dev_dbg(dev, "Found MDIO subnode\n"); + mdio = true; + } + + if (mdio) + plat->mdio_bus_data = + devm_kzalloc(dev, sizeof(struct stmmac_mdio_bus_data), + GFP_KERNEL); + return 0; +} + +/** * stmmac_probe_config_dt - parse device-tree driver parameters * @pdev: platform_device structure * @plat: driver data platform structure @@ -146,7 +209,6 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) struct device_node *np = pdev->dev.of_node; struct plat_stmmacenet_data *plat; struct stmmac_dma_cfg *dma_cfg; - struct device_node *child_node = NULL; plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); if (!plat) @@ -166,36 +228,15 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) /* Default to phy auto-detection */ plat->phy_addr = -1; - /* If we find a phy-handle property, use it as the PHY */ - plat->phy_node = of_parse_phandle(np, "phy-handle", 0); - - /* If phy-handle is not specified, check if we have a fixed-phy */ - if (!plat->phy_node && of_phy_is_fixed_link(np)) { - if ((of_phy_register_fixed_link(np) < 0)) - return ERR_PTR(-ENODEV); - - plat->phy_node = of_node_get(np); - } - - for_each_child_of_node(np, child_node) - if (of_device_is_compatible(child_node, "snps,dwmac-mdio")) { - plat->mdio_node = child_node; - break; - } - /* "snps,phy-addr" is not a standard property. Mark it as deprecated * and warn of its use. Remove this when phy node support is added. */ if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); - if ((plat->phy_node && !of_phy_is_fixed_link(np)) || !plat->mdio_node) - plat->mdio_bus_data = NULL; - else - plat->mdio_bus_data = - devm_kzalloc(&pdev->dev, - sizeof(struct stmmac_mdio_bus_data), - GFP_KERNEL); + /* To Configure PHY by using all device-tree supported properties */ + if (stmmac_dt_phy(plat, np, &pdev->dev)) + return ERR_PTR(-ENODEV); of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size); diff --git a/drivers/net/phy/bcm7xxx.c b/drivers/net/phy/bcm7xxx.c index b881a7b1e4f6..9636da0b6efc 100644 --- a/drivers/net/phy/bcm7xxx.c +++ b/drivers/net/phy/bcm7xxx.c @@ -339,6 +339,8 @@ static struct phy_driver bcm7xxx_driver[] = { BCM7XXX_28NM_GPHY(PHY_ID_BCM7439, "Broadcom BCM7439"), BCM7XXX_28NM_GPHY(PHY_ID_BCM7439_2, "Broadcom BCM7439 (2)"), BCM7XXX_28NM_GPHY(PHY_ID_BCM7445, "Broadcom BCM7445"), + BCM7XXX_40NM_EPHY(PHY_ID_BCM7346, "Broadcom BCM7346"), + BCM7XXX_40NM_EPHY(PHY_ID_BCM7362, "Broadcom BCM7362"), BCM7XXX_40NM_EPHY(PHY_ID_BCM7425, "Broadcom BCM7425"), BCM7XXX_40NM_EPHY(PHY_ID_BCM7429, "Broadcom BCM7429"), BCM7XXX_40NM_EPHY(PHY_ID_BCM7435, "Broadcom BCM7435"), @@ -348,6 +350,8 @@ static struct mdio_device_id __maybe_unused bcm7xxx_tbl[] = { { PHY_ID_BCM7250, 0xfffffff0, }, { PHY_ID_BCM7364, 0xfffffff0, }, { PHY_ID_BCM7366, 0xfffffff0, }, + { PHY_ID_BCM7346, 0xfffffff0, }, + { PHY_ID_BCM7362, 0xfffffff0, }, { PHY_ID_BCM7425, 0xfffffff0, }, { PHY_ID_BCM7429, 0xfffffff0, }, { PHY_ID_BCM7439, 0xfffffff0, }, diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 26c64d2782fa..a0f64cba86ba 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -1198,6 +1198,9 @@ static int team_port_add(struct team *team, struct net_device *port_dev) goto err_dev_open; } + dev_uc_sync_multiple(port_dev, dev); + dev_mc_sync_multiple(port_dev, dev); + err = vlan_vids_add_by_dev(port_dev, dev); if (err) { netdev_err(dev, "Failed to add vlan ids to device %s\n", @@ -1261,6 +1264,8 @@ err_enable_netpoll: vlan_vids_del_by_dev(port_dev, dev); err_vids_add: + dev_uc_unsync(port_dev, dev); + dev_mc_unsync(port_dev, dev); dev_close(port_dev); err_dev_open: diff --git a/drivers/net/tun.c b/drivers/net/tun.c index afdf950617c3..510e90a6bb26 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -622,7 +622,8 @@ static int tun_attach(struct tun_struct *tun, struct file *file, bool skip_filte /* Re-attach the filter to persist device */ if (!skip_filter && (tun->filter_attached == true)) { - err = sk_attach_filter(&tun->fprog, tfile->socket.sk); + err = __sk_attach_filter(&tun->fprog, tfile->socket.sk, + lockdep_rtnl_is_held()); if (!err) goto out; } @@ -1822,7 +1823,7 @@ static void tun_detach_filter(struct tun_struct *tun, int n) for (i = 0; i < n; i++) { tfile = rtnl_dereference(tun->tfiles[i]); - sk_detach_filter(tfile->socket.sk); + __sk_detach_filter(tfile->socket.sk, lockdep_rtnl_is_held()); } tun->filter_attached = false; @@ -1835,7 +1836,8 @@ static int tun_attach_filter(struct tun_struct *tun) for (i = 0; i < tun->numqueues; i++) { tfile = rtnl_dereference(tun->tfiles[i]); - ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); + ret = __sk_attach_filter(&tun->fprog, tfile->socket.sk, + lockdep_rtnl_is_held()); if (ret) { tun_detach_filter(tun, i); return ret; diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 86ba30ba35e8..2fb31edab125 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1626,6 +1626,13 @@ static const struct usb_device_id cdc_devs[] = { .driver_info = (unsigned long) &wwan_info, }, + /* Telit LE910 V2 */ + { USB_DEVICE_AND_INTERFACE_INFO(0x1bc7, 0x0036, + USB_CLASS_COMM, + USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long)&wwan_noarp_info, + }, + /* DW5812 LTE Verizon Mobile Broadband Card * Unlike DW5550 this device requires FLAG_NOARP */ diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 1bfe0fcaccf5..22e1a9a99a7d 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -38,7 +38,7 @@ * HEADS UP: this handshaking isn't all that robust. This driver * gets confused easily if you unplug one end of the cable then * try to connect it again; you'll need to restart both ends. The - * "naplink" software (used by some PlayStation/2 deveopers) does + * "naplink" software (used by some PlayStation/2 developers) does * the handshaking much better! Also, sometimes this hardware * seems to get wedged under load. Prolific docs are weak, and * don't identify differences between PL2301 and PL2302, much less diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 7d717c66bcb0..9d1fce8a6e84 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c @@ -844,6 +844,7 @@ static const struct usb_device_id products[] = { {QMI_FIXED_INTF(0x19d2, 0x1426, 2)}, /* ZTE MF91 */ {QMI_FIXED_INTF(0x19d2, 0x1428, 2)}, /* Telewell TW-LTE 4G v2 */ {QMI_FIXED_INTF(0x19d2, 0x2002, 4)}, /* ZTE (Vodafone) K3765-Z */ + {QMI_FIXED_INTF(0x2001, 0x7e19, 4)}, /* D-Link DWM-221 B1 */ {QMI_FIXED_INTF(0x0f3d, 0x68a2, 8)}, /* Sierra Wireless MC7700 */ {QMI_FIXED_INTF(0x114f, 0x68a2, 8)}, /* Sierra Wireless MC7750 */ {QMI_FIXED_INTF(0x1199, 0x68a2, 8)}, /* Sierra Wireless MC7710 in QMI mode */ diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index ca5721c306bb..cc31c6f1f88e 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -99,7 +99,7 @@ static int pmem_do_bvec(struct pmem_device *pmem, struct page *page, if (unlikely(bad_pmem)) rc = -EIO; else { - memcpy_from_pmem(mem + off, pmem_addr, len); + rc = memcpy_from_pmem(mem + off, pmem_addr, len); flush_dcache_page(page); } } else { @@ -295,7 +295,7 @@ static int pmem_rw_bytes(struct nd_namespace_common *ndns, if (unlikely(is_bad_pmem(&pmem->bb, offset / 512, sz_align))) return -EIO; - memcpy_from_pmem(buf, pmem->virt_addr + offset, size); + return memcpy_from_pmem(buf, pmem->virt_addr + offset, size); } else { memcpy_to_pmem(pmem->virt_addr + offset, buf, size); wmb_pmem(); diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c index 9973cebb4d6f..07462d79d040 100644 --- a/drivers/platform/goldfish/goldfish_pipe.c +++ b/drivers/platform/goldfish/goldfish_pipe.c @@ -309,8 +309,7 @@ static ssize_t goldfish_pipe_read_write(struct file *filp, char __user *buffer, * much memory to the process. */ down_read(¤t->mm->mmap_sem); - ret = get_user_pages(current, current->mm, address, 1, - !is_write, 0, &page, NULL); + ret = get_user_pages(address, 1, !is_write, 0, &page, NULL); up_read(¤t->mm->mmap_sem); if (ret < 0) break; diff --git a/drivers/rapidio/devices/rio_mport_cdev.c b/drivers/rapidio/devices/rio_mport_cdev.c index 9607bc826460..5d4d91846357 100644 --- a/drivers/rapidio/devices/rio_mport_cdev.c +++ b/drivers/rapidio/devices/rio_mport_cdev.c @@ -886,7 +886,7 @@ rio_dma_transfer(struct file *filp, uint32_t transfer_mode, } down_read(¤t->mm->mmap_sem); - pinned = get_user_pages(current, current->mm, + pinned = get_user_pages( (unsigned long)xfer->loc_addr & PAGE_MASK, nr_pages, dir == DMA_FROM_DEVICE, 0, page_list, NULL); diff --git a/drivers/remoteproc/st_remoteproc.c b/drivers/remoteproc/st_remoteproc.c index 6bb04d453247..6f056caa8a56 100644 --- a/drivers/remoteproc/st_remoteproc.c +++ b/drivers/remoteproc/st_remoteproc.c @@ -189,9 +189,9 @@ static int st_rproc_parse_dt(struct platform_device *pdev) } ddata->boot_base = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); - if (!ddata->boot_base) { + if (IS_ERR(ddata->boot_base)) { dev_err(dev, "Boot base not found\n"); - return -EINVAL; + return PTR_ERR(ddata->boot_base); } err = of_property_read_u32_index(np, "st,syscfg", 1, diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 17ad5749e91d..1e560188dd13 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c @@ -317,17 +317,17 @@ static int _add_device_to_lcu(struct alias_lcu *lcu, struct alias_pav_group *group; struct dasd_uid uid; + spin_lock(get_ccwdev_lock(device->cdev)); private->uid.type = lcu->uac->unit[private->uid.real_unit_addr].ua_type; private->uid.base_unit_addr = lcu->uac->unit[private->uid.real_unit_addr].base_ua; uid = private->uid; - + spin_unlock(get_ccwdev_lock(device->cdev)); /* if we have no PAV anyway, we don't need to bother with PAV groups */ if (lcu->pav == NO_PAV) { list_move(&device->alias_list, &lcu->active_devices); return 0; } - group = _find_group(lcu, &uid); if (!group) { group = kzalloc(sizeof(*group), GFP_ATOMIC); @@ -397,130 +397,6 @@ suborder_not_supported(struct dasd_ccw_req *cqr) return 0; } -/* - * This function tries to lock all devices on an lcu via trylock - * return NULL on success otherwise return first failed device - */ -static struct dasd_device *_trylock_all_devices_on_lcu(struct alias_lcu *lcu, - struct dasd_device *pos) - -{ - struct alias_pav_group *pavgroup; - struct dasd_device *device; - - list_for_each_entry(device, &lcu->active_devices, alias_list) { - if (device == pos) - continue; - if (!spin_trylock(get_ccwdev_lock(device->cdev))) - return device; - } - list_for_each_entry(device, &lcu->inactive_devices, alias_list) { - if (device == pos) - continue; - if (!spin_trylock(get_ccwdev_lock(device->cdev))) - return device; - } - list_for_each_entry(pavgroup, &lcu->grouplist, group) { - list_for_each_entry(device, &pavgroup->baselist, alias_list) { - if (device == pos) - continue; - if (!spin_trylock(get_ccwdev_lock(device->cdev))) - return device; - } - list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { - if (device == pos) - continue; - if (!spin_trylock(get_ccwdev_lock(device->cdev))) - return device; - } - } - return NULL; -} - -/* - * unlock all devices except the one that is specified as pos - * stop if enddev is specified and reached - */ -static void _unlock_all_devices_on_lcu(struct alias_lcu *lcu, - struct dasd_device *pos, - struct dasd_device *enddev) - -{ - struct alias_pav_group *pavgroup; - struct dasd_device *device; - - list_for_each_entry(device, &lcu->active_devices, alias_list) { - if (device == pos) - continue; - if (device == enddev) - return; - spin_unlock(get_ccwdev_lock(device->cdev)); - } - list_for_each_entry(device, &lcu->inactive_devices, alias_list) { - if (device == pos) - continue; - if (device == enddev) - return; - spin_unlock(get_ccwdev_lock(device->cdev)); - } - list_for_each_entry(pavgroup, &lcu->grouplist, group) { - list_for_each_entry(device, &pavgroup->baselist, alias_list) { - if (device == pos) - continue; - if (device == enddev) - return; - spin_unlock(get_ccwdev_lock(device->cdev)); - } - list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { - if (device == pos) - continue; - if (device == enddev) - return; - spin_unlock(get_ccwdev_lock(device->cdev)); - } - } -} - -/* - * this function is needed because the locking order - * device lock -> lcu lock - * needs to be assured when iterating over devices in an LCU - * - * if a device is specified in pos then the device lock is already hold - */ -static void _trylock_and_lock_lcu_irqsave(struct alias_lcu *lcu, - struct dasd_device *pos, - unsigned long *flags) -{ - struct dasd_device *failed; - - do { - spin_lock_irqsave(&lcu->lock, *flags); - failed = _trylock_all_devices_on_lcu(lcu, pos); - if (failed) { - _unlock_all_devices_on_lcu(lcu, pos, failed); - spin_unlock_irqrestore(&lcu->lock, *flags); - cpu_relax(); - } - } while (failed); -} - -static void _trylock_and_lock_lcu(struct alias_lcu *lcu, - struct dasd_device *pos) -{ - struct dasd_device *failed; - - do { - spin_lock(&lcu->lock); - failed = _trylock_all_devices_on_lcu(lcu, pos); - if (failed) { - _unlock_all_devices_on_lcu(lcu, pos, failed); - spin_unlock(&lcu->lock); - cpu_relax(); - } - } while (failed); -} - static int read_unit_address_configuration(struct dasd_device *device, struct alias_lcu *lcu) { @@ -615,7 +491,7 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) if (rc) return rc; - _trylock_and_lock_lcu_irqsave(lcu, NULL, &flags); + spin_lock_irqsave(&lcu->lock, flags); lcu->pav = NO_PAV; for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { switch (lcu->uac->unit[i].ua_type) { @@ -634,7 +510,6 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) alias_list) { _add_device_to_lcu(lcu, device, refdev); } - _unlock_all_devices_on_lcu(lcu, NULL, NULL); spin_unlock_irqrestore(&lcu->lock, flags); return 0; } @@ -722,8 +597,7 @@ int dasd_alias_add_device(struct dasd_device *device) lcu = private->lcu; rc = 0; - spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); - spin_lock(&lcu->lock); + spin_lock_irqsave(&lcu->lock, flags); if (!(lcu->flags & UPDATE_PENDING)) { rc = _add_device_to_lcu(lcu, device, device); if (rc) @@ -733,8 +607,7 @@ int dasd_alias_add_device(struct dasd_device *device) list_move(&device->alias_list, &lcu->active_devices); _schedule_lcu_update(lcu, device); } - spin_unlock(&lcu->lock); - spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); + spin_unlock_irqrestore(&lcu->lock, flags); return rc; } @@ -933,15 +806,27 @@ static void _stop_all_devices_on_lcu(struct alias_lcu *lcu) struct alias_pav_group *pavgroup; struct dasd_device *device; - list_for_each_entry(device, &lcu->active_devices, alias_list) + list_for_each_entry(device, &lcu->active_devices, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_set_stop_bits(device, DASD_STOPPED_SU); - list_for_each_entry(device, &lcu->inactive_devices, alias_list) + spin_unlock(get_ccwdev_lock(device->cdev)); + } + list_for_each_entry(device, &lcu->inactive_devices, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_set_stop_bits(device, DASD_STOPPED_SU); + spin_unlock(get_ccwdev_lock(device->cdev)); + } list_for_each_entry(pavgroup, &lcu->grouplist, group) { - list_for_each_entry(device, &pavgroup->baselist, alias_list) + list_for_each_entry(device, &pavgroup->baselist, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_set_stop_bits(device, DASD_STOPPED_SU); - list_for_each_entry(device, &pavgroup->aliaslist, alias_list) + spin_unlock(get_ccwdev_lock(device->cdev)); + } + list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_set_stop_bits(device, DASD_STOPPED_SU); + spin_unlock(get_ccwdev_lock(device->cdev)); + } } } @@ -950,15 +835,27 @@ static void _unstop_all_devices_on_lcu(struct alias_lcu *lcu) struct alias_pav_group *pavgroup; struct dasd_device *device; - list_for_each_entry(device, &lcu->active_devices, alias_list) + list_for_each_entry(device, &lcu->active_devices, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); - list_for_each_entry(device, &lcu->inactive_devices, alias_list) + spin_unlock(get_ccwdev_lock(device->cdev)); + } + list_for_each_entry(device, &lcu->inactive_devices, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); + spin_unlock(get_ccwdev_lock(device->cdev)); + } list_for_each_entry(pavgroup, &lcu->grouplist, group) { - list_for_each_entry(device, &pavgroup->baselist, alias_list) + list_for_each_entry(device, &pavgroup->baselist, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); - list_for_each_entry(device, &pavgroup->aliaslist, alias_list) + spin_unlock(get_ccwdev_lock(device->cdev)); + } + list_for_each_entry(device, &pavgroup->aliaslist, alias_list) { + spin_lock(get_ccwdev_lock(device->cdev)); dasd_device_remove_stop_bits(device, DASD_STOPPED_SU); + spin_unlock(get_ccwdev_lock(device->cdev)); + } } } @@ -984,48 +881,32 @@ static void summary_unit_check_handling_work(struct work_struct *work) spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); reset_summary_unit_check(lcu, device, suc_data->reason); - _trylock_and_lock_lcu_irqsave(lcu, NULL, &flags); + spin_lock_irqsave(&lcu->lock, flags); _unstop_all_devices_on_lcu(lcu); _restart_all_base_devices_on_lcu(lcu); /* 3. read new alias configuration */ _schedule_lcu_update(lcu, device); lcu->suc_data.device = NULL; dasd_put_device(device); - _unlock_all_devices_on_lcu(lcu, NULL, NULL); spin_unlock_irqrestore(&lcu->lock, flags); } -/* - * note: this will be called from int handler context (cdev locked) - */ -void dasd_alias_handle_summary_unit_check(struct dasd_device *device, - struct irb *irb) +void dasd_alias_handle_summary_unit_check(struct work_struct *work) { + struct dasd_device *device = container_of(work, struct dasd_device, + suc_work); struct dasd_eckd_private *private = device->private; struct alias_lcu *lcu; - char reason; - char *sense; - - sense = dasd_get_sense(irb); - if (sense) { - reason = sense[8]; - DBF_DEV_EVENT(DBF_NOTICE, device, "%s %x", - "eckd handle summary unit check: reason", reason); - } else { - DBF_DEV_EVENT(DBF_WARNING, device, "%s", - "eckd handle summary unit check:" - " no reason code available"); - return; - } + unsigned long flags; lcu = private->lcu; if (!lcu) { DBF_DEV_EVENT(DBF_WARNING, device, "%s", "device not ready to handle summary" " unit check (no lcu structure)"); - return; + goto out; } - _trylock_and_lock_lcu(lcu, device); + spin_lock_irqsave(&lcu->lock, flags); /* If this device is about to be removed just return and wait for * the next interrupt on a different device */ @@ -1033,27 +914,26 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *device, DBF_DEV_EVENT(DBF_WARNING, device, "%s", "device is in offline processing," " don't do summary unit check handling"); - _unlock_all_devices_on_lcu(lcu, device, NULL); - spin_unlock(&lcu->lock); - return; + goto out_unlock; } if (lcu->suc_data.device) { /* already scheduled or running */ DBF_DEV_EVENT(DBF_WARNING, device, "%s", "previous instance of summary unit check worker" " still pending"); - _unlock_all_devices_on_lcu(lcu, device, NULL); - spin_unlock(&lcu->lock); - return ; + goto out_unlock; } _stop_all_devices_on_lcu(lcu); /* prepare for lcu_update */ - private->lcu->flags |= NEED_UAC_UPDATE | UPDATE_PENDING; - lcu->suc_data.reason = reason; + lcu->flags |= NEED_UAC_UPDATE | UPDATE_PENDING; + lcu->suc_data.reason = private->suc_reason; lcu->suc_data.device = device; dasd_get_device(device); - _unlock_all_devices_on_lcu(lcu, device, NULL); - spin_unlock(&lcu->lock); if (!schedule_work(&lcu->suc_data.worker)) dasd_put_device(device); +out_unlock: + spin_unlock_irqrestore(&lcu->lock, flags); +out: + clear_bit(DASD_FLAG_SUC, &device->flags); + dasd_put_device(device); }; diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 75c032dcf173..c1b4ae55e129 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c @@ -1682,6 +1682,8 @@ dasd_eckd_check_characteristics(struct dasd_device *device) /* setup work queue for validate server*/ INIT_WORK(&device->kick_validate, dasd_eckd_do_validate_server); + /* setup work queue for summary unit check */ + INIT_WORK(&device->suc_work, dasd_alias_handle_summary_unit_check); if (!ccw_device_is_pathgroup(device->cdev)) { dev_warn(&device->cdev->dev, @@ -2549,14 +2551,6 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device, device->state == DASD_STATE_ONLINE && !test_bit(DASD_FLAG_OFFLINE, &device->flags) && !test_bit(DASD_FLAG_SUSPENDED, &device->flags)) { - /* - * the state change could be caused by an alias - * reassignment remove device from alias handling - * to prevent new requests from being scheduled on - * the wrong alias device - */ - dasd_alias_remove_device(device); - /* schedule worker to reload device */ dasd_reload_device(device); } @@ -2571,7 +2565,27 @@ static void dasd_eckd_check_for_device_change(struct dasd_device *device, /* summary unit check */ if ((sense[27] & DASD_SENSE_BIT_0) && (sense[7] == 0x0D) && (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) { - dasd_alias_handle_summary_unit_check(device, irb); + if (test_and_set_bit(DASD_FLAG_SUC, &device->flags)) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "eckd suc: device already notified"); + return; + } + sense = dasd_get_sense(irb); + if (!sense) { + DBF_DEV_EVENT(DBF_WARNING, device, "%s", + "eckd suc: no reason code available"); + clear_bit(DASD_FLAG_SUC, &device->flags); + return; + + } + private->suc_reason = sense[8]; + DBF_DEV_EVENT(DBF_NOTICE, device, "%s %x", + "eckd handle summary unit check: reason", + private->suc_reason); + dasd_get_device(device); + if (!schedule_work(&device->suc_work)) + dasd_put_device(device); + return; } @@ -4495,6 +4509,12 @@ static int dasd_eckd_reload_device(struct dasd_device *device) struct dasd_uid uid; unsigned long flags; + /* + * remove device from alias handling to prevent new requests + * from being scheduled on the wrong alias device + */ + dasd_alias_remove_device(device); + spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); old_base = private->uid.base_unit_addr; spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index f8f91ee652d3..6d9a6d3517cd 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -525,6 +525,7 @@ struct dasd_eckd_private { int count; u32 fcx_max_data; + char suc_reason; }; @@ -534,7 +535,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *); int dasd_alias_add_device(struct dasd_device *); int dasd_alias_remove_device(struct dasd_device *); struct dasd_device *dasd_alias_get_start_dev(struct dasd_device *); -void dasd_alias_handle_summary_unit_check(struct dasd_device *, struct irb *); +void dasd_alias_handle_summary_unit_check(struct work_struct *); void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); void dasd_alias_lcu_setup_complete(struct dasd_device *); void dasd_alias_wait_for_lcu_setup(struct dasd_device *); diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index 8de29be32a56..0f0add932e7a 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h @@ -470,6 +470,7 @@ struct dasd_device { struct work_struct restore_device; struct work_struct reload_device; struct work_struct kick_validate; + struct work_struct suc_work; struct timer_list timer; debug_info_t *debug_area; @@ -542,6 +543,7 @@ struct dasd_attention_data { #define DASD_FLAG_SAFE_OFFLINE_RUNNING 11 /* safe offline running */ #define DASD_FLAG_ABORTALL 12 /* Abort all noretry requests */ #define DASD_FLAG_PATH_VERIFY 13 /* Path verification worker running */ +#define DASD_FLAG_SUC 14 /* unhandled summary unit check */ #define DASD_SLEEPON_START_TAG ((void *) 1) #define DASD_SLEEPON_END_TAG ((void *) 2) diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c index a24443ba59ea..97e5b69e0668 100644 --- a/drivers/target/iscsi/iscsi_target_configfs.c +++ b/drivers/target/iscsi/iscsi_target_configfs.c @@ -779,14 +779,6 @@ static int lio_target_init_nodeacl(struct se_node_acl *se_nacl, return 0; } -static void lio_target_cleanup_nodeacl( struct se_node_acl *se_nacl) -{ - struct iscsi_node_acl *acl = container_of(se_nacl, - struct iscsi_node_acl, se_node_acl); - - configfs_remove_default_groups(&acl->se_node_acl.acl_fabric_stat_group); -} - /* End items for lio_target_acl_cit */ /* Start items for lio_target_tpg_attrib_cit */ @@ -1247,6 +1239,16 @@ static struct se_wwn *lio_target_call_coreaddtiqn( if (IS_ERR(tiqn)) return ERR_CAST(tiqn); + pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n", tiqn->tiqn); + pr_debug("LIO_Target_ConfigFS: REGISTER -> Allocated Node:" + " %s\n", name); + return &tiqn->tiqn_wwn; +} + +static void lio_target_add_wwn_groups(struct se_wwn *wwn) +{ + struct iscsi_tiqn *tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn); + config_group_init_type_name(&tiqn->tiqn_stat_grps.iscsi_instance_group, "iscsi_instance", &iscsi_stat_instance_cit); configfs_add_default_group(&tiqn->tiqn_stat_grps.iscsi_instance_group, @@ -1271,12 +1273,6 @@ static struct se_wwn *lio_target_call_coreaddtiqn( "iscsi_logout_stats", &iscsi_stat_logout_cit); configfs_add_default_group(&tiqn->tiqn_stat_grps.iscsi_logout_stats_group, &tiqn->tiqn_wwn.fabric_stat_group); - - - pr_debug("LIO_Target_ConfigFS: REGISTER -> %s\n", tiqn->tiqn); - pr_debug("LIO_Target_ConfigFS: REGISTER -> Allocated Node:" - " %s\n", name); - return &tiqn->tiqn_wwn; } static void lio_target_call_coredeltiqn( @@ -1284,8 +1280,6 @@ static void lio_target_call_coredeltiqn( { struct iscsi_tiqn *tiqn = container_of(wwn, struct iscsi_tiqn, tiqn_wwn); - configfs_remove_default_groups(&tiqn->tiqn_wwn.fabric_stat_group); - pr_debug("LIO_Target_ConfigFS: DEREGISTER -> %s\n", tiqn->tiqn); iscsit_del_tiqn(tiqn); @@ -1660,12 +1654,12 @@ const struct target_core_fabric_ops iscsi_ops = { .aborted_task = lio_aborted_task, .fabric_make_wwn = lio_target_call_coreaddtiqn, .fabric_drop_wwn = lio_target_call_coredeltiqn, + .add_wwn_groups = lio_target_add_wwn_groups, .fabric_make_tpg = lio_target_tiqn_addtpg, .fabric_drop_tpg = lio_target_tiqn_deltpg, .fabric_make_np = lio_target_call_addnptotpg, .fabric_drop_np = lio_target_call_delnpfromtpg, .fabric_init_nodeacl = lio_target_init_nodeacl, - .fabric_cleanup_nodeacl = lio_target_cleanup_nodeacl, .tfc_discovery_attrs = lio_target_discovery_auth_attrs, .tfc_wwn_attrs = lio_target_wwn_attrs, diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 1bd5c72b663e..31a096aa16ab 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c @@ -338,10 +338,8 @@ static void target_fabric_nacl_base_release(struct config_item *item) { struct se_node_acl *se_nacl = container_of(to_config_group(item), struct se_node_acl, acl_group); - struct target_fabric_configfs *tf = se_nacl->se_tpg->se_tpg_wwn->wwn_tf; - if (tf->tf_ops->fabric_cleanup_nodeacl) - tf->tf_ops->fabric_cleanup_nodeacl(se_nacl); + configfs_remove_default_groups(&se_nacl->acl_fabric_stat_group); core_tpg_del_initiator_node_acl(se_nacl); } @@ -383,14 +381,6 @@ static struct config_group *target_fabric_make_nodeacl( if (IS_ERR(se_nacl)) return ERR_CAST(se_nacl); - if (tf->tf_ops->fabric_init_nodeacl) { - int ret = tf->tf_ops->fabric_init_nodeacl(se_nacl, name); - if (ret) { - core_tpg_del_initiator_node_acl(se_nacl); - return ERR_PTR(ret); - } - } - config_group_init_type_name(&se_nacl->acl_group, name, &tf->tf_tpg_nacl_base_cit); @@ -414,6 +404,15 @@ static struct config_group *target_fabric_make_nodeacl( configfs_add_default_group(&se_nacl->acl_fabric_stat_group, &se_nacl->acl_group); + if (tf->tf_ops->fabric_init_nodeacl) { + int ret = tf->tf_ops->fabric_init_nodeacl(se_nacl, name); + if (ret) { + configfs_remove_default_groups(&se_nacl->acl_fabric_stat_group); + core_tpg_del_initiator_node_acl(se_nacl); + return ERR_PTR(ret); + } + } + return &se_nacl->acl_group; } @@ -892,6 +891,7 @@ static void target_fabric_release_wwn(struct config_item *item) struct se_wwn, wwn_group); struct target_fabric_configfs *tf = wwn->wwn_tf; + configfs_remove_default_groups(&wwn->fabric_stat_group); tf->tf_ops->fabric_drop_wwn(wwn); } @@ -945,6 +945,8 @@ static struct config_group *target_fabric_make_wwn( &tf->tf_wwn_fabric_stats_cit); configfs_add_default_group(&wwn->fabric_stat_group, &wwn->wwn_group); + if (tf->tf_ops->add_wwn_groups) + tf->tf_ops->add_wwn_groups(wwn); return &wwn->wwn_group; } |