mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	Char/Misc driver fixes for 5.2-rc6
Here are a number of small driver fixes for 5.2-rc6 Nothing major, just fixes for reported issues: - soundwire fixes - thunderbolt fixes - MAINTAINERS update for fpga maintainer change - binder bugfix - habanalabs 64bit pointer fix - documentation updates All of these have been in linux-next with no reported issues. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> -----BEGIN PGP SIGNATURE----- iG0EABECAC0WIQT0tgzFv3jCIUoxPcsxR9QN2y37KQUCXQyOkg8cZ3JlZ0Brcm9h aC5jb20ACgkQMUfUDdst+yljIgCfbK0RWqIOa4esqlpUi2+71yM89M8AmQFLdOck gYJS7F+8cXeGEsveqAn2 =4ujv -----END PGP SIGNATURE----- Merge tag 'char-misc-5.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc Pull char/misc driver fixes from Greg KH: "Here are a number of small driver fixes for 5.2-rc6 Nothing major, just fixes for reported issues: - soundwire fixes - thunderbolt fixes - MAINTAINERS update for fpga maintainer change - binder bugfix - habanalabs 64bit pointer fix - documentation updates All of these have been in linux-next with no reported issues" * tag 'char-misc-5.2-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/char-misc: habanalabs: use u64_to_user_ptr() for reading user pointers doc: fix documentation about UIO_MEM_LOGICAL using MAINTAINERS / Documentation: Thorsten Scherer is the successor of Gavin Schenk docs: fb: Add TER16x32 to the available font names MAINTAINERS: fpga: hand off maintainership to Moritz thunderbolt: Implement CIO reset correctly for Titan Ridge binder: fix possible UAF when freeing buffer thunderbolt: Make sure device runtime resume completes before taking domain lock soundwire: intel: set dai min and max channels correctly soundwire: stream: fix bad unlock balance soundwire: stream: fix out of boundary access on port properties
This commit is contained in:
		
						commit
						b7b8a44f3a
					
				
					 11 changed files with 202 additions and 98 deletions
				
			
		| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X/active
 | 
					What:		/sys/bus/siox/devices/siox-X/active
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		On reading represents the current state of the bus. If it
 | 
							On reading represents the current state of the bus. If it
 | 
				
			||||||
		contains a "0" the bus is stopped and connected devices are
 | 
							contains a "0" the bus is stopped and connected devices are
 | 
				
			||||||
| 
						 | 
					@ -12,7 +12,7 @@ Description:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X/device_add
 | 
					What:		/sys/bus/siox/devices/siox-X/device_add
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Write-only file. Write
 | 
							Write-only file. Write
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -27,13 +27,13 @@ Description:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X/device_remove
 | 
					What:		/sys/bus/siox/devices/siox-X/device_remove
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Write-only file. A single write removes the last device in the siox chain.
 | 
							Write-only file. A single write removes the last device in the siox chain.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X/poll_interval_ns
 | 
					What:		/sys/bus/siox/devices/siox-X/poll_interval_ns
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Defines the interval between two poll cycles in nano seconds.
 | 
							Defines the interval between two poll cycles in nano seconds.
 | 
				
			||||||
		Note this is rounded to jiffies on writing. On reading the current value
 | 
							Note this is rounded to jiffies on writing. On reading the current value
 | 
				
			||||||
| 
						 | 
					@ -41,33 +41,33 @@ Description:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X-Y/connected
 | 
					What:		/sys/bus/siox/devices/siox-X-Y/connected
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Read-only value. "0" means the Yth device on siox bus X isn't "connected" i.e.
 | 
							Read-only value. "0" means the Yth device on siox bus X isn't "connected" i.e.
 | 
				
			||||||
		communication with it is not ensured. "1" signals a working connection.
 | 
							communication with it is not ensured. "1" signals a working connection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X-Y/inbytes
 | 
					What:		/sys/bus/siox/devices/siox-X-Y/inbytes
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Read-only value reporting the inbytes value provided to siox-X/device_add
 | 
							Read-only value reporting the inbytes value provided to siox-X/device_add
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X-Y/status_errors
 | 
					What:		/sys/bus/siox/devices/siox-X-Y/status_errors
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Counts the number of time intervals when the read status byte doesn't yield the
 | 
							Counts the number of time intervals when the read status byte doesn't yield the
 | 
				
			||||||
		expected value.
 | 
							expected value.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X-Y/type
 | 
					What:		/sys/bus/siox/devices/siox-X-Y/type
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Read-only value reporting the type value provided to siox-X/device_add.
 | 
							Read-only value reporting the type value provided to siox-X/device_add.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X-Y/watchdog
 | 
					What:		/sys/bus/siox/devices/siox-X-Y/watchdog
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Read-only value reporting if the watchdog of the siox device is
 | 
							Read-only value reporting if the watchdog of the siox device is
 | 
				
			||||||
		active. "0" means the watchdog is not active and the device is expected to
 | 
							active. "0" means the watchdog is not active and the device is expected to
 | 
				
			||||||
| 
						 | 
					@ -75,13 +75,13 @@ Description:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X-Y/watchdog_errors
 | 
					What:		/sys/bus/siox/devices/siox-X-Y/watchdog_errors
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Read-only value reporting the number to time intervals when the
 | 
							Read-only value reporting the number to time intervals when the
 | 
				
			||||||
		watchdog was active.
 | 
							watchdog was active.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
What:		/sys/bus/siox/devices/siox-X-Y/outbytes
 | 
					What:		/sys/bus/siox/devices/siox-X-Y/outbytes
 | 
				
			||||||
KernelVersion:	4.16
 | 
					KernelVersion:	4.16
 | 
				
			||||||
Contact:	Gavin Schenk <g.schenk@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					Contact:	Thorsten Scherer <t.scherer@eckelmann.de>, Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
Description:
 | 
					Description:
 | 
				
			||||||
		Read-only value reporting the outbytes value provided to siox-X/device_add.
 | 
							Read-only value reporting the outbytes value provided to siox-X/device_add.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -276,8 +276,8 @@ fields of ``struct uio_mem``:
 | 
				
			||||||
-  ``int memtype``: Required if the mapping is used. Set this to
 | 
					-  ``int memtype``: Required if the mapping is used. Set this to
 | 
				
			||||||
   ``UIO_MEM_PHYS`` if you you have physical memory on your card to be
 | 
					   ``UIO_MEM_PHYS`` if you you have physical memory on your card to be
 | 
				
			||||||
   mapped. Use ``UIO_MEM_LOGICAL`` for logical memory (e.g. allocated
 | 
					   mapped. Use ``UIO_MEM_LOGICAL`` for logical memory (e.g. allocated
 | 
				
			||||||
   with :c:func:`kmalloc()`). There's also ``UIO_MEM_VIRTUAL`` for
 | 
					   with :c:func:`__get_free_pages()` but not kmalloc()). There's also
 | 
				
			||||||
   virtual memory.
 | 
					   ``UIO_MEM_VIRTUAL`` for virtual memory.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-  ``phys_addr_t addr``: Required if the mapping is used. Fill in the
 | 
					-  ``phys_addr_t addr``: Required if the mapping is used. Fill in the
 | 
				
			||||||
   address of your memory block. This address is the one that appears in
 | 
					   address of your memory block. This address is the one that appears in
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,7 +79,7 @@ C. Boot options
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        Select the initial font to use. The value 'name' can be any of the
 | 
					        Select the initial font to use. The value 'name' can be any of the
 | 
				
			||||||
        compiled-in fonts: 10x18, 6x10, 7x14, Acorn8x8, MINI4x6,
 | 
					        compiled-in fonts: 10x18, 6x10, 7x14, Acorn8x8, MINI4x6,
 | 
				
			||||||
        PEARL8x8, ProFont6x11, SUN12x22, SUN8x16, VGA8x16, VGA8x8.
 | 
					        PEARL8x8, ProFont6x11, SUN12x22, SUN8x16, TER16x32, VGA8x16, VGA8x8.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Note, not all drivers can handle font with widths not divisible by 8,
 | 
						Note, not all drivers can handle font with widths not divisible by 8,
 | 
				
			||||||
        such as vga16fb.
 | 
					        such as vga16fb.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6234,7 +6234,6 @@ F:	include/linux/ipmi-fru.h
 | 
				
			||||||
K:	fmc_d.*register
 | 
					K:	fmc_d.*register
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FPGA MANAGER FRAMEWORK
 | 
					FPGA MANAGER FRAMEWORK
 | 
				
			||||||
M:	Alan Tull <atull@kernel.org>
 | 
					 | 
				
			||||||
M:	Moritz Fischer <mdf@kernel.org>
 | 
					M:	Moritz Fischer <mdf@kernel.org>
 | 
				
			||||||
L:	linux-fpga@vger.kernel.org
 | 
					L:	linux-fpga@vger.kernel.org
 | 
				
			||||||
S:	Maintained
 | 
					S:	Maintained
 | 
				
			||||||
| 
						 | 
					@ -14404,7 +14403,7 @@ F:	lib/test_siphash.c
 | 
				
			||||||
F:	include/linux/siphash.h
 | 
					F:	include/linux/siphash.h
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SIOX
 | 
					SIOX
 | 
				
			||||||
M:	Gavin Schenk <g.schenk@eckelmann.de>
 | 
					M:	Thorsten Scherer <t.scherer@eckelmann.de>
 | 
				
			||||||
M:	Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
					M:	Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
 | 
				
			||||||
R:	Pengutronix Kernel Team <kernel@pengutronix.de>
 | 
					R:	Pengutronix Kernel Team <kernel@pengutronix.de>
 | 
				
			||||||
S:	Supported
 | 
					S:	Supported
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1941,8 +1941,18 @@ static void binder_free_txn_fixups(struct binder_transaction *t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void binder_free_transaction(struct binder_transaction *t)
 | 
					static void binder_free_transaction(struct binder_transaction *t)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct binder_proc *target_proc = t->to_proc;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (target_proc) {
 | 
				
			||||||
 | 
							binder_inner_proc_lock(target_proc);
 | 
				
			||||||
		if (t->buffer)
 | 
							if (t->buffer)
 | 
				
			||||||
			t->buffer->transaction = NULL;
 | 
								t->buffer->transaction = NULL;
 | 
				
			||||||
 | 
							binder_inner_proc_unlock(target_proc);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * If the transaction has no target_proc, then
 | 
				
			||||||
 | 
						 * t->buffer->transaction has already been cleared.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
	binder_free_txn_fixups(t);
 | 
						binder_free_txn_fixups(t);
 | 
				
			||||||
	kfree(t);
 | 
						kfree(t);
 | 
				
			||||||
	binder_stats_deleted(BINDER_STAT_TRANSACTION);
 | 
						binder_stats_deleted(BINDER_STAT_TRANSACTION);
 | 
				
			||||||
| 
						 | 
					@ -3551,10 +3561,12 @@ static void binder_transaction(struct binder_proc *proc,
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer)
 | 
					binder_free_buf(struct binder_proc *proc, struct binder_buffer *buffer)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						binder_inner_proc_lock(proc);
 | 
				
			||||||
	if (buffer->transaction) {
 | 
						if (buffer->transaction) {
 | 
				
			||||||
		buffer->transaction->buffer = NULL;
 | 
							buffer->transaction->buffer = NULL;
 | 
				
			||||||
		buffer->transaction = NULL;
 | 
							buffer->transaction = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						binder_inner_proc_unlock(proc);
 | 
				
			||||||
	if (buffer->async_transaction && buffer->target_node) {
 | 
						if (buffer->async_transaction && buffer->target_node) {
 | 
				
			||||||
		struct binder_node *buf_node;
 | 
							struct binder_node *buf_node;
 | 
				
			||||||
		struct binder_work *w;
 | 
							struct binder_work *w;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,7 +140,7 @@ static int debug_coresight(struct hl_device *hdev, struct hl_debug_args *args)
 | 
				
			||||||
	params->op = args->op;
 | 
						params->op = args->op;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (args->input_ptr && args->input_size) {
 | 
						if (args->input_ptr && args->input_size) {
 | 
				
			||||||
		input = memdup_user((const void __user *) args->input_ptr,
 | 
							input = memdup_user(u64_to_user_ptr(args->input_ptr),
 | 
				
			||||||
					args->input_size);
 | 
										args->input_size);
 | 
				
			||||||
		if (IS_ERR(input)) {
 | 
							if (IS_ERR(input)) {
 | 
				
			||||||
			rc = PTR_ERR(input);
 | 
								rc = PTR_ERR(input);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -715,8 +715,8 @@ static int intel_create_dai(struct sdw_cdns *cdns,
 | 
				
			||||||
				return -ENOMEM;
 | 
									return -ENOMEM;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			dais[i].playback.channels_min = 1;
 | 
								dais[i].capture.channels_min = 1;
 | 
				
			||||||
			dais[i].playback.channels_max = max_ch;
 | 
								dais[i].capture.channels_max = max_ch;
 | 
				
			||||||
			dais[i].capture.rates = SNDRV_PCM_RATE_48000;
 | 
								dais[i].capture.rates = SNDRV_PCM_RATE_48000;
 | 
				
			||||||
			dais[i].capture.formats = SNDRV_PCM_FMTBIT_S16_LE;
 | 
								dais[i].capture.formats = SNDRV_PCM_FMTBIT_S16_LE;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -814,6 +814,7 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
 | 
				
			||||||
			goto error;
 | 
								goto error;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (bus->multi_link)
 | 
				
			||||||
			mutex_unlock(&bus->msg_lock);
 | 
								mutex_unlock(&bus->msg_lock);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1406,9 +1407,7 @@ struct sdw_dpn_prop *sdw_get_slave_dpn_prop(struct sdw_slave *slave,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (i = 0; i < num_ports; i++) {
 | 
						for (i = 0; i < num_ports; i++) {
 | 
				
			||||||
		dpn_prop = &dpn_prop[i];
 | 
							if (dpn_prop[i].num == port_num)
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (dpn_prop->num == port_num)
 | 
					 | 
				
			||||||
			return &dpn_prop[i];
 | 
								return &dpn_prop[i];
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,6 +56,7 @@
 | 
				
			||||||
 * @max_boot_acl: Maximum number of preboot ACL entries (%0 if not supported)
 | 
					 * @max_boot_acl: Maximum number of preboot ACL entries (%0 if not supported)
 | 
				
			||||||
 * @rpm: Does the controller support runtime PM (RTD3)
 | 
					 * @rpm: Does the controller support runtime PM (RTD3)
 | 
				
			||||||
 * @is_supported: Checks if we can support ICM on this controller
 | 
					 * @is_supported: Checks if we can support ICM on this controller
 | 
				
			||||||
 | 
					 * @cio_reset: Trigger CIO reset
 | 
				
			||||||
 * @get_mode: Read and return the ICM firmware mode (optional)
 | 
					 * @get_mode: Read and return the ICM firmware mode (optional)
 | 
				
			||||||
 * @get_route: Find a route string for given switch
 | 
					 * @get_route: Find a route string for given switch
 | 
				
			||||||
 * @save_devices: Ask ICM to save devices to ACL when suspending (optional)
 | 
					 * @save_devices: Ask ICM to save devices to ACL when suspending (optional)
 | 
				
			||||||
| 
						 | 
					@ -74,6 +75,7 @@ struct icm {
 | 
				
			||||||
	bool safe_mode;
 | 
						bool safe_mode;
 | 
				
			||||||
	bool rpm;
 | 
						bool rpm;
 | 
				
			||||||
	bool (*is_supported)(struct tb *tb);
 | 
						bool (*is_supported)(struct tb *tb);
 | 
				
			||||||
 | 
						int (*cio_reset)(struct tb *tb);
 | 
				
			||||||
	int (*get_mode)(struct tb *tb);
 | 
						int (*get_mode)(struct tb *tb);
 | 
				
			||||||
	int (*get_route)(struct tb *tb, u8 link, u8 depth, u64 *route);
 | 
						int (*get_route)(struct tb *tb, u8 link, u8 depth, u64 *route);
 | 
				
			||||||
	void (*save_devices)(struct tb *tb);
 | 
						void (*save_devices)(struct tb *tb);
 | 
				
			||||||
| 
						 | 
					@ -166,6 +168,65 @@ static inline u64 get_parent_route(u64 route)
 | 
				
			||||||
	return depth ? route & ~(0xffULL << (depth - 1) * TB_ROUTE_SHIFT) : 0;
 | 
						return depth ? route & ~(0xffULL << (depth - 1) * TB_ROUTE_SHIFT) : 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int pci2cio_wait_completion(struct icm *icm, unsigned long timeout_msec)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						unsigned long end = jiffies + msecs_to_jiffies(timeout_msec);
 | 
				
			||||||
 | 
						u32 cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						do {
 | 
				
			||||||
 | 
							pci_read_config_dword(icm->upstream_port,
 | 
				
			||||||
 | 
									      icm->vnd_cap + PCIE2CIO_CMD, &cmd);
 | 
				
			||||||
 | 
							if (!(cmd & PCIE2CIO_CMD_START)) {
 | 
				
			||||||
 | 
								if (cmd & PCIE2CIO_CMD_TIMEOUT)
 | 
				
			||||||
 | 
									break;
 | 
				
			||||||
 | 
								return 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							msleep(50);
 | 
				
			||||||
 | 
						} while (time_before(jiffies, end));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return -ETIMEDOUT;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int pcie2cio_read(struct icm *icm, enum tb_cfg_space cs,
 | 
				
			||||||
 | 
								 unsigned int port, unsigned int index, u32 *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct pci_dev *pdev = icm->upstream_port;
 | 
				
			||||||
 | 
						int ret, vnd_cap = icm->vnd_cap;
 | 
				
			||||||
 | 
						u32 cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd = index;
 | 
				
			||||||
 | 
						cmd |= (port << PCIE2CIO_CMD_PORT_SHIFT) & PCIE2CIO_CMD_PORT_MASK;
 | 
				
			||||||
 | 
						cmd |= (cs << PCIE2CIO_CMD_CS_SHIFT) & PCIE2CIO_CMD_CS_MASK;
 | 
				
			||||||
 | 
						cmd |= PCIE2CIO_CMD_START;
 | 
				
			||||||
 | 
						pci_write_config_dword(pdev, vnd_cap + PCIE2CIO_CMD, cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ret = pci2cio_wait_completion(icm, 5000);
 | 
				
			||||||
 | 
						if (ret)
 | 
				
			||||||
 | 
							return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pci_read_config_dword(pdev, vnd_cap + PCIE2CIO_RDDATA, data);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int pcie2cio_write(struct icm *icm, enum tb_cfg_space cs,
 | 
				
			||||||
 | 
								  unsigned int port, unsigned int index, u32 data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct pci_dev *pdev = icm->upstream_port;
 | 
				
			||||||
 | 
						int vnd_cap = icm->vnd_cap;
 | 
				
			||||||
 | 
						u32 cmd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pci_write_config_dword(pdev, vnd_cap + PCIE2CIO_WRDATA, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmd = index;
 | 
				
			||||||
 | 
						cmd |= (port << PCIE2CIO_CMD_PORT_SHIFT) & PCIE2CIO_CMD_PORT_MASK;
 | 
				
			||||||
 | 
						cmd |= (cs << PCIE2CIO_CMD_CS_SHIFT) & PCIE2CIO_CMD_CS_MASK;
 | 
				
			||||||
 | 
						cmd |= PCIE2CIO_CMD_WRITE | PCIE2CIO_CMD_START;
 | 
				
			||||||
 | 
						pci_write_config_dword(pdev, vnd_cap + PCIE2CIO_CMD, cmd);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return pci2cio_wait_completion(icm, 5000);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool icm_match(const struct tb_cfg_request *req,
 | 
					static bool icm_match(const struct tb_cfg_request *req,
 | 
				
			||||||
		      const struct ctl_pkg *pkg)
 | 
							      const struct ctl_pkg *pkg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -484,6 +545,7 @@ static void add_switch(struct tb_switch *parent_sw, u64 route,
 | 
				
			||||||
	sw->authorized = authorized;
 | 
						sw->authorized = authorized;
 | 
				
			||||||
	sw->security_level = security_level;
 | 
						sw->security_level = security_level;
 | 
				
			||||||
	sw->boot = boot;
 | 
						sw->boot = boot;
 | 
				
			||||||
 | 
						init_completion(&sw->rpm_complete);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vss = parse_intel_vss(ep_name, ep_name_size);
 | 
						vss = parse_intel_vss(ep_name, ep_name_size);
 | 
				
			||||||
	if (vss)
 | 
						if (vss)
 | 
				
			||||||
| 
						 | 
					@ -523,6 +585,9 @@ static void update_switch(struct tb_switch *parent_sw, struct tb_switch *sw,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* This switch still exists */
 | 
						/* This switch still exists */
 | 
				
			||||||
	sw->is_unplugged = false;
 | 
						sw->is_unplugged = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Runtime resume is now complete */
 | 
				
			||||||
 | 
						complete(&sw->rpm_complete);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void remove_switch(struct tb_switch *sw)
 | 
					static void remove_switch(struct tb_switch *sw)
 | 
				
			||||||
| 
						 | 
					@ -834,6 +899,11 @@ icm_fr_xdomain_disconnected(struct tb *tb, const struct icm_pkg_header *hdr)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int icm_tr_cio_reset(struct tb *tb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return pcie2cio_write(tb_priv(tb), TB_CFG_SWITCH, 0, 0x777, BIT(1));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int
 | 
					static int
 | 
				
			||||||
icm_tr_driver_ready(struct tb *tb, enum tb_security_level *security_level,
 | 
					icm_tr_driver_ready(struct tb *tb, enum tb_security_level *security_level,
 | 
				
			||||||
		    size_t *nboot_acl, bool *rpm)
 | 
							    size_t *nboot_acl, bool *rpm)
 | 
				
			||||||
| 
						 | 
					@ -1240,6 +1310,11 @@ static bool icm_ar_is_supported(struct tb *tb)
 | 
				
			||||||
	return false;
 | 
						return false;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int icm_ar_cio_reset(struct tb *tb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return pcie2cio_write(tb_priv(tb), TB_CFG_SWITCH, 0, 0x50, BIT(9));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int icm_ar_get_mode(struct tb *tb)
 | 
					static int icm_ar_get_mode(struct tb *tb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct tb_nhi *nhi = tb->nhi;
 | 
						struct tb_nhi *nhi = tb->nhi;
 | 
				
			||||||
| 
						 | 
					@ -1477,65 +1552,6 @@ __icm_driver_ready(struct tb *tb, enum tb_security_level *security_level,
 | 
				
			||||||
	return -ETIMEDOUT;
 | 
						return -ETIMEDOUT;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int pci2cio_wait_completion(struct icm *icm, unsigned long timeout_msec)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	unsigned long end = jiffies + msecs_to_jiffies(timeout_msec);
 | 
					 | 
				
			||||||
	u32 cmd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	do {
 | 
					 | 
				
			||||||
		pci_read_config_dword(icm->upstream_port,
 | 
					 | 
				
			||||||
				      icm->vnd_cap + PCIE2CIO_CMD, &cmd);
 | 
					 | 
				
			||||||
		if (!(cmd & PCIE2CIO_CMD_START)) {
 | 
					 | 
				
			||||||
			if (cmd & PCIE2CIO_CMD_TIMEOUT)
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		msleep(50);
 | 
					 | 
				
			||||||
	} while (time_before(jiffies, end));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return -ETIMEDOUT;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int pcie2cio_read(struct icm *icm, enum tb_cfg_space cs,
 | 
					 | 
				
			||||||
			 unsigned int port, unsigned int index, u32 *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct pci_dev *pdev = icm->upstream_port;
 | 
					 | 
				
			||||||
	int ret, vnd_cap = icm->vnd_cap;
 | 
					 | 
				
			||||||
	u32 cmd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmd = index;
 | 
					 | 
				
			||||||
	cmd |= (port << PCIE2CIO_CMD_PORT_SHIFT) & PCIE2CIO_CMD_PORT_MASK;
 | 
					 | 
				
			||||||
	cmd |= (cs << PCIE2CIO_CMD_CS_SHIFT) & PCIE2CIO_CMD_CS_MASK;
 | 
					 | 
				
			||||||
	cmd |= PCIE2CIO_CMD_START;
 | 
					 | 
				
			||||||
	pci_write_config_dword(pdev, vnd_cap + PCIE2CIO_CMD, cmd);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	ret = pci2cio_wait_completion(icm, 5000);
 | 
					 | 
				
			||||||
	if (ret)
 | 
					 | 
				
			||||||
		return ret;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pci_read_config_dword(pdev, vnd_cap + PCIE2CIO_RDDATA, data);
 | 
					 | 
				
			||||||
	return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int pcie2cio_write(struct icm *icm, enum tb_cfg_space cs,
 | 
					 | 
				
			||||||
			  unsigned int port, unsigned int index, u32 data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	struct pci_dev *pdev = icm->upstream_port;
 | 
					 | 
				
			||||||
	int vnd_cap = icm->vnd_cap;
 | 
					 | 
				
			||||||
	u32 cmd;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pci_write_config_dword(pdev, vnd_cap + PCIE2CIO_WRDATA, data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cmd = index;
 | 
					 | 
				
			||||||
	cmd |= (port << PCIE2CIO_CMD_PORT_SHIFT) & PCIE2CIO_CMD_PORT_MASK;
 | 
					 | 
				
			||||||
	cmd |= (cs << PCIE2CIO_CMD_CS_SHIFT) & PCIE2CIO_CMD_CS_MASK;
 | 
					 | 
				
			||||||
	cmd |= PCIE2CIO_CMD_WRITE | PCIE2CIO_CMD_START;
 | 
					 | 
				
			||||||
	pci_write_config_dword(pdev, vnd_cap + PCIE2CIO_CMD, cmd);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return pci2cio_wait_completion(icm, 5000);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int icm_firmware_reset(struct tb *tb, struct tb_nhi *nhi)
 | 
					static int icm_firmware_reset(struct tb *tb, struct tb_nhi *nhi)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct icm *icm = tb_priv(tb);
 | 
						struct icm *icm = tb_priv(tb);
 | 
				
			||||||
| 
						 | 
					@ -1556,7 +1572,7 @@ static int icm_firmware_reset(struct tb *tb, struct tb_nhi *nhi)
 | 
				
			||||||
	iowrite32(val, nhi->iobase + REG_FW_STS);
 | 
						iowrite32(val, nhi->iobase + REG_FW_STS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Trigger CIO reset now */
 | 
						/* Trigger CIO reset now */
 | 
				
			||||||
	return pcie2cio_write(icm, TB_CFG_SWITCH, 0, 0x50, BIT(9));
 | 
						return icm->cio_reset(tb);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int icm_firmware_start(struct tb *tb, struct tb_nhi *nhi)
 | 
					static int icm_firmware_start(struct tb *tb, struct tb_nhi *nhi)
 | 
				
			||||||
| 
						 | 
					@ -1770,6 +1786,32 @@ static void icm_unplug_children(struct tb_switch *sw)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int complete_rpm(struct device *dev, void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct tb_switch *sw = tb_to_switch(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sw)
 | 
				
			||||||
 | 
							complete(&sw->rpm_complete);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void remove_unplugged_switch(struct tb_switch *sw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						pm_runtime_get_sync(sw->dev.parent);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*
 | 
				
			||||||
 | 
						 * Signal this and switches below for rpm_complete because
 | 
				
			||||||
 | 
						 * tb_switch_remove() calls pm_runtime_get_sync() that then waits
 | 
				
			||||||
 | 
						 * for it.
 | 
				
			||||||
 | 
						 */
 | 
				
			||||||
 | 
						complete_rpm(&sw->dev, NULL);
 | 
				
			||||||
 | 
						bus_for_each_dev(&tb_bus_type, &sw->dev, NULL, complete_rpm);
 | 
				
			||||||
 | 
						tb_switch_remove(sw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pm_runtime_mark_last_busy(sw->dev.parent);
 | 
				
			||||||
 | 
						pm_runtime_put_autosuspend(sw->dev.parent);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void icm_free_unplugged_children(struct tb_switch *sw)
 | 
					static void icm_free_unplugged_children(struct tb_switch *sw)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned int i;
 | 
						unsigned int i;
 | 
				
			||||||
| 
						 | 
					@ -1782,7 +1824,7 @@ static void icm_free_unplugged_children(struct tb_switch *sw)
 | 
				
			||||||
			port->xdomain = NULL;
 | 
								port->xdomain = NULL;
 | 
				
			||||||
		} else if (tb_port_has_remote(port)) {
 | 
							} else if (tb_port_has_remote(port)) {
 | 
				
			||||||
			if (port->remote->sw->is_unplugged) {
 | 
								if (port->remote->sw->is_unplugged) {
 | 
				
			||||||
				tb_switch_remove(port->remote->sw);
 | 
									remove_unplugged_switch(port->remote->sw);
 | 
				
			||||||
				port->remote = NULL;
 | 
									port->remote = NULL;
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				icm_free_unplugged_children(port->remote->sw);
 | 
									icm_free_unplugged_children(port->remote->sw);
 | 
				
			||||||
| 
						 | 
					@ -1831,6 +1873,24 @@ static int icm_runtime_suspend(struct tb *tb)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int icm_runtime_suspend_switch(struct tb_switch *sw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (tb_route(sw))
 | 
				
			||||||
 | 
							reinit_completion(&sw->rpm_complete);
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int icm_runtime_resume_switch(struct tb_switch *sw)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (tb_route(sw)) {
 | 
				
			||||||
 | 
							if (!wait_for_completion_timeout(&sw->rpm_complete,
 | 
				
			||||||
 | 
											 msecs_to_jiffies(500))) {
 | 
				
			||||||
 | 
								dev_dbg(&sw->dev, "runtime resuming timed out\n");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int icm_runtime_resume(struct tb *tb)
 | 
					static int icm_runtime_resume(struct tb *tb)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -1910,6 +1970,8 @@ static const struct tb_cm_ops icm_ar_ops = {
 | 
				
			||||||
	.complete = icm_complete,
 | 
						.complete = icm_complete,
 | 
				
			||||||
	.runtime_suspend = icm_runtime_suspend,
 | 
						.runtime_suspend = icm_runtime_suspend,
 | 
				
			||||||
	.runtime_resume = icm_runtime_resume,
 | 
						.runtime_resume = icm_runtime_resume,
 | 
				
			||||||
 | 
						.runtime_suspend_switch = icm_runtime_suspend_switch,
 | 
				
			||||||
 | 
						.runtime_resume_switch = icm_runtime_resume_switch,
 | 
				
			||||||
	.handle_event = icm_handle_event,
 | 
						.handle_event = icm_handle_event,
 | 
				
			||||||
	.get_boot_acl = icm_ar_get_boot_acl,
 | 
						.get_boot_acl = icm_ar_get_boot_acl,
 | 
				
			||||||
	.set_boot_acl = icm_ar_set_boot_acl,
 | 
						.set_boot_acl = icm_ar_set_boot_acl,
 | 
				
			||||||
| 
						 | 
					@ -1930,6 +1992,8 @@ static const struct tb_cm_ops icm_tr_ops = {
 | 
				
			||||||
	.complete = icm_complete,
 | 
						.complete = icm_complete,
 | 
				
			||||||
	.runtime_suspend = icm_runtime_suspend,
 | 
						.runtime_suspend = icm_runtime_suspend,
 | 
				
			||||||
	.runtime_resume = icm_runtime_resume,
 | 
						.runtime_resume = icm_runtime_resume,
 | 
				
			||||||
 | 
						.runtime_suspend_switch = icm_runtime_suspend_switch,
 | 
				
			||||||
 | 
						.runtime_resume_switch = icm_runtime_resume_switch,
 | 
				
			||||||
	.handle_event = icm_handle_event,
 | 
						.handle_event = icm_handle_event,
 | 
				
			||||||
	.get_boot_acl = icm_ar_get_boot_acl,
 | 
						.get_boot_acl = icm_ar_get_boot_acl,
 | 
				
			||||||
	.set_boot_acl = icm_ar_set_boot_acl,
 | 
						.set_boot_acl = icm_ar_set_boot_acl,
 | 
				
			||||||
| 
						 | 
					@ -1975,6 +2039,7 @@ struct tb *icm_probe(struct tb_nhi *nhi)
 | 
				
			||||||
	case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_NHI:
 | 
						case PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_NHI:
 | 
				
			||||||
		icm->max_boot_acl = ICM_AR_PREBOOT_ACL_ENTRIES;
 | 
							icm->max_boot_acl = ICM_AR_PREBOOT_ACL_ENTRIES;
 | 
				
			||||||
		icm->is_supported = icm_ar_is_supported;
 | 
							icm->is_supported = icm_ar_is_supported;
 | 
				
			||||||
 | 
							icm->cio_reset = icm_ar_cio_reset;
 | 
				
			||||||
		icm->get_mode = icm_ar_get_mode;
 | 
							icm->get_mode = icm_ar_get_mode;
 | 
				
			||||||
		icm->get_route = icm_ar_get_route;
 | 
							icm->get_route = icm_ar_get_route;
 | 
				
			||||||
		icm->save_devices = icm_fr_save_devices;
 | 
							icm->save_devices = icm_fr_save_devices;
 | 
				
			||||||
| 
						 | 
					@ -1990,6 +2055,7 @@ struct tb *icm_probe(struct tb_nhi *nhi)
 | 
				
			||||||
	case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI:
 | 
						case PCI_DEVICE_ID_INTEL_TITAN_RIDGE_4C_NHI:
 | 
				
			||||||
		icm->max_boot_acl = ICM_AR_PREBOOT_ACL_ENTRIES;
 | 
							icm->max_boot_acl = ICM_AR_PREBOOT_ACL_ENTRIES;
 | 
				
			||||||
		icm->is_supported = icm_ar_is_supported;
 | 
							icm->is_supported = icm_ar_is_supported;
 | 
				
			||||||
 | 
							icm->cio_reset = icm_tr_cio_reset;
 | 
				
			||||||
		icm->get_mode = icm_ar_get_mode;
 | 
							icm->get_mode = icm_ar_get_mode;
 | 
				
			||||||
		icm->driver_ready = icm_tr_driver_ready;
 | 
							icm->driver_ready = icm_tr_driver_ready;
 | 
				
			||||||
		icm->device_connected = icm_tr_device_connected;
 | 
							icm->device_connected = icm_tr_device_connected;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -239,7 +239,16 @@ static int tb_switch_nvm_read(void *priv, unsigned int offset, void *val,
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pm_runtime_get_sync(&sw->dev);
 | 
						pm_runtime_get_sync(&sw->dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!mutex_trylock(&sw->tb->lock)) {
 | 
				
			||||||
 | 
							ret = restart_syscall();
 | 
				
			||||||
 | 
							goto out;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = dma_port_flash_read(sw->dma_port, offset, val, bytes);
 | 
						ret = dma_port_flash_read(sw->dma_port, offset, val, bytes);
 | 
				
			||||||
 | 
						mutex_unlock(&sw->tb->lock);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out:
 | 
				
			||||||
	pm_runtime_mark_last_busy(&sw->dev);
 | 
						pm_runtime_mark_last_busy(&sw->dev);
 | 
				
			||||||
	pm_runtime_put_autosuspend(&sw->dev);
 | 
						pm_runtime_put_autosuspend(&sw->dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1019,7 +1028,6 @@ static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val)
 | 
				
			||||||
	 * the new tunnel too early.
 | 
						 * the new tunnel too early.
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
	pci_lock_rescan_remove();
 | 
						pci_lock_rescan_remove();
 | 
				
			||||||
	pm_runtime_get_sync(&sw->dev);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (val) {
 | 
						switch (val) {
 | 
				
			||||||
	/* Approve switch */
 | 
						/* Approve switch */
 | 
				
			||||||
| 
						 | 
					@ -1040,8 +1048,6 @@ static int tb_switch_set_authorized(struct tb_switch *sw, unsigned int val)
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pm_runtime_mark_last_busy(&sw->dev);
 | 
					 | 
				
			||||||
	pm_runtime_put_autosuspend(&sw->dev);
 | 
					 | 
				
			||||||
	pci_unlock_rescan_remove();
 | 
						pci_unlock_rescan_remove();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!ret) {
 | 
						if (!ret) {
 | 
				
			||||||
| 
						 | 
					@ -1069,7 +1075,10 @@ static ssize_t authorized_store(struct device *dev,
 | 
				
			||||||
	if (val > 2)
 | 
						if (val > 2)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pm_runtime_get_sync(&sw->dev);
 | 
				
			||||||
	ret = tb_switch_set_authorized(sw, val);
 | 
						ret = tb_switch_set_authorized(sw, val);
 | 
				
			||||||
 | 
						pm_runtime_mark_last_busy(&sw->dev);
 | 
				
			||||||
 | 
						pm_runtime_put_autosuspend(&sw->dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret ? ret : count;
 | 
						return ret ? ret : count;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1195,8 +1204,12 @@ static ssize_t nvm_authenticate_store(struct device *dev,
 | 
				
			||||||
	bool val;
 | 
						bool val;
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!mutex_trylock(&sw->tb->lock))
 | 
						pm_runtime_get_sync(&sw->dev);
 | 
				
			||||||
		return restart_syscall();
 | 
					
 | 
				
			||||||
 | 
						if (!mutex_trylock(&sw->tb->lock)) {
 | 
				
			||||||
 | 
							ret = restart_syscall();
 | 
				
			||||||
 | 
							goto exit_rpm;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* If NVMem devices are not yet added */
 | 
						/* If NVMem devices are not yet added */
 | 
				
			||||||
	if (!sw->nvm) {
 | 
						if (!sw->nvm) {
 | 
				
			||||||
| 
						 | 
					@ -1217,13 +1230,9 @@ static ssize_t nvm_authenticate_store(struct device *dev,
 | 
				
			||||||
			goto exit_unlock;
 | 
								goto exit_unlock;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pm_runtime_get_sync(&sw->dev);
 | 
					 | 
				
			||||||
		ret = nvm_validate_and_write(sw);
 | 
							ret = nvm_validate_and_write(sw);
 | 
				
			||||||
		if (ret) {
 | 
							if (ret)
 | 
				
			||||||
			pm_runtime_mark_last_busy(&sw->dev);
 | 
					 | 
				
			||||||
			pm_runtime_put_autosuspend(&sw->dev);
 | 
					 | 
				
			||||||
			goto exit_unlock;
 | 
								goto exit_unlock;
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		sw->nvm->authenticating = true;
 | 
							sw->nvm->authenticating = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1239,12 +1248,13 @@ static ssize_t nvm_authenticate_store(struct device *dev,
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ret = nvm_authenticate_device(sw);
 | 
								ret = nvm_authenticate_device(sw);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		pm_runtime_mark_last_busy(&sw->dev);
 | 
					 | 
				
			||||||
		pm_runtime_put_autosuspend(&sw->dev);
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
exit_unlock:
 | 
					exit_unlock:
 | 
				
			||||||
	mutex_unlock(&sw->tb->lock);
 | 
						mutex_unlock(&sw->tb->lock);
 | 
				
			||||||
 | 
					exit_rpm:
 | 
				
			||||||
 | 
						pm_runtime_mark_last_busy(&sw->dev);
 | 
				
			||||||
 | 
						pm_runtime_put_autosuspend(&sw->dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ret)
 | 
						if (ret)
 | 
				
			||||||
		return ret;
 | 
							return ret;
 | 
				
			||||||
| 
						 | 
					@ -1380,11 +1390,22 @@ static void tb_switch_release(struct device *dev)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static int __maybe_unused tb_switch_runtime_suspend(struct device *dev)
 | 
					static int __maybe_unused tb_switch_runtime_suspend(struct device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct tb_switch *sw = tb_to_switch(dev);
 | 
				
			||||||
 | 
						const struct tb_cm_ops *cm_ops = sw->tb->cm_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cm_ops->runtime_suspend_switch)
 | 
				
			||||||
 | 
							return cm_ops->runtime_suspend_switch(sw);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int __maybe_unused tb_switch_runtime_resume(struct device *dev)
 | 
					static int __maybe_unused tb_switch_runtime_resume(struct device *dev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
						struct tb_switch *sw = tb_to_switch(dev);
 | 
				
			||||||
 | 
						const struct tb_cm_ops *cm_ops = sw->tb->cm_ops;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (cm_ops->runtime_resume_switch)
 | 
				
			||||||
 | 
							return cm_ops->runtime_resume_switch(sw);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,6 +79,8 @@ struct tb_switch_nvm {
 | 
				
			||||||
 * @connection_key: Connection key used with ICM messaging
 | 
					 * @connection_key: Connection key used with ICM messaging
 | 
				
			||||||
 * @link: Root switch link this switch is connected (ICM only)
 | 
					 * @link: Root switch link this switch is connected (ICM only)
 | 
				
			||||||
 * @depth: Depth in the chain this switch is connected (ICM only)
 | 
					 * @depth: Depth in the chain this switch is connected (ICM only)
 | 
				
			||||||
 | 
					 * @rpm_complete: Completion used to wait for runtime resume to
 | 
				
			||||||
 | 
					 *		  complete (ICM only)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * When the switch is being added or removed to the domain (other
 | 
					 * When the switch is being added or removed to the domain (other
 | 
				
			||||||
 * switches) you need to have domain lock held.
 | 
					 * switches) you need to have domain lock held.
 | 
				
			||||||
| 
						 | 
					@ -112,6 +114,7 @@ struct tb_switch {
 | 
				
			||||||
	u8 connection_key;
 | 
						u8 connection_key;
 | 
				
			||||||
	u8 link;
 | 
						u8 link;
 | 
				
			||||||
	u8 depth;
 | 
						u8 depth;
 | 
				
			||||||
 | 
						struct completion rpm_complete;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -250,6 +253,8 @@ struct tb_path {
 | 
				
			||||||
 * @complete: Connection manager specific complete
 | 
					 * @complete: Connection manager specific complete
 | 
				
			||||||
 * @runtime_suspend: Connection manager specific runtime_suspend
 | 
					 * @runtime_suspend: Connection manager specific runtime_suspend
 | 
				
			||||||
 * @runtime_resume: Connection manager specific runtime_resume
 | 
					 * @runtime_resume: Connection manager specific runtime_resume
 | 
				
			||||||
 | 
					 * @runtime_suspend_switch: Runtime suspend a switch
 | 
				
			||||||
 | 
					 * @runtime_resume_switch: Runtime resume a switch
 | 
				
			||||||
 * @handle_event: Handle thunderbolt event
 | 
					 * @handle_event: Handle thunderbolt event
 | 
				
			||||||
 * @get_boot_acl: Get boot ACL list
 | 
					 * @get_boot_acl: Get boot ACL list
 | 
				
			||||||
 * @set_boot_acl: Set boot ACL list
 | 
					 * @set_boot_acl: Set boot ACL list
 | 
				
			||||||
| 
						 | 
					@ -270,6 +275,8 @@ struct tb_cm_ops {
 | 
				
			||||||
	void (*complete)(struct tb *tb);
 | 
						void (*complete)(struct tb *tb);
 | 
				
			||||||
	int (*runtime_suspend)(struct tb *tb);
 | 
						int (*runtime_suspend)(struct tb *tb);
 | 
				
			||||||
	int (*runtime_resume)(struct tb *tb);
 | 
						int (*runtime_resume)(struct tb *tb);
 | 
				
			||||||
 | 
						int (*runtime_suspend_switch)(struct tb_switch *sw);
 | 
				
			||||||
 | 
						int (*runtime_resume_switch)(struct tb_switch *sw);
 | 
				
			||||||
	void (*handle_event)(struct tb *tb, enum tb_cfg_pkg_type,
 | 
						void (*handle_event)(struct tb *tb, enum tb_cfg_pkg_type,
 | 
				
			||||||
			     const void *buf, size_t size);
 | 
								     const void *buf, size_t size);
 | 
				
			||||||
	int (*get_boot_acl)(struct tb *tb, uuid_t *uuids, size_t nuuids);
 | 
						int (*get_boot_acl)(struct tb *tb, uuid_t *uuids, size_t nuuids);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue