From 748e4f3d702def1a4bff191e0cf93b6a05340f01 Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Fri, 10 May 2024 07:41:34 +0000
Subject: [PATCH] add gpio led uart
---
kernel/drivers/thunderbolt/ctl.c | 89 ++++++++++++++++++++++++++++++--------------
1 files changed, 61 insertions(+), 28 deletions(-)
diff --git a/kernel/drivers/thunderbolt/ctl.c b/kernel/drivers/thunderbolt/ctl.c
index 37a7f4c..772acb1 100644
--- a/kernel/drivers/thunderbolt/ctl.c
+++ b/kernel/drivers/thunderbolt/ctl.c
@@ -1,8 +1,9 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Thunderbolt Cactus Ridge driver - control channel and configuration commands
+ * Thunderbolt driver - control channel and configuration commands
*
* Copyright (c) 2014 Andreas Noever <andreas.noever@gmail.com>
+ * Copyright (C) 2018, Intel Corporation
*/
#include <linux/crc32.h>
@@ -218,6 +219,7 @@
static struct tb_cfg_result decode_error(const struct ctl_pkg *response)
{
struct cfg_error_pkg *pkg = response->buffer;
+ struct tb_ctl *ctl = response->ctl;
struct tb_cfg_result res = { 0 };
res.response_route = tb_cfg_get_route(&pkg->header);
res.response_port = 0;
@@ -226,9 +228,13 @@
if (res.err)
return res;
- WARN(pkg->zero1, "pkg->zero1 is %#x\n", pkg->zero1);
- WARN(pkg->zero2, "pkg->zero1 is %#x\n", pkg->zero1);
- WARN(pkg->zero3, "pkg->zero1 is %#x\n", pkg->zero1);
+ if (pkg->zero1)
+ tb_ctl_warn(ctl, "pkg->zero1 is %#x\n", pkg->zero1);
+ if (pkg->zero2)
+ tb_ctl_warn(ctl, "pkg->zero2 is %#x\n", pkg->zero2);
+ if (pkg->zero3)
+ tb_ctl_warn(ctl, "pkg->zero3 is %#x\n", pkg->zero3);
+
res.err = 1;
res.tb_error = pkg->error;
res.response_port = pkg->port;
@@ -265,9 +271,8 @@
* Invalid cfg_space/offset/length combination in
* cfg_read/cfg_write.
*/
- tb_ctl_WARN(ctl,
- "CFG_ERROR(%llx:%x): Invalid config space or offset\n",
- res->response_route, res->response_port);
+ tb_ctl_dbg(ctl, "%llx:%x: invalid config space or offset\n",
+ res->response_route, res->response_port);
return;
case TB_CFG_ERROR_NO_SUCH_PORT:
/*
@@ -281,6 +286,10 @@
case TB_CFG_ERROR_LOOP:
tb_ctl_WARN(ctl, "CFG_ERROR(%llx:%x): Route contains a loop\n",
res->response_route, res->response_port);
+ return;
+ case TB_CFG_ERROR_LOCK:
+ tb_ctl_warn(ctl, "%llx:%x: downstream port is locked\n",
+ res->response_route, res->response_port);
return;
default:
/* 5,6,7,9 and 11 are also valid error codes */
@@ -387,7 +396,7 @@
static int tb_async_error(const struct ctl_pkg *pkg)
{
- const struct cfg_error_pkg *error = (const struct cfg_error_pkg *)pkg;
+ const struct cfg_error_pkg *error = pkg->buffer;
if (pkg->frame.eof != TB_CFG_PKG_ERROR)
return false;
@@ -452,7 +461,7 @@
"RX: checksum mismatch, dropping packet\n");
goto rx;
}
- /* Fall through */
+ fallthrough;
case TB_CFG_PKG_ICM_EVENT:
if (tb_ctl_handle_event(pkg->ctl, frame->eof, pkg, frame->size))
goto rx;
@@ -631,7 +640,7 @@
ctl->rx_packets[i]->frame.callback = tb_ctl_rx_callback;
}
- tb_ctl_info(ctl, "control channel created\n");
+ tb_ctl_dbg(ctl, "control channel created\n");
return ctl;
err:
tb_ctl_free(ctl);
@@ -662,8 +671,7 @@
tb_ctl_pkg_free(ctl->rx_packets[i]);
- if (ctl->frame_pool)
- dma_pool_destroy(ctl->frame_pool);
+ dma_pool_destroy(ctl->frame_pool);
kfree(ctl);
}
@@ -673,7 +681,7 @@
void tb_ctl_start(struct tb_ctl *ctl)
{
int i;
- tb_ctl_info(ctl, "control channel starting...\n");
+ tb_ctl_dbg(ctl, "control channel starting...\n");
tb_ring_start(ctl->tx); /* is used to ack hotplug packets, start first */
tb_ring_start(ctl->rx);
for (i = 0; i < TB_CTL_RX_PKG_COUNT; i++)
@@ -702,25 +710,32 @@
if (!list_empty(&ctl->request_queue))
tb_ctl_WARN(ctl, "dangling request in request_queue\n");
INIT_LIST_HEAD(&ctl->request_queue);
- tb_ctl_info(ctl, "control channel stopped\n");
+ tb_ctl_dbg(ctl, "control channel stopped\n");
}
/* 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_info(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);
}
@@ -930,6 +945,26 @@
return res;
}
+static int tb_cfg_get_error(struct tb_ctl *ctl, enum tb_cfg_space space,
+ const struct tb_cfg_result *res)
+{
+ /*
+ * For unimplemented ports access to port config space may return
+ * TB_CFG_ERROR_INVALID_CONFIG_SPACE (alternatively their type is
+ * set to TB_TYPE_INACTIVE). In the former case return -ENODEV so
+ * that the caller can mark the port as disabled.
+ */
+ if (space == TB_CFG_PORT &&
+ res->tb_error == TB_CFG_ERROR_INVALID_CONFIG_SPACE)
+ return -ENODEV;
+
+ tb_cfg_print_error(ctl, res);
+
+ if (res->tb_error == TB_CFG_ERROR_LOCK)
+ return -EACCES;
+ return -EIO;
+}
+
int tb_cfg_read(struct tb_ctl *ctl, void *buffer, u64 route, u32 port,
enum tb_cfg_space space, u32 offset, u32 length)
{
@@ -942,12 +977,11 @@
case 1:
/* Thunderbolt error, tb_error holds the actual number */
- tb_cfg_print_error(ctl, &res);
- return -EIO;
+ return tb_cfg_get_error(ctl, space, &res);
case -ETIMEDOUT:
- tb_ctl_warn(ctl, "timeout reading config space %u from %#x\n",
- space, offset);
+ tb_ctl_warn(ctl, "%llx: timeout reading config space %u from %#x\n",
+ route, space, offset);
break;
default:
@@ -969,12 +1003,11 @@
case 1:
/* Thunderbolt error, tb_error holds the actual number */
- tb_cfg_print_error(ctl, &res);
- return -EIO;
+ return tb_cfg_get_error(ctl, space, &res);
case -ETIMEDOUT:
- tb_ctl_warn(ctl, "timeout writing config space %u to %#x\n",
- space, offset);
+ tb_ctl_warn(ctl, "%llx: timeout writing config space %u to %#x\n",
+ route, space, offset);
break;
default:
--
Gitblit v1.6.2