linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Lukas Wunner <lukas@wunner.de>
To: Andreas Noever <andreas.noever@gmail.com>,
	Mika Westerberg <mika.westerberg@linux.intel.com>,
	Michael Jamet <michael.jamet@intel.com>,
	Yehezkel Bernat <YehezkelShB@gmail.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>,
	linux-kernel@vger.kernel.org
Subject: [PATCH 2/5] thunderbolt: Obtain PCI slot number from DROM
Date: Sun, 9 Sep 2018 23:42:01 +0200	[thread overview]
Message-ID: <756f7148bc106d80d2e43273edd6dc8c48c1b87b.1536517047.git.lukas@wunner.de> (raw)
In-Reply-To: <cover.1536517047.git.lukas@wunner.de>

The port numbers of PCIe adapters on a CIO switch and the slot numbers
of their corresponding PCI devices don't necessarily match up in
ascending order.

E.g. Light Ridge in host mode (MacBookPro9,1) mixes them up like this:
switch port  7 == pci slot 4 (PCIe downstream port)
switch port  8 == pci slot 5 (PCIe downstream port)
switch port  9 == pci slot 6 (PCIe downstream port)
switch port 10 == pci slot 3 (PCIe downstream port)

Light Ridge in endpoint mode (Sonnet Echo Express):
switch port  7 == pci slot 4 (PCIe downstream port)
switch port  8 == pci slot 5 (PCIe downstream port)
switch port  9               (PCIe downstream port, disabled in DROM)
switch port 10 == pci slot 0 (PCIe upstream port, pci slot 3 in DROM)

Obtain the slot number used by a switch port from the DROM and store it
in struct tb_port.  This will allow us to correlate PCI devices with
Thunderbolt ports.  For space efficiency, use a union in struct tb_port
to store attributes that are specific to certain port types.
Attributes specific to TB_TYPE_PORT could be moved into a separate
struct within the union.

The slot number occupies 3 bits in the third byte of PCI DROM entries.
The purpose of the remaining 5 bits is unknown (function number?).

Downstream port entries have 3 bytes, upstream port entries 11 bytes.
The slot number in upstream port entries is not that of the port itself
(which is always zero), but that of the PCI endpoint device built into
the Thunderbolt product.  In the case of the Sonnet Echo Express, the
upstream port specifies slot 3, which is used by a PLX switch.

The purpose of the additional 8 bytes present on upstream ports is
unknown (number of PCIe lanes, priority requirements, direct tunnel to
the host desired?).  Examples:

01 00 64 00 00 00 00 00      (Sonnet Echo Express, PLX switch)
01 40 0a 00 00 00 00 00      (Apple Gigabit Ethernet Adapter, BCM957762)

Signed-off-by: Lukas Wunner <lukas@wunner.de>
---
 drivers/thunderbolt/eeprom.c | 21 +++++++++++++++++++++
 drivers/thunderbolt/switch.c | 14 +++++++++++++-
 drivers/thunderbolt/tb.h     |  9 +++++++++
 3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/thunderbolt/eeprom.c b/drivers/thunderbolt/eeprom.c
index 3e8caf22c294..ce6e037fdb39 100644
--- a/drivers/thunderbolt/eeprom.c
+++ b/drivers/thunderbolt/eeprom.c
@@ -236,6 +236,15 @@ struct tb_drom_entry_port {
 	u8 unknown4:2;
 } __packed;
 
+struct tb_drom_entry_pci {
+	/* BYTES 0-1 */
+	struct tb_drom_entry_header header;
+	/* BYTE 2 */
+	u8 unknown:5;
+	u8 slot:3;
+	/* BYTES 3-10 are only present on PCIe upstream ports */
+} __packed;
+
 
 /**
  * tb_eeprom_get_drom_offset - get drom offset within eeprom
@@ -365,6 +374,18 @@ static int tb_drom_parse_entry_port(struct tb_switch *sw,
 		if (entry->has_dual_link_port)
 			port->dual_link_port =
 				&port->sw->ports[entry->dual_link_port_nr];
+	} else if (type == TB_TYPE_PCIE_UP || type == TB_TYPE_PCIE_DOWN) {
+		struct tb_drom_entry_pci *entry = (void *) header;
+		if (header->len < sizeof(*entry)) {
+			tb_sw_warn(sw,
+				"port entry has size %#x (expected %#zx+)\n",
+				header->len, sizeof(struct tb_drom_entry_pci));
+			return -EIO;
+		}
+		port->pci.devfn = PCI_DEVFN(entry->slot, 0);
+		memcpy(port->pci.unknown, header + 1,
+		       min(header->len - sizeof(struct tb_drom_entry_header),
+			   sizeof(port->pci.unknown)));
 	}
 	return 0;
 }
diff --git a/drivers/thunderbolt/switch.c b/drivers/thunderbolt/switch.c
index 7442bc4c6433..54fd42250935 100644
--- a/drivers/thunderbolt/switch.c
+++ b/drivers/thunderbolt/switch.c
@@ -577,6 +577,7 @@ int tb_port_clear_counter(struct tb_port *port, int counter)
  */
 static int tb_init_port(struct tb_port *port)
 {
+	struct tb *tb = port->sw->tb;
 	int res;
 	int cap;
 
@@ -594,9 +595,20 @@ static int tb_init_port(struct tb_port *port)
 			tb_port_WARN(port, "non switch port without a PHY\n");
 	}
 
-	tb_dump_port(port->sw->tb, &port->config);
+	tb_dump_port(tb, &port->config);
 
 	/* TODO: Read dual link port, DP port and more from EEPROM. */
+	switch (port->config.type) {
+	case TB_TYPE_PCIE_UP:
+	case TB_TYPE_PCIE_DOWN:
+		tb_info(tb, "  PCI slot: %02x.0\n", PCI_SLOT(port->pci.devfn));
+		tb_info(tb, "  PCI unknown data: %*ph\n",
+			(int)sizeof(port->pci.unknown), port->pci.unknown);
+		break;
+	default:
+		break;
+	}
+
 	return 0;
 
 }
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 5067d69d0501..755183f0b257 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -125,6 +125,9 @@ struct tb_switch {
  * @dual_link_port: If the switch is connected using two ports, points
  *		    to the other port.
  * @link_nr: Is this primary or secondary port on the dual_link.
+ * @pci: Data specific to PCIe adapters
+ * @pci.devfn: PCI slot/function according to DROM
+ * @pci.unknown: Unknown data in DROM (to be reverse-engineered)
  */
 struct tb_port {
 	struct tb_regs_port_header config;
@@ -136,6 +139,12 @@ struct tb_port {
 	bool disabled;
 	struct tb_port *dual_link_port;
 	u8 link_nr:1;
+	union {
+		struct {
+			u8 devfn;
+			u8 unknown[9];
+		} pci;
+	};
 };
 
 /**
-- 
2.18.0


  parent reply	other threads:[~2018-09-09 21:44 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-09-09 21:42 [PATCH 0/5] Thunderbolt material for v4.20 Lukas Wunner
2018-09-09 21:42 ` [PATCH 4/5] thunderbolt: Correlate PCI devices with Thunderbolt ports Lukas Wunner
2018-09-10  9:44   ` Mika Westerberg
2018-09-13  9:43     ` Yehezkel Bernat
2018-09-13  9:57       ` Mika Westerberg
2018-09-09 21:42 ` [PATCH 3/5] thunderbolt: Move upstream_port to struct tb Lukas Wunner
2018-09-09 21:42 ` Lukas Wunner [this message]
2018-09-10  9:52   ` [PATCH 2/5] thunderbolt: Obtain PCI slot number from DROM Mika Westerberg
2018-09-09 21:42 ` [PATCH 5/5] MAINTAINERS: Add Lukas Wunner as co-maintainer of thunderbolt Lukas Wunner
2018-09-10  9:33   ` Mika Westerberg
2018-09-10 10:25     ` Lukas Wunner
2018-09-10 12:13       ` Mika Westerberg
2018-09-13  8:58     ` Mika Westerberg
2018-09-13  9:43       ` Greg Kroah-Hartman
2018-09-17 22:34       ` Andreas Noever
2018-09-19 10:16         ` Mika Westerberg
2018-09-09 21:42 ` [PATCH 1/5] thunderbolt: Skip disabled ports on tunnel establishment Lukas Wunner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=756f7148bc106d80d2e43273edd6dc8c48c1b87b.1536517047.git.lukas@wunner.de \
    --to=lukas@wunner.de \
    --cc=YehezkelShB@gmail.com \
    --cc=andreas.noever@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michael.jamet@intel.com \
    --cc=mika.westerberg@linux.intel.com \
    --cc=stephen@networkplumber.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).