thunderbolt: Populate PG field in hot plug acknowledgment packet
USB4 1.0 section 6.4.2.7 specifies a new field (PG) in notification packet that is sent as response of hot plug/unplug events. This field tells whether the acknowledgment is for plug or unplug event. This needs to be set accordingly in order the router to send further hot plug notifications. To make it simpler we fill the field unconditionally. Legacy devices do not look at this field so there should be no problems with them. While there rename tb_cfg_error() to tb_cfg_ack_plug() and update the log message accordingly. The function is only used to ack plug/unplug events. Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com> Link: https://lore.kernel.org/r/20191217123345.31850-4-mika.westerberg@linux.intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
4deb200d34
commit
210e9f56e9
|
@ -708,19 +708,26 @@ void tb_ctl_stop(struct tb_ctl *ctl)
|
|||
/* public interface, commands */
|
||||
|
||||
/**
|
||||
* tb_cfg_error() - send error packet
|
||||
* tb_cfg_ack_plug() - Ack hot plug/unplug event
|
||||
* @ctl: Control channel to use
|
||||
* @route: Router that originated the event
|
||||
* @port: Port where the hot plug/unplug happened
|
||||
* @unplug: Ack hot plug or unplug
|
||||
*
|
||||
* Return: Returns 0 on success or an error code on failure.
|
||||
* Call this as response for hot plug/unplug event to ack it.
|
||||
* Returns %0 on success or an error code on failure.
|
||||
*/
|
||||
int tb_cfg_error(struct tb_ctl *ctl, u64 route, u32 port,
|
||||
enum tb_cfg_error error)
|
||||
int tb_cfg_ack_plug(struct tb_ctl *ctl, u64 route, u32 port, bool unplug)
|
||||
{
|
||||
struct cfg_error_pkg pkg = {
|
||||
.header = tb_cfg_make_header(route),
|
||||
.port = port,
|
||||
.error = error,
|
||||
.error = TB_CFG_ERROR_ACK_PLUG_EVENT,
|
||||
.pg = unplug ? TB_CFG_ERROR_PG_HOT_UNPLUG
|
||||
: TB_CFG_ERROR_PG_HOT_PLUG,
|
||||
};
|
||||
tb_ctl_dbg(ctl, "resetting error on %llx:%x.\n", route, port);
|
||||
tb_ctl_dbg(ctl, "acking hot %splug event on %llx:%x\n",
|
||||
unplug ? "un" : "", route, port);
|
||||
return tb_ctl_tx(ctl, &pkg, sizeof(pkg), TB_CFG_PKG_ERROR);
|
||||
}
|
||||
|
||||
|
|
|
@ -123,8 +123,7 @@ static inline struct tb_cfg_header tb_cfg_make_header(u64 route)
|
|||
return header;
|
||||
}
|
||||
|
||||
int tb_cfg_error(struct tb_ctl *ctl, u64 route, u32 port,
|
||||
enum tb_cfg_error error);
|
||||
int tb_cfg_ack_plug(struct tb_ctl *ctl, u64 route, u32 port, bool unplug);
|
||||
struct tb_cfg_result tb_cfg_reset(struct tb_ctl *ctl, u64 route,
|
||||
int timeout_msec);
|
||||
struct tb_cfg_result tb_cfg_read_raw(struct tb_ctl *ctl, void *buffer,
|
||||
|
|
|
@ -768,8 +768,7 @@ static void tb_handle_event(struct tb *tb, enum tb_cfg_pkg_type type,
|
|||
|
||||
route = tb_cfg_get_route(&pkg->header);
|
||||
|
||||
if (tb_cfg_error(tb->ctl, route, pkg->port,
|
||||
TB_CFG_ERROR_ACK_PLUG_EVENT)) {
|
||||
if (tb_cfg_ack_plug(tb->ctl, route, pkg->port, pkg->unplug)) {
|
||||
tb_warn(tb, "could not ack plug event on %llx:%x\n", route,
|
||||
pkg->port);
|
||||
}
|
||||
|
|
|
@ -67,9 +67,13 @@ struct cfg_error_pkg {
|
|||
u32 zero1:4;
|
||||
u32 port:6;
|
||||
u32 zero2:2; /* Both should be zero, still they are different fields. */
|
||||
u32 zero3:16;
|
||||
u32 zero3:14;
|
||||
u32 pg:2;
|
||||
} __packed;
|
||||
|
||||
#define TB_CFG_ERROR_PG_HOT_PLUG 0x2
|
||||
#define TB_CFG_ERROR_PG_HOT_UNPLUG 0x3
|
||||
|
||||
/* TB_CFG_PKG_EVENT */
|
||||
struct cfg_event_pkg {
|
||||
struct tb_cfg_header header;
|
||||
|
|
Loading…
Reference in New Issue