diff options
Diffstat (limited to 'drivers')
155 files changed, 1583 insertions, 1014 deletions
| diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index eaa60c94205a..1f32caa87686 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -30,6 +30,7 @@ static const struct acpi_device_id forbidden_id_list[] = {  	{"PNP0200",  0},	/* AT DMA Controller */  	{"ACPI0009", 0},	/* IOxAPIC */  	{"ACPI000A", 0},	/* IOAPIC */ +	{"SMB0001",  0},	/* ACPI SMBUS virtual device */  	{"", 0},  }; diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index 3f0e2a14895a..22b53bf26817 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -201,19 +201,28 @@ static const struct of_device_id ti_cpufreq_of_match[] = {  	{},  }; +static const struct of_device_id *ti_cpufreq_match_node(void) +{ +	struct device_node *np; +	const struct of_device_id *match; + +	np = of_find_node_by_path("/"); +	match = of_match_node(ti_cpufreq_of_match, np); +	of_node_put(np); + +	return match; +} +  static int ti_cpufreq_probe(struct platform_device *pdev)  {  	u32 version[VERSION_COUNT]; -	struct device_node *np;  	const struct of_device_id *match;  	struct opp_table *ti_opp_table;  	struct ti_cpufreq_data *opp_data;  	const char * const reg_names[] = {"vdd", "vbb"};  	int ret; -	np = of_find_node_by_path("/"); -	match = of_match_node(ti_cpufreq_of_match, np); -	of_node_put(np); +	match = dev_get_platdata(&pdev->dev);  	if (!match)  		return -ENODEV; @@ -290,7 +299,14 @@ fail_put_node:  static int ti_cpufreq_init(void)  { -	platform_device_register_simple("ti-cpufreq", -1, NULL, 0); +	const struct of_device_id *match; + +	/* Check to ensure we are on a compatible platform */ +	match = ti_cpufreq_match_node(); +	if (match) +		platform_device_register_data(NULL, "ti-cpufreq", -1, match, +					      sizeof(*match)); +  	return 0;  }  module_init(ti_cpufreq_init); diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c index 5b44ef226904..fc359ca4503d 100644 --- a/drivers/dma-buf/udmabuf.c +++ b/drivers/dma-buf/udmabuf.c @@ -184,6 +184,7 @@ static long udmabuf_create(const struct udmabuf_create_list *head,  	exp_info.ops  = &udmabuf_ops;  	exp_info.size = ubuf->pagecount << PAGE_SHIFT;  	exp_info.priv = ubuf; +	exp_info.flags = O_RDWR;  	buf = dma_buf_export(&exp_info);  	if (IS_ERR(buf)) { diff --git a/drivers/gnss/serial.c b/drivers/gnss/serial.c index b01ba4438501..31e891f00175 100644 --- a/drivers/gnss/serial.c +++ b/drivers/gnss/serial.c @@ -13,6 +13,7 @@  #include <linux/of.h>  #include <linux/pm.h>  #include <linux/pm_runtime.h> +#include <linux/sched.h>  #include <linux/serdev.h>  #include <linux/slab.h> @@ -63,7 +64,7 @@ static int gnss_serial_write_raw(struct gnss_device *gdev,  	int ret;  	/* write is only buffered synchronously */ -	ret = serdev_device_write(serdev, buf, count, 0); +	ret = serdev_device_write(serdev, buf, count, MAX_SCHEDULE_TIMEOUT);  	if (ret < 0)  		return ret; diff --git a/drivers/gnss/sirf.c b/drivers/gnss/sirf.c index 79cb98950013..71d014edd167 100644 --- a/drivers/gnss/sirf.c +++ b/drivers/gnss/sirf.c @@ -16,6 +16,7 @@  #include <linux/pm.h>  #include <linux/pm_runtime.h>  #include <linux/regulator/consumer.h> +#include <linux/sched.h>  #include <linux/serdev.h>  #include <linux/slab.h>  #include <linux/wait.h> @@ -83,7 +84,7 @@ static int sirf_write_raw(struct gnss_device *gdev, const unsigned char *buf,  	int ret;  	/* write is only buffered synchronously */ -	ret = serdev_device_write(serdev, buf, count, 0); +	ret = serdev_device_write(serdev, buf, count, MAX_SCHEDULE_TIMEOUT);  	if (ret < 0)  		return ret; diff --git a/drivers/gpio/gpio-mockup.c b/drivers/gpio/gpio-mockup.c index 8269cffc2967..6a50f9f59c90 100644 --- a/drivers/gpio/gpio-mockup.c +++ b/drivers/gpio/gpio-mockup.c @@ -35,8 +35,8 @@  #define gpio_mockup_err(...)	pr_err(GPIO_MOCKUP_NAME ": " __VA_ARGS__)  enum { -	GPIO_MOCKUP_DIR_OUT = 0, -	GPIO_MOCKUP_DIR_IN = 1, +	GPIO_MOCKUP_DIR_IN = 0, +	GPIO_MOCKUP_DIR_OUT = 1,  };  /* @@ -131,7 +131,7 @@ static int gpio_mockup_get_direction(struct gpio_chip *gc, unsigned int offset)  {  	struct gpio_mockup_chip *chip = gpiochip_get_data(gc); -	return chip->lines[offset].dir; +	return !chip->lines[offset].dir;  }  static int gpio_mockup_to_irq(struct gpio_chip *gc, unsigned int offset) diff --git a/drivers/gpio/gpio-pxa.c b/drivers/gpio/gpio-pxa.c index bfe4c5c9f41c..e9600b556f39 100644 --- a/drivers/gpio/gpio-pxa.c +++ b/drivers/gpio/gpio-pxa.c @@ -268,8 +268,8 @@ static int pxa_gpio_direction_input(struct gpio_chip *chip, unsigned offset)  	if (pxa_gpio_has_pinctrl()) {  		ret = pinctrl_gpio_direction_input(chip->base + offset); -		if (!ret) -			return 0; +		if (ret) +			return ret;  	}  	spin_lock_irqsave(&gpio_lock, flags); diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 230e41562462..a2cbb474901c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -1295,7 +1295,7 @@ int gpiochip_add_data_with_key(struct gpio_chip *chip, void *data,  	gdev->descs = kcalloc(chip->ngpio, sizeof(gdev->descs[0]), GFP_KERNEL);  	if (!gdev->descs) {  		status = -ENOMEM; -		goto err_free_gdev; +		goto err_free_ida;  	}  	if (chip->ngpio == 0) { @@ -1427,8 +1427,9 @@ err_free_label:  	kfree_const(gdev->label);  err_free_descs:  	kfree(gdev->descs); -err_free_gdev: +err_free_ida:  	ida_simple_remove(&gpio_ida, gdev->id); +err_free_gdev:  	/* failures here can mean systems won't boot... */  	pr_err("%s: GPIOs %d..%d (%s) failed to register, %d\n", __func__,  	       gdev->base, gdev->base + gdev->ngpio - 1, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index 60f9a87e9c74..bcf1666fb31d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c @@ -501,8 +501,11 @@ void amdgpu_amdkfd_set_compute_idle(struct kgd_dev *kgd, bool idle)  {  	struct amdgpu_device *adev = (struct amdgpu_device *)kgd; -	amdgpu_dpm_switch_power_profile(adev, -					PP_SMC_POWER_PROFILE_COMPUTE, !idle); +	if (adev->powerplay.pp_funcs && +	    adev->powerplay.pp_funcs->switch_power_profile) +		amdgpu_dpm_switch_power_profile(adev, +						PP_SMC_POWER_PROFILE_COMPUTE, +						!idle);  }  bool amdgpu_amdkfd_is_kfd_vmid(struct amdgpu_device *adev, u32 vmid) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 6748cd7fc129..686a26de50f9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -626,6 +626,13 @@ int amdgpu_display_modeset_create_props(struct amdgpu_device *adev)  					 "dither",  					 amdgpu_dither_enum_list, sz); +	if (amdgpu_device_has_dc_support(adev)) { +		adev->mode_info.max_bpc_property = +			drm_property_create_range(adev->ddev, 0, "max bpc", 8, 16); +		if (!adev->mode_info.max_bpc_property) +			return -ENOMEM; +	} +  	return 0;  } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index 11723d8fffbd..0dc2c5c57015 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -338,6 +338,8 @@ struct amdgpu_mode_info {  	struct drm_property *audio_property;  	/* FMT dithering */  	struct drm_property *dither_property; +	/* maximum number of bits per channel for monitor color */ +	struct drm_property *max_bpc_property;  	/* hardcoded DFP edid from BIOS */  	struct edid *bios_hardcoded_edid;  	int bios_hardcoded_edid_size; diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index 2821d1d846e4..9fc3296592fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c @@ -46,6 +46,7 @@ MODULE_FIRMWARE("amdgpu/tahiti_mc.bin");  MODULE_FIRMWARE("amdgpu/pitcairn_mc.bin");  MODULE_FIRMWARE("amdgpu/verde_mc.bin");  MODULE_FIRMWARE("amdgpu/oland_mc.bin"); +MODULE_FIRMWARE("amdgpu/hainan_mc.bin");  MODULE_FIRMWARE("amdgpu/si58_mc.bin");  #define MC_SEQ_MISC0__MT__MASK   0xf0000000 diff --git a/drivers/gpu/drm/amd/amdgpu/soc15.c b/drivers/gpu/drm/amd/amdgpu/soc15.c index bf5e6a413dee..4cc0dcb1a187 100644 --- a/drivers/gpu/drm/amd/amdgpu/soc15.c +++ b/drivers/gpu/drm/amd/amdgpu/soc15.c @@ -65,6 +65,13 @@  #define mmMP0_MISC_LIGHT_SLEEP_CTRL                                                             0x01ba  #define mmMP0_MISC_LIGHT_SLEEP_CTRL_BASE_IDX                                                    0 +/* for Vega20 register name change */ +#define mmHDP_MEM_POWER_CTRL	0x00d4 +#define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK	0x00000001L +#define HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK	0x00000002L +#define HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK	0x00010000L +#define HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK		0x00020000L +#define mmHDP_MEM_POWER_CTRL_BASE_IDX	0  /*   * Indirect registers accessor   */ @@ -870,15 +877,33 @@ static void soc15_update_hdp_light_sleep(struct amdgpu_device *adev, bool enable  {  	uint32_t def, data; -	def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS)); +	if (adev->asic_type == CHIP_VEGA20) { +		def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL)); -	if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)) -		data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK; -	else -		data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK; +		if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)) +			data |= HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK | +				HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK | +				HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK | +				HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK; +		else +			data &= ~(HDP_MEM_POWER_CTRL__IPH_MEM_POWER_CTRL_EN_MASK | +				HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK | +				HDP_MEM_POWER_CTRL__RC_MEM_POWER_CTRL_EN_MASK | +				HDP_MEM_POWER_CTRL__RC_MEM_POWER_LS_EN_MASK); -	if (def != data) -		WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS), data); +		if (def != data) +			WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_CTRL), data); +	} else { +		def = data = RREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS)); + +		if (enable && (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS)) +			data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK; +		else +			data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK; + +		if (def != data) +			WREG32(SOC15_REG_OFFSET(HDP, 0, mmHDP_MEM_POWER_LS), data); +	}  }  static void soc15_update_drm_clock_gating(struct amdgpu_device *adev, bool enable) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index aa43bb253ea2..d8d0b206a79c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -2422,8 +2422,15 @@ static void update_stream_scaling_settings(const struct drm_display_mode *mode,  static enum dc_color_depth  convert_color_depth_from_display_info(const struct drm_connector *connector)  { +	struct dm_connector_state *dm_conn_state = +		to_dm_connector_state(connector->state);  	uint32_t bpc = connector->display_info.bpc; +	/* TODO: Remove this when there's support for max_bpc in drm */ +	if (dm_conn_state && bpc > dm_conn_state->max_bpc) +		/* Round down to nearest even number. */ +		bpc = dm_conn_state->max_bpc - (dm_conn_state->max_bpc & 1); +  	switch (bpc) {  	case 0:  		/* @@ -3007,6 +3014,9 @@ int amdgpu_dm_connector_atomic_set_property(struct drm_connector *connector,  	} else if (property == adev->mode_info.underscan_property) {  		dm_new_state->underscan_enable = val;  		ret = 0; +	} else if (property == adev->mode_info.max_bpc_property) { +		dm_new_state->max_bpc = val; +		ret = 0;  	}  	return ret; @@ -3049,6 +3059,9 @@ int amdgpu_dm_connector_atomic_get_property(struct drm_connector *connector,  	} else if (property == adev->mode_info.underscan_property) {  		*val = dm_state->underscan_enable;  		ret = 0; +	} else if (property == adev->mode_info.max_bpc_property) { +		*val = dm_state->max_bpc; +		ret = 0;  	}  	return ret;  } @@ -3859,6 +3872,9 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,  	drm_object_attach_property(&aconnector->base.base,  				adev->mode_info.underscan_vborder_property,  				0); +	drm_object_attach_property(&aconnector->base.base, +				adev->mode_info.max_bpc_property, +				0);  } diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h index d6960644d714..607c3cdd7d0c 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -252,6 +252,7 @@ struct dm_connector_state {  	enum amdgpu_rmx_type scaling;  	uint8_t underscan_vborder;  	uint8_t underscan_hborder; +	uint8_t max_bpc;  	bool underscan_enable;  	bool freesync_enable;  	bool freesync_capable; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c index ed35ec0341e6..88f6b35ea6fe 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c @@ -4525,12 +4525,12 @@ static int smu7_get_sclk_od(struct pp_hwmgr *hwmgr)  	struct smu7_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table);  	struct smu7_single_dpm_table *golden_sclk_table =  			&(data->golden_dpm_table.sclk_table); -	int value; +	int value = sclk_table->dpm_levels[sclk_table->count - 1].value; +	int golden_value = golden_sclk_table->dpm_levels +			[golden_sclk_table->count - 1].value; -	value = (sclk_table->dpm_levels[sclk_table->count - 1].value - -			golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * -			100 / -			golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; +	value -= golden_value; +	value = DIV_ROUND_UP(value * 100, golden_value);  	return value;  } @@ -4567,12 +4567,12 @@ static int smu7_get_mclk_od(struct pp_hwmgr *hwmgr)  	struct smu7_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table);  	struct smu7_single_dpm_table *golden_mclk_table =  			&(data->golden_dpm_table.mclk_table); -	int value; +        int value = mclk_table->dpm_levels[mclk_table->count - 1].value; +	int golden_value = golden_mclk_table->dpm_levels +			[golden_mclk_table->count - 1].value; -	value = (mclk_table->dpm_levels[mclk_table->count - 1].value - -			golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * -			100 / -			golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value; +	value -= golden_value; +	value = DIV_ROUND_UP(value * 100, golden_value);  	return value;  } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c index 8c4db86bb4b7..e2bc6e0c229f 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega10_hwmgr.c @@ -4522,15 +4522,13 @@ static int vega10_get_sclk_od(struct pp_hwmgr *hwmgr)  	struct vega10_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);  	struct vega10_single_dpm_table *golden_sclk_table =  			&(data->golden_dpm_table.gfx_table); -	int value; - -	value = (sclk_table->dpm_levels[sclk_table->count - 1].value - -			golden_sclk_table->dpm_levels -			[golden_sclk_table->count - 1].value) * -			100 / -			golden_sclk_table->dpm_levels +	int value = sclk_table->dpm_levels[sclk_table->count - 1].value; +	int golden_value = golden_sclk_table->dpm_levels  			[golden_sclk_table->count - 1].value; +	value -= golden_value; +	value = DIV_ROUND_UP(value * 100, golden_value); +  	return value;  } @@ -4575,16 +4573,13 @@ static int vega10_get_mclk_od(struct pp_hwmgr *hwmgr)  	struct vega10_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);  	struct vega10_single_dpm_table *golden_mclk_table =  			&(data->golden_dpm_table.mem_table); -	int value; - -	value = (mclk_table->dpm_levels -			[mclk_table->count - 1].value - -			golden_mclk_table->dpm_levels -			[golden_mclk_table->count - 1].value) * -			100 / -			golden_mclk_table->dpm_levels +	int value = mclk_table->dpm_levels[mclk_table->count - 1].value; +	int golden_value = golden_mclk_table->dpm_levels  			[golden_mclk_table->count - 1].value; +	value -= golden_value; +	value = DIV_ROUND_UP(value * 100, golden_value); +  	return value;  } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c index 74bc37308dc0..54364444ecd1 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega12_hwmgr.c @@ -2243,12 +2243,12 @@ static int vega12_get_sclk_od(struct pp_hwmgr *hwmgr)  	struct vega12_single_dpm_table *sclk_table = &(data->dpm_table.gfx_table);  	struct vega12_single_dpm_table *golden_sclk_table =  			&(data->golden_dpm_table.gfx_table); -	int value; +	int value = sclk_table->dpm_levels[sclk_table->count - 1].value; +	int golden_value = golden_sclk_table->dpm_levels +			[golden_sclk_table->count - 1].value; -	value = (sclk_table->dpm_levels[sclk_table->count - 1].value - -			golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * -			100 / -			golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value; +	value -= golden_value; +	value = DIV_ROUND_UP(value * 100, golden_value);  	return value;  } @@ -2264,16 +2264,13 @@ static int vega12_get_mclk_od(struct pp_hwmgr *hwmgr)  	struct vega12_single_dpm_table *mclk_table = &(data->dpm_table.mem_table);  	struct vega12_single_dpm_table *golden_mclk_table =  			&(data->golden_dpm_table.mem_table); -	int value; - -	value = (mclk_table->dpm_levels -			[mclk_table->count - 1].value - -			golden_mclk_table->dpm_levels -			[golden_mclk_table->count - 1].value) * -			100 / -			golden_mclk_table->dpm_levels +	int value = mclk_table->dpm_levels[mclk_table->count - 1].value; +	int golden_value = golden_mclk_table->dpm_levels  			[golden_mclk_table->count - 1].value; +	value -= golden_value; +	value = DIV_ROUND_UP(value * 100, golden_value); +  	return value;  } diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c index f2daf00cc911..2679d1240fa1 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.c @@ -75,7 +75,17 @@ static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)  	data->phy_clk_quad_eqn_b = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT;  	data->phy_clk_quad_eqn_c = PPREGKEY_VEGA20QUADRATICEQUATION_DFLT; -	data->registry_data.disallowed_features = 0x0; +	/* +	 * Disable the following features for now: +	 *   GFXCLK DS +	 *   SOCLK DS +	 *   LCLK DS +	 *   DCEFCLK DS +	 *   FCLK DS +	 *   MP1CLK DS +	 *   MP0CLK DS +	 */ +	data->registry_data.disallowed_features = 0xE0041C00;  	data->registry_data.od_state_in_dc_support = 0;  	data->registry_data.thermal_support = 1;  	data->registry_data.skip_baco_hardware = 0; @@ -1313,12 +1323,13 @@ static int vega20_get_sclk_od(  			&(data->dpm_table.gfx_table);  	struct vega20_single_dpm_table *golden_sclk_table =  			&(data->golden_dpm_table.gfx_table); -	int value; +	int value = sclk_table->dpm_levels[sclk_table->count - 1].value; +	int golden_value = golden_sclk_table->dpm_levels +			[golden_sclk_table->count - 1].value;  	/* od percentage */ -	value = DIV_ROUND_UP((sclk_table->dpm_levels[sclk_table->count - 1].value - -		golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value) * 100, -		golden_sclk_table->dpm_levels[golden_sclk_table->count - 1].value); +	value -= golden_value; +	value = DIV_ROUND_UP(value * 100, golden_value);  	return value;  } @@ -1358,12 +1369,13 @@ static int vega20_get_mclk_od(  			&(data->dpm_table.mem_table);  	struct vega20_single_dpm_table *golden_mclk_table =  			&(data->golden_dpm_table.mem_table); -	int value; +	int value = mclk_table->dpm_levels[mclk_table->count - 1].value; +	int golden_value = golden_mclk_table->dpm_levels +			[golden_mclk_table->count - 1].value;  	/* od percentage */ -	value = DIV_ROUND_UP((mclk_table->dpm_levels[mclk_table->count - 1].value - -		golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value) * 100, -		golden_mclk_table->dpm_levels[golden_mclk_table->count - 1].value); +	value -= golden_value; +	value = DIV_ROUND_UP(value * 100, golden_value);  	return value;  } diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 69dab82a3771..bf589c53b908 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -60,8 +60,29 @@ static const struct pci_device_id pciidlist[] = {  MODULE_DEVICE_TABLE(pci, pciidlist); +static void ast_kick_out_firmware_fb(struct pci_dev *pdev) +{ +	struct apertures_struct *ap; +	bool primary = false; + +	ap = alloc_apertures(1); +	if (!ap) +		return; + +	ap->ranges[0].base = pci_resource_start(pdev, 0); +	ap->ranges[0].size = pci_resource_len(pdev, 0); + +#ifdef CONFIG_X86 +	primary = pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW; +#endif +	drm_fb_helper_remove_conflicting_framebuffers(ap, "astdrmfb", primary); +	kfree(ap); +} +  static int ast_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)  { +	ast_kick_out_firmware_fb(pdev); +  	return drm_get_pci_dev(pdev, ent, &driver);  } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 5e77d456d9bb..7c6ac3cadb6b 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -568,6 +568,7 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc,  	}  	ast_bo_unreserve(bo); +	ast_set_offset_reg(crtc);  	ast_set_start_address_crt1(crtc, (u32)gpu_addr);  	return 0; @@ -1254,7 +1255,7 @@ static int ast_cursor_move(struct drm_crtc *crtc,  	ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xc7, ((y >> 8) & 0x07));  	/* dummy write to fire HWC */ -	ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xCB, 0xFF, 0x00); +	ast_show_cursor(crtc);  	return 0;  } diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 9a69ad7e9f3b..5e9ca6f96379 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c @@ -219,6 +219,9 @@ int drm_fb_helper_single_add_all_connectors(struct drm_fb_helper *fb_helper)  	mutex_lock(&fb_helper->lock);  	drm_connector_list_iter_begin(dev, &conn_iter);  	drm_for_each_connector_iter(connector, &conn_iter) { +		if (connector->connector_type == DRM_MODE_CONNECTOR_WRITEBACK) +			continue; +  		ret = __drm_fb_helper_add_one_connector(fb_helper, connector);  		if (ret)  			goto fail; diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 127468785f74..1f94b9affe4b 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -214,6 +214,12 @@ static int vc4_atomic_commit(struct drm_device *dev,  		return 0;  	} +	/* We know for sure we don't want an async update here. Set +	 * state->legacy_cursor_update to false to prevent +	 * drm_atomic_helper_setup_commit() from auto-completing +	 * commit->flip_done. +	 */ +	state->legacy_cursor_update = false;  	ret = drm_atomic_helper_setup_commit(state, nonblock);  	if (ret)  		return ret; diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 1728fb7d00ba..c3ded0ba0441 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -854,7 +854,7 @@ void vc4_plane_async_set_fb(struct drm_plane *plane, struct drm_framebuffer *fb)  static void vc4_plane_atomic_async_update(struct drm_plane *plane,  					  struct drm_plane_state *state)  { -	struct vc4_plane_state *vc4_state = to_vc4_plane_state(plane->state); +	struct vc4_plane_state *vc4_state, *new_vc4_state;  	if (plane->state->fb != state->fb) {  		vc4_plane_async_set_fb(plane, state->fb); @@ -875,7 +875,18 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane,  	plane->state->src_y = state->src_y;  	/* Update the display list based on the new crtc_x/y. */ -	vc4_plane_atomic_check(plane, plane->state); +	vc4_plane_atomic_check(plane, state); + +	new_vc4_state = to_vc4_plane_state(state); +	vc4_state = to_vc4_plane_state(plane->state); + +	/* Update the current vc4_state pos0, pos2 and ptr0 dlist entries. */ +	vc4_state->dlist[vc4_state->pos0_offset] = +		new_vc4_state->dlist[vc4_state->pos0_offset]; +	vc4_state->dlist[vc4_state->pos2_offset] = +		new_vc4_state->dlist[vc4_state->pos2_offset]; +	vc4_state->dlist[vc4_state->ptr0_offset] = +		new_vc4_state->dlist[vc4_state->ptr0_offset];  	/* Note that we can't just call vc4_plane_write_dlist()  	 * because that would smash the context data that the HVS is diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index c0d668944dbe..ed35c9a9a110 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -275,6 +275,9 @@  #define USB_VENDOR_ID_CIDC		0x1677 +#define I2C_VENDOR_ID_CIRQUE		0x0488 +#define I2C_PRODUCT_ID_CIRQUE_121F	0x121F +  #define USB_VENDOR_ID_CJTOUCH		0x24b8  #define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0020	0x0020  #define USB_DEVICE_ID_CJTOUCH_MULTI_TOUCH_0040	0x0040 @@ -707,6 +710,7 @@  #define USB_VENDOR_ID_LG		0x1fd2  #define USB_DEVICE_ID_LG_MULTITOUCH	0x0064  #define USB_DEVICE_ID_LG_MELFAS_MT	0x6007 +#define I2C_DEVICE_ID_LG_8001		0x8001  #define USB_VENDOR_ID_LOGITECH		0x046d  #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e @@ -805,6 +809,7 @@  #define USB_DEVICE_ID_MS_TYPE_COVER_2    0x07a9  #define USB_DEVICE_ID_MS_POWER_COVER     0x07da  #define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER	0x02fd +#define USB_DEVICE_ID_MS_PIXART_MOUSE    0x00cb  #define USB_VENDOR_ID_MOJO		0x8282  #define USB_DEVICE_ID_RETRO_ADAPTER	0x3201 @@ -1043,6 +1048,7 @@  #define USB_VENDOR_ID_SYMBOL		0x05e0  #define USB_DEVICE_ID_SYMBOL_SCANNER_1	0x0800  #define USB_DEVICE_ID_SYMBOL_SCANNER_2	0x1300 +#define USB_DEVICE_ID_SYMBOL_SCANNER_3	0x1200  #define USB_VENDOR_ID_SYNAPTICS		0x06cb  #define USB_DEVICE_ID_SYNAPTICS_TP	0x0001 @@ -1204,6 +1210,8 @@  #define USB_DEVICE_ID_PRIMAX_MOUSE_4D22	0x4d22  #define USB_DEVICE_ID_PRIMAX_KEYBOARD	0x4e05  #define USB_DEVICE_ID_PRIMAX_REZEL	0x4e72 +#define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F	0x4d0f +#define USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22	0x4e22  #define USB_VENDOR_ID_RISO_KAGAKU	0x1294	/* Riso Kagaku Corp. */ diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index a2f74e6adc70..d6fab5798487 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -325,6 +325,9 @@ static const struct hid_device_id hid_battery_quirks[] = {  	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM,  		USB_DEVICE_ID_ELECOM_BM084),  	  HID_BATTERY_QUIRK_IGNORE }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_SYMBOL, +		USB_DEVICE_ID_SYMBOL_SCANNER_3), +	  HID_BATTERY_QUIRK_IGNORE },  	{}  }; @@ -1838,47 +1841,3 @@ void hidinput_disconnect(struct hid_device *hid)  }  EXPORT_SYMBOL_GPL(hidinput_disconnect); -/** - * hid_scroll_counter_handle_scroll() - Send high- and low-resolution scroll - *                                      events given a high-resolution wheel - *                                      movement. - * @counter: a hid_scroll_counter struct describing the wheel. - * @hi_res_value: the movement of the wheel, in the mouse's high-resolution - *                units. - * - * Given a high-resolution movement, this function converts the movement into - * microns and emits high-resolution scroll events for the input device. It also - * uses the multiplier from &struct hid_scroll_counter to emit low-resolution - * scroll events when appropriate for backwards-compatibility with userspace - * input libraries. - */ -void hid_scroll_counter_handle_scroll(struct hid_scroll_counter *counter, -				      int hi_res_value) -{ -	int low_res_value, remainder, multiplier; - -	input_report_rel(counter->dev, REL_WHEEL_HI_RES, -			 hi_res_value * counter->microns_per_hi_res_unit); - -	/* -	 * Update the low-res remainder with the high-res value, -	 * but reset if the direction has changed. -	 */ -	remainder = counter->remainder; -	if ((remainder ^ hi_res_value) < 0) -		remainder = 0; -	remainder += hi_res_value; - -	/* -	 * Then just use the resolution multiplier to see if -	 * we should send a low-res (aka regular wheel) event. -	 */ -	multiplier = counter->resolution_multiplier; -	low_res_value = remainder / multiplier; -	remainder -= low_res_value * multiplier; -	counter->remainder = remainder; - -	if (low_res_value) -		input_report_rel(counter->dev, REL_WHEEL, low_res_value); -} -EXPORT_SYMBOL_GPL(hid_scroll_counter_handle_scroll); diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index f01280898b24..19cc980eebce 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -64,14 +64,6 @@ MODULE_PARM_DESC(disable_tap_to_click,  #define HIDPP_QUIRK_NO_HIDINPUT			BIT(23)  #define HIDPP_QUIRK_FORCE_OUTPUT_REPORTS	BIT(24)  #define HIDPP_QUIRK_UNIFYING			BIT(25) -#define HIDPP_QUIRK_HI_RES_SCROLL_1P0		BIT(26) -#define HIDPP_QUIRK_HI_RES_SCROLL_X2120		BIT(27) -#define HIDPP_QUIRK_HI_RES_SCROLL_X2121		BIT(28) - -/* Convenience constant to check for any high-res support. */ -#define HIDPP_QUIRK_HI_RES_SCROLL	(HIDPP_QUIRK_HI_RES_SCROLL_1P0 | \ -					 HIDPP_QUIRK_HI_RES_SCROLL_X2120 | \ -					 HIDPP_QUIRK_HI_RES_SCROLL_X2121)  #define HIDPP_QUIRK_DELAYED_INIT		HIDPP_QUIRK_NO_HIDINPUT @@ -157,7 +149,6 @@ struct hidpp_device {  	unsigned long capabilities;  	struct hidpp_battery battery; -	struct hid_scroll_counter vertical_wheel_counter;  };  /* HID++ 1.0 error codes */ @@ -409,53 +400,32 @@ static void hidpp_prefix_name(char **name, int name_length)  #define HIDPP_SET_LONG_REGISTER				0x82  #define HIDPP_GET_LONG_REGISTER				0x83 -/** - * hidpp10_set_register_bit() - Sets a single bit in a HID++ 1.0 register. - * @hidpp_dev: the device to set the register on. - * @register_address: the address of the register to modify. - * @byte: the byte of the register to modify. Should be less than 3. - * Return: 0 if successful, otherwise a negative error code. - */ -static int hidpp10_set_register_bit(struct hidpp_device *hidpp_dev, -	u8 register_address, u8 byte, u8 bit) +#define HIDPP_REG_GENERAL				0x00 + +static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev)  {  	struct hidpp_report response;  	int ret;  	u8 params[3] = { 0 };  	ret = hidpp_send_rap_command_sync(hidpp_dev, -					  REPORT_ID_HIDPP_SHORT, -					  HIDPP_GET_REGISTER, -					  register_address, -					  NULL, 0, &response); +					REPORT_ID_HIDPP_SHORT, +					HIDPP_GET_REGISTER, +					HIDPP_REG_GENERAL, +					NULL, 0, &response);  	if (ret)  		return ret;  	memcpy(params, response.rap.params, 3); -	params[byte] |= BIT(bit); +	/* Set the battery bit */ +	params[0] |= BIT(4);  	return hidpp_send_rap_command_sync(hidpp_dev, -					   REPORT_ID_HIDPP_SHORT, -					   HIDPP_SET_REGISTER, -					   register_address, -					   params, 3, &response); -} - - -#define HIDPP_REG_GENERAL				0x00 - -static int hidpp10_enable_battery_reporting(struct hidpp_device *hidpp_dev) -{ -	return hidpp10_set_register_bit(hidpp_dev, HIDPP_REG_GENERAL, 0, 4); -} - -#define HIDPP_REG_FEATURES				0x01 - -/* On HID++ 1.0 devices, high-res scroll was called "scrolling acceleration". */ -static int hidpp10_enable_scrolling_acceleration(struct hidpp_device *hidpp_dev) -{ -	return hidpp10_set_register_bit(hidpp_dev, HIDPP_REG_FEATURES, 0, 6); +					REPORT_ID_HIDPP_SHORT, +					HIDPP_SET_REGISTER, +					HIDPP_REG_GENERAL, +					params, 3, &response);  }  #define HIDPP_REG_BATTERY_STATUS			0x07 @@ -1167,100 +1137,6 @@ static int hidpp_battery_get_property(struct power_supply *psy,  }  /* -------------------------------------------------------------------------- */ -/* 0x2120: Hi-resolution scrolling                                            */ -/* -------------------------------------------------------------------------- */ - -#define HIDPP_PAGE_HI_RESOLUTION_SCROLLING			0x2120 - -#define CMD_HI_RESOLUTION_SCROLLING_SET_HIGHRES_SCROLLING_MODE	0x10 - -static int hidpp_hrs_set_highres_scrolling_mode(struct hidpp_device *hidpp, -	bool enabled, u8 *multiplier) -{ -	u8 feature_index; -	u8 feature_type; -	int ret; -	u8 params[1]; -	struct hidpp_report response; - -	ret = hidpp_root_get_feature(hidpp, -				     HIDPP_PAGE_HI_RESOLUTION_SCROLLING, -				     &feature_index, -				     &feature_type); -	if (ret) -		return ret; - -	params[0] = enabled ? BIT(0) : 0; -	ret = hidpp_send_fap_command_sync(hidpp, feature_index, -					  CMD_HI_RESOLUTION_SCROLLING_SET_HIGHRES_SCROLLING_MODE, -					  params, sizeof(params), &response); -	if (ret) -		return ret; -	*multiplier = response.fap.params[1]; -	return 0; -} - -/* -------------------------------------------------------------------------- */ -/* 0x2121: HiRes Wheel                                                        */ -/* -------------------------------------------------------------------------- */ - -#define HIDPP_PAGE_HIRES_WHEEL		0x2121 - -#define CMD_HIRES_WHEEL_GET_WHEEL_CAPABILITY	0x00 -#define CMD_HIRES_WHEEL_SET_WHEEL_MODE		0x20 - -static int hidpp_hrw_get_wheel_capability(struct hidpp_device *hidpp, -	u8 *multiplier) -{ -	u8 feature_index; -	u8 feature_type; -	int ret; -	struct hidpp_report response; - -	ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL, -				     &feature_index, &feature_type); -	if (ret) -		goto return_default; - -	ret = hidpp_send_fap_command_sync(hidpp, feature_index, -					  CMD_HIRES_WHEEL_GET_WHEEL_CAPABILITY, -					  NULL, 0, &response); -	if (ret) -		goto return_default; - -	*multiplier = response.fap.params[0]; -	return 0; -return_default: -	hid_warn(hidpp->hid_dev, -		 "Couldn't get wheel multiplier (error %d), assuming %d.\n", -		 ret, *multiplier); -	return ret; -} - -static int hidpp_hrw_set_wheel_mode(struct hidpp_device *hidpp, bool invert, -	bool high_resolution, bool use_hidpp) -{ -	u8 feature_index; -	u8 feature_type; -	int ret; -	u8 params[1]; -	struct hidpp_report response; - -	ret = hidpp_root_get_feature(hidpp, HIDPP_PAGE_HIRES_WHEEL, -				     &feature_index, &feature_type); -	if (ret) -		return ret; - -	params[0] = (invert          ? BIT(2) : 0) | -		    (high_resolution ? BIT(1) : 0) | -		    (use_hidpp       ? BIT(0) : 0); - -	return hidpp_send_fap_command_sync(hidpp, feature_index, -					   CMD_HIRES_WHEEL_SET_WHEEL_MODE, -					   params, sizeof(params), &response); -} - -/* -------------------------------------------------------------------------- */  /* 0x4301: Solar Keyboard                                                     */  /* -------------------------------------------------------------------------- */ @@ -2523,8 +2399,7 @@ static int m560_raw_event(struct hid_device *hdev, u8 *data, int size)  		input_report_rel(mydata->input, REL_Y, v);  		v = hid_snto32(data[6], 8); -		hid_scroll_counter_handle_scroll( -				&hidpp->vertical_wheel_counter, v); +		input_report_rel(mydata->input, REL_WHEEL, v);  		input_sync(mydata->input);  	} @@ -2653,72 +2528,6 @@ static int g920_get_config(struct hidpp_device *hidpp)  }  /* -------------------------------------------------------------------------- */ -/* High-resolution scroll wheels                                              */ -/* -------------------------------------------------------------------------- */ - -/** - * struct hi_res_scroll_info - Stores info on a device's high-res scroll wheel. - * @product_id: the HID product ID of the device being described. - * @microns_per_hi_res_unit: the distance moved by the user's finger for each - *                         high-resolution unit reported by the device, in - *                         256ths of a millimetre. - */ -struct hi_res_scroll_info { -	__u32 product_id; -	int microns_per_hi_res_unit; -}; - -static struct hi_res_scroll_info hi_res_scroll_devices[] = { -	{ /* Anywhere MX */ -	  .product_id = 0x1017, .microns_per_hi_res_unit = 445 }, -	{ /* Performance MX */ -	  .product_id = 0x101a, .microns_per_hi_res_unit = 406 }, -	{ /* M560 */ -	  .product_id = 0x402d, .microns_per_hi_res_unit = 435 }, -	{ /* MX Master 2S */ -	  .product_id = 0x4069, .microns_per_hi_res_unit = 406 }, -}; - -static int hi_res_scroll_look_up_microns(__u32 product_id) -{ -	int i; -	int num_devices = sizeof(hi_res_scroll_devices) -			  / sizeof(hi_res_scroll_devices[0]); -	for (i = 0; i < num_devices; i++) { -		if (hi_res_scroll_devices[i].product_id == product_id) -			return hi_res_scroll_devices[i].microns_per_hi_res_unit; -	} -	/* We don't have a value for this device, so use a sensible default. */ -	return 406; -} - -static int hi_res_scroll_enable(struct hidpp_device *hidpp) -{ -	int ret; -	u8 multiplier = 8; - -	if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2121) { -		ret = hidpp_hrw_set_wheel_mode(hidpp, false, true, false); -		hidpp_hrw_get_wheel_capability(hidpp, &multiplier); -	} else if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_X2120) { -		ret = hidpp_hrs_set_highres_scrolling_mode(hidpp, true, -							   &multiplier); -	} else /* if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL_1P0) */ -		ret = hidpp10_enable_scrolling_acceleration(hidpp); - -	if (ret) -		return ret; - -	hidpp->vertical_wheel_counter.resolution_multiplier = multiplier; -	hidpp->vertical_wheel_counter.microns_per_hi_res_unit = -		hi_res_scroll_look_up_microns(hidpp->hid_dev->product); -	hid_info(hidpp->hid_dev, "multiplier = %d, microns = %d\n", -		 multiplier, -		 hidpp->vertical_wheel_counter.microns_per_hi_res_unit); -	return 0; -} - -/* -------------------------------------------------------------------------- */  /* Generic HID++ devices                                                      */  /* -------------------------------------------------------------------------- */ @@ -2763,11 +2572,6 @@ static void hidpp_populate_input(struct hidpp_device *hidpp,  		wtp_populate_input(hidpp, input, origin_is_hid_core);  	else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560)  		m560_populate_input(hidpp, input, origin_is_hid_core); - -	if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) { -		input_set_capability(input, EV_REL, REL_WHEEL_HI_RES); -		hidpp->vertical_wheel_counter.dev = input; -	}  }  static int hidpp_input_configured(struct hid_device *hdev, @@ -2886,27 +2690,6 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report,  	return 0;  } -static int hidpp_event(struct hid_device *hdev, struct hid_field *field, -	struct hid_usage *usage, __s32 value) -{ -	/* This function will only be called for scroll events, due to the -	 * restriction imposed in hidpp_usages. -	 */ -	struct hidpp_device *hidpp = hid_get_drvdata(hdev); -	struct hid_scroll_counter *counter = &hidpp->vertical_wheel_counter; -	/* A scroll event may occur before the multiplier has been retrieved or -	 * the input device set, or high-res scroll enabling may fail. In such -	 * cases we must return early (falling back to default behaviour) to -	 * avoid a crash in hid_scroll_counter_handle_scroll. -	 */ -	if (!(hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) || value == 0 -	    || counter->dev == NULL || counter->resolution_multiplier == 0) -		return 0; - -	hid_scroll_counter_handle_scroll(counter, value); -	return 1; -} -  static int hidpp_initialize_battery(struct hidpp_device *hidpp)  {  	static atomic_t battery_no = ATOMIC_INIT(0); @@ -3118,9 +2901,6 @@ static void hidpp_connect_event(struct hidpp_device *hidpp)  	if (hidpp->battery.ps)  		power_supply_changed(hidpp->battery.ps); -	if (hidpp->quirks & HIDPP_QUIRK_HI_RES_SCROLL) -		hi_res_scroll_enable(hidpp); -  	if (!(hidpp->quirks & HIDPP_QUIRK_NO_HIDINPUT) || hidpp->delayed_input)  		/* if the input nodes are already created, we can stop now */  		return; @@ -3306,63 +3086,35 @@ static void hidpp_remove(struct hid_device *hdev)  	mutex_destroy(&hidpp->send_mutex);  } -#define LDJ_DEVICE(product) \ -	HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, \ -		   USB_VENDOR_ID_LOGITECH, (product)) -  static const struct hid_device_id hidpp_devices[] = {  	{ /* wireless touchpad */ -	  LDJ_DEVICE(0x4011), +	  HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, +		USB_VENDOR_ID_LOGITECH, 0x4011),  	  .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT |  			 HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS },  	{ /* wireless touchpad T650 */ -	  LDJ_DEVICE(0x4101), +	  HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, +		USB_VENDOR_ID_LOGITECH, 0x4101),  	  .driver_data = HIDPP_QUIRK_CLASS_WTP | HIDPP_QUIRK_DELAYED_INIT },  	{ /* wireless touchpad T651 */  	  HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH,  		USB_DEVICE_ID_LOGITECH_T651),  	  .driver_data = HIDPP_QUIRK_CLASS_WTP }, -	{ /* Mouse Logitech Anywhere MX */ -	  LDJ_DEVICE(0x1017), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, -	{ /* Mouse Logitech Cube */ -	  LDJ_DEVICE(0x4010), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, -	{ /* Mouse Logitech M335 */ -	  LDJ_DEVICE(0x4050), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ /* Mouse Logitech M515 */ -	  LDJ_DEVICE(0x4007), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2120 },  	{ /* Mouse logitech M560 */ -	  LDJ_DEVICE(0x402d), -	  .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 -		| HIDPP_QUIRK_HI_RES_SCROLL_X2120 }, -	{ /* Mouse Logitech M705 (firmware RQM17) */ -	  LDJ_DEVICE(0x101b), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, -	{ /* Mouse Logitech M705 (firmware RQM67) */ -	  LDJ_DEVICE(0x406d), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ /* Mouse Logitech M720 */ -	  LDJ_DEVICE(0x405e), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ /* Mouse Logitech MX Anywhere 2 */ -	  LDJ_DEVICE(0x404a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ LDJ_DEVICE(0xb013), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ LDJ_DEVICE(0xb018), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ LDJ_DEVICE(0xb01f), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ /* Mouse Logitech MX Anywhere 2S */ -	  LDJ_DEVICE(0x406a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ /* Mouse Logitech MX Master */ -	  LDJ_DEVICE(0x4041), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ LDJ_DEVICE(0x4060), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ LDJ_DEVICE(0x4071), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ /* Mouse Logitech MX Master 2S */ -	  LDJ_DEVICE(0x4069), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_X2121 }, -	{ /* Mouse Logitech Performance MX */ -	  LDJ_DEVICE(0x101a), .driver_data = HIDPP_QUIRK_HI_RES_SCROLL_1P0 }, +	  HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, +		USB_VENDOR_ID_LOGITECH, 0x402d), +	  .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 },  	{ /* Keyboard logitech K400 */ -	  LDJ_DEVICE(0x4024), +	  HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, +		USB_VENDOR_ID_LOGITECH, 0x4024),  	  .driver_data = HIDPP_QUIRK_CLASS_K400 },  	{ /* Solar Keyboard Logitech K750 */ -	  LDJ_DEVICE(0x4002), +	  HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, +		USB_VENDOR_ID_LOGITECH, 0x4002),  	  .driver_data = HIDPP_QUIRK_CLASS_K750 }, -	{ LDJ_DEVICE(HID_ANY_ID) }, +	{ HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, +		USB_VENDOR_ID_LOGITECH, HID_ANY_ID)},  	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G920_WHEEL),  		.driver_data = HIDPP_QUIRK_CLASS_G920 | HIDPP_QUIRK_FORCE_OUTPUT_REPORTS}, @@ -3371,19 +3123,12 @@ static const struct hid_device_id hidpp_devices[] = {  MODULE_DEVICE_TABLE(hid, hidpp_devices); -static const struct hid_usage_id hidpp_usages[] = { -	{ HID_GD_WHEEL, EV_REL, REL_WHEEL }, -	{ HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} -}; -  static struct hid_driver hidpp_driver = {  	.name = "logitech-hidpp-device",  	.id_table = hidpp_devices,  	.probe = hidpp_probe,  	.remove = hidpp_remove,  	.raw_event = hidpp_raw_event, -	.usage_table = hidpp_usages, -	.event = hidpp_event,  	.input_configured = hidpp_input_configured,  	.input_mapping = hidpp_input_mapping,  	.input_mapped = hidpp_input_mapped, diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index f7c6de2b6730..dca0a3a90fb8 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1814,6 +1814,12 @@ static const struct hid_device_id mt_devices[] = {  		MT_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT,  			USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, +	/* Cirque devices */ +	{ .driver_data = MT_CLS_WIN_8_DUAL, +		HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, +			I2C_VENDOR_ID_CIRQUE, +			I2C_PRODUCT_ID_CIRQUE_121F) }, +  	/* CJTouch panels */  	{ .driver_data = MT_CLS_NSMU,  		MT_USB_DEVICE(USB_VENDOR_ID_CJTOUCH, diff --git a/drivers/hid/hid-quirks.c b/drivers/hid/hid-quirks.c index 8237dd86fb17..c85a79986b6a 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -107,6 +107,7 @@ static const struct hid_device_id hid_quirks[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C05A), HID_QUIRK_ALWAYS_POLL },  	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOUSE_C06A), HID_QUIRK_ALWAYS_POLL },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MCS, USB_DEVICE_ID_MCS_GAMEPADBLOCK), HID_QUIRK_MULTI_INPUT }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PIXART_MOUSE), HID_QUIRK_ALWAYS_POLL },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), HID_QUIRK_NO_INIT_REPORTS },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_SURFACE_PRO_2), HID_QUIRK_NO_INIT_REPORTS },  	{ HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TOUCH_COVER_2), HID_QUIRK_NO_INIT_REPORTS }, @@ -129,6 +130,8 @@ static const struct hid_device_id hid_quirks[] = {  	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN), HID_QUIRK_NO_INIT_REPORTS },  	{ HID_USB_DEVICE(USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_USB_OPTICAL_MOUSE), HID_QUIRK_ALWAYS_POLL },  	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_MOUSE_4D22), HID_QUIRK_ALWAYS_POLL }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4D0F), HID_QUIRK_ALWAYS_POLL }, +	{ HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_PIXART_MOUSE_4E22), HID_QUIRK_ALWAYS_POLL },  	{ HID_USB_DEVICE(USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS), HID_QUIRK_NOGET },  	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001), HID_QUIRK_NOGET },  	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003), HID_QUIRK_NOGET }, diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c index 0422ec2b13d2..dc4128bfe2ca 100644 --- a/drivers/hid/hid-steam.c +++ b/drivers/hid/hid-steam.c @@ -23,8 +23,9 @@   * In order to avoid breaking them this driver creates a layered hidraw device,   * so it can detect when the client is running and then:   *  - it will not send any command to the controller. - *  - this input device will be disabled, to avoid double input of the same + *  - this input device will be removed, to avoid double input of the same   *    user action. + * When the client is closed, this input device will be created again.   *   * For additional functions, such as changing the right-pad margin or switching   * the led, you can use the user-space tool at: @@ -113,7 +114,7 @@ struct steam_device {  	spinlock_t lock;  	struct hid_device *hdev, *client_hdev;  	struct mutex mutex; -	bool client_opened, input_opened; +	bool client_opened;  	struct input_dev __rcu *input;  	unsigned long quirks;  	struct work_struct work_connect; @@ -279,18 +280,6 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable)  	}  } -static void steam_update_lizard_mode(struct steam_device *steam) -{ -	mutex_lock(&steam->mutex); -	if (!steam->client_opened) { -		if (steam->input_opened) -			steam_set_lizard_mode(steam, false); -		else -			steam_set_lizard_mode(steam, lizard_mode); -	} -	mutex_unlock(&steam->mutex); -} -  static int steam_input_open(struct input_dev *dev)  {  	struct steam_device *steam = input_get_drvdata(dev); @@ -301,7 +290,6 @@ static int steam_input_open(struct input_dev *dev)  		return ret;  	mutex_lock(&steam->mutex); -	steam->input_opened = true;  	if (!steam->client_opened && lizard_mode)  		steam_set_lizard_mode(steam, false);  	mutex_unlock(&steam->mutex); @@ -313,7 +301,6 @@ static void steam_input_close(struct input_dev *dev)  	struct steam_device *steam = input_get_drvdata(dev);  	mutex_lock(&steam->mutex); -	steam->input_opened = false;  	if (!steam->client_opened && lizard_mode)  		steam_set_lizard_mode(steam, true);  	mutex_unlock(&steam->mutex); @@ -400,7 +387,7 @@ static int steam_battery_register(struct steam_device *steam)  	return 0;  } -static int steam_register(struct steam_device *steam) +static int steam_input_register(struct steam_device *steam)  {  	struct hid_device *hdev = steam->hdev;  	struct input_dev *input; @@ -414,17 +401,6 @@ static int steam_register(struct steam_device *steam)  		return 0;  	} -	/* -	 * Unlikely, but getting the serial could fail, and it is not so -	 * important, so make up a serial number and go on. -	 */ -	if (steam_get_serial(steam) < 0) -		strlcpy(steam->serial_no, "XXXXXXXXXX", -				sizeof(steam->serial_no)); - -	hid_info(hdev, "Steam Controller '%s' connected", -			steam->serial_no); -  	input = input_allocate_device();  	if (!input)  		return -ENOMEM; @@ -492,11 +468,6 @@ static int steam_register(struct steam_device *steam)  		goto input_register_fail;  	rcu_assign_pointer(steam->input, input); - -	/* ignore battery errors, we can live without it */ -	if (steam->quirks & STEAM_QUIRK_WIRELESS) -		steam_battery_register(steam); -  	return 0;  input_register_fail: @@ -504,27 +475,88 @@ input_register_fail:  	return ret;  } -static void steam_unregister(struct steam_device *steam) +static void steam_input_unregister(struct steam_device *steam)  {  	struct input_dev *input; +	rcu_read_lock(); +	input = rcu_dereference(steam->input); +	rcu_read_unlock(); +	if (!input) +		return; +	RCU_INIT_POINTER(steam->input, NULL); +	synchronize_rcu(); +	input_unregister_device(input); +} + +static void steam_battery_unregister(struct steam_device *steam) +{  	struct power_supply *battery;  	rcu_read_lock(); -	input = rcu_dereference(steam->input);  	battery = rcu_dereference(steam->battery);  	rcu_read_unlock(); -	if (battery) { -		RCU_INIT_POINTER(steam->battery, NULL); -		synchronize_rcu(); -		power_supply_unregister(battery); +	if (!battery) +		return; +	RCU_INIT_POINTER(steam->battery, NULL); +	synchronize_rcu(); +	power_supply_unregister(battery); +} + +static int steam_register(struct steam_device *steam) +{ +	int ret; + +	/* +	 * This function can be called several times in a row with the +	 * wireless adaptor, without steam_unregister() between them, because +	 * another client send a get_connection_status command, for example. +	 * The battery and serial number are set just once per device. +	 */ +	if (!steam->serial_no[0]) { +		/* +		 * Unlikely, but getting the serial could fail, and it is not so +		 * important, so make up a serial number and go on. +		 */ +		if (steam_get_serial(steam) < 0) +			strlcpy(steam->serial_no, "XXXXXXXXXX", +					sizeof(steam->serial_no)); + +		hid_info(steam->hdev, "Steam Controller '%s' connected", +				steam->serial_no); + +		/* ignore battery errors, we can live without it */ +		if (steam->quirks & STEAM_QUIRK_WIRELESS) +			steam_battery_register(steam); + +		mutex_lock(&steam_devices_lock); +		list_add(&steam->list, &steam_devices); +		mutex_unlock(&steam_devices_lock);  	} -	if (input) { -		RCU_INIT_POINTER(steam->input, NULL); -		synchronize_rcu(); + +	mutex_lock(&steam->mutex); +	if (!steam->client_opened) { +		steam_set_lizard_mode(steam, lizard_mode); +		ret = steam_input_register(steam); +	} else { +		ret = 0; +	} +	mutex_unlock(&steam->mutex); + +	return ret; +} + +static void steam_unregister(struct steam_device *steam) +{ +	steam_battery_unregister(steam); +	steam_input_unregister(steam); +	if (steam->serial_no[0]) {  		hid_info(steam->hdev, "Steam Controller '%s' disconnected",  				steam->serial_no); -		input_unregister_device(input); +		mutex_lock(&steam_devices_lock); +		list_del(&steam->list); +		mutex_unlock(&steam_devices_lock); +		steam->serial_no[0] = 0;  	}  } @@ -600,6 +632,9 @@ static int steam_client_ll_open(struct hid_device *hdev)  	mutex_lock(&steam->mutex);  	steam->client_opened = true;  	mutex_unlock(&steam->mutex); + +	steam_input_unregister(steam); +  	return ret;  } @@ -609,13 +644,13 @@ static void steam_client_ll_close(struct hid_device *hdev)  	mutex_lock(&steam->mutex);  	steam->client_opened = false; -	if (steam->input_opened) -		steam_set_lizard_mode(steam, false); -	else -		steam_set_lizard_mode(steam, lizard_mode);  	mutex_unlock(&steam->mutex);  	hid_hw_close(steam->hdev); +	if (steam->connected) { +		steam_set_lizard_mode(steam, lizard_mode); +		steam_input_register(steam); +	}  }  static int steam_client_ll_raw_request(struct hid_device *hdev, @@ -744,11 +779,6 @@ static int steam_probe(struct hid_device *hdev,  		}  	} -	mutex_lock(&steam_devices_lock); -	steam_update_lizard_mode(steam); -	list_add(&steam->list, &steam_devices); -	mutex_unlock(&steam_devices_lock); -  	return 0;  hid_hw_open_fail: @@ -774,10 +804,6 @@ static void steam_remove(struct hid_device *hdev)  		return;  	} -	mutex_lock(&steam_devices_lock); -	list_del(&steam->list); -	mutex_unlock(&steam_devices_lock); -  	hid_destroy_device(steam->client_hdev);  	steam->client_opened = false;  	cancel_work_sync(&steam->work_connect); @@ -792,12 +818,14 @@ static void steam_remove(struct hid_device *hdev)  static void steam_do_connect_event(struct steam_device *steam, bool connected)  {  	unsigned long flags; +	bool changed;  	spin_lock_irqsave(&steam->lock, flags); +	changed = steam->connected != connected;  	steam->connected = connected;  	spin_unlock_irqrestore(&steam->lock, flags); -	if (schedule_work(&steam->work_connect) == 0) +	if (changed && schedule_work(&steam->work_connect) == 0)  		dbg_hid("%s: connected=%d event already queued\n",  				__func__, connected);  } @@ -1019,13 +1047,8 @@ static int steam_raw_event(struct hid_device *hdev,  			return 0;  		rcu_read_lock();  		input = rcu_dereference(steam->input); -		if (likely(input)) { +		if (likely(input))  			steam_do_input_event(steam, input, data); -		} else { -			dbg_hid("%s: input data without connect event\n", -					__func__); -			steam_do_connect_event(steam, true); -		}  		rcu_read_unlock();  		break;  	case STEAM_EV_CONNECT: @@ -1074,7 +1097,10 @@ static int steam_param_set_lizard_mode(const char *val,  	mutex_lock(&steam_devices_lock);  	list_for_each_entry(steam, &steam_devices, list) { -		steam_update_lizard_mode(steam); +		mutex_lock(&steam->mutex); +		if (!steam->client_opened) +			steam_set_lizard_mode(steam, lizard_mode); +		mutex_unlock(&steam->mutex);  	}  	mutex_unlock(&steam_devices_lock);  	return 0; diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 3cde7c1b9c33..8555ce7e737b 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -177,6 +177,8 @@ static const struct i2c_hid_quirks {  		I2C_HID_QUIRK_NO_RUNTIME_PM },  	{ I2C_VENDOR_ID_RAYDIUM, I2C_PRODUCT_ID_RAYDIUM_4B33,  		I2C_HID_QUIRK_DELAY_AFTER_SLEEP }, +	{ USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001, +		I2C_HID_QUIRK_NO_RUNTIME_PM },  	{ 0, 0 }  }; diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c index 3c5507313606..840634e0f1e3 100644 --- a/drivers/hid/uhid.c +++ b/drivers/hid/uhid.c @@ -12,6 +12,7 @@  #include <linux/atomic.h>  #include <linux/compat.h> +#include <linux/cred.h>  #include <linux/device.h>  #include <linux/fs.h>  #include <linux/hid.h> @@ -496,12 +497,13 @@ static int uhid_dev_create2(struct uhid_device *uhid,  		goto err_free;  	} -	len = min(sizeof(hid->name), sizeof(ev->u.create2.name)); -	strlcpy(hid->name, ev->u.create2.name, len); -	len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)); -	strlcpy(hid->phys, ev->u.create2.phys, len); -	len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)); -	strlcpy(hid->uniq, ev->u.create2.uniq, len); +	/* @hid is zero-initialized, strncpy() is correct, strlcpy() not */ +	len = min(sizeof(hid->name), sizeof(ev->u.create2.name)) - 1; +	strncpy(hid->name, ev->u.create2.name, len); +	len = min(sizeof(hid->phys), sizeof(ev->u.create2.phys)) - 1; +	strncpy(hid->phys, ev->u.create2.phys, len); +	len = min(sizeof(hid->uniq), sizeof(ev->u.create2.uniq)) - 1; +	strncpy(hid->uniq, ev->u.create2.uniq, len);  	hid->ll_driver = &uhid_hid_driver;  	hid->bus = ev->u.create2.bus; @@ -722,6 +724,17 @@ static ssize_t uhid_char_write(struct file *file, const char __user *buffer,  	switch (uhid->input_buf.type) {  	case UHID_CREATE: +		/* +		 * 'struct uhid_create_req' contains a __user pointer which is +		 * copied from, so it's unsafe to allow this with elevated +		 * privileges (e.g. from a setuid binary) or via kernel_write(). +		 */ +		if (file->f_cred != current_cred() || uaccess_kernel()) { +			pr_err_once("UHID_CREATE from different security context by process %d (%s), this is not allowed.\n", +				    task_tgid_vnr(current), current->comm); +			ret = -EACCES; +			goto unlock; +		}  		ret = uhid_dev_create(uhid, &uhid->input_buf);  		break;  	case UHID_CREATE2: diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c index a7513a8a8e37..d6106e1a0d4a 100644 --- a/drivers/hv/hv_kvp.c +++ b/drivers/hv/hv_kvp.c @@ -353,6 +353,9 @@ static void process_ib_ipinfo(void *in_msg, void *out_msg, int op)  		out->body.kvp_ip_val.dhcp_enabled = in->kvp_ip_val.dhcp_enabled; +		/* fallthrough */ + +	case KVP_OP_GET_IP_INFO:  		utf16s_to_utf8s((wchar_t *)in->kvp_ip_val.adapter_id,  				MAX_ADAPTER_ID_SIZE,  				UTF16_LITTLE_ENDIAN, @@ -405,7 +408,11 @@ kvp_send_key(struct work_struct *dummy)  		process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);  		break;  	case KVP_OP_GET_IP_INFO: -		/* We only need to pass on message->kvp_hdr.operation.  */ +		/* +		 * We only need to pass on the info of operation, adapter_id +		 * and addr_family to the userland kvp daemon. +		 */ +		process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);  		break;  	case KVP_OP_SET:  		switch (in_msg->body.kvp_set.data.value_type) { @@ -446,9 +453,9 @@ kvp_send_key(struct work_struct *dummy)  		} -		break; - -	case KVP_OP_GET: +		/* +		 * The key is always a string - utf16 encoding. +		 */  		message->body.kvp_set.data.key_size =  			utf16s_to_utf8s(  			(wchar_t *)in_msg->body.kvp_set.data.key, @@ -456,6 +463,17 @@ kvp_send_key(struct work_struct *dummy)  			UTF16_LITTLE_ENDIAN,  			message->body.kvp_set.data.key,  			HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1; + +		break; + +	case KVP_OP_GET: +		message->body.kvp_get.data.key_size = +			utf16s_to_utf8s( +			(wchar_t *)in_msg->body.kvp_get.data.key, +			in_msg->body.kvp_get.data.key_size, +			UTF16_LITTLE_ENDIAN, +			message->body.kvp_get.data.key, +			HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;  		break;  	case KVP_OP_DELETE: diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index bb2cd29e1658..d8f7000a466a 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c @@ -797,7 +797,8 @@ static int iommu_init_ga_log(struct amd_iommu *iommu)  	entry = iommu_virt_to_phys(iommu->ga_log) | GA_LOG_SIZE_512;  	memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_BASE_OFFSET,  		    &entry, sizeof(entry)); -	entry = (iommu_virt_to_phys(iommu->ga_log) & 0xFFFFFFFFFFFFFULL) & ~7ULL; +	entry = (iommu_virt_to_phys(iommu->ga_log_tail) & +		 (BIT_ULL(52)-1)) & ~7ULL;  	memcpy_toio(iommu->mmio_base + MMIO_GA_LOG_TAIL_OFFSET,  		    &entry, sizeof(entry));  	writel(0x00, iommu->mmio_base + MMIO_GA_HEAD_OFFSET); diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index f3ccf025108b..41a4b8808802 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -3075,7 +3075,7 @@ static int copy_context_table(struct intel_iommu *iommu,  			}  			if (old_ce) -				iounmap(old_ce); +				memunmap(old_ce);  			ret = 0;  			if (devfn < 0x80) diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c index db301efe126d..887150907526 100644 --- a/drivers/iommu/intel-svm.c +++ b/drivers/iommu/intel-svm.c @@ -595,7 +595,7 @@ static irqreturn_t prq_event_thread(int irq, void *d)  			pr_err("%s: Page request without PASID: %08llx %08llx\n",  			       iommu->name, ((unsigned long long *)req)[0],  			       ((unsigned long long *)req)[1]); -			goto bad_req; +			goto no_pasid;  		}  		if (!svm || svm->pasid != req->pasid) { diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c index b98a03189580..ddf3a492e1d5 100644 --- a/drivers/iommu/ipmmu-vmsa.c +++ b/drivers/iommu/ipmmu-vmsa.c @@ -498,6 +498,9 @@ static int ipmmu_domain_init_context(struct ipmmu_vmsa_domain *domain)  static void ipmmu_domain_destroy_context(struct ipmmu_vmsa_domain *domain)  { +	if (!domain->mmu) +		return; +  	/*  	 * Disable the context. Flush the TLB as required when modifying the  	 * context registers. diff --git a/drivers/media/cec/cec-adap.c b/drivers/media/cec/cec-adap.c index 31d1f4ab915e..65a933a21e68 100644 --- a/drivers/media/cec/cec-adap.c +++ b/drivers/media/cec/cec-adap.c @@ -807,7 +807,7 @@ int cec_transmit_msg_fh(struct cec_adapter *adap, struct cec_msg *msg,  	}  	if (adap->transmit_queue_sz >= CEC_MAX_MSG_TX_QUEUE_SZ) { -		dprintk(1, "%s: transmit queue full\n", __func__); +		dprintk(2, "%s: transmit queue full\n", __func__);  		return -EBUSY;  	} @@ -1180,6 +1180,8 @@ static int cec_config_log_addr(struct cec_adapter *adap,  {  	struct cec_log_addrs *las = &adap->log_addrs;  	struct cec_msg msg = { }; +	const unsigned int max_retries = 2; +	unsigned int i;  	int err;  	if (cec_has_log_addr(adap, log_addr)) @@ -1188,19 +1190,44 @@ static int cec_config_log_addr(struct cec_adapter *adap,  	/* Send poll message */  	msg.len = 1;  	msg.msg[0] = (log_addr << 4) | log_addr; -	err = cec_transmit_msg_fh(adap, &msg, NULL, true); -	/* -	 * While trying to poll the physical address was reset -	 * and the adapter was unconfigured, so bail out. -	 */ -	if (!adap->is_configuring) -		return -EINTR; +	for (i = 0; i < max_retries; i++) { +		err = cec_transmit_msg_fh(adap, &msg, NULL, true); -	if (err) -		return err; +		/* +		 * While trying to poll the physical address was reset +		 * and the adapter was unconfigured, so bail out. +		 */ +		if (!adap->is_configuring) +			return -EINTR; + +		if (err) +			return err; -	if (msg.tx_status & CEC_TX_STATUS_OK) +		/* +		 * The message was aborted due to a disconnect or +		 * unconfigure, just bail out. +		 */ +		if (msg.tx_status & CEC_TX_STATUS_ABORTED) +			return -EINTR; +		if (msg.tx_status & CEC_TX_STATUS_OK) +			return 0; +		if (msg.tx_status & CEC_TX_STATUS_NACK) +			break; +		/* +		 * Retry up to max_retries times if the message was neither +		 * OKed or NACKed. This can happen due to e.g. a Lost +		 * Arbitration condition. +		 */ +	} + +	/* +	 * If we are unable to get an OK or a NACK after max_retries attempts +	 * (and note that each attempt already consists of four polls), then +	 * then we assume that something is really weird and that it is not a +	 * good idea to try and claim this logical address. +	 */ +	if (i == max_retries)  		return 0;  	/* diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index a38e54b8f687..22cafc07de25 100644 --- a/drivers/media/i2c/tc358743.c +++ b/drivers/media/i2c/tc358743.c @@ -1918,7 +1918,6 @@ static int tc358743_probe_of(struct tc358743_state *state)  	ret = v4l2_fwnode_endpoint_alloc_parse(of_fwnode_handle(ep), &endpoint);  	if (ret) {  		dev_err(dev, "failed to parse endpoint\n"); -		ret = ret;  		goto put_node;  	} diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c index 452eb9b42140..447baaebca44 100644 --- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c +++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c @@ -1844,14 +1844,12 @@ fail_mutex_destroy:  static void cio2_pci_remove(struct pci_dev *pci_dev)  {  	struct cio2_device *cio2 = pci_get_drvdata(pci_dev); -	unsigned int i; +	media_device_unregister(&cio2->media_dev);  	cio2_notifier_exit(cio2); +	cio2_queues_exit(cio2);  	cio2_fbpt_exit_dummy(cio2); -	for (i = 0; i < CIO2_QUEUES; i++) -		cio2_queue_exit(cio2, &cio2->queue[i]);  	v4l2_device_unregister(&cio2->v4l2_dev); -	media_device_unregister(&cio2->media_dev);  	media_device_cleanup(&cio2->media_dev);  	mutex_destroy(&cio2->lock);  } diff --git a/drivers/media/platform/omap3isp/isp.c b/drivers/media/platform/omap3isp/isp.c index 77fb7987b42f..13f2828d880d 100644 --- a/drivers/media/platform/omap3isp/isp.c +++ b/drivers/media/platform/omap3isp/isp.c @@ -1587,6 +1587,8 @@ static void isp_pm_complete(struct device *dev)  static void isp_unregister_entities(struct isp_device *isp)  { +	media_device_unregister(&isp->media_dev); +  	omap3isp_csi2_unregister_entities(&isp->isp_csi2a);  	omap3isp_ccp2_unregister_entities(&isp->isp_ccp2);  	omap3isp_ccdc_unregister_entities(&isp->isp_ccdc); @@ -1597,7 +1599,6 @@ static void isp_unregister_entities(struct isp_device *isp)  	omap3isp_stat_unregister_entities(&isp->isp_hist);  	v4l2_device_unregister(&isp->v4l2_dev); -	media_device_unregister(&isp->media_dev);  	media_device_cleanup(&isp->media_dev);  } diff --git a/drivers/media/platform/vicodec/vicodec-core.c b/drivers/media/platform/vicodec/vicodec-core.c index 1eb9132bfc85..b292cff26c86 100644 --- a/drivers/media/platform/vicodec/vicodec-core.c +++ b/drivers/media/platform/vicodec/vicodec-core.c @@ -42,7 +42,7 @@ MODULE_PARM_DESC(debug, " activates debug info");  #define MAX_WIDTH		4096U  #define MIN_WIDTH		640U  #define MAX_HEIGHT		2160U -#define MIN_HEIGHT		480U +#define MIN_HEIGHT		360U  #define dprintk(dev, fmt, arg...) \  	v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg) diff --git a/drivers/media/platform/vim2m.c b/drivers/media/platform/vim2m.c index af150a0395df..d82db738f174 100644 --- a/drivers/media/platform/vim2m.c +++ b/drivers/media/platform/vim2m.c @@ -1009,7 +1009,7 @@ static const struct v4l2_m2m_ops m2m_ops = {  static const struct media_device_ops m2m_media_ops = {  	.req_validate = vb2_request_validate, -	.req_queue = vb2_m2m_request_queue, +	.req_queue = v4l2_m2m_request_queue,  };  static int vim2m_probe(struct platform_device *pdev) diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c index 6e37950292cd..5f2b033a7a42 100644 --- a/drivers/media/v4l2-core/v4l2-ctrls.c +++ b/drivers/media/v4l2-core/v4l2-ctrls.c @@ -1664,6 +1664,11 @@ static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,  		    p_mpeg2_slice_params->forward_ref_index >= VIDEO_MAX_FRAME)  			return -EINVAL; +		if (p_mpeg2_slice_params->pad || +		    p_mpeg2_slice_params->picture.pad || +		    p_mpeg2_slice_params->sequence.pad) +			return -EINVAL; +  		return 0;  	case V4L2_CTRL_TYPE_MPEG2_QUANTIZATION: diff --git a/drivers/media/v4l2-core/v4l2-event.c b/drivers/media/v4l2-core/v4l2-event.c index a3ef1f50a4b3..481e3c65cf97 100644 --- a/drivers/media/v4l2-core/v4l2-event.c +++ b/drivers/media/v4l2-core/v4l2-event.c @@ -193,6 +193,22 @@ int v4l2_event_pending(struct v4l2_fh *fh)  }  EXPORT_SYMBOL_GPL(v4l2_event_pending); +static void __v4l2_event_unsubscribe(struct v4l2_subscribed_event *sev) +{ +	struct v4l2_fh *fh = sev->fh; +	unsigned int i; + +	lockdep_assert_held(&fh->subscribe_lock); +	assert_spin_locked(&fh->vdev->fh_lock); + +	/* Remove any pending events for this subscription */ +	for (i = 0; i < sev->in_use; i++) { +		list_del(&sev->events[sev_pos(sev, i)].list); +		fh->navailable--; +	} +	list_del(&sev->list); +} +  int v4l2_event_subscribe(struct v4l2_fh *fh,  			 const struct v4l2_event_subscription *sub, unsigned elems,  			 const struct v4l2_subscribed_event_ops *ops) @@ -224,27 +240,23 @@ int v4l2_event_subscribe(struct v4l2_fh *fh,  	spin_lock_irqsave(&fh->vdev->fh_lock, flags);  	found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); +	if (!found_ev) +		list_add(&sev->list, &fh->subscribed);  	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);  	if (found_ev) {  		/* Already listening */  		kvfree(sev); -		goto out_unlock; -	} - -	if (sev->ops && sev->ops->add) { +	} else if (sev->ops && sev->ops->add) {  		ret = sev->ops->add(sev, elems);  		if (ret) { +			spin_lock_irqsave(&fh->vdev->fh_lock, flags); +			__v4l2_event_unsubscribe(sev); +			spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);  			kvfree(sev); -			goto out_unlock;  		}  	} -	spin_lock_irqsave(&fh->vdev->fh_lock, flags); -	list_add(&sev->list, &fh->subscribed); -	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); - -out_unlock:  	mutex_unlock(&fh->subscribe_lock);  	return ret; @@ -279,7 +291,6 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,  {  	struct v4l2_subscribed_event *sev;  	unsigned long flags; -	int i;  	if (sub->type == V4L2_EVENT_ALL) {  		v4l2_event_unsubscribe_all(fh); @@ -291,14 +302,8 @@ int v4l2_event_unsubscribe(struct v4l2_fh *fh,  	spin_lock_irqsave(&fh->vdev->fh_lock, flags);  	sev = v4l2_event_subscribed(fh, sub->type, sub->id); -	if (sev != NULL) { -		/* Remove any pending events for this subscription */ -		for (i = 0; i < sev->in_use; i++) { -			list_del(&sev->events[sev_pos(sev, i)].list); -			fh->navailable--; -		} -		list_del(&sev->list); -	} +	if (sev != NULL) +		__v4l2_event_unsubscribe(sev);  	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c index d7806db222d8..1ed2465972ac 100644 --- a/drivers/media/v4l2-core/v4l2-mem2mem.c +++ b/drivers/media/v4l2-core/v4l2-mem2mem.c @@ -953,7 +953,7 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx,  }  EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue); -void vb2_m2m_request_queue(struct media_request *req) +void v4l2_m2m_request_queue(struct media_request *req)  {  	struct media_request_object *obj, *obj_safe;  	struct v4l2_m2m_ctx *m2m_ctx = NULL; @@ -997,7 +997,7 @@ void vb2_m2m_request_queue(struct media_request *req)  	if (m2m_ctx)  		v4l2_m2m_try_schedule(m2m_ctx);  } -EXPORT_SYMBOL_GPL(vb2_m2m_request_queue); +EXPORT_SYMBOL_GPL(v4l2_m2m_request_queue);  /* Videobuf2 ioctl helpers */ diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index b2a0340f277e..d8e3cc2dc747 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c @@ -132,7 +132,7 @@ static const struct of_device_id atmel_ssc_dt_ids[] = {  MODULE_DEVICE_TABLE(of, atmel_ssc_dt_ids);  #endif -static inline const struct atmel_ssc_platform_data * __init +static inline const struct atmel_ssc_platform_data *  	atmel_ssc_get_driver_data(struct platform_device *pdev)  {  	if (pdev->dev.of_node) { diff --git a/drivers/misc/sgi-gru/grukdump.c b/drivers/misc/sgi-gru/grukdump.c index 313da3150262..1540a7785e14 100644 --- a/drivers/misc/sgi-gru/grukdump.c +++ b/drivers/misc/sgi-gru/grukdump.c @@ -27,6 +27,9 @@  #include <linux/delay.h>  #include <linux/bitops.h>  #include <asm/uv/uv_hub.h> + +#include <linux/nospec.h> +  #include "gru.h"  #include "grutables.h"  #include "gruhandles.h" @@ -196,6 +199,7 @@ int gru_dump_chiplet_request(unsigned long arg)  	/* Currently, only dump by gid is implemented */  	if (req.gid >= gru_max_gids)  		return -EINVAL; +	req.gid = array_index_nospec(req.gid, gru_max_gids);  	gru = GID_TO_GRU(req.gid);  	ubuf = req.buf; diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c index 7bfd366d970d..c4115bae5db1 100644 --- a/drivers/mmc/host/sdhci-pci-core.c +++ b/drivers/mmc/host/sdhci-pci-core.c @@ -12,6 +12,7 @@   *     - JMicron (hardware and technical support)   */ +#include <linux/bitfield.h>  #include <linux/string.h>  #include <linux/delay.h>  #include <linux/highmem.h> @@ -462,6 +463,9 @@ struct intel_host {  	u32	dsm_fns;  	int	drv_strength;  	bool	d3_retune; +	bool	rpm_retune_ok; +	u32	glk_rx_ctrl1; +	u32	glk_tun_val;  };  static const guid_t intel_dsm_guid = @@ -791,6 +795,77 @@ cleanup:  	return ret;  } +#ifdef CONFIG_PM +#define GLK_RX_CTRL1	0x834 +#define GLK_TUN_VAL	0x840 +#define GLK_PATH_PLL	GENMASK(13, 8) +#define GLK_DLY		GENMASK(6, 0) +/* Workaround firmware failing to restore the tuning value */ +static void glk_rpm_retune_wa(struct sdhci_pci_chip *chip, bool susp) +{ +	struct sdhci_pci_slot *slot = chip->slots[0]; +	struct intel_host *intel_host = sdhci_pci_priv(slot); +	struct sdhci_host *host = slot->host; +	u32 glk_rx_ctrl1; +	u32 glk_tun_val; +	u32 dly; + +	if (intel_host->rpm_retune_ok || !mmc_can_retune(host->mmc)) +		return; + +	glk_rx_ctrl1 = sdhci_readl(host, GLK_RX_CTRL1); +	glk_tun_val = sdhci_readl(host, GLK_TUN_VAL); + +	if (susp) { +		intel_host->glk_rx_ctrl1 = glk_rx_ctrl1; +		intel_host->glk_tun_val = glk_tun_val; +		return; +	} + +	if (!intel_host->glk_tun_val) +		return; + +	if (glk_rx_ctrl1 != intel_host->glk_rx_ctrl1) { +		intel_host->rpm_retune_ok = true; +		return; +	} + +	dly = FIELD_PREP(GLK_DLY, FIELD_GET(GLK_PATH_PLL, glk_rx_ctrl1) + +				  (intel_host->glk_tun_val << 1)); +	if (dly == FIELD_GET(GLK_DLY, glk_rx_ctrl1)) +		return; + +	glk_rx_ctrl1 = (glk_rx_ctrl1 & ~GLK_DLY) | dly; +	sdhci_writel(host, glk_rx_ctrl1, GLK_RX_CTRL1); + +	intel_host->rpm_retune_ok = true; +	chip->rpm_retune = true; +	mmc_retune_needed(host->mmc); +	pr_info("%s: Requiring re-tune after rpm resume", mmc_hostname(host->mmc)); +} + +static void glk_rpm_retune_chk(struct sdhci_pci_chip *chip, bool susp) +{ +	if (chip->pdev->device == PCI_DEVICE_ID_INTEL_GLK_EMMC && +	    !chip->rpm_retune) +		glk_rpm_retune_wa(chip, susp); +} + +static int glk_runtime_suspend(struct sdhci_pci_chip *chip) +{ +	glk_rpm_retune_chk(chip, true); + +	return sdhci_cqhci_runtime_suspend(chip); +} + +static int glk_runtime_resume(struct sdhci_pci_chip *chip) +{ +	glk_rpm_retune_chk(chip, false); + +	return sdhci_cqhci_runtime_resume(chip); +} +#endif +  #ifdef CONFIG_ACPI  static int ni_set_max_freq(struct sdhci_pci_slot *slot)  { @@ -879,8 +954,8 @@ static const struct sdhci_pci_fixes sdhci_intel_glk_emmc = {  	.resume			= sdhci_cqhci_resume,  #endif  #ifdef CONFIG_PM -	.runtime_suspend	= sdhci_cqhci_runtime_suspend, -	.runtime_resume		= sdhci_cqhci_runtime_resume, +	.runtime_suspend	= glk_runtime_suspend, +	.runtime_resume		= glk_runtime_resume,  #endif  	.quirks			= SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC,  	.quirks2		= SDHCI_QUIRK2_PRESET_VALUE_BROKEN | @@ -1762,8 +1837,13 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(  		device_init_wakeup(&pdev->dev, true);  	if (slot->cd_idx >= 0) { -		ret = mmc_gpiod_request_cd(host->mmc, NULL, slot->cd_idx, +		ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx,  					   slot->cd_override_level, 0, NULL); +		if (ret && ret != -EPROBE_DEFER) +			ret = mmc_gpiod_request_cd(host->mmc, NULL, +						   slot->cd_idx, +						   slot->cd_override_level, +						   0, NULL);  		if (ret == -EPROBE_DEFER)  			goto remove; diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c index fb33f6be7c4f..ad720494e8f7 100644 --- a/drivers/mtd/nand/raw/atmel/nand-controller.c +++ b/drivers/mtd/nand/raw/atmel/nand-controller.c @@ -2032,8 +2032,7 @@ atmel_hsmc_nand_controller_legacy_init(struct atmel_hsmc_nand_controller *nc)  	int ret;  	nand_np = dev->of_node; -	nfc_np = of_find_compatible_node(dev->of_node, NULL, -					 "atmel,sama5d3-nfc"); +	nfc_np = of_get_compatible_child(dev->of_node, "atmel,sama5d3-nfc");  	if (!nfc_np) {  		dev_err(dev, "Could not find device node for sama5d3-nfc\n");  		return -ENODEV; @@ -2447,15 +2446,19 @@ static int atmel_nand_controller_probe(struct platform_device *pdev)  	}  	if (caps->legacy_of_bindings) { +		struct device_node *nfc_node;  		u32 ale_offs = 21;  		/*  		 * If we are parsing legacy DT props and the DT contains a  		 * valid NFC node, forward the request to the sama5 logic.  		 */ -		if (of_find_compatible_node(pdev->dev.of_node, NULL, -					    "atmel,sama5d3-nfc")) +		nfc_node = of_get_compatible_child(pdev->dev.of_node, +						   "atmel,sama5d3-nfc"); +		if (nfc_node) {  			caps = &atmel_sama5_nand_caps; +			of_node_put(nfc_node); +		}  		/*  		 * Even if the compatible says we are dealing with an diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c index ef75dfa62a4f..699d3cf49c6d 100644 --- a/drivers/mtd/nand/raw/qcom_nandc.c +++ b/drivers/mtd/nand/raw/qcom_nandc.c @@ -150,15 +150,15 @@  #define	NAND_VERSION_MINOR_SHIFT	16  /* NAND OP_CMDs */ -#define	PAGE_READ			0x2 -#define	PAGE_READ_WITH_ECC		0x3 -#define	PAGE_READ_WITH_ECC_SPARE	0x4 -#define	PROGRAM_PAGE			0x6 -#define	PAGE_PROGRAM_WITH_ECC		0x7 -#define	PROGRAM_PAGE_SPARE		0x9 -#define	BLOCK_ERASE			0xa -#define	FETCH_ID			0xb -#define	RESET_DEVICE			0xd +#define	OP_PAGE_READ			0x2 +#define	OP_PAGE_READ_WITH_ECC		0x3 +#define	OP_PAGE_READ_WITH_ECC_SPARE	0x4 +#define	OP_PROGRAM_PAGE			0x6 +#define	OP_PAGE_PROGRAM_WITH_ECC	0x7 +#define	OP_PROGRAM_PAGE_SPARE		0x9 +#define	OP_BLOCK_ERASE			0xa +#define	OP_FETCH_ID			0xb +#define	OP_RESET_DEVICE			0xd  /* Default Value for NAND_DEV_CMD_VLD */  #define NAND_DEV_CMD_VLD_VAL		(READ_START_VLD | WRITE_START_VLD | \ @@ -692,11 +692,11 @@ static void update_rw_regs(struct qcom_nand_host *host, int num_cw, bool read)  	if (read) {  		if (host->use_ecc) -			cmd = PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE; +			cmd = OP_PAGE_READ_WITH_ECC | PAGE_ACC | LAST_PAGE;  		else -			cmd = PAGE_READ | PAGE_ACC | LAST_PAGE; +			cmd = OP_PAGE_READ | PAGE_ACC | LAST_PAGE;  	} else { -			cmd = PROGRAM_PAGE | PAGE_ACC | LAST_PAGE; +		cmd = OP_PROGRAM_PAGE | PAGE_ACC | LAST_PAGE;  	}  	if (host->use_ecc) { @@ -1170,7 +1170,7 @@ static int nandc_param(struct qcom_nand_host *host)  	 * in use. we configure the controller to perform a raw read of 512  	 * bytes to read onfi params  	 */ -	nandc_set_reg(nandc, NAND_FLASH_CMD, PAGE_READ | PAGE_ACC | LAST_PAGE); +	nandc_set_reg(nandc, NAND_FLASH_CMD, OP_PAGE_READ | PAGE_ACC | LAST_PAGE);  	nandc_set_reg(nandc, NAND_ADDR0, 0);  	nandc_set_reg(nandc, NAND_ADDR1, 0);  	nandc_set_reg(nandc, NAND_DEV0_CFG0, 0 << CW_PER_PAGE @@ -1224,7 +1224,7 @@ static int erase_block(struct qcom_nand_host *host, int page_addr)  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip);  	nandc_set_reg(nandc, NAND_FLASH_CMD, -		      BLOCK_ERASE | PAGE_ACC | LAST_PAGE); +		      OP_BLOCK_ERASE | PAGE_ACC | LAST_PAGE);  	nandc_set_reg(nandc, NAND_ADDR0, page_addr);  	nandc_set_reg(nandc, NAND_ADDR1, 0);  	nandc_set_reg(nandc, NAND_DEV0_CFG0, @@ -1255,7 +1255,7 @@ static int read_id(struct qcom_nand_host *host, int column)  	if (column == -1)  		return 0; -	nandc_set_reg(nandc, NAND_FLASH_CMD, FETCH_ID); +	nandc_set_reg(nandc, NAND_FLASH_CMD, OP_FETCH_ID);  	nandc_set_reg(nandc, NAND_ADDR0, column);  	nandc_set_reg(nandc, NAND_ADDR1, 0);  	nandc_set_reg(nandc, NAND_FLASH_CHIP_SELECT, @@ -1276,7 +1276,7 @@ static int reset(struct qcom_nand_host *host)  	struct nand_chip *chip = &host->chip;  	struct qcom_nand_controller *nandc = get_qcom_nand_controller(chip); -	nandc_set_reg(nandc, NAND_FLASH_CMD, RESET_DEVICE); +	nandc_set_reg(nandc, NAND_FLASH_CMD, OP_RESET_DEVICE);  	nandc_set_reg(nandc, NAND_EXEC_CMD, 1);  	write_reg_dma(nandc, NAND_FLASH_CMD, 1, NAND_BAM_NEXT_SGL); diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c index d846428ef038..04cedd3a2bf6 100644 --- a/drivers/mtd/spi-nor/cadence-quadspi.c +++ b/drivers/mtd/spi-nor/cadence-quadspi.c @@ -644,9 +644,23 @@ static int cqspi_indirect_write_execute(struct spi_nor *nor, loff_t to_addr,  		ndelay(cqspi->wr_delay);  	while (remaining > 0) { +		size_t write_words, mod_bytes; +  		write_bytes = remaining > page_size ? page_size : remaining; -		iowrite32_rep(cqspi->ahb_base, txbuf, -			      DIV_ROUND_UP(write_bytes, 4)); +		write_words = write_bytes / 4; +		mod_bytes = write_bytes % 4; +		/* Write 4 bytes at a time then single bytes. */ +		if (write_words) { +			iowrite32_rep(cqspi->ahb_base, txbuf, write_words); +			txbuf += (write_words * 4); +		} +		if (mod_bytes) { +			unsigned int temp = 0xFFFFFFFF; + +			memcpy(&temp, txbuf, mod_bytes); +			iowrite32(temp, cqspi->ahb_base); +			txbuf += mod_bytes; +		}  		if (!wait_for_completion_timeout(&cqspi->transfer_complete,  					msecs_to_jiffies(CQSPI_TIMEOUT_MS))) { @@ -655,7 +669,6 @@ static int cqspi_indirect_write_execute(struct spi_nor *nor, loff_t to_addr,  			goto failwr;  		} -		txbuf += write_bytes;  		remaining -= write_bytes;  		if (remaining > 0) diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 3e54e31889c7..93c9bc8931fc 100644 --- a/drivers/mtd/spi-nor/spi-nor.c +++ b/drivers/mtd/spi-nor/spi-nor.c @@ -2156,7 +2156,7 @@ spi_nor_set_pp_settings(struct spi_nor_pp_command *pp,   * @nor:	pointer to a 'struct spi_nor'   * @addr:	offset in the serial flash memory   * @len:	number of bytes to read - * @buf:	buffer where the data is copied into + * @buf:	buffer where the data is copied into (dma-safe memory)   *   * Return: 0 on success, -errno otherwise.   */ @@ -2522,6 +2522,34 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)  }  /** + * spi_nor_sort_erase_mask() - sort erase mask + * @map:	the erase map of the SPI NOR + * @erase_mask:	the erase type mask to be sorted + * + * Replicate the sort done for the map's erase types in BFPT: sort the erase + * mask in ascending order with the smallest erase type size starting from + * BIT(0) in the sorted erase mask. + * + * Return: sorted erase mask. + */ +static u8 spi_nor_sort_erase_mask(struct spi_nor_erase_map *map, u8 erase_mask) +{ +	struct spi_nor_erase_type *erase_type = map->erase_type; +	int i; +	u8 sorted_erase_mask = 0; + +	if (!erase_mask) +		return 0; + +	/* Replicate the sort done for the map's erase types. */ +	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) +		if (erase_type[i].size && erase_mask & BIT(erase_type[i].idx)) +			sorted_erase_mask |= BIT(i); + +	return sorted_erase_mask; +} + +/**   * spi_nor_regions_sort_erase_types() - sort erase types in each region   * @map:	the erase map of the SPI NOR   * @@ -2536,19 +2564,13 @@ static int spi_nor_map_cmp_erase_type(const void *l, const void *r)  static void spi_nor_regions_sort_erase_types(struct spi_nor_erase_map *map)  {  	struct spi_nor_erase_region *region = map->regions; -	struct spi_nor_erase_type *erase_type = map->erase_type; -	int i;  	u8 region_erase_mask, sorted_erase_mask;  	while (region) {  		region_erase_mask = region->offset & SNOR_ERASE_TYPE_MASK; -		/* Replicate the sort done for the map's erase types. */ -		sorted_erase_mask = 0; -		for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) -			if (erase_type[i].size && -			    region_erase_mask & BIT(erase_type[i].idx)) -				sorted_erase_mask |= BIT(i); +		sorted_erase_mask = spi_nor_sort_erase_mask(map, +							    region_erase_mask);  		/* Overwrite erase mask. */  		region->offset = (region->offset & ~SNOR_ERASE_TYPE_MASK) | @@ -2855,52 +2877,84 @@ static u8 spi_nor_smpt_read_dummy(const struct spi_nor *nor, const u32 settings)   * spi_nor_get_map_in_use() - get the configuration map in use   * @nor:	pointer to a 'struct spi_nor'   * @smpt:	pointer to the sector map parameter table + * @smpt_len:	sector map parameter table length + * + * Return: pointer to the map in use, ERR_PTR(-errno) otherwise.   */ -static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt) +static const u32 *spi_nor_get_map_in_use(struct spi_nor *nor, const u32 *smpt, +					 u8 smpt_len)  { -	const u32 *ret = NULL; -	u32 i, addr; +	const u32 *ret; +	u8 *buf; +	u32 addr;  	int err; +	u8 i;  	u8 addr_width, read_opcode, read_dummy; -	u8 read_data_mask, data_byte, map_id; +	u8 read_data_mask, map_id; + +	/* Use a kmalloc'ed bounce buffer to guarantee it is DMA-able. */ +	buf = kmalloc(sizeof(*buf), GFP_KERNEL); +	if (!buf) +		return ERR_PTR(-ENOMEM);  	addr_width = nor->addr_width;  	read_dummy = nor->read_dummy;  	read_opcode = nor->read_opcode;  	map_id = 0; -	i = 0;  	/* Determine if there are any optional Detection Command Descriptors */ -	while (!(smpt[i] & SMPT_DESC_TYPE_MAP)) { +	for (i = 0; i < smpt_len; i += 2) { +		if (smpt[i] & SMPT_DESC_TYPE_MAP) +			break; +  		read_data_mask = SMPT_CMD_READ_DATA(smpt[i]);  		nor->addr_width = spi_nor_smpt_addr_width(nor, smpt[i]);  		nor->read_dummy = spi_nor_smpt_read_dummy(nor, smpt[i]);  		nor->read_opcode = SMPT_CMD_OPCODE(smpt[i]);  		addr = smpt[i + 1]; -		err = spi_nor_read_raw(nor, addr, 1, &data_byte); -		if (err) +		err = spi_nor_read_raw(nor, addr, 1, buf); +		if (err) { +			ret = ERR_PTR(err);  			goto out; +		}  		/*  		 * Build an index value that is used to select the Sector Map  		 * Configuration that is currently in use.  		 */ -		map_id = map_id << 1 | !!(data_byte & read_data_mask); -		i = i + 2; +		map_id = map_id << 1 | !!(*buf & read_data_mask);  	} -	/* Find the matching configuration map */ -	while (SMPT_MAP_ID(smpt[i]) != map_id) { +	/* +	 * If command descriptors are provided, they always precede map +	 * descriptors in the table. There is no need to start the iteration +	 * over smpt array all over again. +	 * +	 * Find the matching configuration map. +	 */ +	ret = ERR_PTR(-EINVAL); +	while (i < smpt_len) { +		if (SMPT_MAP_ID(smpt[i]) == map_id) { +			ret = smpt + i; +			break; +		} + +		/* +		 * If there are no more configuration map descriptors and no +		 * configuration ID matched the configuration identifier, the +		 * sector address map is unknown. +		 */  		if (smpt[i] & SMPT_DESC_END) -			goto out; +			break; +  		/* increment the table index to the next map */  		i += SMPT_MAP_REGION_COUNT(smpt[i]) + 1;  	} -	ret = smpt + i;  	/* fall through */  out: +	kfree(buf);  	nor->addr_width = addr_width;  	nor->read_dummy = read_dummy;  	nor->read_opcode = read_opcode; @@ -2946,7 +3000,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,  	u64 offset;  	u32 region_count;  	int i, j; -	u8 erase_type; +	u8 erase_type, uniform_erase_type;  	region_count = SMPT_MAP_REGION_COUNT(*smpt);  	/* @@ -2959,7 +3013,7 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,  		return -ENOMEM;  	map->regions = region; -	map->uniform_erase_type = 0xff; +	uniform_erase_type = 0xff;  	offset = 0;  	/* Populate regions. */  	for (i = 0; i < region_count; i++) { @@ -2974,12 +3028,15 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,  		 * Save the erase types that are supported in all regions and  		 * can erase the entire flash memory.  		 */ -		map->uniform_erase_type &= erase_type; +		uniform_erase_type &= erase_type;  		offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +  			 region[i].size;  	} +	map->uniform_erase_type = spi_nor_sort_erase_mask(map, +							  uniform_erase_type); +  	spi_nor_region_mark_end(®ion[i - 1]);  	return 0; @@ -3020,9 +3077,9 @@ static int spi_nor_parse_smpt(struct spi_nor *nor,  	for (i = 0; i < smpt_header->length; i++)  		smpt[i] = le32_to_cpu(smpt[i]); -	sector_map = spi_nor_get_map_in_use(nor, smpt); -	if (!sector_map) { -		ret = -EINVAL; +	sector_map = spi_nor_get_map_in_use(nor, smpt, smpt_header->length); +	if (IS_ERR(sector_map)) { +		ret = PTR_ERR(sector_map);  		goto out;  	} @@ -3125,7 +3182,7 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,  	if (err)  		goto exit; -	/* Parse other parameter headers. */ +	/* Parse optional parameter tables. */  	for (i = 0; i < header.nph; i++) {  		param_header = ¶m_headers[i]; @@ -3138,8 +3195,17 @@ static int spi_nor_parse_sfdp(struct spi_nor *nor,  			break;  		} -		if (err) -			goto exit; +		if (err) { +			dev_warn(dev, "Failed to parse optional parameter table: %04x\n", +				 SFDP_PARAM_HEADER_ID(param_header)); +			/* +			 * Let's not drop all information we extracted so far +			 * if optional table parsers fail. In case of failing, +			 * each optional parser is responsible to roll back to +			 * the previously known spi_nor data. +			 */ +			err = 0; +		}  	}  exit: diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 49163570a63a..3b3f88ffab53 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c @@ -477,6 +477,34 @@ void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,  }  EXPORT_SYMBOL_GPL(can_put_echo_skb); +struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr) +{ +	struct can_priv *priv = netdev_priv(dev); +	struct sk_buff *skb = priv->echo_skb[idx]; +	struct canfd_frame *cf; + +	if (idx >= priv->echo_skb_max) { +		netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n", +			   __func__, idx, priv->echo_skb_max); +		return NULL; +	} + +	if (!skb) { +		netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n", +			   __func__, idx); +		return NULL; +	} + +	/* Using "struct canfd_frame::len" for the frame +	 * length is supported on both CAN and CANFD frames. +	 */ +	cf = (struct canfd_frame *)skb->data; +	*len_ptr = cf->len; +	priv->echo_skb[idx] = NULL; + +	return skb; +} +  /*   * Get the skb from the stack and loop it back locally   * @@ -486,22 +514,16 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);   */  unsigned int can_get_echo_skb(struct net_device *dev, unsigned int idx)  { -	struct can_priv *priv = netdev_priv(dev); - -	BUG_ON(idx >= priv->echo_skb_max); - -	if (priv->echo_skb[idx]) { -		struct sk_buff *skb = priv->echo_skb[idx]; -		struct can_frame *cf = (struct can_frame *)skb->data; -		u8 dlc = cf->can_dlc; +	struct sk_buff *skb; +	u8 len; -		netif_rx(priv->echo_skb[idx]); -		priv->echo_skb[idx] = NULL; +	skb = __can_get_echo_skb(dev, idx, &len); +	if (!skb) +		return 0; -		return dlc; -	} +	netif_rx(skb); -	return 0; +	return len;  }  EXPORT_SYMBOL_GPL(can_get_echo_skb); diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 8e972ef08637..75ce11395ee8 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -135,13 +135,12 @@  /* FLEXCAN interrupt flag register (IFLAG) bits */  /* Errata ERR005829 step7: Reserve first valid MB */ -#define FLEXCAN_TX_MB_RESERVED_OFF_FIFO	8 -#define FLEXCAN_TX_MB_OFF_FIFO		9 +#define FLEXCAN_TX_MB_RESERVED_OFF_FIFO		8  #define FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP	0 -#define FLEXCAN_TX_MB_OFF_TIMESTAMP		1 -#define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST	(FLEXCAN_TX_MB_OFF_TIMESTAMP + 1) -#define FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST	63 -#define FLEXCAN_IFLAG_MB(x)		BIT(x) +#define FLEXCAN_TX_MB				63 +#define FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST	(FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP + 1) +#define FLEXCAN_RX_MB_OFF_TIMESTAMP_LAST	(FLEXCAN_TX_MB - 1) +#define FLEXCAN_IFLAG_MB(x)		BIT(x & 0x1f)  #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW	BIT(7)  #define FLEXCAN_IFLAG_RX_FIFO_WARN	BIT(6)  #define FLEXCAN_IFLAG_RX_FIFO_AVAILABLE	BIT(5) @@ -259,9 +258,7 @@ struct flexcan_priv {  	struct can_rx_offload offload;  	struct flexcan_regs __iomem *regs; -	struct flexcan_mb __iomem *tx_mb;  	struct flexcan_mb __iomem *tx_mb_reserved; -	u8 tx_mb_idx;  	u32 reg_ctrl_default;  	u32 reg_imask1_default;  	u32 reg_imask2_default; @@ -515,6 +512,7 @@ static int flexcan_get_berr_counter(const struct net_device *dev,  static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev)  {  	const struct flexcan_priv *priv = netdev_priv(dev); +	struct flexcan_regs __iomem *regs = priv->regs;  	struct can_frame *cf = (struct can_frame *)skb->data;  	u32 can_id;  	u32 data; @@ -537,17 +535,17 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de  	if (cf->can_dlc > 0) {  		data = be32_to_cpup((__be32 *)&cf->data[0]); -		priv->write(data, &priv->tx_mb->data[0]); +		priv->write(data, ®s->mb[FLEXCAN_TX_MB].data[0]);  	}  	if (cf->can_dlc > 4) {  		data = be32_to_cpup((__be32 *)&cf->data[4]); -		priv->write(data, &priv->tx_mb->data[1]); +		priv->write(data, ®s->mb[FLEXCAN_TX_MB].data[1]);  	}  	can_put_echo_skb(skb, dev, 0); -	priv->write(can_id, &priv->tx_mb->can_id); -	priv->write(ctrl, &priv->tx_mb->can_ctrl); +	priv->write(can_id, ®s->mb[FLEXCAN_TX_MB].can_id); +	priv->write(ctrl, ®s->mb[FLEXCAN_TX_MB].can_ctrl);  	/* Errata ERR005829 step8:  	 * Write twice INACTIVE(0x8) code to first MB. @@ -563,9 +561,13 @@ static netdev_tx_t flexcan_start_xmit(struct sk_buff *skb, struct net_device *de  static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)  {  	struct flexcan_priv *priv = netdev_priv(dev); +	struct flexcan_regs __iomem *regs = priv->regs;  	struct sk_buff *skb;  	struct can_frame *cf;  	bool rx_errors = false, tx_errors = false; +	u32 timestamp; + +	timestamp = priv->read(®s->timer) << 16;  	skb = alloc_can_err_skb(dev, &cf);  	if (unlikely(!skb)) @@ -612,17 +614,21 @@ static void flexcan_irq_bus_err(struct net_device *dev, u32 reg_esr)  	if (tx_errors)  		dev->stats.tx_errors++; -	can_rx_offload_irq_queue_err_skb(&priv->offload, skb); +	can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);  }  static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)  {  	struct flexcan_priv *priv = netdev_priv(dev); +	struct flexcan_regs __iomem *regs = priv->regs;  	struct sk_buff *skb;  	struct can_frame *cf;  	enum can_state new_state, rx_state, tx_state;  	int flt;  	struct can_berr_counter bec; +	u32 timestamp; + +	timestamp = priv->read(®s->timer) << 16;  	flt = reg_esr & FLEXCAN_ESR_FLT_CONF_MASK;  	if (likely(flt == FLEXCAN_ESR_FLT_CONF_ACTIVE)) { @@ -652,7 +658,7 @@ static void flexcan_irq_state(struct net_device *dev, u32 reg_esr)  	if (unlikely(new_state == CAN_STATE_BUS_OFF))  		can_bus_off(dev); -	can_rx_offload_irq_queue_err_skb(&priv->offload, skb); +	can_rx_offload_queue_sorted(&priv->offload, skb, timestamp);  }  static inline struct flexcan_priv *rx_offload_to_priv(struct can_rx_offload *offload) @@ -720,9 +726,14 @@ static unsigned int flexcan_mailbox_read(struct can_rx_offload *offload,  			priv->write(BIT(n - 32), ®s->iflag2);  	} else {  		priv->write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, ®s->iflag1); -		priv->read(®s->timer);  	} +	/* Read the Free Running Timer. It is optional but recommended +	 * to unlock Mailbox as soon as possible and make it available +	 * for reception. +	 */ +	priv->read(®s->timer); +  	return 1;  } @@ -732,9 +743,9 @@ static inline u64 flexcan_read_reg_iflag_rx(struct flexcan_priv *priv)  	struct flexcan_regs __iomem *regs = priv->regs;  	u32 iflag1, iflag2; -	iflag2 = priv->read(®s->iflag2) & priv->reg_imask2_default; -	iflag1 = priv->read(®s->iflag1) & priv->reg_imask1_default & -		~FLEXCAN_IFLAG_MB(priv->tx_mb_idx); +	iflag2 = priv->read(®s->iflag2) & priv->reg_imask2_default & +		~FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB); +	iflag1 = priv->read(®s->iflag1) & priv->reg_imask1_default;  	return (u64)iflag2 << 32 | iflag1;  } @@ -746,11 +757,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)  	struct flexcan_priv *priv = netdev_priv(dev);  	struct flexcan_regs __iomem *regs = priv->regs;  	irqreturn_t handled = IRQ_NONE; -	u32 reg_iflag1, reg_esr; +	u32 reg_iflag2, reg_esr;  	enum can_state last_state = priv->can.state; -	reg_iflag1 = priv->read(®s->iflag1); -  	/* reception interrupt */  	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {  		u64 reg_iflag; @@ -764,6 +773,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)  				break;  		}  	} else { +		u32 reg_iflag1; + +		reg_iflag1 = priv->read(®s->iflag1);  		if (reg_iflag1 & FLEXCAN_IFLAG_RX_FIFO_AVAILABLE) {  			handled = IRQ_HANDLED;  			can_rx_offload_irq_offload_fifo(&priv->offload); @@ -779,17 +791,22 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)  		}  	} +	reg_iflag2 = priv->read(®s->iflag2); +  	/* transmission complete interrupt */ -	if (reg_iflag1 & FLEXCAN_IFLAG_MB(priv->tx_mb_idx)) { +	if (reg_iflag2 & FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB)) { +		u32 reg_ctrl = priv->read(®s->mb[FLEXCAN_TX_MB].can_ctrl); +  		handled = IRQ_HANDLED; -		stats->tx_bytes += can_get_echo_skb(dev, 0); +		stats->tx_bytes += can_rx_offload_get_echo_skb(&priv->offload, +							       0, reg_ctrl << 16);  		stats->tx_packets++;  		can_led_event(dev, CAN_LED_EVENT_TX);  		/* after sending a RTR frame MB is in RX mode */  		priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, -			    &priv->tx_mb->can_ctrl); -		priv->write(FLEXCAN_IFLAG_MB(priv->tx_mb_idx), ®s->iflag1); +			    ®s->mb[FLEXCAN_TX_MB].can_ctrl); +		priv->write(FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB), ®s->iflag2);  		netif_wake_queue(dev);  	} @@ -931,15 +948,13 @@ static int flexcan_chip_start(struct net_device *dev)  	reg_mcr &= ~FLEXCAN_MCR_MAXMB(0xff);  	reg_mcr |= FLEXCAN_MCR_FRZ | FLEXCAN_MCR_HALT | FLEXCAN_MCR_SUPV |  		FLEXCAN_MCR_WRN_EN | FLEXCAN_MCR_SRX_DIS | FLEXCAN_MCR_IRMQ | -		FLEXCAN_MCR_IDAM_C; +		FLEXCAN_MCR_IDAM_C | FLEXCAN_MCR_MAXMB(FLEXCAN_TX_MB); -	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { +	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)  		reg_mcr &= ~FLEXCAN_MCR_FEN; -		reg_mcr |= FLEXCAN_MCR_MAXMB(priv->offload.mb_last); -	} else { -		reg_mcr |= FLEXCAN_MCR_FEN | -			FLEXCAN_MCR_MAXMB(priv->tx_mb_idx); -	} +	else +		reg_mcr |= FLEXCAN_MCR_FEN; +  	netdev_dbg(dev, "%s: writing mcr=0x%08x", __func__, reg_mcr);  	priv->write(reg_mcr, ®s->mcr); @@ -982,16 +997,17 @@ static int flexcan_chip_start(struct net_device *dev)  		priv->write(reg_ctrl2, ®s->ctrl2);  	} -	/* clear and invalidate all mailboxes first */ -	for (i = priv->tx_mb_idx; i < ARRAY_SIZE(regs->mb); i++) { -		priv->write(FLEXCAN_MB_CODE_RX_INACTIVE, -			    ®s->mb[i].can_ctrl); -	} -  	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { -		for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) +		for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) {  			priv->write(FLEXCAN_MB_CODE_RX_EMPTY,  				    ®s->mb[i].can_ctrl); +		} +	} else { +		/* clear and invalidate unused mailboxes first */ +		for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= ARRAY_SIZE(regs->mb); i++) { +			priv->write(FLEXCAN_MB_CODE_RX_INACTIVE, +				    ®s->mb[i].can_ctrl); +		}  	}  	/* Errata ERR005829: mark first TX mailbox as INACTIVE */ @@ -1000,7 +1016,7 @@ static int flexcan_chip_start(struct net_device *dev)  	/* mark TX mailbox as INACTIVE */  	priv->write(FLEXCAN_MB_CODE_TX_INACTIVE, -		    &priv->tx_mb->can_ctrl); +		    ®s->mb[FLEXCAN_TX_MB].can_ctrl);  	/* acceptance mask/acceptance code (accept everything) */  	priv->write(0x0, ®s->rxgmask); @@ -1355,17 +1371,13 @@ static int flexcan_probe(struct platform_device *pdev)  	priv->devtype_data = devtype_data;  	priv->reg_xceiver = reg_xceiver; -	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { -		priv->tx_mb_idx = FLEXCAN_TX_MB_OFF_TIMESTAMP; +	if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)  		priv->tx_mb_reserved = ®s->mb[FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP]; -	} else { -		priv->tx_mb_idx = FLEXCAN_TX_MB_OFF_FIFO; +	else  		priv->tx_mb_reserved = ®s->mb[FLEXCAN_TX_MB_RESERVED_OFF_FIFO]; -	} -	priv->tx_mb = ®s->mb[priv->tx_mb_idx]; -	priv->reg_imask1_default = FLEXCAN_IFLAG_MB(priv->tx_mb_idx); -	priv->reg_imask2_default = 0; +	priv->reg_imask1_default = 0; +	priv->reg_imask2_default = FLEXCAN_IFLAG_MB(FLEXCAN_TX_MB);  	priv->offload.mailbox_read = flexcan_mailbox_read; diff --git a/drivers/net/can/rcar/rcar_can.c b/drivers/net/can/rcar/rcar_can.c index 11662f479e76..771a46083739 100644 --- a/drivers/net/can/rcar/rcar_can.c +++ b/drivers/net/can/rcar/rcar_can.c @@ -24,6 +24,9 @@  #define RCAR_CAN_DRV_NAME	"rcar_can" +#define RCAR_SUPPORTED_CLOCKS	(BIT(CLKR_CLKP1) | BIT(CLKR_CLKP2) | \ +				 BIT(CLKR_CLKEXT)) +  /* Mailbox configuration:   * mailbox 60 - 63 - Rx FIFO mailboxes   * mailbox 56 - 59 - Tx FIFO mailboxes @@ -789,7 +792,7 @@ static int rcar_can_probe(struct platform_device *pdev)  		goto fail_clk;  	} -	if (clock_select >= ARRAY_SIZE(clock_names)) { +	if (!(BIT(clock_select) & RCAR_SUPPORTED_CLOCKS)) {  		err = -EINVAL;  		dev_err(&pdev->dev, "invalid CAN clock selected\n");  		goto fail_clk; diff --git a/drivers/net/can/rx-offload.c b/drivers/net/can/rx-offload.c index c7d05027a7a0..2ce4fa8698c7 100644 --- a/drivers/net/can/rx-offload.c +++ b/drivers/net/can/rx-offload.c @@ -211,7 +211,54 @@ int can_rx_offload_irq_offload_fifo(struct can_rx_offload *offload)  }  EXPORT_SYMBOL_GPL(can_rx_offload_irq_offload_fifo); -int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_buff *skb) +int can_rx_offload_queue_sorted(struct can_rx_offload *offload, +				struct sk_buff *skb, u32 timestamp) +{ +	struct can_rx_offload_cb *cb; +	unsigned long flags; + +	if (skb_queue_len(&offload->skb_queue) > +	    offload->skb_queue_len_max) +		return -ENOMEM; + +	cb = can_rx_offload_get_cb(skb); +	cb->timestamp = timestamp; + +	spin_lock_irqsave(&offload->skb_queue.lock, flags); +	__skb_queue_add_sort(&offload->skb_queue, skb, can_rx_offload_compare); +	spin_unlock_irqrestore(&offload->skb_queue.lock, flags); + +	can_rx_offload_schedule(offload); + +	return 0; +} +EXPORT_SYMBOL_GPL(can_rx_offload_queue_sorted); + +unsigned int can_rx_offload_get_echo_skb(struct can_rx_offload *offload, +					 unsigned int idx, u32 timestamp) +{ +	struct net_device *dev = offload->dev; +	struct net_device_stats *stats = &dev->stats; +	struct sk_buff *skb; +	u8 len; +	int err; + +	skb = __can_get_echo_skb(dev, idx, &len); +	if (!skb) +		return 0; + +	err = can_rx_offload_queue_sorted(offload, skb, timestamp); +	if (err) { +		stats->rx_errors++; +		stats->tx_fifo_errors++; +	} + +	return len; +} +EXPORT_SYMBOL_GPL(can_rx_offload_get_echo_skb); + +int can_rx_offload_queue_tail(struct can_rx_offload *offload, +			      struct sk_buff *skb)  {  	if (skb_queue_len(&offload->skb_queue) >  	    offload->skb_queue_len_max) @@ -222,7 +269,7 @@ int can_rx_offload_irq_queue_err_skb(struct can_rx_offload *offload, struct sk_b  	return 0;  } -EXPORT_SYMBOL_GPL(can_rx_offload_irq_queue_err_skb); +EXPORT_SYMBOL_GPL(can_rx_offload_queue_tail);  static int can_rx_offload_init_queue(struct net_device *dev, struct can_rx_offload *offload, unsigned int weight)  { diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index 53e320c92a8b..ddaf46239e39 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -760,7 +760,7 @@ static int hi3110_open(struct net_device *net)  {  	struct hi3110_priv *priv = netdev_priv(net);  	struct spi_device *spi = priv->spi; -	unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_RISING; +	unsigned long flags = IRQF_ONESHOT | IRQF_TRIGGER_HIGH;  	int ret;  	ret = open_candev(net); diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c index b939a4c10b84..c89c7d4900d7 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_core.c @@ -528,7 +528,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,  			context = &priv->tx_contexts[i];  			context->echo_index = i; -			can_put_echo_skb(skb, netdev, context->echo_index);  			++priv->active_tx_contexts;  			if (priv->active_tx_contexts >= (int)dev->max_tx_urbs)  				netif_stop_queue(netdev); @@ -553,7 +552,6 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,  		dev_kfree_skb(skb);  		spin_lock_irqsave(&priv->tx_contexts_lock, flags); -		can_free_echo_skb(netdev, context->echo_index);  		context->echo_index = dev->max_tx_urbs;  		--priv->active_tx_contexts;  		netif_wake_queue(netdev); @@ -564,6 +562,8 @@ static netdev_tx_t kvaser_usb_start_xmit(struct sk_buff *skb,  	context->priv = priv; +	can_put_echo_skb(skb, netdev, context->echo_index); +  	usb_fill_bulk_urb(urb, dev->udev,  			  usb_sndbulkpipe(dev->udev,  					  dev->bulk_out->bEndpointAddress), diff --git a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c index c084bae5ec0a..5fc0be564274 100644 --- a/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c +++ b/drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c @@ -1019,6 +1019,11 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,  					new_state : CAN_STATE_ERROR_ACTIVE;  			can_change_state(netdev, cf, tx_state, rx_state); + +			if (priv->can.restart_ms && +			    old_state >= CAN_STATE_BUS_OFF && +			    new_state < CAN_STATE_BUS_OFF) +				cf->can_id |= CAN_ERR_RESTARTED;  		}  		if (new_state == CAN_STATE_BUS_OFF) { @@ -1028,11 +1033,6 @@ kvaser_usb_hydra_error_frame(struct kvaser_usb_net_priv *priv,  			can_bus_off(netdev);  		} - -		if (priv->can.restart_ms && -		    old_state >= CAN_STATE_BUS_OFF && -		    new_state < CAN_STATE_BUS_OFF) -			cf->can_id |= CAN_ERR_RESTARTED;  	}  	if (!skb) { diff --git a/drivers/net/can/usb/ucan.c b/drivers/net/can/usb/ucan.c index 0678a38b1af4..f3d5bda012a1 100644 --- a/drivers/net/can/usb/ucan.c +++ b/drivers/net/can/usb/ucan.c @@ -35,10 +35,6 @@  #include <linux/slab.h>  #include <linux/usb.h> -#include <linux/can.h> -#include <linux/can/dev.h> -#include <linux/can/error.h> -  #define UCAN_DRIVER_NAME "ucan"  #define UCAN_MAX_RX_URBS 8  /* the CAN controller needs a while to enable/disable the bus */ @@ -1575,11 +1571,8 @@ err_firmware_needs_update:  /* disconnect the device */  static void ucan_disconnect(struct usb_interface *intf)  { -	struct usb_device *udev;  	struct ucan_priv *up = usb_get_intfdata(intf); -	udev = interface_to_usbdev(intf); -  	usb_set_intfdata(intf, NULL);  	if (up) { diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c index 18956e7604a3..a70bb1bb90e7 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.c +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c @@ -1848,6 +1848,8 @@ static void ena_down(struct ena_adapter *adapter)  		rc = ena_com_dev_reset(adapter->ena_dev, adapter->reset_reason);  		if (rc)  			dev_err(&adapter->pdev->dev, "Device reset failed\n"); +		/* stop submitting admin commands on a device that was reset */ +		ena_com_set_admin_running_state(adapter->ena_dev, false);  	}  	ena_destroy_all_io_queues(adapter); @@ -1914,6 +1916,9 @@ static int ena_close(struct net_device *netdev)  	netif_dbg(adapter, ifdown, netdev, "%s\n", __func__); +	if (!test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags)) +		return 0; +  	if (test_bit(ENA_FLAG_DEV_UP, &adapter->flags))  		ena_down(adapter); @@ -2613,9 +2618,7 @@ static void ena_destroy_device(struct ena_adapter *adapter, bool graceful)  		ena_down(adapter);  	/* Stop the device from sending AENQ events (in case reset flag is set -	 *  and device is up, ena_close already reset the device -	 * In case the reset flag is set and the device is up, ena_down() -	 * already perform the reset, so it can be skipped. +	 *  and device is up, ena_down() already reset the device.  	 */  	if (!(test_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags) && dev_up))  		ena_com_dev_reset(adapter->ena_dev, adapter->reset_reason); @@ -2694,8 +2697,8 @@ err_device_destroy:  	ena_com_abort_admin_commands(ena_dev);  	ena_com_wait_for_abort_completion(ena_dev);  	ena_com_admin_destroy(ena_dev); -	ena_com_mmio_reg_read_request_destroy(ena_dev);  	ena_com_dev_reset(ena_dev, ENA_REGS_RESET_DRIVER_INVALID_STATE); +	ena_com_mmio_reg_read_request_destroy(ena_dev);  err:  	clear_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);  	clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags); @@ -3452,6 +3455,8 @@ err_rss:  	ena_com_rss_destroy(ena_dev);  err_free_msix:  	ena_com_dev_reset(ena_dev, ENA_REGS_RESET_INIT_ERR); +	/* stop submitting admin commands on a device that was reset */ +	ena_com_set_admin_running_state(ena_dev, false);  	ena_free_mgmnt_irq(adapter);  	ena_disable_msix(adapter);  err_worker_destroy: @@ -3498,18 +3503,12 @@ static void ena_remove(struct pci_dev *pdev)  	cancel_work_sync(&adapter->reset_task); -	unregister_netdev(netdev); - -	/* If the device is running then we want to make sure the device will be -	 * reset to make sure no more events will be issued by the device. -	 */ -	if (test_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags)) -		set_bit(ENA_FLAG_TRIGGER_RESET, &adapter->flags); -  	rtnl_lock();  	ena_destroy_device(adapter, true);  	rtnl_unlock(); +	unregister_netdev(netdev); +  	free_netdev(netdev);  	ena_com_rss_destroy(ena_dev); diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.h b/drivers/net/ethernet/amazon/ena/ena_netdev.h index 521873642339..dc8b6173d8d8 100644 --- a/drivers/net/ethernet/amazon/ena/ena_netdev.h +++ b/drivers/net/ethernet/amazon/ena/ena_netdev.h @@ -45,7 +45,7 @@  #define DRV_MODULE_VER_MAJOR	2  #define DRV_MODULE_VER_MINOR	0 -#define DRV_MODULE_VER_SUBMINOR 1 +#define DRV_MODULE_VER_SUBMINOR 2  #define DRV_MODULE_NAME		"ena"  #ifndef DRV_MODULE_VERSION diff --git a/drivers/net/ethernet/amd/sunlance.c b/drivers/net/ethernet/amd/sunlance.c index b4fc0ed5bce8..9d4899826823 100644 --- a/drivers/net/ethernet/amd/sunlance.c +++ b/drivers/net/ethernet/amd/sunlance.c @@ -1419,7 +1419,7 @@ static int sparc_lance_probe_one(struct platform_device *op,  			prop = of_get_property(nd, "tpe-link-test?", NULL);  			if (!prop) -				goto no_link_test; +				goto node_put;  			if (strcmp(prop, "true")) {  				printk(KERN_NOTICE "SunLance: warning: overriding option " @@ -1428,6 +1428,8 @@ static int sparc_lance_probe_one(struct platform_device *op,  				       "to ecd@skynet.be\n");  				auxio_set_lte(AUXIO_LTE_ON);  			} +node_put: +			of_node_put(nd);  no_link_test:  			lp->auto_select = 1;  			lp->tpe = 0; diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h index be1506169076..0de487a8f0eb 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h @@ -2191,6 +2191,13 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,  #define PMF_DMAE_C(bp)			(BP_PORT(bp) * MAX_DMAE_C_PER_PORT + \  					 E1HVN_MAX) +/* Following is the DMAE channel number allocation for the clients. + *   MFW: OCBB/OCSD implementations use DMAE channels 14/15 respectively. + *   Driver: 0-3 and 8-11 (for PF dmae operations) + *           4 and 12 (for stats requests) + */ +#define BNX2X_FW_DMAE_C                 13 /* Channel for FW DMAE operations */ +  /* PCIE link and speed */  #define PCICFG_LINK_WIDTH		0x1f00000  #define PCICFG_LINK_WIDTH_SHIFT		20 diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c index 3f4d2c8da21a..a9eaaf3e73a4 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_sp.c @@ -6149,6 +6149,7 @@ static inline int bnx2x_func_send_start(struct bnx2x *bp,  	rdata->sd_vlan_tag	= cpu_to_le16(start_params->sd_vlan_tag);  	rdata->path_id		= BP_PATH(bp);  	rdata->network_cos_mode	= start_params->network_cos_mode; +	rdata->dmae_cmd_id	= BNX2X_FW_DMAE_C;  	rdata->vxlan_dst_port	= cpu_to_le16(start_params->vxlan_dst_port);  	rdata->geneve_dst_port	= cpu_to_le16(start_params->geneve_dst_port); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index dd85d790f638..d4c300117529 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -1675,7 +1675,7 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,  	} else {  		if (rxcmp1->rx_cmp_cfa_code_errors_v2 & RX_CMP_L4_CS_ERR_BITS) {  			if (dev->features & NETIF_F_RXCSUM) -				cpr->rx_l4_csum_errors++; +				bnapi->cp_ring.rx_l4_csum_errors++;  		}  	} @@ -8714,6 +8714,26 @@ static int bnxt_set_features(struct net_device *dev, netdev_features_t features)  	return rc;  } +static int bnxt_dbg_hwrm_ring_info_get(struct bnxt *bp, u8 ring_type, +				       u32 ring_id, u32 *prod, u32 *cons) +{ +	struct hwrm_dbg_ring_info_get_output *resp = bp->hwrm_cmd_resp_addr; +	struct hwrm_dbg_ring_info_get_input req = {0}; +	int rc; + +	bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_DBG_RING_INFO_GET, -1, -1); +	req.ring_type = ring_type; +	req.fw_ring_id = cpu_to_le32(ring_id); +	mutex_lock(&bp->hwrm_cmd_lock); +	rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT); +	if (!rc) { +		*prod = le32_to_cpu(resp->producer_index); +		*cons = le32_to_cpu(resp->consumer_index); +	} +	mutex_unlock(&bp->hwrm_cmd_lock); +	return rc; +} +  static void bnxt_dump_tx_sw_state(struct bnxt_napi *bnapi)  {  	struct bnxt_tx_ring_info *txr = bnapi->tx_ring; @@ -8821,6 +8841,11 @@ static void bnxt_timer(struct timer_list *t)  			bnxt_queue_sp_work(bp);  		}  	} + +	if ((bp->flags & BNXT_FLAG_CHIP_P5) && netif_carrier_ok(dev)) { +		set_bit(BNXT_RING_COAL_NOW_SP_EVENT, &bp->sp_event); +		bnxt_queue_sp_work(bp); +	}  bnxt_restart_timer:  	mod_timer(&bp->timer, jiffies + bp->current_interval);  } @@ -8851,6 +8876,44 @@ static void bnxt_reset(struct bnxt *bp, bool silent)  	bnxt_rtnl_unlock_sp(bp);  } +static void bnxt_chk_missed_irq(struct bnxt *bp) +{ +	int i; + +	if (!(bp->flags & BNXT_FLAG_CHIP_P5)) +		return; + +	for (i = 0; i < bp->cp_nr_rings; i++) { +		struct bnxt_napi *bnapi = bp->bnapi[i]; +		struct bnxt_cp_ring_info *cpr; +		u32 fw_ring_id; +		int j; + +		if (!bnapi) +			continue; + +		cpr = &bnapi->cp_ring; +		for (j = 0; j < 2; j++) { +			struct bnxt_cp_ring_info *cpr2 = cpr->cp_ring_arr[j]; +			u32 val[2]; + +			if (!cpr2 || cpr2->has_more_work || +			    !bnxt_has_work(bp, cpr2)) +				continue; + +			if (cpr2->cp_raw_cons != cpr2->last_cp_raw_cons) { +				cpr2->last_cp_raw_cons = cpr2->cp_raw_cons; +				continue; +			} +			fw_ring_id = cpr2->cp_ring_struct.fw_ring_id; +			bnxt_dbg_hwrm_ring_info_get(bp, +				DBG_RING_INFO_GET_REQ_RING_TYPE_L2_CMPL, +				fw_ring_id, &val[0], &val[1]); +			cpr->missed_irqs++; +		} +	} +} +  static void bnxt_cfg_ntp_filters(struct bnxt *);  static void bnxt_sp_task(struct work_struct *work) @@ -8930,6 +8993,9 @@ static void bnxt_sp_task(struct work_struct *work)  	if (test_and_clear_bit(BNXT_FLOW_STATS_SP_EVENT, &bp->sp_event))  		bnxt_tc_flow_stats_work(bp); +	if (test_and_clear_bit(BNXT_RING_COAL_NOW_SP_EVENT, &bp->sp_event)) +		bnxt_chk_missed_irq(bp); +  	/* These functions below will clear BNXT_STATE_IN_SP_TASK.  They  	 * must be the last functions to be called before exiting.  	 */ @@ -10087,6 +10153,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  	}  	bnxt_hwrm_func_qcfg(bp); +	bnxt_hwrm_vnic_qcaps(bp);  	bnxt_hwrm_port_led_qcaps(bp);  	bnxt_ethtool_init(bp);  	bnxt_dcb_init(bp); @@ -10120,7 +10187,6 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)  				    VNIC_RSS_CFG_REQ_HASH_TYPE_UDP_IPV6;  	} -	bnxt_hwrm_vnic_qcaps(bp);  	if (bnxt_rfs_supported(bp)) {  		dev->hw_features |= NETIF_F_NTUPLE;  		if (bnxt_rfs_capable(bp)) { diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h index 498b373c992d..9e99d4ab3e06 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h @@ -798,6 +798,8 @@ struct bnxt_cp_ring_info {  	u8			had_work_done:1;  	u8			has_more_work:1; +	u32			last_cp_raw_cons; +  	struct bnxt_coal	rx_ring_coal;  	u64			rx_packets;  	u64			rx_bytes; @@ -816,6 +818,7 @@ struct bnxt_cp_ring_info {  	dma_addr_t		hw_stats_map;  	u32			hw_stats_ctx_id;  	u64			rx_l4_csum_errors; +	u64			missed_irqs;  	struct bnxt_ring_struct	cp_ring_struct; @@ -1527,6 +1530,7 @@ struct bnxt {  #define BNXT_LINK_SPEED_CHNG_SP_EVENT	14  #define BNXT_FLOW_STATS_SP_EVENT	15  #define BNXT_UPDATE_PHY_SP_EVENT	16 +#define BNXT_RING_COAL_NOW_SP_EVENT	17  	struct bnxt_hw_resc	hw_resc;  	struct bnxt_pf_info	pf; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 48078564f025..6cc69a58478a 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -137,7 +137,7 @@ reset_coalesce:  	return rc;  } -#define BNXT_NUM_STATS	21 +#define BNXT_NUM_STATS	22  #define BNXT_RX_STATS_ENTRY(counter)	\  	{ BNXT_RX_STATS_OFFSET(counter), __stringify(counter) } @@ -384,6 +384,7 @@ static void bnxt_get_ethtool_stats(struct net_device *dev,  		for (k = 0; k < stat_fields; j++, k++)  			buf[j] = le64_to_cpu(hw_stats[k]);  		buf[j++] = cpr->rx_l4_csum_errors; +		buf[j++] = cpr->missed_irqs;  		bnxt_sw_func_stats[RX_TOTAL_DISCARDS].counter +=  			le64_to_cpu(cpr->hw_stats->rx_discard_pkts); @@ -468,6 +469,8 @@ static void bnxt_get_strings(struct net_device *dev, u32 stringset, u8 *buf)  			buf += ETH_GSTRING_LEN;  			sprintf(buf, "[%d]: rx_l4_csum_errors", i);  			buf += ETH_GSTRING_LEN; +			sprintf(buf, "[%d]: missed_irqs", i); +			buf += ETH_GSTRING_LEN;  		}  		for (i = 0; i < BNXT_NUM_SW_FUNC_STATS; i++) {  			strcpy(buf, bnxt_sw_func_stats[i].string); @@ -2942,8 +2945,8 @@ bnxt_fill_coredump_record(struct bnxt *bp, struct bnxt_coredump_record *record,  	record->asic_state = 0;  	strlcpy(record->system_name, utsname()->nodename,  		sizeof(record->system_name)); -	record->year = cpu_to_le16(tm.tm_year); -	record->month = cpu_to_le16(tm.tm_mon); +	record->year = cpu_to_le16(tm.tm_year + 1900); +	record->month = cpu_to_le16(tm.tm_mon + 1);  	record->day = cpu_to_le16(tm.tm_mday);  	record->hour = cpu_to_le16(tm.tm_hour);  	record->minute = cpu_to_le16(tm.tm_min); diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c index beee61292d5e..b59b382d34f9 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c @@ -43,6 +43,9 @@ static int bnxt_register_dev(struct bnxt_en_dev *edev, int ulp_id,  	if (ulp_id == BNXT_ROCE_ULP) {  		unsigned int max_stat_ctxs; +		if (bp->flags & BNXT_FLAG_CHIP_P5) +			return -EOPNOTSUPP; +  		max_stat_ctxs = bnxt_get_max_func_stat_ctxs(bp);  		if (max_stat_ctxs <= BNXT_MIN_ROCE_STAT_CTXS ||  		    bp->num_stat_ctxs == max_stat_ctxs) diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 89295306f161..432c3b867084 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -12422,6 +12422,7 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e  {  	struct tg3 *tp = netdev_priv(dev);  	int i, irq_sync = 0, err = 0; +	bool reset_phy = false;  	if ((ering->rx_pending > tp->rx_std_ring_mask) ||  	    (ering->rx_jumbo_pending > tp->rx_jmb_ring_mask) || @@ -12453,7 +12454,13 @@ static int tg3_set_ringparam(struct net_device *dev, struct ethtool_ringparam *e  	if (netif_running(dev)) {  		tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); -		err = tg3_restart_hw(tp, false); +		/* Reset PHY to avoid PHY lock up */ +		if (tg3_asic_rev(tp) == ASIC_REV_5717 || +		    tg3_asic_rev(tp) == ASIC_REV_5719 || +		    tg3_asic_rev(tp) == ASIC_REV_5720) +			reset_phy = true; + +		err = tg3_restart_hw(tp, reset_phy);  		if (!err)  			tg3_netif_start(tp);  	} @@ -12487,6 +12494,7 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam  {  	struct tg3 *tp = netdev_priv(dev);  	int err = 0; +	bool reset_phy = false;  	if (tp->link_config.autoneg == AUTONEG_ENABLE)  		tg3_warn_mgmt_link_flap(tp); @@ -12556,7 +12564,13 @@ static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam  		if (netif_running(dev)) {  			tg3_halt(tp, RESET_KIND_SHUTDOWN, 1); -			err = tg3_restart_hw(tp, false); +			/* Reset PHY to avoid PHY lock up */ +			if (tg3_asic_rev(tp) == ASIC_REV_5717 || +			    tg3_asic_rev(tp) == ASIC_REV_5719 || +			    tg3_asic_rev(tp) == ASIC_REV_5720) +				reset_phy = true; + +			err = tg3_restart_hw(tp, reset_phy);  			if (!err)  				tg3_netif_start(tp);  		} diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 768f584f8392..88f8a8fa93cd 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -1784,6 +1784,7 @@ static int nicvf_xdp_setup(struct nicvf *nic, struct bpf_prog *prog)  	bool if_up = netif_running(nic->netdev);  	struct bpf_prog *old_prog;  	bool bpf_attached = false; +	int ret = 0;  	/* For now just support only the usual MTU sized frames */  	if (prog && (dev->mtu > 1500)) { @@ -1817,8 +1818,12 @@ static int nicvf_xdp_setup(struct nicvf *nic, struct bpf_prog *prog)  	if (nic->xdp_prog) {  		/* Attach BPF program */  		nic->xdp_prog = bpf_prog_add(nic->xdp_prog, nic->rx_queues - 1); -		if (!IS_ERR(nic->xdp_prog)) +		if (!IS_ERR(nic->xdp_prog)) {  			bpf_attached = true; +		} else { +			ret = PTR_ERR(nic->xdp_prog); +			nic->xdp_prog = NULL; +		}  	}  	/* Calculate Tx queues needed for XDP and network stack */ @@ -1830,7 +1835,7 @@ static int nicvf_xdp_setup(struct nicvf *nic, struct bpf_prog *prog)  		netif_trans_update(nic->netdev);  	} -	return 0; +	return ret;  }  static int nicvf_xdp(struct net_device *netdev, struct netdev_bpf *xdp) diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c index 187a249ff2d1..fcaf18fa3904 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_queues.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_queues.c @@ -585,10 +585,12 @@ static void nicvf_free_snd_queue(struct nicvf *nic, struct snd_queue *sq)  	if (!sq->dmem.base)  		return; -	if (sq->tso_hdrs) +	if (sq->tso_hdrs) {  		dma_free_coherent(&nic->pdev->dev,  				  sq->dmem.q_len * TSO_HEADER_SIZE,  				  sq->tso_hdrs, sq->tso_hdrs_phys); +		sq->tso_hdrs = NULL; +	}  	/* Free pending skbs in the queue */  	smp_rmb(); diff --git a/drivers/net/ethernet/chelsio/Kconfig b/drivers/net/ethernet/chelsio/Kconfig index 75c1c5ed2387..e2cdfa75673f 100644 --- a/drivers/net/ethernet/chelsio/Kconfig +++ b/drivers/net/ethernet/chelsio/Kconfig @@ -67,7 +67,6 @@ config CHELSIO_T3  config CHELSIO_T4  	tristate "Chelsio Communications T4/T5/T6 Ethernet support"  	depends on PCI && (IPV6 || IPV6=n) -	depends on THERMAL || !THERMAL  	select FW_LOADER  	select MDIO  	select ZLIB_DEFLATE diff --git a/drivers/net/ethernet/chelsio/cxgb4/Makefile b/drivers/net/ethernet/chelsio/cxgb4/Makefile index 78e5d17a1d5f..91d8a885deba 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/Makefile +++ b/drivers/net/ethernet/chelsio/cxgb4/Makefile @@ -12,6 +12,4 @@ cxgb4-objs := cxgb4_main.o l2t.o smt.o t4_hw.o sge.o clip_tbl.o cxgb4_ethtool.o  cxgb4-$(CONFIG_CHELSIO_T4_DCB) +=  cxgb4_dcb.o  cxgb4-$(CONFIG_CHELSIO_T4_FCOE) +=  cxgb4_fcoe.o  cxgb4-$(CONFIG_DEBUG_FS) += cxgb4_debugfs.o -ifdef CONFIG_THERMAL -cxgb4-objs += cxgb4_thermal.o -endif +cxgb4-$(CONFIG_THERMAL) += cxgb4_thermal.o diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 05a46926016a..d49db46254cd 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -5863,7 +5863,7 @@ fw_attach_fail:  	if (!is_t4(adapter->params.chip))  		cxgb4_ptp_init(adapter); -	if (IS_ENABLED(CONFIG_THERMAL) && +	if (IS_REACHABLE(CONFIG_THERMAL) &&  	    !is_t4(adapter->params.chip) && (adapter->flags & FW_OK))  		cxgb4_thermal_init(adapter); @@ -5932,7 +5932,7 @@ static void remove_one(struct pci_dev *pdev)  		if (!is_t4(adapter->params.chip))  			cxgb4_ptp_stop(adapter); -		if (IS_ENABLED(CONFIG_THERMAL)) +		if (IS_REACHABLE(CONFIG_THERMAL))  			cxgb4_thermal_remove(adapter);  		/* If we allocated filters, free up state associated with any diff --git a/drivers/net/ethernet/cortina/gemini.c b/drivers/net/ethernet/cortina/gemini.c index ceec467f590d..949103db8a8a 100644 --- a/drivers/net/ethernet/cortina/gemini.c +++ b/drivers/net/ethernet/cortina/gemini.c @@ -660,7 +660,7 @@ static void gmac_clean_txq(struct net_device *netdev, struct gmac_txq *txq,  			u64_stats_update_begin(&port->tx_stats_syncp);  			port->tx_frag_stats[nfrags]++; -			u64_stats_update_end(&port->ir_stats_syncp); +			u64_stats_update_end(&port->tx_stats_syncp);  		}  	} diff --git a/drivers/net/ethernet/faraday/ftmac100.c b/drivers/net/ethernet/faraday/ftmac100.c index 570caeb8ee9e..084f24daf2b5 100644 --- a/drivers/net/ethernet/faraday/ftmac100.c +++ b/drivers/net/ethernet/faraday/ftmac100.c @@ -872,11 +872,10 @@ static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)  	struct net_device *netdev = dev_id;  	struct ftmac100 *priv = netdev_priv(netdev); -	if (likely(netif_running(netdev))) { -		/* Disable interrupts for polling */ -		ftmac100_disable_all_int(priv); +	/* Disable interrupts for polling */ +	ftmac100_disable_all_int(priv); +	if (likely(netif_running(netdev)))  		napi_schedule(&priv->napi); -	}  	return IRQ_HANDLED;  } diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index c9d5d0a7fbf1..c0203a0d5e3b 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -485,8 +485,8 @@ static void release_rx_pools(struct ibmvnic_adapter *adapter)  		for (j = 0; j < rx_pool->size; j++) {  			if (rx_pool->rx_buff[j].skb) { -				dev_kfree_skb_any(rx_pool->rx_buff[i].skb); -				rx_pool->rx_buff[i].skb = NULL; +				dev_kfree_skb_any(rx_pool->rx_buff[j].skb); +				rx_pool->rx_buff[j].skb = NULL;  			}  		} @@ -1103,20 +1103,15 @@ static int ibmvnic_open(struct net_device *netdev)  		return 0;  	} -	mutex_lock(&adapter->reset_lock); -  	if (adapter->state != VNIC_CLOSED) {  		rc = ibmvnic_login(netdev); -		if (rc) { -			mutex_unlock(&adapter->reset_lock); +		if (rc)  			return rc; -		}  		rc = init_resources(adapter);  		if (rc) {  			netdev_err(netdev, "failed to initialize resources\n");  			release_resources(adapter); -			mutex_unlock(&adapter->reset_lock);  			return rc;  		}  	} @@ -1124,8 +1119,6 @@ static int ibmvnic_open(struct net_device *netdev)  	rc = __ibmvnic_open(netdev);  	netif_carrier_on(netdev); -	mutex_unlock(&adapter->reset_lock); -  	return rc;  } @@ -1269,10 +1262,8 @@ static int ibmvnic_close(struct net_device *netdev)  		return 0;  	} -	mutex_lock(&adapter->reset_lock);  	rc = __ibmvnic_close(netdev);  	ibmvnic_cleanup(netdev); -	mutex_unlock(&adapter->reset_lock);  	return rc;  } @@ -1746,6 +1737,7 @@ static int do_reset(struct ibmvnic_adapter *adapter,  		    struct ibmvnic_rwi *rwi, u32 reset_state)  {  	u64 old_num_rx_queues, old_num_tx_queues; +	u64 old_num_rx_slots, old_num_tx_slots;  	struct net_device *netdev = adapter->netdev;  	int i, rc; @@ -1757,6 +1749,8 @@ static int do_reset(struct ibmvnic_adapter *adapter,  	old_num_rx_queues = adapter->req_rx_queues;  	old_num_tx_queues = adapter->req_tx_queues; +	old_num_rx_slots = adapter->req_rx_add_entries_per_subcrq; +	old_num_tx_slots = adapter->req_tx_entries_per_subcrq;  	ibmvnic_cleanup(netdev); @@ -1819,21 +1813,20 @@ static int do_reset(struct ibmvnic_adapter *adapter,  			if (rc)  				return rc;  		} else if (adapter->req_rx_queues != old_num_rx_queues || -			   adapter->req_tx_queues != old_num_tx_queues) { -			adapter->map_id = 1; +			   adapter->req_tx_queues != old_num_tx_queues || +			   adapter->req_rx_add_entries_per_subcrq != +							old_num_rx_slots || +			   adapter->req_tx_entries_per_subcrq != +							old_num_tx_slots) {  			release_rx_pools(adapter);  			release_tx_pools(adapter); -			rc = init_rx_pools(netdev); -			if (rc) -				return rc; -			rc = init_tx_pools(netdev); -			if (rc) -				return rc; -  			release_napi(adapter); -			rc = init_napi(adapter); +			release_vpd_data(adapter); + +			rc = init_resources(adapter);  			if (rc)  				return rc; +  		} else {  			rc = reset_tx_pools(adapter);  			if (rc) @@ -1917,17 +1910,8 @@ static int do_hard_reset(struct ibmvnic_adapter *adapter,  		adapter->state = VNIC_PROBED;  		return 0;  	} -	/* netif_set_real_num_xx_queues needs to take rtnl lock here -	 * unless wait_for_reset is set, in which case the rtnl lock -	 * has already been taken before initializing the reset -	 */ -	if (!adapter->wait_for_reset) { -		rtnl_lock(); -		rc = init_resources(adapter); -		rtnl_unlock(); -	} else { -		rc = init_resources(adapter); -	} + +	rc = init_resources(adapter);  	if (rc)  		return rc; @@ -1986,13 +1970,21 @@ static void __ibmvnic_reset(struct work_struct *work)  	struct ibmvnic_rwi *rwi;  	struct ibmvnic_adapter *adapter;  	struct net_device *netdev; +	bool we_lock_rtnl = false;  	u32 reset_state;  	int rc = 0;  	adapter = container_of(work, struct ibmvnic_adapter, ibmvnic_reset);  	netdev = adapter->netdev; -	mutex_lock(&adapter->reset_lock); +	/* netif_set_real_num_xx_queues needs to take rtnl lock here +	 * unless wait_for_reset is set, in which case the rtnl lock +	 * has already been taken before initializing the reset +	 */ +	if (!adapter->wait_for_reset) { +		rtnl_lock(); +		we_lock_rtnl = true; +	}  	reset_state = adapter->state;  	rwi = get_next_rwi(adapter); @@ -2020,12 +2012,11 @@ static void __ibmvnic_reset(struct work_struct *work)  	if (rc) {  		netdev_dbg(adapter->netdev, "Reset failed\n");  		free_all_rwi(adapter); -		mutex_unlock(&adapter->reset_lock); -		return;  	}  	adapter->resetting = false; -	mutex_unlock(&adapter->reset_lock); +	if (we_lock_rtnl) +		rtnl_unlock();  }  static int ibmvnic_reset(struct ibmvnic_adapter *adapter, @@ -4768,7 +4759,6 @@ static int ibmvnic_probe(struct vio_dev *dev, const struct vio_device_id *id)  	INIT_WORK(&adapter->ibmvnic_reset, __ibmvnic_reset);  	INIT_LIST_HEAD(&adapter->rwi_list); -	mutex_init(&adapter->reset_lock);  	mutex_init(&adapter->rwi_lock);  	adapter->resetting = false; @@ -4840,8 +4830,8 @@ static int ibmvnic_remove(struct vio_dev *dev)  	struct ibmvnic_adapter *adapter = netdev_priv(netdev);  	adapter->state = VNIC_REMOVING; -	unregister_netdev(netdev); -	mutex_lock(&adapter->reset_lock); +	rtnl_lock(); +	unregister_netdevice(netdev);  	release_resources(adapter);  	release_sub_crqs(adapter, 1); @@ -4852,7 +4842,7 @@ static int ibmvnic_remove(struct vio_dev *dev)  	adapter->state = VNIC_REMOVED; -	mutex_unlock(&adapter->reset_lock); +	rtnl_unlock();  	device_remove_file(&dev->dev, &dev_attr_failover);  	free_netdev(netdev);  	dev_set_drvdata(&dev->dev, NULL); diff --git a/drivers/net/ethernet/ibm/ibmvnic.h b/drivers/net/ethernet/ibm/ibmvnic.h index 18103b811d4d..99c4f8d331ce 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.h +++ b/drivers/net/ethernet/ibm/ibmvnic.h @@ -1075,7 +1075,7 @@ struct ibmvnic_adapter {  	struct tasklet_struct tasklet;  	enum vnic_state state;  	enum ibmvnic_reset_reason reset_reason; -	struct mutex reset_lock, rwi_lock; +	struct mutex rwi_lock;  	struct list_head rwi_list;  	struct work_struct ibmvnic_reset;  	bool resetting; diff --git a/drivers/net/ethernet/lantiq_xrx200.c b/drivers/net/ethernet/lantiq_xrx200.c index 8c5ba4b81fb7..2d4d10a017e5 100644 --- a/drivers/net/ethernet/lantiq_xrx200.c +++ b/drivers/net/ethernet/lantiq_xrx200.c @@ -512,7 +512,8 @@ static int xrx200_probe(struct platform_device *pdev)  	err = register_netdev(net_dev);  	if (err)  		goto err_unprepare_clk; -	return err; + +	return 0;  err_unprepare_clk:  	clk_disable_unprepare(priv->clk); @@ -520,7 +521,7 @@ err_unprepare_clk:  err_uninit_dma:  	xrx200_hw_cleanup(priv); -	return 0; +	return err;  }  static int xrx200_remove(struct platform_device *pdev) diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index 3ba672e9e353..e5397c8197b9 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -3343,7 +3343,6 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported,  	if (state->interface != PHY_INTERFACE_MODE_NA &&  	    state->interface != PHY_INTERFACE_MODE_QSGMII &&  	    state->interface != PHY_INTERFACE_MODE_SGMII && -	    state->interface != PHY_INTERFACE_MODE_2500BASEX &&  	    !phy_interface_mode_is_8023z(state->interface) &&  	    !phy_interface_mode_is_rgmii(state->interface)) {  		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); @@ -3357,14 +3356,9 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported,  	/* Asymmetric pause is unsupported */  	phylink_set(mask, Pause); -	/* We cannot use 1Gbps when using the 2.5G interface. */ -	if (state->interface == PHY_INTERFACE_MODE_2500BASEX) { -		phylink_set(mask, 2500baseT_Full); -		phylink_set(mask, 2500baseX_Full); -	} else { -		phylink_set(mask, 1000baseT_Full); -		phylink_set(mask, 1000baseX_Full); -	} +	/* Half-duplex at speeds higher than 100Mbit is unsupported */ +	phylink_set(mask, 1000baseT_Full); +	phylink_set(mask, 1000baseX_Full);  	if (!phy_interface_mode_is_8023z(state->interface)) {  		/* 10M and 100M are only supported in non-802.3z mode */ diff --git a/drivers/net/ethernet/mellanox/mlx4/alloc.c b/drivers/net/ethernet/mellanox/mlx4/alloc.c index deef5a998985..9af34e03892c 100644 --- a/drivers/net/ethernet/mellanox/mlx4/alloc.c +++ b/drivers/net/ethernet/mellanox/mlx4/alloc.c @@ -337,7 +337,7 @@ void mlx4_zone_allocator_destroy(struct mlx4_zone_allocator *zone_alloc)  static u32 __mlx4_alloc_from_zone(struct mlx4_zone_entry *zone, int count,  				  int align, u32 skip_mask, u32 *puid)  { -	u32 uid; +	u32 uid = 0;  	u32 res;  	struct mlx4_zone_allocator *zone_alloc = zone->allocator;  	struct mlx4_zone_entry *curr_node; diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index ebcd2778eeb3..23f1b5b512c2 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h @@ -540,8 +540,8 @@ struct slave_list {  struct resource_allocator {  	spinlock_t alloc_lock; /* protect quotas */  	union { -		int res_reserved; -		int res_port_rsvd[MLX4_MAX_PORTS]; +		unsigned int res_reserved; +		unsigned int res_port_rsvd[MLX4_MAX_PORTS];  	};  	union {  		int res_free; diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index 2e84f10f59ba..1a11bc0e1612 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -363,6 +363,7 @@ int mlx4_mr_hw_write_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr,  			container_of((void *)mpt_entry, struct mlx4_cmd_mailbox,  				     buf); +		(*mpt_entry)->lkey = 0;  		err = mlx4_SW2HW_MPT(dev, mailbox, key);  	} diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index d7fbd5b6ac95..118324802926 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -569,6 +569,7 @@ struct mlx5e_rq {  	unsigned long          state;  	int                    ix; +	unsigned int           hw_mtu;  	struct net_dim         dim; /* Dynamic Interrupt Moderation */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c index 023dc4bccd28..4a37713023be 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c @@ -88,10 +88,8 @@ int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)  	eth_proto_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);  	*speed = mlx5e_port_ptys2speed(eth_proto_oper); -	if (!(*speed)) { -		mlx5_core_warn(mdev, "cannot get port speed\n"); +	if (!(*speed))  		err = -EINVAL; -	}  	return err;  } @@ -258,7 +256,7 @@ static int mlx5e_fec_admin_field(u32 *pplm,  	case 40000:  		if (!write)  			*fec_policy = MLX5_GET(pplm_reg, pplm, -					       fec_override_cap_10g_40g); +					       fec_override_admin_10g_40g);  		else  			MLX5_SET(pplm_reg, pplm,  				 fec_override_admin_10g_40g, *fec_policy); @@ -310,7 +308,7 @@ static int mlx5e_get_fec_cap_field(u32 *pplm,  	case 10000:  	case 40000:  		*fec_cap = MLX5_GET(pplm_reg, pplm, -				    fec_override_admin_10g_40g); +				    fec_override_cap_10g_40g);  		break;  	case 25000:  		*fec_cap = MLX5_GET(pplm_reg, pplm, @@ -394,12 +392,12 @@ int mlx5e_get_fec_mode(struct mlx5_core_dev *dev, u32 *fec_mode_active,  int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy)  { +	u8 fec_policy_nofec = BIT(MLX5E_FEC_NOFEC);  	bool fec_mode_not_supp_in_speed = false; -	u8 no_fec_policy = BIT(MLX5E_FEC_NOFEC);  	u32 out[MLX5_ST_SZ_DW(pplm_reg)] = {};  	u32 in[MLX5_ST_SZ_DW(pplm_reg)] = {};  	int sz = MLX5_ST_SZ_BYTES(pplm_reg); -	u32 current_fec_speed; +	u8 fec_policy_auto = 0;  	u8 fec_caps = 0;  	int err;  	int i; @@ -415,23 +413,19 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy)  	if (err)  		return err; -	err = mlx5e_port_linkspeed(dev, ¤t_fec_speed); -	if (err) -		return err; +	MLX5_SET(pplm_reg, out, local_port, 1); -	memset(in, 0, sz); -	MLX5_SET(pplm_reg, in, local_port, 1); -	for (i = 0; i < MLX5E_FEC_SUPPORTED_SPEEDS && !!fec_policy; i++) { +	for (i = 0; i < MLX5E_FEC_SUPPORTED_SPEEDS; i++) {  		mlx5e_get_fec_cap_field(out, &fec_caps, fec_supported_speeds[i]); -		/* policy supported for link speed */ -		if (!!(fec_caps & fec_policy)) { -			mlx5e_fec_admin_field(in, &fec_policy, 1, +		/* policy supported for link speed, or policy is auto */ +		if (fec_caps & fec_policy || fec_policy == fec_policy_auto) { +			mlx5e_fec_admin_field(out, &fec_policy, 1,  					      fec_supported_speeds[i]);  		} else { -			if (fec_supported_speeds[i] == current_fec_speed) -				return -EOPNOTSUPP; -			mlx5e_fec_admin_field(in, &no_fec_policy, 1, -					      fec_supported_speeds[i]); +			/* turn off FEC if supported. Else, leave it the same */ +			if (fec_caps & fec_policy_nofec) +				mlx5e_fec_admin_field(out, &fec_policy_nofec, 1, +						      fec_supported_speeds[i]);  			fec_mode_not_supp_in_speed = true;  		}  	} @@ -441,5 +435,5 @@ int mlx5e_set_fec_mode(struct mlx5_core_dev *dev, u8 fec_policy)  			      "FEC policy 0x%x is not supported for some speeds",  			      fec_policy); -	return mlx5_core_access_reg(dev, in, sz, out, sz, MLX5_REG_PPLM, 0, 1); +	return mlx5_core_access_reg(dev, out, sz, out, sz, MLX5_REG_PPLM, 0, 1);  } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c index c047da8752da..eac245a93f91 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port_buffer.c @@ -130,8 +130,10 @@ static u32 calculate_xoff(struct mlx5e_priv *priv, unsigned int mtu)  	int err;  	err = mlx5e_port_linkspeed(priv->mdev, &speed); -	if (err) +	if (err) { +		mlx5_core_warn(priv->mdev, "cannot get port speed\n");  		return 0; +	}  	xoff = (301 + 216 * priv->dcbx.cable_len / 100) * speed / 1000 + 272 * mtu / 100; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index 3e770abfd802..25c1c4f96841 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -843,8 +843,7 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,  	ethtool_link_ksettings_add_link_mode(link_ksettings, supported,  					     Autoneg); -	err = get_fec_supported_advertised(mdev, link_ksettings); -	if (err) +	if (get_fec_supported_advertised(mdev, link_ksettings))  		netdev_dbg(netdev, "%s: FEC caps query failed: %d\n",  			   __func__, err); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 1243edbedc9e..871313d6b34d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -502,6 +502,7 @@ static int mlx5e_alloc_rq(struct mlx5e_channel *c,  	rq->channel = c;  	rq->ix      = c->ix;  	rq->mdev    = mdev; +	rq->hw_mtu  = MLX5E_SW2HW_MTU(params, params->sw_mtu);  	rq->stats   = &c->priv->channel_stats[c->ix].rq;  	rq->xdp_prog = params->xdp_prog ? bpf_prog_inc(params->xdp_prog) : NULL; @@ -1623,13 +1624,15 @@ static int mlx5e_alloc_cq_common(struct mlx5_core_dev *mdev,  	int err;  	u32 i; +	err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn); +	if (err) +		return err; +  	err = mlx5_cqwq_create(mdev, ¶m->wq, param->cqc, &cq->wq,  			       &cq->wq_ctrl);  	if (err)  		return err; -	mlx5_vector2eqn(mdev, param->eq_ix, &eqn_not_used, &irqn); -  	mcq->cqe_sz     = 64;  	mcq->set_ci_db  = cq->wq_ctrl.db.db;  	mcq->arm_db     = cq->wq_ctrl.db.db + 1; @@ -1687,6 +1690,10 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)  	int eqn;  	int err; +	err = mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used); +	if (err) +		return err; +  	inlen = MLX5_ST_SZ_BYTES(create_cq_in) +  		sizeof(u64) * cq->wq_ctrl.buf.npages;  	in = kvzalloc(inlen, GFP_KERNEL); @@ -1700,8 +1707,6 @@ static int mlx5e_create_cq(struct mlx5e_cq *cq, struct mlx5e_cq_param *param)  	mlx5_fill_page_frag_array(&cq->wq_ctrl.buf,  				  (__be64 *)MLX5_ADDR_OF(create_cq_in, in, pas)); -	mlx5_vector2eqn(mdev, param->eq_ix, &eqn, &irqn_not_used); -  	MLX5_SET(cqc,   cqc, cq_period_mode, param->cq_period_mode);  	MLX5_SET(cqc,   cqc, c_eqn,         eqn);  	MLX5_SET(cqc,   cqc, uar_page,      mdev->priv.uar->index); @@ -1921,6 +1926,10 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,  	int err;  	int eqn; +	err = mlx5_vector2eqn(priv->mdev, ix, &eqn, &irq); +	if (err) +		return err; +  	c = kvzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu));  	if (!c)  		return -ENOMEM; @@ -1937,7 +1946,6 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,  	c->xdp      = !!params->xdp_prog;  	c->stats    = &priv->channel_stats[ix].ch; -	mlx5_vector2eqn(priv->mdev, ix, &eqn, &irq);  	c->irq_desc = irq_to_desc(irq);  	netif_napi_add(netdev, &c->napi, mlx5e_napi_poll, 64); @@ -3574,6 +3582,7 @@ static int set_feature_cvlan_filter(struct net_device *netdev, bool enable)  	return 0;  } +#ifdef CONFIG_MLX5_ESWITCH  static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)  {  	struct mlx5e_priv *priv = netdev_priv(netdev); @@ -3586,6 +3595,7 @@ static int set_feature_tc_num_filters(struct net_device *netdev, bool enable)  	return 0;  } +#endif  static int set_feature_rx_all(struct net_device *netdev, bool enable)  { @@ -3684,7 +3694,9 @@ static int mlx5e_set_features(struct net_device *netdev,  	err |= MLX5E_HANDLE_FEATURE(NETIF_F_LRO, set_feature_lro);  	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_FILTER,  				    set_feature_cvlan_filter); +#ifdef CONFIG_MLX5_ESWITCH  	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_TC, set_feature_tc_num_filters); +#endif  	err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXALL, set_feature_rx_all);  	err |= MLX5E_HANDLE_FEATURE(NETIF_F_RXFCS, set_feature_rx_fcs);  	err |= MLX5E_HANDLE_FEATURE(NETIF_F_HW_VLAN_CTAG_RX, set_feature_rx_vlan); @@ -3755,10 +3767,11 @@ int mlx5e_change_mtu(struct net_device *netdev, int new_mtu,  	}  	if (params->rq_wq_type == MLX5_WQ_TYPE_LINKED_LIST_STRIDING_RQ) { +		bool is_linear = mlx5e_rx_mpwqe_is_linear_skb(priv->mdev, &new_channels.params);  		u8 ppw_old = mlx5e_mpwqe_log_pkts_per_wqe(params);  		u8 ppw_new = mlx5e_mpwqe_log_pkts_per_wqe(&new_channels.params); -		reset = reset && (ppw_old != ppw_new); +		reset = reset && (is_linear || (ppw_old != ppw_new));  	}  	if (!reset) { @@ -4678,7 +4691,9 @@ static void mlx5e_build_nic_netdev(struct net_device *netdev)  	    FT_CAP(modify_root) &&  	    FT_CAP(identified_miss_table_mode) &&  	    FT_CAP(flow_table_modify)) { +#ifdef CONFIG_MLX5_ESWITCH  		netdev->hw_features      |= NETIF_F_HW_TC; +#endif  #ifdef CONFIG_MLX5_EN_ARFS  		netdev->hw_features	 |= NETIF_F_NTUPLE;  #endif @@ -5004,11 +5019,21 @@ err_free_netdev:  int mlx5e_attach_netdev(struct mlx5e_priv *priv)  {  	const struct mlx5e_profile *profile; +	int max_nch;  	int err;  	profile = priv->profile;  	clear_bit(MLX5E_STATE_DESTROYING, &priv->state); +	/* max number of channels may have changed */ +	max_nch = mlx5e_get_max_num_channels(priv->mdev); +	if (priv->channels.params.num_channels > max_nch) { +		mlx5_core_warn(priv->mdev, "MLX5E: Reducing number of channels to %d\n", max_nch); +		priv->channels.params.num_channels = max_nch; +		mlx5e_build_default_indir_rqt(priv->channels.params.indirection_rqt, +					      MLX5E_INDIR_RQT_SIZE, max_nch); +	} +  	err = profile->init_tx(priv);  	if (err)  		goto out; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c index 79638dcbae78..16985ca3248d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rx.c @@ -1104,6 +1104,12 @@ mlx5e_skb_from_cqe_mpwrq_linear(struct mlx5e_rq *rq, struct mlx5e_mpw_info *wi,  	u32 frag_size;  	bool consumed; +	/* Check packet size. Note LRO doesn't use linear SKB */ +	if (unlikely(cqe_bcnt > rq->hw_mtu)) { +		rq->stats->oversize_pkts_sw_drop++; +		return NULL; +	} +  	va             = page_address(di->page) + head_offset;  	data           = va + rx_headroom;  	frag_size      = MLX5_SKB_FRAG_SZ(rx_headroom + cqe_bcnt32); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c index 35ded91203f5..4382ef85488c 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_selftest.c @@ -98,18 +98,17 @@ static int mlx5e_test_link_speed(struct mlx5e_priv *priv)  	return 1;  } -#ifdef CONFIG_INET -/* loopback test */ -#define MLX5E_TEST_PKT_SIZE (MLX5E_RX_MAX_HEAD - NET_IP_ALIGN) -static const char mlx5e_test_text[ETH_GSTRING_LEN] = "MLX5E SELF TEST"; -#define MLX5E_TEST_MAGIC 0x5AEED15C001ULL -  struct mlx5ehdr {  	__be32 version;  	__be64 magic; -	char   text[ETH_GSTRING_LEN];  }; +#ifdef CONFIG_INET +/* loopback test */ +#define MLX5E_TEST_PKT_SIZE (sizeof(struct ethhdr) + sizeof(struct iphdr) +\ +			     sizeof(struct udphdr) + sizeof(struct mlx5ehdr)) +#define MLX5E_TEST_MAGIC 0x5AEED15C001ULL +  static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)  {  	struct sk_buff *skb = NULL; @@ -117,10 +116,7 @@ static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)  	struct ethhdr *ethh;  	struct udphdr *udph;  	struct iphdr *iph; -	int datalen, iplen; - -	datalen = MLX5E_TEST_PKT_SIZE - -		  (sizeof(*ethh) + sizeof(*iph) + sizeof(*udph)); +	int    iplen;  	skb = netdev_alloc_skb(priv->netdev, MLX5E_TEST_PKT_SIZE);  	if (!skb) { @@ -149,7 +145,7 @@ static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)  	/* Fill UDP header */  	udph->source = htons(9);  	udph->dest = htons(9); /* Discard Protocol */ -	udph->len = htons(datalen + sizeof(struct udphdr)); +	udph->len = htons(sizeof(struct mlx5ehdr) + sizeof(struct udphdr));  	udph->check = 0;  	/* Fill IP header */ @@ -157,7 +153,8 @@ static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)  	iph->ttl = 32;  	iph->version = 4;  	iph->protocol = IPPROTO_UDP; -	iplen = sizeof(struct iphdr) + sizeof(struct udphdr) + datalen; +	iplen = sizeof(struct iphdr) + sizeof(struct udphdr) + +		sizeof(struct mlx5ehdr);  	iph->tot_len = htons(iplen);  	iph->frag_off = 0;  	iph->saddr = 0; @@ -170,9 +167,6 @@ static struct sk_buff *mlx5e_test_get_udp_skb(struct mlx5e_priv *priv)  	mlxh = skb_put(skb, sizeof(*mlxh));  	mlxh->version = 0;  	mlxh->magic = cpu_to_be64(MLX5E_TEST_MAGIC); -	strlcpy(mlxh->text, mlx5e_test_text, sizeof(mlxh->text)); -	datalen -= sizeof(*mlxh); -	skb_put_zero(skb, datalen);  	skb->csum = 0;  	skb->ip_summed = CHECKSUM_PARTIAL; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 1e55b9c27ffc..3e99d0728b2f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -83,6 +83,7 @@ static const struct counter_desc sw_stats_desc[] = {  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_wqe_err) },  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler_cqes) },  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_mpwqe_filler_strides) }, +	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_oversize_pkts_sw_drop) },  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_buff_alloc_err) },  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_blks) },  	{ MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_cqe_compress_pkts) }, @@ -161,6 +162,7 @@ void mlx5e_grp_sw_update_stats(struct mlx5e_priv *priv)  		s->rx_wqe_err   += rq_stats->wqe_err;  		s->rx_mpwqe_filler_cqes    += rq_stats->mpwqe_filler_cqes;  		s->rx_mpwqe_filler_strides += rq_stats->mpwqe_filler_strides; +		s->rx_oversize_pkts_sw_drop += rq_stats->oversize_pkts_sw_drop;  		s->rx_buff_alloc_err += rq_stats->buff_alloc_err;  		s->rx_cqe_compress_blks += rq_stats->cqe_compress_blks;  		s->rx_cqe_compress_pkts += rq_stats->cqe_compress_pkts; @@ -1189,6 +1191,7 @@ static const struct counter_desc rq_stats_desc[] = {  	{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, wqe_err) },  	{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, mpwqe_filler_cqes) },  	{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, mpwqe_filler_strides) }, +	{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, oversize_pkts_sw_drop) },  	{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, buff_alloc_err) },  	{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_blks) },  	{ MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, cqe_compress_pkts) }, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 77f74ce11280..3f8e870ef4c9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -96,6 +96,7 @@ struct mlx5e_sw_stats {  	u64 rx_wqe_err;  	u64 rx_mpwqe_filler_cqes;  	u64 rx_mpwqe_filler_strides; +	u64 rx_oversize_pkts_sw_drop;  	u64 rx_buff_alloc_err;  	u64 rx_cqe_compress_blks;  	u64 rx_cqe_compress_pkts; @@ -193,6 +194,7 @@ struct mlx5e_rq_stats {  	u64 wqe_err;  	u64 mpwqe_filler_cqes;  	u64 mpwqe_filler_strides; +	u64 oversize_pkts_sw_drop;  	u64 buff_alloc_err;  	u64 cqe_compress_blks;  	u64 cqe_compress_pkts; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index 608025ca5c04..fca6f4132c91 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1447,31 +1447,21 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,  					 inner_headers);  	} -	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { -		struct flow_dissector_key_eth_addrs *key = +	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { +		struct flow_dissector_key_basic *key =  			skb_flow_dissector_target(f->dissector, -						  FLOW_DISSECTOR_KEY_ETH_ADDRS, +						  FLOW_DISSECTOR_KEY_BASIC,  						  f->key); -		struct flow_dissector_key_eth_addrs *mask = +		struct flow_dissector_key_basic *mask =  			skb_flow_dissector_target(f->dissector, -						  FLOW_DISSECTOR_KEY_ETH_ADDRS, +						  FLOW_DISSECTOR_KEY_BASIC,  						  f->mask); +		MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype, +			 ntohs(mask->n_proto)); +		MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, +			 ntohs(key->n_proto)); -		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, -					     dmac_47_16), -				mask->dst); -		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, -					     dmac_47_16), -				key->dst); - -		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, -					     smac_47_16), -				mask->src); -		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, -					     smac_47_16), -				key->src); - -		if (!is_zero_ether_addr(mask->src) || !is_zero_ether_addr(mask->dst)) +		if (mask->n_proto)  			*match_level = MLX5_MATCH_L2;  	} @@ -1505,9 +1495,10 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,  			*match_level = MLX5_MATCH_L2;  		} -	} else { +	} else if (*match_level != MLX5_MATCH_NONE) {  		MLX5_SET(fte_match_set_lyr_2_4, headers_c, svlan_tag, 1);  		MLX5_SET(fte_match_set_lyr_2_4, headers_c, cvlan_tag, 1); +		*match_level = MLX5_MATCH_L2;  	}  	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_CVLAN)) { @@ -1545,21 +1536,31 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,  		}  	} -	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_BASIC)) { -		struct flow_dissector_key_basic *key = +	if (dissector_uses_key(f->dissector, FLOW_DISSECTOR_KEY_ETH_ADDRS)) { +		struct flow_dissector_key_eth_addrs *key =  			skb_flow_dissector_target(f->dissector, -						  FLOW_DISSECTOR_KEY_BASIC, +						  FLOW_DISSECTOR_KEY_ETH_ADDRS,  						  f->key); -		struct flow_dissector_key_basic *mask = +		struct flow_dissector_key_eth_addrs *mask =  			skb_flow_dissector_target(f->dissector, -						  FLOW_DISSECTOR_KEY_BASIC, +						  FLOW_DISSECTOR_KEY_ETH_ADDRS,  						  f->mask); -		MLX5_SET(fte_match_set_lyr_2_4, headers_c, ethertype, -			 ntohs(mask->n_proto)); -		MLX5_SET(fte_match_set_lyr_2_4, headers_v, ethertype, -			 ntohs(key->n_proto)); -		if (mask->n_proto) +		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, +					     dmac_47_16), +				mask->dst); +		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, +					     dmac_47_16), +				key->dst); + +		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_c, +					     smac_47_16), +				mask->src); +		ether_addr_copy(MLX5_ADDR_OF(fte_match_set_lyr_2_4, headers_v, +					     smac_47_16), +				key->src); + +		if (!is_zero_ether_addr(mask->src) || !is_zero_ether_addr(mask->dst))  			*match_level = MLX5_MATCH_L2;  	} @@ -1586,10 +1587,10 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,  			/* the HW doesn't need L3 inline to match on frag=no */  			if (!(key->flags & FLOW_DIS_IS_FRAGMENT)) -				*match_level = MLX5_INLINE_MODE_L2; +				*match_level = MLX5_MATCH_L2;  	/* ***  L2 attributes parsing up to here *** */  			else -				*match_level = MLX5_INLINE_MODE_IP; +				*match_level = MLX5_MATCH_L3;  		}  	} @@ -2979,7 +2980,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,  	if (!actions_match_supported(priv, exts, parse_attr, flow, extack))  		return -EOPNOTSUPP; -	if (attr->out_count > 1 && !mlx5_esw_has_fwd_fdb(priv->mdev)) { +	if (attr->mirror_count > 0 && !mlx5_esw_has_fwd_fdb(priv->mdev)) {  		NL_SET_ERR_MSG_MOD(extack,  				   "current firmware doesn't support split rule for port mirroring");  		netdev_warn_once(priv->netdev, "current firmware doesn't support split rule for port mirroring\n"); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c index 515e3d6de051..5a22c5874f3b 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/fpga/ipsec.c @@ -83,8 +83,14 @@ struct mlx5_fpga_ipsec_rule {  };  static const struct rhashtable_params rhash_sa = { -	.key_len = FIELD_SIZEOF(struct mlx5_fpga_ipsec_sa_ctx, hw_sa), -	.key_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hw_sa), +	/* Keep out "cmd" field from the key as it's +	 * value is not constant during the lifetime +	 * of the key object. +	 */ +	.key_len = FIELD_SIZEOF(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) - +		   FIELD_SIZEOF(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd), +	.key_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hw_sa) + +		      FIELD_SIZEOF(struct mlx5_ifc_fpga_ipsec_sa_v1, cmd),  	.head_offset = offsetof(struct mlx5_fpga_ipsec_sa_ctx, hash),  	.automatic_shrinking = true,  	.min_size = 1, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c index b59953daf8b4..11dabd62e2c7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c @@ -560,9 +560,9 @@ static int mlx5i_close(struct net_device *netdev)  	netif_carrier_off(epriv->netdev);  	mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qp.qpn); -	mlx5i_uninit_underlay_qp(epriv);  	mlx5e_deactivate_priv_channels(epriv);  	mlx5e_close_channels(&epriv->channels); +	mlx5i_uninit_underlay_qp(epriv);  unlock:  	mutex_unlock(&epriv->state_lock);  	return 0; diff --git a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c index 8e8fa823d611..69966dfc6e3d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dcbx.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dcbx.c @@ -191,7 +191,7 @@ qed_dcbx_dp_protocol(struct qed_hwfn *p_hwfn, struct qed_dcbx_results *p_data)  static void  qed_dcbx_set_params(struct qed_dcbx_results *p_data,  		    struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, -		    bool enable, u8 prio, u8 tc, +		    bool app_tlv, bool enable, u8 prio, u8 tc,  		    enum dcbx_protocol_type type,  		    enum qed_pci_personality personality)  { @@ -210,7 +210,7 @@ qed_dcbx_set_params(struct qed_dcbx_results *p_data,  		p_data->arr[type].dont_add_vlan0 = true;  	/* QM reconf data */ -	if (p_hwfn->hw_info.personality == personality) +	if (app_tlv && p_hwfn->hw_info.personality == personality)  		qed_hw_info_set_offload_tc(&p_hwfn->hw_info, tc);  	/* Configure dcbx vlan priority in doorbell block for roce EDPM */ @@ -225,7 +225,7 @@ qed_dcbx_set_params(struct qed_dcbx_results *p_data,  static void  qed_dcbx_update_app_info(struct qed_dcbx_results *p_data,  			 struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, -			 bool enable, u8 prio, u8 tc, +			 bool app_tlv, bool enable, u8 prio, u8 tc,  			 enum dcbx_protocol_type type)  {  	enum qed_pci_personality personality; @@ -240,7 +240,7 @@ qed_dcbx_update_app_info(struct qed_dcbx_results *p_data,  		personality = qed_dcbx_app_update[i].personality; -		qed_dcbx_set_params(p_data, p_hwfn, p_ptt, enable, +		qed_dcbx_set_params(p_data, p_hwfn, p_ptt, app_tlv, enable,  				    prio, tc, type, personality);  	}  } @@ -319,8 +319,8 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,  				enable = true;  			} -			qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, enable, -						 priority, tc, type); +			qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, true, +						 enable, priority, tc, type);  		}  	} @@ -341,7 +341,7 @@ qed_dcbx_process_tlv(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt,  			continue;  		enable = (type == DCBX_PROTOCOL_ETH) ? false : !!dcbx_version; -		qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, enable, +		qed_dcbx_update_app_info(p_data, p_hwfn, p_ptt, false, enable,  					 priority, tc, type);  	} diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 7ceb2b97538d..88a8576ca9ce 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -185,6 +185,10 @@ void qed_resc_free(struct qed_dev *cdev)  			qed_iscsi_free(p_hwfn);  			qed_ooo_free(p_hwfn);  		} + +		if (QED_IS_RDMA_PERSONALITY(p_hwfn)) +			qed_rdma_info_free(p_hwfn); +  		qed_iov_free(p_hwfn);  		qed_l2_free(p_hwfn);  		qed_dmae_info_free(p_hwfn); @@ -481,8 +485,16 @@ static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn,  	struct qed_qm_info *qm_info = &p_hwfn->qm_info;  	/* Can't have multiple flags set here */ -	if (bitmap_weight((unsigned long *)&pq_flags, sizeof(pq_flags)) > 1) +	if (bitmap_weight((unsigned long *)&pq_flags, +			  sizeof(pq_flags) * BITS_PER_BYTE) > 1) { +		DP_ERR(p_hwfn, "requested multiple pq flags 0x%x\n", pq_flags); +		goto err; +	} + +	if (!(qed_get_pq_flags(p_hwfn) & pq_flags)) { +		DP_ERR(p_hwfn, "pq flag 0x%x is not set\n", pq_flags);  		goto err; +	}  	switch (pq_flags) {  	case PQ_FLAGS_RLS: @@ -506,8 +518,7 @@ static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn,  	}  err: -	DP_ERR(p_hwfn, "BAD pq flags %d\n", pq_flags); -	return NULL; +	return &qm_info->start_pq;  }  /* save pq index in qm info */ @@ -531,20 +542,32 @@ u16 qed_get_cm_pq_idx_mcos(struct qed_hwfn *p_hwfn, u8 tc)  {  	u8 max_tc = qed_init_qm_get_num_tcs(p_hwfn); +	if (max_tc == 0) { +		DP_ERR(p_hwfn, "pq with flag 0x%lx do not exist\n", +		       PQ_FLAGS_MCOS); +		return p_hwfn->qm_info.start_pq; +	} +  	if (tc > max_tc)  		DP_ERR(p_hwfn, "tc %d must be smaller than %d\n", tc, max_tc); -	return qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_MCOS) + tc; +	return qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_MCOS) + (tc % max_tc);  }  u16 qed_get_cm_pq_idx_vf(struct qed_hwfn *p_hwfn, u16 vf)  {  	u16 max_vf = qed_init_qm_get_num_vfs(p_hwfn); +	if (max_vf == 0) { +		DP_ERR(p_hwfn, "pq with flag 0x%lx do not exist\n", +		       PQ_FLAGS_VFS); +		return p_hwfn->qm_info.start_pq; +	} +  	if (vf > max_vf)  		DP_ERR(p_hwfn, "vf %d must be smaller than %d\n", vf, max_vf); -	return qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_VFS) + vf; +	return qed_get_cm_pq_idx(p_hwfn, PQ_FLAGS_VFS) + (vf % max_vf);  }  u16 qed_get_cm_pq_idx_ofld_mtc(struct qed_hwfn *p_hwfn, u8 tc) @@ -1081,6 +1104,12 @@ int qed_resc_alloc(struct qed_dev *cdev)  				goto alloc_err;  		} +		if (QED_IS_RDMA_PERSONALITY(p_hwfn)) { +			rc = qed_rdma_info_alloc(p_hwfn); +			if (rc) +				goto alloc_err; +		} +  		/* DMA info initialization */  		rc = qed_dmae_info_alloc(p_hwfn);  		if (rc) @@ -2102,11 +2131,8 @@ int qed_hw_start_fastpath(struct qed_hwfn *p_hwfn)  	if (!p_ptt)  		return -EAGAIN; -	/* If roce info is allocated it means roce is initialized and should -	 * be enabled in searcher. -	 */  	if (p_hwfn->p_rdma_info && -	    p_hwfn->b_rdma_enabled_in_prs) +	    p_hwfn->p_rdma_info->active && p_hwfn->b_rdma_enabled_in_prs)  		qed_wr(p_hwfn, p_ptt, p_hwfn->rdma_prs_search_reg, 0x1);  	/* Re-open incoming traffic */ diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index 0f0aba793352..b22f464ea3fa 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -992,6 +992,8 @@ static int qed_int_attentions(struct qed_hwfn *p_hwfn)  	 */  	do {  		index = p_sb_attn->sb_index; +		/* finish reading index before the loop condition */ +		dma_rmb();  		attn_bits = le32_to_cpu(p_sb_attn->atten_bits);  		attn_acks = le32_to_cpu(p_sb_attn->atten_ack);  	} while (index != p_sb_attn->sb_index); diff --git a/drivers/net/ethernet/qlogic/qed/qed_main.c b/drivers/net/ethernet/qlogic/qed/qed_main.c index 35fd0db6a677..fff7f04d4525 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_main.c +++ b/drivers/net/ethernet/qlogic/qed/qed_main.c @@ -1782,9 +1782,9 @@ static int qed_drain(struct qed_dev *cdev)  			return -EBUSY;  		}  		rc = qed_mcp_drain(hwfn, ptt); +		qed_ptt_release(hwfn, ptt);  		if (rc)  			return rc; -		qed_ptt_release(hwfn, ptt);  	}  	return 0; diff --git a/drivers/net/ethernet/qlogic/qed/qed_rdma.c b/drivers/net/ethernet/qlogic/qed/qed_rdma.c index 62113438c880..7873d6dfd91f 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_rdma.c +++ b/drivers/net/ethernet/qlogic/qed/qed_rdma.c @@ -140,22 +140,34 @@ static u32 qed_rdma_get_sb_id(void *p_hwfn, u32 rel_sb_id)  	return FEAT_NUM((struct qed_hwfn *)p_hwfn, QED_PF_L2_QUE) + rel_sb_id;  } -static int qed_rdma_alloc(struct qed_hwfn *p_hwfn, -			  struct qed_ptt *p_ptt, -			  struct qed_rdma_start_in_params *params) +int qed_rdma_info_alloc(struct qed_hwfn *p_hwfn)  {  	struct qed_rdma_info *p_rdma_info; -	u32 num_cons, num_tasks; -	int rc = -ENOMEM; -	DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Allocating RDMA\n"); - -	/* Allocate a struct with current pf rdma info */  	p_rdma_info = kzalloc(sizeof(*p_rdma_info), GFP_KERNEL);  	if (!p_rdma_info) -		return rc; +		return -ENOMEM; + +	spin_lock_init(&p_rdma_info->lock);  	p_hwfn->p_rdma_info = p_rdma_info; +	return 0; +} + +void qed_rdma_info_free(struct qed_hwfn *p_hwfn) +{ +	kfree(p_hwfn->p_rdma_info); +	p_hwfn->p_rdma_info = NULL; +} + +static int qed_rdma_alloc(struct qed_hwfn *p_hwfn) +{ +	struct qed_rdma_info *p_rdma_info = p_hwfn->p_rdma_info; +	u32 num_cons, num_tasks; +	int rc = -ENOMEM; + +	DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "Allocating RDMA\n"); +  	if (QED_IS_IWARP_PERSONALITY(p_hwfn))  		p_rdma_info->proto = PROTOCOLID_IWARP;  	else @@ -183,7 +195,7 @@ static int qed_rdma_alloc(struct qed_hwfn *p_hwfn,  	/* Allocate a struct with device params and fill it */  	p_rdma_info->dev = kzalloc(sizeof(*p_rdma_info->dev), GFP_KERNEL);  	if (!p_rdma_info->dev) -		goto free_rdma_info; +		return rc;  	/* Allocate a struct with port params and fill it */  	p_rdma_info->port = kzalloc(sizeof(*p_rdma_info->port), GFP_KERNEL); @@ -298,8 +310,6 @@ free_rdma_port:  	kfree(p_rdma_info->port);  free_rdma_dev:  	kfree(p_rdma_info->dev); -free_rdma_info: -	kfree(p_rdma_info);  	return rc;  } @@ -370,8 +380,6 @@ static void qed_rdma_resc_free(struct qed_hwfn *p_hwfn)  	kfree(p_rdma_info->port);  	kfree(p_rdma_info->dev); - -	kfree(p_rdma_info);  }  static void qed_rdma_free_tid(void *rdma_cxt, u32 itid) @@ -679,8 +687,6 @@ static int qed_rdma_setup(struct qed_hwfn *p_hwfn,  	DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "RDMA setup\n"); -	spin_lock_init(&p_hwfn->p_rdma_info->lock); -  	qed_rdma_init_devinfo(p_hwfn, params);  	qed_rdma_init_port(p_hwfn);  	qed_rdma_init_events(p_hwfn, params); @@ -727,7 +733,7 @@ static int qed_rdma_stop(void *rdma_cxt)  	/* Disable RoCE search */  	qed_wr(p_hwfn, p_ptt, p_hwfn->rdma_prs_search_reg, 0);  	p_hwfn->b_rdma_enabled_in_prs = false; - +	p_hwfn->p_rdma_info->active = 0;  	qed_wr(p_hwfn, p_ptt, PRS_REG_ROCE_DEST_QP_MAX_PF, 0);  	ll2_ethertype_en = qed_rd(p_hwfn, p_ptt, PRS_REG_LIGHT_L2_ETHERTYPE_EN); @@ -1236,7 +1242,8 @@ qed_rdma_create_qp(void *rdma_cxt,  	u8 max_stats_queues;  	int rc; -	if (!rdma_cxt || !in_params || !out_params || !p_hwfn->p_rdma_info) { +	if (!rdma_cxt || !in_params || !out_params || +	    !p_hwfn->p_rdma_info->active) {  		DP_ERR(p_hwfn->cdev,  		       "qed roce create qp failed due to NULL entry (rdma_cxt=%p, in=%p, out=%p, roce_info=?\n",  		       rdma_cxt, in_params, out_params); @@ -1802,8 +1809,8 @@ bool qed_rdma_allocated_qps(struct qed_hwfn *p_hwfn)  {  	bool result; -	/* if rdma info has not been allocated, naturally there are no qps */ -	if (!p_hwfn->p_rdma_info) +	/* if rdma wasn't activated yet, naturally there are no qps */ +	if (!p_hwfn->p_rdma_info->active)  		return false;  	spin_lock_bh(&p_hwfn->p_rdma_info->lock); @@ -1849,7 +1856,7 @@ static int qed_rdma_start(void *rdma_cxt,  	if (!p_ptt)  		goto err; -	rc = qed_rdma_alloc(p_hwfn, p_ptt, params); +	rc = qed_rdma_alloc(p_hwfn);  	if (rc)  		goto err1; @@ -1858,6 +1865,7 @@ static int qed_rdma_start(void *rdma_cxt,  		goto err2;  	qed_ptt_release(p_hwfn, p_ptt); +	p_hwfn->p_rdma_info->active = 1;  	return rc; diff --git a/drivers/net/ethernet/qlogic/qed/qed_rdma.h b/drivers/net/ethernet/qlogic/qed/qed_rdma.h index 6f722ee8ee94..3689fe3e5935 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_rdma.h +++ b/drivers/net/ethernet/qlogic/qed/qed_rdma.h @@ -102,6 +102,7 @@ struct qed_rdma_info {  	u16 max_queue_zones;  	enum protocol_type proto;  	struct qed_iwarp_info iwarp; +	u8 active:1;  };  struct qed_rdma_qp { @@ -176,10 +177,14 @@ struct qed_rdma_qp {  #if IS_ENABLED(CONFIG_QED_RDMA)  void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt);  void qed_rdma_dpm_conf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt); +int qed_rdma_info_alloc(struct qed_hwfn *p_hwfn); +void qed_rdma_info_free(struct qed_hwfn *p_hwfn);  #else  static inline void qed_rdma_dpm_conf(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt) {}  static inline void qed_rdma_dpm_bar(struct qed_hwfn *p_hwfn,  				    struct qed_ptt *p_ptt) {} +static inline int qed_rdma_info_alloc(struct qed_hwfn *p_hwfn) {return -EINVAL;} +static inline void qed_rdma_info_free(struct qed_hwfn *p_hwfn) {}  #endif  int diff --git a/drivers/net/phy/mdio-gpio.c b/drivers/net/phy/mdio-gpio.c index 33265747bf39..0fbcedcdf6e2 100644 --- a/drivers/net/phy/mdio-gpio.c +++ b/drivers/net/phy/mdio-gpio.c @@ -63,7 +63,7 @@ static void mdio_dir(struct mdiobb_ctrl *ctrl, int dir)  		 * assume the pin serves as pull-up. If direction is  		 * output, the default value is high.  		 */ -		gpiod_set_value(bitbang->mdo, 1); +		gpiod_set_value_cansleep(bitbang->mdo, 1);  		return;  	} @@ -78,7 +78,7 @@ static int mdio_get(struct mdiobb_ctrl *ctrl)  	struct mdio_gpio_info *bitbang =  		container_of(ctrl, struct mdio_gpio_info, ctrl); -	return gpiod_get_value(bitbang->mdio); +	return gpiod_get_value_cansleep(bitbang->mdio);  }  static void mdio_set(struct mdiobb_ctrl *ctrl, int what) @@ -87,9 +87,9 @@ static void mdio_set(struct mdiobb_ctrl *ctrl, int what)  		container_of(ctrl, struct mdio_gpio_info, ctrl);  	if (bitbang->mdo) -		gpiod_set_value(bitbang->mdo, what); +		gpiod_set_value_cansleep(bitbang->mdo, what);  	else -		gpiod_set_value(bitbang->mdio, what); +		gpiod_set_value_cansleep(bitbang->mdio, what);  }  static void mdc_set(struct mdiobb_ctrl *ctrl, int what) @@ -97,7 +97,7 @@ static void mdc_set(struct mdiobb_ctrl *ctrl, int what)  	struct mdio_gpio_info *bitbang =  		container_of(ctrl, struct mdio_gpio_info, ctrl); -	gpiod_set_value(bitbang->mdc, what); +	gpiod_set_value_cansleep(bitbang->mdc, what);  }  static const struct mdiobb_ops mdio_gpio_ops = { diff --git a/drivers/net/phy/mscc.c b/drivers/net/phy/mscc.c index a2e59f4f6f01..7cae17517744 100644 --- a/drivers/net/phy/mscc.c +++ b/drivers/net/phy/mscc.c @@ -810,17 +810,13 @@ static int vsc85xx_default_config(struct phy_device *phydev)  	phydev->mdix_ctrl = ETH_TP_MDI_AUTO;  	mutex_lock(&phydev->lock); -	rc = phy_select_page(phydev, MSCC_PHY_PAGE_EXTENDED_2); -	if (rc < 0) -		goto out_unlock; -	reg_val = phy_read(phydev, MSCC_PHY_RGMII_CNTL); -	reg_val &= ~(RGMII_RX_CLK_DELAY_MASK); -	reg_val |= (RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS); -	phy_write(phydev, MSCC_PHY_RGMII_CNTL, reg_val); +	reg_val = RGMII_RX_CLK_DELAY_1_1_NS << RGMII_RX_CLK_DELAY_POS; + +	rc = phy_modify_paged(phydev, MSCC_PHY_PAGE_EXTENDED_2, +			      MSCC_PHY_RGMII_CNTL, RGMII_RX_CLK_DELAY_MASK, +			      reg_val); -out_unlock: -	rc = phy_restore_page(phydev, rc, rc > 0 ? 0 : rc);  	mutex_unlock(&phydev->lock);  	return rc; diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index db633ae9f784..364f514d56d8 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c @@ -985,8 +985,6 @@ static void team_port_disable(struct team *team,  	team->en_port_count--;  	team_queue_override_port_del(team, port);  	team_adjust_ops(team); -	team_notify_peers(team); -	team_mcast_rejoin(team);  	team_lower_state_changed(port);  } diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 060135ceaf0e..e244f5d7512a 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -1536,6 +1536,7 @@ static void tun_rx_batched(struct tun_struct *tun, struct tun_file *tfile,  	if (!rx_batched || (!more && skb_queue_empty(queue))) {  		local_bh_disable(); +		skb_record_rx_queue(skb, tfile->queue_index);  		netif_receive_skb(skb);  		local_bh_enable();  		return; @@ -1555,8 +1556,11 @@ static void tun_rx_batched(struct tun_struct *tun, struct tun_file *tfile,  		struct sk_buff *nskb;  		local_bh_disable(); -		while ((nskb = __skb_dequeue(&process_queue))) +		while ((nskb = __skb_dequeue(&process_queue))) { +			skb_record_rx_queue(nskb, tfile->queue_index);  			netif_receive_skb(nskb); +		} +		skb_record_rx_queue(skb, tfile->queue_index);  		netif_receive_skb(skb);  		local_bh_enable();  	} @@ -2451,6 +2455,7 @@ build:  	if (!rcu_dereference(tun->steering_prog))  		rxhash = __skb_get_hash_symmetric(skb); +	skb_record_rx_queue(skb, tfile->queue_index);  	netif_receive_skb(skb);  	stats = get_cpu_ptr(tun->pcpu_stats); diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 3e2c041d76ac..cecfd77c9f3c 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -70,7 +70,8 @@ static const unsigned long guest_offloads[] = {  	VIRTIO_NET_F_GUEST_TSO4,  	VIRTIO_NET_F_GUEST_TSO6,  	VIRTIO_NET_F_GUEST_ECN, -	VIRTIO_NET_F_GUEST_UFO +	VIRTIO_NET_F_GUEST_UFO, +	VIRTIO_NET_F_GUEST_CSUM  };  struct virtnet_stat_desc { @@ -2334,9 +2335,6 @@ static int virtnet_clear_guest_offloads(struct virtnet_info *vi)  	if (!vi->guest_offloads)  		return 0; -	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM)) -		offloads = 1ULL << VIRTIO_NET_F_GUEST_CSUM; -  	return virtnet_set_guest_offloads(vi, offloads);  } @@ -2346,8 +2344,6 @@ static int virtnet_restore_guest_offloads(struct virtnet_info *vi)  	if (!vi->guest_offloads)  		return 0; -	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM)) -		offloads |= 1ULL << VIRTIO_NET_F_GUEST_CSUM;  	return virtnet_set_guest_offloads(vi, offloads);  } @@ -2365,8 +2361,9 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,  	    && (virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO4) ||  	        virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_TSO6) ||  	        virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_ECN) || -		virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO))) { -		NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO, disable LRO first"); +		virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_UFO) || +		virtio_has_feature(vi->vdev, VIRTIO_NET_F_GUEST_CSUM))) { +		NL_SET_ERR_MSG_MOD(extack, "Can't set XDP while host is implementing LRO/CSUM, disable LRO/CSUM first");  		return -EOPNOTSUPP;  	} diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index a1c2801ded10..7e49342bae38 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -6867,7 +6867,7 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,  	u32 bitmap;  	if (drop) { -		if (vif->type == NL80211_IFTYPE_STATION) { +		if (vif && vif->type == NL80211_IFTYPE_STATION) {  			bitmap = ~(1 << WMI_MGMT_TID);  			list_for_each_entry(arvif, &ar->arvifs, list) {  				if (arvif->vdev_type == WMI_VDEV_TYPE_STA) diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 1e3b5f4a4cf9..f23cb2f3d296 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1251,6 +1251,7 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,  	struct ath_vif *avp = (void *)vif->drv_priv;  	struct ath_node *an = &avp->mcast_node; +	mutex_lock(&sc->mutex);  	if (IS_ENABLED(CONFIG_ATH9K_TX99)) {  		if (sc->cur_chan->nvifs >= 1) {  			mutex_unlock(&sc->mutex); @@ -1259,8 +1260,6 @@ static int ath9k_add_interface(struct ieee80211_hw *hw,  		sc->tx99_vif = vif;  	} -	mutex_lock(&sc->mutex); -  	ath_dbg(common, CONFIG, "Attach a VIF of type: %d\n", vif->type);  	sc->cur_chan->nvifs++; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 230a378c26fc..7f0a5bade70a 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -6005,7 +6005,8 @@ static int brcmf_construct_chaninfo(struct brcmf_cfg80211_info *cfg,  			 * for subsequent chanspecs.  			 */  			channel->flags = IEEE80211_CHAN_NO_HT40 | -					 IEEE80211_CHAN_NO_80MHZ; +					 IEEE80211_CHAN_NO_80MHZ | +					 IEEE80211_CHAN_NO_160MHZ;  			ch.bw = BRCMU_CHAN_BW_20;  			cfg->d11inf.encchspec(&ch);  			chaninfo = ch.chspec; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c index e7584b842dce..eb5db94f5745 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmutil/d11.c @@ -193,6 +193,9 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)  		}  		break;  	case BRCMU_CHSPEC_D11AC_BW_160: +		ch->bw = BRCMU_CHAN_BW_160; +		ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK, +					 BRCMU_CHSPEC_D11AC_SB_SHIFT);  		switch (ch->sb) {  		case BRCMU_CHAN_SB_LLL:  			ch->control_ch_num -= CH_70MHZ_APART; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h index 2439e98431ee..7492dfb6729b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/acpi.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/acpi.h @@ -6,6 +6,7 @@   * GPL LICENSE SUMMARY   *   * Copyright(c) 2017        Intel Deutschland GmbH + * Copyright(c) 2018        Intel Corporation   *   * This program is free software; you can redistribute it and/or modify   * it under the terms of version 2 of the GNU General Public License as @@ -26,6 +27,7 @@   * BSD LICENSE   *   * Copyright(c) 2017        Intel Deutschland GmbH + * Copyright(c) 2018        Intel Corporation   * All rights reserved.   *   * Redistribution and use in source and binary forms, with or without @@ -81,7 +83,7 @@  #define ACPI_WRDS_WIFI_DATA_SIZE	(ACPI_SAR_TABLE_SIZE + 2)  #define ACPI_EWRD_WIFI_DATA_SIZE	((ACPI_SAR_PROFILE_NUM - 1) * \  					 ACPI_SAR_TABLE_SIZE + 3) -#define ACPI_WGDS_WIFI_DATA_SIZE	18 +#define ACPI_WGDS_WIFI_DATA_SIZE	19  #define ACPI_WRDD_WIFI_DATA_SIZE	2  #define ACPI_SPLC_WIFI_DATA_SIZE	2 diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 6b95d0e75889..2b8b50a77990 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -154,7 +154,11 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,  			const struct iwl_fw_runtime_ops *ops, void *ops_ctx,  			struct dentry *dbgfs_dir); -void iwl_fw_runtime_exit(struct iwl_fw_runtime *fwrt); +static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt) +{ +	kfree(fwrt->dump.d3_debug_data); +	fwrt->dump.d3_debug_data = NULL; +}  void iwl_fw_runtime_suspend(struct iwl_fw_runtime *fwrt); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index dade206d5511..2ba890445c35 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -893,7 +893,7 @@ static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)  	IWL_DEBUG_RADIO(mvm, "Sending GEO_TX_POWER_LIMIT\n");  	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES * ACPI_WGDS_NUM_BANDS * -		     ACPI_WGDS_TABLE_SIZE !=  ACPI_WGDS_WIFI_DATA_SIZE); +		     ACPI_WGDS_TABLE_SIZE + 1 !=  ACPI_WGDS_WIFI_DATA_SIZE);  	BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES > IWL_NUM_GEO_PROFILES); @@ -928,6 +928,11 @@ static int iwl_mvm_sar_get_ewrd_table(struct iwl_mvm *mvm)  	return -ENOENT;  } +static int iwl_mvm_sar_get_wgds_table(struct iwl_mvm *mvm) +{ +	return -ENOENT; +} +  static int iwl_mvm_sar_geo_init(struct iwl_mvm *mvm)  {  	return 0; @@ -954,8 +959,11 @@ static int iwl_mvm_sar_init(struct iwl_mvm *mvm)  		IWL_DEBUG_RADIO(mvm,  				"WRDS SAR BIOS table invalid or unavailable. (%d)\n",  				ret); -		/* if not available, don't fail and don't bother with EWRD */ -		return 0; +		/* +		 * If not available, don't fail and don't bother with EWRD. +		 * Return 1 to tell that we can't use WGDS either. +		 */ +		return 1;  	}  	ret = iwl_mvm_sar_get_ewrd_table(mvm); @@ -968,9 +976,13 @@ static int iwl_mvm_sar_init(struct iwl_mvm *mvm)  	/* choose profile 1 (WRDS) as default for both chains */  	ret = iwl_mvm_sar_select_profile(mvm, 1, 1); -	/* if we don't have profile 0 from BIOS, just skip it */ +	/* +	 * If we don't have profile 0 from BIOS, just skip it.  This +	 * means that SAR Geo will not be enabled either, even if we +	 * have other valid profiles. +	 */  	if (ret == -ENOENT) -		return 0; +		return 1;  	return ret;  } @@ -1168,11 +1180,19 @@ int iwl_mvm_up(struct iwl_mvm *mvm)  		iwl_mvm_unref(mvm, IWL_MVM_REF_UCODE_DOWN);  	ret = iwl_mvm_sar_init(mvm); -	if (ret) -		goto error; +	if (ret == 0) { +		ret = iwl_mvm_sar_geo_init(mvm); +	} else if (ret > 0 && !iwl_mvm_sar_get_wgds_table(mvm)) { +		/* +		 * If basic SAR is not available, we check for WGDS, +		 * which should *not* be available either.  If it is +		 * available, issue an error, because we can't use SAR +		 * Geo without basic SAR. +		 */ +		IWL_ERR(mvm, "BIOS contains WGDS but no WRDS\n"); +	} -	ret = iwl_mvm_sar_geo_init(mvm); -	if (ret) +	if (ret < 0)  		goto error;  	iwl_mvm_leds_sync(mvm); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 505b0385d800..00f831d88366 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -301,8 +301,12 @@ struct ieee80211_regdomain *iwl_mvm_get_regdomain(struct wiphy *wiphy,  		goto out;  	} -	if (changed) -		*changed = (resp->status == MCC_RESP_NEW_CHAN_PROFILE); +	if (changed) { +		u32 status = le32_to_cpu(resp->status); + +		*changed = (status == MCC_RESP_NEW_CHAN_PROFILE || +			    status == MCC_RESP_ILLEGAL); +	}  	regd = iwl_parse_nvm_mcc_info(mvm->trans->dev, mvm->cfg,  				      __le32_to_cpu(resp->n_channels), @@ -4444,10 +4448,6 @@ static void iwl_mvm_mac_sta_statistics(struct ieee80211_hw *hw,  		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_SIGNAL_AVG);  	} -	if (!fw_has_capa(&mvm->fw->ucode_capa, -			 IWL_UCODE_TLV_CAPA_RADIO_BEACON_STATS)) -		return; -  	/* if beacon filtering isn't on mac80211 does it anyway */  	if (!(vif->driver_flags & IEEE80211_VIF_BEACON_FILTER))  		return; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c index 3633f27d048a..6fc5cc1f2b5b 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/nvm.c @@ -539,9 +539,8 @@ iwl_mvm_update_mcc(struct iwl_mvm *mvm, const char *alpha2,  	}  	IWL_DEBUG_LAR(mvm, -		      "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') change: %d n_chans: %d\n", -		      status, mcc, mcc >> 8, mcc & 0xff, -		      !!(status == MCC_RESP_NEW_CHAN_PROFILE), n_channels); +		      "MCC response status: 0x%x. new MCC: 0x%x ('%c%c') n_chans: %d\n", +		      status, mcc, mcc >> 8, mcc & 0xff, n_channels);  exit:  	iwl_free_resp(&cmd); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index 0e2092526fae..af3fba10abc1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -858,6 +858,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,  	iwl_mvm_thermal_exit(mvm);   out_free:  	iwl_fw_flush_dump(&mvm->fwrt); +	iwl_fw_runtime_free(&mvm->fwrt);  	if (iwlmvm_mod_params.init_dbg)  		return op_mode; @@ -910,6 +911,7 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode)  	iwl_mvm_tof_clean(mvm); +	iwl_fw_runtime_free(&mvm->fwrt);  	mutex_destroy(&mvm->mutex);  	mutex_destroy(&mvm->d0i3_suspend_mutex); diff --git a/drivers/net/wireless/mediatek/mt76/Kconfig b/drivers/net/wireless/mediatek/mt76/Kconfig index 0ccbcd7e887d..c30d8f5bbf2a 100644 --- a/drivers/net/wireless/mediatek/mt76/Kconfig +++ b/drivers/net/wireless/mediatek/mt76/Kconfig @@ -1,6 +1,12 @@  config MT76_CORE  	tristate +config MT76_LEDS +	bool +	depends on MT76_CORE +	depends on LEDS_CLASS=y || MT76_CORE=LEDS_CLASS +	default y +  config MT76_USB  	tristate  	depends on MT76_CORE diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c index 2a699e8b79bf..7d219ff2d480 100644 --- a/drivers/net/wireless/mediatek/mt76/mac80211.c +++ b/drivers/net/wireless/mediatek/mt76/mac80211.c @@ -345,9 +345,11 @@ int mt76_register_device(struct mt76_dev *dev, bool vht,  	mt76_check_sband(dev, NL80211_BAND_2GHZ);  	mt76_check_sband(dev, NL80211_BAND_5GHZ); -	ret = mt76_led_init(dev); -	if (ret) -		return ret; +	if (IS_ENABLED(CONFIG_MT76_LEDS)) { +		ret = mt76_led_init(dev); +		if (ret) +			return ret; +	}  	return ieee80211_register_hw(hw);  } diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02.h b/drivers/net/wireless/mediatek/mt76/mt76x02.h index 47c42c607964..7806963b1905 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02.h +++ b/drivers/net/wireless/mediatek/mt76/mt76x02.h @@ -71,7 +71,6 @@ struct mt76x02_dev {  	struct mac_address macaddr_list[8];  	struct mutex phy_mutex; -	struct mutex mutex;  	u8 txdone_seq;  	DECLARE_KFIFO_PTR(txstatus_fifo, struct mt76x02_tx_status); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c index 3824290b219d..fd125722d1fb 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c @@ -507,8 +507,10 @@ int mt76x2_register_device(struct mt76x02_dev *dev)  	mt76x2_dfs_init_detector(dev);  	/* init led callbacks */ -	dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness; -	dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink; +	if (IS_ENABLED(CONFIG_MT76_LEDS)) { +		dev->mt76.led_cdev.brightness_set = mt76x2_led_set_brightness; +		dev->mt76.led_cdev.blink_set = mt76x2_led_set_blink; +	}  	ret = mt76_register_device(&dev->mt76, true, mt76x02_rates,  				   ARRAY_SIZE(mt76x02_rates)); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c index 034a06295668..3f001bd6806c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x2/pci_main.c @@ -272,9 +272,9 @@ mt76x2_set_rts_threshold(struct ieee80211_hw *hw, u32 val)  	if (val != ~0 && val > 0xffff)  		return -EINVAL; -	mutex_lock(&dev->mutex); +	mutex_lock(&dev->mt76.mutex);  	mt76x2_mac_set_tx_protection(dev, val); -	mutex_unlock(&dev->mutex); +	mutex_unlock(&dev->mt76.mutex);  	return 0;  } diff --git a/drivers/net/wireless/ti/wlcore/sdio.c b/drivers/net/wireless/ti/wlcore/sdio.c index 4c2154b9e6a3..bd10165d7eec 100644 --- a/drivers/net/wireless/ti/wlcore/sdio.c +++ b/drivers/net/wireless/ti/wlcore/sdio.c @@ -285,7 +285,7 @@ static int wl1271_probe(struct sdio_func *func,  	struct resource res[2];  	mmc_pm_flag_t mmcflags;  	int ret = -ENOMEM; -	int irq, wakeirq; +	int irq, wakeirq, num_irqs;  	const char *chip_family;  	/* We are only able to handle the wlan function */ @@ -353,12 +353,17 @@ static int wl1271_probe(struct sdio_func *func,  		       irqd_get_trigger_type(irq_get_irq_data(irq));  	res[0].name = "irq"; -	res[1].start = wakeirq; -	res[1].flags = IORESOURCE_IRQ | -		       irqd_get_trigger_type(irq_get_irq_data(wakeirq)); -	res[1].name = "wakeirq"; -	ret = platform_device_add_resources(glue->core, res, ARRAY_SIZE(res)); +	if (wakeirq > 0) { +		res[1].start = wakeirq; +		res[1].flags = IORESOURCE_IRQ | +			       irqd_get_trigger_type(irq_get_irq_data(wakeirq)); +		res[1].name = "wakeirq"; +		num_irqs = 2; +	} else { +		num_irqs = 1; +	} +	ret = platform_device_add_resources(glue->core, res, num_irqs);  	if (ret) {  		dev_err(glue->dev, "can't add resources\n");  		goto out_dev_put; diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 0b70c8bab045..54032c466636 100644 --- a/drivers/nvme/host/fc.c +++ b/drivers/nvme/host/fc.c @@ -152,6 +152,7 @@ struct nvme_fc_ctrl {  	bool			ioq_live;  	bool			assoc_active; +	atomic_t		err_work_active;  	u64			association_id;  	struct list_head	ctrl_list;	/* rport->ctrl_list */ @@ -160,6 +161,7 @@ struct nvme_fc_ctrl {  	struct blk_mq_tag_set	tag_set;  	struct delayed_work	connect_work; +	struct work_struct	err_work;  	struct kref		ref;  	u32			flags; @@ -1531,6 +1533,10 @@ nvme_fc_abort_aen_ops(struct nvme_fc_ctrl *ctrl)  	struct nvme_fc_fcp_op *aen_op = ctrl->aen_ops;  	int i; +	/* ensure we've initialized the ops once */ +	if (!(aen_op->flags & FCOP_FLAGS_AEN)) +		return; +  	for (i = 0; i < NVME_NR_AEN_COMMANDS; i++, aen_op++)  		__nvme_fc_abort_op(ctrl, aen_op);  } @@ -2049,7 +2055,25 @@ nvme_fc_nvme_ctrl_freed(struct nvme_ctrl *nctrl)  static void  nvme_fc_error_recovery(struct nvme_fc_ctrl *ctrl, char *errmsg)  { -	/* only proceed if in LIVE state - e.g. on first error */ +	int active; + +	/* +	 * if an error (io timeout, etc) while (re)connecting, +	 * it's an error on creating the new association. +	 * Start the error recovery thread if it hasn't already +	 * been started. It is expected there could be multiple +	 * ios hitting this path before things are cleaned up. +	 */ +	if (ctrl->ctrl.state == NVME_CTRL_CONNECTING) { +		active = atomic_xchg(&ctrl->err_work_active, 1); +		if (!active && !schedule_work(&ctrl->err_work)) { +			atomic_set(&ctrl->err_work_active, 0); +			WARN_ON(1); +		} +		return; +	} + +	/* Otherwise, only proceed if in LIVE state - e.g. on first error */  	if (ctrl->ctrl.state != NVME_CTRL_LIVE)  		return; @@ -2814,6 +2838,7 @@ nvme_fc_delete_ctrl(struct nvme_ctrl *nctrl)  {  	struct nvme_fc_ctrl *ctrl = to_fc_ctrl(nctrl); +	cancel_work_sync(&ctrl->err_work);  	cancel_delayed_work_sync(&ctrl->connect_work);  	/*  	 * kill the association on the link side.  this will block @@ -2866,23 +2891,30 @@ nvme_fc_reconnect_or_delete(struct nvme_fc_ctrl *ctrl, int status)  }  static void -nvme_fc_reset_ctrl_work(struct work_struct *work) +__nvme_fc_terminate_io(struct nvme_fc_ctrl *ctrl)  { -	struct nvme_fc_ctrl *ctrl = -		container_of(work, struct nvme_fc_ctrl, ctrl.reset_work); -	int ret; - -	nvme_stop_ctrl(&ctrl->ctrl); +	nvme_stop_keep_alive(&ctrl->ctrl);  	/* will block will waiting for io to terminate */  	nvme_fc_delete_association(ctrl); -	if (!nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING)) { +	if (ctrl->ctrl.state != NVME_CTRL_CONNECTING && +	    !nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_CONNECTING))  		dev_err(ctrl->ctrl.device,  			"NVME-FC{%d}: error_recovery: Couldn't change state "  			"to CONNECTING\n", ctrl->cnum); -		return; -	} +} + +static void +nvme_fc_reset_ctrl_work(struct work_struct *work) +{ +	struct nvme_fc_ctrl *ctrl = +		container_of(work, struct nvme_fc_ctrl, ctrl.reset_work); +	int ret; + +	__nvme_fc_terminate_io(ctrl); + +	nvme_stop_ctrl(&ctrl->ctrl);  	if (ctrl->rport->remoteport.port_state == FC_OBJSTATE_ONLINE)  		ret = nvme_fc_create_association(ctrl); @@ -2897,6 +2929,24 @@ nvme_fc_reset_ctrl_work(struct work_struct *work)  			ctrl->cnum);  } +static void +nvme_fc_connect_err_work(struct work_struct *work) +{ +	struct nvme_fc_ctrl *ctrl = +			container_of(work, struct nvme_fc_ctrl, err_work); + +	__nvme_fc_terminate_io(ctrl); + +	atomic_set(&ctrl->err_work_active, 0); + +	/* +	 * Rescheduling the connection after recovering +	 * from the io error is left to the reconnect work +	 * item, which is what should have stalled waiting on +	 * the io that had the error that scheduled this work. +	 */ +} +  static const struct nvme_ctrl_ops nvme_fc_ctrl_ops = {  	.name			= "fc",  	.module			= THIS_MODULE, @@ -3007,6 +3057,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,  	ctrl->cnum = idx;  	ctrl->ioq_live = false;  	ctrl->assoc_active = false; +	atomic_set(&ctrl->err_work_active, 0);  	init_waitqueue_head(&ctrl->ioabort_wait);  	get_device(ctrl->dev); @@ -3014,6 +3065,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,  	INIT_WORK(&ctrl->ctrl.reset_work, nvme_fc_reset_ctrl_work);  	INIT_DELAYED_WORK(&ctrl->connect_work, nvme_fc_connect_ctrl_work); +	INIT_WORK(&ctrl->err_work, nvme_fc_connect_err_work);  	spin_lock_init(&ctrl->lock);  	/* io queue count */ @@ -3103,6 +3155,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,  fail_ctrl:  	nvme_change_ctrl_state(&ctrl->ctrl, NVME_CTRL_DELETING);  	cancel_work_sync(&ctrl->ctrl.reset_work); +	cancel_work_sync(&ctrl->err_work);  	cancel_delayed_work_sync(&ctrl->connect_work);  	ctrl->ctrl.opts = NULL; diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c index 9b18ce90f907..27f67dfa649d 100644 --- a/drivers/nvmem/core.c +++ b/drivers/nvmem/core.c @@ -44,6 +44,7 @@ struct nvmem_cell {  	int			bytes;  	int			bit_offset;  	int			nbits; +	struct device_node	*np;  	struct nvmem_device	*nvmem;  	struct list_head	node;  }; @@ -298,6 +299,7 @@ static void nvmem_cell_drop(struct nvmem_cell *cell)  	mutex_lock(&nvmem_mutex);  	list_del(&cell->node);  	mutex_unlock(&nvmem_mutex); +	of_node_put(cell->np);  	kfree(cell->name);  	kfree(cell);  } @@ -530,6 +532,7 @@ static int nvmem_add_cells_from_of(struct nvmem_device *nvmem)  			return -ENOMEM;  		cell->nvmem = nvmem; +		cell->np = of_node_get(child);  		cell->offset = be32_to_cpup(addr++);  		cell->bytes = be32_to_cpup(addr);  		cell->name = kasprintf(GFP_KERNEL, "%pOFn", child); @@ -960,14 +963,13 @@ out:  #if IS_ENABLED(CONFIG_OF)  static struct nvmem_cell * -nvmem_find_cell_by_index(struct nvmem_device *nvmem, int index) +nvmem_find_cell_by_node(struct nvmem_device *nvmem, struct device_node *np)  {  	struct nvmem_cell *cell = NULL; -	int i = 0;  	mutex_lock(&nvmem_mutex);  	list_for_each_entry(cell, &nvmem->cells, node) { -		if (index == i++) +		if (np == cell->np)  			break;  	}  	mutex_unlock(&nvmem_mutex); @@ -1011,7 +1013,7 @@ struct nvmem_cell *of_nvmem_cell_get(struct device_node *np, const char *id)  	if (IS_ERR(nvmem))  		return ERR_CAST(nvmem); -	cell = nvmem_find_cell_by_index(nvmem, index); +	cell = nvmem_find_cell_by_node(nvmem, cell_np);  	if (!cell) {  		__nvmem_device_put(nvmem);  		return ERR_PTR(-ENOENT); diff --git a/drivers/opp/ti-opp-supply.c b/drivers/opp/ti-opp-supply.c index 9e5a9a3112c9..3f4fb4dbbe33 100644 --- a/drivers/opp/ti-opp-supply.c +++ b/drivers/opp/ti-opp-supply.c @@ -288,7 +288,10 @@ static int ti_opp_supply_set_opp(struct dev_pm_set_opp_data *data)  	int ret;  	vdd_uv = _get_optimal_vdd_voltage(dev, &opp_data, -					  new_supply_vbb->u_volt); +					  new_supply_vdd->u_volt); + +	if (new_supply_vdd->u_volt_min < vdd_uv) +		new_supply_vdd->u_volt_min = vdd_uv;  	/* Scaling up? Scale voltage before frequency */  	if (freq > old_freq) { diff --git a/drivers/s390/net/ism_drv.c b/drivers/s390/net/ism_drv.c index f96ec68af2e5..dcbf5c857743 100644 --- a/drivers/s390/net/ism_drv.c +++ b/drivers/s390/net/ism_drv.c @@ -415,9 +415,9 @@ static irqreturn_t ism_handle_irq(int irq, void *data)  			break;  		clear_bit_inv(bit, bv); +		ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0;  		barrier();  		smcd_handle_irq(ism->smcd, bit + ISM_DMB_BIT_OFFSET); -		ism->sba->dmbe_mask[bit + ISM_DMB_BIT_OFFSET] = 0;  	}  	if (ism->sba->e) { diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 20c85eed1a75..b658b9a5eb1e 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1749,7 +1749,7 @@ qla2x00_loop_reset(scsi_qla_host_t *vha)  static void  __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)  { -	int cnt; +	int cnt, status;  	unsigned long flags;  	srb_t *sp;  	scsi_qla_host_t *vha = qp->vha; @@ -1799,10 +1799,16 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)  					if (!sp_get(sp)) {  						spin_unlock_irqrestore  							(qp->qp_lock_ptr, flags); -						qla2xxx_eh_abort( +						status = qla2xxx_eh_abort(  							GET_CMD_SP(sp));  						spin_lock_irqsave  							(qp->qp_lock_ptr, flags); +						/* +						 * Get rid of extra reference caused +						 * by early exit from qla2xxx_eh_abort +						 */ +						if (status == FAST_IO_FAIL) +							atomic_dec(&sp->ref_count);  					}  				}  				sp->done(sp, res); diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c index 46df707e6f2c..452e19f8fb47 100644 --- a/drivers/scsi/ufs/ufs-hisi.c +++ b/drivers/scsi/ufs/ufs-hisi.c @@ -20,6 +20,7 @@  #include "unipro.h"  #include "ufs-hisi.h"  #include "ufshci.h" +#include "ufs_quirks.h"  static int ufs_hisi_check_hibern8(struct ufs_hba *hba)  { @@ -390,6 +391,14 @@ static void ufs_hisi_set_dev_cap(struct ufs_hisi_dev_params *hisi_param)  static void ufs_hisi_pwr_change_pre_change(struct ufs_hba *hba)  { +	if (hba->dev_quirks & UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME) { +		pr_info("ufs flash device must set VS_DebugSaveConfigTime 0x10\n"); +		/* VS_DebugSaveConfigTime */ +		ufshcd_dme_set(hba, UIC_ARG_MIB(0xD0A0), 0x10); +		/* sync length */ +		ufshcd_dme_set(hba, UIC_ARG_MIB(0x1556), 0x48); +	} +  	/* update */  	ufshcd_dme_set(hba, UIC_ARG_MIB(0x15A8), 0x1);  	/* PA_TxSkip */ diff --git a/drivers/scsi/ufs/ufs_quirks.h b/drivers/scsi/ufs/ufs_quirks.h index 71f73d1d1ad1..5d2dfdb41a6f 100644 --- a/drivers/scsi/ufs/ufs_quirks.h +++ b/drivers/scsi/ufs/ufs_quirks.h @@ -131,4 +131,10 @@ struct ufs_dev_fix {   */  #define UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME	(1 << 8) +/* + * Some UFS devices require VS_DebugSaveConfigTime is 0x10, + * enabling this quirk ensure this. + */ +#define UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME	(1 << 9) +  #endif /* UFS_QUIRKS_H_ */ diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 27db55b0ca7f..f1c57cd33b5b 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -231,6 +231,8 @@ static struct ufs_dev_fix ufs_fixups[] = {  	UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL, UFS_DEVICE_NO_VCCQ),  	UFS_FIX(UFS_VENDOR_SKHYNIX, UFS_ANY_MODEL,  		UFS_DEVICE_QUIRK_HOST_PA_SAVECONFIGTIME), +	UFS_FIX(UFS_VENDOR_SKHYNIX, "hB8aL1" /*H28U62301AMR*/, +		UFS_DEVICE_QUIRK_HOST_VS_DEBUGSAVECONFIGTIME),  	END_FIX  }; diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c index 7218fb963d0a..1382a8df6c75 100644 --- a/drivers/slimbus/qcom-ngd-ctrl.c +++ b/drivers/slimbus/qcom-ngd-ctrl.c @@ -777,9 +777,6 @@ static int qcom_slim_ngd_xfer_msg(struct slim_controller *sctrl,  	u8 la = txn->la;  	bool usr_msg = false; -	if (txn->mc & SLIM_MSG_CLK_PAUSE_SEQ_FLG) -		return -EPROTONOSUPPORT; -  	if (txn->mt == SLIM_MSG_MT_CORE &&  		(txn->mc >= SLIM_MSG_MC_BEGIN_RECONFIGURATION &&  		 txn->mc <= SLIM_MSG_MC_RECONFIGURE_NOW)) diff --git a/drivers/slimbus/slimbus.h b/drivers/slimbus/slimbus.h index 4399d1873e2d..9be41089edde 100644 --- a/drivers/slimbus/slimbus.h +++ b/drivers/slimbus/slimbus.h @@ -61,12 +61,6 @@  #define SLIM_MSG_MC_NEXT_REMOVE_CHANNEL          0x58  #define SLIM_MSG_MC_RECONFIGURE_NOW              0x5F -/* - * Clock pause flag to indicate that the reconfig message - * corresponds to clock pause sequence - */ -#define SLIM_MSG_CLK_PAUSE_SEQ_FLG		(1U << 8) -  /* Clock pause values per SLIMbus spec */  #define SLIM_CLK_FAST				0  #define SLIM_CLK_CONST_PHASE			1 diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c index a53231b08d30..e3425bf082ae 100644 --- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c +++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c @@ -310,6 +310,7 @@ static int ipipeif_hw_setup(struct v4l2_subdev *sd)  			ipipeif_write(val, ipipeif_base_addr, IPIPEIF_CFG2);  			break;  		} +		/* fall through */  	case IPIPEIF_SDRAM_YUV:  		/* Set clock divider */ diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index 82558455384a..dd121f66fa2d 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -253,7 +253,7 @@ static const struct v4l2_m2m_ops cedrus_m2m_ops = {  static const struct media_device_ops cedrus_m2m_media_ops = {  	.req_validate	= cedrus_request_validate, -	.req_queue	= vb2_m2m_request_queue, +	.req_queue	= v4l2_m2m_request_queue,  };  static int cedrus_probe(struct platform_device *pdev) diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 85644669fbe7..0a357db4b31b 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -961,6 +961,8 @@ int __uio_register_device(struct module *owner,  	if (ret)  		goto err_uio_dev_add_attributes; +	info->uio_dev = idev; +  	if (info->irq && (info->irq != UIO_IRQ_CUSTOM)) {  		/*  		 * Note that we deliberately don't use devm_request_irq @@ -972,11 +974,12 @@ int __uio_register_device(struct module *owner,  		 */  		ret = request_irq(info->irq, uio_interrupt,  				  info->irq_flags, info->name, idev); -		if (ret) +		if (ret) { +			info->uio_dev = NULL;  			goto err_request_irq; +		}  	} -	info->uio_dev = idev;  	return 0;  err_request_irq: diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 47d75c20c211..1b68fed464cb 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1696,6 +1696,9 @@ static const struct usb_device_id acm_ids[] = {  	{ USB_DEVICE(0x0572, 0x1328), /* Shiro / Aztech USB MODEM UM-3100 */  	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */  	}, +	{ USB_DEVICE(0x0572, 0x1349), /* Hiro (Conexant) USB MODEM H50228 */ +	.driver_info = NO_UNION_NORMAL, /* has no union descriptor */ +	},  	{ USB_DEVICE(0x20df, 0x0001), /* Simtec Electronics Entropy Key */  	.driver_info = QUIRK_CONTROL_LINE_STATE, },  	{ USB_DEVICE(0x2184, 0x001c) },	/* GW Instek AFG-2225 */ diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c6077d582d29..0f9381b69a3b 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2794,6 +2794,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  	int i, status;  	u16 portchange, portstatus;  	struct usb_port *port_dev = hub->ports[port1 - 1]; +	int reset_recovery_time;  	if (!hub_is_superspeed(hub->hdev)) {  		if (warm) { @@ -2849,7 +2850,9 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  					USB_PORT_FEAT_C_BH_PORT_RESET);  			usb_clear_port_feature(hub->hdev, port1,  					USB_PORT_FEAT_C_PORT_LINK_STATE); -			usb_clear_port_feature(hub->hdev, port1, + +			if (udev) +				usb_clear_port_feature(hub->hdev, port1,  					USB_PORT_FEAT_C_CONNECTION);  			/* @@ -2885,11 +2888,18 @@ static int hub_port_reset(struct usb_hub *hub, int port1,  done:  	if (status == 0) { -		/* TRSTRCY = 10 ms; plus some extra */  		if (port_dev->quirks & USB_PORT_QUIRK_FAST_ENUM)  			usleep_range(10000, 12000); -		else -			msleep(10 + 40); +		else { +			/* TRSTRCY = 10 ms; plus some extra */ +			reset_recovery_time = 10 + 40; + +			/* Hub needs extra delay after resetting its port. */ +			if (hub->hdev->quirks & USB_QUIRK_HUB_SLOW_RESET) +				reset_recovery_time += 100; + +			msleep(reset_recovery_time); +		}  		if (udev) {  			struct usb_hcd *hcd = bus_to_hcd(udev->bus); diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 178d6c6063c0..f9ff03e6af93 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -128,6 +128,9 @@ static int quirks_param_set(const char *val, const struct kernel_param *kp)  			case 'n':  				flags |= USB_QUIRK_DELAY_CTRL_MSG;  				break; +			case 'o': +				flags |= USB_QUIRK_HUB_SLOW_RESET; +				break;  			/* Ignore unrecognized flag characters */  			}  		} @@ -380,6 +383,9 @@ static const struct usb_device_id usb_quirk_list[] = {  	{ USB_DEVICE(0x1a0a, 0x0200), .driver_info =  			USB_QUIRK_LINEAR_UFRAME_INTR_BINTERVAL }, +	/* Terminus Technology Inc. Hub */ +	{ USB_DEVICE(0x1a40, 0x0101), .driver_info = USB_QUIRK_HUB_SLOW_RESET }, +  	/* Corsair K70 RGB */  	{ USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT }, @@ -391,6 +397,9 @@ static const struct usb_device_id usb_quirk_list[] = {  	{ USB_DEVICE(0x1b1c, 0x1b20), .driver_info = USB_QUIRK_DELAY_INIT |  	  USB_QUIRK_DELAY_CTRL_MSG }, +	/* Corsair K70 LUX RGB */ +	{ USB_DEVICE(0x1b1c, 0x1b33), .driver_info = USB_QUIRK_DELAY_INIT }, +  	/* Corsair K70 LUX */  	{ USB_DEVICE(0x1b1c, 0x1b36), .driver_info = USB_QUIRK_DELAY_INIT }, @@ -411,6 +420,11 @@ static const struct usb_device_id usb_quirk_list[] = {  	{ USB_DEVICE(0x2040, 0x7200), .driver_info =  			USB_QUIRK_CONFIG_INTF_STRINGS }, +	/* Raydium Touchscreen */ +	{ USB_DEVICE(0x2386, 0x3114), .driver_info = USB_QUIRK_NO_LPM }, + +	{ USB_DEVICE(0x2386, 0x3119), .driver_info = USB_QUIRK_NO_LPM }, +  	/* DJI CineSSD */  	{ USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, diff --git a/drivers/usb/dwc2/pci.c b/drivers/usb/dwc2/pci.c index d257c541e51b..7afc10872f1f 100644 --- a/drivers/usb/dwc2/pci.c +++ b/drivers/usb/dwc2/pci.c @@ -120,6 +120,7 @@ static int dwc2_pci_probe(struct pci_dev *pci,  	dwc2 = platform_device_alloc("dwc2", PLATFORM_DEVID_AUTO);  	if (!dwc2) {  		dev_err(dev, "couldn't allocate dwc2 device\n"); +		ret = -ENOMEM;  		goto err;  	} diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index becfbb87f791..2f2048aa5fde 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -1499,6 +1499,7 @@ static int dwc3_probe(struct platform_device *pdev)  err5:  	dwc3_event_buffers_cleanup(dwc); +	dwc3_ulpi_exit(dwc);  err4:  	dwc3_free_scratch_buffers(dwc); diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 1286076a8890..842795856bf4 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -283,8 +283,10 @@ err:  static void dwc3_pci_remove(struct pci_dev *pci)  {  	struct dwc3_pci		*dwc = pci_get_drvdata(pci); +	struct pci_dev		*pdev = dwc->pci; -	gpiod_remove_lookup_table(&platform_bytcr_gpios); +	if (pdev->device == PCI_DEVICE_ID_INTEL_BYT) +		gpiod_remove_lookup_table(&platform_bytcr_gpios);  #ifdef CONFIG_PM  	cancel_work_sync(&dwc->wakeup_work);  #endif diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 679c12e14522..9faad896b3a1 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1081,7 +1081,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,  			/* Now prepare one extra TRB to align transfer size */  			trb = &dep->trb_pool[dep->trb_enqueue];  			__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, -					maxp - rem, false, 0, +					maxp - rem, false, 1,  					req->request.stream_id,  					req->request.short_not_ok,  					req->request.no_interrupt); @@ -1125,7 +1125,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,  		/* Now prepare one extra TRB to align transfer size */  		trb = &dep->trb_pool[dep->trb_enqueue];  		__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem, -				false, 0, req->request.stream_id, +				false, 1, req->request.stream_id,  				req->request.short_not_ok,  				req->request.no_interrupt);  	} else if (req->request.zero && req->request.length && @@ -1141,7 +1141,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,  		/* Now prepare one extra TRB to handle ZLP */  		trb = &dep->trb_pool[dep->trb_enqueue];  		__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0, -				false, 0, req->request.stream_id, +				false, 1, req->request.stream_id,  				req->request.short_not_ok,  				req->request.no_interrupt);  	} else { @@ -2259,7 +2259,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct dwc3_ep *dep,  	 * with one TRB pending in the ring. We need to manually clear HWO bit  	 * from that TRB.  	 */ -	if ((req->zero || req->unaligned) && (trb->ctrl & DWC3_TRB_CTRL_HWO)) { +	if ((req->zero || req->unaligned) && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) {  		trb->ctrl &= ~DWC3_TRB_CTRL_HWO;  		return 1;  	} diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c index 3ada83d81bda..31e8bf3578c8 100644 --- a/drivers/usb/gadget/function/f_fs.c +++ b/drivers/usb/gadget/function/f_fs.c @@ -215,7 +215,6 @@ struct ffs_io_data {  	struct mm_struct *mm;  	struct work_struct work; -	struct work_struct cancellation_work;  	struct usb_ep *ep;  	struct usb_request *req; @@ -1073,31 +1072,22 @@ ffs_epfile_open(struct inode *inode, struct file *file)  	return 0;  } -static void ffs_aio_cancel_worker(struct work_struct *work) -{ -	struct ffs_io_data *io_data = container_of(work, struct ffs_io_data, -						   cancellation_work); - -	ENTER(); - -	usb_ep_dequeue(io_data->ep, io_data->req); -} -  static int ffs_aio_cancel(struct kiocb *kiocb)  {  	struct ffs_io_data *io_data = kiocb->private; -	struct ffs_data *ffs = io_data->ffs; +	struct ffs_epfile *epfile = kiocb->ki_filp->private_data;  	int value;  	ENTER(); -	if (likely(io_data && io_data->ep && io_data->req)) { -		INIT_WORK(&io_data->cancellation_work, ffs_aio_cancel_worker); -		queue_work(ffs->io_completion_wq, &io_data->cancellation_work); -		value = -EINPROGRESS; -	} else { +	spin_lock_irq(&epfile->ffs->eps_lock); + +	if (likely(io_data && io_data->ep && io_data->req)) +		value = usb_ep_dequeue(io_data->ep, io_data->req); +	else  		value = -EINVAL; -	} + +	spin_unlock_irq(&epfile->ffs->eps_lock);  	return value;  } diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c index 27f00160332e..3c4abb5a1c3f 100644 --- a/drivers/usb/host/xhci-histb.c +++ b/drivers/usb/host/xhci-histb.c @@ -325,14 +325,16 @@ static int xhci_histb_remove(struct platform_device *dev)  	struct xhci_hcd_histb *histb = platform_get_drvdata(dev);  	struct usb_hcd *hcd = histb->hcd;  	struct xhci_hcd	*xhci = hcd_to_xhci(hcd); +	struct usb_hcd *shared_hcd = xhci->shared_hcd;  	xhci->xhc_state |= XHCI_STATE_REMOVING; -	usb_remove_hcd(xhci->shared_hcd); +	usb_remove_hcd(shared_hcd); +	xhci->shared_hcd = NULL;  	device_wakeup_disable(&dev->dev);  	usb_remove_hcd(hcd); -	usb_put_hcd(xhci->shared_hcd); +	usb_put_hcd(shared_hcd);  	xhci_histb_host_disable(histb);  	usb_put_hcd(hcd); diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 12eea73d9f20..94aca1b5ac8a 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -876,7 +876,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,  			status |= USB_PORT_STAT_SUSPEND;  	}  	if ((raw_port_status & PORT_PLS_MASK) == XDEV_RESUME && -		!DEV_SUPERSPEED_ANY(raw_port_status)) { +		!DEV_SUPERSPEED_ANY(raw_port_status) && hcd->speed < HCD_USB3) {  		if ((raw_port_status & PORT_RESET) ||  				!(raw_port_status & PORT_PE))  			return 0xffffffff; @@ -921,7 +921,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,  			time_left = wait_for_completion_timeout(  					&bus_state->rexit_done[wIndex],  					msecs_to_jiffies( -						XHCI_MAX_REXIT_TIMEOUT)); +						XHCI_MAX_REXIT_TIMEOUT_MS));  			spin_lock_irqsave(&xhci->lock, flags);  			if (time_left) { @@ -935,7 +935,7 @@ static u32 xhci_get_port_status(struct usb_hcd *hcd,  			} else {  				int port_status = readl(port->addr);  				xhci_warn(xhci, "Port resume took longer than %i msec, port status = 0x%x\n", -						XHCI_MAX_REXIT_TIMEOUT, +						XHCI_MAX_REXIT_TIMEOUT_MS,  						port_status);  				status |= USB_PORT_STAT_SUSPEND;  				clear_bit(wIndex, &bus_state->rexit_ports); @@ -1474,15 +1474,18 @@ int xhci_bus_suspend(struct usb_hcd *hcd)  	unsigned long flags;  	struct xhci_hub *rhub;  	struct xhci_port **ports; +	u32 portsc_buf[USB_MAXCHILDREN]; +	bool wake_enabled;  	rhub = xhci_get_rhub(hcd);  	ports = rhub->ports;  	max_ports = rhub->num_ports;  	bus_state = &xhci->bus_state[hcd_index(hcd)]; +	wake_enabled = hcd->self.root_hub->do_remote_wakeup;  	spin_lock_irqsave(&xhci->lock, flags); -	if (hcd->self.root_hub->do_remote_wakeup) { +	if (wake_enabled) {  		if (bus_state->resuming_ports ||	/* USB2 */  		    bus_state->port_remote_wakeup) {	/* USB3 */  			spin_unlock_irqrestore(&xhci->lock, flags); @@ -1490,26 +1493,36 @@ int xhci_bus_suspend(struct usb_hcd *hcd)  			return -EBUSY;  		}  	} - -	port_index = max_ports; +	/* +	 * Prepare ports for suspend, but don't write anything before all ports +	 * are checked and we know bus suspend can proceed +	 */  	bus_state->bus_suspended = 0; +	port_index = max_ports;  	while (port_index--) { -		/* suspend the port if the port is not suspended */  		u32 t1, t2; -		int slot_id;  		t1 = readl(ports[port_index]->addr);  		t2 = xhci_port_state_to_neutral(t1); +		portsc_buf[port_index] = 0; -		if ((t1 & PORT_PE) && !(t1 & PORT_PLS_MASK)) { -			xhci_dbg(xhci, "port %d not suspended\n", port_index); -			slot_id = xhci_find_slot_id_by_port(hcd, xhci, -					port_index + 1); -			if (slot_id) { +		/* Bail out if a USB3 port has a new device in link training */ +		if ((t1 & PORT_PLS_MASK) == XDEV_POLLING) { +			bus_state->bus_suspended = 0; +			spin_unlock_irqrestore(&xhci->lock, flags); +			xhci_dbg(xhci, "Bus suspend bailout, port in polling\n"); +			return -EBUSY; +		} + +		/* suspend ports in U0, or bail out for new connect changes */ +		if ((t1 & PORT_PE) && (t1 & PORT_PLS_MASK) == XDEV_U0) { +			if ((t1 & PORT_CSC) && wake_enabled) { +				bus_state->bus_suspended = 0;  				spin_unlock_irqrestore(&xhci->lock, flags); -				xhci_stop_device(xhci, slot_id, 1); -				spin_lock_irqsave(&xhci->lock, flags); +				xhci_dbg(xhci, "Bus suspend bailout, port connect change\n"); +				return -EBUSY;  			} +			xhci_dbg(xhci, "port %d not suspended\n", port_index);  			t2 &= ~PORT_PLS_MASK;  			t2 |= PORT_LINK_STROBE | XDEV_U3;  			set_bit(port_index, &bus_state->bus_suspended); @@ -1518,7 +1531,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)  		 * including the USB 3.0 roothub, but only if CONFIG_PM  		 * is enabled, so also enable remote wake here.  		 */ -		if (hcd->self.root_hub->do_remote_wakeup) { +		if (wake_enabled) {  			if (t1 & PORT_CONNECT) {  				t2 |= PORT_WKOC_E | PORT_WKDISC_E;  				t2 &= ~PORT_WKCONN_E; @@ -1538,7 +1551,26 @@ int xhci_bus_suspend(struct usb_hcd *hcd)  		t1 = xhci_port_state_to_neutral(t1);  		if (t1 != t2) -			writel(t2, ports[port_index]->addr); +			portsc_buf[port_index] = t2; +	} + +	/* write port settings, stopping and suspending ports if needed */ +	port_index = max_ports; +	while (port_index--) { +		if (!portsc_buf[port_index]) +			continue; +		if (test_bit(port_index, &bus_state->bus_suspended)) { +			int slot_id; + +			slot_id = xhci_find_slot_id_by_port(hcd, xhci, +							    port_index + 1); +			if (slot_id) { +				spin_unlock_irqrestore(&xhci->lock, flags); +				xhci_stop_device(xhci, slot_id, 1); +				spin_lock_irqsave(&xhci->lock, flags); +			} +		} +		writel(portsc_buf[port_index], ports[port_index]->addr);  	}  	hcd->state = HC_STATE_SUSPENDED;  	bus_state->next_statechange = jiffies + msecs_to_jiffies(10); diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index 71d0d33c3286..60987c787e44 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -590,12 +590,14 @@ static int xhci_mtk_remove(struct platform_device *dev)  	struct xhci_hcd_mtk *mtk = platform_get_drvdata(dev);  	struct usb_hcd	*hcd = mtk->hcd;  	struct xhci_hcd	*xhci = hcd_to_xhci(hcd); +	struct usb_hcd  *shared_hcd = xhci->shared_hcd; -	usb_remove_hcd(xhci->shared_hcd); +	usb_remove_hcd(shared_hcd); +	xhci->shared_hcd = NULL;  	device_init_wakeup(&dev->dev, false);  	usb_remove_hcd(hcd); -	usb_put_hcd(xhci->shared_hcd); +	usb_put_hcd(shared_hcd);  	usb_put_hcd(hcd);  	xhci_mtk_sch_exit(mtk);  	xhci_mtk_clks_disable(mtk); diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 01c57055c0c5..a9515265db4d 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -248,6 +248,11 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)  	if (pdev->vendor == PCI_VENDOR_ID_TI && pdev->device == 0x8241)  		xhci->quirks |= XHCI_LIMIT_ENDPOINT_INTERVAL_7; +	if ((pdev->vendor == PCI_VENDOR_ID_BROADCOM || +	     pdev->vendor == PCI_VENDOR_ID_CAVIUM) && +	     pdev->device == 0x9026) +		xhci->quirks |= XHCI_RESET_PLL_ON_DISCONNECT; +  	if (xhci->quirks & XHCI_RESET_ON_RESUME)  		xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,  				"QUIRK: Resetting on resume"); @@ -380,6 +385,7 @@ static void xhci_pci_remove(struct pci_dev *dev)  	if (xhci->shared_hcd) {  		usb_remove_hcd(xhci->shared_hcd);  		usb_put_hcd(xhci->shared_hcd); +		xhci->shared_hcd = NULL;  	}  	/* Workaround for spurious wakeups at shutdown with HSW */ diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c index 32b5574ad5c5..ef09cb06212f 100644 --- a/drivers/usb/host/xhci-plat.c +++ b/drivers/usb/host/xhci-plat.c @@ -362,14 +362,16 @@ static int xhci_plat_remove(struct platform_device *dev)  	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);  	struct clk *clk = xhci->clk;  	struct clk *reg_clk = xhci->reg_clk; +	struct usb_hcd *shared_hcd = xhci->shared_hcd;  	xhci->xhc_state |= XHCI_STATE_REMOVING; -	usb_remove_hcd(xhci->shared_hcd); +	usb_remove_hcd(shared_hcd); +	xhci->shared_hcd = NULL;  	usb_phy_shutdown(hcd->usb_phy);  	usb_remove_hcd(hcd); -	usb_put_hcd(xhci->shared_hcd); +	usb_put_hcd(shared_hcd);  	clk_disable_unprepare(clk);  	clk_disable_unprepare(reg_clk); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index a8d92c90fb58..65750582133f 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1521,6 +1521,35 @@ static void handle_device_notification(struct xhci_hcd *xhci,  		usb_wakeup_notification(udev->parent, udev->portnum);  } +/* + * Quirk hanlder for errata seen on Cavium ThunderX2 processor XHCI + * Controller. + * As per ThunderX2errata-129 USB 2 device may come up as USB 1 + * If a connection to a USB 1 device is followed by another connection + * to a USB 2 device. + * + * Reset the PHY after the USB device is disconnected if device speed + * is less than HCD_USB3. + * Retry the reset sequence max of 4 times checking the PLL lock status. + * + */ +static void xhci_cavium_reset_phy_quirk(struct xhci_hcd *xhci) +{ +	struct usb_hcd *hcd = xhci_to_hcd(xhci); +	u32 pll_lock_check; +	u32 retry_count = 4; + +	do { +		/* Assert PHY reset */ +		writel(0x6F, hcd->regs + 0x1048); +		udelay(10); +		/* De-assert the PHY reset */ +		writel(0x7F, hcd->regs + 0x1048); +		udelay(200); +		pll_lock_check = readl(hcd->regs + 0x1070); +	} while (!(pll_lock_check & 0x1) && --retry_count); +} +  static void handle_port_status(struct xhci_hcd *xhci,  		union xhci_trb *event)  { @@ -1556,6 +1585,13 @@ static void handle_port_status(struct xhci_hcd *xhci,  		goto cleanup;  	} +	/* We might get interrupts after shared_hcd is removed */ +	if (port->rhub == &xhci->usb3_rhub && xhci->shared_hcd == NULL) { +		xhci_dbg(xhci, "ignore port event for removed USB3 hcd\n"); +		bogus_port_status = true; +		goto cleanup; +	} +  	hcd = port->rhub->hcd;  	bus_state = &xhci->bus_state[hcd_index(hcd)];  	hcd_portnum = port->hcd_portnum; @@ -1639,7 +1675,7 @@ static void handle_port_status(struct xhci_hcd *xhci,  	 * RExit to a disconnect state).  If so, let the the driver know it's  	 * out of the RExit state.  	 */ -	if (!DEV_SUPERSPEED_ANY(portsc) && +	if (!DEV_SUPERSPEED_ANY(portsc) && hcd->speed < HCD_USB3 &&  			test_and_clear_bit(hcd_portnum,  				&bus_state->rexit_ports)) {  		complete(&bus_state->rexit_done[hcd_portnum]); @@ -1647,8 +1683,12 @@ static void handle_port_status(struct xhci_hcd *xhci,  		goto cleanup;  	} -	if (hcd->speed < HCD_USB3) +	if (hcd->speed < HCD_USB3) {  		xhci_test_and_clear_bit(xhci, port, PORT_PLC); +		if ((xhci->quirks & XHCI_RESET_PLL_ON_DISCONNECT) && +		    (portsc & PORT_CSC) && !(portsc & PORT_CONNECT)) +			xhci_cavium_reset_phy_quirk(xhci); +	}  cleanup:  	/* Update event ring dequeue pointer before dropping the lock */ @@ -2266,6 +2306,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,  			goto cleanup;  		case COMP_RING_UNDERRUN:  		case COMP_RING_OVERRUN: +		case COMP_STOPPED_LENGTH_INVALID:  			goto cleanup;  		default:  			xhci_err(xhci, "ERROR Transfer event for unknown stream ring slot %u ep %u\n", diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c index 6b5db344de30..938ff06c0349 100644 --- a/drivers/usb/host/xhci-tegra.c +++ b/drivers/usb/host/xhci-tegra.c @@ -1303,6 +1303,7 @@ static int tegra_xusb_remove(struct platform_device *pdev)  	usb_remove_hcd(xhci->shared_hcd);  	usb_put_hcd(xhci->shared_hcd); +	xhci->shared_hcd = NULL;  	usb_remove_hcd(tegra->hcd);  	usb_put_hcd(tegra->hcd); diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 0420eefa647a..c928dbbff881 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -719,8 +719,6 @@ static void xhci_stop(struct usb_hcd *hcd)  	/* Only halt host and free memory after both hcds are removed */  	if (!usb_hcd_is_primary_hcd(hcd)) { -		/* usb core will free this hcd shortly, unset pointer */ -		xhci->shared_hcd = NULL;  		mutex_unlock(&xhci->mutex);  		return;  	} diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index bf0b3692dc9a..260b259b72bc 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1680,7 +1680,7 @@ struct xhci_bus_state {   * It can take up to 20 ms to transition from RExit to U0 on the   * Intel Lynx Point LP xHCI host.   */ -#define	XHCI_MAX_REXIT_TIMEOUT	(20 * 1000) +#define	XHCI_MAX_REXIT_TIMEOUT_MS	20  static inline unsigned int hcd_index(struct usb_hcd *hcd)  { @@ -1849,6 +1849,7 @@ struct xhci_hcd {  #define XHCI_INTEL_USB_ROLE_SW	BIT_ULL(31)  #define XHCI_ZERO_64B_REGS	BIT_ULL(32)  #define XHCI_DEFAULT_PM_RUNTIME_ALLOW	BIT_ULL(33) +#define XHCI_RESET_PLL_ON_DISCONNECT	BIT_ULL(34)  	unsigned int		num_active_eps;  	unsigned int		limit_active_eps; diff --git a/drivers/usb/misc/appledisplay.c b/drivers/usb/misc/appledisplay.c index bd539f3058bc..85b48c6ddc7e 100644 --- a/drivers/usb/misc/appledisplay.c +++ b/drivers/usb/misc/appledisplay.c @@ -50,6 +50,7 @@ static const struct usb_device_id appledisplay_table[] = {  	{ APPLEDISPLAY_DEVICE(0x9219) },  	{ APPLEDISPLAY_DEVICE(0x921c) },  	{ APPLEDISPLAY_DEVICE(0x921d) }, +	{ APPLEDISPLAY_DEVICE(0x9222) },  	{ APPLEDISPLAY_DEVICE(0x9236) },  	/* Terminating entry */ | 
