diff options
Diffstat (limited to 'drivers')
453 files changed, 4634 insertions, 2788 deletions
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig index 8f3a444c6ea9..7cea769c37df 100644 --- a/drivers/acpi/Kconfig +++ b/drivers/acpi/Kconfig @@ -512,7 +512,7 @@ config CRC_PMIC_OPREGION  config XPOWER_PMIC_OPREGION  	bool "ACPI operation region support for XPower AXP288 PMIC" -	depends on MFD_AXP20X_I2C && IOSF_MBI +	depends on MFD_AXP20X_I2C && IOSF_MBI=y  	help  	  This config adds ACPI operation region support for XPower AXP288 PMIC. 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/acpi/acpica/exserial.c b/drivers/acpi/acpica/exserial.c index 0d42f30e5b25..9920fac6413f 100644 --- a/drivers/acpi/acpica/exserial.c +++ b/drivers/acpi/acpica/exserial.c @@ -244,7 +244,6 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,  {  	acpi_status status;  	u32 buffer_length; -	u32 data_length;  	void *buffer;  	union acpi_operand_object *buffer_desc;  	u32 function; @@ -282,14 +281,12 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,  	case ACPI_ADR_SPACE_SMBUS:  		buffer_length = ACPI_SMBUS_BUFFER_SIZE; -		data_length = ACPI_SMBUS_DATA_SIZE;  		function = ACPI_WRITE | (obj_desc->field.attribute << 16);  		break;  	case ACPI_ADR_SPACE_IPMI:  		buffer_length = ACPI_IPMI_BUFFER_SIZE; -		data_length = ACPI_IPMI_DATA_SIZE;  		function = ACPI_WRITE;  		break; @@ -310,7 +307,6 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,  		/* Add header length to get the full size of the buffer */  		buffer_length += ACPI_SERIAL_HEADER_SIZE; -		data_length = source_desc->buffer.pointer[1];  		function = ACPI_WRITE | (accessor_type << 16);  		break; @@ -318,20 +314,6 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,  		return_ACPI_STATUS(AE_AML_INVALID_SPACE_ID);  	} -#if 0 -	OBSOLETE ? -	    /* Check for possible buffer overflow */ -	    if (data_length > source_desc->buffer.length) { -		ACPI_ERROR((AE_INFO, -			    "Length in buffer header (%u)(%u) is greater than " -			    "the physical buffer length (%u) and will overflow", -			    data_length, buffer_length, -			    source_desc->buffer.length)); - -		return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); -	} -#endif -  	/* Create the transfer/bidirectional/return buffer */  	buffer_desc = acpi_ut_create_buffer_object(buffer_length); @@ -342,7 +324,8 @@ acpi_ex_write_serial_bus(union acpi_operand_object *source_desc,  	/* Copy the input buffer data to the transfer buffer */  	buffer = buffer_desc->buffer.pointer; -	memcpy(buffer, source_desc->buffer.pointer, data_length); +	memcpy(buffer, source_desc->buffer.pointer, +	       min(buffer_length, source_desc->buffer.length));  	/* Lock entire transaction if requested */ diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c index 2a361e22d38d..70f4e80b9246 100644 --- a/drivers/acpi/arm64/iort.c +++ b/drivers/acpi/arm64/iort.c @@ -700,7 +700,7 @@ static void iort_set_device_domain(struct device *dev,   */  static struct irq_domain *iort_get_platform_device_domain(struct device *dev)  { -	struct acpi_iort_node *node, *msi_parent; +	struct acpi_iort_node *node, *msi_parent = NULL;  	struct fwnode_handle *iort_fwnode;  	struct acpi_iort_its_group *its;  	int i; diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index f8c638f3c946..14d9f5bea015 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -2928,9 +2928,9 @@ static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc)  		return rc;  	if (ars_status_process_records(acpi_desc)) -		return -ENOMEM; +		dev_err(acpi_desc->dev, "Failed to process ARS records\n"); -	return 0; +	return rc;  }  static int ars_register(struct acpi_nfit_desc *acpi_desc, @@ -3341,8 +3341,6 @@ static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,  		struct nvdimm *nvdimm, unsigned int cmd)  {  	struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc); -	struct nfit_spa *nfit_spa; -	int rc = 0;  	if (nvdimm)  		return 0; @@ -3355,17 +3353,10 @@ static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,  	 * just needs guarantees that any ARS it initiates are not  	 * interrupted by any intervening start requests from userspace.  	 */ -	mutex_lock(&acpi_desc->init_mutex); -	list_for_each_entry(nfit_spa, &acpi_desc->spas, list) -		if (acpi_desc->scrub_spa -				|| test_bit(ARS_REQ_SHORT, &nfit_spa->ars_state) -				|| test_bit(ARS_REQ_LONG, &nfit_spa->ars_state)) { -			rc = -EBUSY; -			break; -		} -	mutex_unlock(&acpi_desc->init_mutex); +	if (work_busy(&acpi_desc->dwork.work)) +		return -EBUSY; -	return rc; +	return 0;  }  int acpi_nfit_ars_rescan(struct acpi_nfit_desc *acpi_desc, diff --git a/drivers/acpi/nfit/mce.c b/drivers/acpi/nfit/mce.c index e9626bf6ca29..d6c1b10f6c25 100644 --- a/drivers/acpi/nfit/mce.c +++ b/drivers/acpi/nfit/mce.c @@ -25,8 +25,12 @@ static int nfit_handle_mce(struct notifier_block *nb, unsigned long val,  	struct acpi_nfit_desc *acpi_desc;  	struct nfit_spa *nfit_spa; -	/* We only care about memory errors */ -	if (!mce_is_memory_error(mce)) +	/* We only care about uncorrectable memory errors */ +	if (!mce_is_memory_error(mce) || mce_is_correctable(mce)) +		return NOTIFY_DONE; + +	/* Verify the address reported in the MCE is valid. */ +	if (!mce_usable_address(mce))  		return NOTIFY_DONE;  	/* diff --git a/drivers/android/binder.c b/drivers/android/binder.c index cb30a524d16d..9f1000d2a40c 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -2974,7 +2974,6 @@ static void binder_transaction(struct binder_proc *proc,  		t->buffer = NULL;  		goto err_binder_alloc_buf_failed;  	} -	t->buffer->allow_user_free = 0;  	t->buffer->debug_id = t->debug_id;  	t->buffer->transaction = t;  	t->buffer->target_node = target_node; @@ -3510,14 +3509,18 @@ static int binder_thread_write(struct binder_proc *proc,  			buffer = binder_alloc_prepare_to_free(&proc->alloc,  							      data_ptr); -			if (buffer == NULL) { -				binder_user_error("%d:%d BC_FREE_BUFFER u%016llx no match\n", -					proc->pid, thread->pid, (u64)data_ptr); -				break; -			} -			if (!buffer->allow_user_free) { -				binder_user_error("%d:%d BC_FREE_BUFFER u%016llx matched unreturned buffer\n", -					proc->pid, thread->pid, (u64)data_ptr); +			if (IS_ERR_OR_NULL(buffer)) { +				if (PTR_ERR(buffer) == -EPERM) { +					binder_user_error( +						"%d:%d BC_FREE_BUFFER u%016llx matched unreturned or currently freeing buffer\n", +						proc->pid, thread->pid, +						(u64)data_ptr); +				} else { +					binder_user_error( +						"%d:%d BC_FREE_BUFFER u%016llx no match\n", +						proc->pid, thread->pid, +						(u64)data_ptr); +				}  				break;  			}  			binder_debug(BINDER_DEBUG_FREE_BUFFER, diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c index 64fd96eada31..030c98f35cca 100644 --- a/drivers/android/binder_alloc.c +++ b/drivers/android/binder_alloc.c @@ -151,16 +151,12 @@ static struct binder_buffer *binder_alloc_prepare_to_free_locked(  		else {  			/*  			 * Guard against user threads attempting to -			 * free the buffer twice +			 * free the buffer when in use by kernel or +			 * after it's already been freed.  			 */ -			if (buffer->free_in_progress) { -				binder_alloc_debug(BINDER_DEBUG_USER_ERROR, -						   "%d:%d FREE_BUFFER u%016llx user freed buffer twice\n", -						   alloc->pid, current->pid, -						   (u64)user_ptr); -				return NULL; -			} -			buffer->free_in_progress = 1; +			if (!buffer->allow_user_free) +				return ERR_PTR(-EPERM); +			buffer->allow_user_free = 0;  			return buffer;  		}  	} @@ -500,7 +496,7 @@ static struct binder_buffer *binder_alloc_new_buf_locked(  	rb_erase(best_fit, &alloc->free_buffers);  	buffer->free = 0; -	buffer->free_in_progress = 0; +	buffer->allow_user_free = 0;  	binder_insert_allocated_buffer_locked(alloc, buffer);  	binder_alloc_debug(BINDER_DEBUG_BUFFER_ALLOC,  		     "%d: binder_alloc_buf size %zd got %pK\n", diff --git a/drivers/android/binder_alloc.h b/drivers/android/binder_alloc.h index 9ef64e563856..fb3238c74c8a 100644 --- a/drivers/android/binder_alloc.h +++ b/drivers/android/binder_alloc.h @@ -50,8 +50,7 @@ struct binder_buffer {  	unsigned free:1;  	unsigned allow_user_free:1;  	unsigned async_transaction:1; -	unsigned free_in_progress:1; -	unsigned debug_id:28; +	unsigned debug_id:29;  	struct binder_transaction *transaction; diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 6e594644cb1d..b8c3f9e6af89 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4553,7 +4553,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {  	/* These specific Samsung models/firmware-revs do not handle LPM well */  	{ "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, },  	{ "SAMSUNG SSD PM830 mSATA *",  "CXM13D1Q", ATA_HORKAGE_NOLPM, }, -	{ "SAMSUNG MZ7TD256HAFV-000L9", "DXT02L5Q", ATA_HORKAGE_NOLPM, }, +	{ "SAMSUNG MZ7TD256HAFV-000L9", NULL,       ATA_HORKAGE_NOLPM, },  	/* devices that don't properly handle queued TRIM commands */  	{ "Micron_M500IT_*",		"MU01",	ATA_HORKAGE_NO_NCQ_TRIM | @@ -4602,6 +4602,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {  	{ "SSD*INTEL*",			NULL,	ATA_HORKAGE_ZERO_AFTER_TRIM, },  	{ "Samsung*SSD*",		NULL,	ATA_HORKAGE_ZERO_AFTER_TRIM, },  	{ "SAMSUNG*SSD*",		NULL,	ATA_HORKAGE_ZERO_AFTER_TRIM, }, +	{ "SAMSUNG*MZ7KM*",		NULL,	ATA_HORKAGE_ZERO_AFTER_TRIM, },  	{ "ST[1248][0248]0[FH]*",	NULL,	ATA_HORKAGE_ZERO_AFTER_TRIM, },  	/* diff --git a/drivers/ata/sata_rcar.c b/drivers/ata/sata_rcar.c index 10ecb232245d..4b1ff5bc256a 100644 --- a/drivers/ata/sata_rcar.c +++ b/drivers/ata/sata_rcar.c @@ -1,14 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * Renesas R-Car SATA driver   *   * Author: Vladimir Barinov <source@cogentembedded.com>   * Copyright (C) 2013-2015 Cogent Embedded, Inc.   * Copyright (C) 2013-2015 Renesas Solutions Corp. - * - * This program is free software; you can redistribute  it and/or modify it - * under  the terms of  the GNU General  Public License as published by the - * Free Software Foundation;  either version 2 of the  License, or (at your - * option) any later version.   */  #include <linux/kernel.h> diff --git a/drivers/atm/firestream.c b/drivers/atm/firestream.c index 4e46dc9e41ad..11e1663bdc4d 100644 --- a/drivers/atm/firestream.c +++ b/drivers/atm/firestream.c @@ -1410,7 +1410,7 @@ static int init_q(struct fs_dev *dev, struct queue *txq, int queue,  	func_enter (); -	fs_dprintk (FS_DEBUG_INIT, "Inititing queue at %x: %d entries:\n",  +	fs_dprintk (FS_DEBUG_INIT, "Initializing queue at %x: %d entries:\n",  		    queue, nentries);  	p = aligned_kmalloc (sz, GFP_KERNEL, 0x10); @@ -1443,7 +1443,7 @@ static int init_fp(struct fs_dev *dev, struct freepool *fp, int queue,  {  	func_enter (); -	fs_dprintk (FS_DEBUG_INIT, "Inititing free pool at %x:\n", queue); +	fs_dprintk (FS_DEBUG_INIT, "Initializing free pool at %x:\n", queue);  	write_fs (dev, FP_CNF(queue), (bufsize * RBFP_RBS) | RBFP_RBSVAL | RBFP_CME);  	write_fs (dev, FP_SA(queue),  0); diff --git a/drivers/base/devres.c b/drivers/base/devres.c index 4aaf00d2098b..e038e2b3b7ea 100644 --- a/drivers/base/devres.c +++ b/drivers/base/devres.c @@ -26,8 +26,14 @@ struct devres_node {  struct devres {  	struct devres_node		node; -	/* -- 3 pointers */ -	unsigned long long		data[];	/* guarantee ull alignment */ +	/* +	 * Some archs want to perform DMA into kmalloc caches +	 * and need a guaranteed alignment larger than +	 * the alignment of a 64-bit integer. +	 * Thus we use ARCH_KMALLOC_MINALIGN here and get exactly the same +	 * buffer alignment as if it was allocated by plain kmalloc(). +	 */ +	u8 __aligned(ARCH_KMALLOC_MINALIGN) data[];  };  struct devres_group { diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index a8cfa011c284..fb23578e9a41 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4148,10 +4148,11 @@ static int __floppy_read_block_0(struct block_device *bdev, int drive)  	bio.bi_end_io = floppy_rb0_cb;  	bio_set_op_attrs(&bio, REQ_OP_READ, 0); +	init_completion(&cbdata.complete); +  	submit_bio(&bio);  	process_fd_request(); -	init_completion(&cbdata.complete);  	wait_for_completion(&cbdata.complete);  	__free_page(page); diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 56452cabce5b..0ed4b200fa58 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -1919,6 +1919,7 @@ static int negotiate_mq(struct blkfront_info *info)  			      GFP_KERNEL);  	if (!info->rinfo) {  		xenbus_dev_fatal(info->xbdev, -ENOMEM, "allocating ring_info structure"); +		info->nr_rings = 0;  		return -ENOMEM;  	} diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index ef0ca9414f37..ff83e899df71 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -210,6 +210,7 @@ static int of_fixed_factor_clk_remove(struct platform_device *pdev)  {  	struct clk *clk = platform_get_drvdata(pdev); +	of_clk_del_provider(pdev->dev.of_node);  	clk_unregister_fixed_factor(clk);  	return 0; diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index c981159b02c0..792735d7e46e 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c @@ -325,6 +325,7 @@ static struct clk_regmap axg_fclk_div2 = {  		.ops = &clk_regmap_gate_ops,  		.parent_names = (const char *[]){ "fclk_div2_div" },  		.num_parents = 1, +		.flags = CLK_IS_CRITICAL,  	},  }; @@ -349,6 +350,18 @@ static struct clk_regmap axg_fclk_div3 = {  		.ops = &clk_regmap_gate_ops,  		.parent_names = (const char *[]){ "fclk_div3_div" },  		.num_parents = 1, +		/* +		 * FIXME: +		 * This clock, as fdiv2, is used by the SCPI FW and is required +		 * by the platform to operate correctly. +		 * Until the following condition are met, we need this clock to +		 * be marked as critical: +		 * a) The SCPI generic driver claims and enable all the clocks +		 *    it needs +		 * b) CCF has a clock hand-off mechanism to make the sure the +		 *    clock stays on until the proper driver comes along +		 */ +		.flags = CLK_IS_CRITICAL,  	},  }; diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c index 9309cfaaa464..4ada9668fd49 100644 --- a/drivers/clk/meson/gxbb.c +++ b/drivers/clk/meson/gxbb.c @@ -506,6 +506,18 @@ static struct clk_regmap gxbb_fclk_div3 = {  		.ops = &clk_regmap_gate_ops,  		.parent_names = (const char *[]){ "fclk_div3_div" },  		.num_parents = 1, +		/* +		 * FIXME: +		 * This clock, as fdiv2, is used by the SCPI FW and is required +		 * by the platform to operate correctly. +		 * Until the following condition are met, we need this clock to +		 * be marked as critical: +		 * a) The SCPI generic driver claims and enable all the clocks +		 *    it needs +		 * b) CCF has a clock hand-off mechanism to make the sure the +		 *    clock stays on until the proper driver comes along +		 */ +		.flags = CLK_IS_CRITICAL,  	},  }; diff --git a/drivers/clk/qcom/gcc-qcs404.c b/drivers/clk/qcom/gcc-qcs404.c index e4ca6a45f313..ef1b267cb058 100644 --- a/drivers/clk/qcom/gcc-qcs404.c +++ b/drivers/clk/qcom/gcc-qcs404.c @@ -265,7 +265,7 @@ static struct clk_fixed_factor cxo = {  	.div = 1,  	.hw.init = &(struct clk_init_data){  		.name = "cxo", -		.parent_names = (const char *[]){ "xo_board" }, +		.parent_names = (const char *[]){ "xo-board" },  		.num_parents = 1,  		.ops = &clk_fixed_factor_ops,  	}, diff --git a/drivers/clocksource/i8253.c b/drivers/clocksource/i8253.c index 9c38895542f4..d4350bb10b83 100644 --- a/drivers/clocksource/i8253.c +++ b/drivers/clocksource/i8253.c @@ -20,6 +20,13 @@  DEFINE_RAW_SPINLOCK(i8253_lock);  EXPORT_SYMBOL(i8253_lock); +/* + * Handle PIT quirk in pit_shutdown() where zeroing the counter register + * restarts the PIT, negating the shutdown. On platforms with the quirk, + * platform specific code can set this to false. + */ +bool i8253_clear_counter_on_shutdown __ro_after_init = true; +  #ifdef CONFIG_CLKSRC_I8253  /*   * Since the PIT overflows every tick, its not very useful @@ -109,8 +116,11 @@ static int pit_shutdown(struct clock_event_device *evt)  	raw_spin_lock(&i8253_lock);  	outb_p(0x30, PIT_MODE); -	outb_p(0, PIT_CH0); -	outb_p(0, PIT_CH0); + +	if (i8253_clear_counter_on_shutdown) { +		outb_p(0, PIT_CH0); +		outb_p(0, PIT_CH0); +	}  	raw_spin_unlock(&i8253_lock);  	return 0; diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 8cfee0ab804b..d8c3595e9023 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -160,8 +160,13 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)  	/* Ensure the arm clock divider is what we expect */  	ret = clk_set_rate(clks[ARM].clk, new_freq * 1000);  	if (ret) { +		int ret1; +  		dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); -		regulator_set_voltage_tol(arm_reg, volt_old, 0); +		ret1 = regulator_set_voltage_tol(arm_reg, volt_old, 0); +		if (ret1) +			dev_warn(cpu_dev, +				 "failed to restore vddarm voltage: %d\n", ret1);  		return ret;  	} 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/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c index 073557f433eb..3a407a3ef22b 100644 --- a/drivers/cpuidle/cpuidle-arm.c +++ b/drivers/cpuidle/cpuidle-arm.c @@ -82,7 +82,6 @@ static int __init arm_idle_init_cpu(int cpu)  {  	int ret;  	struct cpuidle_driver *drv; -	struct cpuidle_device *dev;  	drv = kmemdup(&arm_idle_driver, sizeof(*drv), GFP_KERNEL);  	if (!drv) @@ -103,13 +102,6 @@ static int __init arm_idle_init_cpu(int cpu)  		goto out_kfree_drv;  	} -	ret = cpuidle_register_driver(drv); -	if (ret) { -		if (ret != -EBUSY) -			pr_err("Failed to register cpuidle driver\n"); -		goto out_kfree_drv; -	} -  	/*  	 * Call arch CPU operations in order to initialize  	 * idle states suspend back-end specific data @@ -117,37 +109,21 @@ static int __init arm_idle_init_cpu(int cpu)  	ret = arm_cpuidle_init(cpu);  	/* -	 * Skip the cpuidle device initialization if the reported +	 * Allow the initialization to continue for other CPUs, if the reported  	 * failure is a HW misconfiguration/breakage (-ENXIO).  	 */ -	if (ret == -ENXIO) -		return 0; -  	if (ret) {  		pr_err("CPU %d failed to init idle CPU ops\n", cpu); -		goto out_unregister_drv; -	} - -	dev = kzalloc(sizeof(*dev), GFP_KERNEL); -	if (!dev) { -		ret = -ENOMEM; -		goto out_unregister_drv; +		ret = ret == -ENXIO ? 0 : ret; +		goto out_kfree_drv;  	} -	dev->cpu = cpu; -	ret = cpuidle_register_device(dev); -	if (ret) { -		pr_err("Failed to register cpuidle device for CPU %d\n", -		       cpu); -		goto out_kfree_dev; -	} +	ret = cpuidle_register(drv, NULL); +	if (ret) +		goto out_kfree_drv;  	return 0; -out_kfree_dev: -	kfree(dev); -out_unregister_drv: -	cpuidle_unregister_driver(drv);  out_kfree_drv:  	kfree(drv);  	return ret; @@ -178,9 +154,7 @@ out_fail:  	while (--cpu >= 0) {  		dev = per_cpu(cpuidle_devices, cpu);  		drv = cpuidle_get_cpu_driver(dev); -		cpuidle_unregister_device(dev); -		cpuidle_unregister_driver(drv); -		kfree(dev); +		cpuidle_unregister(drv);  		kfree(drv);  	} diff --git a/drivers/crypto/hisilicon/sec/sec_algs.c b/drivers/crypto/hisilicon/sec/sec_algs.c index f7d6d690116e..cdc4f9a171d9 100644 --- a/drivers/crypto/hisilicon/sec/sec_algs.c +++ b/drivers/crypto/hisilicon/sec/sec_algs.c @@ -732,6 +732,7 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,  	int *splits_in_nents;  	int *splits_out_nents = NULL;  	struct sec_request_el *el, *temp; +	bool split = skreq->src != skreq->dst;  	mutex_init(&sec_req->lock);  	sec_req->req_base = &skreq->base; @@ -750,7 +751,7 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,  	if (ret)  		goto err_free_split_sizes; -	if (skreq->src != skreq->dst) { +	if (split) {  		sec_req->len_out = sg_nents(skreq->dst);  		ret = sec_map_and_split_sg(skreq->dst, split_sizes, steps,  					   &splits_out, &splits_out_nents, @@ -785,8 +786,9 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,  					       split_sizes[i],  					       skreq->src != skreq->dst,  					       splits_in[i], splits_in_nents[i], -					       splits_out[i], -					       splits_out_nents[i], info); +					       split ? splits_out[i] : NULL, +					       split ? splits_out_nents[i] : 0, +					       info);  		if (IS_ERR(el)) {  			ret = PTR_ERR(el);  			goto err_free_elements; @@ -806,13 +808,6 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,  	 * more refined but this is unlikely to happen so no need.  	 */ -	/* Cleanup - all elements in pointer arrays have been coppied */ -	kfree(splits_in_nents); -	kfree(splits_in); -	kfree(splits_out_nents); -	kfree(splits_out); -	kfree(split_sizes); -  	/* Grab a big lock for a long time to avoid concurrency issues */  	mutex_lock(&queue->queuelock); @@ -827,13 +822,13 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,  	     (!queue->havesoftqueue ||  	      kfifo_avail(&queue->softqueue) > steps)) ||  	    !list_empty(&ctx->backlog)) { +		ret = -EBUSY;  		if ((skreq->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {  			list_add_tail(&sec_req->backlog_head, &ctx->backlog);  			mutex_unlock(&queue->queuelock); -			return -EBUSY; +			goto out;  		} -		ret = -EBUSY;  		mutex_unlock(&queue->queuelock);  		goto err_free_elements;  	} @@ -842,7 +837,15 @@ static int sec_alg_skcipher_crypto(struct skcipher_request *skreq,  	if (ret)  		goto err_free_elements; -	return -EINPROGRESS; +	ret = -EINPROGRESS; +out: +	/* Cleanup - all elements in pointer arrays have been copied */ +	kfree(splits_in_nents); +	kfree(splits_in); +	kfree(splits_out_nents); +	kfree(splits_out); +	kfree(split_sizes); +	return ret;  err_free_elements:  	list_for_each_entry_safe(el, temp, &sec_req->elements, head) { @@ -854,7 +857,7 @@ err_free_elements:  				 crypto_skcipher_ivsize(atfm),  				 DMA_BIDIRECTIONAL);  err_unmap_out_sg: -	if (skreq->src != skreq->dst) +	if (split)  		sec_unmap_sg_on_err(skreq->dst, steps, splits_out,  				    splits_out_nents, sec_req->len_out,  				    info->dev); 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/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 7cbac6e8c113..01d936c9fe89 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1641,6 +1641,12 @@ static void atc_free_chan_resources(struct dma_chan *chan)  	atchan->descs_allocated = 0;  	atchan->status = 0; +	/* +	 * Free atslave allocated in at_dma_xlate() +	 */ +	kfree(chan->private); +	chan->private = NULL; +  	dev_vdbg(chan2dev(chan), "free_chan_resources: done\n");  } @@ -1675,7 +1681,7 @@ static struct dma_chan *at_dma_xlate(struct of_phandle_args *dma_spec,  	dma_cap_zero(mask);  	dma_cap_set(DMA_SLAVE, mask); -	atslave = devm_kzalloc(&dmac_pdev->dev, sizeof(*atslave), GFP_KERNEL); +	atslave = kzalloc(sizeof(*atslave), GFP_KERNEL);  	if (!atslave)  		return NULL; @@ -2000,6 +2006,8 @@ static int at_dma_remove(struct platform_device *pdev)  	struct resource		*io;  	at_dma_off(atdma); +	if (pdev->dev.of_node) +		of_dma_controller_free(pdev->dev.of_node);  	dma_async_device_unregister(&atdma->dma_common);  	dma_pool_destroy(atdma->memset_pool); diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c index 388a929baf95..1a6a77df8a5e 100644 --- a/drivers/firmware/efi/arm-init.c +++ b/drivers/firmware/efi/arm-init.c @@ -265,6 +265,10 @@ void __init efi_init(void)  				    (params.mmap & ~PAGE_MASK)));  	init_screen_info(); + +	/* ARM does not permit early mappings to persist across paging_init() */ +	if (IS_ENABLED(CONFIG_ARM)) +		efi_memmap_unmap();  }  static int __init register_gop_device(void) diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c index 922cfb813109..a00934d263c5 100644 --- a/drivers/firmware/efi/arm-runtime.c +++ b/drivers/firmware/efi/arm-runtime.c @@ -110,7 +110,7 @@ static int __init arm_enable_runtime_services(void)  {  	u64 mapsize; -	if (!efi_enabled(EFI_BOOT) || !efi_enabled(EFI_MEMMAP)) { +	if (!efi_enabled(EFI_BOOT)) {  		pr_info("EFI services will not be available.\n");  		return 0;  	} diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 249eb70691b0..415849bab233 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c @@ -592,7 +592,11 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,  		early_memunmap(tbl, sizeof(*tbl));  	} +	return 0; +} +int __init efi_apply_persistent_mem_reservations(void) +{  	if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {  		unsigned long prsv = efi.mem_reserve; @@ -963,36 +967,59 @@ bool efi_is_table_address(unsigned long phys_addr)  }  static DEFINE_SPINLOCK(efi_mem_reserve_persistent_lock); +static struct linux_efi_memreserve *efi_memreserve_root __ro_after_init; -int efi_mem_reserve_persistent(phys_addr_t addr, u64 size) +static int __init efi_memreserve_map_root(void)  { -	struct linux_efi_memreserve *rsv, *parent; -  	if (efi.mem_reserve == EFI_INVALID_TABLE_ADDR)  		return -ENODEV; -	rsv = kmalloc(sizeof(*rsv), GFP_KERNEL); -	if (!rsv) +	efi_memreserve_root = memremap(efi.mem_reserve, +				       sizeof(*efi_memreserve_root), +				       MEMREMAP_WB); +	if (WARN_ON_ONCE(!efi_memreserve_root))  		return -ENOMEM; +	return 0; +} -	parent = memremap(efi.mem_reserve, sizeof(*rsv), MEMREMAP_WB); -	if (!parent) { -		kfree(rsv); -		return -ENOMEM; +int __ref efi_mem_reserve_persistent(phys_addr_t addr, u64 size) +{ +	struct linux_efi_memreserve *rsv; +	int rc; + +	if (efi_memreserve_root == (void *)ULONG_MAX) +		return -ENODEV; + +	if (!efi_memreserve_root) { +		rc = efi_memreserve_map_root(); +		if (rc) +			return rc;  	} +	rsv = kmalloc(sizeof(*rsv), GFP_ATOMIC); +	if (!rsv) +		return -ENOMEM; +  	rsv->base = addr;  	rsv->size = size;  	spin_lock(&efi_mem_reserve_persistent_lock); -	rsv->next = parent->next; -	parent->next = __pa(rsv); +	rsv->next = efi_memreserve_root->next; +	efi_memreserve_root->next = __pa(rsv);  	spin_unlock(&efi_mem_reserve_persistent_lock); -	memunmap(parent); +	return 0; +} +static int __init efi_memreserve_root_init(void) +{ +	if (efi_memreserve_root) +		return 0; +	if (efi_memreserve_map_root()) +		efi_memreserve_root = (void *)ULONG_MAX;  	return 0;  } +early_initcall(efi_memreserve_root_init);  #ifdef CONFIG_KEXEC  static int update_efi_random_seed(struct notifier_block *nb, diff --git a/drivers/firmware/efi/libstub/arm-stub.c b/drivers/firmware/efi/libstub/arm-stub.c index 30ac0c975f8a..3d36142cf812 100644 --- a/drivers/firmware/efi/libstub/arm-stub.c +++ b/drivers/firmware/efi/libstub/arm-stub.c @@ -75,6 +75,9 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)  	efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;  	efi_status_t status; +	if (IS_ENABLED(CONFIG_ARM)) +		return; +  	status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),  				(void **)&rsv);  	if (status != EFI_SUCCESS) { diff --git a/drivers/firmware/efi/libstub/fdt.c b/drivers/firmware/efi/libstub/fdt.c index 8830fa601e45..0c0d2312f4a8 100644 --- a/drivers/firmware/efi/libstub/fdt.c +++ b/drivers/firmware/efi/libstub/fdt.c @@ -158,6 +158,10 @@ static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt,  			return efi_status;  		}  	} + +	/* shrink the FDT back to its minimum size */ +	fdt_pack(fdt); +  	return EFI_SUCCESS;  fdt_set_fail: diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c index fa2904fb841f..38b686c67b17 100644 --- a/drivers/firmware/efi/memmap.c +++ b/drivers/firmware/efi/memmap.c @@ -118,6 +118,9 @@ int __init efi_memmap_init_early(struct efi_memory_map_data *data)  void __init efi_memmap_unmap(void)  { +	if (!efi_enabled(EFI_MEMMAP)) +		return; +  	if (!efi.memmap.late) {  		unsigned long size; diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c index a19d845bdb06..8903b9ccfc2b 100644 --- a/drivers/firmware/efi/runtime-wrappers.c +++ b/drivers/firmware/efi/runtime-wrappers.c @@ -67,7 +67,7 @@ struct efi_runtime_work efi_rts_work;  	}								\  									\  	init_completion(&efi_rts_work.efi_rts_comp);			\ -	INIT_WORK_ONSTACK(&efi_rts_work.work, efi_call_rts);		\ +	INIT_WORK(&efi_rts_work.work, efi_call_rts);			\  	efi_rts_work.arg1 = _arg1;					\  	efi_rts_work.arg2 = _arg2;					\  	efi_rts_work.arg3 = _arg3;					\ diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig index af3a20dd5aa4..99c99a5d57fe 100644 --- a/drivers/fsi/Kconfig +++ b/drivers/fsi/Kconfig @@ -46,6 +46,7 @@ config FSI_MASTER_AST_CF  	tristate "FSI master based on Aspeed ColdFire coprocessor"  	depends on GPIOLIB  	depends on GPIO_ASPEED +	select GENERIC_ALLOCATOR  	---help---  	This option enables a FSI master using the AST2400 and AST2500 GPIO  	lines driven by the internal ColdFire coprocessor. This requires diff --git a/drivers/fsi/fsi-scom.c b/drivers/fsi/fsi-scom.c index df94021dd9d1..81dc01ac2351 100644 --- a/drivers/fsi/fsi-scom.c +++ b/drivers/fsi/fsi-scom.c @@ -20,7 +20,6 @@  #include <linux/fs.h>  #include <linux/uaccess.h>  #include <linux/slab.h> -#include <linux/cdev.h>  #include <linux/list.h>  #include <uapi/linux/fsi.h> 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-davinci.c b/drivers/gpio/gpio-davinci.c index 5c1564fcc24e..bdb29e51b417 100644 --- a/drivers/gpio/gpio-davinci.c +++ b/drivers/gpio/gpio-davinci.c @@ -258,7 +258,7 @@ static int davinci_gpio_probe(struct platform_device *pdev)  	chips->chip.set = davinci_gpio_set;  	chips->chip.ngpio = ngpio; -	chips->chip.base = -1; +	chips->chip.base = pdata->no_auto_base ? pdata->base : -1;  #ifdef CONFIG_OF_GPIO  	chips->chip.of_gpio_n_cells = 2; 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.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index d0102cfc8efb..104b2e0d893b 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -151,6 +151,7 @@ extern int amdgpu_compute_multipipe;  extern int amdgpu_gpu_recovery;  extern int amdgpu_emu_mode;  extern uint amdgpu_smu_memory_pool_size; +extern uint amdgpu_dc_feature_mask;  extern struct amdgpu_mgpu_info mgpu_info;  #ifdef CONFIG_DRM_AMDGPU_SI diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c index c31a8849e9f8..1580ec60b89f 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_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 943dbf3c5da1..8de55f7f1a3a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -127,6 +127,9 @@ int amdgpu_compute_multipipe = -1;  int amdgpu_gpu_recovery = -1; /* auto */  int amdgpu_emu_mode = 0;  uint amdgpu_smu_memory_pool_size = 0; +/* FBC (bit 0) disabled by default*/ +uint amdgpu_dc_feature_mask = 0; +  struct amdgpu_mgpu_info mgpu_info = {  	.mutex = __MUTEX_INITIALIZER(mgpu_info.mutex),  }; @@ -631,6 +634,14 @@ module_param(halt_if_hws_hang, int, 0644);  MODULE_PARM_DESC(halt_if_hws_hang, "Halt if HWS hang is detected (0 = off (default), 1 = on)");  #endif +/** + * DOC: dcfeaturemask (uint) + * Override display features enabled. See enum DC_FEATURE_MASK in drivers/gpu/drm/amd/include/amd_shared.h. + * The default is the current set of stable display features. + */ +MODULE_PARM_DESC(dcfeaturemask, "all stable DC features enabled (default))"); +module_param_named(dcfeaturemask, amdgpu_dc_feature_mask, uint, 0444); +  static const struct pci_device_id pciidlist[] = {  #ifdef  CONFIG_DRM_AMDGPU_SI  	{0x1002, 0x6780, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CHIP_TAHITI}, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h index b9e9e8b02fb7..d1b4d9b6aae0 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h @@ -339,6 +339,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/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 352b30409060..0877ff9a9594 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -181,7 +181,7 @@ static unsigned amdgpu_vm_num_entries(struct amdgpu_device *adev,  	if (level == adev->vm_manager.root_level)  		/* For the root directory */ -		return round_up(adev->vm_manager.max_pfn, 1 << shift) >> shift; +		return round_up(adev->vm_manager.max_pfn, 1ULL << shift) >> shift;  	else if (level != AMDGPU_VM_PTB)  		/* Everything in between */  		return 512; @@ -1632,13 +1632,6 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  			continue;  		} -		/* First check if the entry is already handled */ -		if (cursor.pfn < frag_start) { -			cursor.entry->huge = true; -			amdgpu_vm_pt_next(adev, &cursor); -			continue; -		} -  		/* If it isn't already handled it can't be a huge page */  		if (cursor.entry->huge) {  			/* Add the entry to the relocated list to update it. */ @@ -1663,9 +1656,11 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  			if (!amdgpu_vm_pt_descendant(adev, &cursor))  				return -ENOENT;  			continue; -		} else if (frag >= parent_shift) { +		} else if (frag >= parent_shift && +			   cursor.level - 1 != adev->vm_manager.root_level) {  			/* If the fragment size is even larger than the parent -			 * shift we should go up one level and check it again. +			 * shift we should go up one level and check it again +			 * unless one level up is the root level.  			 */  			if (!amdgpu_vm_pt_ancestor(&cursor))  				return -ENOENT; @@ -1673,10 +1668,10 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  		}  		/* Looks good so far, calculate parameters for the update */ -		incr = AMDGPU_GPU_PAGE_SIZE << shift; +		incr = (uint64_t)AMDGPU_GPU_PAGE_SIZE << shift;  		mask = amdgpu_vm_entries_mask(adev, cursor.level);  		pe_start = ((cursor.pfn >> shift) & mask) * 8; -		entry_end = (mask + 1) << shift; +		entry_end = (uint64_t)(mask + 1) << shift;  		entry_end += cursor.pfn & ~(entry_end - 1);  		entry_end = min(entry_end, end); @@ -1689,7 +1684,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  					      flags | AMDGPU_PTE_FRAG(frag));  			pe_start += nptes * 8; -			dst += nptes * AMDGPU_GPU_PAGE_SIZE << shift; +			dst += (uint64_t)nptes * AMDGPU_GPU_PAGE_SIZE << shift;  			frag_start = upd_end;  			if (frag_start >= frag_end) { @@ -1701,8 +1696,17 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,  			}  		} while (frag_start < entry_end); -		if (frag >= shift) +		if (amdgpu_vm_pt_descendant(adev, &cursor)) { +			/* Mark all child entries as huge */ +			while (cursor.pfn < frag_start) { +				cursor.entry->huge = true; +				amdgpu_vm_pt_next(adev, &cursor); +			} + +		} else if (frag >= shift) { +			/* or just move on to the next on the same level. */  			amdgpu_vm_pt_next(adev, &cursor); +		}  	}  	return 0; diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c index 6d7baf59d6e1..21363b2b2ee5 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c @@ -2440,12 +2440,13 @@ static void gfx_v9_0_rlc_start(struct amdgpu_device *adev)  #endif  	WREG32_FIELD15(GC, 0, RLC_CNTL, RLC_ENABLE_F32, 1); +	udelay(50);  	/* carrizo do enable cp interrupt after cp inited */ -	if (!(adev->flags & AMD_IS_APU)) +	if (!(adev->flags & AMD_IS_APU)) {  		gfx_v9_0_enable_gui_idle_interrupt(adev, true); - -	udelay(50); +		udelay(50); +	}  #ifdef AMDGPU_RLC_DEBUG_RETRY  	/* RLC_GPM_GENERAL_6 : RLC Ucode version */ diff --git a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c index ceb7847b504f..bfa317ad20a9 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfxhub_v1_0.c @@ -72,7 +72,7 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)  	/* Program the system aperture low logical page number. */  	WREG32_SOC15(GC, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR, -		     min(adev->gmc.vram_start, adev->gmc.agp_start) >> 18); +		     min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);  	if (adev->asic_type == CHIP_RAVEN && adev->rev_id >= 0x8)  		/* @@ -82,11 +82,11 @@ static void gfxhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)  		 * to get rid of the VM fault and hardware hang.  		 */  		WREG32_SOC15(GC, 0, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR, -			     max((adev->gmc.vram_end >> 18) + 0x1, +			     max((adev->gmc.fb_end >> 18) + 0x1,  				 adev->gmc.agp_end >> 18));  	else  		WREG32_SOC15(GC, 0, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR, -			     max(adev->gmc.vram_end, adev->gmc.agp_end) >> 18); +			     max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);  	/* Set default page address. */  	value = adev->vram_scratch.gpu_addr - adev->gmc.vram_start diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v6_0.c index e1c2b4e9c7b2..73ad02aea2b2 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/mmhub_v1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c index fd23ba1226a5..a0db67adc34c 100644 --- a/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c +++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v1_0.c @@ -90,7 +90,7 @@ static void mmhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)  	/* Program the system aperture low logical page number. */  	WREG32_SOC15(MMHUB, 0, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR, -		     min(adev->gmc.vram_start, adev->gmc.agp_start) >> 18); +		     min(adev->gmc.fb_start, adev->gmc.agp_start) >> 18);  	if (adev->asic_type == CHIP_RAVEN && adev->rev_id >= 0x8)  		/* @@ -100,11 +100,11 @@ static void mmhub_v1_0_init_system_aperture_regs(struct amdgpu_device *adev)  		 * to get rid of the VM fault and hardware hang.  		 */  		WREG32_SOC15(MMHUB, 0, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR, -			     max((adev->gmc.vram_end >> 18) + 0x1, +			     max((adev->gmc.fb_end >> 18) + 0x1,  				 adev->gmc.agp_end >> 18));  	else  		WREG32_SOC15(MMHUB, 0, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR, -			     max(adev->gmc.vram_end, adev->gmc.agp_end) >> 18); +			     max(adev->gmc.fb_end, adev->gmc.agp_end) >> 18);  	/* Set default page address. */  	value = adev->vram_scratch.gpu_addr - adev->gmc.vram_start + 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/amdgpu/vega10_ih.c b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c index a99f71797aa3..a0fda6f9252a 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega10_ih.c +++ b/drivers/gpu/drm/amd/amdgpu/vega10_ih.c @@ -129,7 +129,7 @@ static int vega10_ih_irq_init(struct amdgpu_device *adev)  	else  		wptr_off = adev->wb.gpu_addr + (adev->irq.ih.wptr_offs * 4);  	WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_LO, lower_32_bits(wptr_off)); -	WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFF); +	WREG32_SOC15(OSSSYS, 0, mmIH_RB_WPTR_ADDR_HI, upper_32_bits(wptr_off) & 0xFFFF);  	/* set rptr, wptr to 0 */  	WREG32_SOC15(OSSSYS, 0, mmIH_RB_RPTR, 0); diff --git a/drivers/gpu/drm/amd/amdgpu/vega20_reg_init.c b/drivers/gpu/drm/amd/amdgpu/vega20_reg_init.c index 2d4473557b0d..d13fc4fcb517 100644 --- a/drivers/gpu/drm/amd/amdgpu/vega20_reg_init.c +++ b/drivers/gpu/drm/amd/amdgpu/vega20_reg_init.c @@ -49,6 +49,7 @@ int vega20_reg_base_init(struct amdgpu_device *adev)  		adev->reg_offset[SMUIO_HWIP][i] = (uint32_t *)(&(SMUIO_BASE.instance[i]));  		adev->reg_offset[NBIF_HWIP][i] = (uint32_t *)(&(NBIO_BASE.instance[i]));  		adev->reg_offset[THM_HWIP][i] = (uint32_t *)(&(THM_BASE.instance[i])); +		adev->reg_offset[CLK_HWIP][i] = (uint32_t *)(&(CLK_BASE.instance[i]));  	}  	return 0;  } 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 b0df6dc9a775..ca925200fe09 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -429,6 +429,9 @@ static int amdgpu_dm_init(struct amdgpu_device *adev)  	    adev->asic_type < CHIP_RAVEN)  		init_data.flags.gpu_vm_support = true; +	if (amdgpu_dc_feature_mask & DC_FBC_MASK) +		init_data.flags.fbc_support = true; +  	/* Display Core create. */  	adev->dm.dc = dc_create(&init_data); @@ -1524,13 +1527,6 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)  {  	struct amdgpu_display_manager *dm = bl_get_data(bd); -	/* -	 * PWM interperts 0 as 100% rather than 0% because of HW -	 * limitation for level 0.So limiting minimum brightness level -	 * to 1. -	 */ -	if (bd->props.brightness < 1) -		return 1;  	if (dc_link_set_backlight_level(dm->backlight_link,  			bd->props.brightness, 0, 0))  		return 0; @@ -2362,8 +2358,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:  		/* @@ -2707,18 +2710,11 @@ create_stream_for_sink(struct amdgpu_dm_connector *aconnector,  	drm_connector = &aconnector->base;  	if (!aconnector->dc_sink) { -		/* -		 * Create dc_sink when necessary to MST -		 * Don't apply fake_sink to MST -		 */ -		if (aconnector->mst_port) { -			dm_dp_mst_dc_sink_create(drm_connector); -			return stream; +		if (!aconnector->mst_port) { +			sink = create_fake_sink(aconnector); +			if (!sink) +				return stream;  		} - -		sink = create_fake_sink(aconnector); -		if (!sink) -			return stream;  	} else {  		sink = aconnector->dc_sink;  	} @@ -2954,6 +2950,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; @@ -2996,6 +2995,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;  } @@ -3308,7 +3310,7 @@ void dm_drm_plane_destroy_state(struct drm_plane *plane,  static const struct drm_plane_funcs dm_plane_funcs = {  	.update_plane	= drm_atomic_helper_update_plane,  	.disable_plane	= drm_atomic_helper_disable_plane, -	.destroy	= drm_plane_cleanup, +	.destroy	= drm_primary_helper_destroy,  	.reset = dm_drm_plane_reset,  	.atomic_duplicate_state = dm_drm_plane_duplicate_state,  	.atomic_destroy_state = dm_drm_plane_destroy_state, @@ -3806,6 +3808,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 978b34a5011c..6e069d777ab2 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.h @@ -160,8 +160,6 @@ struct amdgpu_dm_connector {  	struct mutex hpd_lock;  	bool fake_enable; - -	bool mst_connected;  };  #define to_amdgpu_dm_connector(x) container_of(x, struct amdgpu_dm_connector, base) @@ -206,6 +204,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/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 03601d717fed..1b0d209d8367 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -205,40 +205,6 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {  	.atomic_get_property = amdgpu_dm_connector_atomic_get_property  }; -void dm_dp_mst_dc_sink_create(struct drm_connector *connector) -{ -	struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); -	struct dc_sink *dc_sink; -	struct dc_sink_init_data init_params = { -			.link = aconnector->dc_link, -			.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST }; - -	/* FIXME none of this is safe. we shouldn't touch aconnector here in -	 * atomic_check -	 */ - -	/* -	 * TODO: Need to further figure out why ddc.algo is NULL while MST port exists -	 */ -	if (!aconnector->port || !aconnector->port->aux.ddc.algo) -		return; - -	ASSERT(aconnector->edid); - -	dc_sink = dc_link_add_remote_sink( -		aconnector->dc_link, -		(uint8_t *)aconnector->edid, -		(aconnector->edid->extensions + 1) * EDID_LENGTH, -		&init_params); - -	dc_sink->priv = aconnector; -	aconnector->dc_sink = dc_sink; - -	if (aconnector->dc_sink) -		amdgpu_dm_update_freesync_caps( -				connector, aconnector->edid); -} -  static int dm_dp_mst_get_modes(struct drm_connector *connector)  {  	struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector); @@ -319,12 +285,7 @@ dm_dp_create_fake_mst_encoder(struct amdgpu_dm_connector *connector)  	struct amdgpu_device *adev = dev->dev_private;  	struct amdgpu_encoder *amdgpu_encoder;  	struct drm_encoder *encoder; -	const struct drm_connector_helper_funcs *connector_funcs = -		connector->base.helper_private; -	struct drm_encoder *enc_master = -		connector_funcs->best_encoder(&connector->base); -	DRM_DEBUG_KMS("enc master is %p\n", enc_master);  	amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);  	if (!amdgpu_encoder)  		return NULL; @@ -354,25 +315,6 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,  	struct amdgpu_device *adev = dev->dev_private;  	struct amdgpu_dm_connector *aconnector;  	struct drm_connector *connector; -	struct drm_connector_list_iter conn_iter; - -	drm_connector_list_iter_begin(dev, &conn_iter); -	drm_for_each_connector_iter(connector, &conn_iter) { -		aconnector = to_amdgpu_dm_connector(connector); -		if (aconnector->mst_port == master -				&& !aconnector->port) { -			DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n", -						aconnector, connector->base.id, aconnector->mst_port); - -			aconnector->port = port; -			drm_connector_set_path_property(connector, pathprop); - -			drm_connector_list_iter_end(&conn_iter); -			aconnector->mst_connected = true; -			return &aconnector->base; -		} -	} -	drm_connector_list_iter_end(&conn_iter);  	aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);  	if (!aconnector) @@ -400,10 +342,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,  		master->connector_id);  	aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master); +	drm_connector_attach_encoder(&aconnector->base, +				     &aconnector->mst_encoder->base); -	/* -	 * TODO: understand why this one is needed -	 */  	drm_object_attach_property(  		&connector->base,  		dev->mode_config.path_property, @@ -421,8 +362,6 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,  	 */  	amdgpu_dm_connector_funcs_reset(connector); -	aconnector->mst_connected = true; -  	DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n",  			aconnector, connector->base.id, aconnector->mst_port); @@ -434,6 +373,9 @@ dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,  static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,  					struct drm_connector *connector)  { +	struct amdgpu_dm_connector *master = container_of(mgr, struct amdgpu_dm_connector, mst_mgr); +	struct drm_device *dev = master->base.dev; +	struct amdgpu_device *adev = dev->dev_private;  	struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);  	DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n", @@ -447,7 +389,10 @@ static void dm_dp_destroy_mst_connector(struct drm_dp_mst_topology_mgr *mgr,  		aconnector->dc_sink = NULL;  	} -	aconnector->mst_connected = false; +	drm_connector_unregister(connector); +	if (adev->mode_info.rfbdev) +		drm_fb_helper_remove_one_connector(&adev->mode_info.rfbdev->helper, connector); +	drm_connector_put(connector);  }  static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr) @@ -458,18 +403,10 @@ static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)  	drm_kms_helper_hotplug_event(dev);  } -static void dm_dp_mst_link_status_reset(struct drm_connector *connector) -{ -	mutex_lock(&connector->dev->mode_config.mutex); -	drm_connector_set_link_status_property(connector, DRM_MODE_LINK_STATUS_BAD); -	mutex_unlock(&connector->dev->mode_config.mutex); -} -  static void dm_dp_mst_register_connector(struct drm_connector *connector)  {  	struct drm_device *dev = connector->dev;  	struct amdgpu_device *adev = dev->dev_private; -	struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);  	if (adev->mode_info.rfbdev)  		drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector); @@ -477,9 +414,6 @@ static void dm_dp_mst_register_connector(struct drm_connector *connector)  		DRM_ERROR("adev->mode_info.rfbdev is NULL\n");  	drm_connector_register(connector); - -	if (aconnector->mst_connected) -		dm_dp_mst_link_status_reset(connector);  }  static const struct drm_dp_mst_topology_cbs dm_mst_cbs = { diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h index 8cf51da26657..2da851b40042 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.h @@ -31,6 +31,5 @@ struct amdgpu_dm_connector;  void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm,  				       struct amdgpu_dm_connector *aconnector); -void dm_dp_mst_dc_sink_create(struct drm_connector *connector);  #endif diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_link.c b/drivers/gpu/drm/amd/display/dc/core/dc_link.c index fb04a4ad141f..5da2186b3615 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_link.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_link.c @@ -1722,7 +1722,7 @@ static void write_i2c_retimer_setting(  		i2c_success = i2c_write(pipe_ctx, slave_address,  				buffer, sizeof(buffer));  		RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ -			offset = 0x%d, reg_val = 0x%d, i2c_success = %d\n", +			offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",  			slave_address, buffer[0], buffer[1], i2c_success?1:0);  		if (!i2c_success)  			/* Write failure */ @@ -1734,7 +1734,7 @@ static void write_i2c_retimer_setting(  		i2c_success = i2c_write(pipe_ctx, slave_address,  				buffer, sizeof(buffer));  		RETIMER_REDRIVER_INFO("retimer write to slave_address = 0x%x,\ -			offset = 0x%d, reg_val = 0x%d, i2c_success = %d\n", +			offset = 0x%x, reg_val = 0x%x, i2c_success = %d\n",  			slave_address, buffer[0], buffer[1], i2c_success?1:0);  		if (!i2c_success)  			/* Write failure */ diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h index 199527171100..b57fa61b3034 100644 --- a/drivers/gpu/drm/amd/display/dc/dc.h +++ b/drivers/gpu/drm/amd/display/dc/dc.h @@ -169,6 +169,7 @@ struct link_training_settings;  struct dc_config {  	bool gpu_vm_support;  	bool disable_disp_pll_sharing; +	bool fbc_support;  };  enum visual_confirm { diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c index b75ede5f84f7..b459867a05b2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_hw_sequencer.c @@ -1736,7 +1736,12 @@ static void set_static_screen_control(struct pipe_ctx **pipe_ctx,  	if (events->force_trigger)  		value |= 0x1; -	value |= 0x84; +	if (num_pipes) { +		struct dc *dc = pipe_ctx[0]->stream->ctx->dc; + +		if (dc->fbc_compressor) +			value |= 0x84; +	}  	for (i = 0; i < num_pipes; i++)  		pipe_ctx[i]->stream_res.tg->funcs-> diff --git a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c index e3624ca24574..7c9fd9052ee2 100644 --- a/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c +++ b/drivers/gpu/drm/amd/display/dc/dce110/dce110_resource.c @@ -1362,7 +1362,8 @@ static bool construct(  		pool->base.sw_i2cs[i] = NULL;  	} -	dc->fbc_compressor = dce110_compressor_create(ctx); +	if (dc->config.fbc_support) +		dc->fbc_compressor = dce110_compressor_create(ctx);  	if (!underlay_create(ctx, &pool->base))  		goto res_create_fail; diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index 2083c308007c..470d7b89071a 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -133,6 +133,10 @@ enum PP_FEATURE_MASK {  	PP_AVFS_MASK = 0x40000,  }; +enum DC_FEATURE_MASK { +	DC_FBC_MASK = 0x1, +}; +  /**   * struct amd_ip_funcs - general hooks for managing amdgpu IP Blocks   */ diff --git a/drivers/gpu/drm/amd/include/atomfirmware.h b/drivers/gpu/drm/amd/include/atomfirmware.h index d2e7c0fa96c2..8eb0bb241210 100644 --- a/drivers/gpu/drm/amd/include/atomfirmware.h +++ b/drivers/gpu/drm/amd/include/atomfirmware.h @@ -1325,7 +1325,7 @@ struct atom_smu_info_v3_3 {    struct   atom_common_table_header  table_header;    uint8_t  smuip_min_ver;    uint8_t  smuip_max_ver; -  uint8_t  smu_rsd1; +  uint8_t  waflclk_ss_mode;    uint8_t  gpuclk_ss_mode;    uint16_t sclk_ss_percentage;    uint16_t sclk_ss_rate_10hz; @@ -1355,7 +1355,10 @@ struct atom_smu_info_v3_3 {    uint32_t syspll3_1_vco_freq_10khz;    uint32_t bootup_fclk_10khz;    uint32_t bootup_waflclk_10khz; -  uint32_t reserved[3]; +  uint32_t smu_info_caps; +  uint16_t waflclk_ss_percentage;    // in unit of 0.001% +  uint16_t smuinitoffset; +  uint32_t reserved;  };  /* 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/smu_helper.c b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c index 99a33c33a32c..101c09b212ad 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/smu_helper.c @@ -713,20 +713,20 @@ int smu_set_watermarks_for_clocks_ranges(void *wt_table,  	for (i = 0; i < wm_with_clock_ranges->num_wm_dmif_sets; i++) {  		table->WatermarkRow[1][i].MinClock =  			cpu_to_le16((uint16_t) -			(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz) / -			1000); +			(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_dcfclk_clk_in_khz / +			1000));  		table->WatermarkRow[1][i].MaxClock =  			cpu_to_le16((uint16_t) -			(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz) / -			1000); +			(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_dcfclk_clk_in_khz / +			1000));  		table->WatermarkRow[1][i].MinUclk =  			cpu_to_le16((uint16_t) -			(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz) / -			1000); +			(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_min_mem_clk_in_khz / +			1000));  		table->WatermarkRow[1][i].MaxUclk =  			cpu_to_le16((uint16_t) -			(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz) / -			1000); +			(wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_max_mem_clk_in_khz / +			1000));  		table->WatermarkRow[1][i].WmSetting = (uint8_t)  				wm_with_clock_ranges->wm_dmif_clocks_ranges[i].wm_set_id;  	} @@ -734,20 +734,20 @@ int smu_set_watermarks_for_clocks_ranges(void *wt_table,  	for (i = 0; i < wm_with_clock_ranges->num_wm_mcif_sets; i++) {  		table->WatermarkRow[0][i].MinClock =  			cpu_to_le16((uint16_t) -			(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz) / -			1000); +			(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_socclk_clk_in_khz / +			1000));  		table->WatermarkRow[0][i].MaxClock =  			cpu_to_le16((uint16_t) -			(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz) / -			1000); +			(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_socclk_clk_in_khz / +			1000));  		table->WatermarkRow[0][i].MinUclk =  			cpu_to_le16((uint16_t) -			(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz) / -			1000); +			(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_min_mem_clk_in_khz / +			1000));  		table->WatermarkRow[0][i].MaxUclk =  			cpu_to_le16((uint16_t) -			(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz) / -			1000); +			(wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_max_mem_clk_in_khz / +			1000));  		table->WatermarkRow[0][i].WmSetting = (uint8_t)  				wm_with_clock_ranges->wm_mcif_clocks_ranges[i].wm_set_id;  	} 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 57143d51e3ee..b4eadd47f3a4 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; @@ -120,6 +130,7 @@ static void vega20_set_default_registry_data(struct pp_hwmgr *hwmgr)  	data->registry_data.disable_auto_wattman = 1;  	data->registry_data.auto_wattman_debug = 0;  	data->registry_data.auto_wattman_sample_period = 100; +	data->registry_data.fclk_gfxclk_ratio = 0x3F6CCCCD;  	data->registry_data.auto_wattman_threshold = 50;  	data->registry_data.gfxoff_controlled_by_driver = 1;  	data->gfxoff_allowed = false; @@ -829,6 +840,28 @@ static int vega20_enable_all_smu_features(struct pp_hwmgr *hwmgr)  	return 0;  } +static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr) +{ +	struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); + +	if (data->smu_features[GNLD_DPM_UCLK].enabled) +		return smum_send_msg_to_smc_with_parameter(hwmgr, +			PPSMC_MSG_SetUclkFastSwitch, +			1); + +	return 0; +} + +static int vega20_send_clock_ratio(struct pp_hwmgr *hwmgr) +{ +	struct vega20_hwmgr *data = +			(struct vega20_hwmgr *)(hwmgr->backend); + +	return smum_send_msg_to_smc_with_parameter(hwmgr, +			PPSMC_MSG_SetFclkGfxClkRatio, +			data->registry_data.fclk_gfxclk_ratio); +} +  static int vega20_disable_all_smu_features(struct pp_hwmgr *hwmgr)  {  	struct vega20_hwmgr *data = @@ -1290,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;  } @@ -1335,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;  } @@ -1532,6 +1567,16 @@ static int vega20_enable_dpm_tasks(struct pp_hwmgr *hwmgr)  			"[EnableDPMTasks] Failed to enable all smu features!",  			return result); +	result = vega20_notify_smc_display_change(hwmgr); +	PP_ASSERT_WITH_CODE(!result, +			"[EnableDPMTasks] Failed to notify smc display change!", +			return result); + +	result = vega20_send_clock_ratio(hwmgr); +	PP_ASSERT_WITH_CODE(!result, +			"[EnableDPMTasks] Failed to send clock ratio!", +			return result); +  	/* Initialize UVD/VCE powergating state */  	vega20_init_powergate_state(hwmgr); @@ -1972,19 +2017,6 @@ static int vega20_read_sensor(struct pp_hwmgr *hwmgr, int idx,  	return ret;  } -static int vega20_notify_smc_display_change(struct pp_hwmgr *hwmgr, -		bool has_disp) -{ -	struct vega20_hwmgr *data = (struct vega20_hwmgr *)(hwmgr->backend); - -	if (data->smu_features[GNLD_DPM_UCLK].enabled) -		return smum_send_msg_to_smc_with_parameter(hwmgr, -			PPSMC_MSG_SetUclkFastSwitch, -			has_disp ? 1 : 0); - -	return 0; -} -  int vega20_display_clock_voltage_request(struct pp_hwmgr *hwmgr,  		struct pp_display_clock_request *clock_req)  { @@ -2044,13 +2076,6 @@ static int vega20_notify_smc_display_config_after_ps_adjustment(  	struct pp_display_clock_request clock_req;  	int ret = 0; -	if ((hwmgr->display_config->num_display > 1) && -	     !hwmgr->display_config->multi_monitor_in_sync && -	     !hwmgr->display_config->nb_pstate_switch_disable) -		vega20_notify_smc_display_change(hwmgr, false); -	else -		vega20_notify_smc_display_change(hwmgr, true); -  	min_clocks.dcefClock = hwmgr->display_config->min_dcef_set_clk;  	min_clocks.dcefClockInSR = hwmgr->display_config->min_dcef_deep_sleep_set_clk;  	min_clocks.memoryClock = hwmgr->display_config->min_mem_set_clock; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h index 56fe6a0d42e8..25faaa5c5b10 100644 --- a/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/vega20_hwmgr.h @@ -328,6 +328,7 @@ struct vega20_registry_data {  	uint8_t   disable_auto_wattman;  	uint32_t  auto_wattman_debug;  	uint32_t  auto_wattman_sample_period; +	uint32_t  fclk_gfxclk_ratio;  	uint8_t   auto_wattman_threshold;  	uint8_t   log_avfs_param;  	uint8_t   enable_enginess; diff --git a/drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h index 45d64a81e945..4f63a736ea0e 100644 --- a/drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h +++ b/drivers/gpu/drm/amd/powerplay/inc/vega20_ppsmc.h @@ -105,7 +105,8 @@  #define PPSMC_MSG_SetSystemVirtualDramAddrHigh   0x4B  #define PPSMC_MSG_SetSystemVirtualDramAddrLow    0x4C  #define PPSMC_MSG_WaflTest                       0x4D -// Unused ID 0x4E to 0x50 +#define PPSMC_MSG_SetFclkGfxClkRatio             0x4E +// Unused ID 0x4F to 0x50  #define PPSMC_MSG_AllowGfxOff                    0x51  #define PPSMC_MSG_DisallowGfxOff                 0x52  #define PPSMC_MSG_GetPptLimit                    0x53 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_main.c b/drivers/gpu/drm/ast/ast_main.c index dac355812adc..373700c05a00 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -583,7 +583,8 @@ void ast_driver_unload(struct drm_device *dev)  	drm_mode_config_cleanup(dev);  	ast_mm_fini(ast); -	pci_iounmap(dev->pdev, ast->ioregs); +	if (ast->ioregs != ast->regs + AST_IO_MM_OFFSET) +		pci_iounmap(dev->pdev, ast->ioregs);  	pci_iounmap(dev->pdev, ast->regs);  	kfree(ast);  } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index 5e77d456d9bb..8bb355d5d43d 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; @@ -972,9 +973,21 @@ static int get_clock(void *i2c_priv)  {  	struct ast_i2c_chan *i2c = i2c_priv;  	struct ast_private *ast = i2c->dev->dev_private; -	uint32_t val; +	uint32_t val, val2, count, pass; + +	count = 0; +	pass = 0; +	val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01; +	do { +		val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01; +		if (val == val2) { +			pass++; +		} else { +			pass = 0; +			val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4) & 0x01; +		} +	} while ((pass < 5) && (count++ < 0x10000)); -	val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x10) >> 4;  	return val & 1 ? 1 : 0;  } @@ -982,9 +995,21 @@ static int get_data(void *i2c_priv)  {  	struct ast_i2c_chan *i2c = i2c_priv;  	struct ast_private *ast = i2c->dev->dev_private; -	uint32_t val; +	uint32_t val, val2, count, pass; + +	count = 0; +	pass = 0; +	val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01; +	do { +		val2 = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01; +		if (val == val2) { +			pass++; +		} else { +			pass = 0; +			val = (ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5) & 0x01; +		} +	} while ((pass < 5) && (count++ < 0x10000)); -	val = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x20) >> 5;  	return val & 1 ? 1 : 0;  } @@ -997,7 +1022,7 @@ static void set_clock(void *i2c_priv, int clock)  	for (i = 0; i < 0x10000; i++) {  		ujcrb7 = ((clock & 0x01) ? 0 : 1); -		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfe, ujcrb7); +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf4, ujcrb7);  		jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x01);  		if (ujcrb7 == jtemp)  			break; @@ -1013,7 +1038,7 @@ static void set_data(void *i2c_priv, int data)  	for (i = 0; i < 0x10000; i++) {  		ujcrb7 = ((data & 0x01) ? 0 : 1) << 2; -		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xfb, ujcrb7); +		ast_set_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0xf1, ujcrb7);  		jtemp = ast_get_index_reg_mask(ast, AST_IO_CRTC_PORT, 0xb7, 0x04);  		if (ujcrb7 == jtemp)  			break; @@ -1254,7 +1279,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_auth.c b/drivers/gpu/drm/drm_auth.c index d9c0f7573905..1669c42c40ed 100644 --- a/drivers/gpu/drm/drm_auth.c +++ b/drivers/gpu/drm/drm_auth.c @@ -142,6 +142,7 @@ static int drm_new_set_master(struct drm_device *dev, struct drm_file *fpriv)  	lockdep_assert_held_once(&dev->master_mutex); +	WARN_ON(fpriv->is_master);  	old_master = fpriv->master;  	fpriv->master = drm_master_create(dev);  	if (!fpriv->master) { @@ -170,6 +171,7 @@ out_err:  	/* drop references and restore old master on failure */  	drm_master_put(&fpriv->master);  	fpriv->master = old_master; +	fpriv->is_master = 0;  	return ret;  } diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 5ff1d79b86c4..0e0df398222d 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -1275,6 +1275,9 @@ static struct drm_dp_mst_branch *drm_dp_get_mst_branch_device(struct drm_dp_mst_  	mutex_lock(&mgr->lock);  	mstb = mgr->mst_primary; +	if (!mstb) +		goto out; +  	for (i = 0; i < lct - 1; i++) {  		int shift = (i % 2) ? 0 : 4;  		int port_num = (rad[i / 2] >> shift) & 0xf; diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index a502f3e519fd..dd852a25d375 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/drm_fourcc.c b/drivers/gpu/drm/drm_fourcc.c index 90a1c846fc25..8aaa5e86a979 100644 --- a/drivers/gpu/drm/drm_fourcc.c +++ b/drivers/gpu/drm/drm_fourcc.c @@ -97,9 +97,9 @@ EXPORT_SYMBOL(drm_mode_legacy_fb_format);  /**   * drm_driver_legacy_fb_format - compute drm fourcc code from legacy description + * @dev: DRM device   * @bpp: bits per pixels   * @depth: bit depth per pixel - * @native: use host native byte order   *   * Computes a drm fourcc pixel format code for the given @bpp/@depth values.   * Unlike drm_mode_legacy_fb_format() this looks at the drivers mode_config, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c index e7c3ed6c9a2e..9b476368aa31 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c @@ -93,7 +93,7 @@ static void etnaviv_sched_timedout_job(struct drm_sched_job *sched_job)  	 * If the GPU managed to complete this jobs fence, the timout is  	 * spurious. Bail out.  	 */ -	if (fence_completed(gpu, submit->out_fence->seqno)) +	if (dma_fence_is_signaled(submit->out_fence))  		return;  	/* diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 94529aa82339..aef487dd8731 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -164,13 +164,6 @@ static u32 decon_get_frame_count(struct decon_context *ctx, bool end)  	return frm;  } -static u32 decon_get_vblank_counter(struct exynos_drm_crtc *crtc) -{ -	struct decon_context *ctx = crtc->ctx; - -	return decon_get_frame_count(ctx, false); -} -  static void decon_setup_trigger(struct decon_context *ctx)  {  	if (!ctx->crtc->i80_mode && !(ctx->out_type & I80_HW_TRG)) @@ -536,7 +529,6 @@ static const struct exynos_drm_crtc_ops decon_crtc_ops = {  	.disable		= decon_disable,  	.enable_vblank		= decon_enable_vblank,  	.disable_vblank		= decon_disable_vblank, -	.get_vblank_counter	= decon_get_vblank_counter,  	.atomic_begin		= decon_atomic_begin,  	.update_plane		= decon_update_plane,  	.disable_plane		= decon_disable_plane, @@ -554,7 +546,6 @@ static int decon_bind(struct device *dev, struct device *master, void *data)  	int ret;  	ctx->drm_dev = drm_dev; -	drm_dev->max_vblank_count = 0xffffffff;  	for (win = ctx->first_win; win < WINDOWS_NR; win++) {  		ctx->configs[win].pixel_formats = decon_formats; diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c index eea90251808f..2696289ecc78 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c +++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c @@ -162,16 +162,6 @@ static void exynos_drm_crtc_disable_vblank(struct drm_crtc *crtc)  		exynos_crtc->ops->disable_vblank(exynos_crtc);  } -static u32 exynos_drm_crtc_get_vblank_counter(struct drm_crtc *crtc) -{ -	struct exynos_drm_crtc *exynos_crtc = to_exynos_crtc(crtc); - -	if (exynos_crtc->ops->get_vblank_counter) -		return exynos_crtc->ops->get_vblank_counter(exynos_crtc); - -	return 0; -} -  static const struct drm_crtc_funcs exynos_crtc_funcs = {  	.set_config	= drm_atomic_helper_set_config,  	.page_flip	= drm_atomic_helper_page_flip, @@ -181,7 +171,6 @@ static const struct drm_crtc_funcs exynos_crtc_funcs = {  	.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,  	.enable_vblank = exynos_drm_crtc_enable_vblank,  	.disable_vblank = exynos_drm_crtc_disable_vblank, -	.get_vblank_counter = exynos_drm_crtc_get_vblank_counter,  };  struct exynos_drm_crtc *exynos_drm_crtc_create(struct drm_device *drm_dev, diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index ec9604f1272b..5e61e707f955 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h @@ -135,7 +135,6 @@ struct exynos_drm_crtc_ops {  	void (*disable)(struct exynos_drm_crtc *crtc);  	int (*enable_vblank)(struct exynos_drm_crtc *crtc);  	void (*disable_vblank)(struct exynos_drm_crtc *crtc); -	u32 (*get_vblank_counter)(struct exynos_drm_crtc *crtc);  	enum drm_mode_status (*mode_valid)(struct exynos_drm_crtc *crtc,  		const struct drm_display_mode *mode);  	bool (*mode_fixup)(struct exynos_drm_crtc *crtc, diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c index 07af7758066d..d81e62ae286a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c @@ -14,6 +14,7 @@  #include <drm/drmP.h>  #include <drm/drm_crtc_helper.h> +#include <drm/drm_fb_helper.h>  #include <drm/drm_mipi_dsi.h>  #include <drm/drm_panel.h>  #include <drm/drm_atomic_helper.h> @@ -1474,12 +1475,12 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)  {  	struct exynos_dsi *dsi = encoder_to_dsi(encoder);  	struct drm_connector *connector = &dsi->connector; +	struct drm_device *drm = encoder->dev;  	int ret;  	connector->polled = DRM_CONNECTOR_POLL_HPD; -	ret = drm_connector_init(encoder->dev, connector, -				 &exynos_dsi_connector_funcs, +	ret = drm_connector_init(drm, connector, &exynos_dsi_connector_funcs,  				 DRM_MODE_CONNECTOR_DSI);  	if (ret) {  		DRM_ERROR("Failed to initialize connector with drm\n"); @@ -1489,7 +1490,12 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)  	connector->status = connector_status_disconnected;  	drm_connector_helper_add(connector, &exynos_dsi_connector_helper_funcs);  	drm_connector_attach_encoder(connector, encoder); +	if (!drm->registered) +		return 0; +	connector->funcs->reset(connector); +	drm_fb_helper_add_one_connector(drm->fb_helper, connector); +	drm_connector_register(connector);  	return 0;  } @@ -1527,7 +1533,9 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,  		}  		dsi->panel = of_drm_find_panel(device->dev.of_node); -		if (dsi->panel) { +		if (IS_ERR(dsi->panel)) { +			dsi->panel = NULL; +		} else {  			drm_panel_attach(dsi->panel, &dsi->connector);  			dsi->connector.status = connector_status_connected;  		} diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c index 918dd2c82209..01d182289efa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c @@ -192,7 +192,7 @@ int exynos_drm_fbdev_init(struct drm_device *dev)  	struct drm_fb_helper *helper;  	int ret; -	if (!dev->mode_config.num_crtc || !dev->mode_config.num_connector) +	if (!dev->mode_config.num_crtc)  		return 0;  	fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); diff --git a/drivers/gpu/drm/i915/gvt/aperture_gm.c b/drivers/gpu/drm/i915/gvt/aperture_gm.c index fe754022e356..359d37d5c958 100644 --- a/drivers/gpu/drm/i915/gvt/aperture_gm.c +++ b/drivers/gpu/drm/i915/gvt/aperture_gm.c @@ -61,10 +61,12 @@ static int alloc_gm(struct intel_vgpu *vgpu, bool high_gm)  	}  	mutex_lock(&dev_priv->drm.struct_mutex); +	mmio_hw_access_pre(dev_priv);  	ret = i915_gem_gtt_insert(&dev_priv->ggtt.vm, node,  				  size, I915_GTT_PAGE_SIZE,  				  I915_COLOR_UNEVICTABLE,  				  start, end, flags); +	mmio_hw_access_post(dev_priv);  	mutex_unlock(&dev_priv->drm.struct_mutex);  	if (ret)  		gvt_err("fail to alloc %s gm space from host\n", diff --git a/drivers/gpu/drm/i915/gvt/gtt.c b/drivers/gpu/drm/i915/gvt/gtt.c index 2402395a068d..c7103dd2d8d5 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.c +++ b/drivers/gpu/drm/i915/gvt/gtt.c @@ -1905,7 +1905,6 @@ static struct intel_vgpu_mm *intel_vgpu_create_ggtt_mm(struct intel_vgpu *vgpu)  		vgpu_free_mm(mm);  		return ERR_PTR(-ENOMEM);  	} -	mm->ggtt_mm.last_partial_off = -1UL;  	return mm;  } @@ -1930,7 +1929,6 @@ void _intel_vgpu_mm_release(struct kref *mm_ref)  		invalidate_ppgtt_mm(mm);  	} else {  		vfree(mm->ggtt_mm.virtual_ggtt); -		mm->ggtt_mm.last_partial_off = -1UL;  	}  	vgpu_free_mm(mm); @@ -2168,6 +2166,8 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,  	struct intel_gvt_gtt_entry e, m;  	dma_addr_t dma_addr;  	int ret; +	struct intel_gvt_partial_pte *partial_pte, *pos, *n; +	bool partial_update = false;  	if (bytes != 4 && bytes != 8)  		return -EINVAL; @@ -2178,68 +2178,57 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,  	if (!vgpu_gmadr_is_valid(vgpu, gma))  		return 0; -	ggtt_get_guest_entry(ggtt_mm, &e, g_gtt_index); - +	e.type = GTT_TYPE_GGTT_PTE;  	memcpy((void *)&e.val64 + (off & (info->gtt_entry_size - 1)), p_data,  			bytes);  	/* If ggtt entry size is 8 bytes, and it's split into two 4 bytes -	 * write, we assume the two 4 bytes writes are consecutive. -	 * Otherwise, we abort and report error +	 * write, save the first 4 bytes in a list and update virtual +	 * PTE. Only update shadow PTE when the second 4 bytes comes.  	 */  	if (bytes < info->gtt_entry_size) { -		if (ggtt_mm->ggtt_mm.last_partial_off == -1UL) { -			/* the first partial part*/ -			ggtt_mm->ggtt_mm.last_partial_off = off; -			ggtt_mm->ggtt_mm.last_partial_data = e.val64; -			return 0; -		} else if ((g_gtt_index == -				(ggtt_mm->ggtt_mm.last_partial_off >> -				info->gtt_entry_size_shift)) && -			(off !=	ggtt_mm->ggtt_mm.last_partial_off)) { -			/* the second partial part */ - -			int last_off = ggtt_mm->ggtt_mm.last_partial_off & -				(info->gtt_entry_size - 1); - -			memcpy((void *)&e.val64 + last_off, -				(void *)&ggtt_mm->ggtt_mm.last_partial_data + -				last_off, bytes); - -			ggtt_mm->ggtt_mm.last_partial_off = -1UL; -		} else { -			int last_offset; - -			gvt_vgpu_err("failed to populate guest ggtt entry: abnormal ggtt entry write sequence, last_partial_off=%lx, offset=%x, bytes=%d, ggtt entry size=%d\n", -					ggtt_mm->ggtt_mm.last_partial_off, off, -					bytes, info->gtt_entry_size); - -			/* set host ggtt entry to scratch page and clear -			 * virtual ggtt entry as not present for last -			 * partially write offset -			 */ -			last_offset = ggtt_mm->ggtt_mm.last_partial_off & -					(~(info->gtt_entry_size - 1)); - -			ggtt_get_host_entry(ggtt_mm, &m, last_offset); -			ggtt_invalidate_pte(vgpu, &m); -			ops->set_pfn(&m, gvt->gtt.scratch_mfn); -			ops->clear_present(&m); -			ggtt_set_host_entry(ggtt_mm, &m, last_offset); -			ggtt_invalidate(gvt->dev_priv); - -			ggtt_get_guest_entry(ggtt_mm, &e, last_offset); -			ops->clear_present(&e); -			ggtt_set_guest_entry(ggtt_mm, &e, last_offset); - -			ggtt_mm->ggtt_mm.last_partial_off = off; -			ggtt_mm->ggtt_mm.last_partial_data = e.val64; +		bool found = false; + +		list_for_each_entry_safe(pos, n, +				&ggtt_mm->ggtt_mm.partial_pte_list, list) { +			if (g_gtt_index == pos->offset >> +					info->gtt_entry_size_shift) { +				if (off != pos->offset) { +					/* the second partial part*/ +					int last_off = pos->offset & +						(info->gtt_entry_size - 1); + +					memcpy((void *)&e.val64 + last_off, +						(void *)&pos->data + last_off, +						bytes); + +					list_del(&pos->list); +					kfree(pos); +					found = true; +					break; +				} + +				/* update of the first partial part */ +				pos->data = e.val64; +				ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index); +				return 0; +			} +		} -			return 0; +		if (!found) { +			/* the first partial part */ +			partial_pte = kzalloc(sizeof(*partial_pte), GFP_KERNEL); +			if (!partial_pte) +				return -ENOMEM; +			partial_pte->offset = off; +			partial_pte->data = e.val64; +			list_add_tail(&partial_pte->list, +				&ggtt_mm->ggtt_mm.partial_pte_list); +			partial_update = true;  		}  	} -	if (ops->test_present(&e)) { +	if (!partial_update && (ops->test_present(&e))) {  		gfn = ops->get_pfn(&e);  		m = e; @@ -2263,16 +2252,18 @@ static int emulate_ggtt_mmio_write(struct intel_vgpu *vgpu, unsigned int off,  		} else  			ops->set_pfn(&m, dma_addr >> PAGE_SHIFT);  	} else { -		ggtt_get_host_entry(ggtt_mm, &m, g_gtt_index); -		ggtt_invalidate_pte(vgpu, &m);  		ops->set_pfn(&m, gvt->gtt.scratch_mfn);  		ops->clear_present(&m);  	}  out: +	ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index); + +	ggtt_get_host_entry(ggtt_mm, &e, g_gtt_index); +	ggtt_invalidate_pte(vgpu, &e); +  	ggtt_set_host_entry(ggtt_mm, &m, g_gtt_index);  	ggtt_invalidate(gvt->dev_priv); -	ggtt_set_guest_entry(ggtt_mm, &e, g_gtt_index);  	return 0;  } @@ -2430,6 +2421,8 @@ int intel_vgpu_init_gtt(struct intel_vgpu *vgpu)  	intel_vgpu_reset_ggtt(vgpu, false); +	INIT_LIST_HEAD(>t->ggtt_mm->ggtt_mm.partial_pte_list); +  	return create_scratch_page_tree(vgpu);  } @@ -2454,6 +2447,15 @@ static void intel_vgpu_destroy_all_ppgtt_mm(struct intel_vgpu *vgpu)  static void intel_vgpu_destroy_ggtt_mm(struct intel_vgpu *vgpu)  { +	struct intel_gvt_partial_pte *pos, *next; + +	list_for_each_entry_safe(pos, next, +				 &vgpu->gtt.ggtt_mm->ggtt_mm.partial_pte_list, +				 list) { +		gvt_dbg_mm("partial PTE update on hold 0x%lx : 0x%llx\n", +			pos->offset, pos->data); +		kfree(pos); +	}  	intel_vgpu_destroy_mm(vgpu->gtt.ggtt_mm);  	vgpu->gtt.ggtt_mm = NULL;  } diff --git a/drivers/gpu/drm/i915/gvt/gtt.h b/drivers/gpu/drm/i915/gvt/gtt.h index 7a9b36176efb..d8cb04cc946d 100644 --- a/drivers/gpu/drm/i915/gvt/gtt.h +++ b/drivers/gpu/drm/i915/gvt/gtt.h @@ -35,7 +35,6 @@  #define _GVT_GTT_H_  #define I915_GTT_PAGE_SHIFT         12 -#define I915_GTT_PAGE_MASK		(~(I915_GTT_PAGE_SIZE - 1))  struct intel_vgpu_mm; @@ -133,6 +132,12 @@ enum intel_gvt_mm_type {  #define GVT_RING_CTX_NR_PDPS	GEN8_3LVL_PDPES +struct intel_gvt_partial_pte { +	unsigned long offset; +	u64 data; +	struct list_head list; +}; +  struct intel_vgpu_mm {  	enum intel_gvt_mm_type type;  	struct intel_vgpu *vgpu; @@ -157,8 +162,7 @@ struct intel_vgpu_mm {  		} ppgtt_mm;  		struct {  			void *virtual_ggtt; -			unsigned long last_partial_off; -			u64 last_partial_data; +			struct list_head partial_pte_list;  		} ggtt_mm;  	};  }; diff --git a/drivers/gpu/drm/i915/gvt/handlers.c b/drivers/gpu/drm/i915/gvt/handlers.c index 90f50f67909a..aa280bb07125 100644 --- a/drivers/gpu/drm/i915/gvt/handlers.c +++ b/drivers/gpu/drm/i915/gvt/handlers.c @@ -1609,7 +1609,7 @@ static int bxt_gt_disp_pwron_write(struct intel_vgpu *vgpu,  	return 0;  } -static int bxt_edp_psr_imr_iir_write(struct intel_vgpu *vgpu, +static int edp_psr_imr_iir_write(struct intel_vgpu *vgpu,  		unsigned int offset, void *p_data, unsigned int bytes)  {  	vgpu_vreg(vgpu, offset) = 0; @@ -2607,6 +2607,9 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)  	MMIO_DFH(_MMIO(0x1a178), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(_MMIO(0x1a17c), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);  	MMIO_DFH(_MMIO(0x2217c), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL); + +	MMIO_DH(EDP_PSR_IMR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write); +	MMIO_DH(EDP_PSR_IIR, D_BDW_PLUS, NULL, edp_psr_imr_iir_write);  	return 0;  } @@ -3205,9 +3208,6 @@ static int init_bxt_mmio_info(struct intel_gvt *gvt)  	MMIO_D(HSW_TVIDEO_DIP_GCP(TRANSCODER_B), D_BXT);  	MMIO_D(HSW_TVIDEO_DIP_GCP(TRANSCODER_C), D_BXT); -	MMIO_DH(EDP_PSR_IMR, D_BXT, NULL, bxt_edp_psr_imr_iir_write); -	MMIO_DH(EDP_PSR_IIR, D_BXT, NULL, bxt_edp_psr_imr_iir_write); -  	MMIO_D(RC6_CTX_BASE, D_BXT);  	MMIO_D(GEN8_PUSHBUS_CONTROL, D_BXT); diff --git a/drivers/gpu/drm/i915/gvt/mmio_context.c b/drivers/gpu/drm/i915/gvt/mmio_context.c index 10e63eea5492..d6e02c15ef97 100644 --- a/drivers/gpu/drm/i915/gvt/mmio_context.c +++ b/drivers/gpu/drm/i915/gvt/mmio_context.c @@ -131,7 +131,7 @@ static struct engine_mmio gen9_engine_mmio_list[] __cacheline_aligned = {  	{RCS, GAMT_CHKN_BIT_REG, 0x0, false}, /* 0x4ab8 */  	{RCS, GEN9_GAMT_ECO_REG_RW_IA, 0x0, false}, /* 0x4ab0 */ -	{RCS, GEN9_CSFE_CHICKEN1_RCS, 0x0, false}, /* 0x20d4 */ +	{RCS, GEN9_CSFE_CHICKEN1_RCS, 0xffff, false}, /* 0x20d4 */  	{RCS, GEN8_GARBCNTL, 0x0, false}, /* 0xb004 */  	{RCS, GEN7_FF_THREAD_MODE, 0x0, false}, /* 0x20a0 */ @@ -158,6 +158,8 @@ static void load_render_mocs(struct drm_i915_private *dev_priv)  	int ring_id, i;  	for (ring_id = 0; ring_id < ARRAY_SIZE(regs); ring_id++) { +		if (!HAS_ENGINE(dev_priv, ring_id)) +			continue;  		offset.reg = regs[ring_id];  		for (i = 0; i < GEN9_MOCS_SIZE; i++) {  			gen9_render_mocs.control_table[ring_id][i] = diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 44e2c0f5ec50..ffdbbac4400e 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -1175,8 +1175,6 @@ skl_dram_get_channels_info(struct drm_i915_private *dev_priv)  		return -EINVAL;  	} -	dram_info->valid_dimm = true; -  	/*  	 * If any of the channel is single rank channel, worst case output  	 * will be same as if single rank memory, so consider single rank @@ -1193,8 +1191,7 @@ skl_dram_get_channels_info(struct drm_i915_private *dev_priv)  		return -EINVAL;  	} -	if (ch0.is_16gb_dimm || ch1.is_16gb_dimm) -		dram_info->is_16gb_dimm = true; +	dram_info->is_16gb_dimm = ch0.is_16gb_dimm || ch1.is_16gb_dimm;  	dev_priv->dram_info.symmetric_memory = intel_is_dram_symmetric(val_ch0,  								       val_ch1, @@ -1314,7 +1311,6 @@ bxt_get_dram_info(struct drm_i915_private *dev_priv)  		return -EINVAL;  	} -	dram_info->valid_dimm = true;  	dram_info->valid = true;  	return 0;  } @@ -1327,12 +1323,17 @@ intel_get_dram_info(struct drm_i915_private *dev_priv)  	int ret;  	dram_info->valid = false; -	dram_info->valid_dimm = false; -	dram_info->is_16gb_dimm = false;  	dram_info->rank = I915_DRAM_RANK_INVALID;  	dram_info->bandwidth_kbps = 0;  	dram_info->num_channels = 0; +	/* +	 * Assume 16Gb DIMMs are present until proven otherwise. +	 * This is only used for the level 0 watermark latency +	 * w/a which does not apply to bxt/glk. +	 */ +	dram_info->is_16gb_dimm = !IS_GEN9_LP(dev_priv); +  	if (INTEL_GEN(dev_priv) < 9 || IS_GEMINILAKE(dev_priv))  		return; diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 8624b4bdc242..9102571e9692 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -1948,7 +1948,6 @@ struct drm_i915_private {  	struct dram_info {  		bool valid; -		bool valid_dimm;  		bool is_16gb_dimm;  		u8 num_channels;  		enum dram_rank { diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 09187286d346..d4fac09095f8 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c @@ -460,7 +460,7 @@ eb_validate_vma(struct i915_execbuffer *eb,  	 * any non-page-aligned or non-canonical addresses.  	 */  	if (unlikely(entry->flags & EXEC_OBJECT_PINNED && -		     entry->offset != gen8_canonical_addr(entry->offset & PAGE_MASK))) +		     entry->offset != gen8_canonical_addr(entry->offset & I915_GTT_PAGE_MASK)))  		return -EINVAL;  	/* pad_to_size was once a reserved field, so sanitize it */ @@ -1268,7 +1268,7 @@ relocate_entry(struct i915_vma *vma,  		else if (gen >= 4)  			len = 4;  		else -			len = 3; +			len = 6;  		batch = reloc_gpu(eb, vma, len);  		if (IS_ERR(batch)) @@ -1309,6 +1309,11 @@ relocate_entry(struct i915_vma *vma,  			*batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL;  			*batch++ = addr;  			*batch++ = target_offset; + +			/* And again for good measure (blb/pnv) */ +			*batch++ = MI_STORE_DWORD_IMM | MI_MEM_VIRTUAL; +			*batch++ = addr; +			*batch++ = target_offset;  		}  		goto out; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.c b/drivers/gpu/drm/i915/i915_gem_gtt.c index 56c7f8637311..07999fe09ad2 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/i915_gem_gtt.c @@ -1757,7 +1757,7 @@ static void gen6_dump_ppgtt(struct i915_hw_ppgtt *base, struct seq_file *m)  			if (i == 4)  				continue; -			seq_printf(m, "\t\t(%03d, %04d) %08lx: ", +			seq_printf(m, "\t\t(%03d, %04d) %08llx: ",  				   pde, pte,  				   (pde * GEN6_PTES + pte) * I915_GTT_PAGE_SIZE);  			for (i = 0; i < 4; i++) { @@ -3413,6 +3413,11 @@ static int gen8_gmch_probe(struct i915_ggtt *ggtt)  		ggtt->vm.insert_page    = bxt_vtd_ggtt_insert_page__BKL;  		if (ggtt->vm.clear_range != nop_clear_range)  			ggtt->vm.clear_range = bxt_vtd_ggtt_clear_range__BKL; + +		/* Prevent recursively calling stop_machine() and deadlocks. */ +		dev_info(dev_priv->drm.dev, +			 "Disabling error capture for VT-d workaround\n"); +		i915_disable_error_state(dev_priv, -ENODEV);  	}  	ggtt->invalidate = gen6_ggtt_invalidate; diff --git a/drivers/gpu/drm/i915/i915_gem_gtt.h b/drivers/gpu/drm/i915/i915_gem_gtt.h index 7e2af5f4f39b..28039290655c 100644 --- a/drivers/gpu/drm/i915/i915_gem_gtt.h +++ b/drivers/gpu/drm/i915/i915_gem_gtt.h @@ -42,13 +42,15 @@  #include "i915_selftest.h"  #include "i915_timeline.h" -#define I915_GTT_PAGE_SIZE_4K BIT(12) -#define I915_GTT_PAGE_SIZE_64K BIT(16) -#define I915_GTT_PAGE_SIZE_2M BIT(21) +#define I915_GTT_PAGE_SIZE_4K	BIT_ULL(12) +#define I915_GTT_PAGE_SIZE_64K	BIT_ULL(16) +#define I915_GTT_PAGE_SIZE_2M	BIT_ULL(21)  #define I915_GTT_PAGE_SIZE I915_GTT_PAGE_SIZE_4K  #define I915_GTT_MAX_PAGE_SIZE I915_GTT_PAGE_SIZE_2M +#define I915_GTT_PAGE_MASK -I915_GTT_PAGE_SIZE +  #define I915_GTT_MIN_ALIGNMENT I915_GTT_PAGE_SIZE  #define I915_FENCE_REG_NONE -1 @@ -659,20 +661,20 @@ int i915_gem_gtt_insert(struct i915_address_space *vm,  			u64 start, u64 end, unsigned int flags);  /* Flags used by pin/bind&friends. */ -#define PIN_NONBLOCK		BIT(0) -#define PIN_MAPPABLE		BIT(1) -#define PIN_ZONE_4G		BIT(2) -#define PIN_NONFAULT		BIT(3) -#define PIN_NOEVICT		BIT(4) - -#define PIN_MBZ			BIT(5) /* I915_VMA_PIN_OVERFLOW */ -#define PIN_GLOBAL		BIT(6) /* I915_VMA_GLOBAL_BIND */ -#define PIN_USER		BIT(7) /* I915_VMA_LOCAL_BIND */ -#define PIN_UPDATE		BIT(8) - -#define PIN_HIGH		BIT(9) -#define PIN_OFFSET_BIAS		BIT(10) -#define PIN_OFFSET_FIXED	BIT(11) +#define PIN_NONBLOCK		BIT_ULL(0) +#define PIN_MAPPABLE		BIT_ULL(1) +#define PIN_ZONE_4G		BIT_ULL(2) +#define PIN_NONFAULT		BIT_ULL(3) +#define PIN_NOEVICT		BIT_ULL(4) + +#define PIN_MBZ			BIT_ULL(5) /* I915_VMA_PIN_OVERFLOW */ +#define PIN_GLOBAL		BIT_ULL(6) /* I915_VMA_GLOBAL_BIND */ +#define PIN_USER		BIT_ULL(7) /* I915_VMA_LOCAL_BIND */ +#define PIN_UPDATE		BIT_ULL(8) + +#define PIN_HIGH		BIT_ULL(9) +#define PIN_OFFSET_BIAS		BIT_ULL(10) +#define PIN_OFFSET_FIXED	BIT_ULL(11)  #define PIN_OFFSET_MASK		(-I915_GTT_PAGE_SIZE)  #endif diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c index 8762d17b6659..3eb33e000d6f 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.c +++ b/drivers/gpu/drm/i915/i915_gpu_error.c @@ -648,6 +648,9 @@ int i915_error_state_to_str(struct drm_i915_error_state_buf *m,  		return 0;  	} +	if (IS_ERR(error)) +		return PTR_ERR(error); +  	if (*error->error_msg)  		err_printf(m, "%s\n", error->error_msg);  	err_printf(m, "Kernel: " UTS_RELEASE "\n"); @@ -1859,6 +1862,7 @@ void i915_capture_error_state(struct drm_i915_private *i915,  	error = i915_capture_gpu_state(i915);  	if (!error) {  		DRM_DEBUG_DRIVER("out of memory, not capturing error state\n"); +		i915_disable_error_state(i915, -ENOMEM);  		return;  	} @@ -1914,5 +1918,14 @@ void i915_reset_error_state(struct drm_i915_private *i915)  	i915->gpu_error.first_error = NULL;  	spin_unlock_irq(&i915->gpu_error.lock); -	i915_gpu_state_put(error); +	if (!IS_ERR(error)) +		i915_gpu_state_put(error); +} + +void i915_disable_error_state(struct drm_i915_private *i915, int err) +{ +	spin_lock_irq(&i915->gpu_error.lock); +	if (!i915->gpu_error.first_error) +		i915->gpu_error.first_error = ERR_PTR(err); +	spin_unlock_irq(&i915->gpu_error.lock);  } diff --git a/drivers/gpu/drm/i915/i915_gpu_error.h b/drivers/gpu/drm/i915/i915_gpu_error.h index 8710fb18ed74..3ec89a504de5 100644 --- a/drivers/gpu/drm/i915/i915_gpu_error.h +++ b/drivers/gpu/drm/i915/i915_gpu_error.h @@ -343,6 +343,7 @@ static inline void i915_gpu_state_put(struct i915_gpu_state *gpu)  struct i915_gpu_state *i915_first_error_state(struct drm_i915_private *i915);  void i915_reset_error_state(struct drm_i915_private *i915); +void i915_disable_error_state(struct drm_i915_private *i915, int err);  #else @@ -355,13 +356,18 @@ static inline void i915_capture_error_state(struct drm_i915_private *dev_priv,  static inline struct i915_gpu_state *  i915_first_error_state(struct drm_i915_private *i915)  { -	return NULL; +	return ERR_PTR(-ENODEV);  }  static inline void i915_reset_error_state(struct drm_i915_private *i915)  {  } +static inline void i915_disable_error_state(struct drm_i915_private *i915, +					    int err) +{ +} +  #endif /* IS_ENABLED(CONFIG_DRM_I915_CAPTURE_ERROR) */  #endif /* _I915_GPU_ERROR_H_ */ diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 7c491ea3d052..e31c27e45734 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -2095,8 +2095,12 @@ enum i915_power_well_id {  /* ICL PHY DFLEX registers */  #define PORT_TX_DFLEXDPMLE1		_MMIO(0x1638C0) -#define   DFLEXDPMLE1_DPMLETC_MASK(n)	(0xf << (4 * (n))) -#define   DFLEXDPMLE1_DPMLETC(n, x)	((x) << (4 * (n))) +#define   DFLEXDPMLE1_DPMLETC_MASK(tc_port)	(0xf << (4 * (tc_port))) +#define   DFLEXDPMLE1_DPMLETC_ML0(tc_port)	(1 << (4 * (tc_port))) +#define   DFLEXDPMLE1_DPMLETC_ML1_0(tc_port)	(3 << (4 * (tc_port))) +#define   DFLEXDPMLE1_DPMLETC_ML3(tc_port)	(8 << (4 * (tc_port))) +#define   DFLEXDPMLE1_DPMLETC_ML3_2(tc_port)	(12 << (4 * (tc_port))) +#define   DFLEXDPMLE1_DPMLETC_ML3_0(tc_port)	(15 << (4 * (tc_port)))  /* BXT PHY Ref registers */  #define _PORT_REF_DW3_A			0x16218C @@ -4593,12 +4597,12 @@ enum {  #define  DRM_DIP_ENABLE			(1 << 28)  #define  PSR_VSC_BIT_7_SET		(1 << 27) -#define  VSC_SELECT_MASK		(0x3 << 26) -#define  VSC_SELECT_SHIFT		26 -#define  VSC_DIP_HW_HEA_DATA		(0 << 26) -#define  VSC_DIP_HW_HEA_SW_DATA		(1 << 26) -#define  VSC_DIP_HW_DATA_SW_HEA		(2 << 26) -#define  VSC_DIP_SW_HEA_DATA		(3 << 26) +#define  VSC_SELECT_MASK		(0x3 << 25) +#define  VSC_SELECT_SHIFT		25 +#define  VSC_DIP_HW_HEA_DATA		(0 << 25) +#define  VSC_DIP_HW_HEA_SW_DATA		(1 << 25) +#define  VSC_DIP_HW_DATA_SW_HEA		(2 << 25) +#define  VSC_DIP_SW_HEA_DATA		(3 << 25)  #define  VDIP_ENABLE_PPS		(1 << 24)  /* Panel power sequencing */ diff --git a/drivers/gpu/drm/i915/intel_audio.c b/drivers/gpu/drm/i915/intel_audio.c index 769f3f586661..ee3ca2de983b 100644 --- a/drivers/gpu/drm/i915/intel_audio.c +++ b/drivers/gpu/drm/i915/intel_audio.c @@ -144,6 +144,9 @@ static const struct {  /* HDMI N/CTS table */  #define TMDS_297M 297000  #define TMDS_296M 296703 +#define TMDS_594M 594000 +#define TMDS_593M 593407 +  static const struct {  	int sample_rate;  	int clock; @@ -164,6 +167,20 @@ static const struct {  	{ 176400, TMDS_297M, 18816, 247500 },  	{ 192000, TMDS_296M, 23296, 281250 },  	{ 192000, TMDS_297M, 20480, 247500 }, +	{ 44100, TMDS_593M, 8918, 937500 }, +	{ 44100, TMDS_594M, 9408, 990000 }, +	{ 48000, TMDS_593M, 5824, 562500 }, +	{ 48000, TMDS_594M, 6144, 594000 }, +	{ 32000, TMDS_593M, 5824, 843750 }, +	{ 32000, TMDS_594M, 3072, 445500 }, +	{ 88200, TMDS_593M, 17836, 937500 }, +	{ 88200, TMDS_594M, 18816, 990000 }, +	{ 96000, TMDS_593M, 11648, 562500 }, +	{ 96000, TMDS_594M, 12288, 594000 }, +	{ 176400, TMDS_593M, 35672, 937500 }, +	{ 176400, TMDS_594M, 37632, 990000 }, +	{ 192000, TMDS_593M, 23296, 562500 }, +	{ 192000, TMDS_594M, 24576, 594000 },  };  /* get AUD_CONFIG_PIXEL_CLOCK_HDMI_* value for mode */ diff --git a/drivers/gpu/drm/i915/intel_cdclk.c b/drivers/gpu/drm/i915/intel_cdclk.c index 29075c763428..8d74276029e6 100644 --- a/drivers/gpu/drm/i915/intel_cdclk.c +++ b/drivers/gpu/drm/i915/intel_cdclk.c @@ -2138,16 +2138,8 @@ void intel_set_cdclk(struct drm_i915_private *dev_priv,  static int intel_pixel_rate_to_cdclk(struct drm_i915_private *dev_priv,  				     int pixel_rate)  { -	if (INTEL_GEN(dev_priv) >= 10) +	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))  		return DIV_ROUND_UP(pixel_rate, 2); -	else if (IS_GEMINILAKE(dev_priv)) -		/* -		 * FIXME: Avoid using a pixel clock that is more than 99% of the cdclk -		 * as a temporary workaround. Use a higher cdclk instead. (Note that -		 * intel_compute_max_dotclk() limits the max pixel clock to 99% of max -		 * cdclk.) -		 */ -		return DIV_ROUND_UP(pixel_rate * 100, 2 * 99);  	else if (IS_GEN9(dev_priv) ||  		 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))  		return pixel_rate; @@ -2543,14 +2535,8 @@ static int intel_compute_max_dotclk(struct drm_i915_private *dev_priv)  {  	int max_cdclk_freq = dev_priv->max_cdclk_freq; -	if (INTEL_GEN(dev_priv) >= 10) +	if (INTEL_GEN(dev_priv) >= 10 || IS_GEMINILAKE(dev_priv))  		return 2 * max_cdclk_freq; -	else if (IS_GEMINILAKE(dev_priv)) -		/* -		 * FIXME: Limiting to 99% as a temporary workaround. See -		 * intel_min_cdclk() for details. -		 */ -		return 2 * max_cdclk_freq * 99 / 100;  	else if (IS_GEN9(dev_priv) ||  		 IS_BROADWELL(dev_priv) || IS_HASWELL(dev_priv))  		return max_cdclk_freq; diff --git a/drivers/gpu/drm/i915/intel_device_info.c b/drivers/gpu/drm/i915/intel_device_info.c index 0ef0c6448d53..01fa98299bae 100644 --- a/drivers/gpu/drm/i915/intel_device_info.c +++ b/drivers/gpu/drm/i915/intel_device_info.c @@ -474,7 +474,7 @@ static void broadwell_sseu_info_init(struct drm_i915_private *dev_priv)  			u8 eu_disabled_mask;  			u32 n_disabled; -			if (!(sseu->subslice_mask[ss] & BIT(ss))) +			if (!(sseu->subslice_mask[s] & BIT(ss)))  				/* skip disabled subslice */  				continue; diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 9741cc419e1b..c9878dd1f7cd 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -2890,6 +2890,7 @@ intel_find_initial_plane_obj(struct intel_crtc *intel_crtc,  	return;  valid_fb: +	intel_state->base.rotation = plane_config->rotation;  	intel_fill_fb_ggtt_view(&intel_state->view, fb,  				intel_state->base.rotation);  	intel_state->color_plane[0].stride = @@ -4850,8 +4851,31 @@ static void cpt_verify_modeset(struct drm_device *dev, int pipe)   * chroma samples for both of the luma samples, and thus we don't   * actually get the expected MPEG2 chroma siting convention :(   * The same behaviour is observed on pre-SKL platforms as well. + * + * Theory behind the formula (note that we ignore sub-pixel + * source coordinates): + * s = source sample position + * d = destination sample position + * + * Downscaling 4:1: + * -0.5 + * | 0.0 + * | |     1.5 (initial phase) + * | |     | + * v v     v + * | s | s | s | s | + * |       d       | + * + * Upscaling 1:4: + * -0.5 + * | -0.375 (initial phase) + * | |     0.0 + * | |     | + * v v     v + * |       s       | + * | d | d | d | d |   */ -u16 skl_scaler_calc_phase(int sub, bool chroma_cosited) +u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_cosited)  {  	int phase = -0x8000;  	u16 trip = 0; @@ -4859,6 +4883,15 @@ u16 skl_scaler_calc_phase(int sub, bool chroma_cosited)  	if (chroma_cosited)  		phase += (sub - 1) * 0x8000 / sub; +	phase += scale / (2 * sub); + +	/* +	 * Hardware initial phase limited to [-0.5:1.5]. +	 * Since the max hardware scale factor is 3.0, we +	 * should never actually excdeed 1.0 here. +	 */ +	WARN_ON(phase < -0x8000 || phase > 0x18000); +  	if (phase < 0)  		phase = 0x10000 + phase;  	else @@ -5067,13 +5100,20 @@ static void skylake_pfit_enable(struct intel_crtc *crtc)  	if (crtc->config->pch_pfit.enabled) {  		u16 uv_rgb_hphase, uv_rgb_vphase; +		int pfit_w, pfit_h, hscale, vscale;  		int id;  		if (WARN_ON(crtc->config->scaler_state.scaler_id < 0))  			return; -		uv_rgb_hphase = skl_scaler_calc_phase(1, false); -		uv_rgb_vphase = skl_scaler_calc_phase(1, false); +		pfit_w = (crtc->config->pch_pfit.size >> 16) & 0xFFFF; +		pfit_h = crtc->config->pch_pfit.size & 0xFFFF; + +		hscale = (crtc->config->pipe_src_w << 16) / pfit_w; +		vscale = (crtc->config->pipe_src_h << 16) / pfit_h; + +		uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false); +		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false);  		id = scaler_state->scaler_id;  		I915_WRITE(SKL_PS_CTRL(pipe, id), PS_SCALER_EN | @@ -7843,8 +7883,15 @@ i9xx_get_initial_plane_config(struct intel_crtc *crtc,  			plane_config->tiling = I915_TILING_X;  			fb->modifier = I915_FORMAT_MOD_X_TILED;  		} + +		if (val & DISPPLANE_ROTATE_180) +			plane_config->rotation = DRM_MODE_ROTATE_180;  	} +	if (IS_CHERRYVIEW(dev_priv) && pipe == PIPE_B && +	    val & DISPPLANE_MIRROR) +		plane_config->rotation |= DRM_MODE_REFLECT_X; +  	pixel_format = val & DISPPLANE_PIXFORMAT_MASK;  	fourcc = i9xx_format_to_fourcc(pixel_format);  	fb->format = drm_format_info(fourcc); @@ -8913,6 +8960,29 @@ skylake_get_initial_plane_config(struct intel_crtc *crtc,  		goto error;  	} +	/* +	 * DRM_MODE_ROTATE_ is counter clockwise to stay compatible with Xrandr +	 * while i915 HW rotation is clockwise, thats why this swapping. +	 */ +	switch (val & PLANE_CTL_ROTATE_MASK) { +	case PLANE_CTL_ROTATE_0: +		plane_config->rotation = DRM_MODE_ROTATE_0; +		break; +	case PLANE_CTL_ROTATE_90: +		plane_config->rotation = DRM_MODE_ROTATE_270; +		break; +	case PLANE_CTL_ROTATE_180: +		plane_config->rotation = DRM_MODE_ROTATE_180; +		break; +	case PLANE_CTL_ROTATE_270: +		plane_config->rotation = DRM_MODE_ROTATE_90; +		break; +	} + +	if (INTEL_GEN(dev_priv) >= 10 && +	    val & PLANE_CTL_FLIP_HORIZONTAL) +		plane_config->rotation |= DRM_MODE_REFLECT_X; +  	base = I915_READ(PLANE_SURF(pipe, plane_id)) & 0xfffff000;  	plane_config->base = base; @@ -12768,17 +12838,12 @@ static void intel_atomic_commit_tail(struct drm_atomic_state *state)  			intel_check_cpu_fifo_underruns(dev_priv);  			intel_check_pch_fifo_underruns(dev_priv); -			if (!new_crtc_state->active) { -				/* -				 * Make sure we don't call initial_watermarks -				 * for ILK-style watermark updates. -				 * -				 * No clue what this is supposed to achieve. -				 */ -				if (INTEL_GEN(dev_priv) >= 9) -					dev_priv->display.initial_watermarks(intel_state, -									     to_intel_crtc_state(new_crtc_state)); -			} +			/* FIXME unify this for all platforms */ +			if (!new_crtc_state->active && +			    !HAS_GMCH_DISPLAY(dev_priv) && +			    dev_priv->display.initial_watermarks) +				dev_priv->display.initial_watermarks(intel_state, +								     to_intel_crtc_state(new_crtc_state));  		}  	} @@ -14646,7 +14711,7 @@ static int intel_framebuffer_init(struct intel_framebuffer *intel_fb,  	     fb->height < SKL_MIN_YUV_420_SRC_H ||  	     (fb->width % 4) != 0 || (fb->height % 4) != 0)) {  		DRM_DEBUG_KMS("src dimensions not correct for NV12\n"); -		return -EINVAL; +		goto err;  	}  	for (i = 0; i < fb->format->num_planes; i++) { @@ -15233,6 +15298,14 @@ retry:  			ret = drm_atomic_add_affected_planes(state, crtc);  			if (ret)  				goto out; + +			/* +			 * FIXME hack to force a LUT update to avoid the +			 * plane update forcing the pipe gamma on without +			 * having a proper LUT loaded. Remove once we +			 * have readout for pipe gamma enable. +			 */ +			crtc_state->color_mgmt_changed = true;  		}  	} diff --git a/drivers/gpu/drm/i915/intel_dp_mst.c b/drivers/gpu/drm/i915/intel_dp_mst.c index 1b00f8ea145b..a911691dbd0f 100644 --- a/drivers/gpu/drm/i915/intel_dp_mst.c +++ b/drivers/gpu/drm/i915/intel_dp_mst.c @@ -452,6 +452,10 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo  	if (!intel_connector)  		return NULL; +	intel_connector->get_hw_state = intel_dp_mst_get_hw_state; +	intel_connector->mst_port = intel_dp; +	intel_connector->port = port; +  	connector = &intel_connector->base;  	ret = drm_connector_init(dev, connector, &intel_dp_mst_connector_funcs,  				 DRM_MODE_CONNECTOR_DisplayPort); @@ -462,10 +466,6 @@ static struct drm_connector *intel_dp_add_mst_connector(struct drm_dp_mst_topolo  	drm_connector_helper_add(connector, &intel_dp_mst_connector_helper_funcs); -	intel_connector->get_hw_state = intel_dp_mst_get_hw_state; -	intel_connector->mst_port = intel_dp; -	intel_connector->port = port; -  	for_each_pipe(dev_priv, pipe) {  		struct drm_encoder *enc =  			&intel_dp->mst_encoders[pipe]->base.base; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index f8dc84b2d2d3..db6fa1d0cbda 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -547,6 +547,7 @@ struct intel_initial_plane_config {  	unsigned int tiling;  	int size;  	u32 base; +	u8 rotation;  };  #define SKL_MIN_SRC_W 8 @@ -1646,7 +1647,7 @@ void intel_mode_from_pipe_config(struct drm_display_mode *mode,  void intel_crtc_arm_fifo_underrun(struct intel_crtc *crtc,  				  struct intel_crtc_state *crtc_state); -u16 skl_scaler_calc_phase(int sub, bool chroma_center); +u16 skl_scaler_calc_phase(int sub, int scale, bool chroma_center);  int skl_update_scaler_crtc(struct intel_crtc_state *crtc_state);  int skl_max_scale(const struct intel_crtc_state *crtc_state,  		  u32 pixel_format); diff --git a/drivers/gpu/drm/i915/intel_hotplug.c b/drivers/gpu/drm/i915/intel_hotplug.c index 648a13c6043c..9a8018130237 100644 --- a/drivers/gpu/drm/i915/intel_hotplug.c +++ b/drivers/gpu/drm/i915/intel_hotplug.c @@ -228,7 +228,9 @@ static void intel_hpd_irq_storm_reenable_work(struct work_struct *work)  		drm_for_each_connector_iter(connector, &conn_iter) {  			struct intel_connector *intel_connector = to_intel_connector(connector); -			if (intel_connector->encoder->hpd_pin == pin) { +			/* Don't check MST ports, they don't have pins */ +			if (!intel_connector->mst_port && +			    intel_connector->encoder->hpd_pin == pin) {  				if (connector->polled != intel_connector->polled)  					DRM_DEBUG_DRIVER("Reenabling HPD on connector %s\n",  							 connector->name); @@ -395,37 +397,54 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,  	struct intel_encoder *encoder;  	bool storm_detected = false;  	bool queue_dig = false, queue_hp = false; +	u32 long_hpd_pulse_mask = 0; +	u32 short_hpd_pulse_mask = 0; +	enum hpd_pin pin;  	if (!pin_mask)  		return;  	spin_lock(&dev_priv->irq_lock); + +	/* +	 * Determine whether ->hpd_pulse() exists for each pin, and +	 * whether we have a short or a long pulse. This is needed +	 * as each pin may have up to two encoders (HDMI and DP) and +	 * only the one of them (DP) will have ->hpd_pulse(). +	 */  	for_each_intel_encoder(&dev_priv->drm, encoder) { -		enum hpd_pin pin = encoder->hpd_pin;  		bool has_hpd_pulse = intel_encoder_has_hpd_pulse(encoder); +		enum port port = encoder->port; +		bool long_hpd; +		pin = encoder->hpd_pin;  		if (!(BIT(pin) & pin_mask))  			continue; -		if (has_hpd_pulse) { -			bool long_hpd = long_mask & BIT(pin); -			enum port port = encoder->port; +		if (!has_hpd_pulse) +			continue; -			DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port), -					 long_hpd ? "long" : "short"); -			/* -			 * For long HPD pulses we want to have the digital queue happen, -			 * but we still want HPD storm detection to function. -			 */ -			queue_dig = true; -			if (long_hpd) { -				dev_priv->hotplug.long_port_mask |= (1 << port); -			} else { -				/* for short HPD just trigger the digital queue */ -				dev_priv->hotplug.short_port_mask |= (1 << port); -				continue; -			} +		long_hpd = long_mask & BIT(pin); + +		DRM_DEBUG_DRIVER("digital hpd port %c - %s\n", port_name(port), +				 long_hpd ? "long" : "short"); +		queue_dig = true; + +		if (long_hpd) { +			long_hpd_pulse_mask |= BIT(pin); +			dev_priv->hotplug.long_port_mask |= BIT(port); +		} else { +			short_hpd_pulse_mask |= BIT(pin); +			dev_priv->hotplug.short_port_mask |= BIT(port);  		} +	} + +	/* Now process each pin just once */ +	for_each_hpd_pin(pin) { +		bool long_hpd; + +		if (!(BIT(pin) & pin_mask)) +			continue;  		if (dev_priv->hotplug.stats[pin].state == HPD_DISABLED) {  			/* @@ -442,11 +461,22 @@ void intel_hpd_irq_handler(struct drm_i915_private *dev_priv,  		if (dev_priv->hotplug.stats[pin].state != HPD_ENABLED)  			continue; -		if (!has_hpd_pulse) { +		/* +		 * Delegate to ->hpd_pulse() if one of the encoders for this +		 * pin has it, otherwise let the hotplug_work deal with this +		 * pin directly. +		 */ +		if (((short_hpd_pulse_mask | long_hpd_pulse_mask) & BIT(pin))) { +			long_hpd = long_hpd_pulse_mask & BIT(pin); +		} else {  			dev_priv->hotplug.event_bits |= BIT(pin); +			long_hpd = true;  			queue_hp = true;  		} +		if (!long_hpd) +			continue; +  		if (intel_hpd_irq_storm_detect(dev_priv, pin)) {  			dev_priv->hotplug.event_bits &= ~BIT(pin);  			storm_detected = true; diff --git a/drivers/gpu/drm/i915/intel_lpe_audio.c b/drivers/gpu/drm/i915/intel_lpe_audio.c index cdf19553ffac..5d5336fbe7b0 100644 --- a/drivers/gpu/drm/i915/intel_lpe_audio.c +++ b/drivers/gpu/drm/i915/intel_lpe_audio.c @@ -297,8 +297,10 @@ void intel_lpe_audio_teardown(struct drm_i915_private *dev_priv)  	lpe_audio_platdev_destroy(dev_priv);  	irq_free_desc(dev_priv->lpe_audio.irq); -} +	dev_priv->lpe_audio.irq = -1; +	dev_priv->lpe_audio.platdev = NULL; +}  /**   * intel_lpe_audio_notify() - notify lpe audio event diff --git a/drivers/gpu/drm/i915/intel_lrc.c b/drivers/gpu/drm/i915/intel_lrc.c index 43957bb37a42..37c94a54efcb 100644 --- a/drivers/gpu/drm/i915/intel_lrc.c +++ b/drivers/gpu/drm/i915/intel_lrc.c @@ -424,7 +424,8 @@ static u64 execlists_update_context(struct i915_request *rq)  	reg_state[CTX_RING_TAIL+1] = intel_ring_set_tail(rq->ring, rq->tail); -	/* True 32b PPGTT with dynamic page allocation: update PDP +	/* +	 * True 32b PPGTT with dynamic page allocation: update PDP  	 * registers and point the unallocated PDPs to scratch page.  	 * PML4 is allocated during ppgtt init, so this is not needed  	 * in 48-bit mode. @@ -432,6 +433,17 @@ static u64 execlists_update_context(struct i915_request *rq)  	if (ppgtt && !i915_vm_is_48bit(&ppgtt->vm))  		execlists_update_context_pdps(ppgtt, reg_state); +	/* +	 * Make sure the context image is complete before we submit it to HW. +	 * +	 * Ostensibly, writes (including the WCB) should be flushed prior to +	 * an uncached write such as our mmio register access, the empirical +	 * evidence (esp. on Braswell) suggests that the WC write into memory +	 * may not be visible to the HW prior to the completion of the UC +	 * register write and that we may begin execution from the context +	 * before its image is complete leading to invalid PD chasing. +	 */ +	wmb();  	return ce->lrc_desc;  } diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1db9b8328275..3fe358db1276 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -2493,6 +2493,9 @@ static uint32_t ilk_compute_pri_wm(const struct intel_crtc_state *cstate,  	uint32_t method1, method2;  	int cpp; +	if (mem_value == 0) +		return U32_MAX; +  	if (!intel_wm_plane_visible(cstate, pstate))  		return 0; @@ -2522,6 +2525,9 @@ static uint32_t ilk_compute_spr_wm(const struct intel_crtc_state *cstate,  	uint32_t method1, method2;  	int cpp; +	if (mem_value == 0) +		return U32_MAX; +  	if (!intel_wm_plane_visible(cstate, pstate))  		return 0; @@ -2545,6 +2551,9 @@ static uint32_t ilk_compute_cur_wm(const struct intel_crtc_state *cstate,  {  	int cpp; +	if (mem_value == 0) +		return U32_MAX; +  	if (!intel_wm_plane_visible(cstate, pstate))  		return 0; @@ -2881,8 +2890,7 @@ static void intel_read_wm_latency(struct drm_i915_private *dev_priv,  		 * any underrun. If not able to get Dimm info assume 16GB dimm  		 * to avoid any underrun.  		 */ -		if (!dev_priv->dram_info.valid_dimm || -		    dev_priv->dram_info.is_16gb_dimm) +		if (dev_priv->dram_info.is_16gb_dimm)  			wm[0] += 1;  	} else if (IS_HASWELL(dev_priv) || IS_BROADWELL(dev_priv)) { @@ -3009,6 +3017,34 @@ static void snb_wm_latency_quirk(struct drm_i915_private *dev_priv)  	intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency);  } +static void snb_wm_lp3_irq_quirk(struct drm_i915_private *dev_priv) +{ +	/* +	 * On some SNB machines (Thinkpad X220 Tablet at least) +	 * LP3 usage can cause vblank interrupts to be lost. +	 * The DEIIR bit will go high but it looks like the CPU +	 * never gets interrupted. +	 * +	 * It's not clear whether other interrupt source could +	 * be affected or if this is somehow limited to vblank +	 * interrupts only. To play it safe we disable LP3 +	 * watermarks entirely. +	 */ +	if (dev_priv->wm.pri_latency[3] == 0 && +	    dev_priv->wm.spr_latency[3] == 0 && +	    dev_priv->wm.cur_latency[3] == 0) +		return; + +	dev_priv->wm.pri_latency[3] = 0; +	dev_priv->wm.spr_latency[3] = 0; +	dev_priv->wm.cur_latency[3] = 0; + +	DRM_DEBUG_KMS("LP3 watermarks disabled due to potential for lost interrupts\n"); +	intel_print_wm_latency(dev_priv, "Primary", dev_priv->wm.pri_latency); +	intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency); +	intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); +} +  static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)  {  	intel_read_wm_latency(dev_priv, dev_priv->wm.pri_latency); @@ -3025,8 +3061,10 @@ static void ilk_setup_wm_latency(struct drm_i915_private *dev_priv)  	intel_print_wm_latency(dev_priv, "Sprite", dev_priv->wm.spr_latency);  	intel_print_wm_latency(dev_priv, "Cursor", dev_priv->wm.cur_latency); -	if (IS_GEN6(dev_priv)) +	if (IS_GEN6(dev_priv)) {  		snb_wm_latency_quirk(dev_priv); +		snb_wm_lp3_irq_quirk(dev_priv); +	}  }  static void skl_setup_wm_latency(struct drm_i915_private *dev_priv) diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index d0ef50bf930a..187bb0ceb4ac 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c @@ -91,6 +91,7 @@ static int  gen4_render_ring_flush(struct i915_request *rq, u32 mode)  {  	u32 cmd, *cs; +	int i;  	/*  	 * read/write caches: @@ -127,12 +128,45 @@ gen4_render_ring_flush(struct i915_request *rq, u32 mode)  			cmd |= MI_INVALIDATE_ISP;  	} -	cs = intel_ring_begin(rq, 2); +	i = 2; +	if (mode & EMIT_INVALIDATE) +		i += 20; + +	cs = intel_ring_begin(rq, i);  	if (IS_ERR(cs))  		return PTR_ERR(cs);  	*cs++ = cmd; -	*cs++ = MI_NOOP; + +	/* +	 * A random delay to let the CS invalidate take effect? Without this +	 * delay, the GPU relocation path fails as the CS does not see +	 * the updated contents. Just as important, if we apply the flushes +	 * to the EMIT_FLUSH branch (i.e. immediately after the relocation +	 * write and before the invalidate on the next batch), the relocations +	 * still fail. This implies that is a delay following invalidation +	 * that is required to reset the caches as opposed to a delay to +	 * ensure the memory is written. +	 */ +	if (mode & EMIT_INVALIDATE) { +		*cs++ = GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE; +		*cs++ = i915_ggtt_offset(rq->engine->scratch) | +			PIPE_CONTROL_GLOBAL_GTT; +		*cs++ = 0; +		*cs++ = 0; + +		for (i = 0; i < 12; i++) +			*cs++ = MI_FLUSH; + +		*cs++ = GFX_OP_PIPE_CONTROL(4) | PIPE_CONTROL_QW_WRITE; +		*cs++ = i915_ggtt_offset(rq->engine->scratch) | +			PIPE_CONTROL_GLOBAL_GTT; +		*cs++ = 0; +		*cs++ = 0; +	} + +	*cs++ = cmd; +  	intel_ring_advance(rq, cs);  	return 0; diff --git a/drivers/gpu/drm/i915/intel_runtime_pm.c b/drivers/gpu/drm/i915/intel_runtime_pm.c index 0fdabce647ab..44e4491a4918 100644 --- a/drivers/gpu/drm/i915/intel_runtime_pm.c +++ b/drivers/gpu/drm/i915/intel_runtime_pm.c @@ -2749,6 +2749,12 @@ static const struct i915_power_well_desc icl_power_wells[] = {  		},  	},  	{ +		.name = "DC off", +		.domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS, +		.ops = &gen9_dc_off_power_well_ops, +		.id = DISP_PW_ID_NONE, +	}, +	{  		.name = "power well 2",  		.domains = ICL_PW_2_POWER_DOMAINS,  		.ops = &hsw_power_well_ops, @@ -2760,12 +2766,6 @@ static const struct i915_power_well_desc icl_power_wells[] = {  		},  	},  	{ -		.name = "DC off", -		.domains = ICL_DISPLAY_DC_OFF_POWER_DOMAINS, -		.ops = &gen9_dc_off_power_well_ops, -		.id = DISP_PW_ID_NONE, -	}, -	{  		.name = "power well 3",  		.domains = ICL_PW_3_POWER_DOMAINS,  		.ops = &hsw_power_well_ops, @@ -3176,8 +3176,7 @@ static u8 intel_dbuf_max_slices(struct drm_i915_private *dev_priv)  void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,  			    u8 req_slices)  { -	u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices; -	u32 val; +	const u8 hw_enabled_slices = dev_priv->wm.skl_hw.ddb.enabled_slices;  	bool ret;  	if (req_slices > intel_dbuf_max_slices(dev_priv)) { @@ -3188,7 +3187,6 @@ void icl_dbuf_slices_update(struct drm_i915_private *dev_priv,  	if (req_slices == hw_enabled_slices || req_slices == 0)  		return; -	val = I915_READ(DBUF_CTL_S2);  	if (req_slices > hw_enabled_slices)  		ret = intel_dbuf_slice_set(dev_priv, DBUF_CTL_S2, true);  	else diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 5fd2f7bf3927..d3090a7537bb 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c @@ -302,13 +302,65 @@ skl_plane_max_stride(struct intel_plane *plane,  		return min(8192 * cpp, 32768);  } +static void +skl_program_scaler(struct intel_plane *plane, +		   const struct intel_crtc_state *crtc_state, +		   const struct intel_plane_state *plane_state) +{ +	struct drm_i915_private *dev_priv = to_i915(plane->base.dev); +	enum pipe pipe = plane->pipe; +	int scaler_id = plane_state->scaler_id; +	const struct intel_scaler *scaler = +		&crtc_state->scaler_state.scalers[scaler_id]; +	int crtc_x = plane_state->base.dst.x1; +	int crtc_y = plane_state->base.dst.y1; +	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); +	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst); +	u16 y_hphase, uv_rgb_hphase; +	u16 y_vphase, uv_rgb_vphase; +	int hscale, vscale; + +	hscale = drm_rect_calc_hscale(&plane_state->base.src, +				      &plane_state->base.dst, +				      0, INT_MAX); +	vscale = drm_rect_calc_vscale(&plane_state->base.src, +				      &plane_state->base.dst, +				      0, INT_MAX); + +	/* TODO: handle sub-pixel coordinates */ +	if (plane_state->base.fb->format->format == DRM_FORMAT_NV12) { +		y_hphase = skl_scaler_calc_phase(1, hscale, false); +		y_vphase = skl_scaler_calc_phase(1, vscale, false); + +		/* MPEG2 chroma siting convention */ +		uv_rgb_hphase = skl_scaler_calc_phase(2, hscale, true); +		uv_rgb_vphase = skl_scaler_calc_phase(2, vscale, false); +	} else { +		/* not used */ +		y_hphase = 0; +		y_vphase = 0; + +		uv_rgb_hphase = skl_scaler_calc_phase(1, hscale, false); +		uv_rgb_vphase = skl_scaler_calc_phase(1, vscale, false); +	} + +	I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id), +		      PS_SCALER_EN | PS_PLANE_SEL(plane->id) | scaler->mode); +	I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0); +	I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id), +		      PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase)); +	I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id), +		      PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase)); +	I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y); +	I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), (crtc_w << 16) | crtc_h); +} +  void  skl_update_plane(struct intel_plane *plane,  		 const struct intel_crtc_state *crtc_state,  		 const struct intel_plane_state *plane_state)  {  	struct drm_i915_private *dev_priv = to_i915(plane->base.dev); -	const struct drm_framebuffer *fb = plane_state->base.fb;  	enum plane_id plane_id = plane->id;  	enum pipe pipe = plane->pipe;  	u32 plane_ctl = plane_state->ctl; @@ -318,8 +370,6 @@ skl_update_plane(struct intel_plane *plane,  	u32 aux_stride = skl_plane_stride(plane_state, 1);  	int crtc_x = plane_state->base.dst.x1;  	int crtc_y = plane_state->base.dst.y1; -	uint32_t crtc_w = drm_rect_width(&plane_state->base.dst); -	uint32_t crtc_h = drm_rect_height(&plane_state->base.dst);  	uint32_t x = plane_state->color_plane[0].x;  	uint32_t y = plane_state->color_plane[0].y;  	uint32_t src_w = drm_rect_width(&plane_state->base.src) >> 16; @@ -329,8 +379,6 @@ skl_update_plane(struct intel_plane *plane,  	/* Sizes are 0 based */  	src_w--;  	src_h--; -	crtc_w--; -	crtc_h--;  	spin_lock_irqsave(&dev_priv->uncore.lock, irqflags); @@ -353,41 +401,8 @@ skl_update_plane(struct intel_plane *plane,  		      (plane_state->color_plane[1].y << 16) |  		      plane_state->color_plane[1].x); -	/* program plane scaler */  	if (plane_state->scaler_id >= 0) { -		int scaler_id = plane_state->scaler_id; -		const struct intel_scaler *scaler = -			&crtc_state->scaler_state.scalers[scaler_id]; -		u16 y_hphase, uv_rgb_hphase; -		u16 y_vphase, uv_rgb_vphase; - -		/* TODO: handle sub-pixel coordinates */ -		if (fb->format->format == DRM_FORMAT_NV12) { -			y_hphase = skl_scaler_calc_phase(1, false); -			y_vphase = skl_scaler_calc_phase(1, false); - -			/* MPEG2 chroma siting convention */ -			uv_rgb_hphase = skl_scaler_calc_phase(2, true); -			uv_rgb_vphase = skl_scaler_calc_phase(2, false); -		} else { -			/* not used */ -			y_hphase = 0; -			y_vphase = 0; - -			uv_rgb_hphase = skl_scaler_calc_phase(1, false); -			uv_rgb_vphase = skl_scaler_calc_phase(1, false); -		} - -		I915_WRITE_FW(SKL_PS_CTRL(pipe, scaler_id), -			      PS_SCALER_EN | PS_PLANE_SEL(plane_id) | scaler->mode); -		I915_WRITE_FW(SKL_PS_PWR_GATE(pipe, scaler_id), 0); -		I915_WRITE_FW(SKL_PS_VPHASE(pipe, scaler_id), -			      PS_Y_PHASE(y_vphase) | PS_UV_RGB_PHASE(uv_rgb_vphase)); -		I915_WRITE_FW(SKL_PS_HPHASE(pipe, scaler_id), -			      PS_Y_PHASE(y_hphase) | PS_UV_RGB_PHASE(uv_rgb_hphase)); -		I915_WRITE_FW(SKL_PS_WIN_POS(pipe, scaler_id), (crtc_x << 16) | crtc_y); -		I915_WRITE_FW(SKL_PS_WIN_SZ(pipe, scaler_id), -			      ((crtc_w + 1) << 16)|(crtc_h + 1)); +		skl_program_scaler(plane, crtc_state, plane_state);  		I915_WRITE_FW(PLANE_POS(pipe, plane_id), 0);  	} else { diff --git a/drivers/gpu/drm/i915/selftests/huge_pages.c b/drivers/gpu/drm/i915/selftests/huge_pages.c index 8d03f64eabd7..5c22f2c8d4cf 100644 --- a/drivers/gpu/drm/i915/selftests/huge_pages.c +++ b/drivers/gpu/drm/i915/selftests/huge_pages.c @@ -551,7 +551,7 @@ static int igt_mock_ppgtt_misaligned_dma(void *arg)  			err = igt_check_page_sizes(vma);  			if (vma->page_sizes.gtt != I915_GTT_PAGE_SIZE_4K) { -				pr_err("page_sizes.gtt=%u, expected %lu\n", +				pr_err("page_sizes.gtt=%u, expected %llu\n",  				       vma->page_sizes.gtt, I915_GTT_PAGE_SIZE_4K);  				err = -EINVAL;  			} diff --git a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c index 8e2e269db97e..127d81513671 100644 --- a/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c +++ b/drivers/gpu/drm/i915/selftests/i915_gem_gtt.c @@ -1337,7 +1337,7 @@ static int igt_gtt_reserve(void *arg)  		GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));  		if (vma->node.start != total ||  		    vma->node.size != 2*I915_GTT_PAGE_SIZE) { -			pr_err("i915_gem_gtt_reserve (pass 1) placement failed, found (%llx + %llx), expected (%llx + %lx)\n", +			pr_err("i915_gem_gtt_reserve (pass 1) placement failed, found (%llx + %llx), expected (%llx + %llx)\n",  			       vma->node.start, vma->node.size,  			       total, 2*I915_GTT_PAGE_SIZE);  			err = -EINVAL; @@ -1386,7 +1386,7 @@ static int igt_gtt_reserve(void *arg)  		GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));  		if (vma->node.start != total ||  		    vma->node.size != 2*I915_GTT_PAGE_SIZE) { -			pr_err("i915_gem_gtt_reserve (pass 2) placement failed, found (%llx + %llx), expected (%llx + %lx)\n", +			pr_err("i915_gem_gtt_reserve (pass 2) placement failed, found (%llx + %llx), expected (%llx + %llx)\n",  			       vma->node.start, vma->node.size,  			       total, 2*I915_GTT_PAGE_SIZE);  			err = -EINVAL; @@ -1430,7 +1430,7 @@ static int igt_gtt_reserve(void *arg)  		GEM_BUG_ON(!drm_mm_node_allocated(&vma->node));  		if (vma->node.start != offset ||  		    vma->node.size != 2*I915_GTT_PAGE_SIZE) { -			pr_err("i915_gem_gtt_reserve (pass 3) placement failed, found (%llx + %llx), expected (%llx + %lx)\n", +			pr_err("i915_gem_gtt_reserve (pass 3) placement failed, found (%llx + %llx), expected (%llx + %llx)\n",  			       vma->node.start, vma->node.size,  			       offset, 2*I915_GTT_PAGE_SIZE);  			err = -EINVAL; diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c index 05520202c967..191b314f9e9e 100644 --- a/drivers/gpu/drm/meson/meson_crtc.c +++ b/drivers/gpu/drm/meson/meson_crtc.c @@ -45,6 +45,7 @@ struct meson_crtc {  	struct drm_crtc base;  	struct drm_pending_vblank_event *event;  	struct meson_drm *priv; +	bool enabled;  };  #define to_meson_crtc(x) container_of(x, struct meson_crtc, base) @@ -80,8 +81,7 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {  }; -static void meson_crtc_atomic_enable(struct drm_crtc *crtc, -				     struct drm_crtc_state *old_state) +static void meson_crtc_enable(struct drm_crtc *crtc)  {  	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);  	struct drm_crtc_state *crtc_state = crtc->state; @@ -101,6 +101,22 @@ static void meson_crtc_atomic_enable(struct drm_crtc *crtc,  	writel_bits_relaxed(VPP_POSTBLEND_ENABLE, VPP_POSTBLEND_ENABLE,  			    priv->io_base + _REG(VPP_MISC)); +	drm_crtc_vblank_on(crtc); + +	meson_crtc->enabled = true; +} + +static void meson_crtc_atomic_enable(struct drm_crtc *crtc, +				     struct drm_crtc_state *old_state) +{ +	struct meson_crtc *meson_crtc = to_meson_crtc(crtc); +	struct meson_drm *priv = meson_crtc->priv; + +	DRM_DEBUG_DRIVER("\n"); + +	if (!meson_crtc->enabled) +		meson_crtc_enable(crtc); +  	priv->viu.osd1_enabled = true;  } @@ -110,6 +126,8 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,  	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);  	struct meson_drm *priv = meson_crtc->priv; +	drm_crtc_vblank_off(crtc); +  	priv->viu.osd1_enabled = false;  	priv->viu.osd1_commit = false; @@ -124,6 +142,8 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,  		crtc->state->event = NULL;  	} + +	meson_crtc->enabled = false;  }  static void meson_crtc_atomic_begin(struct drm_crtc *crtc, @@ -132,6 +152,9 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc,  	struct meson_crtc *meson_crtc = to_meson_crtc(crtc);  	unsigned long flags; +	if (crtc->state->enable && !meson_crtc->enabled) +		meson_crtc_enable(crtc); +  	if (crtc->state->event) {  		WARN_ON(drm_crtc_vblank_get(crtc) != 0); diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index df7247cd93f9..2cb2ad26d716 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c @@ -706,6 +706,7 @@ static const struct regmap_config meson_dw_hdmi_regmap_config = {  	.reg_read = meson_dw_hdmi_reg_read,  	.reg_write = meson_dw_hdmi_reg_write,  	.max_register = 0x10000, +	.fast_io = true,  };  static bool meson_hdmi_connector_is_available(struct device *dev) diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c index 514245e69b38..be76f3d64bf2 100644 --- a/drivers/gpu/drm/meson/meson_venc.c +++ b/drivers/gpu/drm/meson/meson_venc.c @@ -71,6 +71,7 @@   */  /* HHI Registers */ +#define HHI_GCLK_MPEG2		0x148 /* 0x52 offset in data sheet */  #define HHI_VDAC_CNTL0		0x2F4 /* 0xbd offset in data sheet */  #define HHI_VDAC_CNTL1		0x2F8 /* 0xbe offset in data sheet */  #define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 offset in data sheet */ @@ -714,6 +715,7 @@ struct meson_hdmi_venc_vic_mode {  	{ 5, &meson_hdmi_encp_mode_1080i60 },  	{ 20, &meson_hdmi_encp_mode_1080i50 },  	{ 32, &meson_hdmi_encp_mode_1080p24 }, +	{ 33, &meson_hdmi_encp_mode_1080p50 },  	{ 34, &meson_hdmi_encp_mode_1080p30 },  	{ 31, &meson_hdmi_encp_mode_1080p50 },  	{ 16, &meson_hdmi_encp_mode_1080p60 }, @@ -854,6 +856,13 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,  	unsigned int sof_lines;  	unsigned int vsync_lines; +	/* Use VENCI for 480i and 576i and double HDMI pixels */ +	if (mode->flags & DRM_MODE_FLAG_DBLCLK) { +		hdmi_repeat = true; +		use_enci = true; +		venc_hdmi_latency = 1; +	} +  	if (meson_venc_hdmi_supported_vic(vic)) {  		vmode = meson_venc_hdmi_get_vic_vmode(vic);  		if (!vmode) { @@ -865,13 +874,7 @@ void meson_venc_hdmi_mode_set(struct meson_drm *priv, int vic,  	} else {  		meson_venc_hdmi_get_dmt_vmode(mode, &vmode_dmt);  		vmode = &vmode_dmt; -	} - -	/* Use VENCI for 480i and 576i and double HDMI pixels */ -	if (mode->flags & DRM_MODE_FLAG_DBLCLK) { -		hdmi_repeat = true; -		use_enci = true; -		venc_hdmi_latency = 1; +		use_enci = false;  	}  	/* Repeat VENC pixels for 480/576i/p, 720p50/60 and 1080p50/60 */ @@ -1529,10 +1532,12 @@ unsigned int meson_venci_get_field(struct meson_drm *priv)  void meson_venc_enable_vsync(struct meson_drm *priv)  {  	writel_relaxed(2, priv->io_base + _REG(VENC_INTCTRL)); +	regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), BIT(25));  }  void meson_venc_disable_vsync(struct meson_drm *priv)  { +	regmap_update_bits(priv->hhi, HHI_GCLK_MPEG2, BIT(25), 0);  	writel_relaxed(0, priv->io_base + _REG(VENC_INTCTRL));  } diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c index 6bcfa527c180..26a0857878bf 100644 --- a/drivers/gpu/drm/meson/meson_viu.c +++ b/drivers/gpu/drm/meson/meson_viu.c @@ -184,18 +184,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,  	if (lut_sel == VIU_LUT_OSD_OETF) {  		writel(0, priv->io_base + _REG(addr_port)); -		for (i = 0; i < 20; i++) +		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)  			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),  				priv->io_base + _REG(data_port));  		writel(r_map[OSD_OETF_LUT_SIZE - 1] | (g_map[0] << 16),  			priv->io_base + _REG(data_port)); -		for (i = 0; i < 20; i++) +		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)  			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),  				priv->io_base + _REG(data_port)); -		for (i = 0; i < 20; i++) +		for (i = 0; i < (OSD_OETF_LUT_SIZE / 2); i++)  			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),  				priv->io_base + _REG(data_port)); @@ -211,18 +211,18 @@ void meson_viu_set_osd_lut(struct meson_drm *priv, enum viu_lut_sel_e lut_sel,  	} else if (lut_sel == VIU_LUT_OSD_EOTF) {  		writel(0, priv->io_base + _REG(addr_port)); -		for (i = 0; i < 20; i++) +		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)  			writel(r_map[i * 2] | (r_map[i * 2 + 1] << 16),  				priv->io_base + _REG(data_port));  		writel(r_map[OSD_EOTF_LUT_SIZE - 1] | (g_map[0] << 16),  			priv->io_base + _REG(data_port)); -		for (i = 0; i < 20; i++) +		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)  			writel(g_map[i * 2 + 1] | (g_map[i * 2 + 2] << 16),  				priv->io_base + _REG(data_port)); -		for (i = 0; i < 20; i++) +		for (i = 0; i < (OSD_EOTF_LUT_SIZE / 2); i++)  			writel(b_map[i * 2] | (b_map[i * 2 + 1] << 16),  				priv->io_base + _REG(data_port)); diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index 394c129cfb3b..0a485c5b982e 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -5409,11 +5409,14 @@ static int dsi_probe(struct platform_device *pdev)  	/* DSI on OMAP3 doesn't have register DSI_GNQ, set number  	 * of data to 3 by default */ -	if (dsi->data->quirks & DSI_QUIRK_GNQ) +	if (dsi->data->quirks & DSI_QUIRK_GNQ) { +		dsi_runtime_get(dsi);  		/* NB_DATA_LANES */  		dsi->num_lanes_supported = 1 + REG_GET(dsi, DSI_GNQ, 11, 9); -	else +		dsi_runtime_put(dsi); +	} else {  		dsi->num_lanes_supported = 3; +	}  	r = dsi_init_output(dsi);  	if (r) @@ -5426,15 +5429,19 @@ static int dsi_probe(struct platform_device *pdev)  	}  	r = of_platform_populate(dev->of_node, NULL, NULL, dev); -	if (r) +	if (r) {  		DSSERR("Failed to populate DSI child devices: %d\n", r); +		goto err_uninit_output; +	}  	r = component_add(&pdev->dev, &dsi_component_ops);  	if (r) -		goto err_uninit_output; +		goto err_of_depopulate;  	return 0; +err_of_depopulate: +	of_platform_depopulate(dev);  err_uninit_output:  	dsi_uninit_output(dsi);  err_pm_disable: @@ -5470,19 +5477,12 @@ static int dsi_runtime_suspend(struct device *dev)  	/* wait for current handler to finish before turning the DSI off */  	synchronize_irq(dsi->irq); -	dispc_runtime_put(dsi->dss->dispc); -  	return 0;  }  static int dsi_runtime_resume(struct device *dev)  {  	struct dsi_data *dsi = dev_get_drvdata(dev); -	int r; - -	r = dispc_runtime_get(dsi->dss->dispc); -	if (r) -		return r;  	dsi->is_enabled = true;  	/* ensure the irq handler sees the is_enabled value */ diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 1aaf260aa9b8..7553c7fc1c45 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -1484,16 +1484,23 @@ static int dss_probe(struct platform_device *pdev)  						   dss);  	/* Add all the child devices as components. */ +	r = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); +	if (r) +		goto err_uninit_debugfs; +  	omapdss_gather_components(&pdev->dev);  	device_for_each_child(&pdev->dev, &match, dss_add_child_component);  	r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);  	if (r) -		goto err_uninit_debugfs; +		goto err_of_depopulate;  	return 0; +err_of_depopulate: +	of_platform_depopulate(&pdev->dev); +  err_uninit_debugfs:  	dss_debugfs_remove_file(dss->debugfs.clk);  	dss_debugfs_remove_file(dss->debugfs.dss); @@ -1522,6 +1529,8 @@ static int dss_remove(struct platform_device *pdev)  {  	struct dss_device *dss = platform_get_drvdata(pdev); +	of_platform_depopulate(&pdev->dev); +  	component_master_del(&pdev->dev, &dss_component_ops);  	dss_debugfs_remove_file(dss->debugfs.clk); diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index cf6230eac31a..aabdda394c9c 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -635,10 +635,14 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)  	hdmi->dss = dss; -	r = hdmi_pll_init(dss, hdmi->pdev, &hdmi->pll, &hdmi->wp); +	r = hdmi_runtime_get(hdmi);  	if (r)  		return r; +	r = hdmi_pll_init(dss, hdmi->pdev, &hdmi->pll, &hdmi->wp); +	if (r) +		goto err_runtime_put; +  	r = hdmi4_cec_init(hdmi->pdev, &hdmi->core, &hdmi->wp);  	if (r)  		goto err_pll_uninit; @@ -652,12 +656,16 @@ static int hdmi4_bind(struct device *dev, struct device *master, void *data)  	hdmi->debugfs = dss_debugfs_create_file(dss, "hdmi", hdmi_dump_regs,  					       hdmi); +	hdmi_runtime_put(hdmi); +  	return 0;  err_cec_uninit:  	hdmi4_cec_uninit(&hdmi->core);  err_pll_uninit:  	hdmi_pll_uninit(&hdmi->pll); +err_runtime_put: +	hdmi_runtime_put(hdmi);  	return r;  } @@ -833,32 +841,6 @@ static int hdmi4_remove(struct platform_device *pdev)  	return 0;  } -static int hdmi_runtime_suspend(struct device *dev) -{ -	struct omap_hdmi *hdmi = dev_get_drvdata(dev); - -	dispc_runtime_put(hdmi->dss->dispc); - -	return 0; -} - -static int hdmi_runtime_resume(struct device *dev) -{ -	struct omap_hdmi *hdmi = dev_get_drvdata(dev); -	int r; - -	r = dispc_runtime_get(hdmi->dss->dispc); -	if (r < 0) -		return r; - -	return 0; -} - -static const struct dev_pm_ops hdmi_pm_ops = { -	.runtime_suspend = hdmi_runtime_suspend, -	.runtime_resume = hdmi_runtime_resume, -}; -  static const struct of_device_id hdmi_of_match[] = {  	{ .compatible = "ti,omap4-hdmi", },  	{}, @@ -869,7 +851,6 @@ struct platform_driver omapdss_hdmi4hw_driver = {  	.remove		= hdmi4_remove,  	.driver         = {  		.name   = "omapdss_hdmi", -		.pm	= &hdmi_pm_ops,  		.of_match_table = hdmi_of_match,  		.suppress_bind_attrs = true,  	}, diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index b0e4a7463f8c..9e8556f67a29 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -825,32 +825,6 @@ static int hdmi5_remove(struct platform_device *pdev)  	return 0;  } -static int hdmi_runtime_suspend(struct device *dev) -{ -	struct omap_hdmi *hdmi = dev_get_drvdata(dev); - -	dispc_runtime_put(hdmi->dss->dispc); - -	return 0; -} - -static int hdmi_runtime_resume(struct device *dev) -{ -	struct omap_hdmi *hdmi = dev_get_drvdata(dev); -	int r; - -	r = dispc_runtime_get(hdmi->dss->dispc); -	if (r < 0) -		return r; - -	return 0; -} - -static const struct dev_pm_ops hdmi_pm_ops = { -	.runtime_suspend = hdmi_runtime_suspend, -	.runtime_resume = hdmi_runtime_resume, -}; -  static const struct of_device_id hdmi_of_match[] = {  	{ .compatible = "ti,omap5-hdmi", },  	{ .compatible = "ti,dra7-hdmi", }, @@ -862,7 +836,6 @@ struct platform_driver omapdss_hdmi5hw_driver = {  	.remove		= hdmi5_remove,  	.driver         = {  		.name   = "omapdss_hdmi5", -		.pm	= &hdmi_pm_ops,  		.of_match_table = hdmi_of_match,  		.suppress_bind_attrs = true,  	}, diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index ff0b18c8e4ac..b5f52727f8b1 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -946,19 +946,12 @@ static int venc_runtime_suspend(struct device *dev)  	if (venc->tv_dac_clk)  		clk_disable_unprepare(venc->tv_dac_clk); -	dispc_runtime_put(venc->dss->dispc); -  	return 0;  }  static int venc_runtime_resume(struct device *dev)  {  	struct venc_device *venc = dev_get_drvdata(dev); -	int r; - -	r = dispc_runtime_get(venc->dss->dispc); -	if (r < 0) -		return r;  	if (venc->tv_dac_clk)  		clk_prepare_enable(venc->tv_dac_clk); diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 62928ec0e7db..caffc547ef97 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -350,11 +350,14 @@ static void omap_crtc_arm_event(struct drm_crtc *crtc)  static void omap_crtc_atomic_enable(struct drm_crtc *crtc,  				    struct drm_crtc_state *old_state)  { +	struct omap_drm_private *priv = crtc->dev->dev_private;  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);  	int ret;  	DBG("%s", omap_crtc->name); +	priv->dispc_ops->runtime_get(priv->dispc); +  	spin_lock_irq(&crtc->dev->event_lock);  	drm_crtc_vblank_on(crtc);  	ret = drm_crtc_vblank_get(crtc); @@ -367,6 +370,7 @@ static void omap_crtc_atomic_enable(struct drm_crtc *crtc,  static void omap_crtc_atomic_disable(struct drm_crtc *crtc,  				     struct drm_crtc_state *old_state)  { +	struct omap_drm_private *priv = crtc->dev->dev_private;  	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);  	DBG("%s", omap_crtc->name); @@ -379,6 +383,8 @@ static void omap_crtc_atomic_disable(struct drm_crtc *crtc,  	spin_unlock_irq(&crtc->dev->event_lock);  	drm_crtc_vblank_off(crtc); + +	priv->dispc_ops->runtime_put(priv->dispc);  }  static enum drm_mode_status omap_crtc_mode_valid(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c index d85f0a1c1581..cebf313c6e1f 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_group.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c @@ -202,10 +202,25 @@ void rcar_du_group_put(struct rcar_du_group *rgrp)  static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)  { -	struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2]; +	struct rcar_du_device *rcdu = rgrp->dev; + +	/* +	 * Group start/stop is controlled by the DRES and DEN bits of DSYSR0 +	 * for the first group and DSYSR2 for the second group. On most DU +	 * instances, this maps to the first CRTC of the group, and we can just +	 * use rcar_du_crtc_dsysr_clr_set() to access the correct DSYSR. On +	 * M3-N, however, DU2 doesn't exist, but DSYSR2 does. We thus need to +	 * access the register directly using group read/write. +	 */ +	if (rcdu->info->channels_mask & BIT(rgrp->index * 2)) { +		struct rcar_du_crtc *rcrtc = &rgrp->dev->crtcs[rgrp->index * 2]; -	rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN, -				   start ? DSYSR_DEN : DSYSR_DRES); +		rcar_du_crtc_dsysr_clr_set(rcrtc, DSYSR_DRES | DSYSR_DEN, +					   start ? DSYSR_DEN : DSYSR_DRES); +	} else { +		rcar_du_group_write(rgrp, DSYSR, +				    start ? DSYSR_DEN : DSYSR_DRES); +	}  }  void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c index af7dcb6da351..e7eb0d1e17be 100644 --- a/drivers/gpu/drm/sun4i/sun4i_lvds.c +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c @@ -75,7 +75,7 @@ static void sun4i_lvds_encoder_enable(struct drm_encoder *encoder)  	DRM_DEBUG_DRIVER("Enabling LVDS output\n"); -	if (!IS_ERR(tcon->panel)) { +	if (tcon->panel) {  		drm_panel_prepare(tcon->panel);  		drm_panel_enable(tcon->panel);  	} @@ -88,7 +88,7 @@ static void sun4i_lvds_encoder_disable(struct drm_encoder *encoder)  	DRM_DEBUG_DRIVER("Disabling LVDS output\n"); -	if (!IS_ERR(tcon->panel)) { +	if (tcon->panel) {  		drm_panel_disable(tcon->panel);  		drm_panel_unprepare(tcon->panel);  	} diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index bf068da6b12e..f4a22689eb54 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -135,7 +135,7 @@ static void sun4i_rgb_encoder_enable(struct drm_encoder *encoder)  	DRM_DEBUG_DRIVER("Enabling RGB output\n"); -	if (!IS_ERR(tcon->panel)) { +	if (tcon->panel) {  		drm_panel_prepare(tcon->panel);  		drm_panel_enable(tcon->panel);  	} @@ -148,7 +148,7 @@ static void sun4i_rgb_encoder_disable(struct drm_encoder *encoder)  	DRM_DEBUG_DRIVER("Disabling RGB output\n"); -	if (!IS_ERR(tcon->panel)) { +	if (tcon->panel) {  		drm_panel_disable(tcon->panel);  		drm_panel_unprepare(tcon->panel);  	} diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index c78cd35a1294..f949287d926c 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -491,7 +491,8 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,  	sun4i_tcon0_mode_set_common(tcon, mode);  	/* Set dithering if needed */ -	sun4i_tcon0_mode_set_dithering(tcon, tcon->panel->connector); +	if (tcon->panel) +		sun4i_tcon0_mode_set_dithering(tcon, tcon->panel->connector);  	/* Adjust clock delay */  	clk_delay = sun4i_tcon_get_clk_delay(mode, 0); @@ -555,7 +556,7 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,  	 * Following code is a way to avoid quirks all around TCON  	 * and DOTCLOCK drivers.  	 */ -	if (!IS_ERR(tcon->panel)) { +	if (tcon->panel) {  		struct drm_panel *panel = tcon->panel;  		struct drm_connector *connector = panel->connector;  		struct drm_display_info display_info = connector->display_info; 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 9dc3fcbd290b..c6635f23918a 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -807,7 +807,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); @@ -828,7 +828,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/gpu/vga/vga_switcheroo.c b/drivers/gpu/vga/vga_switcheroo.c index cf2a18571d48..a132c37d7334 100644 --- a/drivers/gpu/vga/vga_switcheroo.c +++ b/drivers/gpu/vga/vga_switcheroo.c @@ -380,6 +380,9 @@ int vga_switcheroo_register_audio_client(struct pci_dev *pdev,  			mutex_unlock(&vgasr_mutex);  			return -EINVAL;  		} +		/* notify if GPU has been already bound */ +		if (ops->gpu_bound) +			ops->gpu_bound(pdev, id);  	}  	mutex_unlock(&vgasr_mutex); diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c index aec253b44156..3cd7229b6e54 100644 --- a/drivers/hid/hid-alps.c +++ b/drivers/hid/hid-alps.c @@ -660,6 +660,20 @@ exit:  	return ret;  } +static int alps_sp_open(struct input_dev *dev) +{ +	struct hid_device *hid = input_get_drvdata(dev); + +	return hid_hw_open(hid); +} + +static void alps_sp_close(struct input_dev *dev) +{ +	struct hid_device *hid = input_get_drvdata(dev); + +	hid_hw_close(hid); +} +  static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)  {  	struct alps_dev *data = hid_get_drvdata(hdev); @@ -733,6 +747,10 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi)  		input2->id.version = input->id.version;  		input2->dev.parent = input->dev.parent; +		input_set_drvdata(input2, hdev); +		input2->open = alps_sp_open; +		input2->close = alps_sp_close; +  		__set_bit(EV_KEY, input2->evbit);  		data->sp_btn_cnt = (data->sp_btn_info & 0x0F);  		for (i = 0; i < data->sp_btn_cnt; i++) diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index dc6d6477e961..a1fa2fc8c9b5 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -359,6 +359,9 @@ static bool asus_kbd_wmi_led_control_present(struct hid_device *hdev)  	u32 value;  	int ret; +	if (!IS_ENABLED(CONFIG_ASUS_WMI)) +		return false; +  	ret = asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2,  				       ASUS_WMI_DEVID_KBD_BACKLIGHT, 0, &value);  	hid_dbg(hdev, "WMI backlight check: rc %d value %x", ret, value); diff --git a/drivers/hid/hid-hyperv.c b/drivers/hid/hid-hyperv.c index b372854cf38d..704049e62d58 100644 --- a/drivers/hid/hid-hyperv.c +++ b/drivers/hid/hid-hyperv.c @@ -309,7 +309,7 @@ static void mousevsc_on_receive(struct hv_device *device,  		hid_input_report(input_dev->hid_device, HID_INPUT_REPORT,  				 input_dev->input_buf, len, 1); -		pm_wakeup_event(&input_dev->device->device, 0); +		pm_wakeup_hard_event(&input_dev->device->device);  		break;  	default: diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index f63489c882bb..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 @@ -927,6 +932,9 @@  #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3003		0x3003  #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008		0x3008 +#define I2C_VENDOR_ID_RAYDIUM		0x2386 +#define I2C_PRODUCT_ID_RAYDIUM_4B33	0x4b33 +  #define USB_VENDOR_ID_RAZER            0x1532  #define USB_DEVICE_ID_RAZER_BLADE_14   0x011D @@ -1040,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 @@ -1201,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 52c3b01917e7..c85a79986b6a 100644 --- a/drivers/hid/hid-quirks.c +++ b/drivers/hid/hid-quirks.c @@ -107,7 +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_MGE, USB_DEVICE_ID_MGE_UPS), HID_QUIRK_NOGET }, +	{ 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 }, @@ -130,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-sensor-custom.c b/drivers/hid/hid-sensor-custom.c index e8a114157f87..bb012bc032e0 100644 --- a/drivers/hid/hid-sensor-custom.c +++ b/drivers/hid/hid-sensor-custom.c @@ -358,7 +358,7 @@ static ssize_t show_value(struct device *dev, struct device_attribute *attr,  						sensor_inst->hsdev,  						sensor_inst->hsdev->usage,  						usage, report_id, -						SENSOR_HUB_SYNC); +						SENSOR_HUB_SYNC, false);  	} else if (!strncmp(name, "units", strlen("units")))  		value = sensor_inst->fields[field_index].attribute.units;  	else if (!strncmp(name, "unit-expo", strlen("unit-expo"))) diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 2b63487057c2..4256fdc5cd6d 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -299,7 +299,8 @@ EXPORT_SYMBOL_GPL(sensor_hub_get_feature);  int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,  					u32 usage_id,  					u32 attr_usage_id, u32 report_id, -					enum sensor_hub_read_flags flag) +					enum sensor_hub_read_flags flag, +					bool is_signed)  {  	struct sensor_hub_data *data = hid_get_drvdata(hsdev->hdev);  	unsigned long flags; @@ -331,10 +332,16 @@ int sensor_hub_input_attr_get_raw_value(struct hid_sensor_hub_device *hsdev,  						&hsdev->pending.ready, HZ*5);  		switch (hsdev->pending.raw_size) {  		case 1: -			ret_val = *(u8 *)hsdev->pending.raw_data; +			if (is_signed) +				ret_val = *(s8 *)hsdev->pending.raw_data; +			else +				ret_val = *(u8 *)hsdev->pending.raw_data;  			break;  		case 2: -			ret_val = *(u16 *)hsdev->pending.raw_data; +			if (is_signed) +				ret_val = *(s16 *)hsdev->pending.raw_data; +			else +				ret_val = *(u16 *)hsdev->pending.raw_data;  			break;  		case 4:  			ret_val = *(u32 *)hsdev->pending.raw_data; 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 4aab96cf0818..8555ce7e737b 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -49,6 +49,7 @@  #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV	BIT(0)  #define I2C_HID_QUIRK_NO_IRQ_AFTER_RESET	BIT(1)  #define I2C_HID_QUIRK_NO_RUNTIME_PM		BIT(2) +#define I2C_HID_QUIRK_DELAY_AFTER_SLEEP		BIT(3)  /* flags */  #define I2C_HID_STARTED		0 @@ -158,6 +159,8 @@ struct i2c_hid {  	bool			irq_wake_enabled;  	struct mutex		reset_lock; + +	unsigned long		sleep_delay;  };  static const struct i2c_hid_quirks { @@ -172,6 +175,10 @@ static const struct i2c_hid_quirks {  	{ I2C_VENDOR_ID_HANTICK, I2C_PRODUCT_ID_HANTICK_5288,  		I2C_HID_QUIRK_NO_IRQ_AFTER_RESET |  		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 }  }; @@ -387,6 +394,7 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)  {  	struct i2c_hid *ihid = i2c_get_clientdata(client);  	int ret; +	unsigned long now, delay;  	i2c_hid_dbg(ihid, "%s\n", __func__); @@ -404,9 +412,22 @@ static int i2c_hid_set_power(struct i2c_client *client, int power_state)  			goto set_pwr_exit;  	} +	if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP && +	    power_state == I2C_HID_PWR_ON) { +		now = jiffies; +		if (time_after(ihid->sleep_delay, now)) { +			delay = jiffies_to_usecs(ihid->sleep_delay - now); +			usleep_range(delay, delay + 1); +		} +	} +  	ret = __i2c_hid_command(client, &hid_set_power_cmd, power_state,  		0, NULL, 0, NULL, 0); +	if (ihid->quirks & I2C_HID_QUIRK_DELAY_AFTER_SLEEP && +	    power_state == I2C_HID_PWR_SLEEP) +		ihid->sleep_delay = jiffies + msecs_to_jiffies(20); +  	if (ret)  		dev_err(&client->dev, "failed to change power setting.\n"); diff --git a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c index cac262a912c1..89f2976f9c53 100644 --- a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c +++ b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c @@ -331,6 +331,14 @@ static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {  		.driver_data = (void *)&sipodev_desc  	},  	{ +		.ident = "Direkt-Tek DTLAPY133-1", +		.matches = { +			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"), +			DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "DTLAPY133-1"), +		}, +		.driver_data = (void *)&sipodev_desc +	}, +	{  		.ident = "Mediacom Flexbook Edge 11",  		.matches = {  			DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"), 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/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 23872d08308c..a746017fac17 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -512,14 +512,24 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd,  			if (cmd == HIDIOCGCOLLECTIONINDEX) {  				if (uref->usage_index >= field->maxusage)  					goto inval; +				uref->usage_index = +					array_index_nospec(uref->usage_index, +							   field->maxusage);  			} else if (uref->usage_index >= field->report_count)  				goto inval;  		} -		if ((cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) && -		    (uref_multi->num_values > HID_MAX_MULTI_USAGES || -		     uref->usage_index + uref_multi->num_values > field->report_count)) -			goto inval; +		if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { +			if (uref_multi->num_values > HID_MAX_MULTI_USAGES || +			    uref->usage_index + uref_multi->num_values > +			    field->report_count) +				goto inval; + +			uref->usage_index = +				array_index_nospec(uref->usage_index, +						   field->report_count - +						   uref_multi->num_values); +		}  		switch (cmd) {  		case HIDIOCGUSAGE: diff --git a/drivers/hv/channel.c b/drivers/hv/channel.c index de8193f3b838..fe00b12e4417 100644 --- a/drivers/hv/channel.c +++ b/drivers/hv/channel.c @@ -516,6 +516,14 @@ int vmbus_establish_gpadl(struct vmbus_channel *channel, void *kbuffer,  	}  	wait_for_completion(&msginfo->waitevent); +	if (msginfo->response.gpadl_created.creation_status != 0) { +		pr_err("Failed to establish GPADL: err = 0x%x\n", +		       msginfo->response.gpadl_created.creation_status); + +		ret = -EDQUOT; +		goto cleanup; +	} +  	if (channel->rescind) {  		ret = -ENODEV;  		goto cleanup; 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/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 975c95169884..84f61cec6319 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -649,8 +649,10 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,  				if (info[i]->config[j] & HWMON_T_INPUT) {  					err = hwmon_thermal_add_sensor(dev,  								hwdev, j); -					if (err) -						goto free_device; +					if (err) { +						device_unregister(hdev); +						goto ida_remove; +					}  				}  			}  		} @@ -658,8 +660,6 @@ __hwmon_device_register(struct device *dev, const char *name, void *drvdata,  	return hdev; -free_device: -	device_unregister(hdev);  free_hwmon:  	kfree(hwdev);  ida_remove: diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c index 0ccca87f5271..293dd1c6c7b3 100644 --- a/drivers/hwmon/ibmpowernv.c +++ b/drivers/hwmon/ibmpowernv.c @@ -181,7 +181,7 @@ static ssize_t show_label(struct device *dev, struct device_attribute *devattr,  	return sprintf(buf, "%s\n", sdata->label);  } -static int __init get_logical_cpu(int hwcpu) +static int get_logical_cpu(int hwcpu)  {  	int cpu; @@ -192,9 +192,8 @@ static int __init get_logical_cpu(int hwcpu)  	return -ENOENT;  } -static void __init make_sensor_label(struct device_node *np, -				     struct sensor_data *sdata, -				     const char *label) +static void make_sensor_label(struct device_node *np, +			      struct sensor_data *sdata, const char *label)  {  	u32 id;  	size_t n; diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index 71d3445ba869..07ee19573b3f 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -274,7 +274,7 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,  		break;  	case INA2XX_CURRENT:  		/* signed register, result in mA */ -		val = regval * data->current_lsb_uA; +		val = (s16)regval * data->current_lsb_uA;  		val = DIV_ROUND_CLOSEST(val, 1000);  		break;  	case INA2XX_CALIBRATION: @@ -491,7 +491,7 @@ static int ina2xx_probe(struct i2c_client *client,  	}  	data->groups[group++] = &ina2xx_group; -	if (id->driver_data == ina226) +	if (chip == ina226)  		data->groups[group++] = &ina226_group;  	hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, @@ -500,7 +500,7 @@ static int ina2xx_probe(struct i2c_client *client,  		return PTR_ERR(hwmon_dev);  	dev_info(dev, "power monitor %s (Rshunt = %li uOhm)\n", -		 id->name, data->rshunt); +		 client->name, data->rshunt);  	return 0;  } diff --git a/drivers/hwmon/mlxreg-fan.c b/drivers/hwmon/mlxreg-fan.c index de46577c7d5a..d8fa4bea4bc8 100644 --- a/drivers/hwmon/mlxreg-fan.c +++ b/drivers/hwmon/mlxreg-fan.c @@ -51,7 +51,7 @@   */  #define MLXREG_FAN_GET_RPM(rval, d, s)	(DIV_ROUND_CLOSEST(15000000 * 100, \  					 ((rval) + (s)) * (d))) -#define MLXREG_FAN_GET_FAULT(val, mask) (!!((val) ^ (mask))) +#define MLXREG_FAN_GET_FAULT(val, mask) (!((val) ^ (mask)))  #define MLXREG_FAN_PWM_DUTY2STATE(duty)	(DIV_ROUND_CLOSEST((duty) *	\  					 MLXREG_FAN_MAX_STATE,		\  					 MLXREG_FAN_MAX_DUTY)) diff --git a/drivers/hwmon/raspberrypi-hwmon.c b/drivers/hwmon/raspberrypi-hwmon.c index be5ba4690895..0d0457245e7d 100644 --- a/drivers/hwmon/raspberrypi-hwmon.c +++ b/drivers/hwmon/raspberrypi-hwmon.c @@ -115,7 +115,6 @@ static int rpi_hwmon_probe(struct platform_device *pdev)  {  	struct device *dev = &pdev->dev;  	struct rpi_hwmon_data *data; -	int ret;  	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);  	if (!data) @@ -124,11 +123,6 @@ static int rpi_hwmon_probe(struct platform_device *pdev)  	/* Parent driver assure that firmware is correct */  	data->fw = dev_get_drvdata(dev->parent); -	/* Init throttled */ -	ret = rpi_firmware_property(data->fw, RPI_FIRMWARE_GET_THROTTLED, -				    &data->last_throttled, -				    sizeof(data->last_throttled)); -  	data->hwmon_dev = devm_hwmon_device_register_with_info(dev, "rpi_volt",  							       data,  							       &rpi_chip_info, diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c index 49276bbdac3d..1bb80f992aa8 100644 --- a/drivers/hwmon/w83795.c +++ b/drivers/hwmon/w83795.c @@ -1691,7 +1691,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,   * somewhere else in the code   */  #define SENSOR_ATTR_TEMP(index) {					\ -	SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \ +	SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 5 ? S_IWUSR : 0), \  		show_temp_mode, store_temp_mode, NOT_USED, index - 1),	\  	SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp,		\  		NULL, TEMP_READ, index - 1),				\ diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 56ccb1ea7da5..f2c681971201 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -224,6 +224,15 @@ config I2C_NFORCE2_S4985  	  This driver can also be built as a module.  If so, the module  	  will be called i2c-nforce2-s4985. +config I2C_NVIDIA_GPU +	tristate "NVIDIA GPU I2C controller" +	depends on PCI +	help +	  If you say yes to this option, support will be included for the +	  NVIDIA GPU I2C controller which is used to communicate with the GPU's +	  Type-C controller. This driver can also be built as a module called +	  i2c-nvidia-gpu. +  config I2C_SIS5595  	tristate "SiS 5595"  	depends on PCI @@ -752,7 +761,7 @@ config I2C_OCORES  config I2C_OMAP  	tristate "OMAP I2C adapter" -	depends on ARCH_OMAP +	depends on ARCH_OMAP || ARCH_K3  	default y if MACH_OMAP_H3 || MACH_OMAP_OSK  	help  	  If you say yes to this option, support will be included for the diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 18b26af82b1c..5f0cb6915969 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_I2C_ISCH)		+= i2c-isch.o  obj-$(CONFIG_I2C_ISMT)		+= i2c-ismt.o  obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o  obj-$(CONFIG_I2C_NFORCE2_S4985)	+= i2c-nforce2-s4985.o +obj-$(CONFIG_I2C_NVIDIA_GPU)	+= i2c-nvidia-gpu.o  obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o  obj-$(CONFIG_I2C_SIS5595)	+= i2c-sis5595.o  obj-$(CONFIG_I2C_SIS630)	+= i2c-sis630.o diff --git a/drivers/i2c/busses/i2c-nvidia-gpu.c b/drivers/i2c/busses/i2c-nvidia-gpu.c new file mode 100644 index 000000000000..8822357bca0c --- /dev/null +++ b/drivers/i2c/busses/i2c-nvidia-gpu.c @@ -0,0 +1,368 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Nvidia GPU I2C controller Driver + * + * Copyright (C) 2018 NVIDIA Corporation. All rights reserved. + * Author: Ajay Gupta <ajayg@nvidia.com> + */ +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/interrupt.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/platform_device.h> +#include <linux/pm.h> +#include <linux/pm_runtime.h> + +#include <asm/unaligned.h> + +/* I2C definitions */ +#define I2C_MST_CNTL				0x00 +#define I2C_MST_CNTL_GEN_START			BIT(0) +#define I2C_MST_CNTL_GEN_STOP			BIT(1) +#define I2C_MST_CNTL_CMD_READ			(1 << 2) +#define I2C_MST_CNTL_CMD_WRITE			(2 << 2) +#define I2C_MST_CNTL_BURST_SIZE_SHIFT		6 +#define I2C_MST_CNTL_GEN_NACK			BIT(28) +#define I2C_MST_CNTL_STATUS			GENMASK(30, 29) +#define I2C_MST_CNTL_STATUS_OKAY		(0 << 29) +#define I2C_MST_CNTL_STATUS_NO_ACK		(1 << 29) +#define I2C_MST_CNTL_STATUS_TIMEOUT		(2 << 29) +#define I2C_MST_CNTL_STATUS_BUS_BUSY		(3 << 29) +#define I2C_MST_CNTL_CYCLE_TRIGGER		BIT(31) + +#define I2C_MST_ADDR				0x04 + +#define I2C_MST_I2C0_TIMING				0x08 +#define I2C_MST_I2C0_TIMING_SCL_PERIOD_100KHZ		0x10e +#define I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT		16 +#define I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT_MAX		255 +#define I2C_MST_I2C0_TIMING_TIMEOUT_CHECK		BIT(24) + +#define I2C_MST_DATA					0x0c + +#define I2C_MST_HYBRID_PADCTL				0x20 +#define I2C_MST_HYBRID_PADCTL_MODE_I2C			BIT(0) +#define I2C_MST_HYBRID_PADCTL_I2C_SCL_INPUT_RCV		BIT(14) +#define I2C_MST_HYBRID_PADCTL_I2C_SDA_INPUT_RCV		BIT(15) + +struct gpu_i2c_dev { +	struct device *dev; +	void __iomem *regs; +	struct i2c_adapter adapter; +	struct i2c_board_info *gpu_ccgx_ucsi; +}; + +static void gpu_enable_i2c_bus(struct gpu_i2c_dev *i2cd) +{ +	u32 val; + +	/* enable I2C */ +	val = readl(i2cd->regs + I2C_MST_HYBRID_PADCTL); +	val |= I2C_MST_HYBRID_PADCTL_MODE_I2C | +		I2C_MST_HYBRID_PADCTL_I2C_SCL_INPUT_RCV | +		I2C_MST_HYBRID_PADCTL_I2C_SDA_INPUT_RCV; +	writel(val, i2cd->regs + I2C_MST_HYBRID_PADCTL); + +	/* enable 100KHZ mode */ +	val = I2C_MST_I2C0_TIMING_SCL_PERIOD_100KHZ; +	val |= (I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT_MAX +	    << I2C_MST_I2C0_TIMING_TIMEOUT_CLK_CNT); +	val |= I2C_MST_I2C0_TIMING_TIMEOUT_CHECK; +	writel(val, i2cd->regs + I2C_MST_I2C0_TIMING); +} + +static int gpu_i2c_check_status(struct gpu_i2c_dev *i2cd) +{ +	unsigned long target = jiffies + msecs_to_jiffies(1000); +	u32 val; + +	do { +		val = readl(i2cd->regs + I2C_MST_CNTL); +		if (!(val & I2C_MST_CNTL_CYCLE_TRIGGER)) +			break; +		if ((val & I2C_MST_CNTL_STATUS) != +				I2C_MST_CNTL_STATUS_BUS_BUSY) +			break; +		usleep_range(500, 600); +	} while (time_is_after_jiffies(target)); + +	if (time_is_before_jiffies(target)) { +		dev_err(i2cd->dev, "i2c timeout error %x\n", val); +		return -ETIME; +	} + +	val = readl(i2cd->regs + I2C_MST_CNTL); +	switch (val & I2C_MST_CNTL_STATUS) { +	case I2C_MST_CNTL_STATUS_OKAY: +		return 0; +	case I2C_MST_CNTL_STATUS_NO_ACK: +		return -EIO; +	case I2C_MST_CNTL_STATUS_TIMEOUT: +		return -ETIME; +	default: +		return 0; +	} +} + +static int gpu_i2c_read(struct gpu_i2c_dev *i2cd, u8 *data, u16 len) +{ +	int status; +	u32 val; + +	val = I2C_MST_CNTL_GEN_START | I2C_MST_CNTL_CMD_READ | +		(len << I2C_MST_CNTL_BURST_SIZE_SHIFT) | +		I2C_MST_CNTL_CYCLE_TRIGGER | I2C_MST_CNTL_GEN_NACK; +	writel(val, i2cd->regs + I2C_MST_CNTL); + +	status = gpu_i2c_check_status(i2cd); +	if (status < 0) +		return status; + +	val = readl(i2cd->regs + I2C_MST_DATA); +	switch (len) { +	case 1: +		data[0] = val; +		break; +	case 2: +		put_unaligned_be16(val, data); +		break; +	case 3: +		put_unaligned_be16(val >> 8, data); +		data[2] = val; +		break; +	case 4: +		put_unaligned_be32(val, data); +		break; +	default: +		break; +	} +	return status; +} + +static int gpu_i2c_start(struct gpu_i2c_dev *i2cd) +{ +	writel(I2C_MST_CNTL_GEN_START, i2cd->regs + I2C_MST_CNTL); +	return gpu_i2c_check_status(i2cd); +} + +static int gpu_i2c_stop(struct gpu_i2c_dev *i2cd) +{ +	writel(I2C_MST_CNTL_GEN_STOP, i2cd->regs + I2C_MST_CNTL); +	return gpu_i2c_check_status(i2cd); +} + +static int gpu_i2c_write(struct gpu_i2c_dev *i2cd, u8 data) +{ +	u32 val; + +	writel(data, i2cd->regs + I2C_MST_DATA); + +	val = I2C_MST_CNTL_CMD_WRITE | (1 << I2C_MST_CNTL_BURST_SIZE_SHIFT); +	writel(val, i2cd->regs + I2C_MST_CNTL); + +	return gpu_i2c_check_status(i2cd); +} + +static int gpu_i2c_master_xfer(struct i2c_adapter *adap, +			       struct i2c_msg *msgs, int num) +{ +	struct gpu_i2c_dev *i2cd = i2c_get_adapdata(adap); +	int status, status2; +	int i, j; + +	/* +	 * The controller supports maximum 4 byte read due to known +	 * limitation of sending STOP after every read. +	 */ +	for (i = 0; i < num; i++) { +		if (msgs[i].flags & I2C_M_RD) { +			/* program client address before starting read */ +			writel(msgs[i].addr, i2cd->regs + I2C_MST_ADDR); +			/* gpu_i2c_read has implicit start */ +			status = gpu_i2c_read(i2cd, msgs[i].buf, msgs[i].len); +			if (status < 0) +				goto stop; +		} else { +			u8 addr = i2c_8bit_addr_from_msg(msgs + i); + +			status = gpu_i2c_start(i2cd); +			if (status < 0) { +				if (i == 0) +					return status; +				goto stop; +			} + +			status = gpu_i2c_write(i2cd, addr); +			if (status < 0) +				goto stop; + +			for (j = 0; j < msgs[i].len; j++) { +				status = gpu_i2c_write(i2cd, msgs[i].buf[j]); +				if (status < 0) +					goto stop; +			} +		} +	} +	status = gpu_i2c_stop(i2cd); +	if (status < 0) +		return status; + +	return i; +stop: +	status2 = gpu_i2c_stop(i2cd); +	if (status2 < 0) +		dev_err(i2cd->dev, "i2c stop failed %d\n", status2); +	return status; +} + +static const struct i2c_adapter_quirks gpu_i2c_quirks = { +	.max_read_len = 4, +	.flags = I2C_AQ_COMB_WRITE_THEN_READ, +}; + +static u32 gpu_i2c_functionality(struct i2c_adapter *adap) +{ +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; +} + +static const struct i2c_algorithm gpu_i2c_algorithm = { +	.master_xfer	= gpu_i2c_master_xfer, +	.functionality	= gpu_i2c_functionality, +}; + +/* + * This driver is for Nvidia GPU cards with USB Type-C interface. + * We want to identify the cards using vendor ID and class code only + * to avoid dependency of adding product id for any new card which + * requires this driver. + * Currently there is no class code defined for UCSI device over PCI + * so using UNKNOWN class for now and it will be updated when UCSI + * over PCI gets a class code. + * There is no other NVIDIA cards with UNKNOWN class code. Even if the + * driver gets loaded for an undesired card then eventually i2c_read() + * (initiated from UCSI i2c_client) will timeout or UCSI commands will + * timeout. + */ +#define PCI_CLASS_SERIAL_UNKNOWN	0x0c80 +static const struct pci_device_id gpu_i2c_ids[] = { +	{ PCI_VENDOR_ID_NVIDIA, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, +		PCI_CLASS_SERIAL_UNKNOWN << 8, 0xffffff00}, +	{ } +}; +MODULE_DEVICE_TABLE(pci, gpu_i2c_ids); + +static int gpu_populate_client(struct gpu_i2c_dev *i2cd, int irq) +{ +	struct i2c_client *ccgx_client; + +	i2cd->gpu_ccgx_ucsi = devm_kzalloc(i2cd->dev, +					   sizeof(*i2cd->gpu_ccgx_ucsi), +					   GFP_KERNEL); +	if (!i2cd->gpu_ccgx_ucsi) +		return -ENOMEM; + +	strlcpy(i2cd->gpu_ccgx_ucsi->type, "ccgx-ucsi", +		sizeof(i2cd->gpu_ccgx_ucsi->type)); +	i2cd->gpu_ccgx_ucsi->addr = 0x8; +	i2cd->gpu_ccgx_ucsi->irq = irq; +	ccgx_client = i2c_new_device(&i2cd->adapter, i2cd->gpu_ccgx_ucsi); +	if (!ccgx_client) +		return -ENODEV; + +	return 0; +} + +static int gpu_i2c_probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ +	struct gpu_i2c_dev *i2cd; +	int status; + +	i2cd = devm_kzalloc(&pdev->dev, sizeof(*i2cd), GFP_KERNEL); +	if (!i2cd) +		return -ENOMEM; + +	i2cd->dev = &pdev->dev; +	dev_set_drvdata(&pdev->dev, i2cd); + +	status = pcim_enable_device(pdev); +	if (status < 0) { +		dev_err(&pdev->dev, "pcim_enable_device failed %d\n", status); +		return status; +	} + +	pci_set_master(pdev); + +	i2cd->regs = pcim_iomap(pdev, 0, 0); +	if (!i2cd->regs) { +		dev_err(&pdev->dev, "pcim_iomap failed\n"); +		return -ENOMEM; +	} + +	status = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_MSI); +	if (status < 0) { +		dev_err(&pdev->dev, "pci_alloc_irq_vectors err %d\n", status); +		return status; +	} + +	gpu_enable_i2c_bus(i2cd); + +	i2c_set_adapdata(&i2cd->adapter, i2cd); +	i2cd->adapter.owner = THIS_MODULE; +	strlcpy(i2cd->adapter.name, "NVIDIA GPU I2C adapter", +		sizeof(i2cd->adapter.name)); +	i2cd->adapter.algo = &gpu_i2c_algorithm; +	i2cd->adapter.quirks = &gpu_i2c_quirks; +	i2cd->adapter.dev.parent = &pdev->dev; +	status = i2c_add_adapter(&i2cd->adapter); +	if (status < 0) +		goto free_irq_vectors; + +	status = gpu_populate_client(i2cd, pdev->irq); +	if (status < 0) { +		dev_err(&pdev->dev, "gpu_populate_client failed %d\n", status); +		goto del_adapter; +	} + +	return 0; + +del_adapter: +	i2c_del_adapter(&i2cd->adapter); +free_irq_vectors: +	pci_free_irq_vectors(pdev); +	return status; +} + +static void gpu_i2c_remove(struct pci_dev *pdev) +{ +	struct gpu_i2c_dev *i2cd = dev_get_drvdata(&pdev->dev); + +	i2c_del_adapter(&i2cd->adapter); +	pci_free_irq_vectors(pdev); +} + +static int gpu_i2c_resume(struct device *dev) +{ +	struct gpu_i2c_dev *i2cd = dev_get_drvdata(dev); + +	gpu_enable_i2c_bus(i2cd); +	return 0; +} + +static UNIVERSAL_DEV_PM_OPS(gpu_i2c_driver_pm, NULL, gpu_i2c_resume, NULL); + +static struct pci_driver gpu_i2c_driver = { +	.name		= "nvidia-gpu", +	.id_table	= gpu_i2c_ids, +	.probe		= gpu_i2c_probe, +	.remove		= gpu_i2c_remove, +	.driver		= { +		.pm	= &gpu_i2c_driver_pm, +	}, +}; + +module_pci_driver(gpu_i2c_driver); + +MODULE_AUTHOR("Ajay Gupta <ajayg@nvidia.com>"); +MODULE_DESCRIPTION("Nvidia GPU I2C controller Driver"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 527f55c8c4c7..db075bc0d952 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -571,18 +571,19 @@ static int geni_i2c_probe(struct platform_device *pdev)  	dev_dbg(&pdev->dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth); -	ret = i2c_add_adapter(&gi2c->adap); -	if (ret) { -		dev_err(&pdev->dev, "Error adding i2c adapter %d\n", ret); -		return ret; -	} -  	gi2c->suspended = 1;  	pm_runtime_set_suspended(gi2c->se.dev);  	pm_runtime_set_autosuspend_delay(gi2c->se.dev, I2C_AUTO_SUSPEND_DELAY);  	pm_runtime_use_autosuspend(gi2c->se.dev);  	pm_runtime_enable(gi2c->se.dev); +	ret = i2c_add_adapter(&gi2c->adap); +	if (ret) { +		dev_err(&pdev->dev, "Error adding i2c adapter %d\n", ret); +		pm_runtime_disable(gi2c->se.dev); +		return ret; +	} +  	return 0;  } @@ -590,8 +591,8 @@ static int geni_i2c_remove(struct platform_device *pdev)  {  	struct geni_i2c_dev *gi2c = platform_get_drvdata(pdev); -	pm_runtime_disable(gi2c->se.dev);  	i2c_del_adapter(&gi2c->adap); +	pm_runtime_disable(gi2c->se.dev);  	return 0;  } diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 45c997430332..4c8c7a620d08 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -614,18 +614,7 @@ static int ide_drivers_show(struct seq_file *s, void *p)  	return 0;  } -static int ide_drivers_open(struct inode *inode, struct file *file) -{ -	return single_open(file, &ide_drivers_show, NULL); -} - -static const struct file_operations ide_drivers_operations = { -	.owner		= THIS_MODULE, -	.open		= ide_drivers_open, -	.read		= seq_read, -	.llseek		= seq_lseek, -	.release	= single_release, -}; +DEFINE_SHOW_ATTRIBUTE(ide_drivers);  void proc_ide_create(void)  { @@ -634,7 +623,7 @@ void proc_ide_create(void)  	if (!proc_ide_root)  		return; -	proc_create("drivers", 0, proc_ide_root, &ide_drivers_operations); +	proc_create("drivers", 0, proc_ide_root, &ide_drivers_fops);  }  void proc_ide_destroy(void) diff --git a/drivers/ide/pmac.c b/drivers/ide/pmac.c index c5b902b86b44..203ed4adc04a 100644 --- a/drivers/ide/pmac.c +++ b/drivers/ide/pmac.c @@ -920,6 +920,7 @@ static u8 pmac_ide_cable_detect(ide_hwif_t *hwif)  	struct device_node *root = of_find_node_by_path("/");  	const char *model = of_get_property(root, "model", NULL); +	of_node_put(root);  	/* Get cable type from device-tree. */  	if (cable && !strncmp(cable, "80-", 3)) {  		/* Some drives fail to detect 80c cable in PowerBook */ diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c index 41d97faf5013..38ff374a3ca4 100644 --- a/drivers/iio/accel/hid-sensor-accel-3d.c +++ b/drivers/iio/accel/hid-sensor-accel-3d.c @@ -149,6 +149,7 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,  	int report_id = -1;  	u32 address;  	int ret_type; +	s32 min;  	struct hid_sensor_hub_device *hsdev =  					accel_state->common_attributes.hsdev; @@ -158,12 +159,14 @@ static int accel_3d_read_raw(struct iio_dev *indio_dev,  	case IIO_CHAN_INFO_RAW:  		hid_sensor_power_state(&accel_state->common_attributes, true);  		report_id = accel_state->accel[chan->scan_index].report_id; +		min = accel_state->accel[chan->scan_index].logical_minimum;  		address = accel_3d_addresses[chan->scan_index];  		if (report_id >= 0)  			*val = sensor_hub_input_attr_get_raw_value(  					accel_state->common_attributes.hsdev,  					hsdev->usage, address, report_id, -					SENSOR_HUB_SYNC); +					SENSOR_HUB_SYNC, +					min < 0);  		else {  			*val = 0;  			hid_sensor_power_state(&accel_state->common_attributes, diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c index 36941e69f959..88e857c4baf4 100644 --- a/drivers/iio/gyro/hid-sensor-gyro-3d.c +++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c @@ -111,6 +111,7 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,  	int report_id = -1;  	u32 address;  	int ret_type; +	s32 min;  	*val = 0;  	*val2 = 0; @@ -118,13 +119,15 @@ static int gyro_3d_read_raw(struct iio_dev *indio_dev,  	case IIO_CHAN_INFO_RAW:  		hid_sensor_power_state(&gyro_state->common_attributes, true);  		report_id = gyro_state->gyro[chan->scan_index].report_id; +		min = gyro_state->gyro[chan->scan_index].logical_minimum;  		address = gyro_3d_addresses[chan->scan_index];  		if (report_id >= 0)  			*val = sensor_hub_input_attr_get_raw_value(  					gyro_state->common_attributes.hsdev,  					HID_USAGE_SENSOR_GYRO_3D, address,  					report_id, -					SENSOR_HUB_SYNC); +					SENSOR_HUB_SYNC, +					min < 0);  		else {  			*val = 0;  			hid_sensor_power_state(&gyro_state->common_attributes, diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c index beab6d6fd6e1..4bc95f31c730 100644 --- a/drivers/iio/humidity/hid-sensor-humidity.c +++ b/drivers/iio/humidity/hid-sensor-humidity.c @@ -75,7 +75,8 @@ static int humidity_read_raw(struct iio_dev *indio_dev,  				HID_USAGE_SENSOR_HUMIDITY,  				HID_USAGE_SENSOR_ATMOSPHERIC_HUMIDITY,  				humid_st->humidity_attr.report_id, -				SENSOR_HUB_SYNC); +				SENSOR_HUB_SYNC, +				humid_st->humidity_attr.logical_minimum < 0);  		hid_sensor_power_state(&humid_st->common_attributes, false);  		return IIO_VAL_INT; diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c index 406caaee9a3c..94f33250ba5a 100644 --- a/drivers/iio/light/hid-sensor-als.c +++ b/drivers/iio/light/hid-sensor-als.c @@ -93,6 +93,7 @@ static int als_read_raw(struct iio_dev *indio_dev,  	int report_id = -1;  	u32 address;  	int ret_type; +	s32 min;  	*val = 0;  	*val2 = 0; @@ -102,8 +103,8 @@ static int als_read_raw(struct iio_dev *indio_dev,  		case  CHANNEL_SCAN_INDEX_INTENSITY:  		case  CHANNEL_SCAN_INDEX_ILLUM:  			report_id = als_state->als_illum.report_id; -			address = -			HID_USAGE_SENSOR_LIGHT_ILLUM; +			min = als_state->als_illum.logical_minimum; +			address = HID_USAGE_SENSOR_LIGHT_ILLUM;  			break;  		default:  			report_id = -1; @@ -116,7 +117,8 @@ static int als_read_raw(struct iio_dev *indio_dev,  					als_state->common_attributes.hsdev,  					HID_USAGE_SENSOR_ALS, address,  					report_id, -					SENSOR_HUB_SYNC); +					SENSOR_HUB_SYNC, +					min < 0);  			hid_sensor_power_state(&als_state->common_attributes,  						false);  		} else { diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c index 45107f7537b5..cf5a0c242609 100644 --- a/drivers/iio/light/hid-sensor-prox.c +++ b/drivers/iio/light/hid-sensor-prox.c @@ -73,6 +73,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,  	int report_id = -1;  	u32 address;  	int ret_type; +	s32 min;  	*val = 0;  	*val2 = 0; @@ -81,8 +82,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,  		switch (chan->scan_index) {  		case  CHANNEL_SCAN_INDEX_PRESENCE:  			report_id = prox_state->prox_attr.report_id; -			address = -			HID_USAGE_SENSOR_HUMAN_PRESENCE; +			min = prox_state->prox_attr.logical_minimum; +			address = HID_USAGE_SENSOR_HUMAN_PRESENCE;  			break;  		default:  			report_id = -1; @@ -95,7 +96,8 @@ static int prox_read_raw(struct iio_dev *indio_dev,  				prox_state->common_attributes.hsdev,  				HID_USAGE_SENSOR_PROX, address,  				report_id, -				SENSOR_HUB_SYNC); +				SENSOR_HUB_SYNC, +				min < 0);  			hid_sensor_power_state(&prox_state->common_attributes,  						false);  		} else { diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c index d55c4885211a..f3c0d41e5a8c 100644 --- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c +++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c @@ -163,21 +163,23 @@ static int magn_3d_read_raw(struct iio_dev *indio_dev,  	int report_id = -1;  	u32 address;  	int ret_type; +	s32 min;  	*val = 0;  	*val2 = 0;  	switch (mask) {  	case IIO_CHAN_INFO_RAW:  		hid_sensor_power_state(&magn_state->magn_flux_attributes, true); -		report_id = -			magn_state->magn[chan->address].report_id; +		report_id = magn_state->magn[chan->address].report_id; +		min = magn_state->magn[chan->address].logical_minimum;  		address = magn_3d_addresses[chan->address];  		if (report_id >= 0)  			*val = sensor_hub_input_attr_get_raw_value(  				magn_state->magn_flux_attributes.hsdev,  				HID_USAGE_SENSOR_COMPASS_3D, address,  				report_id, -				SENSOR_HUB_SYNC); +				SENSOR_HUB_SYNC, +				min < 0);  		else {  			*val = 0;  			hid_sensor_power_state( diff --git a/drivers/iio/magnetometer/st_magn_buffer.c b/drivers/iio/magnetometer/st_magn_buffer.c index 0a9e8fadfa9d..37ab30566464 100644 --- a/drivers/iio/magnetometer/st_magn_buffer.c +++ b/drivers/iio/magnetometer/st_magn_buffer.c @@ -30,11 +30,6 @@ int st_magn_trig_set_state(struct iio_trigger *trig, bool state)  	return st_sensors_set_dataready_irq(indio_dev, state);  } -static int st_magn_buffer_preenable(struct iio_dev *indio_dev) -{ -	return st_sensors_set_enable(indio_dev, true); -} -  static int st_magn_buffer_postenable(struct iio_dev *indio_dev)  {  	int err; @@ -50,7 +45,7 @@ static int st_magn_buffer_postenable(struct iio_dev *indio_dev)  	if (err < 0)  		goto st_magn_buffer_postenable_error; -	return err; +	return st_sensors_set_enable(indio_dev, true);  st_magn_buffer_postenable_error:  	kfree(mdata->buffer_data); @@ -63,11 +58,11 @@ static int st_magn_buffer_predisable(struct iio_dev *indio_dev)  	int err;  	struct st_sensor_data *mdata = iio_priv(indio_dev); -	err = iio_triggered_buffer_predisable(indio_dev); +	err = st_sensors_set_enable(indio_dev, false);  	if (err < 0)  		goto st_magn_buffer_predisable_error; -	err = st_sensors_set_enable(indio_dev, false); +	err = iio_triggered_buffer_predisable(indio_dev);  st_magn_buffer_predisable_error:  	kfree(mdata->buffer_data); @@ -75,7 +70,6 @@ st_magn_buffer_predisable_error:  }  static const struct iio_buffer_setup_ops st_magn_buffer_setup_ops = { -	.preenable = &st_magn_buffer_preenable,  	.postenable = &st_magn_buffer_postenable,  	.predisable = &st_magn_buffer_predisable,  }; diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c index 1e5451d1ff88..bdc5e4554ee4 100644 --- a/drivers/iio/orientation/hid-sensor-incl-3d.c +++ b/drivers/iio/orientation/hid-sensor-incl-3d.c @@ -111,21 +111,23 @@ static int incl_3d_read_raw(struct iio_dev *indio_dev,  	int report_id = -1;  	u32 address;  	int ret_type; +	s32 min;  	*val = 0;  	*val2 = 0;  	switch (mask) {  	case IIO_CHAN_INFO_RAW:  		hid_sensor_power_state(&incl_state->common_attributes, true); -		report_id = -			incl_state->incl[chan->scan_index].report_id; +		report_id = incl_state->incl[chan->scan_index].report_id; +		min = incl_state->incl[chan->scan_index].logical_minimum;  		address = incl_3d_addresses[chan->scan_index];  		if (report_id >= 0)  			*val = sensor_hub_input_attr_get_raw_value(  				incl_state->common_attributes.hsdev,  				HID_USAGE_SENSOR_INCLINOMETER_3D, address,  				report_id, -				SENSOR_HUB_SYNC); +				SENSOR_HUB_SYNC, +				min < 0);  		else {  			hid_sensor_power_state(&incl_state->common_attributes,  						false); diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c index 4c437918f1d2..d7b1c00ceb4d 100644 --- a/drivers/iio/pressure/hid-sensor-press.c +++ b/drivers/iio/pressure/hid-sensor-press.c @@ -77,6 +77,7 @@ static int press_read_raw(struct iio_dev *indio_dev,  	int report_id = -1;  	u32 address;  	int ret_type; +	s32 min;  	*val = 0;  	*val2 = 0; @@ -85,8 +86,8 @@ static int press_read_raw(struct iio_dev *indio_dev,  		switch (chan->scan_index) {  		case  CHANNEL_SCAN_INDEX_PRESSURE:  			report_id = press_state->press_attr.report_id; -			address = -			HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE; +			min = press_state->press_attr.logical_minimum; +			address = HID_USAGE_SENSOR_ATMOSPHERIC_PRESSURE;  			break;  		default:  			report_id = -1; @@ -99,7 +100,8 @@ static int press_read_raw(struct iio_dev *indio_dev,  				press_state->common_attributes.hsdev,  				HID_USAGE_SENSOR_PRESSURE, address,  				report_id, -				SENSOR_HUB_SYNC); +				SENSOR_HUB_SYNC, +				min < 0);  			hid_sensor_power_state(&press_state->common_attributes,  						false);  		} else { diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c index beaf6fd3e337..b592fc4f007e 100644 --- a/drivers/iio/temperature/hid-sensor-temperature.c +++ b/drivers/iio/temperature/hid-sensor-temperature.c @@ -76,7 +76,8 @@ static int temperature_read_raw(struct iio_dev *indio_dev,  			HID_USAGE_SENSOR_TEMPERATURE,  			HID_USAGE_SENSOR_DATA_ENVIRONMENTAL_TEMPERATURE,  			temp_st->temperature_attr.report_id, -			SENSOR_HUB_SYNC); +			SENSOR_HUB_SYNC, +			temp_st->temperature_attr.logical_minimum < 0);  		hid_sensor_power_state(  				&temp_st->common_attributes,  				false); diff --git a/drivers/infiniband/core/roce_gid_mgmt.c b/drivers/infiniband/core/roce_gid_mgmt.c index ee366199b169..25d43c8f1c2a 100644 --- a/drivers/infiniband/core/roce_gid_mgmt.c +++ b/drivers/infiniband/core/roce_gid_mgmt.c @@ -767,8 +767,10 @@ static int netdevice_event(struct notifier_block *this, unsigned long event,  	case NETDEV_CHANGEADDR:  		cmds[0] = netdev_del_cmd; -		cmds[1] = add_default_gid_cmd; -		cmds[2] = add_cmd; +		if (ndev->reg_state == NETREG_REGISTERED) { +			cmds[1] = add_default_gid_cmd; +			cmds[2] = add_cmd; +		}  		break;  	case NETDEV_CHANGEUPPER: diff --git a/drivers/infiniband/core/umem_odp.c b/drivers/infiniband/core/umem_odp.c index 2b4c5e7dd5a1..676c1fd1119d 100644 --- a/drivers/infiniband/core/umem_odp.c +++ b/drivers/infiniband/core/umem_odp.c @@ -137,15 +137,6 @@ static void ib_umem_notifier_release(struct mmu_notifier *mn,  	up_read(&per_mm->umem_rwsem);  } -static int invalidate_page_trampoline(struct ib_umem_odp *item, u64 start, -				      u64 end, void *cookie) -{ -	ib_umem_notifier_start_account(item); -	item->umem.context->invalidate_range(item, start, start + PAGE_SIZE); -	ib_umem_notifier_end_account(item); -	return 0; -} -  static int invalidate_range_start_trampoline(struct ib_umem_odp *item,  					     u64 start, u64 end, void *cookie)  { @@ -553,12 +544,13 @@ out:  		put_page(page);  	if (remove_existing_mapping && umem->context->invalidate_range) { -		invalidate_page_trampoline( +		ib_umem_notifier_start_account(umem_odp); +		umem->context->invalidate_range(  			umem_odp, -			ib_umem_start(umem) + (page_index >> umem->page_shift), -			ib_umem_start(umem) + ((page_index + 1) >> -					       umem->page_shift), -			NULL); +			ib_umem_start(umem) + (page_index << umem->page_shift), +			ib_umem_start(umem) + +				((page_index + 1) << umem->page_shift)); +		ib_umem_notifier_end_account(umem_odp);  		ret = -EAGAIN;  	} diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c index cf2282654210..77f095e5fbe3 100644 --- a/drivers/infiniband/hw/bnxt_re/main.c +++ b/drivers/infiniband/hw/bnxt_re/main.c @@ -1268,6 +1268,7 @@ static int bnxt_re_ib_reg(struct bnxt_re_dev *rdev)  	/* Registered a new RoCE device instance to netdev */  	rc = bnxt_re_register_netdev(rdev);  	if (rc) { +		rtnl_unlock();  		pr_err("Failed to register with netedev: %#x\n", rc);  		return -EINVAL;  	} @@ -1466,6 +1467,7 @@ static void bnxt_re_task(struct work_struct *work)  				"Failed to register with IB: %#x", rc);  			bnxt_re_remove_one(rdev);  			bnxt_re_dev_unreg(rdev); +			goto exit;  		}  		break;  	case NETDEV_UP: @@ -1489,6 +1491,7 @@ static void bnxt_re_task(struct work_struct *work)  	}  	smp_mb__before_atomic();  	atomic_dec(&rdev->sched_count); +exit:  	kfree(re_work);  } diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index a4c62ae23a9a..3beb1523e17c 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -1756,10 +1756,9 @@ static int hns_roce_v2_set_mac(struct hns_roce_dev *hr_dev, u8 phy_port,  	return hns_roce_cmq_send(hr_dev, &desc, 1);  } -static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr, -				  unsigned long mtpt_idx) +static int set_mtpt_pbl(struct hns_roce_v2_mpt_entry *mpt_entry, +			struct hns_roce_mr *mr)  { -	struct hns_roce_v2_mpt_entry *mpt_entry;  	struct scatterlist *sg;  	u64 page_addr;  	u64 *pages; @@ -1767,6 +1766,53 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,  	int len;  	int entry; +	mpt_entry->pbl_size = cpu_to_le32(mr->pbl_size); +	mpt_entry->pbl_ba_l = cpu_to_le32(lower_32_bits(mr->pbl_ba >> 3)); +	roce_set_field(mpt_entry->byte_48_mode_ba, +		       V2_MPT_BYTE_48_PBL_BA_H_M, V2_MPT_BYTE_48_PBL_BA_H_S, +		       upper_32_bits(mr->pbl_ba >> 3)); + +	pages = (u64 *)__get_free_page(GFP_KERNEL); +	if (!pages) +		return -ENOMEM; + +	i = 0; +	for_each_sg(mr->umem->sg_head.sgl, sg, mr->umem->nmap, entry) { +		len = sg_dma_len(sg) >> PAGE_SHIFT; +		for (j = 0; j < len; ++j) { +			page_addr = sg_dma_address(sg) + +				(j << mr->umem->page_shift); +			pages[i] = page_addr >> 6; +			/* Record the first 2 entry directly to MTPT table */ +			if (i >= HNS_ROCE_V2_MAX_INNER_MTPT_NUM - 1) +				goto found; +			i++; +		} +	} +found: +	mpt_entry->pa0_l = cpu_to_le32(lower_32_bits(pages[0])); +	roce_set_field(mpt_entry->byte_56_pa0_h, V2_MPT_BYTE_56_PA0_H_M, +		       V2_MPT_BYTE_56_PA0_H_S, upper_32_bits(pages[0])); + +	mpt_entry->pa1_l = cpu_to_le32(lower_32_bits(pages[1])); +	roce_set_field(mpt_entry->byte_64_buf_pa1, V2_MPT_BYTE_64_PA1_H_M, +		       V2_MPT_BYTE_64_PA1_H_S, upper_32_bits(pages[1])); +	roce_set_field(mpt_entry->byte_64_buf_pa1, +		       V2_MPT_BYTE_64_PBL_BUF_PG_SZ_M, +		       V2_MPT_BYTE_64_PBL_BUF_PG_SZ_S, +		       mr->pbl_buf_pg_sz + PG_SHIFT_OFFSET); + +	free_page((unsigned long)pages); + +	return 0; +} + +static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr, +				  unsigned long mtpt_idx) +{ +	struct hns_roce_v2_mpt_entry *mpt_entry; +	int ret; +  	mpt_entry = mb_buf;  	memset(mpt_entry, 0, sizeof(*mpt_entry)); @@ -1781,7 +1827,6 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,  		       mr->pbl_ba_pg_sz + PG_SHIFT_OFFSET);  	roce_set_field(mpt_entry->byte_4_pd_hop_st, V2_MPT_BYTE_4_PD_M,  		       V2_MPT_BYTE_4_PD_S, mr->pd); -	mpt_entry->byte_4_pd_hop_st = cpu_to_le32(mpt_entry->byte_4_pd_hop_st);  	roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_RA_EN_S, 0);  	roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_R_INV_EN_S, 1); @@ -1796,13 +1841,11 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,  		     (mr->access & IB_ACCESS_REMOTE_WRITE ? 1 : 0));  	roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S,  		     (mr->access & IB_ACCESS_LOCAL_WRITE ? 1 : 0)); -	mpt_entry->byte_8_mw_cnt_en = cpu_to_le32(mpt_entry->byte_8_mw_cnt_en);  	roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_PA_S,  		     mr->type == MR_TYPE_MR ? 0 : 1);  	roce_set_bit(mpt_entry->byte_12_mw_pa, V2_MPT_BYTE_12_INNER_PA_VLD_S,  		     1); -	mpt_entry->byte_12_mw_pa = cpu_to_le32(mpt_entry->byte_12_mw_pa);  	mpt_entry->len_l = cpu_to_le32(lower_32_bits(mr->size));  	mpt_entry->len_h = cpu_to_le32(upper_32_bits(mr->size)); @@ -1813,53 +1856,9 @@ static int hns_roce_v2_write_mtpt(void *mb_buf, struct hns_roce_mr *mr,  	if (mr->type == MR_TYPE_DMA)  		return 0; -	mpt_entry->pbl_size = cpu_to_le32(mr->pbl_size); - -	mpt_entry->pbl_ba_l = cpu_to_le32(lower_32_bits(mr->pbl_ba >> 3)); -	roce_set_field(mpt_entry->byte_48_mode_ba, V2_MPT_BYTE_48_PBL_BA_H_M, -		       V2_MPT_BYTE_48_PBL_BA_H_S, -		       upper_32_bits(mr->pbl_ba >> 3)); -	mpt_entry->byte_48_mode_ba = cpu_to_le32(mpt_entry->byte_48_mode_ba); - -	pages = (u64 *)__get_free_page(GFP_KERNEL); -	if (!pages) -		return -ENOMEM; - -	i = 0; -	for_each_sg(mr->umem->sg_head.sgl, sg, mr->umem->nmap, entry) { -		len = sg_dma_len(sg) >> PAGE_SHIFT; -		for (j = 0; j < len; ++j) { -			page_addr = sg_dma_address(sg) + -				    (j << mr->umem->page_shift); -			pages[i] = page_addr >> 6; - -			/* Record the first 2 entry directly to MTPT table */ -			if (i >= HNS_ROCE_V2_MAX_INNER_MTPT_NUM - 1) -				goto found; -			i++; -		} -	} - -found: -	mpt_entry->pa0_l = cpu_to_le32(lower_32_bits(pages[0])); -	roce_set_field(mpt_entry->byte_56_pa0_h, V2_MPT_BYTE_56_PA0_H_M, -		       V2_MPT_BYTE_56_PA0_H_S, -		       upper_32_bits(pages[0])); -	mpt_entry->byte_56_pa0_h = cpu_to_le32(mpt_entry->byte_56_pa0_h); - -	mpt_entry->pa1_l = cpu_to_le32(lower_32_bits(pages[1])); -	roce_set_field(mpt_entry->byte_64_buf_pa1, V2_MPT_BYTE_64_PA1_H_M, -		       V2_MPT_BYTE_64_PA1_H_S, upper_32_bits(pages[1])); +	ret = set_mtpt_pbl(mpt_entry, mr); -	free_page((unsigned long)pages); - -	roce_set_field(mpt_entry->byte_64_buf_pa1, -		       V2_MPT_BYTE_64_PBL_BUF_PG_SZ_M, -		       V2_MPT_BYTE_64_PBL_BUF_PG_SZ_S, -		       mr->pbl_buf_pg_sz + PG_SHIFT_OFFSET); -	mpt_entry->byte_64_buf_pa1 = cpu_to_le32(mpt_entry->byte_64_buf_pa1); - -	return 0; +	return ret;  }  static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev, @@ -1868,6 +1867,7 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,  					u64 size, void *mb_buf)  {  	struct hns_roce_v2_mpt_entry *mpt_entry = mb_buf; +	int ret = 0;  	if (flags & IB_MR_REREG_PD) {  		roce_set_field(mpt_entry->byte_4_pd_hop_st, V2_MPT_BYTE_4_PD_M, @@ -1880,14 +1880,14 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,  			     V2_MPT_BYTE_8_BIND_EN_S,  			     (mr_access_flags & IB_ACCESS_MW_BIND ? 1 : 0));  		roce_set_bit(mpt_entry->byte_8_mw_cnt_en, -			   V2_MPT_BYTE_8_ATOMIC_EN_S, -			   (mr_access_flags & IB_ACCESS_REMOTE_ATOMIC ? 1 : 0)); +			     V2_MPT_BYTE_8_ATOMIC_EN_S, +			     mr_access_flags & IB_ACCESS_REMOTE_ATOMIC ? 1 : 0);  		roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_RR_EN_S, -			     (mr_access_flags & IB_ACCESS_REMOTE_READ ? 1 : 0)); +			     mr_access_flags & IB_ACCESS_REMOTE_READ ? 1 : 0);  		roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_RW_EN_S, -			    (mr_access_flags & IB_ACCESS_REMOTE_WRITE ? 1 : 0)); +			     mr_access_flags & IB_ACCESS_REMOTE_WRITE ? 1 : 0);  		roce_set_bit(mpt_entry->byte_8_mw_cnt_en, V2_MPT_BYTE_8_LW_EN_S, -			     (mr_access_flags & IB_ACCESS_LOCAL_WRITE ? 1 : 0)); +			     mr_access_flags & IB_ACCESS_LOCAL_WRITE ? 1 : 0);  	}  	if (flags & IB_MR_REREG_TRANS) { @@ -1896,21 +1896,13 @@ static int hns_roce_v2_rereg_write_mtpt(struct hns_roce_dev *hr_dev,  		mpt_entry->len_l = cpu_to_le32(lower_32_bits(size));  		mpt_entry->len_h = cpu_to_le32(upper_32_bits(size)); -		mpt_entry->pbl_size = cpu_to_le32(mr->pbl_size); -		mpt_entry->pbl_ba_l = -				cpu_to_le32(lower_32_bits(mr->pbl_ba >> 3)); -		roce_set_field(mpt_entry->byte_48_mode_ba, -			       V2_MPT_BYTE_48_PBL_BA_H_M, -			       V2_MPT_BYTE_48_PBL_BA_H_S, -			       upper_32_bits(mr->pbl_ba >> 3)); -		mpt_entry->byte_48_mode_ba = -				cpu_to_le32(mpt_entry->byte_48_mode_ba); -  		mr->iova = iova;  		mr->size = size; + +		ret = set_mtpt_pbl(mpt_entry, mr);  	} -	return 0; +	return ret;  }  static int hns_roce_v2_frmr_write_mtpt(void *mb_buf, struct hns_roce_mr *mr) diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c index e9c428071df3..3569fda07e07 100644 --- a/drivers/infiniband/hw/mlx5/main.c +++ b/drivers/infiniband/hw/mlx5/main.c @@ -1094,31 +1094,26 @@ enum mlx5_ib_width {  	MLX5_IB_WIDTH_12X	= 1 << 4  }; -static int translate_active_width(struct ib_device *ibdev, u8 active_width, +static void translate_active_width(struct ib_device *ibdev, u8 active_width,  				  u8 *ib_width)  {  	struct mlx5_ib_dev *dev = to_mdev(ibdev); -	int err = 0; -	if (active_width & MLX5_IB_WIDTH_1X) { +	if (active_width & MLX5_IB_WIDTH_1X)  		*ib_width = IB_WIDTH_1X; -	} else if (active_width & MLX5_IB_WIDTH_2X) { -		mlx5_ib_dbg(dev, "active_width %d is not supported by IB spec\n", -			    (int)active_width); -		err = -EINVAL; -	} else if (active_width & MLX5_IB_WIDTH_4X) { +	else if (active_width & MLX5_IB_WIDTH_4X)  		*ib_width = IB_WIDTH_4X; -	} else if (active_width & MLX5_IB_WIDTH_8X) { +	else if (active_width & MLX5_IB_WIDTH_8X)  		*ib_width = IB_WIDTH_8X; -	} else if (active_width & MLX5_IB_WIDTH_12X) { +	else if (active_width & MLX5_IB_WIDTH_12X)  		*ib_width = IB_WIDTH_12X; -	} else { -		mlx5_ib_dbg(dev, "Invalid active_width %d\n", +	else { +		mlx5_ib_dbg(dev, "Invalid active_width %d, setting width to default value: 4x\n",  			    (int)active_width); -		err = -EINVAL; +		*ib_width = IB_WIDTH_4X;  	} -	return err; +	return;  }  static int mlx5_mtu_to_ib_mtu(int mtu) @@ -1225,10 +1220,8 @@ static int mlx5_query_hca_port(struct ib_device *ibdev, u8 port,  	if (err)  		goto out; -	err = translate_active_width(ibdev, ib_link_width_oper, -				     &props->active_width); -	if (err) -		goto out; +	translate_active_width(ibdev, ib_link_width_oper, &props->active_width); +  	err = mlx5_query_port_ib_proto_oper(mdev, &props->active_speed, port);  	if (err)  		goto out; diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c index b04eb6775326..2cc3d69ab6f6 100644 --- a/drivers/infiniband/hw/mlx5/odp.c +++ b/drivers/infiniband/hw/mlx5/odp.c @@ -674,6 +674,15 @@ next_mr:  			goto srcu_unlock;  		} +		if (!mr->umem->is_odp) { +			mlx5_ib_dbg(dev, "skipping non ODP MR (lkey=0x%06x) in page fault handler.\n", +				    key); +			if (bytes_mapped) +				*bytes_mapped += bcnt; +			ret = 0; +			goto srcu_unlock; +		} +  		ret = pagefault_mr(dev, mr, io_virt, bcnt, bytes_mapped);  		if (ret < 0)  			goto srcu_unlock; @@ -735,6 +744,7 @@ next_mr:  			head = frame;  			bcnt -= frame->bcnt; +			offset = 0;  		}  		break; diff --git a/drivers/infiniband/hw/mlx5/qp.c b/drivers/infiniband/hw/mlx5/qp.c index 6841c0f9237f..3747cc681b18 100644 --- a/drivers/infiniband/hw/mlx5/qp.c +++ b/drivers/infiniband/hw/mlx5/qp.c @@ -2633,8 +2633,7 @@ static int to_mlx5_access_flags(struct mlx5_ib_qp *qp,  	if (access_flags & IB_ACCESS_REMOTE_READ)  		*hw_access_flags |= MLX5_QP_BIT_RRE; -	if ((access_flags & IB_ACCESS_REMOTE_ATOMIC) && -	    qp->ibqp.qp_type == IB_QPT_RC) { +	if (access_flags & IB_ACCESS_REMOTE_ATOMIC) {  		int atomic_mode;  		atomic_mode = get_atomic_mode(dev, qp->ibqp.qp_type); @@ -4678,17 +4677,18 @@ static int _mlx5_ib_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,  			goto out;  		} -		if (wr->opcode == IB_WR_LOCAL_INV || -		    wr->opcode == IB_WR_REG_MR) { +		if (wr->opcode == IB_WR_REG_MR) {  			fence = dev->umr_fence;  			next_fence = MLX5_FENCE_MODE_INITIATOR_SMALL; -		} else if (wr->send_flags & IB_SEND_FENCE) { -			if (qp->next_fence) -				fence = MLX5_FENCE_MODE_SMALL_AND_FENCE; -			else -				fence = MLX5_FENCE_MODE_FENCE; -		} else { -			fence = qp->next_fence; +		} else  { +			if (wr->send_flags & IB_SEND_FENCE) { +				if (qp->next_fence) +					fence = MLX5_FENCE_MODE_SMALL_AND_FENCE; +				else +					fence = MLX5_FENCE_MODE_FENCE; +			} else { +				fence = qp->next_fence; +			}  		}  		switch (ibqp->qp_type) { diff --git a/drivers/infiniband/sw/rdmavt/ah.c b/drivers/infiniband/sw/rdmavt/ah.c index 89ec0f64abfc..084bb4baebb5 100644 --- a/drivers/infiniband/sw/rdmavt/ah.c +++ b/drivers/infiniband/sw/rdmavt/ah.c @@ -91,13 +91,15 @@ EXPORT_SYMBOL(rvt_check_ah);   * rvt_create_ah - create an address handle   * @pd: the protection domain   * @ah_attr: the attributes of the AH + * @udata: pointer to user's input output buffer information.   *   * This may be called from interrupt context.   *   * Return: newly allocated ah   */  struct ib_ah *rvt_create_ah(struct ib_pd *pd, -			    struct rdma_ah_attr *ah_attr) +			    struct rdma_ah_attr *ah_attr, +			    struct ib_udata *udata)  {  	struct rvt_ah *ah;  	struct rvt_dev_info *dev = ib_to_rvt(pd->device); diff --git a/drivers/infiniband/sw/rdmavt/ah.h b/drivers/infiniband/sw/rdmavt/ah.h index 16105af99189..25271b48a683 100644 --- a/drivers/infiniband/sw/rdmavt/ah.h +++ b/drivers/infiniband/sw/rdmavt/ah.h @@ -51,7 +51,8 @@  #include <rdma/rdma_vt.h>  struct ib_ah *rvt_create_ah(struct ib_pd *pd, -			    struct rdma_ah_attr *ah_attr); +			    struct rdma_ah_attr *ah_attr, +			    struct ib_udata *udata);  int rvt_destroy_ah(struct ib_ah *ibah);  int rvt_modify_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr);  int rvt_query_ah(struct ib_ah *ibah, struct rdma_ah_attr *ah_attr); diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 946b623ba5eb..4ff3d98fa6a4 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -1124,7 +1124,9 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,  					 IB_MR_CHECK_SIG_STATUS, &mr_status);  		if (ret) {  			pr_err("ib_check_mr_status failed, ret %d\n", ret); -			goto err; +			/* Not a lot we can do, return ambiguous guard error */ +			*sector = 0; +			return 0x1;  		}  		if (mr_status.fail_status & IB_MR_CHECK_SIG_STATUS) { @@ -1152,9 +1154,6 @@ u8 iser_check_task_pi_status(struct iscsi_iser_task *iser_task,  	}  	return 0; -err: -	/* Not alot we can do here, return ambiguous guard error */ -	return 0x1;  }  void iser_err_comp(struct ib_wc *wc, const char *type) diff --git a/drivers/input/joystick/xpad.c b/drivers/input/joystick/xpad.c index d4b9db487b16..cfc8b94527b9 100644 --- a/drivers/input/joystick/xpad.c +++ b/drivers/input/joystick/xpad.c @@ -480,18 +480,18 @@ static const u8 xboxone_hori_init[] = {  };  /* - * This packet is required for some of the PDP pads to start + * This packet is required for most (all?) of the PDP pads to start   * sending input reports. These pads include: (0x0e6f:0x02ab), - * (0x0e6f:0x02a4). + * (0x0e6f:0x02a4), (0x0e6f:0x02a6).   */  static const u8 xboxone_pdp_init1[] = {  	0x0a, 0x20, 0x00, 0x03, 0x00, 0x01, 0x14  };  /* - * This packet is required for some of the PDP pads to start + * This packet is required for most (all?) of the PDP pads to start   * sending input reports. These pads include: (0x0e6f:0x02ab), - * (0x0e6f:0x02a4). + * (0x0e6f:0x02a4), (0x0e6f:0x02a6).   */  static const u8 xboxone_pdp_init2[] = {  	0x06, 0x20, 0x00, 0x02, 0x01, 0x00 @@ -527,12 +527,8 @@ static const struct xboxone_init_packet xboxone_init_packets[] = {  	XBOXONE_INIT_PKT(0x0e6f, 0x0165, xboxone_hori_init),  	XBOXONE_INIT_PKT(0x0f0d, 0x0067, xboxone_hori_init),  	XBOXONE_INIT_PKT(0x0000, 0x0000, xboxone_fw2015_init), -	XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init1), -	XBOXONE_INIT_PKT(0x0e6f, 0x02ab, xboxone_pdp_init2), -	XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init1), -	XBOXONE_INIT_PKT(0x0e6f, 0x02a4, xboxone_pdp_init2), -	XBOXONE_INIT_PKT(0x0e6f, 0x02a6, xboxone_pdp_init1), -	XBOXONE_INIT_PKT(0x0e6f, 0x02a6, xboxone_pdp_init2), +	XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init1), +	XBOXONE_INIT_PKT(0x0e6f, 0x0000, xboxone_pdp_init2),  	XBOXONE_INIT_PKT(0x24c6, 0x541a, xboxone_rumblebegin_init),  	XBOXONE_INIT_PKT(0x24c6, 0x542a, xboxone_rumblebegin_init),  	XBOXONE_INIT_PKT(0x24c6, 0x543a, xboxone_rumblebegin_init), diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c index 7e75835e220f..850bb259c20e 100644 --- a/drivers/input/keyboard/atkbd.c +++ b/drivers/input/keyboard/atkbd.c @@ -841,7 +841,7 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra  	if (param[0] != 3) {  		param[0] = 2;  		if (ps2_command(ps2dev, param, ATKBD_CMD_SSCANSET)) -		return 2; +			return 2;  	}  	ps2_command(ps2dev, param, ATKBD_CMD_SETALL_MBR); diff --git a/drivers/input/keyboard/cros_ec_keyb.c b/drivers/input/keyboard/cros_ec_keyb.c index 81be6f781f0b..d56001181598 100644 --- a/drivers/input/keyboard/cros_ec_keyb.c +++ b/drivers/input/keyboard/cros_ec_keyb.c @@ -493,7 +493,8 @@ static int cros_ec_keyb_register_bs(struct cros_ec_keyb *ckdev)  	for (i = 0; i < ARRAY_SIZE(cros_ec_keyb_bs); i++) {  		const struct cros_ec_bs_map *map = &cros_ec_keyb_bs[i]; -		if (buttons & BIT(map->bit)) +		if ((map->ev_type == EV_KEY && (buttons & BIT(map->bit))) || +		    (map->ev_type == EV_SW && (switches & BIT(map->bit))))  			input_set_capability(idev, map->ev_type, map->code);  	} diff --git a/drivers/input/keyboard/matrix_keypad.c b/drivers/input/keyboard/matrix_keypad.c index f51ae09596ef..403452ef00e6 100644 --- a/drivers/input/keyboard/matrix_keypad.c +++ b/drivers/input/keyboard/matrix_keypad.c @@ -407,7 +407,7 @@ matrix_keypad_parse_dt(struct device *dev)  	struct matrix_keypad_platform_data *pdata;  	struct device_node *np = dev->of_node;  	unsigned int *gpios; -	int i, nrow, ncol; +	int ret, i, nrow, ncol;  	if (!np) {  		dev_err(dev, "device lacks DT data\n"); @@ -452,12 +452,19 @@ matrix_keypad_parse_dt(struct device *dev)  		return ERR_PTR(-ENOMEM);  	} -	for (i = 0; i < pdata->num_row_gpios; i++) -		gpios[i] = of_get_named_gpio(np, "row-gpios", i); +	for (i = 0; i < nrow; i++) { +		ret = of_get_named_gpio(np, "row-gpios", i); +		if (ret < 0) +			return ERR_PTR(ret); +		gpios[i] = ret; +	} -	for (i = 0; i < pdata->num_col_gpios; i++) -		gpios[pdata->num_row_gpios + i] = -			of_get_named_gpio(np, "col-gpios", i); +	for (i = 0; i < ncol; i++) { +		ret = of_get_named_gpio(np, "col-gpios", i); +		if (ret < 0) +			return ERR_PTR(ret); +		gpios[nrow + i] = ret; +	}  	pdata->row_gpios = gpios;  	pdata->col_gpios = &gpios[pdata->num_row_gpios]; @@ -484,10 +491,8 @@ static int matrix_keypad_probe(struct platform_device *pdev)  	pdata = dev_get_platdata(&pdev->dev);  	if (!pdata) {  		pdata = matrix_keypad_parse_dt(&pdev->dev); -		if (IS_ERR(pdata)) { -			dev_err(&pdev->dev, "no platform data defined\n"); +		if (IS_ERR(pdata))  			return PTR_ERR(pdata); -		}  	} else if (!pdata->keymap_data) {  		dev_err(&pdev->dev, "no keymap data defined\n");  		return -EINVAL; diff --git a/drivers/input/keyboard/omap4-keypad.c b/drivers/input/keyboard/omap4-keypad.c index 46406345742b..a7dc286f406c 100644 --- a/drivers/input/keyboard/omap4-keypad.c +++ b/drivers/input/keyboard/omap4-keypad.c @@ -60,8 +60,18 @@  /* OMAP4 values */  #define OMAP4_VAL_IRQDISABLE		0x0 -#define OMAP4_VAL_DEBOUNCINGTIME	0x7 -#define OMAP4_VAL_PVT			0x7 + +/* + * Errata i689: If a key is released for a time shorter than debounce time, + * the keyboard will idle and never detect the key release. The workaround + * is to use at least a 12ms debounce time. See omap5432 TRM chapter + * "26.4.6.2 Keyboard Controller Timer" for more information. + */ +#define OMAP4_KEYPAD_PTV_DIV_128        0x6 +#define OMAP4_KEYPAD_DEBOUNCINGTIME_MS(dbms, ptv)     \ +	((((dbms) * 1000) / ((1 << ((ptv) + 1)) * (1000000 / 32768))) - 1) +#define OMAP4_VAL_DEBOUNCINGTIME_16MS					\ +	OMAP4_KEYPAD_DEBOUNCINGTIME_MS(16, OMAP4_KEYPAD_PTV_DIV_128)  enum {  	KBD_REVISION_OMAP4 = 0, @@ -181,9 +191,9 @@ static int omap4_keypad_open(struct input_dev *input)  	kbd_writel(keypad_data, OMAP4_KBD_CTRL,  			OMAP4_DEF_CTRL_NOSOFTMODE | -			(OMAP4_VAL_PVT << OMAP4_DEF_CTRL_PTV_SHIFT)); +			(OMAP4_KEYPAD_PTV_DIV_128 << OMAP4_DEF_CTRL_PTV_SHIFT));  	kbd_writel(keypad_data, OMAP4_KBD_DEBOUNCINGTIME, -			OMAP4_VAL_DEBOUNCINGTIME); +			OMAP4_VAL_DEBOUNCINGTIME_16MS);  	/* clear pending interrupts */  	kbd_write_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS,  			 kbd_read_irqreg(keypad_data, OMAP4_KBD_IRQSTATUS)); diff --git a/drivers/input/mouse/elan_i2c_core.c b/drivers/input/mouse/elan_i2c_core.c index b0f9d19b3410..a94b6494e71a 100644 --- a/drivers/input/mouse/elan_i2c_core.c +++ b/drivers/input/mouse/elan_i2c_core.c @@ -1348,6 +1348,9 @@ static const struct acpi_device_id elan_acpi_id[] = {  	{ "ELAN0618", 0 },  	{ "ELAN061C", 0 },  	{ "ELAN061D", 0 }, +	{ "ELAN061E", 0 }, +	{ "ELAN0620", 0 }, +	{ "ELAN0621", 0 },  	{ "ELAN0622", 0 },  	{ "ELAN1000", 0 },  	{ } diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 5e85f3cca867..2bd5bb11c8ba 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -170,6 +170,7 @@ static const char * const smbus_pnp_ids[] = {  	"LEN0048", /* X1 Carbon 3 */  	"LEN0046", /* X250 */  	"LEN004a", /* W541 */ +	"LEN005b", /* P50 */  	"LEN0071", /* T480 */  	"LEN0072", /* X1 Carbon Gen 5 (2017) - Elan/ALPS trackpoint */  	"LEN0073", /* X1 Carbon G5 (Elantech) */ @@ -177,6 +178,7 @@ static const char * const smbus_pnp_ids[] = {  	"LEN0096", /* X280 */  	"LEN0097", /* X280 -> ALPS trackpoint */  	"LEN200f", /* T450s */ +	"SYN3221", /* HP 15-ay000 */  	NULL  }; diff --git a/drivers/input/serio/hyperv-keyboard.c b/drivers/input/serio/hyperv-keyboard.c index 47a0e81a2989..a8b9be3e28db 100644 --- a/drivers/input/serio/hyperv-keyboard.c +++ b/drivers/input/serio/hyperv-keyboard.c @@ -177,7 +177,7 @@ static void hv_kbd_on_receive(struct hv_device *hv_dev,  		 * state because the Enter-UP can trigger a wakeup at once.  		 */  		if (!(info & IS_BREAK)) -			pm_wakeup_event(&hv_dev->device, 0); +			pm_wakeup_hard_event(&hv_dev->device);  		break; diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index 02fb11985819..42d3fd7e04d7 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c @@ -1,23 +1,10 @@ +// SPDX-License-Identifier: GPL-2.0+  /*   * Touch Screen driver for Renesas MIGO-R Platform   *   * Copyright (c) 2008 Magnus Damm   * Copyright (c) 2007 Ujjwal Pande <ujjwal@kenati.com>,   *  Kenati Technologies Pvt Ltd. - * - * This file is free software; you can redistribute it and/or - * modify it under the terms of the GNU  General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This file is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU - *  General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA   */  #include <linux/module.h>  #include <linux/kernel.h> diff --git a/drivers/input/touchscreen/st1232.c b/drivers/input/touchscreen/st1232.c index b71673911aac..11ff32c68025 100644 --- a/drivers/input/touchscreen/st1232.c +++ b/drivers/input/touchscreen/st1232.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0  /*   * ST1232 Touchscreen Controller Driver   * @@ -7,15 +8,6 @@   * Using code from:   *  - android.git.kernel.org: projects/kernel/common.git: synaptics_i2c_rmi.c   *	Copyright (C) 2007 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the - * GNU General Public License for more details.   */  #include <linux/delay.h> @@ -295,4 +287,4 @@ module_i2c_driver(st1232_ts_driver);  MODULE_AUTHOR("Tony SIM <chinyeow.sim.xt@renesas.com>");  MODULE_DESCRIPTION("SITRONIX ST1232 Touchscreen Controller Driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); 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/leds/trigger/ledtrig-pattern.c b/drivers/leds/trigger/ledtrig-pattern.c index ce7acd115dd8..1870cf87afe1 100644 --- a/drivers/leds/trigger/ledtrig-pattern.c +++ b/drivers/leds/trigger/ledtrig-pattern.c @@ -75,8 +75,6 @@ static void pattern_trig_timer_function(struct timer_list *t)  {  	struct pattern_trig_data *data = from_timer(data, t, timer); -	mutex_lock(&data->lock); -  	for (;;) {  		if (!data->is_indefinite && !data->repeat)  			break; @@ -87,9 +85,10 @@ static void pattern_trig_timer_function(struct timer_list *t)  					   data->curr->brightness);  			mod_timer(&data->timer,  				  jiffies + msecs_to_jiffies(data->curr->delta_t)); - -			/* Skip the tuple with zero duration */ -			pattern_trig_update_patterns(data); +			if (!data->next->delta_t) { +				/* Skip the tuple with zero duration */ +				pattern_trig_update_patterns(data); +			}  			/* Select next tuple */  			pattern_trig_update_patterns(data);  		} else { @@ -116,8 +115,6 @@ static void pattern_trig_timer_function(struct timer_list *t)  		break;  	} - -	mutex_unlock(&data->lock);  }  static int pattern_trig_start_pattern(struct led_classdev *led_cdev) @@ -176,14 +173,10 @@ static ssize_t repeat_store(struct device *dev, struct device_attribute *attr,  	if (res < -1 || res == 0)  		return -EINVAL; -	/* -	 * Clear previous patterns' performence firstly, and remove the timer -	 * without mutex lock to avoid dead lock. -	 */ -	del_timer_sync(&data->timer); -  	mutex_lock(&data->lock); +	del_timer_sync(&data->timer); +  	if (data->is_hw_pattern)  		led_cdev->pattern_clear(led_cdev); @@ -234,14 +227,10 @@ static ssize_t pattern_trig_store_patterns(struct led_classdev *led_cdev,  	struct pattern_trig_data *data = led_cdev->trigger_data;  	int ccount, cr, offset = 0, err = 0; -	/* -	 * Clear previous patterns' performence firstly, and remove the timer -	 * without mutex lock to avoid dead lock. -	 */ -	del_timer_sync(&data->timer); -  	mutex_lock(&data->lock); +	del_timer_sync(&data->timer); +  	if (data->is_hw_pattern)  		led_cdev->pattern_clear(led_cdev); 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/dvb-frontends/dvb-pll.c b/drivers/media/dvb-frontends/dvb-pll.c index 6d4b2eec67b4..29836c1a40e9 100644 --- a/drivers/media/dvb-frontends/dvb-pll.c +++ b/drivers/media/dvb-frontends/dvb-pll.c @@ -80,8 +80,8 @@ struct dvb_pll_desc {  static const struct dvb_pll_desc dvb_pll_thomson_dtt7579 = {  	.name  = "Thomson dtt7579", -	.min   = 177000000, -	.max   = 858000000, +	.min   = 177 * MHz, +	.max   = 858 * MHz,  	.iffreq= 36166667,  	.sleepdata = (u8[]){ 2, 0xb4, 0x03 },  	.count = 4, @@ -102,8 +102,8 @@ static void thomson_dtt759x_bw(struct dvb_frontend *fe, u8 *buf)  static const struct dvb_pll_desc dvb_pll_thomson_dtt759x = {  	.name  = "Thomson dtt759x", -	.min   = 177000000, -	.max   = 896000000, +	.min   = 177 * MHz, +	.max   = 896 * MHz,  	.set   = thomson_dtt759x_bw,  	.iffreq= 36166667,  	.sleepdata = (u8[]){ 2, 0x84, 0x03 }, @@ -126,8 +126,8 @@ static void thomson_dtt7520x_bw(struct dvb_frontend *fe, u8 *buf)  static const struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {  	.name  = "Thomson dtt7520x", -	.min   = 185000000, -	.max   = 900000000, +	.min   = 185 * MHz, +	.max   = 900 * MHz,  	.set   = thomson_dtt7520x_bw,  	.iffreq = 36166667,  	.count = 7, @@ -144,8 +144,8 @@ static const struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {  static const struct dvb_pll_desc dvb_pll_lg_z201 = {  	.name  = "LG z201", -	.min   = 174000000, -	.max   = 862000000, +	.min   = 174 * MHz, +	.max   = 862 * MHz,  	.iffreq= 36166667,  	.sleepdata = (u8[]){ 2, 0xbc, 0x03 },  	.count = 5, @@ -160,8 +160,8 @@ static const struct dvb_pll_desc dvb_pll_lg_z201 = {  static const struct dvb_pll_desc dvb_pll_unknown_1 = {  	.name  = "unknown 1", /* used by dntv live dvb-t */ -	.min   = 174000000, -	.max   = 862000000, +	.min   = 174 * MHz, +	.max   = 862 * MHz,  	.iffreq= 36166667,  	.count = 9,  	.entries = { @@ -182,8 +182,8 @@ static const struct dvb_pll_desc dvb_pll_unknown_1 = {   */  static const struct dvb_pll_desc dvb_pll_tua6010xs = {  	.name  = "Infineon TUA6010XS", -	.min   =  44250000, -	.max   = 858000000, +	.min   = 44250 * kHz, +	.max   = 858 * MHz,  	.iffreq= 36125000,  	.count = 3,  	.entries = { @@ -196,8 +196,8 @@ static const struct dvb_pll_desc dvb_pll_tua6010xs = {  /* Panasonic env57h1xd5 (some Philips PLL ?) */  static const struct dvb_pll_desc dvb_pll_env57h1xd5 = {  	.name  = "Panasonic ENV57H1XD5", -	.min   =  44250000, -	.max   = 858000000, +	.min   = 44250 * kHz, +	.max   = 858 * MHz,  	.iffreq= 36125000,  	.count = 4,  	.entries = { @@ -220,8 +220,8 @@ static void tda665x_bw(struct dvb_frontend *fe, u8 *buf)  static const struct dvb_pll_desc dvb_pll_tda665x = {  	.name  = "Philips TDA6650/TDA6651", -	.min   =  44250000, -	.max   = 858000000, +	.min   = 44250 * kHz, +	.max   = 858 * MHz,  	.set   = tda665x_bw,  	.iffreq= 36166667,  	.initdata = (u8[]){ 4, 0x0b, 0xf5, 0x85, 0xab }, @@ -254,8 +254,8 @@ static void tua6034_bw(struct dvb_frontend *fe, u8 *buf)  static const struct dvb_pll_desc dvb_pll_tua6034 = {  	.name  = "Infineon TUA6034", -	.min   =  44250000, -	.max   = 858000000, +	.min   = 44250 * kHz, +	.max   = 858 * MHz,  	.iffreq= 36166667,  	.count = 3,  	.set   = tua6034_bw, @@ -278,8 +278,8 @@ static void tded4_bw(struct dvb_frontend *fe, u8 *buf)  static const struct dvb_pll_desc dvb_pll_tded4 = {  	.name = "ALPS TDED4", -	.min = 47000000, -	.max = 863000000, +	.min =  47 * MHz, +	.max = 863 * MHz,  	.iffreq= 36166667,  	.set   = tded4_bw,  	.count = 4, @@ -296,8 +296,8 @@ static const struct dvb_pll_desc dvb_pll_tded4 = {   */  static const struct dvb_pll_desc dvb_pll_tdhu2 = {  	.name = "ALPS TDHU2", -	.min = 54000000, -	.max = 864000000, +	.min =  54 * MHz, +	.max = 864 * MHz,  	.iffreq= 44000000,  	.count = 4,  	.entries = { @@ -313,8 +313,8 @@ static const struct dvb_pll_desc dvb_pll_tdhu2 = {   */  static const struct dvb_pll_desc dvb_pll_samsung_tbmv = {  	.name = "Samsung TBMV30111IN / TBMV30712IN1", -	.min = 54000000, -	.max = 860000000, +	.min =  54 * MHz, +	.max = 860 * MHz,  	.iffreq= 44000000,  	.count = 6,  	.entries = { @@ -332,8 +332,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_tbmv = {   */  static const struct dvb_pll_desc dvb_pll_philips_sd1878_tda8261 = {  	.name  = "Philips SD1878", -	.min   =  950000, -	.max   = 2150000, +	.min   =  950 * MHz, +	.max   = 2150 * MHz,  	.iffreq= 249, /* zero-IF, offset 249 is to round up */  	.count = 4,  	.entries = { @@ -398,8 +398,8 @@ static void opera1_bw(struct dvb_frontend *fe, u8 *buf)  static const struct dvb_pll_desc dvb_pll_opera1 = {  	.name  = "Opera Tuner", -	.min   =  900000, -	.max   = 2250000, +	.min   =  900 * MHz, +	.max   = 2250 * MHz,  	.initdata = (u8[]){ 4, 0x08, 0xe5, 0xe1, 0x00 },  	.initdata2 = (u8[]){ 4, 0x08, 0xe5, 0xe5, 0x00 },  	.iffreq= 0, @@ -445,8 +445,8 @@ static void samsung_dtos403ih102a_set(struct dvb_frontend *fe, u8 *buf)  /* unknown pll used in Samsung DTOS403IH102A DVB-C tuner */  static const struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {  	.name   = "Samsung DTOS403IH102A", -	.min    =  44250000, -	.max    = 858000000, +	.min    = 44250 * kHz, +	.max    = 858 * MHz,  	.iffreq =  36125000,  	.count  = 8,  	.set    = samsung_dtos403ih102a_set, @@ -465,8 +465,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_dtos403ih102a = {  /* Samsung TDTC9251DH0 DVB-T NIM, as used on AirStar 2 */  static const struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {  	.name	= "Samsung TDTC9251DH0", -	.min	=  48000000, -	.max	= 863000000, +	.min	=  48 * MHz, +	.max	= 863 * MHz,  	.iffreq	=  36166667,  	.count	= 3,  	.entries = { @@ -479,8 +479,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_tdtc9251dh0 = {  /* Samsung TBDU18132 DVB-S NIM with TSA5059 PLL, used in SkyStar2 DVB-S 2.3 */  static const struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {  	.name = "Samsung TBDU18132", -	.min	=  950000, -	.max	= 2150000, /* guesses */ +	.min	=  950 * MHz, +	.max	= 2150 * MHz, /* guesses */  	.iffreq = 0,  	.count = 2,  	.entries = { @@ -500,8 +500,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_tbdu18132 = {  /* Samsung TBMU24112 DVB-S NIM with SL1935 zero-IF tuner */  static const struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {  	.name = "Samsung TBMU24112", -	.min	=  950000, -	.max	= 2150000, /* guesses */ +	.min	=  950 * MHz, +	.max	= 2150 * MHz, /* guesses */  	.iffreq = 0,  	.count = 2,  	.entries = { @@ -521,8 +521,8 @@ static const struct dvb_pll_desc dvb_pll_samsung_tbmu24112 = {   * 822 - 862   1  *  0   0   1   0   0   0   0x88 */  static const struct dvb_pll_desc dvb_pll_alps_tdee4 = {  	.name = "ALPS TDEE4", -	.min	=  47000000, -	.max	= 862000000, +	.min	=  47 * MHz, +	.max	= 862 * MHz,  	.iffreq	=  36125000,  	.count = 4,  	.entries = { @@ -537,8 +537,8 @@ static const struct dvb_pll_desc dvb_pll_alps_tdee4 = {  /* CP cur. 50uA, AGC takeover: 103dBuV, PORT3 on */  static const struct dvb_pll_desc dvb_pll_tua6034_friio = {  	.name   = "Infineon TUA6034 ISDB-T (Friio)", -	.min    =  90000000, -	.max    = 770000000, +	.min    =  90 * MHz, +	.max    = 770 * MHz,  	.iffreq =  57000000,  	.initdata = (u8[]){ 4, 0x9a, 0x50, 0xb2, 0x08 },  	.sleepdata = (u8[]){ 4, 0x9a, 0x70, 0xb3, 0x0b }, @@ -553,8 +553,8 @@ static const struct dvb_pll_desc dvb_pll_tua6034_friio = {  /* Philips TDA6651 ISDB-T, used in Earthsoft PT1 */  static const struct dvb_pll_desc dvb_pll_tda665x_earth_pt1 = {  	.name   = "Philips TDA6651 ISDB-T (EarthSoft PT1)", -	.min    =  90000000, -	.max    = 770000000, +	.min    =  90 * MHz, +	.max    = 770 * MHz,  	.iffreq =  57000000,  	.initdata = (u8[]){ 5, 0x0e, 0x7f, 0xc1, 0x80, 0x80 },  	.count = 10, @@ -610,9 +610,6 @@ static int dvb_pll_configure(struct dvb_frontend *fe, u8 *buf,  	u32 div;  	int i; -	if (frequency && (frequency < desc->min || frequency > desc->max)) -		return -EINVAL; -  	for (i = 0; i < desc->count; i++) {  		if (frequency > desc->entries[i].limit)  			continue; @@ -799,7 +796,6 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,  	struct dvb_pll_priv *priv = NULL;  	int ret;  	const struct dvb_pll_desc *desc; -	struct dtv_frontend_properties *c = &fe->dtv_property_cache;  	b1 = kmalloc(1, GFP_KERNEL);  	if (!b1) @@ -845,18 +841,12 @@ struct dvb_frontend *dvb_pll_attach(struct dvb_frontend *fe, int pll_addr,  	strncpy(fe->ops.tuner_ops.info.name, desc->name,  		sizeof(fe->ops.tuner_ops.info.name)); -	switch (c->delivery_system) { -	case SYS_DVBS: -	case SYS_DVBS2: -	case SYS_TURBO: -	case SYS_ISDBS: -		fe->ops.tuner_ops.info.frequency_min_hz = desc->min * kHz; -		fe->ops.tuner_ops.info.frequency_max_hz = desc->max * kHz; -		break; -	default: -		fe->ops.tuner_ops.info.frequency_min_hz = desc->min; -		fe->ops.tuner_ops.info.frequency_max_hz = desc->max; -	} + +	fe->ops.tuner_ops.info.frequency_min_hz = desc->min; +	fe->ops.tuner_ops.info.frequency_max_hz = desc->max; + +	dprintk("%s tuner, frequency range: %u...%u\n", +		desc->name, desc->min, desc->max);  	if (!desc->initdata)  		fe->ops.tuner_ops.init = NULL; diff --git a/drivers/media/i2c/tc358743.c b/drivers/media/i2c/tc358743.c index ca5d92942820..41d470d9ca94 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/media-request.c b/drivers/media/media-request.c index 4e9db1fed697..c71a34ae6383 100644 --- a/drivers/media/media-request.c +++ b/drivers/media/media-request.c @@ -238,6 +238,9 @@ static const struct file_operations request_fops = {  	.owner = THIS_MODULE,  	.poll = media_request_poll,  	.unlocked_ioctl = media_request_ioctl, +#ifdef CONFIG_COMPAT +	.compat_ioctl = media_request_ioctl, +#endif /* CONFIG_COMPAT */  	.release = media_request_close,  }; 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..013cdebecbc4 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) @@ -304,7 +304,8 @@ restart:  		for (; p < p_out + sz; p++) {  			u32 copy; -			p = memchr(p, magic[ctx->comp_magic_cnt], sz); +			p = memchr(p, magic[ctx->comp_magic_cnt], +				   p_out + sz - p);  			if (!p) {  				ctx->comp_magic_cnt = 0;  				break; 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/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c index fce9d6f4b7c9..3137f5d89d80 100644 --- a/drivers/media/usb/gspca/gspca.c +++ b/drivers/media/usb/gspca/gspca.c @@ -426,10 +426,10 @@ void gspca_frame_add(struct gspca_dev *gspca_dev,  	/* append the packet to the frame buffer */  	if (len > 0) { -		if (gspca_dev->image_len + len > gspca_dev->pixfmt.sizeimage) { +		if (gspca_dev->image_len + len > PAGE_ALIGN(gspca_dev->pixfmt.sizeimage)) {  			gspca_err(gspca_dev, "frame overflow %d > %d\n",  				  gspca_dev->image_len + len, -				  gspca_dev->pixfmt.sizeimage); +				  PAGE_ALIGN(gspca_dev->pixfmt.sizeimage));  			packet_type = DISCARD_PACKET;  		} else {  /* !! image is NULL only when last pkt is LAST or DISCARD @@ -1297,18 +1297,19 @@ static int gspca_queue_setup(struct vb2_queue *vq,  			     unsigned int sizes[], struct device *alloc_devs[])  {  	struct gspca_dev *gspca_dev = vb2_get_drv_priv(vq); +	unsigned int size = PAGE_ALIGN(gspca_dev->pixfmt.sizeimage);  	if (*nplanes) -		return sizes[0] < gspca_dev->pixfmt.sizeimage ? -EINVAL : 0; +		return sizes[0] < size ? -EINVAL : 0;  	*nplanes = 1; -	sizes[0] = gspca_dev->pixfmt.sizeimage; +	sizes[0] = size;  	return 0;  }  static int gspca_buffer_prepare(struct vb2_buffer *vb)  {  	struct gspca_dev *gspca_dev = vb2_get_drv_priv(vb->vb2_queue); -	unsigned long size = gspca_dev->pixfmt.sizeimage; +	unsigned long size = PAGE_ALIGN(gspca_dev->pixfmt.sizeimage);  	if (vb2_plane_size(vb, 0) < size) {  		gspca_err(gspca_dev, "buffer too small (%lu < %lu)\n", 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/mfd/cros_ec_dev.c b/drivers/mfd/cros_ec_dev.c index 8f9d6964173e..b99a194ce5a4 100644 --- a/drivers/mfd/cros_ec_dev.c +++ b/drivers/mfd/cros_ec_dev.c @@ -263,6 +263,11 @@ static const struct file_operations fops = {  #endif  }; +static void cros_ec_class_release(struct device *dev) +{ +	kfree(to_cros_ec_dev(dev)); +} +  static void cros_ec_sensors_register(struct cros_ec_dev *ec)  {  	/* @@ -395,7 +400,7 @@ static int ec_device_probe(struct platform_device *pdev)  	int retval = -ENOMEM;  	struct device *dev = &pdev->dev;  	struct cros_ec_platform *ec_platform = dev_get_platdata(dev); -	struct cros_ec_dev *ec = devm_kzalloc(dev, sizeof(*ec), GFP_KERNEL); +	struct cros_ec_dev *ec = kzalloc(sizeof(*ec), GFP_KERNEL);  	if (!ec)  		return retval; @@ -417,6 +422,7 @@ static int ec_device_probe(struct platform_device *pdev)  	ec->class_dev.devt = MKDEV(ec_major, pdev->id);  	ec->class_dev.class = &cros_class;  	ec->class_dev.parent = dev; +	ec->class_dev.release = cros_ec_class_release;  	retval = dev_set_name(&ec->class_dev, "%s", ec_platform->ec_name);  	if (retval) { 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/mic/scif/scif_rma.c b/drivers/misc/mic/scif/scif_rma.c index c824329f7012..0e4193cb08cf 100644 --- a/drivers/misc/mic/scif/scif_rma.c +++ b/drivers/misc/mic/scif/scif_rma.c @@ -416,7 +416,7 @@ static int scif_create_remote_lookup(struct scif_dev *remote_dev,  		if (err)  			goto error_window;  		err = scif_map_page(&window->num_pages_lookup.lookup[j], -				    vmalloc_dma_phys ? +				    vmalloc_num_pages ?  				    vmalloc_to_page(&window->num_pages[i]) :  				    virt_to_page(&window->num_pages[i]),  				    remote_dev); 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/devices/Kconfig b/drivers/mtd/devices/Kconfig index e514d57a0419..aa983422aa97 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -207,7 +207,7 @@ comment "Disk-On-Chip Device Drivers"  config MTD_DOCG3  	tristate "M-Systems Disk-On-Chip G3"  	select BCH -	select BCH_CONST_PARAMS +	select BCH_CONST_PARAMS if !MTD_NAND_BCH  	select BITREVERSE  	help  	  This provides an MTD device driver for the M-Systems DiskOnChip diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c index 784c6e1a0391..fd5fe12d7461 100644 --- a/drivers/mtd/maps/sa1100-flash.c +++ b/drivers/mtd/maps/sa1100-flash.c @@ -221,7 +221,14 @@ static struct sa_info *sa1100_setup_mtd(struct platform_device *pdev,  		info->mtd = info->subdev[0].mtd;  		ret = 0;  	} else if (info->num_subdev > 1) { -		struct mtd_info *cdev[nr]; +		struct mtd_info **cdev; + +		cdev = kmalloc_array(nr, sizeof(*cdev), GFP_KERNEL); +		if (!cdev) { +			ret = -ENOMEM; +			goto err; +		} +  		/*  		 * We detected multiple devices.  Concatenate them together.  		 */ @@ -230,6 +237,7 @@ static struct sa_info *sa1100_setup_mtd(struct platform_device *pdev,  		info->mtd = mtd_concat_create(cdev, info->num_subdev,  					      plat->name); +		kfree(cdev);  		if (info->mtd == NULL) {  			ret = -ENXIO;  			goto err; diff --git a/drivers/mtd/nand/bbt.c b/drivers/mtd/nand/bbt.c index 56cde38b92c0..044adf913854 100644 --- a/drivers/mtd/nand/bbt.c +++ b/drivers/mtd/nand/bbt.c @@ -27,7 +27,8 @@ int nanddev_bbt_init(struct nand_device *nand)  	unsigned int nwords = DIV_ROUND_UP(nblocks * bits_per_block,  					   BITS_PER_LONG); -	nand->bbt.cache = kzalloc(nwords, GFP_KERNEL); +	nand->bbt.cache = kcalloc(nwords, sizeof(*nand->bbt.cache), +				  GFP_KERNEL);  	if (!nand->bbt.cache)  		return -ENOMEM; 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/nand_base.c b/drivers/mtd/nand/raw/nand_base.c index 05bd0779fe9b..71050a0b31df 100644 --- a/drivers/mtd/nand/raw/nand_base.c +++ b/drivers/mtd/nand/raw/nand_base.c @@ -590,7 +590,6 @@ retry:  /**   * panic_nand_wait - [GENERIC] wait until the command is done - * @mtd: MTD device structure   * @chip: NAND chip structure   * @timeo: timeout   * 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 e24db817154e..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) @@ -996,7 +1009,7 @@ static int cqspi_direct_read_execute(struct spi_nor *nor, u_char *buf,  err_unmap:  	dma_unmap_single(nor->dev, dma_dst, len, DMA_FROM_DEVICE); -	return 0; +	return ret;  }  static ssize_t cqspi_read(struct spi_nor *nor, loff_t from, diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c index 9407ca5f9443..1fdd2834fbcb 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; @@ -2941,12 +2995,13 @@ static int spi_nor_init_non_uniform_erase_map(struct spi_nor *nor,  					      const u32 *smpt)  {  	struct spi_nor_erase_map *map = &nor->erase_map; -	const struct spi_nor_erase_type *erase = map->erase_type; +	struct spi_nor_erase_type *erase = map->erase_type;  	struct spi_nor_erase_region *region;  	u64 offset;  	u32 region_count;  	int i, j; -	u8 erase_type; +	u8 uniform_erase_type, save_uniform_erase_type; +	u8 erase_type, regions_erase_type;  	region_count = SMPT_MAP_REGION_COUNT(*smpt);  	/* @@ -2959,7 +3014,8 @@ 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; +	regions_erase_type = 0;  	offset = 0;  	/* Populate regions. */  	for (i = 0; i < region_count; i++) { @@ -2974,12 +3030,40 @@ 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; + +		/* +		 * regions_erase_type mask will indicate all the erase types +		 * supported in this configuration map. +		 */ +		regions_erase_type |= erase_type;  		offset = (region[i].offset & ~SNOR_ERASE_FLAGS_MASK) +  			 region[i].size;  	} +	save_uniform_erase_type = map->uniform_erase_type; +	map->uniform_erase_type = spi_nor_sort_erase_mask(map, +							  uniform_erase_type); + +	if (!regions_erase_type) { +		/* +		 * Roll back to the previous uniform_erase_type mask, SMPT is +		 * broken. +		 */ +		map->uniform_erase_type = save_uniform_erase_type; +		return -EINVAL; +	} + +	/* +	 * BFPT advertises all the erase types supported by all the possible +	 * map configurations. Mask out the erase types that are not supported +	 * by the current map configuration. +	 */ +	for (i = 0; i < SNOR_ERASE_TYPE_MAX; i++) +		if (!(regions_erase_type & BIT(erase[i].idx))) +			spi_nor_set_erase_type(&erase[i], 0, 0xFF); +  	spi_nor_region_mark_end(®ion[i - 1]);  	return 0; @@ -3020,9 +3104,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 +3209,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 +3222,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: @@ -3250,12 +3343,14 @@ static int spi_nor_init_params(struct spi_nor *nor,  		memcpy(&sfdp_params, params, sizeof(sfdp_params));  		memcpy(&prev_map, &nor->erase_map, sizeof(prev_map)); -		if (spi_nor_parse_sfdp(nor, &sfdp_params)) +		if (spi_nor_parse_sfdp(nor, &sfdp_params)) { +			nor->addr_width = 0;  			/* restore previous erase map */  			memcpy(&nor->erase_map, &prev_map,  			       sizeof(nor->erase_map)); -		else +		} else {  			memcpy(params, &sfdp_params, sizeof(*params)); +		}  	}  	return 0; diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index ffa37adb7681..333387f1f1fe 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -3112,13 +3112,13 @@ static int bond_slave_netdev_event(unsigned long event,  	case NETDEV_CHANGE:  		/* For 802.3ad mode only:  		 * Getting invalid Speed/Duplex values here will put slave -		 * in weird state. So mark it as link-down for the time +		 * in weird state. So mark it as link-fail for the time  		 * being and let link-monitoring (miimon) set it right when  		 * correct speeds/duplex are available.  		 */  		if (bond_update_speed_duplex(slave) &&  		    BOND_MODE(bond) == BOND_MODE_8023AD) -			slave->link = BOND_LINK_DOWN; +			slave->link = BOND_LINK_FAIL;  		if (BOND_MODE(bond) == BOND_MODE_8023AD)  			bond_3ad_adapter_speed_duplex_changed(slave); 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/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 54e0ca6ed730..86b6464b4525 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -1117,11 +1117,6 @@ static int ksz_switch_init(struct ksz_device *dev)  {  	int i; -	mutex_init(&dev->reg_mutex); -	mutex_init(&dev->stats_mutex); -	mutex_init(&dev->alu_mutex); -	mutex_init(&dev->vlan_mutex); -  	dev->ds->ops = &ksz_switch_ops;  	for (i = 0; i < ARRAY_SIZE(ksz_switch_chips); i++) { @@ -1206,6 +1201,11 @@ int ksz_switch_register(struct ksz_device *dev)  	if (dev->pdata)  		dev->chip_id = dev->pdata->chip_id; +	mutex_init(&dev->reg_mutex); +	mutex_init(&dev->stats_mutex); +	mutex_init(&dev->alu_mutex); +	mutex_init(&dev->vlan_mutex); +  	if (ksz_switch_detect(dev))  		return -EINVAL; diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c index d721ccf7d8be..38e399e0f30e 100644 --- a/drivers/net/dsa/mv88e6xxx/global1.c +++ b/drivers/net/dsa/mv88e6xxx/global1.c @@ -567,6 +567,8 @@ int mv88e6xxx_g1_stats_clear(struct mv88e6xxx_chip *chip)  	if (err)  		return err; +	/* Keep the histogram mode bits */ +	val &= MV88E6XXX_G1_STATS_OP_HIST_RX_TX;  	val |= MV88E6XXX_G1_STATS_OP_BUSY | MV88E6XXX_G1_STATS_OP_FLUSH_ALL;  	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_STATS_OP, val); 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/aquantia/atlantic/aq_ethtool.c b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c index 6a633c70f603..99ef1daaa4d8 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ethtool.c @@ -407,13 +407,13 @@ static void aq_ethtool_get_pauseparam(struct net_device *ndev,  				      struct ethtool_pauseparam *pause)  {  	struct aq_nic_s *aq_nic = netdev_priv(ndev); +	u32 fc = aq_nic->aq_nic_cfg.flow_control;  	pause->autoneg = 0; -	if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_RX) -		pause->rx_pause = 1; -	if (aq_nic->aq_hw->aq_nic_cfg->flow_control & AQ_NIC_FC_TX) -		pause->tx_pause = 1; +	pause->rx_pause = !!(fc & AQ_NIC_FC_RX); +	pause->tx_pause = !!(fc & AQ_NIC_FC_TX); +  }  static int aq_ethtool_set_pauseparam(struct net_device *ndev, diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index e8689241204e..a1e70da358ca 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -204,6 +204,10 @@ struct aq_hw_ops {  	int (*hw_get_fw_version)(struct aq_hw_s *self, u32 *fw_version); +	int (*hw_set_offload)(struct aq_hw_s *self, +			      struct aq_nic_cfg_s *aq_nic_cfg); + +	int (*hw_set_fc)(struct aq_hw_s *self, u32 fc, u32 tc);  };  struct aq_fw_ops { @@ -226,6 +230,8 @@ struct aq_fw_ops {  	int (*update_stats)(struct aq_hw_s *self); +	u32 (*get_flow_control)(struct aq_hw_s *self, u32 *fcmode); +  	int (*set_flow_control)(struct aq_hw_s *self);  	int (*set_power)(struct aq_hw_s *self, unsigned int power_state, diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_main.c b/drivers/net/ethernet/aquantia/atlantic/aq_main.c index e3ae29e523f0..7c07eef275eb 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_main.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_main.c @@ -99,8 +99,11 @@ static int aq_ndev_set_features(struct net_device *ndev,  	struct aq_nic_s *aq_nic = netdev_priv(ndev);  	struct aq_nic_cfg_s *aq_cfg = aq_nic_get_cfg(aq_nic);  	bool is_lro = false; +	int err = 0; + +	aq_cfg->features = features; -	if (aq_cfg->hw_features & NETIF_F_LRO) { +	if (aq_cfg->aq_hw_caps->hw_features & NETIF_F_LRO) {  		is_lro = features & NETIF_F_LRO;  		if (aq_cfg->is_lro != is_lro) { @@ -112,8 +115,11 @@ static int aq_ndev_set_features(struct net_device *ndev,  			}  		}  	} +	if ((aq_nic->ndev->features ^ features) & NETIF_F_RXCSUM) +		err = aq_nic->aq_hw_ops->hw_set_offload(aq_nic->aq_hw, +							aq_cfg); -	return 0; +	return err;  }  static int aq_ndev_set_mac_address(struct net_device *ndev, void *addr) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 5fed24446687..7abdc0952425 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -118,12 +118,13 @@ void aq_nic_cfg_start(struct aq_nic_s *self)  	}  	cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk; -	cfg->hw_features = cfg->aq_hw_caps->hw_features; +	cfg->features = cfg->aq_hw_caps->hw_features;  }  static int aq_nic_update_link_status(struct aq_nic_s *self)  {  	int err = self->aq_fw_ops->update_link_status(self->aq_hw); +	u32 fc = 0;  	if (err)  		return err; @@ -133,6 +134,15 @@ static int aq_nic_update_link_status(struct aq_nic_s *self)  			AQ_CFG_DRV_NAME, self->link_status.mbps,  			self->aq_hw->aq_link_status.mbps);  		aq_nic_update_interrupt_moderation_settings(self); + +		/* Driver has to update flow control settings on RX block +		 * on any link event. +		 * We should query FW whether it negotiated FC. +		 */ +		if (self->aq_fw_ops->get_flow_control) +			self->aq_fw_ops->get_flow_control(self->aq_hw, &fc); +		if (self->aq_hw_ops->hw_set_fc) +			self->aq_hw_ops->hw_set_fc(self->aq_hw, fc, 0);  	}  	self->link_status = self->aq_hw->aq_link_status; @@ -590,7 +600,7 @@ int aq_nic_set_multicast_list(struct aq_nic_s *self, struct net_device *ndev)  		}  	} -	if (i > 0 && i < AQ_HW_MULTICAST_ADDRESS_MAX) { +	if (i > 0 && i <= AQ_HW_MULTICAST_ADDRESS_MAX) {  		packet_filter |= IFF_MULTICAST;  		self->mc_list.count = i;  		self->aq_hw_ops->hw_multicast_list_set(self->aq_hw, @@ -772,7 +782,9 @@ void aq_nic_get_link_ksettings(struct aq_nic_s *self,  		ethtool_link_ksettings_add_link_mode(cmd, advertising,  						     Pause); -	if (self->aq_nic_cfg.flow_control & AQ_NIC_FC_TX) +	/* Asym is when either RX or TX, but not both */ +	if (!!(self->aq_nic_cfg.flow_control & AQ_NIC_FC_TX) ^ +	    !!(self->aq_nic_cfg.flow_control & AQ_NIC_FC_RX))  		ethtool_link_ksettings_add_link_mode(cmd, advertising,  						     Asym_Pause); diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index c1582f4e8e1b..44ec47a3d60a 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -23,7 +23,7 @@ struct aq_vec_s;  struct aq_nic_cfg_s {  	const struct aq_hw_caps_s *aq_hw_caps; -	u64 hw_features; +	u64 features;  	u32 rxds;		/* rx ring size, descriptors # */  	u32 txds;		/* tx ring size, descriptors # */  	u32 vecs;		/* vecs==allocated irqs */ diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c index 3db91446cc67..74550ccc7a20 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_ring.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_ring.c @@ -172,6 +172,27 @@ bool aq_ring_tx_clean(struct aq_ring_s *self)  	return !!budget;  } +static void aq_rx_checksum(struct aq_ring_s *self, +			   struct aq_ring_buff_s *buff, +			   struct sk_buff *skb) +{ +	if (!(self->aq_nic->ndev->features & NETIF_F_RXCSUM)) +		return; + +	if (unlikely(buff->is_cso_err)) { +		++self->stats.rx.errors; +		skb->ip_summed = CHECKSUM_NONE; +		return; +	} +	if (buff->is_ip_cso) { +		__skb_incr_checksum_unnecessary(skb); +		if (buff->is_udp_cso || buff->is_tcp_cso) +			__skb_incr_checksum_unnecessary(skb); +	} else { +		skb->ip_summed = CHECKSUM_NONE; +	} +} +  #define AQ_SKB_ALIGN SKB_DATA_ALIGN(sizeof(struct skb_shared_info))  int aq_ring_rx_clean(struct aq_ring_s *self,  		     struct napi_struct *napi, @@ -267,18 +288,8 @@ int aq_ring_rx_clean(struct aq_ring_s *self,  		}  		skb->protocol = eth_type_trans(skb, ndev); -		if (unlikely(buff->is_cso_err)) { -			++self->stats.rx.errors; -			skb->ip_summed = CHECKSUM_NONE; -		} else { -			if (buff->is_ip_cso) { -				__skb_incr_checksum_unnecessary(skb); -				if (buff->is_udp_cso || buff->is_tcp_cso) -					__skb_incr_checksum_unnecessary(skb); -			} else { -				skb->ip_summed = CHECKSUM_NONE; -			} -		} + +		aq_rx_checksum(self, buff, skb);  		skb_set_hash(skb, buff->rss_hash,  			     buff->is_hash_l4 ? PKT_HASH_TYPE_L4 : diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 76d25d594a0f..f02592f43fe3 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -100,12 +100,17 @@ static int hw_atl_b0_hw_reset(struct aq_hw_s *self)  	return err;  } +static int hw_atl_b0_set_fc(struct aq_hw_s *self, u32 fc, u32 tc) +{ +	hw_atl_rpb_rx_xoff_en_per_tc_set(self, !!(fc & AQ_NIC_FC_RX), tc); +	return 0; +} +  static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)  {  	u32 tc = 0U;  	u32 buff_size = 0U;  	unsigned int i_priority = 0U; -	bool is_rx_flow_control = false;  	/* TPS Descriptor rate init */  	hw_atl_tps_tx_pkt_shed_desc_rate_curr_time_res_set(self, 0x0U); @@ -138,7 +143,6 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)  	/* QoS Rx buf size per TC */  	tc = 0; -	is_rx_flow_control = (AQ_NIC_FC_RX & self->aq_nic_cfg->flow_control);  	buff_size = HW_ATL_B0_RXBUF_MAX;  	hw_atl_rpb_rx_pkt_buff_size_per_tc_set(self, buff_size, tc); @@ -150,7 +154,8 @@ static int hw_atl_b0_hw_qos_set(struct aq_hw_s *self)  						   (buff_size *  						   (1024U / 32U) * 50U) /  						   100U, tc); -	hw_atl_rpb_rx_xoff_en_per_tc_set(self, is_rx_flow_control ? 1U : 0U, tc); + +	hw_atl_b0_set_fc(self, self->aq_nic_cfg->flow_control, tc);  	/* QoS 802.1p priority -> TC mapping */  	for (i_priority = 8U; i_priority--;) @@ -229,8 +234,10 @@ static int hw_atl_b0_hw_offload_set(struct aq_hw_s *self,  	hw_atl_tpo_tcp_udp_crc_offload_en_set(self, 1);  	/* RX checksums offloads*/ -	hw_atl_rpo_ipv4header_crc_offload_en_set(self, 1); -	hw_atl_rpo_tcp_udp_crc_offload_en_set(self, 1); +	hw_atl_rpo_ipv4header_crc_offload_en_set(self, !!(aq_nic_cfg->features & +						 NETIF_F_RXCSUM)); +	hw_atl_rpo_tcp_udp_crc_offload_en_set(self, !!(aq_nic_cfg->features & +					      NETIF_F_RXCSUM));  	/* LSO offloads*/  	hw_atl_tdm_large_send_offload_en_set(self, 0xFFFFFFFFU); @@ -655,9 +662,9 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,  		struct hw_atl_rxd_wb_s *rxd_wb = (struct hw_atl_rxd_wb_s *)  			&ring->dx_ring[ring->hw_head * HW_ATL_B0_RXD_SIZE]; -		unsigned int is_err = 1U;  		unsigned int is_rx_check_sum_enabled = 0U;  		unsigned int pkt_type = 0U; +		u8 rx_stat = 0U;  		if (!(rxd_wb->status & 0x1U)) { /* RxD is not done */  			break; @@ -665,35 +672,35 @@ static int hw_atl_b0_hw_ring_rx_receive(struct aq_hw_s *self,  		buff = &ring->buff_ring[ring->hw_head]; -		is_err = (0x0000003CU & rxd_wb->status); +		rx_stat = (0x0000003CU & rxd_wb->status) >> 2;  		is_rx_check_sum_enabled = (rxd_wb->type) & (0x3U << 19); -		is_err &= ~0x20U; /* exclude validity bit */  		pkt_type = 0xFFU & (rxd_wb->type >> 4); -		if (is_rx_check_sum_enabled) { -			if (0x0U == (pkt_type & 0x3U)) -				buff->is_ip_cso = (is_err & 0x08U) ? 0U : 1U; +		if (is_rx_check_sum_enabled & BIT(0) && +		    (0x0U == (pkt_type & 0x3U))) +			buff->is_ip_cso = (rx_stat & BIT(1)) ? 0U : 1U; +		if (is_rx_check_sum_enabled & BIT(1)) {  			if (0x4U == (pkt_type & 0x1CU)) -				buff->is_udp_cso = buff->is_cso_err ? 0U : 1U; +				buff->is_udp_cso = (rx_stat & BIT(2)) ? 0U : +						   !!(rx_stat & BIT(3));  			else if (0x0U == (pkt_type & 0x1CU)) -				buff->is_tcp_cso = buff->is_cso_err ? 0U : 1U; - -			/* Checksum offload workaround for small packets */ -			if (rxd_wb->pkt_len <= 60) { -				buff->is_ip_cso = 0U; -				buff->is_cso_err = 0U; -			} +				buff->is_tcp_cso = (rx_stat & BIT(2)) ? 0U : +						   !!(rx_stat & BIT(3)); +		} +		buff->is_cso_err = !!(rx_stat & 0x6); +		/* Checksum offload workaround for small packets */ +		if (unlikely(rxd_wb->pkt_len <= 60)) { +			buff->is_ip_cso = 0U; +			buff->is_cso_err = 0U;  		} - -		is_err &= ~0x18U;  		dma_unmap_page(ndev, buff->pa, buff->len, DMA_FROM_DEVICE); -		if (is_err || rxd_wb->type & 0x1000U) { -			/* status error or DMA error */ +		if ((rx_stat & BIT(0)) || rxd_wb->type & 0x1000U) { +			/* MAC error or DMA error */  			buff->is_error = 1U;  		} else {  			if (self->aq_nic_cfg->is_rss) { @@ -915,6 +922,12 @@ static int hw_atl_b0_hw_interrupt_moderation_set(struct aq_hw_s *self)  static int hw_atl_b0_hw_stop(struct aq_hw_s *self)  {  	hw_atl_b0_hw_irq_disable(self, HW_ATL_B0_INT_MASK); + +	/* Invalidate Descriptor Cache to prevent writing to the cached +	 * descriptors and to the data pointer of those descriptors +	 */ +	hw_atl_rdm_rx_dma_desc_cache_init_set(self, 1); +  	return aq_hw_err_from_flags(self);  } @@ -963,4 +976,6 @@ const struct aq_hw_ops hw_atl_ops_b0 = {  	.hw_get_regs                 = hw_atl_utils_hw_get_regs,  	.hw_get_hw_stats             = hw_atl_utils_get_hw_stats,  	.hw_get_fw_version           = hw_atl_utils_get_fw_version, +	.hw_set_offload              = hw_atl_b0_hw_offload_set, +	.hw_set_fc                   = hw_atl_b0_set_fc,  }; diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c index be0a3a90dfad..5502ec5f0f69 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.c @@ -619,6 +619,14 @@ void hw_atl_rpb_rx_flow_ctl_mode_set(struct aq_hw_s *aq_hw, u32 rx_flow_ctl_mode  			    HW_ATL_RPB_RX_FC_MODE_SHIFT, rx_flow_ctl_mode);  } +void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init) +{ +	aq_hw_write_reg_bit(aq_hw, HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR, +			    HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK, +			    HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT, +			    init); +} +  void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw,  					    u32 rx_pkt_buff_size_per_tc, u32 buffer)  { diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h index 7056c7342afc..41f239928c15 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh.h @@ -325,6 +325,9 @@ void hw_atl_rpb_rx_pkt_buff_size_per_tc_set(struct aq_hw_s *aq_hw,  					    u32 rx_pkt_buff_size_per_tc,  					    u32 buffer); +/* set rdm rx dma descriptor cache init */ +void hw_atl_rdm_rx_dma_desc_cache_init_set(struct aq_hw_s *aq_hw, u32 init); +  /* set rx xoff enable (per tc) */  void hw_atl_rpb_rx_xoff_en_per_tc_set(struct aq_hw_s *aq_hw, u32 rx_xoff_en_per_tc,  				      u32 buffer); diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h index 716674a9b729..a715fa317b1c 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_llh_internal.h @@ -293,6 +293,24 @@  /* default value of bitfield desc{d}_reset */  #define HW_ATL_RDM_DESCDRESET_DEFAULT 0x0 +/* rdm_desc_init_i bitfield definitions + * preprocessor definitions for the bitfield rdm_desc_init_i. + * port="pif_rdm_desc_init_i" + */ + +/* register address for bitfield rdm_desc_init_i */ +#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_ADR 0x00005a00 +/* bitmask for bitfield rdm_desc_init_i */ +#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSK 0xffffffff +/* inverted bitmask for bitfield rdm_desc_init_i */ +#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_MSKN 0x00000000 +/* lower bit position of bitfield  rdm_desc_init_i */ +#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_SHIFT 0 +/* width of bitfield rdm_desc_init_i */ +#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_WIDTH 32 +/* default value of bitfield rdm_desc_init_i */ +#define HW_ATL_RDM_RX_DMA_DESC_CACHE_INIT_DEFAULT 0x0 +  /* rx int_desc_wrb_en bitfield definitions   * preprocessor definitions for the bitfield "int_desc_wrb_en".   * port="pif_rdm_int_desc_wrb_en_i" diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c index 096ca5730887..7de3220d9cab 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_utils_fw2x.c @@ -30,6 +30,8 @@  #define HW_ATL_FW2X_MPI_STATE_ADDR	0x370  #define HW_ATL_FW2X_MPI_STATE2_ADDR	0x374 +#define HW_ATL_FW2X_CAP_PAUSE            BIT(CAPS_HI_PAUSE) +#define HW_ATL_FW2X_CAP_ASYM_PAUSE       BIT(CAPS_HI_ASYMMETRIC_PAUSE)  #define HW_ATL_FW2X_CAP_SLEEP_PROXY      BIT(CAPS_HI_SLEEP_PROXY)  #define HW_ATL_FW2X_CAP_WOL              BIT(CAPS_HI_WOL) @@ -451,6 +453,24 @@ static int aq_fw2x_set_flow_control(struct aq_hw_s *self)  	return 0;  } +static u32 aq_fw2x_get_flow_control(struct aq_hw_s *self, u32 *fcmode) +{ +	u32 mpi_state = aq_hw_read_reg(self, HW_ATL_FW2X_MPI_STATE2_ADDR); + +	if (mpi_state & HW_ATL_FW2X_CAP_PAUSE) +		if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) +			*fcmode = AQ_NIC_FC_RX; +		else +			*fcmode = AQ_NIC_FC_RX | AQ_NIC_FC_TX; +	else +		if (mpi_state & HW_ATL_FW2X_CAP_ASYM_PAUSE) +			*fcmode = AQ_NIC_FC_TX; +		else +			*fcmode = 0; + +	return 0; +} +  const struct aq_fw_ops aq_fw_2x_ops = {  	.init = aq_fw2x_init,  	.deinit = aq_fw2x_deinit, @@ -465,4 +485,5 @@ const struct aq_fw_ops aq_fw_2x_ops = {  	.set_eee_rate = aq_fw2x_set_eee_rate,  	.get_eee_rate = aq_fw2x_get_eee_rate,  	.set_flow_control = aq_fw2x_set_flow_control, +	.get_flow_control = aq_fw2x_get_flow_control  }; diff --git a/drivers/net/ethernet/atheros/alx/alx.h b/drivers/net/ethernet/atheros/alx/alx.h index 78c5de467426..9d0e74f6b089 100644 --- a/drivers/net/ethernet/atheros/alx/alx.h +++ b/drivers/net/ethernet/atheros/alx/alx.h @@ -140,6 +140,5 @@ struct alx_priv {  };  extern const struct ethtool_ops alx_ethtool_ops; -extern const char alx_drv_name[];  #endif diff --git a/drivers/net/ethernet/atheros/alx/main.c b/drivers/net/ethernet/atheros/alx/main.c index 7968c644ad86..c131cfc1b79d 100644 --- a/drivers/net/ethernet/atheros/alx/main.c +++ b/drivers/net/ethernet/atheros/alx/main.c @@ -49,7 +49,7 @@  #include "hw.h"  #include "reg.h" -const char alx_drv_name[] = "alx"; +static const char alx_drv_name[] = "alx";  static void alx_free_txbuf(struct alx_tx_queue *txq, int entry)  { diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 4122553e224b..0e2d99c737e3 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -1902,9 +1902,6 @@ static void bcm_sysport_netif_start(struct net_device *dev)  		intrl2_1_mask_clear(priv, 0xffffffff);  	else  		intrl2_0_mask_clear(priv, INTRL2_0_TDMA_MBDONE_MASK); - -	/* Last call before we start the real business */ -	netif_tx_start_all_queues(dev);  }  static void rbuf_init(struct bcm_sysport_priv *priv) @@ -2048,6 +2045,8 @@ static int bcm_sysport_open(struct net_device *dev)  	bcm_sysport_netif_start(dev); +	netif_tx_start_all_queues(dev); +  	return 0;  out_clear_rx_int: @@ -2071,7 +2070,7 @@ static void bcm_sysport_netif_stop(struct net_device *dev)  	struct bcm_sysport_priv *priv = netdev_priv(dev);  	/* stop all software from updating hardware */ -	netif_tx_stop_all_queues(dev); +	netif_tx_disable(dev);  	napi_disable(&priv->napi);  	cancel_work_sync(&priv->dim.dim.work);  	phy_stop(dev->phydev); @@ -2658,12 +2657,12 @@ static int __maybe_unused bcm_sysport_suspend(struct device *d)  	if (!netif_running(dev))  		return 0; +	netif_device_detach(dev); +  	bcm_sysport_netif_stop(dev);  	phy_suspend(dev->phydev); -	netif_device_detach(dev); -  	/* Disable UniMAC RX */  	umac_enable_set(priv, CMD_RX_EN, 0); @@ -2746,8 +2745,6 @@ static int __maybe_unused bcm_sysport_resume(struct device *d)  		goto out_free_rx_ring;  	} -	netif_device_attach(dev); -  	/* RX pipe enable */  	topctrl_writel(priv, 0, RX_FLUSH_CNTL); @@ -2788,6 +2785,8 @@ static int __maybe_unused bcm_sysport_resume(struct device *d)  	bcm_sysport_netif_start(dev); +	netif_device_attach(dev); +  	return 0;  out_free_rx_ring: 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/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 20c1681bb1af..2d6f090bf644 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -2855,7 +2855,6 @@ static void bcmgenet_netif_start(struct net_device *dev)  	umac_enable_set(priv, CMD_TX_EN | CMD_RX_EN, true); -	netif_tx_start_all_queues(dev);  	bcmgenet_enable_tx_napi(priv);  	/* Monitor link interrupts now */ @@ -2937,6 +2936,8 @@ static int bcmgenet_open(struct net_device *dev)  	bcmgenet_netif_start(dev); +	netif_tx_start_all_queues(dev); +  	return 0;  err_irq1: @@ -2958,7 +2959,7 @@ static void bcmgenet_netif_stop(struct net_device *dev)  	struct bcmgenet_priv *priv = netdev_priv(dev);  	bcmgenet_disable_tx_napi(priv); -	netif_tx_stop_all_queues(dev); +	netif_tx_disable(dev);  	/* Disable MAC receive */  	umac_enable_set(priv, CMD_RX_EN, false); @@ -3620,13 +3621,13 @@ static int bcmgenet_suspend(struct device *d)  	if (!netif_running(dev))  		return 0; +	netif_device_detach(dev); +  	bcmgenet_netif_stop(dev);  	if (!device_may_wakeup(d))  		phy_suspend(dev->phydev); -	netif_device_detach(dev); -  	/* Prepare the device for Wake-on-LAN and switch to the slow clock */  	if (device_may_wakeup(d) && priv->wolopts) {  		ret = bcmgenet_power_down(priv, GENET_POWER_WOL_MAGIC); @@ -3700,8 +3701,6 @@ static int bcmgenet_resume(struct device *d)  	/* Always enable ring 16 - descriptor ring */  	bcmgenet_enable_dma(priv, dma_ctrl); -	netif_device_attach(dev); -  	if (!device_may_wakeup(d))  		phy_resume(dev->phydev); @@ -3710,6 +3709,8 @@ static int bcmgenet_resume(struct device *d)  	bcmgenet_netif_start(dev); +	netif_device_attach(dev); +  	return 0;  out_clk_disable: 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/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c index 55af04fa03a7..6c8dcb65ff03 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_main.c +++ b/drivers/net/ethernet/cavium/thunder/nic_main.c @@ -1441,6 +1441,9 @@ static void nic_remove(struct pci_dev *pdev)  {  	struct nicpf *nic = pci_get_drvdata(pdev); +	if (!nic) +		return; +  	if (nic->flags & NIC_SRIOV_ENABLED)  		pci_disable_sriov(pdev); 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/hisilicon/hip04_eth.c b/drivers/net/ethernet/hisilicon/hip04_eth.c index be268dcde8fa..f9a4e76c5a8b 100644 --- a/drivers/net/ethernet/hisilicon/hip04_eth.c +++ b/drivers/net/ethernet/hisilicon/hip04_eth.c @@ -915,10 +915,8 @@ static int hip04_mac_probe(struct platform_device *pdev)  	}  	ret = register_netdev(ndev); -	if (ret) { -		free_netdev(ndev); +	if (ret)  		goto alloc_fail; -	}  	return 0; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index 3f96aa30068e..20fcf0d1c2ce 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -3760,7 +3760,8 @@ static int hns3_reset_notify_init_enet(struct hnae3_handle *handle)  	/* Hardware table is only clear when pf resets */  	if (!(handle->flags & HNAE3_SUPPORT_VF)) {  		ret = hns3_restore_vlan(netdev); -		return ret; +		if (ret) +			return ret;  	}  	ret = hns3_restore_fd_rules(netdev); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c index aa5cb9834d73..494e562fe8c7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_tm.c @@ -1168,14 +1168,14 @@ static int hclge_pfc_setup_hw(struct hclge_dev *hdev)   */  static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc)  { -	struct hclge_vport *vport = hdev->vport; -	u32 i, k, qs_bitmap; -	int ret; +	int i;  	for (i = 0; i < HCLGE_BP_GRP_NUM; i++) { -		qs_bitmap = 0; +		u32 qs_bitmap = 0; +		int k, ret;  		for (k = 0; k < hdev->num_alloc_vport; k++) { +			struct hclge_vport *vport = &hdev->vport[k];  			u16 qs_id = vport->qs_offset + tc;  			u8 grp, sub_grp; @@ -1185,8 +1185,6 @@ static int hclge_bp_setup_hw(struct hclge_dev *hdev, u8 tc)  						  HCLGE_BP_SUB_GRP_ID_S);  			if (i == grp)  				qs_bitmap |= (1 << sub_grp); - -			vport++;  		}  		ret = hclge_tm_qs_bp_cfg(hdev, tc, i, qs_bitmap); diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 7893beffcc71..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;  } @@ -1545,7 +1536,7 @@ static netdev_tx_t ibmvnic_xmit(struct sk_buff *skb, struct net_device *netdev)  	tx_crq.v1.sge_len = cpu_to_be32(skb->len);  	tx_crq.v1.ioba = cpu_to_be64(data_dma_addr); -	if (adapter->vlan_header_insertion) { +	if (adapter->vlan_header_insertion && skb_vlan_tag_present(skb)) {  		tx_crq.v1.flags2 |= IBMVNIC_TX_VLAN_INSERT;  		tx_crq.v1.vlan_id = cpu_to_be16(skb->vlan_tci);  	} @@ -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/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index bc71a21c1dc2..a3f45335437c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -1413,7 +1413,7 @@ void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)  	}  	vsi->flags |= I40E_VSI_FLAG_FILTER_CHANGED; -	set_bit(__I40E_MACVLAN_SYNC_PENDING, vsi->state); +	set_bit(__I40E_MACVLAN_SYNC_PENDING, vsi->back->state);  }  /** @@ -12249,6 +12249,8 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)  			  NETIF_F_GSO_GRE		|  			  NETIF_F_GSO_GRE_CSUM		|  			  NETIF_F_GSO_PARTIAL		| +			  NETIF_F_GSO_IPXIP4		| +			  NETIF_F_GSO_IPXIP6		|  			  NETIF_F_GSO_UDP_TUNNEL	|  			  NETIF_F_GSO_UDP_TUNNEL_CSUM	|  			  NETIF_F_SCTP_CRC		| @@ -12266,13 +12268,13 @@ static int i40e_config_netdev(struct i40e_vsi *vsi)  	/* record features VLANs can make use of */  	netdev->vlan_features |= hw_enc_features | NETIF_F_TSO_MANGLEID; -	if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) -		netdev->hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC; -  	hw_features = hw_enc_features		|  		      NETIF_F_HW_VLAN_CTAG_TX	|  		      NETIF_F_HW_VLAN_CTAG_RX; +	if (!(pf->flags & I40E_FLAG_MFP_ENABLED)) +		hw_features |= NETIF_F_NTUPLE | NETIF_F_HW_TC; +  	netdev->hw_features |= hw_features;  	netdev->features |= hw_features | NETIF_F_HW_VLAN_CTAG_FILTER; diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index add1e457886d..433c8e688c78 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -33,7 +33,7 @@ static int i40e_alloc_xsk_umems(struct i40e_vsi *vsi)  }  /** - * i40e_add_xsk_umem - Store an UMEM for a certain ring/qid + * i40e_add_xsk_umem - Store a UMEM for a certain ring/qid   * @vsi: Current VSI   * @umem: UMEM to store   * @qid: Ring/qid to associate with the UMEM @@ -56,7 +56,7 @@ static int i40e_add_xsk_umem(struct i40e_vsi *vsi, struct xdp_umem *umem,  }  /** - * i40e_remove_xsk_umem - Remove an UMEM for a certain ring/qid + * i40e_remove_xsk_umem - Remove a UMEM for a certain ring/qid   * @vsi: Current VSI   * @qid: Ring/qid associated with the UMEM   **/ @@ -130,7 +130,7 @@ static void i40e_xsk_umem_dma_unmap(struct i40e_vsi *vsi, struct xdp_umem *umem)  }  /** - * i40e_xsk_umem_enable - Enable/associate an UMEM to a certain ring/qid + * i40e_xsk_umem_enable - Enable/associate a UMEM to a certain ring/qid   * @vsi: Current VSI   * @umem: UMEM   * @qid: Rx ring to associate UMEM to @@ -189,7 +189,7 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,  }  /** - * i40e_xsk_umem_disable - Diassociate an UMEM from a certain ring/qid + * i40e_xsk_umem_disable - Disassociate a UMEM from a certain ring/qid   * @vsi: Current VSI   * @qid: Rx ring to associate UMEM to   * @@ -255,12 +255,12 @@ int i40e_xsk_umem_query(struct i40e_vsi *vsi, struct xdp_umem **umem,  }  /** - * i40e_xsk_umem_query - Queries a certain ring/qid for its UMEM + * i40e_xsk_umem_setup - Enable/disassociate a UMEM to/from a ring/qid   * @vsi: Current VSI   * @umem: UMEM to enable/associate to a ring, or NULL to disable   * @qid: Rx ring to (dis)associate UMEM (from)to   * - * This function enables or disables an UMEM to a certain ring. + * This function enables or disables a UMEM to a certain ring.   *   * Returns 0 on success, <0 on failure   **/ @@ -276,7 +276,7 @@ int i40e_xsk_umem_setup(struct i40e_vsi *vsi, struct xdp_umem *umem,   * @rx_ring: Rx ring   * @xdp: xdp_buff used as input to the XDP program   * - * This function enables or disables an UMEM to a certain ring. + * This function enables or disables a UMEM to a certain ring.   *   * Returns any of I40E_XDP_{PASS, CONSUMED, TX, REDIR}   **/ diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 4c4b5717a627..b8548370f1c7 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -76,6 +76,8 @@ extern const char ice_drv_ver[];  #define ICE_MIN_INTR_PER_VF		(ICE_MIN_QS_PER_VF + 1)  #define ICE_DFLT_INTR_PER_VF		(ICE_DFLT_QS_PER_VF + 1) +#define ICE_MAX_RESET_WAIT		20 +  #define ICE_VSIQF_HKEY_ARRAY_SIZE	((VSIQF_HKEY_MAX_INDEX + 1) *	4)  #define ICE_DFLT_NETIF_M (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) @@ -189,7 +191,6 @@ struct ice_vsi {  	u64 tx_linearize;  	DECLARE_BITMAP(state, __ICE_STATE_NBITS);  	DECLARE_BITMAP(flags, ICE_VSI_FLAG_NBITS); -	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];  	unsigned int current_netdev_flags;  	u32 tx_restart;  	u32 tx_busy; @@ -369,5 +370,6 @@ int ice_set_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);  int ice_get_rss(struct ice_vsi *vsi, u8 *seed, u8 *lut, u16 lut_size);  void ice_fill_rss_lut(u8 *lut, u16 rss_table_size, u16 rss_size);  void ice_print_link_msg(struct ice_vsi *vsi, bool isup); +void ice_napi_del(struct ice_vsi *vsi);  #endif /* _ICE_H_ */ diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 8cd6a2401fd9..554fd707a6d6 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -811,6 +811,9 @@ void ice_deinit_hw(struct ice_hw *hw)  	/* Attempt to disable FW logging before shutting down control queues */  	ice_cfg_fw_log(hw, false);  	ice_shutdown_all_ctrlq(hw); + +	/* Clear VSI contexts if not already cleared */ +	ice_clear_all_vsi_ctx(hw);  }  /** diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 96923580f2a6..648acdb4c644 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -1517,10 +1517,15 @@ ice_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *pause)  	}  	if (!test_bit(__ICE_DOWN, pf->state)) { -		/* Give it a little more time to try to come back */ +		/* Give it a little more time to try to come back. If still +		 * down, restart autoneg link or reinitialize the interface. +		 */  		msleep(75);  		if (!test_bit(__ICE_DOWN, pf->state))  			return ice_nway_reset(netdev); + +		ice_down(vsi); +		ice_up(vsi);  	}  	return err; diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h index 5fdea6ec7675..596b9fb1c510 100644 --- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h +++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h @@ -242,6 +242,8 @@  #define GLNVM_ULD				0x000B6008  #define GLNVM_ULD_CORER_DONE_M			BIT(3)  #define GLNVM_ULD_GLOBR_DONE_M			BIT(4) +#define GLPCI_CNF2				0x000BE004 +#define GLPCI_CNF2_CACHELINE_SIZE_M		BIT(1)  #define PF_FUNC_RID				0x0009E880  #define PF_FUNC_RID_FUNC_NUM_S			0  #define PF_FUNC_RID_FUNC_NUM_M			ICE_M(0x7, 0) diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 5bacad01f0c9..1041fa2a7767 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -1997,7 +1997,7 @@ int ice_cfg_vlan_pruning(struct ice_vsi *vsi, bool ena)  	status = ice_update_vsi(&vsi->back->hw, vsi->idx, ctxt, NULL);  	if (status) {  		netdev_err(vsi->netdev, "%sabling VLAN pruning on VSI handle: %d, VSI HW ID: %d failed, err = %d, aq_err = %d\n", -			   ena ? "Ena" : "Dis", vsi->idx, vsi->vsi_num, status, +			   ena ? "En" : "Dis", vsi->idx, vsi->vsi_num, status,  			   vsi->back->hw.adminq.sq_last_status);  		goto err_out;  	} @@ -2458,6 +2458,7 @@ int ice_vsi_release(struct ice_vsi *vsi)  	 * on this wq  	 */  	if (vsi->netdev && !ice_is_reset_in_progress(pf->state)) { +		ice_napi_del(vsi);  		unregister_netdev(vsi->netdev);  		free_netdev(vsi->netdev);  		vsi->netdev = NULL; diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 05993451147a..333312a1d595 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -1465,7 +1465,7 @@ skip_req_irq:   * ice_napi_del - Remove NAPI handler for the VSI   * @vsi: VSI for which NAPI handler is to be removed   */ -static void ice_napi_del(struct ice_vsi *vsi) +void ice_napi_del(struct ice_vsi *vsi)  {  	int v_idx; @@ -1622,7 +1622,6 @@ static int ice_vlan_rx_add_vid(struct net_device *netdev,  {  	struct ice_netdev_priv *np = netdev_priv(netdev);  	struct ice_vsi *vsi = np->vsi; -	int ret;  	if (vid >= VLAN_N_VID) {  		netdev_err(netdev, "VLAN id requested %d is out of range %d\n", @@ -1635,7 +1634,8 @@ static int ice_vlan_rx_add_vid(struct net_device *netdev,  	/* Enable VLAN pruning when VLAN 0 is added */  	if (unlikely(!vid)) { -		ret = ice_cfg_vlan_pruning(vsi, true); +		int ret = ice_cfg_vlan_pruning(vsi, true); +  		if (ret)  			return ret;  	} @@ -1644,12 +1644,7 @@ static int ice_vlan_rx_add_vid(struct net_device *netdev,  	 * needed to continue allowing all untagged packets since VLAN prune  	 * list is applied to all packets by the switch  	 */ -	ret = ice_vsi_add_vlan(vsi, vid); - -	if (!ret) -		set_bit(vid, vsi->active_vlans); - -	return ret; +	return ice_vsi_add_vlan(vsi, vid);  }  /** @@ -1677,8 +1672,6 @@ static int ice_vlan_rx_kill_vid(struct net_device *netdev,  	if (status)  		return status; -	clear_bit(vid, vsi->active_vlans); -  	/* Disable VLAN pruning when VLAN 0 is removed */  	if (unlikely(!vid))  		status = ice_cfg_vlan_pruning(vsi, false); @@ -2002,6 +1995,22 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf)  }  /** + * ice_verify_cacheline_size - verify driver's assumption of 64 Byte cache lines + * @pf: pointer to the PF structure + * + * There is no error returned here because the driver should be able to handle + * 128 Byte cache lines, so we only print a warning in case issues are seen, + * specifically with Tx. + */ +static void ice_verify_cacheline_size(struct ice_pf *pf) +{ +	if (rd32(&pf->hw, GLPCI_CNF2) & GLPCI_CNF2_CACHELINE_SIZE_M) +		dev_warn(&pf->pdev->dev, +			 "%d Byte cache line assumption is invalid, driver may have Tx timeouts!\n", +			 ICE_CACHE_LINE_BYTES); +} + +/**   * ice_probe - Device initialization routine   * @pdev: PCI device information struct   * @ent: entry in ice_pci_tbl @@ -2151,6 +2160,8 @@ static int ice_probe(struct pci_dev *pdev,  	/* since everything is good, start the service timer */  	mod_timer(&pf->serv_tmr, round_jiffies(jiffies + pf->serv_tmr_period)); +	ice_verify_cacheline_size(pf); +  	return 0;  err_alloc_sw_unroll: @@ -2182,6 +2193,12 @@ static void ice_remove(struct pci_dev *pdev)  	if (!pf)  		return; +	for (i = 0; i < ICE_MAX_RESET_WAIT; i++) { +		if (!ice_is_reset_in_progress(pf->state)) +			break; +		msleep(100); +	} +  	set_bit(__ICE_DOWN, pf->state);  	ice_service_task_stop(pf); @@ -2510,31 +2527,6 @@ static int ice_vsi_vlan_setup(struct ice_vsi *vsi)  }  /** - * ice_restore_vlan - Reinstate VLANs when vsi/netdev comes back up - * @vsi: the VSI being brought back up - */ -static int ice_restore_vlan(struct ice_vsi *vsi) -{ -	int err; -	u16 vid; - -	if (!vsi->netdev) -		return -EINVAL; - -	err = ice_vsi_vlan_setup(vsi); -	if (err) -		return err; - -	for_each_set_bit(vid, vsi->active_vlans, VLAN_N_VID) { -		err = ice_vlan_rx_add_vid(vsi->netdev, htons(ETH_P_8021Q), vid); -		if (err) -			break; -	} - -	return err; -} - -/**   * ice_vsi_cfg - Setup the VSI   * @vsi: the VSI being configured   * @@ -2546,7 +2538,9 @@ static int ice_vsi_cfg(struct ice_vsi *vsi)  	if (vsi->netdev) {  		ice_set_rx_mode(vsi->netdev); -		err = ice_restore_vlan(vsi); + +		err = ice_vsi_vlan_setup(vsi); +  		if (err)  			return err;  	} @@ -3296,7 +3290,7 @@ static void ice_rebuild(struct ice_pf *pf)  	struct device *dev = &pf->pdev->dev;  	struct ice_hw *hw = &pf->hw;  	enum ice_status ret; -	int err; +	int err, i;  	if (test_bit(__ICE_DOWN, pf->state))  		goto clear_recovery; @@ -3370,6 +3364,22 @@ static void ice_rebuild(struct ice_pf *pf)  	}  	ice_reset_all_vfs(pf, true); + +	for (i = 0; i < pf->num_alloc_vsi; i++) { +		bool link_up; + +		if (!pf->vsi[i] || pf->vsi[i]->type != ICE_VSI_PF) +			continue; +		ice_get_link_status(pf->vsi[i]->port_info, &link_up); +		if (link_up) { +			netif_carrier_on(pf->vsi[i]->netdev); +			netif_tx_wake_all_queues(pf->vsi[i]->netdev); +		} else { +			netif_carrier_off(pf->vsi[i]->netdev); +			netif_tx_stop_all_queues(pf->vsi[i]->netdev); +		} +	} +  	/* if we get here, reset flow is successful */  	clear_bit(__ICE_RESET_FAILED, pf->state);  	return; diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 33403f39f1b3..40c9c6558956 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -348,6 +348,18 @@ static void ice_clear_vsi_ctx(struct ice_hw *hw, u16 vsi_handle)  }  /** + * ice_clear_all_vsi_ctx - clear all the VSI context entries + * @hw: pointer to the hw struct + */ +void ice_clear_all_vsi_ctx(struct ice_hw *hw) +{ +	u16 i; + +	for (i = 0; i < ICE_MAX_VSI; i++) +		ice_clear_vsi_ctx(hw, i); +} + +/**   * ice_add_vsi - add VSI context to the hardware and VSI handle list   * @hw: pointer to the hw struct   * @vsi_handle: unique VSI handle provided by drivers diff --git a/drivers/net/ethernet/intel/ice/ice_switch.h b/drivers/net/ethernet/intel/ice/ice_switch.h index b88d96a1ef69..d5ef0bd58bf9 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.h +++ b/drivers/net/ethernet/intel/ice/ice_switch.h @@ -190,6 +190,8 @@ ice_update_vsi(struct ice_hw *hw, u16 vsi_handle, struct ice_vsi_ctx *vsi_ctx,  	       struct ice_sq_cd *cd);  bool ice_is_vsi_valid(struct ice_hw *hw, u16 vsi_handle);  struct ice_vsi_ctx *ice_get_vsi_ctx(struct ice_hw *hw, u16 vsi_handle); +void ice_clear_all_vsi_ctx(struct ice_hw *hw); +/* Switch config */  enum ice_status ice_get_initial_sw_cfg(struct ice_hw *hw);  /* Switch/bridge related commands */ diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.c b/drivers/net/ethernet/intel/ice/ice_txrx.c index 5dae968d853e..fe5bbabbb41e 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.c +++ b/drivers/net/ethernet/intel/ice/ice_txrx.c @@ -1520,7 +1520,7 @@ int ice_tso(struct ice_tx_buf *first, struct ice_tx_offload_params *off)  	/* update gso_segs and bytecount */  	first->gso_segs = skb_shinfo(skb)->gso_segs; -	first->bytecount = (first->gso_segs - 1) * off->header_len; +	first->bytecount += (first->gso_segs - 1) * off->header_len;  	cd_tso_len = skb->len - off->header_len;  	cd_mss = skb_shinfo(skb)->gso_size; @@ -1556,15 +1556,15 @@ int ice_tso(struct ice_tx_buf *first, struct ice_tx_offload_params *off)   * magnitude greater than our largest possible GSO size.   *   * This would then be implemented as: - *     return (((size >> 12) * 85) >> 8) + 1; + *     return (((size >> 12) * 85) >> 8) + ICE_DESCS_FOR_SKB_DATA_PTR;   *   * Since multiplication and division are commutative, we can reorder   * operations into: - *     return ((size * 85) >> 20) + 1; + *     return ((size * 85) >> 20) + ICE_DESCS_FOR_SKB_DATA_PTR;   */  static unsigned int ice_txd_use_count(unsigned int size)  { -	return ((size * 85) >> 20) + 1; +	return ((size * 85) >> 20) + ICE_DESCS_FOR_SKB_DATA_PTR;  }  /** @@ -1706,7 +1706,8 @@ ice_xmit_frame_ring(struct sk_buff *skb, struct ice_ring *tx_ring)  	 *       + 1 desc for context descriptor,  	 * otherwise try next time  	 */ -	if (ice_maybe_stop_tx(tx_ring, count + 4 + 1)) { +	if (ice_maybe_stop_tx(tx_ring, count + ICE_DESCS_PER_CACHE_LINE + +			      ICE_DESCS_FOR_CTX_DESC)) {  		tx_ring->tx_stats.tx_busy++;  		return NETDEV_TX_BUSY;  	} diff --git a/drivers/net/ethernet/intel/ice/ice_txrx.h b/drivers/net/ethernet/intel/ice/ice_txrx.h index 1d0f58bd389b..75d0eaf6c9dd 100644 --- a/drivers/net/ethernet/intel/ice/ice_txrx.h +++ b/drivers/net/ethernet/intel/ice/ice_txrx.h @@ -22,8 +22,21 @@  #define ICE_RX_BUF_WRITE	16	/* Must be power of 2 */  #define ICE_MAX_TXQ_PER_TXQG	128 -/* Tx Descriptors needed, worst case */ -#define DESC_NEEDED (MAX_SKB_FRAGS + 4) +/* We are assuming that the cache line is always 64 Bytes here for ice. + * In order to make sure that is a correct assumption there is a check in probe + * to print a warning if the read from GLPCI_CNF2 tells us that the cache line + * size is 128 bytes. We do it this way because we do not want to read the + * GLPCI_CNF2 register or a variable containing the value on every pass through + * the Tx path. + */ +#define ICE_CACHE_LINE_BYTES		64 +#define ICE_DESCS_PER_CACHE_LINE	(ICE_CACHE_LINE_BYTES / \ +					 sizeof(struct ice_tx_desc)) +#define ICE_DESCS_FOR_CTX_DESC		1 +#define ICE_DESCS_FOR_SKB_DATA_PTR	1 +/* Tx descriptors needed, worst case */ +#define DESC_NEEDED (MAX_SKB_FRAGS + ICE_DESCS_FOR_CTX_DESC + \ +		     ICE_DESCS_PER_CACHE_LINE + ICE_DESCS_FOR_SKB_DATA_PTR)  #define ICE_DESC_UNUSED(R)	\  	((((R)->next_to_clean > (R)->next_to_use) ? 0 : (R)->count) + \  	(R)->next_to_clean - (R)->next_to_use - 1) diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index 12f9432abf11..f4dbc81c1988 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -92,12 +92,12 @@ struct ice_link_status {  	u64 phy_type_low;  	u16 max_frame_size;  	u16 link_speed; +	u16 req_speeds;  	u8 lse_ena;	/* Link Status Event notification */  	u8 link_info;  	u8 an_info;  	u8 ext_info;  	u8 pacing; -	u8 req_speeds;  	/* Refer to #define from module_type[ICE_MODULE_TYPE_TOTAL_BYTE] of  	 * ice_aqc_get_phy_caps structure  	 */ diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c index 45f10f8f01dc..e71065f9d391 100644 --- a/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c @@ -348,7 +348,7 @@ static int ice_vsi_set_pvid(struct ice_vsi *vsi, u16 vid)  	struct ice_vsi_ctx ctxt = { 0 };  	enum ice_status status; -	ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_TAGGED | +	ctxt.info.vlan_flags = ICE_AQ_VSI_VLAN_MODE_UNTAGGED |  			       ICE_AQ_VSI_PVLAN_INSERT_PVID |  			       ICE_AQ_VSI_VLAN_EMOD_STR;  	ctxt.info.pvid = cpu_to_le16(vid); @@ -2171,7 +2171,6 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)  			if (!ice_vsi_add_vlan(vsi, vid)) {  				vf->num_vlan++; -				set_bit(vid, vsi->active_vlans);  				/* Enable VLAN pruning when VLAN 0 is added */  				if (unlikely(!vid)) @@ -2190,7 +2189,6 @@ static int ice_vc_process_vlan_msg(struct ice_vf *vf, u8 *msg, bool add_v)  			 */  			if (!ice_vsi_kill_vlan(vsi, vid)) {  				vf->num_vlan--; -				clear_bit(vid, vsi->active_vlans);  				/* Disable VLAN pruning when removing VLAN 0 */  				if (unlikely(!vid)) diff --git a/drivers/net/ethernet/intel/igb/e1000_i210.c b/drivers/net/ethernet/intel/igb/e1000_i210.c index c54ebedca6da..c393cb2c0f16 100644 --- a/drivers/net/ethernet/intel/igb/e1000_i210.c +++ b/drivers/net/ethernet/intel/igb/e1000_i210.c @@ -842,6 +842,7 @@ s32 igb_pll_workaround_i210(struct e1000_hw *hw)  		nvm_word = E1000_INVM_DEFAULT_AL;  	tmp_nvm = nvm_word | E1000_INVM_PLL_WO_VAL;  	igb_write_phy_reg_82580(hw, I347AT4_PAGE_SELECT, E1000_PHY_PLL_FREQ_PAGE); +	phy_word = E1000_PHY_PLL_UNCONF;  	for (i = 0; i < E1000_MAX_PLL_TRIES; i++) {  		/* check current state directly from internal PHY */  		igb_read_phy_reg_82580(hw, E1000_PHY_PLL_FREQ_REG, &phy_word); diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 29ced6b74d36..2b95dc9c7a6a 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c @@ -53,13 +53,15 @@   *   2^40 * 10^-9 /  60  = 18.3 minutes.   *   * SYSTIM is converted to real time using a timecounter. As - * timecounter_cyc2time() allows old timestamps, the timecounter - * needs to be updated at least once per half of the SYSTIM interval. - * Scheduling of delayed work is not very accurate, so we aim for 8 - * minutes to be sure the actual interval is shorter than 9.16 minutes. + * timecounter_cyc2time() allows old timestamps, the timecounter needs + * to be updated at least once per half of the SYSTIM interval. + * Scheduling of delayed work is not very accurate, and also the NIC + * clock can be adjusted to run up to 6% faster and the system clock + * up to 10% slower, so we aim for 6 minutes to be sure the actual + * interval in the NIC time is shorter than 9.16 minutes.   */ -#define IGB_SYSTIM_OVERFLOW_PERIOD	(HZ * 60 * 8) +#define IGB_SYSTIM_OVERFLOW_PERIOD	(HZ * 60 * 6)  #define IGB_PTP_TX_TIMEOUT		(HZ * 15)  #define INCPERIOD_82576			BIT(E1000_TIMINCA_16NS_SHIFT)  #define INCVALUE_82576_MASK		GENMASK(E1000_TIMINCA_16NS_SHIFT - 1, 0) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 10dbaf4f6e80..9c42f741ed5e 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -2262,7 +2262,9 @@ static s32 ixgbe_get_link_capabilities_X550em(struct ixgbe_hw *hw,  		*autoneg = false;  		if (hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core0 || -		    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1) { +		    hw->phy.sfp_type == ixgbe_sfp_type_1g_sx_core1 || +		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core0 || +		    hw->phy.sfp_type == ixgbe_sfp_type_1g_lx_core1) {  			*speed = IXGBE_LINK_SPEED_1GB_FULL;  			return 0;  		} 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 5bfd349bf41a..e5397c8197b9 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -494,7 +494,7 @@ struct mvneta_port {  #if defined(__LITTLE_ENDIAN)  struct mvneta_tx_desc {  	u32  command;		/* Options used by HW for packet transmitting.*/ -	u16  reserverd1;	/* csum_l4 (for future use)		*/ +	u16  reserved1;		/* csum_l4 (for future use)		*/  	u16  data_size;		/* Data size of transmitted packet in bytes */  	u32  buf_phys_addr;	/* Physical addr of transmitted buffer	*/  	u32  reserved2;		/* hw_cmd - (for future use, PMT)	*/ @@ -519,7 +519,7 @@ struct mvneta_rx_desc {  #else  struct mvneta_tx_desc {  	u16  data_size;		/* Data size of transmitted packet in bytes */ -	u16  reserverd1;	/* csum_l4 (for future use)		*/ +	u16  reserved1;		/* csum_l4 (for future use)		*/  	u32  command;		/* Options used by HW for packet transmitting.*/  	u32  reserved2;		/* hw_cmd - (for future use, PMT)	*/  	u32  buf_phys_addr;	/* Physical addr of transmitted buffer	*/ @@ -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/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 1857ee0f0871..6f5153afcab4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c @@ -1006,7 +1006,6 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)  		ring->packets++;  	}  	ring->bytes += tx_info->nr_bytes; -	netdev_tx_sent_queue(ring->tx_queue, tx_info->nr_bytes);  	AVG_PERF_COUNTER(priv->pstats.tx_pktsz_avg, skb->len);  	if (tx_info->inl) @@ -1044,7 +1043,10 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)  		netif_tx_stop_queue(ring->tx_queue);  		ring->queue_stopped++;  	} -	send_doorbell = !skb->xmit_more || netif_xmit_stopped(ring->tx_queue); + +	send_doorbell = __netdev_tx_sent_queue(ring->tx_queue, +					       tx_info->nr_bytes, +					       skb->xmit_more);  	real_size = (real_size / 16) & 0x3f; 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/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index a2df12b79f8e..9bec940330a4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3568,7 +3568,6 @@ static int mlxsw_sp_cpu_policers_set(struct mlxsw_core *mlxsw_core)  			burst_size = 7;  			break;  		case MLXSW_REG_HTGT_TRAP_GROUP_SP_IP2ME: -			is_bytes = true;  			rate = 4 * 1024;  			burst_size = 4;  			break; diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index 867cddba840f..e8ca98c070f6 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -1672,7 +1672,7 @@ static int lan743x_tx_napi_poll(struct napi_struct *napi, int weight)  		netif_wake_queue(adapter->netdev);  	} -	if (!napi_complete_done(napi, weight)) +	if (!napi_complete(napi))  		goto done;  	/* enable isr */ @@ -1681,7 +1681,7 @@ static int lan743x_tx_napi_poll(struct napi_struct *napi, int weight)  	lan743x_csr_read(adapter, INT_STS);  done: -	return weight; +	return 0;  }  static void lan743x_tx_ring_cleanup(struct lan743x_tx *tx) @@ -1870,9 +1870,9 @@ static int lan743x_tx_open(struct lan743x_tx *tx)  	tx->vector_flags = lan743x_intr_get_vector_flags(adapter,  							 INT_BIT_DMA_TX_  							 (tx->channel_number)); -	netif_napi_add(adapter->netdev, -		       &tx->napi, lan743x_tx_napi_poll, -		       tx->ring_size - 1); +	netif_tx_napi_add(adapter->netdev, +			  &tx->napi, lan743x_tx_napi_poll, +			  tx->ring_size - 1);  	napi_enable(&tx->napi);  	data = 0; @@ -3017,6 +3017,7 @@ static const struct dev_pm_ops lan743x_pm_ops = {  static const struct pci_device_id lan743x_pcidev_tbl[] = {  	{ PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7430) }, +	{ PCI_DEVICE(PCI_VENDOR_ID_SMSC, PCI_DEVICE_ID_SMSC_LAN7431) },  	{ 0, }  }; diff --git a/drivers/net/ethernet/microchip/lan743x_main.h b/drivers/net/ethernet/microchip/lan743x_main.h index 0e82b6368798..2d6eea18973e 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.h +++ b/drivers/net/ethernet/microchip/lan743x_main.h @@ -548,6 +548,7 @@ struct lan743x_adapter;  /* SMSC acquired EFAR late 1990's, MCHP acquired SMSC 2012 */  #define PCI_VENDOR_ID_SMSC		PCI_VENDOR_ID_EFAR  #define PCI_DEVICE_ID_SMSC_LAN7430	(0x7430) +#define PCI_DEVICE_ID_SMSC_LAN7431	(0x7431)  #define PCI_CONFIG_LENGTH		(0x1000) 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_debug.c b/drivers/net/ethernet/qlogic/qed/qed_debug.c index 78a638ec7c0a..979f1e4bc18b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_debug.c +++ b/drivers/net/ethernet/qlogic/qed/qed_debug.c @@ -6071,7 +6071,7 @@ static const char * const s_igu_fifo_error_strs[] = {  	"no error",  	"length error",  	"function disabled", -	"VF sent command to attnetion address", +	"VF sent command to attention address",  	"host sent prod update command",  	"read of during interrupt register while in MIMD mode",  	"access to PXP BAR reserved address", 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_fcoe.c b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c index cc1b373c0ace..46dc93d3b9b5 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_fcoe.c +++ b/drivers/net/ethernet/qlogic/qed/qed_fcoe.c @@ -147,7 +147,8 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn,  		       "Cannot satisfy CQ amount. CQs requested %d, CQs available %d. Aborting function start\n",  		       fcoe_pf_params->num_cqs,  		       p_hwfn->hw_info.feat_num[QED_FCOE_CQ]); -		return -EINVAL; +		rc = -EINVAL; +		goto err;  	}  	p_data->mtu = cpu_to_le16(fcoe_pf_params->mtu); @@ -156,14 +157,14 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn,  	rc = qed_cxt_acquire_cid(p_hwfn, PROTOCOLID_FCOE, &dummy_cid);  	if (rc) -		return rc; +		goto err;  	cxt_info.iid = dummy_cid;  	rc = qed_cxt_get_cid_info(p_hwfn, &cxt_info);  	if (rc) {  		DP_NOTICE(p_hwfn, "Cannot find context info for dummy cid=%d\n",  			  dummy_cid); -		return rc; +		goto err;  	}  	p_cxt = cxt_info.p_cxt;  	SET_FIELD(p_cxt->tstorm_ag_context.flags3, @@ -240,6 +241,10 @@ qed_sp_fcoe_func_start(struct qed_hwfn *p_hwfn,  	rc = qed_spq_post(p_hwfn, p_ent, NULL);  	return rc; + +err: +	qed_sp_destroy_request(p_hwfn, p_ent); +	return rc;  }  static int 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_iscsi.c b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c index 1135387bd99d..4f8a685d1a55 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_iscsi.c +++ b/drivers/net/ethernet/qlogic/qed/qed_iscsi.c @@ -200,6 +200,7 @@ qed_sp_iscsi_func_start(struct qed_hwfn *p_hwfn,  		       "Cannot satisfy CQ amount. Queues requested %d, CQs available %d. Aborting function start\n",  		       p_params->num_queues,  		       p_hwfn->hw_info.feat_num[QED_ISCSI_CQ]); +		qed_sp_destroy_request(p_hwfn, p_ent);  		return -EINVAL;  	} diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c index 82a1bd1f8a8c..67c02ea93906 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_l2.c +++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c @@ -740,8 +740,7 @@ int qed_sp_vport_update(struct qed_hwfn *p_hwfn,  	rc = qed_sp_vport_update_rss(p_hwfn, p_ramrod, p_rss_params);  	if (rc) { -		/* Return spq entry which is taken in qed_sp_init_request()*/ -		qed_spq_return_entry(p_hwfn, p_ent); +		qed_sp_destroy_request(p_hwfn, p_ent);  		return rc;  	} @@ -1355,6 +1354,7 @@ qed_filter_ucast_common(struct qed_hwfn *p_hwfn,  			DP_NOTICE(p_hwfn,  				  "%d is not supported yet\n",  				  p_filter_cmd->opcode); +			qed_sp_destroy_request(p_hwfn, *pp_ent);  			return -EINVAL;  		} @@ -2056,13 +2056,13 @@ qed_configure_rfs_ntuple_filter(struct qed_hwfn *p_hwfn,  	} else {  		rc = qed_fw_vport(p_hwfn, p_params->vport_id, &abs_vport_id);  		if (rc) -			return rc; +			goto err;  		if (p_params->qid != QED_RFS_NTUPLE_QID_RSS) {  			rc = qed_fw_l2_queue(p_hwfn, p_params->qid,  					     &abs_rx_q_id);  			if (rc) -				return rc; +				goto err;  			p_ramrod->rx_qid_valid = 1;  			p_ramrod->rx_qid = cpu_to_le16(abs_rx_q_id); @@ -2083,6 +2083,10 @@ qed_configure_rfs_ntuple_filter(struct qed_hwfn *p_hwfn,  		   (u64)p_params->addr, p_params->length);  	return qed_spq_post(p_hwfn, p_ent, NULL); + +err: +	qed_sp_destroy_request(p_hwfn, p_ent); +	return rc;  }  int qed_get_rxq_coalesce(struct qed_hwfn *p_hwfn, 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_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c index f40f654398a0..a96364df4320 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c +++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c @@ -1944,9 +1944,12 @@ int qed_mcp_trans_speed_mask(struct qed_hwfn *p_hwfn,  			     struct qed_ptt *p_ptt, u32 *p_speed_mask)  {  	u32 transceiver_type, transceiver_state; +	int ret; -	qed_mcp_get_transceiver_data(p_hwfn, p_ptt, &transceiver_state, -				     &transceiver_type); +	ret = qed_mcp_get_transceiver_data(p_hwfn, p_ptt, &transceiver_state, +					   &transceiver_type); +	if (ret) +		return ret;  	if (qed_is_transceiver_ready(transceiver_state, transceiver_type) ==  				     false) diff --git a/drivers/net/ethernet/qlogic/qed/qed_rdma.c b/drivers/net/ethernet/qlogic/qed/qed_rdma.c index c71391b9c757..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); @@ -1514,6 +1521,7 @@ qed_rdma_register_tid(void *rdma_cxt,  	default:  		rc = -EINVAL;  		DP_VERBOSE(p_hwfn, QED_MSG_RDMA, "rc = %d\n", rc); +		qed_sp_destroy_request(p_hwfn, p_ent);  		return rc;  	}  	SET_FIELD(p_ramrod->flags1, @@ -1801,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); @@ -1848,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; @@ -1857,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/ethernet/qlogic/qed/qed_roce.c b/drivers/net/ethernet/qlogic/qed/qed_roce.c index f9167d1354bb..e49fada85410 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_roce.c +++ b/drivers/net/ethernet/qlogic/qed/qed_roce.c @@ -745,6 +745,7 @@ static int qed_roce_sp_destroy_qp_responder(struct qed_hwfn *p_hwfn,  		DP_NOTICE(p_hwfn,  			  "qed destroy responder failed: cannot allocate memory (ramrod). rc = %d\n",  			  rc); +		qed_sp_destroy_request(p_hwfn, p_ent);  		return rc;  	} diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp.h b/drivers/net/ethernet/qlogic/qed/qed_sp.h index e95431f6acd4..3157c0d99441 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp.h +++ b/drivers/net/ethernet/qlogic/qed/qed_sp.h @@ -167,6 +167,9 @@ struct qed_spq_entry {  	enum spq_mode			comp_mode;  	struct qed_spq_comp_cb		comp_cb;  	struct qed_spq_comp_done	comp_done; /* SPQ_MODE_EBLOCK */ + +	/* Posted entry for unlimited list entry in EBLOCK mode */ +	struct qed_spq_entry		*post_ent;  };  struct qed_eq { @@ -396,6 +399,17 @@ struct qed_sp_init_data {  	struct qed_spq_comp_cb *p_comp_data;  }; +/** + * @brief Returns a SPQ entry to the pool / frees the entry if allocated. + *        Should be called on in error flows after initializing the SPQ entry + *        and before posting it. + * + * @param p_hwfn + * @param p_ent + */ +void qed_sp_destroy_request(struct qed_hwfn *p_hwfn, +			    struct qed_spq_entry *p_ent); +  int qed_sp_init_request(struct qed_hwfn *p_hwfn,  			struct qed_spq_entry **pp_ent,  			u8 cmd, diff --git a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c index 77b6248ad3b9..888274fa208b 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sp_commands.c @@ -47,6 +47,19 @@  #include "qed_sp.h"  #include "qed_sriov.h" +void qed_sp_destroy_request(struct qed_hwfn *p_hwfn, +			    struct qed_spq_entry *p_ent) +{ +	/* qed_spq_get_entry() can either get an entry from the free_pool, +	 * or, if no entries are left, allocate a new entry and add it to +	 * the unlimited_pending list. +	 */ +	if (p_ent->queue == &p_hwfn->p_spq->unlimited_pending) +		kfree(p_ent); +	else +		qed_spq_return_entry(p_hwfn, p_ent); +} +  int qed_sp_init_request(struct qed_hwfn *p_hwfn,  			struct qed_spq_entry **pp_ent,  			u8 cmd, u8 protocol, struct qed_sp_init_data *p_data) @@ -80,7 +93,7 @@ int qed_sp_init_request(struct qed_hwfn *p_hwfn,  	case QED_SPQ_MODE_BLOCK:  		if (!p_data->p_comp_data) -			return -EINVAL; +			goto err;  		p_ent->comp_cb.cookie = p_data->p_comp_data->cookie;  		break; @@ -95,7 +108,7 @@ int qed_sp_init_request(struct qed_hwfn *p_hwfn,  	default:  		DP_NOTICE(p_hwfn, "Unknown SPQE completion mode %d\n",  			  p_ent->comp_mode); -		return -EINVAL; +		goto err;  	}  	DP_VERBOSE(p_hwfn, QED_MSG_SPQ, @@ -109,6 +122,11 @@ int qed_sp_init_request(struct qed_hwfn *p_hwfn,  	memset(&p_ent->ramrod, 0, sizeof(p_ent->ramrod));  	return 0; + +err: +	qed_sp_destroy_request(p_hwfn, p_ent); + +	return -EINVAL;  }  static enum tunnel_clss qed_tunn_clss_to_fw_clss(u8 type) diff --git a/drivers/net/ethernet/qlogic/qed/qed_spq.c b/drivers/net/ethernet/qlogic/qed/qed_spq.c index c4a6274dd625..0a9c5bb0fa48 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_spq.c +++ b/drivers/net/ethernet/qlogic/qed/qed_spq.c @@ -142,6 +142,7 @@ static int qed_spq_block(struct qed_hwfn *p_hwfn,  	DP_INFO(p_hwfn, "Ramrod is stuck, requesting MCP drain\n");  	rc = qed_mcp_drain(p_hwfn, p_ptt); +	qed_ptt_release(p_hwfn, p_ptt);  	if (rc) {  		DP_NOTICE(p_hwfn, "MCP drain failed\n");  		goto err; @@ -150,18 +151,15 @@ static int qed_spq_block(struct qed_hwfn *p_hwfn,  	/* Retry after drain */  	rc = __qed_spq_block(p_hwfn, p_ent, p_fw_ret, true);  	if (!rc) -		goto out; +		return 0;  	comp_done = (struct qed_spq_comp_done *)p_ent->comp_cb.cookie; -	if (comp_done->done == 1) +	if (comp_done->done == 1) {  		if (p_fw_ret)  			*p_fw_ret = comp_done->fw_return_code; -out: -	qed_ptt_release(p_hwfn, p_ptt); -	return 0; - +		return 0; +	}  err: -	qed_ptt_release(p_hwfn, p_ptt);  	DP_NOTICE(p_hwfn,  		  "Ramrod is stuck [CID %08x cmd %02x protocol %02x echo %04x]\n",  		  le32_to_cpu(p_ent->elem.hdr.cid), @@ -685,6 +683,8 @@ static int qed_spq_add_entry(struct qed_hwfn *p_hwfn,  			/* EBLOCK responsible to free the allocated p_ent */  			if (p_ent->comp_mode != QED_SPQ_MODE_EBLOCK)  				kfree(p_ent); +			else +				p_ent->post_ent = p_en2;  			p_ent = p_en2;  		} @@ -767,6 +767,25 @@ static int qed_spq_pend_post(struct qed_hwfn *p_hwfn)  				 SPQ_HIGH_PRI_RESERVE_DEFAULT);  } +/* Avoid overriding of SPQ entries when getting out-of-order completions, by + * marking the completions in a bitmap and increasing the chain consumer only + * for the first successive completed entries. + */ +static void qed_spq_comp_bmap_update(struct qed_hwfn *p_hwfn, __le16 echo) +{ +	u16 pos = le16_to_cpu(echo) % SPQ_RING_SIZE; +	struct qed_spq *p_spq = p_hwfn->p_spq; + +	__set_bit(pos, p_spq->p_comp_bitmap); +	while (test_bit(p_spq->comp_bitmap_idx, +			p_spq->p_comp_bitmap)) { +		__clear_bit(p_spq->comp_bitmap_idx, +			    p_spq->p_comp_bitmap); +		p_spq->comp_bitmap_idx++; +		qed_chain_return_produced(&p_spq->chain); +	} +} +  int qed_spq_post(struct qed_hwfn *p_hwfn,  		 struct qed_spq_entry *p_ent, u8 *fw_return_code)  { @@ -824,11 +843,12 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,  				   p_ent->queue == &p_spq->unlimited_pending);  		if (p_ent->queue == &p_spq->unlimited_pending) { -			/* This is an allocated p_ent which does not need to -			 * return to pool. -			 */ +			struct qed_spq_entry *p_post_ent = p_ent->post_ent; +  			kfree(p_ent); -			return rc; + +			/* Return the entry which was actually posted */ +			p_ent = p_post_ent;  		}  		if (rc) @@ -842,7 +862,7 @@ int qed_spq_post(struct qed_hwfn *p_hwfn,  spq_post_fail2:  	spin_lock_bh(&p_spq->lock);  	list_del(&p_ent->list); -	qed_chain_return_produced(&p_spq->chain); +	qed_spq_comp_bmap_update(p_hwfn, p_ent->elem.hdr.echo);  spq_post_fail:  	/* return to the free pool */ @@ -874,25 +894,8 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,  	spin_lock_bh(&p_spq->lock);  	list_for_each_entry_safe(p_ent, tmp, &p_spq->completion_pending, list) {  		if (p_ent->elem.hdr.echo == echo) { -			u16 pos = le16_to_cpu(echo) % SPQ_RING_SIZE; -  			list_del(&p_ent->list); - -			/* Avoid overriding of SPQ entries when getting -			 * out-of-order completions, by marking the completions -			 * in a bitmap and increasing the chain consumer only -			 * for the first successive completed entries. -			 */ -			__set_bit(pos, p_spq->p_comp_bitmap); - -			while (test_bit(p_spq->comp_bitmap_idx, -					p_spq->p_comp_bitmap)) { -				__clear_bit(p_spq->comp_bitmap_idx, -					    p_spq->p_comp_bitmap); -				p_spq->comp_bitmap_idx++; -				qed_chain_return_produced(&p_spq->chain); -			} - +			qed_spq_comp_bmap_update(p_hwfn, echo);  			p_spq->comp_count++;  			found = p_ent;  			break; @@ -931,11 +934,9 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,  			   QED_MSG_SPQ,  			   "Got a completion without a callback function\n"); -	if ((found->comp_mode != QED_SPQ_MODE_EBLOCK) || -	    (found->queue == &p_spq->unlimited_pending)) +	if (found->comp_mode != QED_SPQ_MODE_EBLOCK)  		/* EBLOCK  is responsible for returning its own entry into the -		 * free list, unless it originally added the entry into the -		 * unlimited pending list. +		 * free list.  		 */  		qed_spq_return_entry(p_hwfn, found); diff --git a/drivers/net/ethernet/qlogic/qed/qed_sriov.c b/drivers/net/ethernet/qlogic/qed/qed_sriov.c index 9b08a9d9e151..ca6290fa0f30 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_sriov.c +++ b/drivers/net/ethernet/qlogic/qed/qed_sriov.c @@ -101,6 +101,7 @@ static int qed_sp_vf_start(struct qed_hwfn *p_hwfn, struct qed_vf_info *p_vf)  	default:  		DP_NOTICE(p_hwfn, "Unknown VF personality %d\n",  			  p_hwfn->hw_info.personality); +		qed_sp_destroy_request(p_hwfn, p_ent);  		return -EINVAL;  	} diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 9647578cbe6a..14f26bf3b388 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c @@ -459,7 +459,7 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,  			 struct cmd_desc_type0 *first_desc, struct sk_buff *skb,  			 struct qlcnic_host_tx_ring *tx_ring)  { -	u8 l4proto, opcode = 0, hdr_len = 0; +	u8 l4proto, opcode = 0, hdr_len = 0, tag_vlan = 0;  	u16 flags = 0, vlan_tci = 0;  	int copied, offset, copy_len, size;  	struct cmd_desc_type0 *hwdesc; @@ -472,14 +472,16 @@ static int qlcnic_tx_pkt(struct qlcnic_adapter *adapter,  		flags = QLCNIC_FLAGS_VLAN_TAGGED;  		vlan_tci = ntohs(vh->h_vlan_TCI);  		protocol = ntohs(vh->h_vlan_encapsulated_proto); +		tag_vlan = 1;  	} else if (skb_vlan_tag_present(skb)) {  		flags = QLCNIC_FLAGS_VLAN_OOB;  		vlan_tci = skb_vlan_tag_get(skb); +		tag_vlan = 1;  	}  	if (unlikely(adapter->tx_pvid)) { -		if (vlan_tci && !(adapter->flags & QLCNIC_TAGGING_ENABLED)) +		if (tag_vlan && !(adapter->flags & QLCNIC_TAGGING_ENABLED))  			return -EIO; -		if (vlan_tci && (adapter->flags & QLCNIC_TAGGING_ENABLED)) +		if (tag_vlan && (adapter->flags & QLCNIC_TAGGING_ENABLED))  			goto set_flags;  		flags = QLCNIC_FLAGS_VLAN_OOB; diff --git a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c index 0afc3d335d56..d11c16aeb19a 100644 --- a/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c +++ b/drivers/net/ethernet/qualcomm/rmnet/rmnet_vnd.c @@ -234,7 +234,7 @@ int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev,  		      struct net_device *real_dev,  		      struct rmnet_endpoint *ep)  { -	struct rmnet_priv *priv; +	struct rmnet_priv *priv = netdev_priv(rmnet_dev);  	int rc;  	if (ep->egress_dev) @@ -247,6 +247,8 @@ int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev,  	rmnet_dev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;  	rmnet_dev->hw_features |= NETIF_F_SG; +	priv->real_dev = real_dev; +  	rc = register_netdevice(rmnet_dev);  	if (!rc) {  		ep->egress_dev = rmnet_dev; @@ -255,9 +257,7 @@ int rmnet_vnd_newlink(u8 id, struct net_device *rmnet_dev,  		rmnet_dev->rtnl_link_ops = &rmnet_link_ops; -		priv = netdev_priv(rmnet_dev);  		priv->mux_id = id; -		priv->real_dev = real_dev;  		netdev_dbg(rmnet_dev, "rmnet dev created\n");  	} diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h index b1b305f8f414..272b9ca66314 100644 --- a/drivers/net/ethernet/stmicro/stmmac/common.h +++ b/drivers/net/ethernet/stmicro/stmmac/common.h @@ -365,7 +365,8 @@ struct dma_features {  /* GMAC TX FIFO is 8K, Rx FIFO is 16K */  #define BUF_SIZE_16KiB 16384 -#define BUF_SIZE_8KiB 8192 +/* RX Buffer size must be < 8191 and multiple of 4/8/16 bytes */ +#define BUF_SIZE_8KiB 8188  #define BUF_SIZE_4KiB 4096  #define BUF_SIZE_2KiB 2048 diff --git a/drivers/net/ethernet/stmicro/stmmac/descs_com.h b/drivers/net/ethernet/stmicro/stmmac/descs_com.h index ca9d7e48034c..40d6356a7e73 100644 --- a/drivers/net/ethernet/stmicro/stmmac/descs_com.h +++ b/drivers/net/ethernet/stmicro/stmmac/descs_com.h @@ -31,7 +31,7 @@  /* Enhanced descriptors */  static inline void ehn_desc_rx_set_on_ring(struct dma_desc *p, int end)  { -	p->des1 |= cpu_to_le32(((BUF_SIZE_8KiB - 1) +	p->des1 |= cpu_to_le32((BUF_SIZE_8KiB  			<< ERDES1_BUFFER2_SIZE_SHIFT)  		   & ERDES1_BUFFER2_SIZE_MASK); diff --git a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c index 77914c89d749..5ef91a790f9d 100644 --- a/drivers/net/ethernet/stmicro/stmmac/enh_desc.c +++ b/drivers/net/ethernet/stmicro/stmmac/enh_desc.c @@ -262,7 +262,7 @@ static void enh_desc_init_rx_desc(struct dma_desc *p, int disable_rx_ic,  				  int mode, int end)  {  	p->des0 |= cpu_to_le32(RDES0_OWN); -	p->des1 |= cpu_to_le32((BUF_SIZE_8KiB - 1) & ERDES1_BUFFER1_SIZE_MASK); +	p->des1 |= cpu_to_le32(BUF_SIZE_8KiB & ERDES1_BUFFER1_SIZE_MASK);  	if (mode == STMMAC_CHAIN_MODE)  		ehn_desc_rx_set_on_chain(p); diff --git a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c index abc3f85270cd..d8c5bc412219 100644 --- a/drivers/net/ethernet/stmicro/stmmac/ring_mode.c +++ b/drivers/net/ethernet/stmicro/stmmac/ring_mode.c @@ -140,7 +140,7 @@ static void clean_desc3(void *priv_ptr, struct dma_desc *p)  static int set_16kib_bfsize(int mtu)  {  	int ret = 0; -	if (unlikely(mtu >= BUF_SIZE_8KiB)) +	if (unlikely(mtu > BUF_SIZE_8KiB))  		ret = BUF_SIZE_16KiB;  	return ret;  } diff --git a/drivers/net/ethernet/via/via-velocity.c b/drivers/net/ethernet/via/via-velocity.c index ef9538ee53d0..82412691ee66 100644 --- a/drivers/net/ethernet/via/via-velocity.c +++ b/drivers/net/ethernet/via/via-velocity.c @@ -3605,7 +3605,7 @@ static const char velocity_gstrings[][ETH_GSTRING_LEN] = {  	"tx_jumbo",  	"rx_mac_control_frames",  	"tx_mac_control_frames", -	"rx_frame_alignement_errors", +	"rx_frame_alignment_errors",  	"rx_long_ok",  	"rx_long_err",  	"tx_sqe_errors", diff --git a/drivers/net/fddi/defza.c b/drivers/net/fddi/defza.c index 3b7f10a5f06a..c5cae8e74dc4 100644 --- a/drivers/net/fddi/defza.c +++ b/drivers/net/fddi/defza.c @@ -1,4 +1,4 @@ -// SPDX-License-Identifier: GPL-2.0 +// SPDX-License-Identifier: GPL-2.0+  /*	FDDI network adapter driver for DEC FDDIcontroller 700/700-C devices.   *   *	Copyright (c) 2018  Maciej W. Rozycki @@ -56,7 +56,7 @@  #define DRV_VERSION "v.1.1.4"  #define DRV_RELDATE "Oct  6 2018" -static char version[] = +static const char version[] =  	DRV_NAME ": " DRV_VERSION "  " DRV_RELDATE "  Maciej W. Rozycki\n";  MODULE_AUTHOR("Maciej W. Rozycki <macro@linux-mips.org>"); @@ -784,7 +784,7 @@ err_rx:  static void fza_tx_smt(struct net_device *dev)  {  	struct fza_private *fp = netdev_priv(dev); -	struct fza_buffer_tx __iomem *smt_tx_ptr, *skb_data_ptr; +	struct fza_buffer_tx __iomem *smt_tx_ptr;  	int i, len;  	u32 own; @@ -799,6 +799,7 @@ static void fza_tx_smt(struct net_device *dev)  		if (!netif_queue_stopped(dev)) {  			if (dev_nit_active(dev)) { +				struct fza_buffer_tx *skb_data_ptr;  				struct sk_buff *skb;  				/* Length must be a multiple of 4 as only word diff --git a/drivers/net/fddi/defza.h b/drivers/net/fddi/defza.h index b06acf32738e..93bda61be8e3 100644 --- a/drivers/net/fddi/defza.h +++ b/drivers/net/fddi/defza.h @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0 */ +/* SPDX-License-Identifier: GPL-2.0+ */  /*	FDDI network adapter driver for DEC FDDIcontroller 700/700-C devices.   *   *	Copyright (c) 2018  Maciej W. Rozycki @@ -235,6 +235,7 @@ struct fza_ring_cmd {  #define FZA_RING_CMD		0x200400	/* command ring address */  #define FZA_RING_CMD_SIZE	0x40		/* command descriptor ring  						 * size +						 */  /* Command constants. */  #define FZA_RING_CMD_MASK	0x7fffffff  #define FZA_RING_CMD_NOP	0x00000000	/* nop */ diff --git a/drivers/net/phy/broadcom.c b/drivers/net/phy/broadcom.c index e86ea105c802..704537010453 100644 --- a/drivers/net/phy/broadcom.c +++ b/drivers/net/phy/broadcom.c @@ -92,7 +92,7 @@ static int bcm54612e_config_init(struct phy_device *phydev)  	return 0;  } -static int bcm5481x_config(struct phy_device *phydev) +static int bcm54xx_config_clock_delay(struct phy_device *phydev)  {  	int rc, val; @@ -429,7 +429,7 @@ static int bcm5481_config_aneg(struct phy_device *phydev)  	ret = genphy_config_aneg(phydev);  	/* Then we can set up the delay. */ -	bcm5481x_config(phydev); +	bcm54xx_config_clock_delay(phydev);  	if (of_property_read_bool(np, "enet-phy-lane-swap")) {  		/* Lane Swap - Undocumented register...magic! */ @@ -442,6 +442,19 @@ static int bcm5481_config_aneg(struct phy_device *phydev)  	return ret;  } +static int bcm54616s_config_aneg(struct phy_device *phydev) +{ +	int ret; + +	/* Aneg firsly. */ +	ret = genphy_config_aneg(phydev); + +	/* Then we can set up the delay. */ +	bcm54xx_config_clock_delay(phydev); + +	return ret; +} +  static int brcm_phy_setbits(struct phy_device *phydev, int reg, int set)  {  	int val; @@ -636,6 +649,7 @@ static struct phy_driver broadcom_drivers[] = {  	.features	= PHY_GBIT_FEATURES,  	.flags		= PHY_HAS_INTERRUPT,  	.config_init	= bcm54xx_config_init, +	.config_aneg	= bcm54616s_config_aneg,  	.ack_interrupt	= bcm_phy_ack_intr,  	.config_intr	= bcm_phy_config_intr,  }, { 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/phy/phy_device.c b/drivers/net/phy/phy_device.c index ab33d1777132..23ee3967c166 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -2197,6 +2197,14 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)  	new_driver->mdiodrv.driver.remove = phy_remove;  	new_driver->mdiodrv.driver.owner = owner; +	/* The following works around an issue where the PHY driver doesn't bind +	 * to the device, resulting in the genphy driver being used instead of +	 * the dedicated driver. The root cause of the issue isn't known yet +	 * and seems to be in the base driver core. Once this is fixed we may +	 * remove this workaround. +	 */ +	new_driver->mdiodrv.driver.probe_type = PROBE_FORCE_SYNCHRONOUS; +  	retval = driver_register(&new_driver->mdiodrv.driver);  	if (retval) {  		pr_err("%s: Error %d in registering driver\n", diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c index 7fc8508b5231..271e8adc39f1 100644 --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c @@ -220,7 +220,7 @@ static struct phy_driver realtek_drvs[] = {  		.flags          = PHY_HAS_INTERRUPT,  	}, {  		.phy_id		= 0x001cc816, -		.name		= "RTL8201F 10/100Mbps Ethernet", +		.name		= "RTL8201F Fast Ethernet",  		.phy_id_mask	= 0x001fffff,  		.features	= PHY_BASIC_FEATURES,  		.flags		= PHY_HAS_INTERRUPT, diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c index e9f101c9bae2..bfbb39f93554 100644 --- a/drivers/net/rionet.c +++ b/drivers/net/rionet.c @@ -216,9 +216,9 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)  			 * it just report sending a packet to the target  			 * (without actual packet transfer).  			 */ -			dev_kfree_skb_any(skb);  			ndev->stats.tx_packets++;  			ndev->stats.tx_bytes += skb->len; +			dev_kfree_skb_any(skb);  		}  	} 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/usb/ipheth.c b/drivers/net/usb/ipheth.c index 7275761a1177..3d8a70d3ea9b 100644 --- a/drivers/net/usb/ipheth.c +++ b/drivers/net/usb/ipheth.c @@ -140,7 +140,6 @@ struct ipheth_device {  	struct usb_device *udev;  	struct usb_interface *intf;  	struct net_device *net; -	struct sk_buff *tx_skb;  	struct urb *tx_urb;  	struct urb *rx_urb;  	unsigned char *tx_buf; @@ -230,6 +229,7 @@ static void ipheth_rcvbulk_callback(struct urb *urb)  	case -ENOENT:  	case -ECONNRESET:  	case -ESHUTDOWN: +	case -EPROTO:  		return;  	case 0:  		break; @@ -281,7 +281,6 @@ static void ipheth_sndbulk_callback(struct urb *urb)  		dev_err(&dev->intf->dev, "%s: urb status: %d\n",  		__func__, status); -	dev_kfree_skb_irq(dev->tx_skb);  	if (status == 0)  		netif_wake_queue(dev->net);  	else @@ -423,7 +422,7 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net)  	if (skb->len > IPHETH_BUF_SIZE) {  		WARN(1, "%s: skb too large: %d bytes\n", __func__, skb->len);  		dev->net->stats.tx_dropped++; -		dev_kfree_skb_irq(skb); +		dev_kfree_skb_any(skb);  		return NETDEV_TX_OK;  	} @@ -443,12 +442,11 @@ static int ipheth_tx(struct sk_buff *skb, struct net_device *net)  		dev_err(&dev->intf->dev, "%s: usb_submit_urb: %d\n",  			__func__, retval);  		dev->net->stats.tx_errors++; -		dev_kfree_skb_irq(skb); +		dev_kfree_skb_any(skb);  	} else { -		dev->tx_skb = skb; -  		dev->net->stats.tx_packets++;  		dev->net->stats.tx_bytes += skb->len; +		dev_consume_skb_any(skb);  		netif_stop_queue(net);  	} diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c index 262e7a3c23cb..f2d01cb6f958 100644 --- a/drivers/net/usb/smsc95xx.c +++ b/drivers/net/usb/smsc95xx.c @@ -1321,6 +1321,8 @@ static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf)  	dev->net->ethtool_ops = &smsc95xx_ethtool_ops;  	dev->net->flags |= IFF_MULTICAST;  	dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD_CSUM; +	dev->net->min_mtu = ETH_MIN_MTU; +	dev->net->max_mtu = ETH_DATA_LEN;  	dev->hard_mtu = dev->net->mtu + dev->net->hard_header_len;  	pdata->dev = dev; @@ -1598,6 +1600,8 @@ static int smsc95xx_suspend(struct usb_interface *intf, pm_message_t message)  		return ret;  	} +	cancel_delayed_work_sync(&pdata->carrier_check); +  	if (pdata->suspend_flags) {  		netdev_warn(dev->net, "error during last resume\n");  		pdata->suspend_flags = 0; @@ -1840,6 +1844,11 @@ done:  	 */  	if (ret && PMSG_IS_AUTO(message))  		usbnet_resume(intf); + +	if (ret) +		schedule_delayed_work(&pdata->carrier_check, +				      CARRIER_CHECK_DELAY); +  	return ret;  } 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/core.c b/drivers/nvme/host/core.c index 2e65be8b1387..3cf1b773158e 100644 --- a/drivers/nvme/host/core.c +++ b/drivers/nvme/host/core.c @@ -1519,8 +1519,10 @@ static void __nvme_revalidate_disk(struct gendisk *disk, struct nvme_id_ns *id)  	if (ns->ndev)  		nvme_nvm_update_nvm_info(ns);  #ifdef CONFIG_NVME_MULTIPATH -	if (ns->head->disk) +	if (ns->head->disk) {  		nvme_update_disk_info(ns->head->disk, ns, id); +		blk_queue_stack_limits(ns->head->disk->queue, ns->queue); +	}  #endif  } @@ -3312,6 +3314,9 @@ void nvme_remove_namespaces(struct nvme_ctrl *ctrl)  	struct nvme_ns *ns, *next;  	LIST_HEAD(ns_list); +	/* prevent racing with ns scanning */ +	flush_work(&ctrl->scan_work); +  	/*  	 * The dead states indicates the controller was not gracefully  	 * disconnected. In that case, we won't be able to flush any data while @@ -3474,7 +3479,6 @@ void nvme_stop_ctrl(struct nvme_ctrl *ctrl)  	nvme_mpath_stop(ctrl);  	nvme_stop_keep_alive(ctrl);  	flush_work(&ctrl->async_event_work); -	flush_work(&ctrl->scan_work);  	cancel_work_sync(&ctrl->fw_act_work);  	if (ctrl->ops->stop_ctrl)  		ctrl->ops->stop_ctrl(ctrl); @@ -3583,7 +3587,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,  	return 0;  out_free_name: -	kfree_const(dev->kobj.name); +	kfree_const(ctrl->device->kobj.name);  out_release_instance:  	ida_simple_remove(&nvme_instance_ida, ctrl->instance);  out: @@ -3605,7 +3609,7 @@ void nvme_kill_queues(struct nvme_ctrl *ctrl)  	down_read(&ctrl->namespaces_rwsem);  	/* Forcibly unquiesce queues to avoid blocking dispatch */ -	if (ctrl->admin_q) +	if (ctrl->admin_q && !blk_queue_dying(ctrl->admin_q))  		blk_mq_unquiesce_queue(ctrl->admin_q);  	list_for_each_entry(ns, &ctrl->namespaces, list) diff --git a/drivers/nvme/host/fc.c b/drivers/nvme/host/fc.c index 0b70c8bab045..feb86b59170e 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);  } @@ -1746,12 +1752,12 @@ nvme_fc_init_request(struct blk_mq_tag_set *set, struct request *rq,  	struct nvme_fc_queue *queue = &ctrl->queues[queue_idx];  	int res; -	nvme_req(rq)->ctrl = &ctrl->ctrl;  	res = __nvme_fc_init_request(ctrl, queue, &op->op, rq, queue->rqcnt++);  	if (res)  		return res;  	op->op.fcp_req.first_sgl = &op->sgl[0];  	op->op.fcp_req.private = &op->priv[0]; +	nvme_req(rq)->ctrl = &ctrl->ctrl;  	return res;  } @@ -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/nvme/host/multipath.c b/drivers/nvme/host/multipath.c index 5e3cc8c59a39..9901afd804ce 100644 --- a/drivers/nvme/host/multipath.c +++ b/drivers/nvme/host/multipath.c @@ -285,6 +285,7 @@ int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl, struct nvme_ns_head *head)  	blk_queue_flag_set(QUEUE_FLAG_NONROT, q);  	/* set to a default value for 512 until disk is validated */  	blk_queue_logical_block_size(q, 512); +	blk_set_stacking_limits(&q->limits);  	/* we need to propagate up the VMC settings */  	if (ctrl->vwc & NVME_CTRL_VWC_PRESENT) diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h index cee79cb388af..081cbdcce880 100644 --- a/drivers/nvme/host/nvme.h +++ b/drivers/nvme/host/nvme.h @@ -531,6 +531,9 @@ static inline void nvme_mpath_check_last_path(struct nvme_ns *ns)  static inline int nvme_mpath_init(struct nvme_ctrl *ctrl,  		struct nvme_id_ctrl *id)  { +	if (ctrl->subsys->cmic & (1 << 3)) +		dev_warn(ctrl->device, +"Please enable CONFIG_NVME_MULTIPATH for full support of multi-port devices.\n");  	return 0;  }  static inline void nvme_mpath_uninit(struct nvme_ctrl *ctrl) diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c index d181cafedc58..ab6ec7295bf9 100644 --- a/drivers/nvme/host/rdma.c +++ b/drivers/nvme/host/rdma.c @@ -184,6 +184,7 @@ static int nvme_rdma_alloc_qe(struct ib_device *ibdev, struct nvme_rdma_qe *qe,  	qe->dma = ib_dma_map_single(ibdev, qe->data, capsule_size, dir);  	if (ib_dma_mapping_error(ibdev, qe->dma)) {  		kfree(qe->data); +		qe->data = NULL;  		return -ENOMEM;  	} @@ -823,6 +824,7 @@ out_free_tagset:  out_free_async_qe:  	nvme_rdma_free_qe(ctrl->device->dev, &ctrl->async_event_sqe,  		sizeof(struct nvme_command), DMA_TO_DEVICE); +	ctrl->async_event_sqe.data = NULL;  out_free_queue:  	nvme_rdma_free_queue(&ctrl->queues[0]);  	return error; diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c index f4efe289dc7b..a5f9bbce863f 100644 --- a/drivers/nvme/target/core.c +++ b/drivers/nvme/target/core.c @@ -420,7 +420,7 @@ static void nvmet_p2pmem_ns_add_p2p(struct nvmet_ctrl *ctrl,  	struct pci_dev *p2p_dev;  	int ret; -	if (!ctrl->p2p_client) +	if (!ctrl->p2p_client || !ns->use_p2pmem)  		return;  	if (ns->p2p_dev) { diff --git a/drivers/nvme/target/rdma.c b/drivers/nvme/target/rdma.c index ddce100be57a..3f7971d3706d 100644 --- a/drivers/nvme/target/rdma.c +++ b/drivers/nvme/target/rdma.c @@ -122,7 +122,6 @@ struct nvmet_rdma_device {  	int			inline_page_count;  }; -static struct workqueue_struct *nvmet_rdma_delete_wq;  static bool nvmet_rdma_use_srq;  module_param_named(use_srq, nvmet_rdma_use_srq, bool, 0444);  MODULE_PARM_DESC(use_srq, "Use shared receive queue."); @@ -1274,12 +1273,12 @@ static int nvmet_rdma_queue_connect(struct rdma_cm_id *cm_id,  	if (queue->host_qid == 0) {  		/* Let inflight controller teardown complete */ -		flush_workqueue(nvmet_rdma_delete_wq); +		flush_scheduled_work();  	}  	ret = nvmet_rdma_cm_accept(cm_id, queue, &event->param.conn);  	if (ret) { -		queue_work(nvmet_rdma_delete_wq, &queue->release_work); +		schedule_work(&queue->release_work);  		/* Destroying rdma_cm id is not needed here */  		return 0;  	} @@ -1344,7 +1343,7 @@ static void __nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue)  	if (disconnect) {  		rdma_disconnect(queue->cm_id); -		queue_work(nvmet_rdma_delete_wq, &queue->release_work); +		schedule_work(&queue->release_work);  	}  } @@ -1374,7 +1373,7 @@ static void nvmet_rdma_queue_connect_fail(struct rdma_cm_id *cm_id,  	mutex_unlock(&nvmet_rdma_queue_mutex);  	pr_err("failed to connect queue %d\n", queue->idx); -	queue_work(nvmet_rdma_delete_wq, &queue->release_work); +	schedule_work(&queue->release_work);  }  /** @@ -1656,17 +1655,8 @@ static int __init nvmet_rdma_init(void)  	if (ret)  		goto err_ib_client; -	nvmet_rdma_delete_wq = alloc_workqueue("nvmet-rdma-delete-wq", -			WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_SYSFS, 0); -	if (!nvmet_rdma_delete_wq) { -		ret = -ENOMEM; -		goto err_unreg_transport; -	} -  	return 0; -err_unreg_transport: -	nvmet_unregister_transport(&nvmet_rdma_ops);  err_ib_client:  	ib_unregister_client(&nvmet_rdma_ib_client);  	return ret; @@ -1674,7 +1664,6 @@ err_ib_client:  static void __exit nvmet_rdma_exit(void)  { -	destroy_workqueue(nvmet_rdma_delete_wq);  	nvmet_unregister_transport(&nvmet_rdma_ops);  	ib_unregister_client(&nvmet_rdma_ib_client);  	WARN_ON_ONCE(!list_empty(&nvmet_rdma_queue_list)); 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/of/device.c b/drivers/of/device.c index 0f27fad9fe94..5592437bb3d1 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -149,9 +149,11 @@ int of_dma_configure(struct device *dev, struct device_node *np, bool force_dma)  	 * set by the driver.  	 */  	mask = DMA_BIT_MASK(ilog2(dma_addr + size - 1) + 1); -	dev->bus_dma_mask = mask;  	dev->coherent_dma_mask &= mask;  	*dev->dma_mask &= mask; +	/* ...but only set bus mask if we found valid dma-ranges earlier */ +	if (!ret) +		dev->bus_dma_mask = mask;  	coherent = of_dma_is_coherent(np);  	dev_dbg(dev, "device is%sdma coherent\n", diff --git a/drivers/of/of_numa.c b/drivers/of/of_numa.c index 35c64a4295e0..fe6b13608e51 100644 --- a/drivers/of/of_numa.c +++ b/drivers/of/of_numa.c @@ -104,9 +104,14 @@ static int __init of_numa_parse_distance_map_v1(struct device_node *map)  		distance = of_read_number(matrix, 1);  		matrix++; +		if ((nodea == nodeb && distance != LOCAL_DISTANCE) || +		    (nodea != nodeb && distance <= LOCAL_DISTANCE)) { +			pr_err("Invalid distance[node%d -> node%d] = %d\n", +			       nodea, nodeb, distance); +			return -EINVAL; +		} +  		numa_set_distance(nodea, nodeb, distance); -		pr_debug("distance[node%d -> node%d] = %d\n", -			 nodea, nodeb, distance);  		/* Set default distance of node B->A same as A->B */  		if (nodeb > nodea) diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 5a4b47958073..38a08805a30c 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c @@ -579,10 +579,8 @@ int dev_pm_opp_of_add_table_indexed(struct device *dev, int index)  		 */  		count = of_count_phandle_with_args(dev->of_node,  						   "operating-points-v2", NULL); -		if (count != 1) -			return -ENODEV; - -		index = 0; +		if (count == 1) +			index = 0;  	}  	opp_table = dev_pm_opp_get_opp_table_indexed(dev, index); diff --git a/drivers/opp/ti-opp-supply.c b/drivers/opp/ti-opp-supply.c index 9e5a9a3112c9..1c69c404df11 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) { @@ -414,7 +417,6 @@ static struct platform_driver ti_opp_supply_driver = {  	.probe = ti_opp_supply_probe,  	.driver = {  		   .name = "ti_opp_supply", -		   .owner = THIS_MODULE,  		   .of_match_table = of_match_ptr(ti_opp_supply_of_match),  		   },  }; diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c index 2cbef2d7c207..88af6bff945f 100644 --- a/drivers/pci/controller/dwc/pci-imx6.c +++ b/drivers/pci/controller/dwc/pci-imx6.c @@ -81,8 +81,6 @@ struct imx6_pcie {  #define PCIE_PL_PFLR_FORCE_LINK			(1 << 15)  #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28)  #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) -#define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING	(1 << 29) -#define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP		(1 << 4)  #define PCIE_PHY_CTRL (PL_OFFSET + 0x114)  #define PCIE_PHY_CTRL_DATA_LOC 0 @@ -711,12 +709,6 @@ static int imx6_pcie_host_init(struct pcie_port *pp)  	return 0;  } -static int imx6_pcie_link_up(struct dw_pcie *pci) -{ -	return dw_pcie_readl_dbi(pci, PCIE_PHY_DEBUG_R1) & -			PCIE_PHY_DEBUG_R1_XMLH_LINK_UP; -} -  static const struct dw_pcie_host_ops imx6_pcie_host_ops = {  	.host_init = imx6_pcie_host_init,  }; @@ -749,7 +741,7 @@ static int imx6_add_pcie_port(struct imx6_pcie *imx6_pcie,  }  static const struct dw_pcie_ops dw_pcie_ops = { -	.link_up = imx6_pcie_link_up, +	/* No special ops needed, but pcie-designware still expects this struct */  };  #ifdef CONFIG_PM_SLEEP diff --git a/drivers/pci/controller/dwc/pci-layerscape.c b/drivers/pci/controller/dwc/pci-layerscape.c index 3724d3ef7008..7aa9a82b7ebd 100644 --- a/drivers/pci/controller/dwc/pci-layerscape.c +++ b/drivers/pci/controller/dwc/pci-layerscape.c @@ -88,7 +88,7 @@ static void ls_pcie_disable_outbound_atus(struct ls_pcie *pcie)  	int i;  	for (i = 0; i < PCIE_IATU_NUM; i++) -		dw_pcie_disable_atu(pcie->pci, DW_PCIE_REGION_OUTBOUND, i); +		dw_pcie_disable_atu(pcie->pci, i, DW_PCIE_REGION_OUTBOUND);  }  static int ls1021_pcie_link_up(struct dw_pcie *pci) diff --git a/drivers/pci/controller/dwc/pcie-designware-ep.c b/drivers/pci/controller/dwc/pcie-designware-ep.c index 1e7b02221eac..de8635af4cde 100644 --- a/drivers/pci/controller/dwc/pcie-designware-ep.c +++ b/drivers/pci/controller/dwc/pcie-designware-ep.c @@ -440,7 +440,6 @@ int dw_pcie_ep_raise_msix_irq(struct dw_pcie_ep *ep, u8 func_no,  	tbl_offset = dw_pcie_readl_dbi(pci, reg);  	bir = (tbl_offset & PCI_MSIX_TABLE_BIR);  	tbl_offset &= PCI_MSIX_TABLE_OFFSET; -	tbl_offset >>= 3;  	reg = PCI_BASE_ADDRESS_0 + (4 * bir);  	bar_addr_upper = 0; diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 2a4aa6468579..921db6f80340 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -793,15 +793,10 @@ static void pci_acpi_setup(struct device *dev)  {  	struct pci_dev *pci_dev = to_pci_dev(dev);  	struct acpi_device *adev = ACPI_COMPANION(dev); -	int node;  	if (!adev)  		return; -	node = acpi_get_node(adev->handle); -	if (node != NUMA_NO_NODE) -		set_dev_node(dev, node); -  	pci_acpi_optimize_delay(pci_dev, adev->handle);  	pci_acpi_add_pm_notifier(adev, pci_dev); diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index d068f11d08a7..c9d8e3c837de 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -5556,9 +5556,13 @@ enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)  	u32 lnkcap2, lnkcap;  	/* -	 * PCIe r4.0 sec 7.5.3.18 recommends using the Supported Link -	 * Speeds Vector in Link Capabilities 2 when supported, falling -	 * back to Max Link Speed in Link Capabilities otherwise. +	 * Link Capabilities 2 was added in PCIe r3.0, sec 7.8.18.  The +	 * implementation note there recommends using the Supported Link +	 * Speeds Vector in Link Capabilities 2 when supported. +	 * +	 * Without Link Capabilities 2, i.e., prior to PCIe r3.0, software +	 * should use the Supported Link Speeds field in Link Capabilities, +	 * where only 2.5 GT/s and 5.0 GT/s speeds were defined.  	 */  	pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2);  	if (lnkcap2) { /* PCIe r3.0-compliant */ @@ -5574,16 +5578,10 @@ enum pci_bus_speed pcie_get_speed_cap(struct pci_dev *dev)  	}  	pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap); -	if (lnkcap) { -		if (lnkcap & PCI_EXP_LNKCAP_SLS_16_0GB) -			return PCIE_SPEED_16_0GT; -		else if (lnkcap & PCI_EXP_LNKCAP_SLS_8_0GB) -			return PCIE_SPEED_8_0GT; -		else if (lnkcap & PCI_EXP_LNKCAP_SLS_5_0GB) -			return PCIE_SPEED_5_0GT; -		else if (lnkcap & PCI_EXP_LNKCAP_SLS_2_5GB) -			return PCIE_SPEED_2_5GT; -	} +	if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_5_0GB) +		return PCIE_SPEED_5_0GT; +	else if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_2_5GB) +		return PCIE_SPEED_2_5GT;  	return PCI_SPEED_UNKNOWN;  } diff --git a/drivers/phy/qualcomm/phy-qcom-qusb2.c b/drivers/phy/qualcomm/phy-qcom-qusb2.c index 9ce531194f8a..6d4b44b569bc 100644 --- a/drivers/phy/qualcomm/phy-qcom-qusb2.c +++ b/drivers/phy/qualcomm/phy-qcom-qusb2.c @@ -231,6 +231,7 @@ static const struct qusb2_phy_cfg sdm845_phy_cfg = {  	.mask_core_ready = CORE_READY_STATUS,  	.has_pll_override = true,  	.autoresume_en	  = BIT(0), +	.update_tune1_with_efuse = true,  };  static const char * const qusb2_phy_vreg_names[] = { @@ -402,10 +403,10 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)  	/*  	 * Read efuse register having TUNE2/1 parameter's high nibble. -	 * If efuse register shows value as 0x0, or if we fail to find -	 * a valid efuse register settings, then use default value -	 * as 0xB for high nibble that we have already set while -	 * configuring phy. +	 * If efuse register shows value as 0x0 (indicating value is not +	 * fused), or if we fail to find a valid efuse register setting, +	 * then use default value for high nibble that we have already +	 * set while configuring the phy.  	 */  	val = nvmem_cell_read(qphy->cell, NULL);  	if (IS_ERR(val) || !val[0]) { @@ -415,12 +416,13 @@ static void qusb2_phy_set_tune2_param(struct qusb2_phy *qphy)  	/* Fused TUNE1/2 value is the higher nibble only */  	if (cfg->update_tune1_with_efuse) -		qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1], -			      val[0] << 0x4); +		qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE1], +				 val[0] << HSTX_TRIM_SHIFT, +				 HSTX_TRIM_MASK);  	else -		qusb2_setbits(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2], -			      val[0] << 0x4); - +		qusb2_write_mask(qphy->base, cfg->regs[QUSB2PHY_PORT_TUNE2], +				 val[0] << HSTX_TRIM_SHIFT, +				 HSTX_TRIM_MASK);  }  static int qusb2_phy_set_mode(struct phy *phy, enum phy_mode mode) diff --git a/drivers/phy/socionext/Kconfig b/drivers/phy/socionext/Kconfig index 467e8147972b..9c85231a6dbc 100644 --- a/drivers/phy/socionext/Kconfig +++ b/drivers/phy/socionext/Kconfig @@ -26,7 +26,8 @@ config PHY_UNIPHIER_USB3  config PHY_UNIPHIER_PCIE  	tristate "Uniphier PHY driver for PCIe controller" -	depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF +	depends on ARCH_UNIPHIER || COMPILE_TEST +	depends on OF && HAS_IOMEM  	default PCIE_UNIPHIER  	select GENERIC_PHY  	help diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c index 4ceb06f8a33c..4edeb4cae72a 100644 --- a/drivers/pinctrl/meson/pinctrl-meson-gxbb.c +++ b/drivers/pinctrl/meson/pinctrl-meson-gxbb.c @@ -830,7 +830,7 @@ static struct meson_bank meson_gxbb_periphs_banks[] = {  static struct meson_bank meson_gxbb_aobus_banks[] = {  	/*   name    first      last       irq    pullen  pull    dir     out     in  */ -	BANK("AO",   GPIOAO_0,  GPIOAO_13, 0, 13, 0,  0,  0, 16,  0,  0,  0, 16,  1,  0), +	BANK("AO",   GPIOAO_0,  GPIOAO_13, 0, 13, 0,  16, 0, 0,   0,  0,  0, 16,  1,  0),  };  static struct meson_pinctrl_data meson_gxbb_periphs_pinctrl_data = { diff --git a/drivers/pinctrl/meson/pinctrl-meson-gxl.c b/drivers/pinctrl/meson/pinctrl-meson-gxl.c index 7dae1d7bf6b0..158f618f1695 100644 --- a/drivers/pinctrl/meson/pinctrl-meson-gxl.c +++ b/drivers/pinctrl/meson/pinctrl-meson-gxl.c @@ -807,7 +807,7 @@ static struct meson_bank meson_gxl_periphs_banks[] = {  static struct meson_bank meson_gxl_aobus_banks[] = {  	/*   name    first      last      irq	pullen  pull    dir     out     in  */ -	BANK("AO",   GPIOAO_0,  GPIOAO_9, 0, 9, 0,  0,  0, 16,  0,  0,  0, 16,  1,  0), +	BANK("AO",   GPIOAO_0,  GPIOAO_9, 0, 9, 0,  16, 0, 0,   0,  0,  0, 16,  1,  0),  };  static struct meson_pinctrl_data meson_gxl_periphs_pinctrl_data = { diff --git a/drivers/pinctrl/meson/pinctrl-meson.c b/drivers/pinctrl/meson/pinctrl-meson.c index f8b778a7d471..53d449076dee 100644 --- a/drivers/pinctrl/meson/pinctrl-meson.c +++ b/drivers/pinctrl/meson/pinctrl-meson.c @@ -192,7 +192,7 @@ static int meson_pinconf_set(struct pinctrl_dev *pcdev, unsigned int pin,  			dev_dbg(pc->dev, "pin %u: disable bias\n", pin);  			meson_calc_reg_and_bit(bank, pin, REG_PULL, ®, &bit); -			ret = regmap_update_bits(pc->reg_pull, reg, +			ret = regmap_update_bits(pc->reg_pullen, reg,  						 BIT(bit), 0);  			if (ret)  				return ret; diff --git a/drivers/pinctrl/meson/pinctrl-meson8.c b/drivers/pinctrl/meson/pinctrl-meson8.c index c6d79315218f..86466173114d 100644 --- a/drivers/pinctrl/meson/pinctrl-meson8.c +++ b/drivers/pinctrl/meson/pinctrl-meson8.c @@ -1053,7 +1053,7 @@ static struct meson_bank meson8_cbus_banks[] = {  static struct meson_bank meson8_aobus_banks[] = {  	/*   name    first     last         irq    pullen  pull    dir     out     in  */ -	BANK("AO",   GPIOAO_0, GPIO_TEST_N, 0, 13, 0,  0,  0, 16,  0,  0,  0, 16,  1,  0), +	BANK("AO",   GPIOAO_0, GPIO_TEST_N, 0, 13, 0, 16,  0,  0,  0,  0,  0, 16,  1,  0),  };  static struct meson_pinctrl_data meson8_cbus_pinctrl_data = { diff --git a/drivers/pinctrl/meson/pinctrl-meson8b.c b/drivers/pinctrl/meson/pinctrl-meson8b.c index bb2a30964fc6..647ad15d5c3c 100644 --- a/drivers/pinctrl/meson/pinctrl-meson8b.c +++ b/drivers/pinctrl/meson/pinctrl-meson8b.c @@ -906,7 +906,7 @@ static struct meson_bank meson8b_cbus_banks[] = {  static struct meson_bank meson8b_aobus_banks[] = {  	/*   name    first     lastc        irq    pullen  pull    dir     out     in  */ -	BANK("AO",   GPIOAO_0, GPIO_TEST_N, 0, 13, 0,  0,  0, 16,  0,  0,  0, 16,  1,  0), +	BANK("AO",   GPIOAO_0, GPIO_TEST_N, 0, 13, 0,  16, 0, 0,  0,  0,  0, 16,  1,  0),  };  static struct meson_pinctrl_data meson8b_cbus_pinctrl_data = { diff --git a/drivers/rtc/hctosys.c b/drivers/rtc/hctosys.c index e79f2a181ad2..b9ec4a16db1f 100644 --- a/drivers/rtc/hctosys.c +++ b/drivers/rtc/hctosys.c @@ -50,8 +50,10 @@ static int __init rtc_hctosys(void)  	tv64.tv_sec = rtc_tm_to_time64(&tm);  #if BITS_PER_LONG == 32 -	if (tv64.tv_sec > INT_MAX) +	if (tv64.tv_sec > INT_MAX) { +		err = -ERANGE;  		goto err_read; +	}  #endif  	err = do_settimeofday64(&tv64); diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index df0c5776d49b..a5a19ff10535 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c @@ -257,6 +257,7 @@ static int cmos_read_alarm(struct device *dev, struct rtc_wkalrm *t)  	struct cmos_rtc	*cmos = dev_get_drvdata(dev);  	unsigned char	rtc_control; +	/* This not only a rtc_op, but also called directly */  	if (!is_valid_irq(cmos->irq))  		return -EIO; @@ -452,6 +453,7 @@ static int cmos_set_alarm(struct device *dev, struct rtc_wkalrm *t)  	unsigned char mon, mday, hrs, min, sec, rtc_control;  	int ret; +	/* This not only a rtc_op, but also called directly */  	if (!is_valid_irq(cmos->irq))  		return -EIO; @@ -516,9 +518,6 @@ static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)  	struct cmos_rtc	*cmos = dev_get_drvdata(dev);  	unsigned long	flags; -	if (!is_valid_irq(cmos->irq)) -		return -EINVAL; -  	spin_lock_irqsave(&rtc_lock, flags);  	if (enabled) @@ -579,6 +578,12 @@ static const struct rtc_class_ops cmos_rtc_ops = {  	.alarm_irq_enable	= cmos_alarm_irq_enable,  }; +static const struct rtc_class_ops cmos_rtc_ops_no_alarm = { +	.read_time		= cmos_read_time, +	.set_time		= cmos_set_time, +	.proc			= cmos_procfs, +}; +  /*----------------------------------------------------------------*/  /* @@ -855,9 +860,12 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq)  			dev_dbg(dev, "IRQ %d is already in use\n", rtc_irq);  			goto cleanup1;  		} + +		cmos_rtc.rtc->ops = &cmos_rtc_ops; +	} else { +		cmos_rtc.rtc->ops = &cmos_rtc_ops_no_alarm;  	} -	cmos_rtc.rtc->ops = &cmos_rtc_ops;  	cmos_rtc.rtc->nvram_old_abi = true;  	retval = rtc_register_device(cmos_rtc.rtc);  	if (retval) diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c index 2751dba850c6..3e1abb455472 100644 --- a/drivers/rtc/rtc-hid-sensor-time.c +++ b/drivers/rtc/rtc-hid-sensor-time.c @@ -213,7 +213,7 @@ static int hid_rtc_read_time(struct device *dev, struct rtc_time *tm)  	/* get a report with all values through requesting one value */  	sensor_hub_input_attr_get_raw_value(time_state->common_attributes.hsdev,  			HID_USAGE_SENSOR_TIME, hid_time_addresses[0], -			time_state->info[0].report_id, SENSOR_HUB_SYNC); +			time_state->info[0].report_id, SENSOR_HUB_SYNC, false);  	/* wait for all values (event) */  	ret = wait_for_completion_killable_timeout(  			&time_state->comp_last_time, HZ*6); diff --git a/drivers/rtc/rtc-pcf2127.c b/drivers/rtc/rtc-pcf2127.c index 9f99a0966550..7cb786d76e3c 100644 --- a/drivers/rtc/rtc-pcf2127.c +++ b/drivers/rtc/rtc-pcf2127.c @@ -303,6 +303,9 @@ static int pcf2127_i2c_gather_write(void *context,  	memcpy(buf + 1, val, val_size);  	ret = i2c_master_send(client, buf, val_size + 1); + +	kfree(buf); +  	if (ret != val_size + 1)  		return ret < 0 ? ret : -EIO; diff --git a/drivers/s390/cio/vfio_ccw_cp.c b/drivers/s390/cio/vfio_ccw_cp.c index fd77e46eb3b2..70a006ba4d05 100644 --- a/drivers/s390/cio/vfio_ccw_cp.c +++ b/drivers/s390/cio/vfio_ccw_cp.c @@ -387,8 +387,10 @@ static int ccwchain_calc_length(u64 iova, struct channel_program *cp)  		 * orb specified one of the unsupported formats, we defer  		 * checking for IDAWs in unsupported formats to here.  		 */ -		if ((!cp->orb.cmd.c64 || cp->orb.cmd.i2k) && ccw_is_idal(ccw)) +		if ((!cp->orb.cmd.c64 || cp->orb.cmd.i2k) && ccw_is_idal(ccw)) { +			kfree(p);  			return -EOPNOTSUPP; +		}  		if ((!ccw_is_chain(ccw)) && (!ccw_is_tic(ccw)))  			break; @@ -528,7 +530,7 @@ static int ccwchain_fetch_direct(struct ccwchain *chain,  	ret = pfn_array_alloc_pin(pat->pat_pa, cp->mdev, ccw->cda, ccw->count);  	if (ret < 0) -		goto out_init; +		goto out_unpin;  	/* Translate this direct ccw to a idal ccw. */  	idaws = kcalloc(ret, sizeof(*idaws), GFP_DMA | GFP_KERNEL); diff --git a/drivers/s390/cio/vfio_ccw_drv.c b/drivers/s390/cio/vfio_ccw_drv.c index f47d16b5810b..a10cec0e86eb 100644 --- a/drivers/s390/cio/vfio_ccw_drv.c +++ b/drivers/s390/cio/vfio_ccw_drv.c @@ -22,7 +22,7 @@  #include "vfio_ccw_private.h"  struct workqueue_struct *vfio_ccw_work_q; -struct kmem_cache *vfio_ccw_io_region; +static struct kmem_cache *vfio_ccw_io_region;  /*   * Helpers @@ -134,14 +134,14 @@ static int vfio_ccw_sch_probe(struct subchannel *sch)  	if (ret)  		goto out_free; -	ret = vfio_ccw_mdev_reg(sch); -	if (ret) -		goto out_disable; -  	INIT_WORK(&private->io_work, vfio_ccw_sch_io_todo);  	atomic_set(&private->avail, 1);  	private->state = VFIO_CCW_STATE_STANDBY; +	ret = vfio_ccw_mdev_reg(sch); +	if (ret) +		goto out_disable; +  	return 0;  out_disable: diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 048665e4f13d..9f5a201c4c87 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -775,6 +775,8 @@ static int ap_device_probe(struct device *dev)  		drvres = ap_drv->flags & AP_DRIVER_FLAG_DEFAULT;  		if (!!devres != !!drvres)  			return -ENODEV; +		/* (re-)init queue's state machine */ +		ap_queue_reinit_state(to_ap_queue(dev));  	}  	/* Add queue/card to list of active queues/cards */ @@ -807,6 +809,8 @@ static int ap_device_remove(struct device *dev)  	struct ap_device *ap_dev = to_ap_dev(dev);  	struct ap_driver *ap_drv = ap_dev->drv; +	if (is_queue_dev(dev)) +		ap_queue_remove(to_ap_queue(dev));  	if (ap_drv->remove)  		ap_drv->remove(ap_dev); @@ -1444,10 +1448,6 @@ static void ap_scan_bus(struct work_struct *unused)  			aq->ap_dev.device.parent = &ac->ap_dev.device;  			dev_set_name(&aq->ap_dev.device,  				     "%02x.%04x", id, dom); -			/* Start with a device reset */ -			spin_lock_bh(&aq->lock); -			ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); -			spin_unlock_bh(&aq->lock);  			/* Register device */  			rc = device_register(&aq->ap_dev.device);  			if (rc) { diff --git a/drivers/s390/crypto/ap_bus.h b/drivers/s390/crypto/ap_bus.h index 3eed1b36c876..bfc66e4a9de1 100644 --- a/drivers/s390/crypto/ap_bus.h +++ b/drivers/s390/crypto/ap_bus.h @@ -254,6 +254,7 @@ struct ap_queue *ap_queue_create(ap_qid_t qid, int device_type);  void ap_queue_remove(struct ap_queue *aq);  void ap_queue_suspend(struct ap_device *ap_dev);  void ap_queue_resume(struct ap_device *ap_dev); +void ap_queue_reinit_state(struct ap_queue *aq);  struct ap_card *ap_card_create(int id, int queue_depth, int raw_device_type,  			       int comp_device_type, unsigned int functions); diff --git a/drivers/s390/crypto/ap_queue.c b/drivers/s390/crypto/ap_queue.c index 66f7334bcb03..0aa4b3ccc948 100644 --- a/drivers/s390/crypto/ap_queue.c +++ b/drivers/s390/crypto/ap_queue.c @@ -718,5 +718,20 @@ void ap_queue_remove(struct ap_queue *aq)  {  	ap_flush_queue(aq);  	del_timer_sync(&aq->timeout); + +	/* reset with zero, also clears irq registration */ +	spin_lock_bh(&aq->lock); +	ap_zapq(aq->qid); +	aq->state = AP_STATE_BORKED; +	spin_unlock_bh(&aq->lock);  }  EXPORT_SYMBOL(ap_queue_remove); + +void ap_queue_reinit_state(struct ap_queue *aq) +{ +	spin_lock_bh(&aq->lock); +	aq->state = AP_STATE_RESET_START; +	ap_wait(ap_sm_event(aq, AP_EVENT_POLL)); +	spin_unlock_bh(&aq->lock); +} +EXPORT_SYMBOL(ap_queue_reinit_state); diff --git a/drivers/s390/crypto/zcrypt_cex2a.c b/drivers/s390/crypto/zcrypt_cex2a.c index 146f54f5cbb8..c50f3e86cc74 100644 --- a/drivers/s390/crypto/zcrypt_cex2a.c +++ b/drivers/s390/crypto/zcrypt_cex2a.c @@ -196,7 +196,6 @@ static void zcrypt_cex2a_queue_remove(struct ap_device *ap_dev)  	struct ap_queue *aq = to_ap_queue(&ap_dev->device);  	struct zcrypt_queue *zq = aq->private; -	ap_queue_remove(aq);  	if (zq)  		zcrypt_queue_unregister(zq);  } diff --git a/drivers/s390/crypto/zcrypt_cex2c.c b/drivers/s390/crypto/zcrypt_cex2c.c index 546f67676734..35c7c6672713 100644 --- a/drivers/s390/crypto/zcrypt_cex2c.c +++ b/drivers/s390/crypto/zcrypt_cex2c.c @@ -251,7 +251,6 @@ static void zcrypt_cex2c_queue_remove(struct ap_device *ap_dev)  	struct ap_queue *aq = to_ap_queue(&ap_dev->device);  	struct zcrypt_queue *zq = aq->private; -	ap_queue_remove(aq);  	if (zq)  		zcrypt_queue_unregister(zq);  } diff --git a/drivers/s390/crypto/zcrypt_cex4.c b/drivers/s390/crypto/zcrypt_cex4.c index f9d4c6c7521d..582ffa7e0f18 100644 --- a/drivers/s390/crypto/zcrypt_cex4.c +++ b/drivers/s390/crypto/zcrypt_cex4.c @@ -275,7 +275,6 @@ static void zcrypt_cex4_queue_remove(struct ap_device *ap_dev)  	struct ap_queue *aq = to_ap_queue(&ap_dev->device);  	struct zcrypt_queue *zq = aq->private; -	ap_queue_remove(aq);  	if (zq)  		zcrypt_queue_unregister(zq);  } 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/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 6843bc7ee9f2..04e294d1d16d 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -87,6 +87,18 @@ struct qeth_dbf_info {  #define SENSE_RESETTING_EVENT_BYTE 1  #define SENSE_RESETTING_EVENT_FLAG 0x80 +static inline u32 qeth_get_device_id(struct ccw_device *cdev) +{ +	struct ccw_dev_id dev_id; +	u32 id; + +	ccw_device_get_id(cdev, &dev_id); +	id = dev_id.devno; +	id |= (u32) (dev_id.ssid << 16); + +	return id; +} +  /*   * Common IO related definitions   */ @@ -97,7 +109,8 @@ struct qeth_dbf_info {  #define CARD_RDEV_ID(card) dev_name(&card->read.ccwdev->dev)  #define CARD_WDEV_ID(card) dev_name(&card->write.ccwdev->dev)  #define CARD_DDEV_ID(card) dev_name(&card->data.ccwdev->dev) -#define CHANNEL_ID(channel) dev_name(&channel->ccwdev->dev) +#define CCW_DEVID(cdev)		(qeth_get_device_id(cdev)) +#define CARD_DEVID(card)	(CCW_DEVID(CARD_RDEV(card)))  /**   * card stuff @@ -830,6 +843,11 @@ struct qeth_trap_id {  /*some helper functions*/  #define QETH_CARD_IFNAME(card) (((card)->dev)? (card)->dev->name : "") +static inline bool qeth_netdev_is_registered(struct net_device *dev) +{ +	return dev->netdev_ops != NULL; +} +  static inline void qeth_scrub_qdio_buffer(struct qdio_buffer *buf,  					  unsigned int elements)  { @@ -973,7 +991,7 @@ int qeth_wait_for_threads(struct qeth_card *, unsigned long);  int qeth_do_run_thread(struct qeth_card *, unsigned long);  void qeth_clear_thread_start_bit(struct qeth_card *, unsigned long);  void qeth_clear_thread_running_bit(struct qeth_card *, unsigned long); -int qeth_core_hardsetup_card(struct qeth_card *); +int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok);  void qeth_print_status_message(struct qeth_card *);  int qeth_init_qdio_queues(struct qeth_card *);  int qeth_send_ipa_cmd(struct qeth_card *, struct qeth_cmd_buffer *, @@ -1028,11 +1046,6 @@ int qeth_configure_cq(struct qeth_card *, enum qeth_cq);  int qeth_hw_trap(struct qeth_card *, enum qeth_diags_trap_action);  void qeth_trace_features(struct qeth_card *);  void qeth_close_dev(struct qeth_card *); -int qeth_send_setassparms(struct qeth_card *, struct qeth_cmd_buffer *, __u16, -			  long, -			  int (*reply_cb)(struct qeth_card *, -					  struct qeth_reply *, unsigned long), -			  void *);  int qeth_setassparms_cb(struct qeth_card *, struct qeth_reply *, unsigned long);  struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *,  						 enum qeth_ipa_funcs, diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3274f13aad57..254065271867 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -167,6 +167,8 @@ const char *qeth_get_cardname_short(struct qeth_card *card)  				return "OSD_1000";  			case QETH_LINK_TYPE_10GBIT_ETH:  				return "OSD_10GIG"; +			case QETH_LINK_TYPE_25GBIT_ETH: +				return "OSD_25GIG";  			case QETH_LINK_TYPE_LANE_ETH100:  				return "OSD_FE_LANE";  			case QETH_LINK_TYPE_LANE_TR: @@ -554,8 +556,8 @@ static int __qeth_issue_next_read(struct qeth_card *card)  	if (!iob) {  		dev_warn(&card->gdev->dev, "The qeth device driver "  			"failed to recover an error on the device\n"); -		QETH_DBF_MESSAGE(2, "%s issue_next_read failed: no iob " -			"available\n", dev_name(&card->gdev->dev)); +		QETH_DBF_MESSAGE(2, "issue_next_read on device %x failed: no iob available\n", +				 CARD_DEVID(card));  		return -ENOMEM;  	}  	qeth_setup_ccw(channel->ccw, CCW_CMD_READ, QETH_BUFSIZE, iob->data); @@ -563,8 +565,8 @@ static int __qeth_issue_next_read(struct qeth_card *card)  	rc = ccw_device_start(channel->ccwdev, channel->ccw,  			      (addr_t) iob, 0, 0);  	if (rc) { -		QETH_DBF_MESSAGE(2, "%s error in starting next read ccw! " -			"rc=%i\n", dev_name(&card->gdev->dev), rc); +		QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n", +				 rc, CARD_DEVID(card));  		atomic_set(&channel->irq_pending, 0);  		card->read_or_write_problem = 1;  		qeth_schedule_recovery(card); @@ -613,16 +615,14 @@ static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc,  	const char *ipa_name;  	int com = cmd->hdr.command;  	ipa_name = qeth_get_ipa_cmd_name(com); +  	if (rc) -		QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s/%s returned " -				"x%X \"%s\"\n", -				ipa_name, com, dev_name(&card->gdev->dev), -				QETH_CARD_IFNAME(card), rc, -				qeth_get_ipa_msg(rc)); +		QETH_DBF_MESSAGE(2, "IPA: %s(%#x) for device %x returned %#x \"%s\"\n", +				 ipa_name, com, CARD_DEVID(card), rc, +				 qeth_get_ipa_msg(rc));  	else -		QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s/%s succeeded\n", -				ipa_name, com, dev_name(&card->gdev->dev), -				QETH_CARD_IFNAME(card)); +		QETH_DBF_MESSAGE(5, "IPA: %s(%#x) for device %x succeeded\n", +				 ipa_name, com, CARD_DEVID(card));  }  static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card, @@ -711,7 +711,7 @@ static int qeth_check_idx_response(struct qeth_card *card,  	QETH_DBF_HEX(CTRL, 2, buffer, QETH_DBF_CTRL_LEN);  	if ((buffer[2] & 0xc0) == 0xc0) { -		QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#02x\n", +		QETH_DBF_MESSAGE(2, "received an IDX TERMINATE with cause code %#04x\n",  				 buffer[4]);  		QETH_CARD_TEXT(card, 2, "ckidxres");  		QETH_CARD_TEXT(card, 2, " idxterm"); @@ -972,8 +972,8 @@ static int qeth_get_problem(struct qeth_card *card, struct ccw_device *cdev,  		QETH_CARD_TEXT(card, 2, "CGENCHK");  		dev_warn(&cdev->dev, "The qeth device driver "  			"failed to recover an error on the device\n"); -		QETH_DBF_MESSAGE(2, "%s check on device dstat=x%x, cstat=x%x\n", -			dev_name(&cdev->dev), dstat, cstat); +		QETH_DBF_MESSAGE(2, "check on channel %x with dstat=%#x, cstat=%#x\n", +				 CCW_DEVID(cdev), dstat, cstat);  		print_hex_dump(KERN_WARNING, "qeth: irb ", DUMP_PREFIX_OFFSET,  				16, 1, irb, 64, 1);  		return 1; @@ -1013,8 +1013,8 @@ static long qeth_check_irb_error(struct qeth_card *card,  	switch (PTR_ERR(irb)) {  	case -EIO: -		QETH_DBF_MESSAGE(2, "%s i/o-error on device\n", -			dev_name(&cdev->dev)); +		QETH_DBF_MESSAGE(2, "i/o-error on channel %x\n", +				 CCW_DEVID(cdev));  		QETH_CARD_TEXT(card, 2, "ckirberr");  		QETH_CARD_TEXT_(card, 2, "  rc%d", -EIO);  		break; @@ -1031,8 +1031,8 @@ static long qeth_check_irb_error(struct qeth_card *card,  		}  		break;  	default: -		QETH_DBF_MESSAGE(2, "%s unknown error %ld on device\n", -			dev_name(&cdev->dev), PTR_ERR(irb)); +		QETH_DBF_MESSAGE(2, "unknown error %ld on channel %x\n", +				 PTR_ERR(irb), CCW_DEVID(cdev));  		QETH_CARD_TEXT(card, 2, "ckirberr");  		QETH_CARD_TEXT(card, 2, "  rc???");  	} @@ -1114,9 +1114,9 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,  			dev_warn(&channel->ccwdev->dev,  				"The qeth device driver failed to recover "  				"an error on the device\n"); -			QETH_DBF_MESSAGE(2, "%s sense data available. cstat " -				"0x%X dstat 0x%X\n", -				dev_name(&channel->ccwdev->dev), cstat, dstat); +			QETH_DBF_MESSAGE(2, "sense data available on channel %x: cstat %#X dstat %#X\n", +					 CCW_DEVID(channel->ccwdev), cstat, +					 dstat);  			print_hex_dump(KERN_WARNING, "qeth: irb ",  				DUMP_PREFIX_OFFSET, 16, 1, irb, 32, 1);  			print_hex_dump(KERN_WARNING, "qeth: sense data ", @@ -1890,8 +1890,8 @@ static int qeth_idx_activate_channel(struct qeth_card *card,  	if (channel->state != CH_STATE_ACTIVATING) {  		dev_warn(&channel->ccwdev->dev, "The qeth device driver"  			" failed to recover an error on the device\n"); -		QETH_DBF_MESSAGE(2, "%s IDX activate timed out\n", -			dev_name(&channel->ccwdev->dev)); +		QETH_DBF_MESSAGE(2, "IDX activate timed out on channel %x\n", +				 CCW_DEVID(channel->ccwdev));  		QETH_DBF_TEXT_(SETUP, 2, "2err%d", -ETIME);  		return -ETIME;  	} @@ -1926,17 +1926,15 @@ static void qeth_idx_write_cb(struct qeth_card *card,  				"The adapter is used exclusively by another "  				"host\n");  		else -			QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on write channel:" -				" negative reply\n", -				dev_name(&channel->ccwdev->dev)); +			QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: negative reply\n", +					 CCW_DEVID(channel->ccwdev));  		goto out;  	}  	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);  	if ((temp & ~0x0100) != qeth_peer_func_level(card->info.func_level)) { -		QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on write channel: " -			"function level mismatch (sent: 0x%x, received: " -			"0x%x)\n", dev_name(&channel->ccwdev->dev), -			card->info.func_level, temp); +		QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: function level mismatch (sent: %#x, received: %#x)\n", +				 CCW_DEVID(channel->ccwdev), +				 card->info.func_level, temp);  		goto out;  	}  	channel->state = CH_STATE_UP; @@ -1973,9 +1971,8 @@ static void qeth_idx_read_cb(struct qeth_card *card,  				"insufficient authorization\n");  			break;  		default: -			QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel:" -				" negative reply\n", -				dev_name(&channel->ccwdev->dev)); +			QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: negative reply\n", +					 CCW_DEVID(channel->ccwdev));  		}  		QETH_CARD_TEXT_(card, 2, "idxread%c",  			QETH_IDX_ACT_CAUSE_CODE(iob->data)); @@ -1984,10 +1981,9 @@ static void qeth_idx_read_cb(struct qeth_card *card,  	memcpy(&temp, QETH_IDX_ACT_FUNC_LEVEL(iob->data), 2);  	if (temp != qeth_peer_func_level(card->info.func_level)) { -		QETH_DBF_MESSAGE(2, "%s IDX_ACTIVATE on read channel: function " -			"level mismatch (sent: 0x%x, received: 0x%x)\n", -			dev_name(&channel->ccwdev->dev), -			card->info.func_level, temp); +		QETH_DBF_MESSAGE(2, "IDX_ACTIVATE on channel %x: function level mismatch (sent: %#x, received: %#x)\n", +				 CCW_DEVID(channel->ccwdev), +				 card->info.func_level, temp);  		goto out;  	}  	memcpy(&card->token.issuer_rm_r, @@ -2096,9 +2092,8 @@ int qeth_send_control_data(struct qeth_card *card, int len,  				      (addr_t) iob, 0, 0, event_timeout);  	spin_unlock_irq(get_ccwdev_lock(channel->ccwdev));  	if (rc) { -		QETH_DBF_MESSAGE(2, "%s qeth_send_control_data: " -			"ccw_device_start rc = %i\n", -			dev_name(&channel->ccwdev->dev), rc); +		QETH_DBF_MESSAGE(2, "qeth_send_control_data on device %x: ccw_device_start rc = %i\n", +				 CARD_DEVID(card), rc);  		QETH_CARD_TEXT_(card, 2, " err%d", rc);  		spin_lock_irq(&card->lock);  		list_del_init(&reply->list); @@ -2853,8 +2848,8 @@ struct qeth_cmd_buffer *qeth_get_ipacmd_buffer(struct qeth_card *card,  	} else {  		dev_warn(&card->gdev->dev,  			 "The qeth driver ran out of channel command buffers\n"); -		QETH_DBF_MESSAGE(1, "%s The qeth driver ran out of channel command buffers", -				 dev_name(&card->gdev->dev)); +		QETH_DBF_MESSAGE(1, "device %x ran out of channel command buffers", +				 CARD_DEVID(card));  	}  	return iob; @@ -2989,10 +2984,9 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,  		return 0;  	default:  		if (cmd->hdr.return_code) { -			QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Unhandled " -						"rc=%d\n", -						dev_name(&card->gdev->dev), -						cmd->hdr.return_code); +			QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Unhandled rc=%#x\n", +					 CARD_DEVID(card), +					 cmd->hdr.return_code);  			return 0;  		}  	} @@ -3004,8 +2998,8 @@ static int qeth_query_ipassists_cb(struct qeth_card *card,  		card->options.ipa6.supported_funcs = cmd->hdr.ipa_supported;  		card->options.ipa6.enabled_funcs = cmd->hdr.ipa_enabled;  	} else -		QETH_DBF_MESSAGE(1, "%s IPA_CMD_QIPASSIST: Flawed LIC detected" -					"\n", dev_name(&card->gdev->dev)); +		QETH_DBF_MESSAGE(1, "IPA_CMD_QIPASSIST on device %x: Flawed LIC detected\n", +				 CARD_DEVID(card));  	return 0;  } @@ -4297,10 +4291,9 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,  		cmd->data.setadapterparms.hdr.return_code);  	if (cmd->data.setadapterparms.hdr.return_code !=  						SET_ACCESS_CTRL_RC_SUCCESS) -		QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%s,%d)==%d\n", -				card->gdev->dev.kobj.name, -				access_ctrl_req->subcmd_code, -				cmd->data.setadapterparms.hdr.return_code); +		QETH_DBF_MESSAGE(3, "ERR:SET_ACCESS_CTRL(%#x) on device %x: %#x\n", +				 access_ctrl_req->subcmd_code, CARD_DEVID(card), +				 cmd->data.setadapterparms.hdr.return_code);  	switch (cmd->data.setadapterparms.hdr.return_code) {  	case SET_ACCESS_CTRL_RC_SUCCESS:  		if (card->options.isolation == ISOLATION_MODE_NONE) { @@ -4312,14 +4305,14 @@ static int qeth_setadpparms_set_access_ctrl_cb(struct qeth_card *card,  		}  		break;  	case SET_ACCESS_CTRL_RC_ALREADY_NOT_ISOLATED: -		QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already " -				"deactivated\n", dev_name(&card->gdev->dev)); +		QETH_DBF_MESSAGE(2, "QDIO data connection isolation on device %x already deactivated\n", +				 CARD_DEVID(card));  		if (fallback)  			card->options.isolation = card->options.prev_isolation;  		break;  	case SET_ACCESS_CTRL_RC_ALREADY_ISOLATED: -		QETH_DBF_MESSAGE(2, "%s QDIO data connection isolation already" -				" activated\n", dev_name(&card->gdev->dev)); +		QETH_DBF_MESSAGE(2, "QDIO data connection isolation on device %x already activated\n", +				 CARD_DEVID(card));  		if (fallback)  			card->options.isolation = card->options.prev_isolation;  		break; @@ -4405,10 +4398,8 @@ int qeth_set_access_ctrl_online(struct qeth_card *card, int fallback)  		rc = qeth_setadpparms_set_access_ctrl(card,  			card->options.isolation, fallback);  		if (rc) { -			QETH_DBF_MESSAGE(3, -				"IPA(SET_ACCESS_CTRL,%s,%d) sent failed\n", -				card->gdev->dev.kobj.name, -				rc); +			QETH_DBF_MESSAGE(3, "IPA(SET_ACCESS_CTRL(%d) on device %x: sent failed\n", +					 rc, CARD_DEVID(card));  			rc = -EOPNOTSUPP;  		}  	} else if (card->options.isolation != ISOLATION_MODE_NONE) { @@ -4443,7 +4434,8 @@ static int qeth_mdio_read(struct net_device *dev, int phy_id, int regnum)  		rc = BMCR_FULLDPLX;  		if ((card->info.link_type != QETH_LINK_TYPE_GBIT_ETH) &&  		    (card->info.link_type != QETH_LINK_TYPE_OSN) && -		    (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH)) +		    (card->info.link_type != QETH_LINK_TYPE_10GBIT_ETH) && +		    (card->info.link_type != QETH_LINK_TYPE_25GBIT_ETH))  			rc |= BMCR_SPEED100;  		break;  	case MII_BMSR: /* Basic mode status register */ @@ -4526,8 +4518,8 @@ static int qeth_snmp_command_cb(struct qeth_card *card,  {  	struct qeth_ipa_cmd *cmd;  	struct qeth_arp_query_info *qinfo; -	struct qeth_snmp_cmd *snmp;  	unsigned char *data; +	void *snmp_data;  	__u16 data_len;  	QETH_CARD_TEXT(card, 3, "snpcmdcb"); @@ -4535,7 +4527,6 @@ static int qeth_snmp_command_cb(struct qeth_card *card,  	cmd = (struct qeth_ipa_cmd *) sdata;  	data = (unsigned char *)((char *)cmd - reply->offset);  	qinfo = (struct qeth_arp_query_info *) reply->param; -	snmp = &cmd->data.setadapterparms.data.snmp;  	if (cmd->hdr.return_code) {  		QETH_CARD_TEXT_(card, 4, "scer1%x", cmd->hdr.return_code); @@ -4548,10 +4539,15 @@ static int qeth_snmp_command_cb(struct qeth_card *card,  		return 0;  	}  	data_len = *((__u16 *)QETH_IPA_PDU_LEN_PDU1(data)); -	if (cmd->data.setadapterparms.hdr.seq_no == 1) -		data_len -= (__u16)((char *)&snmp->data - (char *)cmd); -	else -		data_len -= (__u16)((char *)&snmp->request - (char *)cmd); +	if (cmd->data.setadapterparms.hdr.seq_no == 1) { +		snmp_data = &cmd->data.setadapterparms.data.snmp; +		data_len -= offsetof(struct qeth_ipa_cmd, +				     data.setadapterparms.data.snmp); +	} else { +		snmp_data = &cmd->data.setadapterparms.data.snmp.request; +		data_len -= offsetof(struct qeth_ipa_cmd, +				     data.setadapterparms.data.snmp.request); +	}  	/* check if there is enough room in userspace */  	if ((qinfo->udata_len - qinfo->udata_offset) < data_len) { @@ -4564,16 +4560,9 @@ static int qeth_snmp_command_cb(struct qeth_card *card,  	QETH_CARD_TEXT_(card, 4, "sseqn%i",  		cmd->data.setadapterparms.hdr.seq_no);  	/*copy entries to user buffer*/ -	if (cmd->data.setadapterparms.hdr.seq_no == 1) { -		memcpy(qinfo->udata + qinfo->udata_offset, -		       (char *)snmp, -		       data_len + offsetof(struct qeth_snmp_cmd, data)); -		qinfo->udata_offset += offsetof(struct qeth_snmp_cmd, data); -	} else { -		memcpy(qinfo->udata + qinfo->udata_offset, -		       (char *)&snmp->request, data_len); -	} +	memcpy(qinfo->udata + qinfo->udata_offset, snmp_data, data_len);  	qinfo->udata_offset += data_len; +  	/* check if all replies received ... */  		QETH_CARD_TEXT_(card, 4, "srtot%i",  			       cmd->data.setadapterparms.hdr.used_total); @@ -4634,8 +4623,8 @@ static int qeth_snmp_command(struct qeth_card *card, char __user *udata)  	rc = qeth_send_ipa_snmp_cmd(card, iob, QETH_SETADP_BASE_LEN + req_len,  				    qeth_snmp_command_cb, (void *)&qinfo);  	if (rc) -		QETH_DBF_MESSAGE(2, "SNMP command failed on %s: (0x%x)\n", -			   QETH_CARD_IFNAME(card), rc); +		QETH_DBF_MESSAGE(2, "SNMP command failed on device %x: (%#x)\n", +				 CARD_DEVID(card), rc);  	else {  		if (copy_to_user(udata, qinfo.udata, qinfo.udata_len))  			rc = -EFAULT; @@ -4869,8 +4858,8 @@ static void qeth_determine_capabilities(struct qeth_card *card)  	rc = qeth_read_conf_data(card, (void **) &prcd, &length);  	if (rc) { -		QETH_DBF_MESSAGE(2, "%s qeth_read_conf_data returned %i\n", -			dev_name(&card->gdev->dev), rc); +		QETH_DBF_MESSAGE(2, "qeth_read_conf_data on device %x returned %i\n", +				 CARD_DEVID(card), rc);  		QETH_DBF_TEXT_(SETUP, 2, "5err%d", rc);  		goto out_offline;  	} @@ -5086,7 +5075,7 @@ static struct ccw_driver qeth_ccw_driver = {  	.remove = ccwgroup_remove_ccwdev,  }; -int qeth_core_hardsetup_card(struct qeth_card *card) +int qeth_core_hardsetup_card(struct qeth_card *card, bool *carrier_ok)  {  	int retries = 3;  	int rc; @@ -5096,8 +5085,8 @@ int qeth_core_hardsetup_card(struct qeth_card *card)  	qeth_update_from_chp_desc(card);  retry:  	if (retries < 3) -		QETH_DBF_MESSAGE(2, "%s Retrying to do IDX activates.\n", -			dev_name(&card->gdev->dev)); +		QETH_DBF_MESSAGE(2, "Retrying to do IDX activates on device %x.\n", +				 CARD_DEVID(card));  	rc = qeth_qdio_clear_card(card, card->info.type != QETH_CARD_TYPE_IQD);  	ccw_device_set_offline(CARD_DDEV(card));  	ccw_device_set_offline(CARD_WDEV(card)); @@ -5161,13 +5150,20 @@ retriable:  		if (rc == IPA_RC_LAN_OFFLINE) {  			dev_warn(&card->gdev->dev,  				"The LAN is offline\n"); -			netif_carrier_off(card->dev); +			*carrier_ok = false;  		} else {  			rc = -ENODEV;  			goto out;  		}  	} else { -		netif_carrier_on(card->dev); +		*carrier_ok = true; +	} + +	if (qeth_netdev_is_registered(card->dev)) { +		if (*carrier_ok) +			netif_carrier_on(card->dev); +		else +			netif_carrier_off(card->dev);  	}  	card->options.ipa4.supported_funcs = 0; @@ -5201,8 +5197,8 @@ retriable:  out:  	dev_warn(&card->gdev->dev, "The qeth device driver failed to recover "  		"an error on the device\n"); -	QETH_DBF_MESSAGE(2, "%s Initialization in hardsetup failed! rc=%d\n", -		dev_name(&card->gdev->dev), rc); +	QETH_DBF_MESSAGE(2, "Initialization for device %x failed in hardsetup! rc=%d\n", +			 CARD_DEVID(card), rc);  	return rc;  }  EXPORT_SYMBOL_GPL(qeth_core_hardsetup_card); @@ -5481,11 +5477,12 @@ struct qeth_cmd_buffer *qeth_get_setassparms_cmd(struct qeth_card *card,  }  EXPORT_SYMBOL_GPL(qeth_get_setassparms_cmd); -int qeth_send_setassparms(struct qeth_card *card, -			  struct qeth_cmd_buffer *iob, __u16 len, long data, -			  int (*reply_cb)(struct qeth_card *, -					  struct qeth_reply *, unsigned long), -			  void *reply_param) +static int qeth_send_setassparms(struct qeth_card *card, +				 struct qeth_cmd_buffer *iob, u16 len, +				 long data, int (*reply_cb)(struct qeth_card *, +							    struct qeth_reply *, +							    unsigned long), +				 void *reply_param)  {  	int rc;  	struct qeth_ipa_cmd *cmd; @@ -5501,7 +5498,6 @@ int qeth_send_setassparms(struct qeth_card *card,  	rc = qeth_send_ipa_cmd(card, iob, reply_cb, reply_param);  	return rc;  } -EXPORT_SYMBOL_GPL(qeth_send_setassparms);  int qeth_send_simple_setassparms_prot(struct qeth_card *card,  				      enum qeth_ipa_funcs ipa_func, @@ -6170,8 +6166,14 @@ static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,  		WARN_ON_ONCE(1);  	} -	/* fallthrough from high to low, to select all legal speeds: */ +	/* partially does fall through, to also select lower speeds */  	switch (maxspeed) { +	case SPEED_25000: +		ethtool_link_ksettings_add_link_mode(cmd, supported, +						     25000baseSR_Full); +		ethtool_link_ksettings_add_link_mode(cmd, advertising, +						     25000baseSR_Full); +		break;  	case SPEED_10000:  		ethtool_link_ksettings_add_link_mode(cmd, supported,  						     10000baseT_Full); @@ -6254,6 +6256,10 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,  		cmd->base.speed = SPEED_10000;  		cmd->base.port = PORT_FIBRE;  		break; +	case QETH_LINK_TYPE_25GBIT_ETH: +		cmd->base.speed = SPEED_25000; +		cmd->base.port = PORT_FIBRE; +		break;  	default:  		cmd->base.speed = SPEED_10;  		cmd->base.port = PORT_TP; @@ -6320,6 +6326,9 @@ int qeth_core_ethtool_get_link_ksettings(struct net_device *netdev,  	case CARD_INFO_PORTS_10G:  		cmd->base.speed = SPEED_10000;  		break; +	case CARD_INFO_PORTS_25G: +		cmd->base.speed = SPEED_25000; +		break;  	}  	return 0; diff --git a/drivers/s390/net/qeth_core_mpc.h b/drivers/s390/net/qeth_core_mpc.h index e85090467afe..3e54be201b27 100644 --- a/drivers/s390/net/qeth_core_mpc.h +++ b/drivers/s390/net/qeth_core_mpc.h @@ -90,6 +90,7 @@ enum qeth_link_types {  	QETH_LINK_TYPE_GBIT_ETH     = 0x03,  	QETH_LINK_TYPE_OSN          = 0x04,  	QETH_LINK_TYPE_10GBIT_ETH   = 0x10, +	QETH_LINK_TYPE_25GBIT_ETH   = 0x12,  	QETH_LINK_TYPE_LANE_ETH100  = 0x81,  	QETH_LINK_TYPE_LANE_TR      = 0x82,  	QETH_LINK_TYPE_LANE_ETH1000 = 0x83, @@ -347,6 +348,7 @@ enum qeth_card_info_port_speed {  	CARD_INFO_PORTS_100M		= 0x00000006,  	CARD_INFO_PORTS_1G		= 0x00000007,  	CARD_INFO_PORTS_10G		= 0x00000008, +	CARD_INFO_PORTS_25G		= 0x0000000A,  };  /* (SET)DELIP(M) IPA stuff ***************************************************/ @@ -436,7 +438,7 @@ struct qeth_ipacmd_setassparms {  		__u32 flags_32bit;  		struct qeth_ipa_caps caps;  		struct qeth_checksum_cmd chksum; -		struct qeth_arp_cache_entry add_arp_entry; +		struct qeth_arp_cache_entry arp_entry;  		struct qeth_arp_query_data query_arp;  		struct qeth_tso_start_data tso;  		__u8 ip[16]; diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 23aaf373f631..2914a1a69f83 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -146,11 +146,11 @@ static int qeth_l2_write_mac(struct qeth_card *card, u8 *mac)  	QETH_CARD_TEXT(card, 2, "L2Wmac");  	rc = qeth_l2_send_setdelmac(card, mac, cmd);  	if (rc == -EEXIST) -		QETH_DBF_MESSAGE(2, "MAC %pM already registered on %s\n", -				 mac, QETH_CARD_IFNAME(card)); +		QETH_DBF_MESSAGE(2, "MAC already registered on device %x\n", +				 CARD_DEVID(card));  	else if (rc) -		QETH_DBF_MESSAGE(2, "Failed to register MAC %pM on %s: %d\n", -				 mac, QETH_CARD_IFNAME(card), rc); +		QETH_DBF_MESSAGE(2, "Failed to register MAC on device %x: %d\n", +				 CARD_DEVID(card), rc);  	return rc;  } @@ -163,8 +163,8 @@ static int qeth_l2_remove_mac(struct qeth_card *card, u8 *mac)  	QETH_CARD_TEXT(card, 2, "L2Rmac");  	rc = qeth_l2_send_setdelmac(card, mac, cmd);  	if (rc) -		QETH_DBF_MESSAGE(2, "Failed to delete MAC %pM on %s: %d\n", -				 mac, QETH_CARD_IFNAME(card), rc); +		QETH_DBF_MESSAGE(2, "Failed to delete MAC on device %u: %d\n", +				 CARD_DEVID(card), rc);  	return rc;  } @@ -260,9 +260,9 @@ static int qeth_l2_send_setdelvlan_cb(struct qeth_card *card,  	QETH_CARD_TEXT(card, 2, "L2sdvcb");  	if (cmd->hdr.return_code) { -		QETH_DBF_MESSAGE(2, "Error in processing VLAN %i on %s: 0x%x.\n", +		QETH_DBF_MESSAGE(2, "Error in processing VLAN %u on device %x: %#x.\n",  				 cmd->data.setdelvlan.vlan_id, -				 QETH_CARD_IFNAME(card), cmd->hdr.return_code); +				 CARD_DEVID(card), cmd->hdr.return_code);  		QETH_CARD_TEXT_(card, 2, "L2VL%4x", cmd->hdr.command);  		QETH_CARD_TEXT_(card, 2, "err%d", cmd->hdr.return_code);  	} @@ -455,8 +455,8 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)  		rc = qeth_vm_request_mac(card);  		if (!rc)  			goto out; -		QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %s: x%x\n", -				 CARD_BUS_ID(card), rc); +		QETH_DBF_MESSAGE(2, "z/VM MAC Service failed on device %x: %#x\n", +				 CARD_DEVID(card), rc);  		QETH_DBF_TEXT_(SETUP, 2, "err%04x", rc);  		/* fall back to alternative mechanism: */  	} @@ -468,8 +468,8 @@ static int qeth_l2_request_initial_mac(struct qeth_card *card)  		rc = qeth_setadpparms_change_macaddr(card);  		if (!rc)  			goto out; -		QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %s: x%x\n", -				 CARD_BUS_ID(card), rc); +		QETH_DBF_MESSAGE(2, "READ_MAC Assist failed on device %x: %#x\n", +				 CARD_DEVID(card), rc);  		QETH_DBF_TEXT_(SETUP, 2, "1err%04x", rc);  		/* fall back once more: */  	} @@ -826,7 +826,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)  	if (cgdev->state == CCWGROUP_ONLINE)  		qeth_l2_set_offline(cgdev); -	unregister_netdev(card->dev); +	if (qeth_netdev_is_registered(card->dev)) +		unregister_netdev(card->dev);  }  static const struct ethtool_ops qeth_l2_ethtool_ops = { @@ -862,11 +863,11 @@ static const struct net_device_ops qeth_l2_netdev_ops = {  	.ndo_set_features	= qeth_set_features  }; -static int qeth_l2_setup_netdev(struct qeth_card *card) +static int qeth_l2_setup_netdev(struct qeth_card *card, bool carrier_ok)  {  	int rc; -	if (card->dev->netdev_ops) +	if (qeth_netdev_is_registered(card->dev))  		return 0;  	card->dev->priv_flags |= IFF_UNICAST_FLT; @@ -919,6 +920,9 @@ static int qeth_l2_setup_netdev(struct qeth_card *card)  	qeth_l2_request_initial_mac(card);  	netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);  	rc = register_netdev(card->dev); +	if (!rc && carrier_ok) +		netif_carrier_on(card->dev); +  	if (rc)  		card->dev->netdev_ops = NULL;  	return rc; @@ -949,6 +953,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)  	struct qeth_card *card = dev_get_drvdata(&gdev->dev);  	int rc = 0;  	enum qeth_card_states recover_flag; +	bool carrier_ok;  	mutex_lock(&card->discipline_mutex);  	mutex_lock(&card->conf_mutex); @@ -956,7 +961,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)  	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));  	recover_flag = card->state; -	rc = qeth_core_hardsetup_card(card); +	rc = qeth_core_hardsetup_card(card, &carrier_ok);  	if (rc) {  		QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);  		rc = -ENODEV; @@ -967,7 +972,7 @@ static int __qeth_l2_set_online(struct ccwgroup_device *gdev, int recovery_mode)  		dev_info(&card->gdev->dev,  		"The device represents a Bridge Capable Port\n"); -	rc = qeth_l2_setup_netdev(card); +	rc = qeth_l2_setup_netdev(card, carrier_ok);  	if (rc)  		goto out_remove; diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 0b161cc1fd2e..f08b745c2007 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -278,9 +278,6 @@ static void qeth_l3_clear_ip_htable(struct qeth_card *card, int recover)  	QETH_CARD_TEXT(card, 4, "clearip"); -	if (recover && card->options.sniffer) -		return; -  	spin_lock_bh(&card->ip_lock);  	hash_for_each_safe(card->ip_htable, i, tmp, addr, hnode) { @@ -494,9 +491,8 @@ int qeth_l3_setrouting_v4(struct qeth_card *card)  				  QETH_PROT_IPV4);  	if (rc) {  		card->options.route4.type = NO_ROUTER; -		QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" -			" on %s. Type set to 'no router'.\n", rc, -			QETH_CARD_IFNAME(card)); +		QETH_DBF_MESSAGE(2, "Error (%#06x) while setting routing type on device %x. Type set to 'no router'.\n", +				 rc, CARD_DEVID(card));  	}  	return rc;  } @@ -518,9 +514,8 @@ int qeth_l3_setrouting_v6(struct qeth_card *card)  				  QETH_PROT_IPV6);  	if (rc) {  		card->options.route6.type = NO_ROUTER; -		QETH_DBF_MESSAGE(2, "Error (0x%04x) while setting routing type" -			" on %s. Type set to 'no router'.\n", rc, -			QETH_CARD_IFNAME(card)); +		QETH_DBF_MESSAGE(2, "Error (%#06x) while setting routing type on device %x. Type set to 'no router'.\n", +				 rc, CARD_DEVID(card));  	}  	return rc;  } @@ -663,6 +658,8 @@ static int qeth_l3_register_addr_entry(struct qeth_card *card,  	int rc = 0;  	int cnt = 3; +	if (card->options.sniffer) +		return 0;  	if (addr->proto == QETH_PROT_IPV4) {  		QETH_CARD_TEXT(card, 2, "setaddr4"); @@ -697,6 +694,9 @@ static int qeth_l3_deregister_addr_entry(struct qeth_card *card,  {  	int rc = 0; +	if (card->options.sniffer) +		return 0; +  	if (addr->proto == QETH_PROT_IPV4) {  		QETH_CARD_TEXT(card, 2, "deladdr4");  		QETH_CARD_HEX(card, 3, &addr->u.a4.addr, sizeof(int)); @@ -1070,8 +1070,8 @@ qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply,  		}  		break;  	default: -		QETH_DBF_MESSAGE(2, "Unknown sniffer action (0x%04x) on %s\n", -			cmd->data.diagass.action, QETH_CARD_IFNAME(card)); +		QETH_DBF_MESSAGE(2, "Unknown sniffer action (%#06x) on device %x\n", +				 cmd->data.diagass.action, CARD_DEVID(card));  	}  	return 0; @@ -1517,32 +1517,25 @@ static void qeth_l3_set_rx_mode(struct net_device *dev)  	qeth_l3_handle_promisc_mode(card);  } -static const char *qeth_l3_arp_get_error_cause(int *rc) +static int qeth_l3_arp_makerc(int rc)  { -	switch (*rc) { -	case QETH_IPA_ARP_RC_FAILED: -		*rc = -EIO; -		return "operation failed"; +	switch (rc) { +	case IPA_RC_SUCCESS: +		return 0;  	case QETH_IPA_ARP_RC_NOTSUPP: -		*rc = -EOPNOTSUPP; -		return "operation not supported"; -	case QETH_IPA_ARP_RC_OUT_OF_RANGE: -		*rc = -EINVAL; -		return "argument out of range";  	case QETH_IPA_ARP_RC_Q_NOTSUPP: -		*rc = -EOPNOTSUPP; -		return "query operation not supported"; +		return -EOPNOTSUPP; +	case QETH_IPA_ARP_RC_OUT_OF_RANGE: +		return -EINVAL;  	case QETH_IPA_ARP_RC_Q_NO_DATA: -		*rc = -ENOENT; -		return "no query data available"; +		return -ENOENT;  	default: -		return "unknown error"; +		return -EIO;  	}  }  static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)  { -	int tmp;  	int rc;  	QETH_CARD_TEXT(card, 3, "arpstnoe"); @@ -1560,13 +1553,10 @@ static int qeth_l3_arp_set_no_entries(struct qeth_card *card, int no_entries)  	rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,  					  IPA_CMD_ASS_ARP_SET_NO_ENTRIES,  					  no_entries); -	if (rc) { -		tmp = rc; -		QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on " -			"%s: %s (0x%x/%d)\n", QETH_CARD_IFNAME(card), -			qeth_l3_arp_get_error_cause(&rc), tmp, tmp); -	} -	return rc; +	if (rc) +		QETH_DBF_MESSAGE(2, "Could not set number of ARP entries on device %x: %#x\n", +				 CARD_DEVID(card), rc); +	return qeth_l3_arp_makerc(rc);  }  static __u32 get_arp_entry_size(struct qeth_card *card, @@ -1716,7 +1706,6 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,  {  	struct qeth_cmd_buffer *iob;  	struct qeth_ipa_cmd *cmd; -	int tmp;  	int rc;  	QETH_CARD_TEXT_(card, 3, "qarpipv%i", prot); @@ -1735,15 +1724,10 @@ static int qeth_l3_query_arp_cache_info(struct qeth_card *card,  	rc = qeth_l3_send_ipa_arp_cmd(card, iob,  			   QETH_SETASS_BASE_LEN+QETH_ARP_CMD_LEN,  			   qeth_l3_arp_query_cb, (void *)qinfo); -	if (rc) { -		tmp = rc; -		QETH_DBF_MESSAGE(2, -			"Error while querying ARP cache on %s: %s " -			"(0x%x/%d)\n", QETH_CARD_IFNAME(card), -			qeth_l3_arp_get_error_cause(&rc), tmp, tmp); -	} - -	return rc; +	if (rc) +		QETH_DBF_MESSAGE(2, "Error while querying ARP cache on device %x: %#x\n", +				 CARD_DEVID(card), rc); +	return qeth_l3_arp_makerc(rc);  }  static int qeth_l3_arp_query(struct qeth_card *card, char __user *udata) @@ -1793,15 +1777,18 @@ out:  	return rc;  } -static int qeth_l3_arp_add_entry(struct qeth_card *card, -				struct qeth_arp_cache_entry *entry) +static int qeth_l3_arp_modify_entry(struct qeth_card *card, +				    struct qeth_arp_cache_entry *entry, +				    enum qeth_arp_process_subcmds arp_cmd)  { +	struct qeth_arp_cache_entry *cmd_entry;  	struct qeth_cmd_buffer *iob; -	char buf[16]; -	int tmp;  	int rc; -	QETH_CARD_TEXT(card, 3, "arpadent"); +	if (arp_cmd == IPA_CMD_ASS_ARP_ADD_ENTRY) +		QETH_CARD_TEXT(card, 3, "arpadd"); +	else +		QETH_CARD_TEXT(card, 3, "arpdel");  	/*  	 * currently GuestLAN only supports the ARP assist function @@ -1814,71 +1801,25 @@ static int qeth_l3_arp_add_entry(struct qeth_card *card,  		return -EOPNOTSUPP;  	} -	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, -				       IPA_CMD_ASS_ARP_ADD_ENTRY, -				       sizeof(struct qeth_arp_cache_entry), -				       QETH_PROT_IPV4); +	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, arp_cmd, +				       sizeof(*cmd_entry), QETH_PROT_IPV4);  	if (!iob)  		return -ENOMEM; -	rc = qeth_send_setassparms(card, iob, -				   sizeof(struct qeth_arp_cache_entry), -				   (unsigned long) entry, -				   qeth_setassparms_cb, NULL); -	if (rc) { -		tmp = rc; -		qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf); -		QETH_DBF_MESSAGE(2, "Could not add ARP entry for address %s " -			"on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card), -			qeth_l3_arp_get_error_cause(&rc), tmp, tmp); -	} -	return rc; -} - -static int qeth_l3_arp_remove_entry(struct qeth_card *card, -				struct qeth_arp_cache_entry *entry) -{ -	struct qeth_cmd_buffer *iob; -	char buf[16] = {0, }; -	int tmp; -	int rc; -	QETH_CARD_TEXT(card, 3, "arprment"); +	cmd_entry = &__ipa_cmd(iob)->data.setassparms.data.arp_entry; +	ether_addr_copy(cmd_entry->macaddr, entry->macaddr); +	memcpy(cmd_entry->ipaddr, entry->ipaddr, 4); +	rc = qeth_send_ipa_cmd(card, iob, qeth_setassparms_cb, NULL); +	if (rc) +		QETH_DBF_MESSAGE(2, "Could not modify (cmd: %#x) ARP entry on device %x: %#x\n", +				 arp_cmd, CARD_DEVID(card), rc); -	/* -	 * currently GuestLAN only supports the ARP assist function -	 * IPA_CMD_ASS_ARP_QUERY_INFO, but not IPA_CMD_ASS_ARP_REMOVE_ENTRY; -	 * thus we say EOPNOTSUPP for this ARP function -	 */ -	if (card->info.guestlan) -		return -EOPNOTSUPP; -	if (!qeth_is_supported(card, IPA_ARP_PROCESSING)) { -		return -EOPNOTSUPP; -	} -	memcpy(buf, entry, 12); -	iob = qeth_get_setassparms_cmd(card, IPA_ARP_PROCESSING, -				       IPA_CMD_ASS_ARP_REMOVE_ENTRY, -				       12, -				       QETH_PROT_IPV4); -	if (!iob) -		return -ENOMEM; -	rc = qeth_send_setassparms(card, iob, -				   12, (unsigned long)buf, -				   qeth_setassparms_cb, NULL); -	if (rc) { -		tmp = rc; -		memset(buf, 0, 16); -		qeth_l3_ipaddr4_to_string((u8 *)entry->ipaddr, buf); -		QETH_DBF_MESSAGE(2, "Could not delete ARP entry for address %s" -			" on %s: %s (0x%x/%d)\n", buf, QETH_CARD_IFNAME(card), -			qeth_l3_arp_get_error_cause(&rc), tmp, tmp); -	} -	return rc; +	return qeth_l3_arp_makerc(rc);  }  static int qeth_l3_arp_flush_cache(struct qeth_card *card)  {  	int rc; -	int tmp;  	QETH_CARD_TEXT(card, 3, "arpflush"); @@ -1894,19 +1835,17 @@ static int qeth_l3_arp_flush_cache(struct qeth_card *card)  	}  	rc = qeth_send_simple_setassparms(card, IPA_ARP_PROCESSING,  					  IPA_CMD_ASS_ARP_FLUSH_CACHE, 0); -	if (rc) { -		tmp = rc; -		QETH_DBF_MESSAGE(2, "Could not flush ARP cache on %s: %s " -			"(0x%x/%d)\n", QETH_CARD_IFNAME(card), -			qeth_l3_arp_get_error_cause(&rc), tmp, tmp); -	} -	return rc; +	if (rc) +		QETH_DBF_MESSAGE(2, "Could not flush ARP cache on device %x: %#x\n", +				 CARD_DEVID(card), rc); +	return qeth_l3_arp_makerc(rc);  }  static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  {  	struct qeth_card *card = dev->ml_priv;  	struct qeth_arp_cache_entry arp_entry; +	enum qeth_arp_process_subcmds arp_cmd;  	int rc = 0;  	switch (cmd) { @@ -1925,27 +1864,16 @@ static int qeth_l3_do_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)  		rc = qeth_l3_arp_query(card, rq->ifr_ifru.ifru_data);  		break;  	case SIOC_QETH_ARP_ADD_ENTRY: -		if (!capable(CAP_NET_ADMIN)) { -			rc = -EPERM; -			break; -		} -		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data, -				   sizeof(struct qeth_arp_cache_entry))) -			rc = -EFAULT; -		else -			rc = qeth_l3_arp_add_entry(card, &arp_entry); -		break;  	case SIOC_QETH_ARP_REMOVE_ENTRY: -		if (!capable(CAP_NET_ADMIN)) { -			rc = -EPERM; -			break; -		} -		if (copy_from_user(&arp_entry, rq->ifr_ifru.ifru_data, -				   sizeof(struct qeth_arp_cache_entry))) -			rc = -EFAULT; -		else -			rc = qeth_l3_arp_remove_entry(card, &arp_entry); -		break; +		if (!capable(CAP_NET_ADMIN)) +			return -EPERM; +		if (copy_from_user(&arp_entry, rq->ifr_data, sizeof(arp_entry))) +			return -EFAULT; + +		arp_cmd = (cmd == SIOC_QETH_ARP_ADD_ENTRY) ? +				IPA_CMD_ASS_ARP_ADD_ENTRY : +				IPA_CMD_ASS_ARP_REMOVE_ENTRY; +		return qeth_l3_arp_modify_entry(card, &arp_entry, arp_cmd);  	case SIOC_QETH_ARP_FLUSH_CACHE:  		if (!capable(CAP_NET_ADMIN)) {  			rc = -EPERM; @@ -2383,12 +2311,12 @@ static const struct net_device_ops qeth_l3_osa_netdev_ops = {  	.ndo_neigh_setup	= qeth_l3_neigh_setup,  }; -static int qeth_l3_setup_netdev(struct qeth_card *card) +static int qeth_l3_setup_netdev(struct qeth_card *card, bool carrier_ok)  {  	unsigned int headroom;  	int rc; -	if (card->dev->netdev_ops) +	if (qeth_netdev_is_registered(card->dev))  		return 0;  	if (card->info.type == QETH_CARD_TYPE_OSD || @@ -2457,6 +2385,9 @@ static int qeth_l3_setup_netdev(struct qeth_card *card)  	netif_napi_add(card->dev, &card->napi, qeth_poll, QETH_NAPI_WEIGHT);  	rc = register_netdev(card->dev); +	if (!rc && carrier_ok) +		netif_carrier_on(card->dev); +  out:  	if (rc)  		card->dev->netdev_ops = NULL; @@ -2497,7 +2428,8 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)  	if (cgdev->state == CCWGROUP_ONLINE)  		qeth_l3_set_offline(cgdev); -	unregister_netdev(card->dev); +	if (qeth_netdev_is_registered(card->dev)) +		unregister_netdev(card->dev);  	qeth_l3_clear_ip_htable(card, 0);  	qeth_l3_clear_ipato_list(card);  } @@ -2507,6 +2439,7 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)  	struct qeth_card *card = dev_get_drvdata(&gdev->dev);  	int rc = 0;  	enum qeth_card_states recover_flag; +	bool carrier_ok;  	mutex_lock(&card->discipline_mutex);  	mutex_lock(&card->conf_mutex); @@ -2514,14 +2447,14 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode)  	QETH_DBF_HEX(SETUP, 2, &card, sizeof(void *));  	recover_flag = card->state; -	rc = qeth_core_hardsetup_card(card); +	rc = qeth_core_hardsetup_card(card, &carrier_ok);  	if (rc) {  		QETH_DBF_TEXT_(SETUP, 2, "2err%04x", rc);  		rc = -ENODEV;  		goto out_remove;  	} -	rc = qeth_l3_setup_netdev(card); +	rc = qeth_l3_setup_netdev(card, carrier_ok);  	if (rc)  		goto out_remove; diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index 5c8ed7350a04..a36e4cf1841d 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c @@ -220,6 +220,7 @@ static int d7s_probe(struct platform_device *op)  	dev_set_drvdata(&op->dev, p);  	d7s_device = p;  	err = 0; +	of_node_put(opts);  out:  	return err; diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index 56e962a01493..b8481927bfe4 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c @@ -910,8 +910,10 @@ static void envctrl_init_i2c_child(struct device_node *dp,  			for (len = 0; len < PCF8584_MAX_CHANNELS; ++len) {  				pchild->mon_type[len] = ENVCTRL_NOMON;  			} +			of_node_put(root_node);  			return;  		} +		of_node_put(root_node);  	}  	/* Get the monitor channels. */ diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index c7fccbb8f554..fa6e0c3b3aa6 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -697,6 +697,12 @@ static bool scsi_end_request(struct request *req, blk_status_t error,  		 */  		scsi_mq_uninit_cmd(cmd); +		/* +		 * queue is still alive, so grab the ref for preventing it +		 * from being cleaned up during running queue. +		 */ +		percpu_ref_get(&q->q_usage_counter); +  		__blk_mq_end_request(req, error);  		if (scsi_target(sdev)->single_lun || @@ -704,6 +710,8 @@ static bool scsi_end_request(struct request *req, blk_status_t error,  			kblockd_schedule_work(&sdev->requeue_work);  		else  			blk_mq_run_hw_queues(q, true); + +		percpu_ref_put(&q->q_usage_counter);  	} else {  		unsigned long flags; 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/spi/spi-mt65xx.c b/drivers/spi/spi-mt65xx.c index 3dc31627c655..0c2867deb36f 100644 --- a/drivers/spi/spi-mt65xx.c +++ b/drivers/spi/spi-mt65xx.c @@ -522,11 +522,11 @@ static irqreturn_t mtk_spi_interrupt(int irq, void *dev_id)  		mdata->xfer_len = min(MTK_SPI_MAX_FIFO_SIZE, len);  		mtk_spi_setup_packet(master); -		cnt = len / 4; +		cnt = mdata->xfer_len / 4;  		iowrite32_rep(mdata->base + SPI_TX_DATA_REG,  				trans->tx_buf + mdata->num_xfered, cnt); -		remainder = len % 4; +		remainder = mdata->xfer_len % 4;  		if (remainder > 0) {  			reg_val = 0;  			memcpy(®_val, diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c index f024c3fc3679..2fd8881fcd65 100644 --- a/drivers/spi/spi-omap2-mcspi.c +++ b/drivers/spi/spi-omap2-mcspi.c @@ -1540,13 +1540,26 @@ static int omap2_mcspi_remove(struct platform_device *pdev)  /* work with hotplug and coldplug */  MODULE_ALIAS("platform:omap2_mcspi"); -#ifdef	CONFIG_SUSPEND -static int omap2_mcspi_suspend_noirq(struct device *dev) +static int __maybe_unused omap2_mcspi_suspend(struct device *dev)  { -	return pinctrl_pm_select_sleep_state(dev); +	struct spi_master *master = dev_get_drvdata(dev); +	struct omap2_mcspi *mcspi = spi_master_get_devdata(master); +	int error; + +	error = pinctrl_pm_select_sleep_state(dev); +	if (error) +		dev_warn(mcspi->dev, "%s: failed to set pins: %i\n", +			 __func__, error); + +	error = spi_master_suspend(master); +	if (error) +		dev_warn(mcspi->dev, "%s: master suspend failed: %i\n", +			 __func__, error); + +	return pm_runtime_force_suspend(dev);  } -static int omap2_mcspi_resume_noirq(struct device *dev) +static int __maybe_unused omap2_mcspi_resume(struct device *dev)  {  	struct spi_master *master = dev_get_drvdata(dev);  	struct omap2_mcspi *mcspi = spi_master_get_devdata(master); @@ -1557,17 +1570,17 @@ static int omap2_mcspi_resume_noirq(struct device *dev)  		dev_warn(mcspi->dev, "%s: failed to set pins: %i\n",  			 __func__, error); -	return 0; -} +	error = spi_master_resume(master); +	if (error) +		dev_warn(mcspi->dev, "%s: master resume failed: %i\n", +			 __func__, error); -#else -#define omap2_mcspi_suspend_noirq	NULL -#define omap2_mcspi_resume_noirq	NULL -#endif +	return pm_runtime_force_resume(dev); +}  static const struct dev_pm_ops omap2_mcspi_pm_ops = { -	.suspend_noirq = omap2_mcspi_suspend_noirq, -	.resume_noirq = omap2_mcspi_resume_noirq, +	SET_SYSTEM_SLEEP_PM_OPS(omap2_mcspi_suspend, +				omap2_mcspi_resume)  	.runtime_resume	= omap_mcspi_runtime_resume,  }; diff --git a/drivers/staging/comedi/comedi.h b/drivers/staging/comedi/comedi.h index e90b17775284..09a940066c0e 100644 --- a/drivers/staging/comedi/comedi.h +++ b/drivers/staging/comedi/comedi.h @@ -1005,35 +1005,38 @@ enum i8254_mode {   * and INSN_DEVICE_CONFIG_GET_ROUTES.   */  #define NI_NAMES_BASE	0x8000u + +#define _TERM_N(base, n, x)	((base) + ((x) & ((n) - 1))) +  /*   * not necessarily all allowed 64 PFIs are valid--certainly not for all devices   */ -#define NI_PFI(x)	(NI_NAMES_BASE        + ((x) & 0x3f)) +#define NI_PFI(x)		_TERM_N(NI_NAMES_BASE, 64, x)  /* 8 trigger lines by standard, Some devices cannot talk to all eight. */ -#define TRIGGER_LINE(x)	(NI_PFI(-1)       + 1 + ((x) & 0x7)) +#define TRIGGER_LINE(x)		_TERM_N(NI_PFI(-1) + 1, 8, x)  /* 4 RTSI shared MUXes to route signals to/from TRIGGER_LINES on NI hardware */ -#define NI_RTSI_BRD(x)	(TRIGGER_LINE(-1) + 1 + ((x) & 0x3)) +#define NI_RTSI_BRD(x)		_TERM_N(TRIGGER_LINE(-1) + 1, 4, x)  /* *** Counter/timer names : 8 counters max *** */ -#define NI_COUNTER_NAMES_BASE  (NI_RTSI_BRD(-1)  + 1) -#define NI_MAX_COUNTERS	       7 -#define NI_CtrSource(x)	       (NI_COUNTER_NAMES_BASE + ((x) & NI_MAX_COUNTERS)) +#define NI_MAX_COUNTERS		8 +#define NI_COUNTER_NAMES_BASE	(NI_RTSI_BRD(-1)  + 1) +#define NI_CtrSource(x)	      _TERM_N(NI_COUNTER_NAMES_BASE, NI_MAX_COUNTERS, x)  /* Gate, Aux, A,B,Z are all treated, at times as gates */ -#define NI_GATES_NAMES_BASE    (NI_CtrSource(-1) + 1) -#define NI_CtrGate(x)	       (NI_GATES_NAMES_BASE   + ((x) & NI_MAX_COUNTERS)) -#define NI_CtrAux(x)	       (NI_CtrGate(-1)   + 1  + ((x) & NI_MAX_COUNTERS)) -#define NI_CtrA(x)	       (NI_CtrAux(-1)    + 1  + ((x) & NI_MAX_COUNTERS)) -#define NI_CtrB(x)	       (NI_CtrA(-1)      + 1  + ((x) & NI_MAX_COUNTERS)) -#define NI_CtrZ(x)	       (NI_CtrB(-1)      + 1  + ((x) & NI_MAX_COUNTERS)) -#define NI_GATES_NAMES_MAX     NI_CtrZ(-1) -#define NI_CtrArmStartTrigger(x) (NI_CtrZ(-1)    + 1  + ((x) & NI_MAX_COUNTERS)) +#define NI_GATES_NAMES_BASE	(NI_CtrSource(-1) + 1) +#define NI_CtrGate(x)		_TERM_N(NI_GATES_NAMES_BASE, NI_MAX_COUNTERS, x) +#define NI_CtrAux(x)		_TERM_N(NI_CtrGate(-1)  + 1, NI_MAX_COUNTERS, x) +#define NI_CtrA(x)		_TERM_N(NI_CtrAux(-1)   + 1, NI_MAX_COUNTERS, x) +#define NI_CtrB(x)		_TERM_N(NI_CtrA(-1)     + 1, NI_MAX_COUNTERS, x) +#define NI_CtrZ(x)		_TERM_N(NI_CtrB(-1)     + 1, NI_MAX_COUNTERS, x) +#define NI_GATES_NAMES_MAX	NI_CtrZ(-1) +#define NI_CtrArmStartTrigger(x) _TERM_N(NI_CtrZ(-1)    + 1, NI_MAX_COUNTERS, x)  #define NI_CtrInternalOutput(x) \ -		     (NI_CtrArmStartTrigger(-1)  + 1  + ((x) & NI_MAX_COUNTERS)) +		      _TERM_N(NI_CtrArmStartTrigger(-1) + 1, NI_MAX_COUNTERS, x)  /** external pin(s) labeled conveniently as Ctr<i>Out. */ -#define NI_CtrOut(x)  (NI_CtrInternalOutput(-1)  + 1  + ((x) & NI_MAX_COUNTERS)) +#define NI_CtrOut(x)   _TERM_N(NI_CtrInternalOutput(-1) + 1, NI_MAX_COUNTERS, x)  /** For Buffered sampling of ctr -- x series capability. */ -#define NI_CtrSampleClock(x)	(NI_CtrOut(-1)   + 1  + ((x) & NI_MAX_COUNTERS)) -#define NI_COUNTER_NAMES_MAX   NI_CtrSampleClock(-1) +#define NI_CtrSampleClock(x)	_TERM_N(NI_CtrOut(-1)   + 1, NI_MAX_COUNTERS, x) +#define NI_COUNTER_NAMES_MAX	NI_CtrSampleClock(-1)  enum ni_common_signal_names {  	/* PXI_Star: this is a non-NI-specific signal */ diff --git a/drivers/staging/comedi/drivers/ni_mio_common.c b/drivers/staging/comedi/drivers/ni_mio_common.c index 2d1e0325d04d..5edf59ac6706 100644 --- a/drivers/staging/comedi/drivers/ni_mio_common.c +++ b/drivers/staging/comedi/drivers/ni_mio_common.c @@ -2843,7 +2843,8 @@ static int ni_ao_insn_config(struct comedi_device *dev,  		return ni_ao_arm(dev, s);  	case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS:  		/* we don't care about actual channels */ -		data[1] = board->ao_speed; +		/* data[3] : chanlist_len */ +		data[1] = board->ao_speed * data[3];  		data[2] = 0;  		return 0;  	default: 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/TODO b/drivers/staging/media/sunxi/cedrus/TODO index ec277ece47af..a951b3fd1ea1 100644 --- a/drivers/staging/media/sunxi/cedrus/TODO +++ b/drivers/staging/media/sunxi/cedrus/TODO @@ -5,3 +5,8 @@ Before this stateless decoder driver can leave the staging area:  * Userspace support for the Request API needs to be reviewed;  * Another stateless decoder driver should be submitted;  * At least one stateless encoder driver should be submitted. +* When queueing a request containing references to I frames, the +  refcount of the memory for those I frames needs to be incremented +  and decremented when the request is completed. This will likely +  require some help from vb2. The driver should fail the request +  if the memory/buffer is gone. diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index 82558455384a..c912c70b3ef7 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -108,17 +108,6 @@ static int cedrus_request_validate(struct media_request *req)  	unsigned int count;  	unsigned int i; -	count = vb2_request_buffer_cnt(req); -	if (!count) { -		v4l2_info(&ctx->dev->v4l2_dev, -			  "No buffer was provided with the request\n"); -		return -ENOENT; -	} else if (count > 1) { -		v4l2_info(&ctx->dev->v4l2_dev, -			  "More than one buffer was provided with the request\n"); -		return -EINVAL; -	} -  	list_for_each_entry(obj, &req->objects, list) {  		struct vb2_buffer *vb; @@ -133,6 +122,17 @@ static int cedrus_request_validate(struct media_request *req)  	if (!ctx)  		return -ENOENT; +	count = vb2_request_buffer_cnt(req); +	if (!count) { +		v4l2_info(&ctx->dev->v4l2_dev, +			  "No buffer was provided with the request\n"); +		return -ENOENT; +	} else if (count > 1) { +		v4l2_info(&ctx->dev->v4l2_dev, +			  "More than one buffer was provided with the request\n"); +		return -EINVAL; +	} +  	parent_hdl = &ctx->hdl;  	hdl = v4l2_ctrl_request_hdl_find(req, parent_hdl); @@ -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/staging/most/core.c b/drivers/staging/most/core.c index 6a18cf73c85e..18936cdb1083 100644 --- a/drivers/staging/most/core.c +++ b/drivers/staging/most/core.c @@ -351,7 +351,7 @@ static ssize_t set_datatype_show(struct device *dev,  	for (i = 0; i < ARRAY_SIZE(ch_data_type); i++) {  		if (c->cfg.data_type & ch_data_type[i].most_ch_data_type) -			return snprintf(buf, PAGE_SIZE, ch_data_type[i].name); +			return snprintf(buf, PAGE_SIZE, "%s", ch_data_type[i].name);  	}  	return snprintf(buf, PAGE_SIZE, "unconfigured\n");  } diff --git a/drivers/staging/mt7621-dma/mtk-hsdma.c b/drivers/staging/mt7621-dma/mtk-hsdma.c index df6ebf41bdea..5831f816c17b 100644 --- a/drivers/staging/mt7621-dma/mtk-hsdma.c +++ b/drivers/staging/mt7621-dma/mtk-hsdma.c @@ -335,6 +335,8 @@ static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma,  	/* tx desc */  	src = sg->src_addr;  	for (i = 0; i < chan->desc->num_sgs; i++) { +		tx_desc = &chan->tx_ring[chan->tx_idx]; +  		if (len > HSDMA_MAX_PLEN)  			tlen = HSDMA_MAX_PLEN;  		else @@ -344,7 +346,6 @@ static int mtk_hsdma_start_transfer(struct mtk_hsdam_engine *hsdma,  			tx_desc->addr1 = src;  			tx_desc->flags |= HSDMA_DESC_PLEN1(tlen);  		} else { -			tx_desc = &chan->tx_ring[chan->tx_idx];  			tx_desc->addr0 = src;  			tx_desc->flags = HSDMA_DESC_PLEN0(tlen); diff --git a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c index b8566ed898f1..aa98fbb17013 100644 --- a/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c +++ b/drivers/staging/mt7621-pinctrl/pinctrl-rt2880.c @@ -82,7 +82,7 @@ static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev,  	struct property *prop;  	const char *function_name, *group_name;  	int ret; -	int ngroups; +	int ngroups = 0;  	unsigned int reserved_maps = 0;  	for_each_node_with_property(np_config, "group") diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c index 85077947b9b8..85aba8a503cd 100644 --- a/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c +++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_recv.c @@ -109,12 +109,12 @@ static void update_recvframe_phyinfo(union recv_frame *precvframe,  	rx_bssid = get_hdr_bssid(wlanhdr);  	pkt_info.bssid_match = ((!IsFrameTypeCtrl(wlanhdr)) &&  				!pattrib->icv_err && !pattrib->crc_err && -				!ether_addr_equal(rx_bssid, my_bssid)); +				ether_addr_equal(rx_bssid, my_bssid));  	rx_ra = get_ra(wlanhdr);  	my_hwaddr = myid(&padapter->eeprompriv);  	pkt_info.to_self = pkt_info.bssid_match && -		!ether_addr_equal(rx_ra, my_hwaddr); +		ether_addr_equal(rx_ra, my_hwaddr);  	pkt_info.is_beacon = pkt_info.bssid_match && diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c index af2234798fa8..db553f2e4c0b 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -1277,7 +1277,7 @@ static int cfg80211_rtw_get_station(struct wiphy *wiphy,  		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_PACKETS);  		sinfo->tx_packets = psta->sta_stats.tx_pkts; - +		sinfo->filled |= BIT_ULL(NL80211_STA_INFO_TX_FAILED);  	}  	/* for Ad-Hoc/AP mode */ diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c index 28bfdbdc6e76..b8631baf128d 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c @@ -2289,7 +2289,7 @@ static int rtw_wx_read32(struct net_device *dev,  exit:  	kfree(ptmp); -	return 0; +	return ret;  }  static int rtw_wx_write32(struct net_device *dev, diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c index ea789376de0f..45de21c210c1 100644 --- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c +++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c @@ -1795,6 +1795,7 @@ vchiq_compat_ioctl_await_completion(struct file *file,  	struct vchiq_await_completion32 args32;  	struct vchiq_completion_data32 completion32;  	unsigned int *msgbufcount32; +	unsigned int msgbufcount_native;  	compat_uptr_t msgbuf32;  	void *msgbuf;  	void **msgbufptr; @@ -1906,7 +1907,11 @@ vchiq_compat_ioctl_await_completion(struct file *file,  			 sizeof(completion32)))  		return -EFAULT; -	args32.msgbufcount--; +	if (get_user(msgbufcount_native, &args->msgbufcount)) +		return -EFAULT; + +	if (!msgbufcount_native) +		args32.msgbufcount--;  	msgbufcount32 =  		&((struct vchiq_await_completion32 __user *)arg)->msgbufcount; diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c index 52ff854f0d6c..cd96994dc094 100644 --- a/drivers/thunderbolt/switch.c +++ b/drivers/thunderbolt/switch.c @@ -863,6 +863,30 @@ static ssize_t key_store(struct device *dev, struct device_attribute *attr,  }  static DEVICE_ATTR(key, 0600, key_show, key_store); +static void nvm_authenticate_start(struct tb_switch *sw) +{ +	struct pci_dev *root_port; + +	/* +	 * During host router NVM upgrade we should not allow root port to +	 * go into D3cold because some root ports cannot trigger PME +	 * itself. To be on the safe side keep the root port in D0 during +	 * the whole upgrade process. +	 */ +	root_port = pci_find_pcie_root_port(sw->tb->nhi->pdev); +	if (root_port) +		pm_runtime_get_noresume(&root_port->dev); +} + +static void nvm_authenticate_complete(struct tb_switch *sw) +{ +	struct pci_dev *root_port; + +	root_port = pci_find_pcie_root_port(sw->tb->nhi->pdev); +	if (root_port) +		pm_runtime_put(&root_port->dev); +} +  static ssize_t nvm_authenticate_show(struct device *dev,  	struct device_attribute *attr, char *buf)  { @@ -912,10 +936,18 @@ static ssize_t nvm_authenticate_store(struct device *dev,  		sw->nvm->authenticating = true; -		if (!tb_route(sw)) +		if (!tb_route(sw)) { +			/* +			 * Keep root port from suspending as long as the +			 * NVM upgrade process is running. +			 */ +			nvm_authenticate_start(sw);  			ret = nvm_authenticate_host(sw); -		else +			if (ret) +				nvm_authenticate_complete(sw); +		} else {  			ret = nvm_authenticate_device(sw); +		}  		pm_runtime_mark_last_busy(&sw->dev);  		pm_runtime_put_autosuspend(&sw->dev);  	} @@ -1334,6 +1366,10 @@ static int tb_switch_add_dma_port(struct tb_switch *sw)  	if (ret <= 0)  		return ret; +	/* Now we can allow root port to suspend again */ +	if (!tb_route(sw)) +		nvm_authenticate_complete(sw); +  	if (status) {  		tb_sw_info(sw, "switch flash authentication failed\n");  		tb_switch_set_uuid(sw); diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c index ff6ba6d86cd8..cc56cb3b3eca 100644 --- a/drivers/tty/serial/sh-sci.c +++ b/drivers/tty/serial/sh-sci.c @@ -1614,10 +1614,10 @@ static void sci_request_dma(struct uart_port *port)  		hrtimer_init(&s->rx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);  		s->rx_timer.function = rx_timer_fn; +		s->chan_rx_saved = s->chan_rx = chan; +  		if (port->type == PORT_SCIFA || port->type == PORT_SCIFB)  			sci_submit_rx(s); - -		s->chan_rx_saved = s->chan_rx = chan;  	}  } @@ -3102,6 +3102,7 @@ static struct uart_driver sci_uart_driver = {  static int sci_remove(struct platform_device *dev)  {  	struct sci_port *port = platform_get_drvdata(dev); +	unsigned int type = port->port.type;	/* uart_remove_... clears it */  	sci_ports_in_use &= ~BIT(port->port.line);  	uart_remove_one_port(&sci_uart_driver, &port->port); @@ -3112,8 +3113,7 @@ static int sci_remove(struct platform_device *dev)  		sysfs_remove_file(&dev->dev.kobj,  				  &dev_attr_rx_fifo_trigger.attr);  	} -	if (port->port.type == PORT_SCIFA || port->port.type == PORT_SCIFB || -	    port->port.type == PORT_HSCIF) { +	if (type == PORT_SCIFA || type == PORT_SCIFB || type == PORT_HSCIF) {  		sysfs_remove_file(&dev->dev.kobj,  				  &dev_attr_rx_fifo_timeout.attr);  	} diff --git a/drivers/tty/serial/suncore.c b/drivers/tty/serial/suncore.c index 70a4ea4eaa6e..990376576970 100644 --- a/drivers/tty/serial/suncore.c +++ b/drivers/tty/serial/suncore.c @@ -112,6 +112,7 @@ void sunserial_console_termios(struct console *con, struct device_node *uart_dp)  		mode = of_get_property(dp, mode_prop, NULL);  		if (!mode)  			mode = "9600,8,n,1,-"; +		of_node_put(dp);  	}  	cflag = CREAD | HUPCL | CLOCAL; diff --git a/drivers/tty/tty_baudrate.c b/drivers/tty/tty_baudrate.c index 7576ceace571..f438eaa68246 100644 --- a/drivers/tty/tty_baudrate.c +++ b/drivers/tty/tty_baudrate.c @@ -77,7 +77,7 @@ speed_t tty_termios_baud_rate(struct ktermios *termios)  		else  			cbaud += 15;  	} -	return baud_table[cbaud]; +	return cbaud >= n_baud_table ? 0 : baud_table[cbaud];  }  EXPORT_SYMBOL(tty_termios_baud_rate); @@ -113,7 +113,7 @@ speed_t tty_termios_input_baud_rate(struct ktermios *termios)  		else  			cbaud += 15;  	} -	return baud_table[cbaud]; +	return cbaud >= n_baud_table ? 0 : baud_table[cbaud];  #else	/* IBSHIFT */  	return tty_termios_baud_rate(termios);  #endif	/* IBSHIFT */ diff --git a/drivers/tty/vt/vt.c b/drivers/tty/vt/vt.c index 55370e651db3..41ec8e5010f3 100644 --- a/drivers/tty/vt/vt.c +++ b/drivers/tty/vt/vt.c @@ -1548,7 +1548,7 @@ static void csi_K(struct vc_data *vc, int vpar)  	scr_memsetw(start + offset, vc->vc_video_erase_char, 2 * count);  	vc->vc_need_wrap = 0;  	if (con_should_update(vc)) -		do_update_region(vc, (unsigned long) start, count); +		do_update_region(vc, (unsigned long)(start + offset), count);  }  static void csi_X(struct vc_data *vc, int vpar) /* erase the following vpar positions */ 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..0690fcff0ea2 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 */  			}  		} @@ -206,6 +209,9 @@ static const struct usb_device_id usb_quirk_list[] = {  	/* Microsoft LifeCam-VX700 v2.0 */  	{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, +	/* Cherry Stream G230 2.0 (G85-231) and 3.0 (G85-232) */ +	{ USB_DEVICE(0x046a, 0x0023), .driver_info = USB_QUIRK_RESET_RESUME }, +  	/* Logitech HD Pro Webcams C920, C920-C, C925e and C930e */  	{ USB_DEVICE(0x046d, 0x082d), .driver_info = USB_QUIRK_DELAY_INIT },  	{ USB_DEVICE(0x046d, 0x0841), .driver_info = USB_QUIRK_DELAY_INIT }, @@ -380,6 +386,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 +400,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 +423,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..9f92ee03dde7 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 { @@ -1470,9 +1470,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)  		unsigned transfer_in_flight;  		unsigned started; -		if (dep->flags & DWC3_EP_STALL) -			return 0; -  		if (dep->number > 1)  			trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue);  		else @@ -1494,8 +1491,6 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)  		else  			dep->flags |= DWC3_EP_STALL;  	} else { -		if (!(dep->flags & DWC3_EP_STALL)) -			return 0;  		ret = dwc3_send_clear_stall_ep_cmd(dep);  		if (ret) @@ -2259,7 +2254,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/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c index 1000d864929c..0f026d445e31 100644 --- a/drivers/usb/gadget/function/u_ether.c +++ b/drivers/usb/gadget/function/u_ether.c @@ -401,12 +401,12 @@ done:  static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags)  {  	struct usb_request	*req; -	struct usb_request	*tmp;  	unsigned long		flags;  	/* fill unused rxq slots with some skb */  	spin_lock_irqsave(&dev->req_lock, flags); -	list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) { +	while (!list_empty(&dev->rx_reqs)) { +		req = list_first_entry(&dev->rx_reqs, struct usb_request, list);  		list_del_init(&req->list);  		spin_unlock_irqrestore(&dev->req_lock, flags); @@ -1125,7 +1125,6 @@ void gether_disconnect(struct gether *link)  {  	struct eth_dev		*dev = link->ioport;  	struct usb_request	*req; -	struct usb_request	*tmp;  	WARN_ON(!dev);  	if (!dev) @@ -1142,7 +1141,8 @@ void gether_disconnect(struct gether *link)  	 */  	usb_ep_disable(link->in_ep);  	spin_lock(&dev->req_lock); -	list_for_each_entry_safe(req, tmp, &dev->tx_reqs, list) { +	while (!list_empty(&dev->tx_reqs)) { +		req = list_first_entry(&dev->tx_reqs, struct usb_request, list);  		list_del(&req->list);  		spin_unlock(&dev->req_lock); @@ -1154,7 +1154,8 @@ void gether_disconnect(struct gether *link)  	usb_ep_disable(link->out_ep);  	spin_lock(&dev->req_lock); -	list_for_each_entry_safe(req, tmp, &dev->rx_reqs, list) { +	while (!list_empty(&dev->rx_reqs)) { +		req = list_first_entry(&dev->rx_reqs, struct usb_request, list);  		list_del(&req->list);  		spin_unlock(&dev->req_lock); diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c index 3a16431da321..fcf13ef33b31 100644 --- a/drivers/usb/gadget/udc/omap_udc.c +++ b/drivers/usb/gadget/udc/omap_udc.c @@ -2033,6 +2033,7 @@ static inline int machine_without_vbus_sense(void)  {  	return machine_is_omap_innovator()  		|| machine_is_omap_osk() +		|| machine_is_omap_palmte()  		|| machine_is_sx1()  		/* No known omap7xx boards with vbus sense */  		|| cpu_is_omap7xx(); @@ -2041,7 +2042,7 @@ static inline int machine_without_vbus_sense(void)  static int omap_udc_start(struct usb_gadget *g,  		struct usb_gadget_driver *driver)  { -	int		status = -ENODEV; +	int		status;  	struct omap_ep	*ep;  	unsigned long	flags; @@ -2079,6 +2080,7 @@ static int omap_udc_start(struct usb_gadget *g,  			goto done;  		}  	} else { +		status = 0;  		if (can_pullup(udc))  			pullup_enable(udc);  		else @@ -2593,9 +2595,22 @@ omap_ep_setup(char *name, u8 addr, u8 type,  static void omap_udc_release(struct device *dev)  { -	complete(udc->done); +	pullup_disable(udc); +	if (!IS_ERR_OR_NULL(udc->transceiver)) { +		usb_put_phy(udc->transceiver); +		udc->transceiver = NULL; +	} +	omap_writew(0, UDC_SYSCON1); +	remove_proc_file(); +	if (udc->dc_clk) { +		if (udc->clk_requested) +			omap_udc_enable_clock(0); +		clk_put(udc->hhc_clk); +		clk_put(udc->dc_clk); +	} +	if (udc->done) +		complete(udc->done);  	kfree(udc); -	udc = NULL;  }  static int @@ -2627,6 +2642,7 @@ omap_udc_setup(struct platform_device *odev, struct usb_phy *xceiv)  	udc->gadget.speed = USB_SPEED_UNKNOWN;  	udc->gadget.max_speed = USB_SPEED_FULL;  	udc->gadget.name = driver_name; +	udc->gadget.quirk_ep_out_aligned_size = 1;  	udc->transceiver = xceiv;  	/* ep0 is special; put it right after the SETUP buffer */ @@ -2867,8 +2883,8 @@ bad_on_1710:  		udc->clr_halt = UDC_RESET_EP;  	/* USB general purpose IRQ:  ep0, state changes, dma, etc */ -	status = request_irq(pdev->resource[1].start, omap_udc_irq, -			0, driver_name, udc); +	status = devm_request_irq(&pdev->dev, pdev->resource[1].start, +				  omap_udc_irq, 0, driver_name, udc);  	if (status != 0) {  		ERR("can't get irq %d, err %d\n",  			(int) pdev->resource[1].start, status); @@ -2876,20 +2892,20 @@ bad_on_1710:  	}  	/* USB "non-iso" IRQ (PIO for all but ep0) */ -	status = request_irq(pdev->resource[2].start, omap_udc_pio_irq, -			0, "omap_udc pio", udc); +	status = devm_request_irq(&pdev->dev, pdev->resource[2].start, +				  omap_udc_pio_irq, 0, "omap_udc pio", udc);  	if (status != 0) {  		ERR("can't get irq %d, err %d\n",  			(int) pdev->resource[2].start, status); -		goto cleanup2; +		goto cleanup1;  	}  #ifdef	USE_ISO -	status = request_irq(pdev->resource[3].start, omap_udc_iso_irq, -			0, "omap_udc iso", udc); +	status = devm_request_irq(&pdev->dev, pdev->resource[3].start, +				  omap_udc_iso_irq, 0, "omap_udc iso", udc);  	if (status != 0) {  		ERR("can't get irq %d, err %d\n",  			(int) pdev->resource[3].start, status); -		goto cleanup3; +		goto cleanup1;  	}  #endif  	if (cpu_is_omap16xx() || cpu_is_omap7xx()) { @@ -2900,23 +2916,8 @@ bad_on_1710:  	}  	create_proc_file(); -	status = usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, -			omap_udc_release); -	if (status) -		goto cleanup4; - -	return 0; - -cleanup4: -	remove_proc_file(); - -#ifdef	USE_ISO -cleanup3: -	free_irq(pdev->resource[2].start, udc); -#endif - -cleanup2: -	free_irq(pdev->resource[1].start, udc); +	return usb_add_gadget_udc_release(&pdev->dev, &udc->gadget, +					  omap_udc_release);  cleanup1:  	kfree(udc); @@ -2943,42 +2944,15 @@ static int omap_udc_remove(struct platform_device *pdev)  {  	DECLARE_COMPLETION_ONSTACK(done); -	if (!udc) -		return -ENODEV; - -	usb_del_gadget_udc(&udc->gadget); -	if (udc->driver) -		return -EBUSY; -  	udc->done = &done; -	pullup_disable(udc); -	if (!IS_ERR_OR_NULL(udc->transceiver)) { -		usb_put_phy(udc->transceiver); -		udc->transceiver = NULL; -	} -	omap_writew(0, UDC_SYSCON1); - -	remove_proc_file(); - -#ifdef	USE_ISO -	free_irq(pdev->resource[3].start, udc); -#endif -	free_irq(pdev->resource[2].start, udc); -	free_irq(pdev->resource[1].start, udc); +	usb_del_gadget_udc(&udc->gadget); -	if (udc->dc_clk) { -		if (udc->clk_requested) -			omap_udc_enable_clock(0); -		clk_put(udc->hhc_clk); -		clk_put(udc->dc_clk); -	} +	wait_for_completion(&done);  	release_mem_region(pdev->resource[0].start,  			pdev->resource[0].end - pdev->resource[0].start + 1); -	wait_for_completion(&done); -  	return 0;  } 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 */ diff --git a/drivers/usb/storage/unusual_realtek.h b/drivers/usb/storage/unusual_realtek.h index d17cd95b55bb..6b2140f966ef 100644 --- a/drivers/usb/storage/unusual_realtek.h +++ b/drivers/usb/storage/unusual_realtek.h @@ -27,4 +27,14 @@ UNUSUAL_DEV(0x0bda, 0x0159, 0x0000, 0x9999,  		"USB Card Reader",  		USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), +UNUSUAL_DEV(0x0bda, 0x0177, 0x0000, 0x9999, +		"Realtek", +		"USB Card Reader", +		USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), + +UNUSUAL_DEV(0x0bda, 0x0184, 0x0000, 0x9999, +		"Realtek", +		"USB Card Reader", +		USB_SC_DEVICE, USB_PR_DEVICE, init_realtek_cr, 0), +  #endif  /* defined(CONFIG_USB_STORAGE_REALTEK) || ... */ diff --git a/drivers/usb/typec/ucsi/Kconfig b/drivers/usb/typec/ucsi/Kconfig index e36d6c73c4a4..78118883f96c 100644 --- a/drivers/usb/typec/ucsi/Kconfig +++ b/drivers/usb/typec/ucsi/Kconfig @@ -23,6 +23,16 @@ config TYPEC_UCSI  if TYPEC_UCSI +config UCSI_CCG +	tristate "UCSI Interface Driver for Cypress CCGx" +	depends on I2C +	help +	  This driver enables UCSI support on platforms that expose a +	  Cypress CCGx Type-C controller over I2C interface. + +	  To compile the driver as a module, choose M here: the module will be +	  called ucsi_ccg. +  config UCSI_ACPI  	tristate "UCSI ACPI Interface Driver"  	depends on ACPI diff --git a/drivers/usb/typec/ucsi/Makefile b/drivers/usb/typec/ucsi/Makefile index 7afbea512207..2f4900b26210 100644 --- a/drivers/usb/typec/ucsi/Makefile +++ b/drivers/usb/typec/ucsi/Makefile @@ -8,3 +8,5 @@ typec_ucsi-y			:= ucsi.o  typec_ucsi-$(CONFIG_TRACING)	+= trace.o  obj-$(CONFIG_UCSI_ACPI)		+= ucsi_acpi.o + +obj-$(CONFIG_UCSI_CCG)		+= ucsi_ccg.o diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c new file mode 100644 index 000000000000..de8a43bdff68 --- /dev/null +++ b/drivers/usb/typec/ucsi/ucsi_ccg.c @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * UCSI driver for Cypress CCGx Type-C controller + * + * Copyright (C) 2017-2018 NVIDIA Corporation. All rights reserved. + * Author: Ajay Gupta <ajayg@nvidia.com> + * + * Some code borrowed from drivers/usb/typec/ucsi/ucsi_acpi.c + */ +#include <linux/acpi.h> +#include <linux/delay.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/pci.h> +#include <linux/platform_device.h> + +#include <asm/unaligned.h> +#include "ucsi.h" + +struct ucsi_ccg { +	struct device *dev; +	struct ucsi *ucsi; +	struct ucsi_ppm ppm; +	struct i2c_client *client; +}; + +#define CCGX_RAB_INTR_REG			0x06 +#define CCGX_RAB_UCSI_CONTROL			0x39 +#define CCGX_RAB_UCSI_CONTROL_START		BIT(0) +#define CCGX_RAB_UCSI_CONTROL_STOP		BIT(1) +#define CCGX_RAB_UCSI_DATA_BLOCK(offset)	(0xf000 | ((offset) & 0xff)) + +static int ccg_read(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len) +{ +	struct i2c_client *client = uc->client; +	const struct i2c_adapter_quirks *quirks = client->adapter->quirks; +	unsigned char buf[2]; +	struct i2c_msg msgs[] = { +		{ +			.addr	= client->addr, +			.flags  = 0x0, +			.len	= sizeof(buf), +			.buf	= buf, +		}, +		{ +			.addr	= client->addr, +			.flags  = I2C_M_RD, +			.buf	= data, +		}, +	}; +	u32 rlen, rem_len = len, max_read_len = len; +	int status; + +	/* check any max_read_len limitation on i2c adapter */ +	if (quirks && quirks->max_read_len) +		max_read_len = quirks->max_read_len; + +	while (rem_len > 0) { +		msgs[1].buf = &data[len - rem_len]; +		rlen = min_t(u16, rem_len, max_read_len); +		msgs[1].len = rlen; +		put_unaligned_le16(rab, buf); +		status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); +		if (status < 0) { +			dev_err(uc->dev, "i2c_transfer failed %d\n", status); +			return status; +		} +		rab += rlen; +		rem_len -= rlen; +	} + +	return 0; +} + +static int ccg_write(struct ucsi_ccg *uc, u16 rab, u8 *data, u32 len) +{ +	struct i2c_client *client = uc->client; +	unsigned char *buf; +	struct i2c_msg msgs[] = { +		{ +			.addr	= client->addr, +			.flags  = 0x0, +		} +	}; +	int status; + +	buf = kzalloc(len + sizeof(rab), GFP_KERNEL); +	if (!buf) +		return -ENOMEM; + +	put_unaligned_le16(rab, buf); +	memcpy(buf + sizeof(rab), data, len); + +	msgs[0].len = len + sizeof(rab); +	msgs[0].buf = buf; + +	status = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); +	if (status < 0) { +		dev_err(uc->dev, "i2c_transfer failed %d\n", status); +		kfree(buf); +		return status; +	} + +	kfree(buf); +	return 0; +} + +static int ucsi_ccg_init(struct ucsi_ccg *uc) +{ +	unsigned int count = 10; +	u8 data; +	int status; + +	data = CCGX_RAB_UCSI_CONTROL_STOP; +	status = ccg_write(uc, CCGX_RAB_UCSI_CONTROL, &data, sizeof(data)); +	if (status < 0) +		return status; + +	data = CCGX_RAB_UCSI_CONTROL_START; +	status = ccg_write(uc, CCGX_RAB_UCSI_CONTROL, &data, sizeof(data)); +	if (status < 0) +		return status; + +	/* +	 * Flush CCGx RESPONSE queue by acking interrupts. Above ucsi control +	 * register write will push response which must be cleared. +	 */ +	do { +		status = ccg_read(uc, CCGX_RAB_INTR_REG, &data, sizeof(data)); +		if (status < 0) +			return status; + +		if (!data) +			return 0; + +		status = ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data)); +		if (status < 0) +			return status; + +		usleep_range(10000, 11000); +	} while (--count); + +	return -ETIMEDOUT; +} + +static int ucsi_ccg_send_data(struct ucsi_ccg *uc) +{ +	u8 *ppm = (u8 *)uc->ppm.data; +	int status; +	u16 rab; + +	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_out)); +	status = ccg_write(uc, rab, ppm + +			   offsetof(struct ucsi_data, message_out), +			   sizeof(uc->ppm.data->message_out)); +	if (status < 0) +		return status; + +	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, ctrl)); +	return ccg_write(uc, rab, ppm + offsetof(struct ucsi_data, ctrl), +			 sizeof(uc->ppm.data->ctrl)); +} + +static int ucsi_ccg_recv_data(struct ucsi_ccg *uc) +{ +	u8 *ppm = (u8 *)uc->ppm.data; +	int status; +	u16 rab; + +	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, cci)); +	status = ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, cci), +			  sizeof(uc->ppm.data->cci)); +	if (status < 0) +		return status; + +	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, message_in)); +	return ccg_read(uc, rab, ppm + offsetof(struct ucsi_data, message_in), +			sizeof(uc->ppm.data->message_in)); +} + +static int ucsi_ccg_ack_interrupt(struct ucsi_ccg *uc) +{ +	int status; +	unsigned char data; + +	status = ccg_read(uc, CCGX_RAB_INTR_REG, &data, sizeof(data)); +	if (status < 0) +		return status; + +	return ccg_write(uc, CCGX_RAB_INTR_REG, &data, sizeof(data)); +} + +static int ucsi_ccg_sync(struct ucsi_ppm *ppm) +{ +	struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm); +	int status; + +	status = ucsi_ccg_recv_data(uc); +	if (status < 0) +		return status; + +	/* ack interrupt to allow next command to run */ +	return ucsi_ccg_ack_interrupt(uc); +} + +static int ucsi_ccg_cmd(struct ucsi_ppm *ppm, struct ucsi_control *ctrl) +{ +	struct ucsi_ccg *uc = container_of(ppm, struct ucsi_ccg, ppm); + +	ppm->data->ctrl.raw_cmd = ctrl->raw_cmd; +	return ucsi_ccg_send_data(uc); +} + +static irqreturn_t ccg_irq_handler(int irq, void *data) +{ +	struct ucsi_ccg *uc = data; + +	ucsi_notify(uc->ucsi); + +	return IRQ_HANDLED; +} + +static int ucsi_ccg_probe(struct i2c_client *client, +			  const struct i2c_device_id *id) +{ +	struct device *dev = &client->dev; +	struct ucsi_ccg *uc; +	int status; +	u16 rab; + +	uc = devm_kzalloc(dev, sizeof(*uc), GFP_KERNEL); +	if (!uc) +		return -ENOMEM; + +	uc->ppm.data = devm_kzalloc(dev, sizeof(struct ucsi_data), GFP_KERNEL); +	if (!uc->ppm.data) +		return -ENOMEM; + +	uc->ppm.cmd = ucsi_ccg_cmd; +	uc->ppm.sync = ucsi_ccg_sync; +	uc->dev = dev; +	uc->client = client; + +	/* reset ccg device and initialize ucsi */ +	status = ucsi_ccg_init(uc); +	if (status < 0) { +		dev_err(uc->dev, "ucsi_ccg_init failed - %d\n", status); +		return status; +	} + +	status = devm_request_threaded_irq(dev, client->irq, NULL, +					   ccg_irq_handler, +					   IRQF_ONESHOT | IRQF_TRIGGER_HIGH, +					   dev_name(dev), uc); +	if (status < 0) { +		dev_err(uc->dev, "request_threaded_irq failed - %d\n", status); +		return status; +	} + +	uc->ucsi = ucsi_register_ppm(dev, &uc->ppm); +	if (IS_ERR(uc->ucsi)) { +		dev_err(uc->dev, "ucsi_register_ppm failed\n"); +		return PTR_ERR(uc->ucsi); +	} + +	rab = CCGX_RAB_UCSI_DATA_BLOCK(offsetof(struct ucsi_data, version)); +	status = ccg_read(uc, rab, (u8 *)(uc->ppm.data) + +			  offsetof(struct ucsi_data, version), +			  sizeof(uc->ppm.data->version)); +	if (status < 0) { +		ucsi_unregister_ppm(uc->ucsi); +		return status; +	} + +	i2c_set_clientdata(client, uc); +	return 0; +} + +static int ucsi_ccg_remove(struct i2c_client *client) +{ +	struct ucsi_ccg *uc = i2c_get_clientdata(client); + +	ucsi_unregister_ppm(uc->ucsi); + +	return 0; +} + +static const struct i2c_device_id ucsi_ccg_device_id[] = { +	{"ccgx-ucsi", 0}, +	{} +}; +MODULE_DEVICE_TABLE(i2c, ucsi_ccg_device_id); + +static struct i2c_driver ucsi_ccg_driver = { +	.driver = { +		.name = "ucsi_ccg", +	}, +	.probe = ucsi_ccg_probe, +	.remove = ucsi_ccg_remove, +	.id_table = ucsi_ccg_device_id, +}; + +module_i2c_driver(ucsi_ccg_driver); + +MODULE_AUTHOR("Ajay Gupta <ajayg@nvidia.com>"); +MODULE_DESCRIPTION("UCSI driver for Cypress CCGx Type-C controller"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/xen/balloon.c b/drivers/xen/balloon.c index fdfc64f5acea..221b7333d067 100644 --- a/drivers/xen/balloon.c +++ b/drivers/xen/balloon.c @@ -251,25 +251,10 @@ static void release_memory_resource(struct resource *resource)  	kfree(resource);  } -/* - * Host memory not allocated to dom0. We can use this range for hotplug-based - * ballooning. - * - * It's a type-less resource. Setting IORESOURCE_MEM will make resource - * management algorithms (arch_remove_reservations()) look into guest e820, - * which we don't want. - */ -static struct resource hostmem_resource = { -	.name   = "Host RAM", -}; - -void __attribute__((weak)) __init arch_xen_balloon_init(struct resource *res) -{} -  static struct resource *additional_memory_resource(phys_addr_t size)  { -	struct resource *res, *res_hostmem; -	int ret = -ENOMEM; +	struct resource *res; +	int ret;  	res = kzalloc(sizeof(*res), GFP_KERNEL);  	if (!res) @@ -278,42 +263,13 @@ static struct resource *additional_memory_resource(phys_addr_t size)  	res->name = "System RAM";  	res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY; -	res_hostmem = kzalloc(sizeof(*res), GFP_KERNEL); -	if (res_hostmem) { -		/* Try to grab a range from hostmem */ -		res_hostmem->name = "Host memory"; -		ret = allocate_resource(&hostmem_resource, res_hostmem, -					size, 0, -1, -					PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL); -	} - -	if (!ret) { -		/* -		 * Insert this resource into iomem. Because hostmem_resource -		 * tracks portion of guest e820 marked as UNUSABLE noone else -		 * should try to use it. -		 */ -		res->start = res_hostmem->start; -		res->end = res_hostmem->end; -		ret = insert_resource(&iomem_resource, res); -		if (ret < 0) { -			pr_err("Can't insert iomem_resource [%llx - %llx]\n", -				res->start, res->end); -			release_memory_resource(res_hostmem); -			res_hostmem = NULL; -			res->start = res->end = 0; -		} -	} - -	if (ret) { -		ret = allocate_resource(&iomem_resource, res, -					size, 0, -1, -					PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL); -		if (ret < 0) { -			pr_err("Cannot allocate new System RAM resource\n"); -			kfree(res); -			return NULL; -		} +	ret = allocate_resource(&iomem_resource, res, +				size, 0, -1, +				PAGES_PER_SECTION * PAGE_SIZE, NULL, NULL); +	if (ret < 0) { +		pr_err("Cannot allocate new System RAM resource\n"); +		kfree(res); +		return NULL;  	}  #ifdef CONFIG_SPARSEMEM @@ -325,7 +281,6 @@ static struct resource *additional_memory_resource(phys_addr_t size)  			pr_err("New System RAM resource outside addressable RAM (%lu > %lu)\n",  			       pfn, limit);  			release_memory_resource(res); -			release_memory_resource(res_hostmem);  			return NULL;  		}  	} @@ -750,8 +705,6 @@ static int __init balloon_init(void)  	set_online_page_callback(&xen_online_page);  	register_memory_notifier(&xen_memory_nb);  	register_sysctl_table(xen_root); - -	arch_xen_balloon_init(&hostmem_resource);  #endif  #ifdef CONFIG_XEN_PV diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index f15f89df1f36..7ea6fb6a2e5d 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -914,7 +914,7 @@ int gnttab_dma_free_pages(struct gnttab_dma_alloc_args *args)  	ret = xenmem_reservation_increase(args->nr_pages, args->frames);  	if (ret != args->nr_pages) { -		pr_debug("Failed to decrease reservation for DMA buffer\n"); +		pr_debug("Failed to increase reservation for DMA buffer\n");  		ret = -EFAULT;  	} else {  		ret = 0; diff --git a/drivers/xen/privcmd-buf.c b/drivers/xen/privcmd-buf.c index df1ed37c3269..de01a6d0059d 100644 --- a/drivers/xen/privcmd-buf.c +++ b/drivers/xen/privcmd-buf.c @@ -21,15 +21,9 @@  MODULE_LICENSE("GPL"); -static unsigned int limit = 64; -module_param(limit, uint, 0644); -MODULE_PARM_DESC(limit, "Maximum number of pages that may be allocated by " -			"the privcmd-buf device per open file"); -  struct privcmd_buf_private {  	struct mutex lock;  	struct list_head list; -	unsigned int allocated;  };  struct privcmd_buf_vma_private { @@ -60,13 +54,10 @@ static void privcmd_buf_vmapriv_free(struct privcmd_buf_vma_private *vma_priv)  {  	unsigned int i; -	vma_priv->file_priv->allocated -= vma_priv->n_pages; -  	list_del(&vma_priv->list);  	for (i = 0; i < vma_priv->n_pages; i++) -		if (vma_priv->pages[i]) -			__free_page(vma_priv->pages[i]); +		__free_page(vma_priv->pages[i]);  	kfree(vma_priv);  } @@ -146,8 +137,7 @@ static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma)  	unsigned int i;  	int ret = 0; -	if (!(vma->vm_flags & VM_SHARED) || count > limit || -	    file_priv->allocated + count > limit) +	if (!(vma->vm_flags & VM_SHARED))  		return -EINVAL;  	vma_priv = kzalloc(sizeof(*vma_priv) + count * sizeof(void *), @@ -155,19 +145,15 @@ static int privcmd_buf_mmap(struct file *file, struct vm_area_struct *vma)  	if (!vma_priv)  		return -ENOMEM; -	vma_priv->n_pages = count; -	count = 0; -	for (i = 0; i < vma_priv->n_pages; i++) { +	for (i = 0; i < count; i++) {  		vma_priv->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);  		if (!vma_priv->pages[i])  			break; -		count++; +		vma_priv->n_pages++;  	}  	mutex_lock(&file_priv->lock); -	file_priv->allocated += count; -  	vma_priv->file_priv = file_priv;  	vma_priv->users = 1; diff --git a/drivers/xen/pvcalls-front.c b/drivers/xen/pvcalls-front.c index 2f11ca72a281..77224d8f3e6f 100644 --- a/drivers/xen/pvcalls-front.c +++ b/drivers/xen/pvcalls-front.c @@ -385,8 +385,8 @@ static int create_active(struct sock_mapping *map, int *evtchn)  out_error:  	if (*evtchn >= 0)  		xenbus_free_evtchn(pvcalls_front_dev, *evtchn); -	kfree(map->active.data.in); -	kfree(map->active.ring); +	free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER); +	free_page((unsigned long)map->active.ring);  	return ret;  } diff --git a/drivers/xen/xlate_mmu.c b/drivers/xen/xlate_mmu.c index 23f1387b3ef7..e7df65d32c91 100644 --- a/drivers/xen/xlate_mmu.c +++ b/drivers/xen/xlate_mmu.c @@ -36,6 +36,7 @@  #include <asm/xen/hypervisor.h>  #include <xen/xen.h> +#include <xen/xen-ops.h>  #include <xen/page.h>  #include <xen/interface/xen.h>  #include <xen/interface/memory.h>  | 

