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
|
@ -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)
|
||||||
{
|
{
|
||||||
if (t->buffer)
|
struct binder_proc *target_proc = t->to_proc;
|
||||||
t->buffer->transaction = NULL;
|
|
||||||
|
if (target_proc) {
|
||||||
|
binder_inner_proc_lock(target_proc);
|
||||||
|
if (t->buffer)
|
||||||
|
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 @@ err_invalid_target_handle:
|
||||||
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,7 +814,8 @@ static int do_bank_switch(struct sdw_stream_runtime *stream)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&bus->msg_lock);
|
if (bus->multi_link)
|
||||||
|
mutex_unlock(&bus->msg_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -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 New Issue