[PATCH v9 1/8] thunderbolt: Macro rename
This first patch updates the NHI Thunderbolt controller registers file to reflect that it is not only for Cactus Ridge. No functional change intended. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> Signed-off-by: Andreas Noever <andreas.noe...@gmail.com> --- drivers/thunderbolt/nhi_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 86b996c..75cf069 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -1,11 +1,11 @@ /* - * Thunderbolt Cactus Ridge driver - NHI registers + * Thunderbolt driver - NHI registers * * Copyright (c) 2014 Andreas Noever <andreas.noe...@gmail.com> */ -#ifndef DSL3510_REGS_H_ -#define DSL3510_REGS_H_ +#ifndef NHI_REGS_H_ +#define NHI_REGS_H_ #include -- 2.7.4
[PATCH v9 4/8] thunderbolt: Networking state machine
This patch builds the peer to peer communication path. Communication is established by a negotiation process whereby messages are sent back and forth between the peers until a connection is established. This includes the Thunderbolt Network driver communication with the second peer via Intel Connection Manager(ICM) firmware. ++++ |Host 1 ||Host 2 | |||| | +---+ || +---+ | | |Thunderbolt| || |Thunderbolt| | | |Networking | || |Networking | | | |Driver | || |Driver | | | +---+ || +---+ | | ^ || ^ | | | || | | | ++---+ || ++---+ | | |Thunderbolt | | || |Thunderbolt | | | | |Controller v | || |Controller v | | | | +---+ | || | +---+ | | | | |ICM|<-+-++-+>|ICM| | | | | +---+ | || | +---+ | | | ++ || ++ | ++++ Note that this patch only establishes the link between the two hosts and not Network Packet handling - this is dealt with in the next patch. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/Makefile | 2 +- drivers/thunderbolt/icm/icm_nhi.c | 262 - drivers/thunderbolt/icm/net.c | 783 ++ drivers/thunderbolt/icm/net.h | 70 4 files changed, 1109 insertions(+), 8 deletions(-) create mode 100644 drivers/thunderbolt/icm/net.c diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile index f0d0fbb..94a2797 100644 --- a/drivers/thunderbolt/icm/Makefile +++ b/drivers/thunderbolt/icm/Makefile @@ -1,2 +1,2 @@ obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o -thunderbolt-icm-objs := icm_nhi.o +thunderbolt-icm-objs := icm_nhi.o net.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index c843ce8..edc910b 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -64,6 +64,13 @@ static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { .len = TBT_ICM_RING_MAX_FRAME_SIZE }, [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_LOCAL_ROUTE_STRING] = { + .len = sizeof(struct route_string) }, + [NHI_ATTR_LOCAL_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_REMOTE_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_LOCAL_DEPTH] = { .type = NLA_U8, }, + [NHI_ATTR_ENABLE_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MATCH_FRAME_ID] = { .type = NLA_FLAG, }, }; /* NHI genetlink family */ @@ -480,6 +487,29 @@ int nhi_mailbox(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd, u32 data, bool deinit) return 0; } +static inline bool nhi_is_path_disconnected(u32 cmd, u8 num_ports) +{ + return (cmd >= DISCONNECT_PORT_A_INTER_DOMAIN_PATH && + cmd < (DISCONNECT_PORT_A_INTER_DOMAIN_PATH + num_ports)); +} + +static int nhi_mailbox_disconn_path(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd) + __releases(_list_mutex) +{ + struct port_net_dev *port; + u32 port_num = cmd - DISCONNECT_PORT_A_INTER_DOMAIN_PATH; + + port = &(nhi_ctxt->net_devices[port_num]); + mutex_lock(>state_mutex); + + mutex_unlock(_list_mutex); + port->medium_sts = MEDIUM_READY_FOR_APPROVAL; + if (port->net_dev) + negotiation_events(port->net_dev, MEDIUM_DISCONNECTED); + mutex_unlock(>state_mutex); + return 0; +} + static int nhi_mailbox_generic(struct tbt_nhi_ctxt *nhi_ctxt, u32 mb_cmd) __releases(_list_mutex) { @@ -526,13 +556,90 @@ static int nhi_genl_mailbox(__always_unused struct sk_buff *u_skb, return -ERESTART; nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); - if (nhi_ctxt && !nhi_ctxt->d0_exit) - return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + + /* rwsem is released later by the below functions */ + if (nhi_is_path_disconnected(cmd, nhi_ctxt->num_ports)) + return nhi_mailbox_disconn_path(nhi_ctxt, cmd); + else + return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + + } mutex_unlock(_list_
[PATCH v9 6/8] thunderbolt: Kconfig for Thunderbolt Networking
Update to the Kconfig Thunderbolt description to add Thunderbolt networking as an option. The menu item "Thunderbolt support" now offers: "Apple Hardware Support" (existing) and/or "Thunderbolt Networking" (new) You can choose the driver for your platform or build both drivers - each driver will detect if it can run on the specific platform. If the Thunderbolt Networking option is chosen, Thunderbolt Networking will be enabled between Linux non-Apple systems, macOS and Windows based systems. Thunderbolt Networking will not affect any other Thunderbolt feature that was previous available to Linux users on either Apple or non-Apple platforms. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Kconfig | 27 +++ drivers/thunderbolt/Makefile | 3 ++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index c121acc..376e5bb 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -1,13 +1,32 @@ -menuconfig THUNDERBOLT - tristate "Thunderbolt support for Apple devices" +config THUNDERBOLT + tristate "Thunderbolt support" depends on PCI select CRC32 help - Cactus Ridge Thunderbolt Controller driver + Thunderbolt Controller driver + +if THUNDERBOLT + +config THUNDERBOLT_APPLE + tristate "Apple hardware support" + help This driver is required if you want to hotplug Thunderbolt devices on Apple hardware. Device chaining is currently not supported. - To compile this driver a module, choose M here. The module will be + To compile this driver as a module, choose M here. The module will be called thunderbolt. + +config THUNDERBOLT_ICM + tristate "Thunderbolt Networking" + help + This driver is required if you want Thunderbolt Networking on + non-Apple hardware. + It creates a virtual Ethernet device that enables computer to + computer communication over a Thunderbolt cable. + + To compile this driver as a module, choose M here. The module will be + called thunderbolt_icm. + +endif diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 5d1053c..b6aa6a3 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,4 @@ -obj-${CONFIG_THUNDERBOLT} := thunderbolt.o +obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o +obj-${CONFIG_THUNDERBOLT_ICM} += icm/ -- 2.7.4
[PATCH v9 7/8] thunderbolt: Networking doc
Adding Thunderbolt(TM) networking documentation. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- Documentation/00-INDEX | 2 + Documentation/thunderbolt/networking.txt | 132 +++ 2 files changed, 134 insertions(+) create mode 100644 Documentation/thunderbolt/networking.txt diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index 3acc4f1..0239e68 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -440,6 +440,8 @@ this_cpu_ops.txt - List rationale behind and the way to use this_cpu operations. thermal/ - directory with information on managing thermal issues (CPU/temp) +thunderbolt/ + - directory with info regarding Thunderbolt. trace/ - directory with info on tracing technologies within linux unaligned-memory-access.txt diff --git a/Documentation/thunderbolt/networking.txt b/Documentation/thunderbolt/networking.txt new file mode 100644 index 000..88d1c12 --- /dev/null +++ b/Documentation/thunderbolt/networking.txt @@ -0,0 +1,132 @@ +Intel Thunderbolt(TM) Networking driver +=== + +Copyright(c) 2013 - 2016 Intel Corporation. + +Contact Information: +Intel Thunderbolt mailing list <thunderbolt-softw...@lists.01.org> +Edited by Amir Levy <amir.jer.l...@intel.com> + +Overview + + +* The Thunderbolt Networking driver enables peer to peer networking on non-Apple + platforms running Linux. + +* The driver creates a virtual Ethernet device that enables computer to computer + communication over the Thunderbolt cable. + +* Using Thunderbolt Networking you can perform high speed file transfers between + computers, perform PC migrations and/or set up small workgroups with shared + storage without compromising any other Thunderbolt functionality. + +* The driver is located in drivers/thunderbolt/icm. + +* This driver will function only on non-Apple platforms with firmware based + Thunderbolt controllers that support Thunderbolt Networking. + + ++++ + |Host 1 ||Host 2 | + |||| + | +---+||+---+ | + | |Network||||Network| | + | |Stack ||||Stack | | + | +---+||+---+ | + | ^||^ | + | |||| | + | v||v | + | +---+ || +---+ | + | |Thunderbolt| || |Thunderbolt| | + | |Networking | || |Networking | | + | |Driver | || |Driver | | + | +---+ || +---+ | + | ^||^ | + | |||| | + | v||v | + | +---+ || +---+ | + | |Thunderbolt| || |Thunderbolt| | + | |Controller |<-++->|Controller | | + | |with ICM | || |with ICM | | + | |enabled| || |enabled| | + | +---+ || +---+ | + ++++ + +Files += + +The following files are located in the drivers/thunderbolt/icm directory: + +- icm_nhi.c/h: These files allow communication with the firmware (Intel + Connection Manager) based controller. They also create an interface for + netlink communication with a user space daemon. + +- net.c/net.h: These files implement the 'eth' interface for the + Thunderbolt(TM) Networking. + +Interface to User Space +=== + +The interface to the user space module is implemented through a Generic Netlink. +This is the communications protocol between the Thunderbolt driver and the user +space application. + +Note that this interface mediates user space communication with ICM. +(Existing Linux tools can be used to configure the network interface.) + +The Thunderbolt Daemon utilizes this interface to communicate with the driver. +To be accessed by the user space module, both kernel and user space modules +have to register with the same GENL_NAME. +For the purpose of the Thunderbolt Network driver, "thunderbolt" is used. +The registration is done at driver initialization time for all instances +of the Thunderbolt controllers. The communication is carried through pre-defined +Thunderbolt messages. Each specific message has a callback function that is +called when the related message is received. + +Message Definitions: +* NHI_CMD_UNSPEC: Not used. +* NHI_CMD_SUBSCRIBE: Subscription request from daemon to driver to open the + communication channel. +* NHI_CMD_UNSUBSCRIBE: Request from daemon to driver to unsubscribe and + to close communication channel. +* NHI_CMD_QUERY_INFORMATION: R
[PATCH v9 2/8] thunderbolt: Updating the register definitions
Adding more Thunderbolt(TM) register definitions and some helper macros. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 109 + 1 file changed, 109 insertions(+) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 75cf069..b8e961f 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -9,6 +9,11 @@ #include +#define NHI_MMIO_BAR 0 + +#define TBT_RING_MIN_NUM_BUFFERS 2 +#define TBT_RING_MAX_FRAME_SIZE(4 * 1024) + enum ring_flags { RING_FLAG_ISOCH_ENABLE = 1 << 27, /* TX only? */ RING_FLAG_E2E_FLOW_CONTROL = 1 << 28, @@ -39,6 +44,33 @@ struct ring_desc { u32 time; /* write zero */ } __packed; +/** + * struct tbt_buf_desc - TX/RX ring buffer descriptor. + * This is same as struct ring_desc, but without the use of bitfields and + * with explicit endianity. + */ +struct tbt_buf_desc { + __le64 phys; + __le32 attributes; + __le32 time; +}; + +#define DESC_ATTR_LEN_SHIFT0 +#define DESC_ATTR_LEN_MASK GENMASK(11, DESC_ATTR_LEN_SHIFT) +#define DESC_ATTR_EOF_SHIFT12 +#define DESC_ATTR_EOF_MASK GENMASK(15, DESC_ATTR_EOF_SHIFT) +#define DESC_ATTR_SOF_SHIFT16 +#define DESC_ATTR_SOF_MASK GENMASK(19, DESC_ATTR_SOF_SHIFT) +#define DESC_ATTR_TX_ISOCH_DMA_EN BIT(20) /* TX */ +#define DESC_ATTR_RX_CRC_ERR BIT(20) /* RX after use */ +#define DESC_ATTR_DESC_DONEBIT(21) +#define DESC_ATTR_REQ_STS BIT(22) /* TX and RX before use */ +#define DESC_ATTR_RX_BUF_OVRN_ERR BIT(22) /* RX after use */ +#define DESC_ATTR_INT_EN BIT(23) +#define DESC_ATTR_OFFSET_SHIFT 24 +#define DESC_ATTR_OFFSET_MASK GENMASK(31, DESC_ATTR_OFFSET_SHIFT) + + /* NHI registers in bar 0 */ /* @@ -60,6 +92,30 @@ struct ring_desc { */ #define REG_RX_RING_BASE 0x08000 +#define REG_RING_STEP 16 +#define REG_RING_PHYS_LO_OFFSET0 +#define REG_RING_PHYS_HI_OFFSET4 +#define REG_RING_CONS_PROD_OFFSET 8 /* cons - RO, prod - RW */ +#define REG_RING_CONS_SHIFT0 +#define REG_RING_CONS_MASK GENMASK(15, REG_RING_CONS_SHIFT) +#define REG_RING_PROD_SHIFT16 +#define REG_RING_PROD_MASK GENMASK(31, REG_RING_PROD_SHIFT) +#define REG_RING_SIZE_OFFSET 12 +#define REG_RING_SIZE_SHIFT0 +#define REG_RING_SIZE_MASK GENMASK(15, REG_RING_SIZE_SHIFT) +#define REG_RING_BUF_SIZE_SHIFT16 +#define REG_RING_BUF_SIZE_MASK GENMASK(27, REG_RING_BUF_SIZE_SHIFT) + +#define TBT_RING_CONS_PROD_REG(iobase, ringbase, ringnumber) \ + ((iobase) + (ringbase) + \ + ((ringnumber) * REG_RING_STEP) + \ + REG_RING_CONS_PROD_OFFSET) + +#define TBT_REG_RING_PROD_EXTRACT(val) (((val) & REG_RING_PROD_MASK) >> \ + REG_RING_PROD_SHIFT) + +#define TBT_REG_RING_CONS_EXTRACT(val) (((val) & REG_RING_CONS_MASK) >> \ + REG_RING_CONS_SHIFT) /* * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) * 00: enum_ring_flags @@ -77,6 +133,19 @@ struct ring_desc { * ..: unknown */ #define REG_RX_OPTIONS_BASE0x29800 +#define REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT12 +#define REG_RX_OPTS_TX_E2E_HOP_ID_MASK \ + GENMASK(22, REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT) +#define REG_RX_OPTS_MASK_OFFSET4 +#define REG_RX_OPTS_MASK_EOF_SHIFT 0 +#define REG_RX_OPTS_MASK_EOF_MASK GENMASK(15, REG_RX_OPTS_MASK_EOF_SHIFT) +#define REG_RX_OPTS_MASK_SOF_SHIFT 16 +#define REG_RX_OPTS_MASK_SOF_MASK GENMASK(31, REG_RX_OPTS_MASK_SOF_SHIFT) + +#define REG_OPTS_STEP 32 +#define REG_OPTS_E2E_ENBIT(28) +#define REG_OPTS_RAW BIT(30) +#define REG_OPTS_VALID BIT(31) /* * three bitfields: tx, rx, rx overflow @@ -86,6 +155,7 @@ struct ring_desc { */ #define REG_RING_NOTIFY_BASE 0x37800 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32) +#define REG_RING_NOTIFY_STEP 4 /* * two bitfields: rx, tx @@ -94,8 +164,47 @@ struct ring_desc { */ #define REG_RING_INTERRUPT_BASE0x38200 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32) +#define REG_RING_INT_TX_PROCESSED(ring_num)BIT(ring_num) +#define REG_RING_INT_RX_PROCESSED(ring_num, num_paths) BIT((ring_num) + \ + (num_paths)) +#define RING_INT_DISABLE(base, val) iowrite32( \ + ioread32((base) + REG_RING_INTERRUPT_BASE) & ~(val), \ + (base) + REG_RING_IN
[PATCH v9 5/8] thunderbolt: Networking transmit and receive
This patch provides the handling interface for sending and receiving network packets between the hosts over the full communication route (using the communication path established in the previous patch). The Thunderbolt Network driver interfaces the Linux network stack and the hardware controller configuration to handle packet transmissions: ++++ |Host 1 ||Host 2 | |||| | +---+||+---+ | | |Network||||Network| | | |Stack ||||Stack | | | +---+||+---+ | | ^||^ | | |||| | | v||v | | +---+ || +---+ | | |Thunderbolt| || |Thunderbolt| | | |Networking | || |Networking | | | |Driver | || |Driver | | | +---+ || +---+ | | ^||^ | | |||| | | v||v | | +---+ || +---+ | | |Thunderbolt| || |Thunderbolt| | | |Controller |<-++->|Controller | | | +---+ || +---+ | ++++ Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/icm_nhi.c | 15 + drivers/thunderbolt/icm/net.c | 1471 + 2 files changed, 1486 insertions(+) diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index edc910b..b1cc347 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -928,6 +928,7 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) { struct tbt_nhi_ctxt *nhi_ctxt = data; u32 isr0, isr1, imr0, imr1; + int i; /* clear on read */ isr0 = ioread32(nhi_ctxt->iobase + REG_RING_NOTIFY_BASE); @@ -950,6 +951,20 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) spin_unlock(_ctxt->lock); + for (i = 0; i < nhi_ctxt->num_ports; ++i) { + struct net_device *net_dev = + nhi_ctxt->net_devices[i].net_dev; + if (net_dev) { + u8 path = PATH_FROM_PORT(nhi_ctxt->num_paths, i); + + if (isr0 & REG_RING_INT_RX_PROCESSED( + path, nhi_ctxt->num_paths)) + tbt_net_rx_msi(net_dev); + if (isr0 & REG_RING_INT_TX_PROCESSED(path)) + tbt_net_tx_msi(net_dev); + } + } + if (isr0 & REG_RING_INT_RX_PROCESSED(TBT_ICM_RING_NUM, nhi_ctxt->num_paths)) schedule_work(_ctxt->icm_msgs_work); diff --git a/drivers/thunderbolt/icm/net.c b/drivers/thunderbolt/icm/net.c index beeafb3..cf985dd 100644 --- a/drivers/thunderbolt/icm/net.c +++ b/drivers/thunderbolt/icm/net.c @@ -124,6 +124,17 @@ struct approve_inter_domain_connection_cmd { }; +struct tbt_frame_header { + /* size of the data with the frame */ + __le32 frame_size; + /* running index on the frames */ + __le16 frame_index; + /* ID of the frame to match frames to specific packet */ + __le16 frame_id; + /* how many frames assembles a full packet */ + __le32 frame_count; +}; + enum neg_event { RECEIVE_LOGOUT = NUM_MEDIUM_STATUSES, RECEIVE_LOGIN_RESPONSE, @@ -131,15 +142,81 @@ enum neg_event { NUM_NEG_EVENTS }; +enum frame_status { + GOOD_FRAME, + GOOD_AS_FIRST_FRAME, + GOOD_AS_FIRST_MULTICAST_FRAME, + FRAME_NOT_READY, + FRAME_ERROR, +}; + +enum packet_filter { + /* all multicast MAC addresses */ + PACKET_TYPE_ALL_MULTICAST, + /* all types of MAC addresses: multicast, unicast and broadcast */ + PACKET_TYPE_PROMISCUOUS, + /* all unicast MAC addresses */ + PACKET_TYPE_UNICAST_PROMISCUOUS, +}; + enum disconnect_path_stage { STAGE_1 = BIT(0), STAGE_2 = BIT(1) }; +struct tbt_net_stats { + u64 tx_packets; + u64 tx_bytes; + u64 tx_errors; + u64 rx_packets; + u64 rx_bytes; + u64 rx_length_errors; + u64 rx_over_errors; + u64 rx_crc_errors; + u64 rx_missed_errors; + u64 multicast; +}; + +static const char tbt_net_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_packets", + "tx_bytes", + "tx_errors", + "rx_packets", + "rx_bytes", +
[PATCH v9 8/8] thunderbolt: Adding maintainer entry
Add Amir Levy as maintainer for Thunderbolt(TM) ICM driver Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- MAINTAINERS | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 411e3b8..87763c44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10652,7 +10652,13 @@ F: include/uapi/linux/stm.h THUNDERBOLT DRIVER M: Andreas Noever <andreas.noe...@gmail.com> S: Maintained -F: drivers/thunderbolt/ +F: drivers/thunderbolt/* + +THUNDERBOLT ICM DRIVER +M: Amir Levy <amir.jer.l...@intel.com> +S: Maintained +F: drivers/thunderbolt/icm/ +F: Documentation/thunderbolt/networking.txt TI BQ27XXX POWER SUPPLY DRIVER R: Andrew F. Davis <a...@ti.com> -- 2.7.4
[PATCH v9 0/8] thunderbolt: Introducing Thunderbolt(TM) Networking
This driver enables Thunderbolt Networking on non-Apple platforms running Linux. Thunderbolt Networking provides peer-to-peer connections to transfer files between computers, perform PC migrations, and/or set up small workgroups with shared storage. This is a virtual connection that emulates an Ethernet adapter that enables Ethernet networking with the benefit of Thunderbolt superfast medium capability. Thunderbolt Networking enables two hosts and several devices that have a Thunderbolt controller to be connected together in a linear (Daisy chain) series from a single port. Thunderbolt Networking for Linux is compatible with Thunderbolt Networking on systems running macOS or Windows and also supports Thunderbolt generation 2 and 3 controllers. Note that all pre-existing Thunderbolt generation 3 features, such as USB, Display and other Thunderbolt device connectivity will continue to function exactly as they did prior to enabling Thunderbolt Networking. Code and Software Specifications: This kernel code creates a virtual ethernet device for computer to computer communication over a Thunderbolt cable. The new driver is a separate driver to the existing Thunderbolt driver. It is designed to work on systems running Linux that interface with Intel Connection Manager (ICM) firmware based Thunderbolt controllers that support Thunderbolt Networking. The kernel code operates in coordination with the Thunderbolt user- space daemon to implement full Thunderbolt networking functionality. Hardware Specifications: Thunderbolt Hardware specs have not yet been published but are used where necessary for register definitions. Acked-by: Andreas Noever <andreas.noe...@gmail.com> Tested-by: Mario Limonciello <mario.limoncie...@dell.com> Changes since v8: - Added support for more Thunderbolt device IDs These patches were pushed to GitHub where they can be reviewed more comfortably with green/red highlighting: https://github.com/01org/thunderbolt-software-kernel-tree Daemon code: https://github.com/01org/thunderbolt-software-daemon For reference, here's a link to version 8: [v8]: https://lkml.org/lkml/2016/9/28/378 Amir Levy (8): thunderbolt: Macro rename thunderbolt: Updating the register definitions thunderbolt: Communication with the ICM (firmware) thunderbolt: Networking state machine thunderbolt: Networking transmit and receive thunderbolt: Kconfig for Thunderbolt Networking thunderbolt: Networking doc thunderbolt: Adding maintainer entry Documentation/00-INDEX |2 + Documentation/thunderbolt/networking.txt | 132 ++ MAINTAINERS |8 +- drivers/thunderbolt/Kconfig | 27 +- drivers/thunderbolt/Makefile |3 +- drivers/thunderbolt/icm/Makefile |2 + drivers/thunderbolt/icm/icm_nhi.c| 1520 drivers/thunderbolt/icm/icm_nhi.h| 85 ++ drivers/thunderbolt/icm/net.c| 2254 ++ drivers/thunderbolt/icm/net.h| 287 drivers/thunderbolt/nhi_regs.h | 115 +- 11 files changed, 4426 insertions(+), 9 deletions(-) create mode 100644 Documentation/thunderbolt/networking.txt create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.c create mode 100644 drivers/thunderbolt/icm/net.h -- 2.7.4
[PATCH v9 3/8] thunderbolt: Communication with the ICM (firmware)
This patch provides the communication protocol between the Intel Connection Manager(ICM) firmware that is operational in the Thunderbolt controller in non-Apple hardware. The ICM firmware-based controller is used for establishing and maintaining the Thunderbolt Networking connection - we need to be able to communicate with it. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/Makefile |2 + drivers/thunderbolt/icm/icm_nhi.c | 1257 + drivers/thunderbolt/icm/icm_nhi.h | 85 +++ drivers/thunderbolt/icm/net.h | 217 +++ 4 files changed, 1561 insertions(+) create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.h diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile new file mode 100644 index 000..f0d0fbb --- /dev/null +++ b/drivers/thunderbolt/icm/Makefile @@ -0,0 +1,2 @@ +obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o +thunderbolt-icm-objs := icm_nhi.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c new file mode 100644 index 000..c843ce8 --- /dev/null +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -0,0 +1,1257 @@ +/*** + * + * Intel Thunderbolt(TM) driver + * Copyright(c) 2014 - 2016 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + **/ + +#include +#include +#include +#include +#include "icm_nhi.h" +#include "net.h" + +#define NHI_GENL_VERSION 1 +#define NHI_GENL_NAME "thunderbolt" + +#define DEVICE_DATA(num_ports, dma_port, nvm_ver_offset, nvm_auth_on_boot,\ + support_full_e2e) \ + ((num_ports) | ((dma_port) << 4) | ((nvm_ver_offset) << 10) | \ +((nvm_auth_on_boot) << 22) | ((support_full_e2e) << 23)) +#define DEVICE_DATA_NUM_PORTS(device_data) ((device_data) & 0xf) +#define DEVICE_DATA_DMA_PORT(device_data) (((device_data) >> 4) & 0x3f) +#define DEVICE_DATA_NVM_VER_OFFSET(device_data) (((device_data) >> 10) & 0xfff) +#define DEVICE_DATA_NVM_AUTH_ON_BOOT(device_data) (((device_data) >> 22) & 0x1) +#define DEVICE_DATA_SUPPORT_FULL_E2E(device_data) (((device_data) >> 23) & 0x1) + +#define USEC_TO_256_NSECS(usec) DIV_ROUND_UP((usec) * NSEC_PER_USEC, 256) + +/* NHI genetlink commands */ +enum { + NHI_CMD_UNSPEC, + NHI_CMD_SUBSCRIBE, + NHI_CMD_UNSUBSCRIBE, + NHI_CMD_QUERY_INFORMATION, + NHI_CMD_MSG_TO_ICM, + NHI_CMD_MSG_FROM_ICM, + NHI_CMD_MAILBOX, + NHI_CMD_APPROVE_TBT_NETWORKING, + NHI_CMD_ICM_IN_SAFE_MODE, + __NHI_CMD_MAX, +}; +#define NHI_CMD_MAX (__NHI_CMD_MAX - 1) + +/* NHI genetlink policy */ +static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { + [NHI_ATTR_DRV_VERSION] = { .type = NLA_NUL_STRING, }, + [NHI_ATTR_NVM_VER_OFFSET] = { .type = NLA_U16, }, + [NHI_ATTR_NUM_PORTS]= { .type = NLA_U8, }, + [NHI_ATTR_DMA_PORT] = { .type = NLA_U8, }, + [NHI_ATTR_SUPPORT_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MAILBOX_CMD] = { .type = NLA_U32, }, + [NHI_ATTR_PDF] = { .type = NLA_U32, }, + [NHI_ATTR_MSG_TO_ICM] = { .type = NLA_BINARY, + .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, + .len = TBT_ICM_RING_MAX_FRAME_SIZE }, +}; + +/* NHI genetlink family */ +static struct genl_family nhi_genl_family = { + .id = GENL_ID_GENERATE, + .hdrsize= FIELD_SIZEOF(struct tbt_nhi_ctxt, id), + .name = NHI_GENL_NAME, + .version= NHI_GENL_VERSION, + .maxattr= NHI_ATTR_MAX, +}; + +static LIST_HEAD(controllers_list); +static DEFINE_MUTEX(controllers_list_mutex); +static atomic_t subscribers = ATOMIC_INIT(0); +/* + * Some of the received generic netlink messages are replied in a different + * context. The reply has to include the netlink portid of sender, therefore + * saving it in global variable (current assuption is one sender). + */ +static u32 portid; + +static bool nhi_nvm_authenticated(struct
[PATCH v8 1/8] thunderbolt: Macro rename
This first patch updates the NHI Thunderbolt controller registers file to reflect that it is not only for Cactus Ridge. No functional change intended. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> Signed-off-by: Andreas Noever <andreas.noe...@gmail.com> --- drivers/thunderbolt/nhi_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 86b996c..75cf069 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -1,11 +1,11 @@ /* - * Thunderbolt Cactus Ridge driver - NHI registers + * Thunderbolt driver - NHI registers * * Copyright (c) 2014 Andreas Noever <andreas.noe...@gmail.com> */ -#ifndef DSL3510_REGS_H_ -#define DSL3510_REGS_H_ +#ifndef NHI_REGS_H_ +#define NHI_REGS_H_ #include -- 2.7.4
[PATCH v8 4/8] thunderbolt: Networking state machine
This patch builds the peer to peer communication path. Communication is established by a negotiation process whereby messages are sent back and forth between the peers until a connection is established. This includes the Thunderbolt Network driver communication with the second peer via Intel Connection Manager(ICM) firmware. ++++ |Host 1 ||Host 2 | |||| | +---+ || +---+ | | |Thunderbolt| || |Thunderbolt| | | |Networking | || |Networking | | | |Driver | || |Driver | | | +---+ || +---+ | | ^ || ^ | | | || | | | ++---+ || ++---+ | | |Thunderbolt | | || |Thunderbolt | | | | |Controller v | || |Controller v | | | | +---+ | || | +---+ | | | | |ICM|<-+-++-+>|ICM| | | | | +---+ | || | +---+ | | | ++ || ++ | ++++ Note that this patch only establishes the link between the two hosts and not Network Packet handling - this is dealt with in the next patch. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/Makefile | 2 +- drivers/thunderbolt/icm/icm_nhi.c | 262 - drivers/thunderbolt/icm/net.c | 783 ++ drivers/thunderbolt/icm/net.h | 70 4 files changed, 1109 insertions(+), 8 deletions(-) create mode 100644 drivers/thunderbolt/icm/net.c diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile index f0d0fbb..94a2797 100644 --- a/drivers/thunderbolt/icm/Makefile +++ b/drivers/thunderbolt/icm/Makefile @@ -1,2 +1,2 @@ obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o -thunderbolt-icm-objs := icm_nhi.o +thunderbolt-icm-objs := icm_nhi.o net.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index 23047d3..a849698 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -64,6 +64,13 @@ static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { .len = TBT_ICM_RING_MAX_FRAME_SIZE }, [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_LOCAL_ROUTE_STRING] = { + .len = sizeof(struct route_string) }, + [NHI_ATTR_LOCAL_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_REMOTE_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_LOCAL_DEPTH] = { .type = NLA_U8, }, + [NHI_ATTR_ENABLE_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MATCH_FRAME_ID] = { .type = NLA_FLAG, }, }; /* NHI genetlink family */ @@ -480,6 +487,29 @@ int nhi_mailbox(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd, u32 data, bool deinit) return 0; } +static inline bool nhi_is_path_disconnected(u32 cmd, u8 num_ports) +{ + return (cmd >= DISCONNECT_PORT_A_INTER_DOMAIN_PATH && + cmd < (DISCONNECT_PORT_A_INTER_DOMAIN_PATH + num_ports)); +} + +static int nhi_mailbox_disconn_path(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd) + __releases(_list_mutex) +{ + struct port_net_dev *port; + u32 port_num = cmd - DISCONNECT_PORT_A_INTER_DOMAIN_PATH; + + port = &(nhi_ctxt->net_devices[port_num]); + mutex_lock(>state_mutex); + + mutex_unlock(_list_mutex); + port->medium_sts = MEDIUM_READY_FOR_APPROVAL; + if (port->net_dev) + negotiation_events(port->net_dev, MEDIUM_DISCONNECTED); + mutex_unlock(>state_mutex); + return 0; +} + static int nhi_mailbox_generic(struct tbt_nhi_ctxt *nhi_ctxt, u32 mb_cmd) __releases(_list_mutex) { @@ -526,13 +556,90 @@ static int nhi_genl_mailbox(__always_unused struct sk_buff *u_skb, return -ERESTART; nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); - if (nhi_ctxt && !nhi_ctxt->d0_exit) - return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + + /* rwsem is released later by the below functions */ + if (nhi_is_path_disconnected(cmd, nhi_ctxt->num_ports)) + return nhi_mailbox_disconn_path(nhi_ctxt, cmd); + else + return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + + } mutex_unlock(_list_
[PATCH v8 6/8] thunderbolt: Kconfig for Thunderbolt Networking
Update to the Kconfig Thunderbolt description to add Thunderbolt networking as an option. The menu item "Thunderbolt support" now offers: "Apple Hardware Support" (existing) and/or "Thunderbolt Networking" (new) You can choose the driver for your platform or build both drivers - each driver will detect if it can run on the specific platform. If the Thunderbolt Networking option is chosen, Thunderbolt Networking will be enabled between Linux non-Apple systems, macOS and Windows based systems. Thunderbolt Networking will not affect any other Thunderbolt feature that was previous available to Linux users on either Apple or non-Apple platforms. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Kconfig | 27 +++ drivers/thunderbolt/Makefile | 3 ++- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index c121acc..376e5bb 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -1,13 +1,32 @@ -menuconfig THUNDERBOLT - tristate "Thunderbolt support for Apple devices" +config THUNDERBOLT + tristate "Thunderbolt support" depends on PCI select CRC32 help - Cactus Ridge Thunderbolt Controller driver + Thunderbolt Controller driver + +if THUNDERBOLT + +config THUNDERBOLT_APPLE + tristate "Apple hardware support" + help This driver is required if you want to hotplug Thunderbolt devices on Apple hardware. Device chaining is currently not supported. - To compile this driver a module, choose M here. The module will be + To compile this driver as a module, choose M here. The module will be called thunderbolt. + +config THUNDERBOLT_ICM + tristate "Thunderbolt Networking" + help + This driver is required if you want Thunderbolt Networking on + non-Apple hardware. + It creates a virtual Ethernet device that enables computer to + computer communication over a Thunderbolt cable. + + To compile this driver as a module, choose M here. The module will be + called thunderbolt_icm. + +endif diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 5d1053c..b6aa6a3 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,4 @@ -obj-${CONFIG_THUNDERBOLT} := thunderbolt.o +obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o +obj-${CONFIG_THUNDERBOLT_ICM} += icm/ -- 2.7.4
[PATCH v8 7/8] thunderbolt: Networking doc
Adding Thunderbolt(TM) networking documentation. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- Documentation/00-INDEX | 2 + Documentation/thunderbolt/networking.txt | 132 +++ 2 files changed, 134 insertions(+) create mode 100644 Documentation/thunderbolt/networking.txt diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index cb9a6c6..a448ba1 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -439,6 +439,8 @@ this_cpu_ops.txt - List rationale behind and the way to use this_cpu operations. thermal/ - directory with information on managing thermal issues (CPU/temp) +thunderbolt/ + - directory with info regarding Thunderbolt. trace/ - directory with info on tracing technologies within linux unaligned-memory-access.txt diff --git a/Documentation/thunderbolt/networking.txt b/Documentation/thunderbolt/networking.txt new file mode 100644 index 000..88d1c12 --- /dev/null +++ b/Documentation/thunderbolt/networking.txt @@ -0,0 +1,132 @@ +Intel Thunderbolt(TM) Networking driver +=== + +Copyright(c) 2013 - 2016 Intel Corporation. + +Contact Information: +Intel Thunderbolt mailing list <thunderbolt-softw...@lists.01.org> +Edited by Amir Levy <amir.jer.l...@intel.com> + +Overview + + +* The Thunderbolt Networking driver enables peer to peer networking on non-Apple + platforms running Linux. + +* The driver creates a virtual Ethernet device that enables computer to computer + communication over the Thunderbolt cable. + +* Using Thunderbolt Networking you can perform high speed file transfers between + computers, perform PC migrations and/or set up small workgroups with shared + storage without compromising any other Thunderbolt functionality. + +* The driver is located in drivers/thunderbolt/icm. + +* This driver will function only on non-Apple platforms with firmware based + Thunderbolt controllers that support Thunderbolt Networking. + + ++++ + |Host 1 ||Host 2 | + |||| + | +---+||+---+ | + | |Network||||Network| | + | |Stack ||||Stack | | + | +---+||+---+ | + | ^||^ | + | |||| | + | v||v | + | +---+ || +---+ | + | |Thunderbolt| || |Thunderbolt| | + | |Networking | || |Networking | | + | |Driver | || |Driver | | + | +---+ || +---+ | + | ^||^ | + | |||| | + | v||v | + | +---+ || +---+ | + | |Thunderbolt| || |Thunderbolt| | + | |Controller |<-++->|Controller | | + | |with ICM | || |with ICM | | + | |enabled| || |enabled| | + | +---+ || +---+ | + ++++ + +Files += + +The following files are located in the drivers/thunderbolt/icm directory: + +- icm_nhi.c/h: These files allow communication with the firmware (Intel + Connection Manager) based controller. They also create an interface for + netlink communication with a user space daemon. + +- net.c/net.h: These files implement the 'eth' interface for the + Thunderbolt(TM) Networking. + +Interface to User Space +=== + +The interface to the user space module is implemented through a Generic Netlink. +This is the communications protocol between the Thunderbolt driver and the user +space application. + +Note that this interface mediates user space communication with ICM. +(Existing Linux tools can be used to configure the network interface.) + +The Thunderbolt Daemon utilizes this interface to communicate with the driver. +To be accessed by the user space module, both kernel and user space modules +have to register with the same GENL_NAME. +For the purpose of the Thunderbolt Network driver, "thunderbolt" is used. +The registration is done at driver initialization time for all instances +of the Thunderbolt controllers. The communication is carried through pre-defined +Thunderbolt messages. Each specific message has a callback function that is +called when the related message is received. + +Message Definitions: +* NHI_CMD_UNSPEC: Not used. +* NHI_CMD_SUBSCRIBE: Subscription request from daemon to driver to open the + communication channel. +* NHI_CMD_UNSUBSCRIBE: Request from daemon to driver to unsubscribe and + to close communication channel. +* NHI_CMD_QUERY_INFORMATION: R
[PATCH v8 3/8] thunderbolt: Communication with the ICM (firmware)
This patch provides the communication protocol between the Intel Connection Manager(ICM) firmware that is operational in the Thunderbolt controller in non-Apple hardware. The ICM firmware-based controller is used for establishing and maintaining the Thunderbolt Networking connection - we need to be able to communicate with it. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/Makefile |2 + drivers/thunderbolt/icm/icm_nhi.c | 1251 + drivers/thunderbolt/icm/icm_nhi.h | 82 +++ drivers/thunderbolt/icm/net.h | 217 +++ 4 files changed, 1552 insertions(+) create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.h diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile new file mode 100644 index 000..f0d0fbb --- /dev/null +++ b/drivers/thunderbolt/icm/Makefile @@ -0,0 +1,2 @@ +obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o +thunderbolt-icm-objs := icm_nhi.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c new file mode 100644 index 000..23047d3 --- /dev/null +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -0,0 +1,1251 @@ +/*** + * + * Intel Thunderbolt(TM) driver + * Copyright(c) 2014 - 2016 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + **/ + +#include +#include +#include +#include +#include "icm_nhi.h" +#include "net.h" + +#define NHI_GENL_VERSION 1 +#define NHI_GENL_NAME "thunderbolt" + +#define DEVICE_DATA(num_ports, dma_port, nvm_ver_offset, nvm_auth_on_boot,\ + support_full_e2e) \ + ((num_ports) | ((dma_port) << 4) | ((nvm_ver_offset) << 10) | \ +((nvm_auth_on_boot) << 22) | ((support_full_e2e) << 23)) +#define DEVICE_DATA_NUM_PORTS(device_data) ((device_data) & 0xf) +#define DEVICE_DATA_DMA_PORT(device_data) (((device_data) >> 4) & 0x3f) +#define DEVICE_DATA_NVM_VER_OFFSET(device_data) (((device_data) >> 10) & 0xfff) +#define DEVICE_DATA_NVM_AUTH_ON_BOOT(device_data) (((device_data) >> 22) & 0x1) +#define DEVICE_DATA_SUPPORT_FULL_E2E(device_data) (((device_data) >> 23) & 0x1) + +#define USEC_TO_256_NSECS(usec) DIV_ROUND_UP((usec) * NSEC_PER_USEC, 256) + +/* NHI genetlink commands */ +enum { + NHI_CMD_UNSPEC, + NHI_CMD_SUBSCRIBE, + NHI_CMD_UNSUBSCRIBE, + NHI_CMD_QUERY_INFORMATION, + NHI_CMD_MSG_TO_ICM, + NHI_CMD_MSG_FROM_ICM, + NHI_CMD_MAILBOX, + NHI_CMD_APPROVE_TBT_NETWORKING, + NHI_CMD_ICM_IN_SAFE_MODE, + __NHI_CMD_MAX, +}; +#define NHI_CMD_MAX (__NHI_CMD_MAX - 1) + +/* NHI genetlink policy */ +static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { + [NHI_ATTR_DRV_VERSION] = { .type = NLA_NUL_STRING, }, + [NHI_ATTR_NVM_VER_OFFSET] = { .type = NLA_U16, }, + [NHI_ATTR_NUM_PORTS]= { .type = NLA_U8, }, + [NHI_ATTR_DMA_PORT] = { .type = NLA_U8, }, + [NHI_ATTR_SUPPORT_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MAILBOX_CMD] = { .type = NLA_U32, }, + [NHI_ATTR_PDF] = { .type = NLA_U32, }, + [NHI_ATTR_MSG_TO_ICM] = { .type = NLA_BINARY, + .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, + .len = TBT_ICM_RING_MAX_FRAME_SIZE }, +}; + +/* NHI genetlink family */ +static struct genl_family nhi_genl_family = { + .id = GENL_ID_GENERATE, + .hdrsize= FIELD_SIZEOF(struct tbt_nhi_ctxt, id), + .name = NHI_GENL_NAME, + .version= NHI_GENL_VERSION, + .maxattr= NHI_ATTR_MAX, +}; + +static LIST_HEAD(controllers_list); +static DEFINE_MUTEX(controllers_list_mutex); +static atomic_t subscribers = ATOMIC_INIT(0); +/* + * Some of the received generic netlink messages are replied in a different + * context. The reply has to include the netlink portid of sender, therefore + * saving it in global variable (current assuption is one sender). + */ +static u32 portid; + +static bool nhi_nvm_authenticated(struct
[PATCH v8 8/8] thunderbolt: Adding maintainer entry
Add Amir Levy as maintainer for Thunderbolt(TM) ICM driver Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- MAINTAINERS | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 01bff8e..a4a4614 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10358,7 +10358,13 @@ F: include/uapi/linux/stm.h THUNDERBOLT DRIVER M: Andreas Noever <andreas.noe...@gmail.com> S: Maintained -F: drivers/thunderbolt/ +F: drivers/thunderbolt/* + +THUNDERBOLT ICM DRIVER +M: Amir Levy <amir.jer.l...@intel.com> +S: Maintained +F: drivers/thunderbolt/icm/ +F: Documentation/thunderbolt/networking.txt TI BQ27XXX POWER SUPPLY DRIVER R: Andrew F. Davis <a...@ti.com> -- 2.7.4
[PATCH v8 5/8] thunderbolt: Networking transmit and receive
This patch provides the handling interface for sending and receiving network packets between the hosts over the full communication route (using the communication path established in the previous patch). The Thunderbolt Network driver interfaces the Linux network stack and the hardware controller configuration to handle packet transmissions: ++++ |Host 1 ||Host 2 | |||| | +---+||+---+ | | |Network||||Network| | | |Stack ||||Stack | | | +---+||+---+ | | ^||^ | | |||| | | v||v | | +---+ || +---+ | | |Thunderbolt| || |Thunderbolt| | | |Networking | || |Networking | | | |Driver | || |Driver | | | +---+ || +---+ | | ^||^ | | |||| | | v||v | | +---+ || +---+ | | |Thunderbolt| || |Thunderbolt| | | |Controller |<-++->|Controller | | | +---+ || +---+ | ++++ Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/icm_nhi.c | 15 + drivers/thunderbolt/icm/net.c | 1471 + 2 files changed, 1486 insertions(+) diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index a849698..5148081 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -928,6 +928,7 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) { struct tbt_nhi_ctxt *nhi_ctxt = data; u32 isr0, isr1, imr0, imr1; + int i; /* clear on read */ isr0 = ioread32(nhi_ctxt->iobase + REG_RING_NOTIFY_BASE); @@ -950,6 +951,20 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) spin_unlock(_ctxt->lock); + for (i = 0; i < nhi_ctxt->num_ports; ++i) { + struct net_device *net_dev = + nhi_ctxt->net_devices[i].net_dev; + if (net_dev) { + u8 path = PATH_FROM_PORT(nhi_ctxt->num_paths, i); + + if (isr0 & REG_RING_INT_RX_PROCESSED( + path, nhi_ctxt->num_paths)) + tbt_net_rx_msi(net_dev); + if (isr0 & REG_RING_INT_TX_PROCESSED(path)) + tbt_net_tx_msi(net_dev); + } + } + if (isr0 & REG_RING_INT_RX_PROCESSED(TBT_ICM_RING_NUM, nhi_ctxt->num_paths)) schedule_work(_ctxt->icm_msgs_work); diff --git a/drivers/thunderbolt/icm/net.c b/drivers/thunderbolt/icm/net.c index beeafb3..cf985dd 100644 --- a/drivers/thunderbolt/icm/net.c +++ b/drivers/thunderbolt/icm/net.c @@ -124,6 +124,17 @@ struct approve_inter_domain_connection_cmd { }; +struct tbt_frame_header { + /* size of the data with the frame */ + __le32 frame_size; + /* running index on the frames */ + __le16 frame_index; + /* ID of the frame to match frames to specific packet */ + __le16 frame_id; + /* how many frames assembles a full packet */ + __le32 frame_count; +}; + enum neg_event { RECEIVE_LOGOUT = NUM_MEDIUM_STATUSES, RECEIVE_LOGIN_RESPONSE, @@ -131,15 +142,81 @@ enum neg_event { NUM_NEG_EVENTS }; +enum frame_status { + GOOD_FRAME, + GOOD_AS_FIRST_FRAME, + GOOD_AS_FIRST_MULTICAST_FRAME, + FRAME_NOT_READY, + FRAME_ERROR, +}; + +enum packet_filter { + /* all multicast MAC addresses */ + PACKET_TYPE_ALL_MULTICAST, + /* all types of MAC addresses: multicast, unicast and broadcast */ + PACKET_TYPE_PROMISCUOUS, + /* all unicast MAC addresses */ + PACKET_TYPE_UNICAST_PROMISCUOUS, +}; + enum disconnect_path_stage { STAGE_1 = BIT(0), STAGE_2 = BIT(1) }; +struct tbt_net_stats { + u64 tx_packets; + u64 tx_bytes; + u64 tx_errors; + u64 rx_packets; + u64 rx_bytes; + u64 rx_length_errors; + u64 rx_over_errors; + u64 rx_crc_errors; + u64 rx_missed_errors; + u64 multicast; +}; + +static const char tbt_net_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_packets", + "tx_bytes", + "tx_errors", + "rx_packets", + "rx_bytes", +
[PATCH v8 2/8] thunderbolt: Updating the register definitions
Adding more Thunderbolt(TM) register definitions and some helper macros. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 109 + 1 file changed, 109 insertions(+) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 75cf069..b8e961f 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -9,6 +9,11 @@ #include +#define NHI_MMIO_BAR 0 + +#define TBT_RING_MIN_NUM_BUFFERS 2 +#define TBT_RING_MAX_FRAME_SIZE(4 * 1024) + enum ring_flags { RING_FLAG_ISOCH_ENABLE = 1 << 27, /* TX only? */ RING_FLAG_E2E_FLOW_CONTROL = 1 << 28, @@ -39,6 +44,33 @@ struct ring_desc { u32 time; /* write zero */ } __packed; +/** + * struct tbt_buf_desc - TX/RX ring buffer descriptor. + * This is same as struct ring_desc, but without the use of bitfields and + * with explicit endianity. + */ +struct tbt_buf_desc { + __le64 phys; + __le32 attributes; + __le32 time; +}; + +#define DESC_ATTR_LEN_SHIFT0 +#define DESC_ATTR_LEN_MASK GENMASK(11, DESC_ATTR_LEN_SHIFT) +#define DESC_ATTR_EOF_SHIFT12 +#define DESC_ATTR_EOF_MASK GENMASK(15, DESC_ATTR_EOF_SHIFT) +#define DESC_ATTR_SOF_SHIFT16 +#define DESC_ATTR_SOF_MASK GENMASK(19, DESC_ATTR_SOF_SHIFT) +#define DESC_ATTR_TX_ISOCH_DMA_EN BIT(20) /* TX */ +#define DESC_ATTR_RX_CRC_ERR BIT(20) /* RX after use */ +#define DESC_ATTR_DESC_DONEBIT(21) +#define DESC_ATTR_REQ_STS BIT(22) /* TX and RX before use */ +#define DESC_ATTR_RX_BUF_OVRN_ERR BIT(22) /* RX after use */ +#define DESC_ATTR_INT_EN BIT(23) +#define DESC_ATTR_OFFSET_SHIFT 24 +#define DESC_ATTR_OFFSET_MASK GENMASK(31, DESC_ATTR_OFFSET_SHIFT) + + /* NHI registers in bar 0 */ /* @@ -60,6 +92,30 @@ struct ring_desc { */ #define REG_RX_RING_BASE 0x08000 +#define REG_RING_STEP 16 +#define REG_RING_PHYS_LO_OFFSET0 +#define REG_RING_PHYS_HI_OFFSET4 +#define REG_RING_CONS_PROD_OFFSET 8 /* cons - RO, prod - RW */ +#define REG_RING_CONS_SHIFT0 +#define REG_RING_CONS_MASK GENMASK(15, REG_RING_CONS_SHIFT) +#define REG_RING_PROD_SHIFT16 +#define REG_RING_PROD_MASK GENMASK(31, REG_RING_PROD_SHIFT) +#define REG_RING_SIZE_OFFSET 12 +#define REG_RING_SIZE_SHIFT0 +#define REG_RING_SIZE_MASK GENMASK(15, REG_RING_SIZE_SHIFT) +#define REG_RING_BUF_SIZE_SHIFT16 +#define REG_RING_BUF_SIZE_MASK GENMASK(27, REG_RING_BUF_SIZE_SHIFT) + +#define TBT_RING_CONS_PROD_REG(iobase, ringbase, ringnumber) \ + ((iobase) + (ringbase) + \ + ((ringnumber) * REG_RING_STEP) + \ + REG_RING_CONS_PROD_OFFSET) + +#define TBT_REG_RING_PROD_EXTRACT(val) (((val) & REG_RING_PROD_MASK) >> \ + REG_RING_PROD_SHIFT) + +#define TBT_REG_RING_CONS_EXTRACT(val) (((val) & REG_RING_CONS_MASK) >> \ + REG_RING_CONS_SHIFT) /* * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) * 00: enum_ring_flags @@ -77,6 +133,19 @@ struct ring_desc { * ..: unknown */ #define REG_RX_OPTIONS_BASE0x29800 +#define REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT12 +#define REG_RX_OPTS_TX_E2E_HOP_ID_MASK \ + GENMASK(22, REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT) +#define REG_RX_OPTS_MASK_OFFSET4 +#define REG_RX_OPTS_MASK_EOF_SHIFT 0 +#define REG_RX_OPTS_MASK_EOF_MASK GENMASK(15, REG_RX_OPTS_MASK_EOF_SHIFT) +#define REG_RX_OPTS_MASK_SOF_SHIFT 16 +#define REG_RX_OPTS_MASK_SOF_MASK GENMASK(31, REG_RX_OPTS_MASK_SOF_SHIFT) + +#define REG_OPTS_STEP 32 +#define REG_OPTS_E2E_ENBIT(28) +#define REG_OPTS_RAW BIT(30) +#define REG_OPTS_VALID BIT(31) /* * three bitfields: tx, rx, rx overflow @@ -86,6 +155,7 @@ struct ring_desc { */ #define REG_RING_NOTIFY_BASE 0x37800 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32) +#define REG_RING_NOTIFY_STEP 4 /* * two bitfields: rx, tx @@ -94,8 +164,47 @@ struct ring_desc { */ #define REG_RING_INTERRUPT_BASE0x38200 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32) +#define REG_RING_INT_TX_PROCESSED(ring_num)BIT(ring_num) +#define REG_RING_INT_RX_PROCESSED(ring_num, num_paths) BIT((ring_num) + \ + (num_paths)) +#define RING_INT_DISABLE(base, val) iowrite32( \ + ioread32((base) + REG_RING_INTERRUPT_BASE) & ~(val), \ + (base) + REG_RING_IN
[PATCH v8 0/8] thunderbolt: Introducing Thunderbolt(TM) Networking
This driver enables Thunderbolt Networking on non-Apple platforms running Linux. Thunderbolt Networking provides peer-to-peer connections to transfer files between computers, perform PC migrations, and/or set up small workgroups with shared storage. This is a virtual connection that emulates an Ethernet adapter that enables Ethernet networking with the benefit of Thunderbolt superfast medium capability. Thunderbolt Networking enables two hosts and several devices that have a Thunderbolt controller to be connected together in a linear (Daisy chain) series from a single port. Thunderbolt Networking for Linux is compatible with Thunderbolt Networking on systems running macOS or Windows and also supports Thunderbolt generation 2 and 3 controllers. Note that all pre-existing Thunderbolt generation 3 features, such as USB, Display and other Thunderbolt device connectivity will continue to function exactly as they did prior to enabling Thunderbolt Networking. Code and Software Specifications: This kernel code creates a virtual ethernet device for computer to computer communication over a Thunderbolt cable. The new driver is a separate driver to the existing Thunderbolt driver. It is designed to work on systems running Linux that interface with Intel Connection Manager (ICM) firmware based Thunderbolt controllers that support Thunderbolt Networking. The kernel code operates in coordination with the Thunderbolt user- space daemon to implement full Thunderbolt networking functionality. Hardware Specifications: Thunderbolt Hardware specs have not yet been published but are used where necessary for register definitions. Changes since v7: - Removed debug prints - Edited error prints - Edited copyright notice - Changed the Kconfig patch to be after the code changes These patches were pushed to GitHub where they can be reviewed more comfortably with green/red highlighting: https://github.com/01org/thunderbolt-software-kernel-tree Daemon code: https://github.com/01org/thunderbolt-software-daemon For reference, here's a link to version 6: [v7]: https://lkml.org/lkml/2016/9/27/244 Amir Levy (8): thunderbolt: Macro rename thunderbolt: Updating the register definitions thunderbolt: Communication with the ICM (firmware) thunderbolt: Networking state machine thunderbolt: Networking transmit and receive thunderbolt: Kconfig for Thunderbolt Networking thunderbolt: Networking doc thunderbolt: Adding maintainer entry Documentation/00-INDEX |2 + Documentation/thunderbolt/networking.txt | 132 ++ MAINTAINERS |8 +- drivers/thunderbolt/Kconfig | 27 +- drivers/thunderbolt/Makefile |3 +- drivers/thunderbolt/icm/Makefile |2 + drivers/thunderbolt/icm/icm_nhi.c| 1514 drivers/thunderbolt/icm/icm_nhi.h| 82 ++ drivers/thunderbolt/icm/net.c| 2254 ++ drivers/thunderbolt/icm/net.h| 287 drivers/thunderbolt/nhi_regs.h | 115 +- 11 files changed, 4417 insertions(+), 9 deletions(-) create mode 100644 Documentation/thunderbolt/networking.txt create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.c create mode 100644 drivers/thunderbolt/icm/net.h -- 2.7.4
[PATCH v7 3/8] thunderbolt: Kconfig for Thunderbolt Networking
Update to the Kconfig Thunderbolt description to add Thunderbolt networking as an option. The menu item "Thunderbolt support" now offers: "Apple Hardware Support" (existing) and/or "Thunderbolt Networking" (new) You can choose the driver for your platform or build both drivers - each driver will detect if it can run on the specific platform. If the Thunderbolt Networking option is chosen, Thunderbolt Networking will be enabled between Linux non-Apple systems, macOS and Windows based systems. Thunderbolt Networking will not affect any other Thunderbolt feature that was previous available to Linux users on either Apple or non-Apple platforms. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Kconfig | 27 +++ drivers/thunderbolt/Makefile | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index c121acc..376e5bb 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -1,13 +1,32 @@ -menuconfig THUNDERBOLT - tristate "Thunderbolt support for Apple devices" +config THUNDERBOLT + tristate "Thunderbolt support" depends on PCI select CRC32 help - Cactus Ridge Thunderbolt Controller driver + Thunderbolt Controller driver + +if THUNDERBOLT + +config THUNDERBOLT_APPLE + tristate "Apple hardware support" + help This driver is required if you want to hotplug Thunderbolt devices on Apple hardware. Device chaining is currently not supported. - To compile this driver a module, choose M here. The module will be + To compile this driver as a module, choose M here. The module will be called thunderbolt. + +config THUNDERBOLT_ICM + tristate "Thunderbolt Networking" + help + This driver is required if you want Thunderbolt Networking on + non-Apple hardware. + It creates a virtual Ethernet device that enables computer to + computer communication over a Thunderbolt cable. + + To compile this driver as a module, choose M here. The module will be + called thunderbolt_icm. + +endif diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 5d1053c..7a85bd1 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,3 @@ -obj-${CONFIG_THUNDERBOLT} := thunderbolt.o +obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o -- 2.7.4
[PATCH v7 2/8] thunderbolt: Updating the register definitions
Adding more Thunderbolt(TM) register definitions and some helper macros. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 109 + 1 file changed, 109 insertions(+) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 75cf069..b8e961f 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -9,6 +9,11 @@ #include +#define NHI_MMIO_BAR 0 + +#define TBT_RING_MIN_NUM_BUFFERS 2 +#define TBT_RING_MAX_FRAME_SIZE(4 * 1024) + enum ring_flags { RING_FLAG_ISOCH_ENABLE = 1 << 27, /* TX only? */ RING_FLAG_E2E_FLOW_CONTROL = 1 << 28, @@ -39,6 +44,33 @@ struct ring_desc { u32 time; /* write zero */ } __packed; +/** + * struct tbt_buf_desc - TX/RX ring buffer descriptor. + * This is same as struct ring_desc, but without the use of bitfields and + * with explicit endianity. + */ +struct tbt_buf_desc { + __le64 phys; + __le32 attributes; + __le32 time; +}; + +#define DESC_ATTR_LEN_SHIFT0 +#define DESC_ATTR_LEN_MASK GENMASK(11, DESC_ATTR_LEN_SHIFT) +#define DESC_ATTR_EOF_SHIFT12 +#define DESC_ATTR_EOF_MASK GENMASK(15, DESC_ATTR_EOF_SHIFT) +#define DESC_ATTR_SOF_SHIFT16 +#define DESC_ATTR_SOF_MASK GENMASK(19, DESC_ATTR_SOF_SHIFT) +#define DESC_ATTR_TX_ISOCH_DMA_EN BIT(20) /* TX */ +#define DESC_ATTR_RX_CRC_ERR BIT(20) /* RX after use */ +#define DESC_ATTR_DESC_DONEBIT(21) +#define DESC_ATTR_REQ_STS BIT(22) /* TX and RX before use */ +#define DESC_ATTR_RX_BUF_OVRN_ERR BIT(22) /* RX after use */ +#define DESC_ATTR_INT_EN BIT(23) +#define DESC_ATTR_OFFSET_SHIFT 24 +#define DESC_ATTR_OFFSET_MASK GENMASK(31, DESC_ATTR_OFFSET_SHIFT) + + /* NHI registers in bar 0 */ /* @@ -60,6 +92,30 @@ struct ring_desc { */ #define REG_RX_RING_BASE 0x08000 +#define REG_RING_STEP 16 +#define REG_RING_PHYS_LO_OFFSET0 +#define REG_RING_PHYS_HI_OFFSET4 +#define REG_RING_CONS_PROD_OFFSET 8 /* cons - RO, prod - RW */ +#define REG_RING_CONS_SHIFT0 +#define REG_RING_CONS_MASK GENMASK(15, REG_RING_CONS_SHIFT) +#define REG_RING_PROD_SHIFT16 +#define REG_RING_PROD_MASK GENMASK(31, REG_RING_PROD_SHIFT) +#define REG_RING_SIZE_OFFSET 12 +#define REG_RING_SIZE_SHIFT0 +#define REG_RING_SIZE_MASK GENMASK(15, REG_RING_SIZE_SHIFT) +#define REG_RING_BUF_SIZE_SHIFT16 +#define REG_RING_BUF_SIZE_MASK GENMASK(27, REG_RING_BUF_SIZE_SHIFT) + +#define TBT_RING_CONS_PROD_REG(iobase, ringbase, ringnumber) \ + ((iobase) + (ringbase) + \ + ((ringnumber) * REG_RING_STEP) + \ + REG_RING_CONS_PROD_OFFSET) + +#define TBT_REG_RING_PROD_EXTRACT(val) (((val) & REG_RING_PROD_MASK) >> \ + REG_RING_PROD_SHIFT) + +#define TBT_REG_RING_CONS_EXTRACT(val) (((val) & REG_RING_CONS_MASK) >> \ + REG_RING_CONS_SHIFT) /* * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) * 00: enum_ring_flags @@ -77,6 +133,19 @@ struct ring_desc { * ..: unknown */ #define REG_RX_OPTIONS_BASE0x29800 +#define REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT12 +#define REG_RX_OPTS_TX_E2E_HOP_ID_MASK \ + GENMASK(22, REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT) +#define REG_RX_OPTS_MASK_OFFSET4 +#define REG_RX_OPTS_MASK_EOF_SHIFT 0 +#define REG_RX_OPTS_MASK_EOF_MASK GENMASK(15, REG_RX_OPTS_MASK_EOF_SHIFT) +#define REG_RX_OPTS_MASK_SOF_SHIFT 16 +#define REG_RX_OPTS_MASK_SOF_MASK GENMASK(31, REG_RX_OPTS_MASK_SOF_SHIFT) + +#define REG_OPTS_STEP 32 +#define REG_OPTS_E2E_ENBIT(28) +#define REG_OPTS_RAW BIT(30) +#define REG_OPTS_VALID BIT(31) /* * three bitfields: tx, rx, rx overflow @@ -86,6 +155,7 @@ struct ring_desc { */ #define REG_RING_NOTIFY_BASE 0x37800 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32) +#define REG_RING_NOTIFY_STEP 4 /* * two bitfields: rx, tx @@ -94,8 +164,47 @@ struct ring_desc { */ #define REG_RING_INTERRUPT_BASE0x38200 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32) +#define REG_RING_INT_TX_PROCESSED(ring_num)BIT(ring_num) +#define REG_RING_INT_RX_PROCESSED(ring_num, num_paths) BIT((ring_num) + \ + (num_paths)) +#define RING_INT_DISABLE(base, val) iowrite32( \ + ioread32((base) + REG_RING_INTERRUPT_BASE) & ~(val), \ + (base) + REG_RING_IN
[PATCH v7 4/8] thunderbolt: Communication with the ICM (firmware)
This patch provides the communication protocol between the Intel Connection Manager(ICM) firmware that is operational in the Thunderbolt controller in non-Apple hardware. The ICM firmware-based controller is used for establishing and maintaining the Thunderbolt Networking connection - we need to be able to communicate with it. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Makefile |1 + drivers/thunderbolt/icm/Makefile |2 + drivers/thunderbolt/icm/icm_nhi.c | 1324 + drivers/thunderbolt/icm/icm_nhi.h | 92 +++ drivers/thunderbolt/icm/net.h | 227 +++ 5 files changed, 1646 insertions(+) create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.h diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 7a85bd1..b6aa6a3 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,4 @@ obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o +obj-${CONFIG_THUNDERBOLT_ICM} += icm/ diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile new file mode 100644 index 000..f0d0fbb --- /dev/null +++ b/drivers/thunderbolt/icm/Makefile @@ -0,0 +1,2 @@ +obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o +thunderbolt-icm-objs := icm_nhi.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c new file mode 100644 index 000..984aa7c --- /dev/null +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -0,0 +1,1324 @@ +/*** + * + * Intel Thunderbolt(TM) driver + * Copyright(c) 2014 - 2016 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + **/ + +#include +#include +#include +#include +#include "icm_nhi.h" +#include "net.h" + +#define NHI_GENL_VERSION 1 +#define NHI_GENL_NAME "thunderbolt" + +#define DEVICE_DATA(num_ports, dma_port, nvm_ver_offset, nvm_auth_on_boot,\ + support_full_e2e) \ + ((num_ports) | ((dma_port) << 4) | ((nvm_ver_offset) << 10) | \ +((nvm_auth_on_boot) << 22) | ((support_full_e2e) << 23)) +#define DEVICE_DATA_NUM_PORTS(device_data) ((device_data) & 0xf) +#define DEVICE_DATA_DMA_PORT(device_data) (((device_data) >> 4) & 0x3f) +#define DEVICE_DATA_NVM_VER_OFFSET(device_data) (((device_data) >> 10) & 0xfff) +#define DEVICE_DATA_NVM_AUTH_ON_BOOT(device_data) (((device_data) >> 22) & 0x1) +#define DEVICE_DATA_SUPPORT_FULL_E2E(device_data) (((device_data) >> 23) & 0x1) + +#define USEC_TO_256_NSECS(usec) DIV_ROUND_UP((usec) * NSEC_PER_USEC, 256) + +/* NHI genetlink commands */ +enum { + NHI_CMD_UNSPEC, + NHI_CMD_SUBSCRIBE, + NHI_CMD_UNSUBSCRIBE, + NHI_CMD_QUERY_INFORMATION, + NHI_CMD_MSG_TO_ICM, + NHI_CMD_MSG_FROM_ICM, + NHI_CMD_MAILBOX, + NHI_CMD_APPROVE_TBT_NETWORKING, + NHI_CMD_ICM_IN_SAFE_MODE, + __NHI_CMD_MAX, +}; +#define NHI_CMD_MAX (__NHI_CMD_MAX - 1) + +/* NHI genetlink policy */ +static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { + [NHI_ATTR_DRV_VERSION] = { .type = NLA_NUL_STRING, }, + [NHI_ATTR_NVM_VER_OFFSET] = { .type = NLA_U16, }, + [NHI_ATTR_NUM_PORTS]= { .type = NLA_U8, }, + [NHI_ATTR_DMA_PORT] = { .type = NLA_U8, }, + [NHI_ATTR_SUPPORT_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MAILBOX_CMD] = { .type = NLA_U32, }, + [NHI_ATTR_PDF] = { .type = NLA_U32, }, + [NHI_ATTR_MSG_TO_ICM] = { .type = NLA_BINARY, + .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_MSG_FROM_IC
[PATCH v7 1/8] thunderbolt: Macro rename
This first patch updates the NHI Thunderbolt controller registers file to reflect that it is not only for Cactus Ridge. No functional change intended. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> Signed-off-by: Andreas Noever <andreas.noe...@gmail.com> --- drivers/thunderbolt/nhi_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 86b996c..75cf069 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -1,11 +1,11 @@ /* - * Thunderbolt Cactus Ridge driver - NHI registers + * Thunderbolt driver - NHI registers * * Copyright (c) 2014 Andreas Noever <andreas.noe...@gmail.com> */ -#ifndef DSL3510_REGS_H_ -#define DSL3510_REGS_H_ +#ifndef NHI_REGS_H_ +#define NHI_REGS_H_ #include -- 2.7.4
[PATCH v7 0/8] thunderbolt: Introducing Thunderbolt(TM) Networking
This driver enables Thunderbolt Networking on non-Apple platforms running Linux. Thunderbolt Networking provides peer-to-peer connections to transfer files between computers, perform PC migrations, and/or set up small workgroups with shared storage. This is a virtual connection that emulates an Ethernet adapter that enables Ethernet networking with the benefit of Thunderbolt superfast medium capability. Thunderbolt Networking enables two hosts and several devices that have a Thunderbolt controller to be connected together in a linear (Daisy chain) series from a single port. Thunderbolt Networking for Linux is compatible with Thunderbolt Networking on systems running macOS or Windows and also supports Thunderbolt generation 2 and 3 controllers. Note that all pre-existing Thunderbolt generation 3 features, such as USB, Display and other Thunderbolt device connectivity will continue to function exactly as they did prior to enabling Thunderbolt Networking. Code and Software Specifications: This kernel code creates a virtual ethernet device for computer to computer communication over a Thunderbolt cable. The new driver is a separate driver to the existing Thunderbolt driver. It is designed to work on systems running Linux that interface with Intel Connection Manager (ICM) firmware based Thunderbolt controllers that support Thunderbolt Networking. The kernel code operates in coordination with the Thunderbolt user- space daemon to implement full Thunderbolt networking functionality. Hardware Specifications: Thunderbolt Hardware specs have not yet been published but are used where necessary for register definitions. Changes since v6: - Removed (TM) from Kconfig - Removed redundant DRV_NAME macro - Removed copyright notice from Makefile - Moved networking.txt file to Documentation/Thunderbolt/ - Edited patch descriptions - Edited documentation in networking.txt These patches were pushed to GitHub where they can be reviewed more comfortably with green/red highlighting: https://github.com/01org/thunderbolt-software-kernel-tree Daemon code: https://github.com/01org/thunderbolt-software-daemon For reference, here's a link to version 6: [v6]: https://lkml.org/lkml/2016/8/1/233 Amir Levy (8): thunderbolt: Macro rename thunderbolt: Updating the register definitions thunderbolt: Kconfig for Thunderbolt Networking thunderbolt: Communication with the ICM (firmware) thunderbolt: Networking state machine thunderbolt: Networking transmit and receive thunderbolt: Networking doc thunderbolt: Adding maintainer entry Documentation/00-INDEX |2 + Documentation/thunderbolt/networking.txt | 132 ++ MAINTAINERS |8 +- drivers/thunderbolt/Kconfig | 27 +- drivers/thunderbolt/Makefile |3 +- drivers/thunderbolt/icm/Makefile |2 + drivers/thunderbolt/icm/icm_nhi.c| 1622 + drivers/thunderbolt/icm/icm_nhi.h| 92 ++ drivers/thunderbolt/icm/net.c| 2264 ++ drivers/thunderbolt/icm/net.h| 297 drivers/thunderbolt/nhi_regs.h | 115 +- 11 files changed, 4555 insertions(+), 9 deletions(-) create mode 100644 Documentation/thunderbolt/networking.txt create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.c create mode 100644 drivers/thunderbolt/icm/net.h -- 2.7.4
[PATCH v7 8/8] thunderbolt: Adding maintainer entry
Add Amir Levy as maintainer for Thunderbolt(TM) ICM driver Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- MAINTAINERS | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 01bff8e..a4a4614 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10358,7 +10358,13 @@ F: include/uapi/linux/stm.h THUNDERBOLT DRIVER M: Andreas Noever <andreas.noe...@gmail.com> S: Maintained -F: drivers/thunderbolt/ +F: drivers/thunderbolt/* + +THUNDERBOLT ICM DRIVER +M: Amir Levy <amir.jer.l...@intel.com> +S: Maintained +F: drivers/thunderbolt/icm/ +F: Documentation/thunderbolt/networking.txt TI BQ27XXX POWER SUPPLY DRIVER R: Andrew F. Davis <a...@ti.com> -- 2.7.4
[PATCH v7 5/8] thunderbolt: Networking state machine
This patch builds the peer to peer communication path. Communication is established by a negotiation process whereby messages are sent back and forth between the peers until a connection is established. This includes the Thunderbolt Network driver communication with the second peer via Intel Connection Manager(ICM) firmware. ++++ |Host 1 ||Host 2 | |||| | +---+ || +---+ | | |Thunderbolt| || |Thunderbolt| | | |Networking | || |Networking | | | |Driver | || |Driver | | | +---+ || +---+ | | ^ || ^ | | | || | | | ++---+ || ++---+ | | |Thunderbolt | | || |Thunderbolt | | | | |Controller v | || |Controller v | | | | +---+ | || | +---+ | | | | |ICM|<-+-++-+>|ICM| | | | | +---+ | || | +---+ | | | ++ || ++ | ++++ Note that this patch only establishes the link between the two hosts and not Network Packet handling - this is dealt with in the next patch. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/Makefile | 2 +- drivers/thunderbolt/icm/icm_nhi.c | 303 ++- drivers/thunderbolt/icm/net.c | 793 ++ drivers/thunderbolt/icm/net.h | 70 4 files changed, 1157 insertions(+), 11 deletions(-) create mode 100644 drivers/thunderbolt/icm/net.c diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile index f0d0fbb..94a2797 100644 --- a/drivers/thunderbolt/icm/Makefile +++ b/drivers/thunderbolt/icm/Makefile @@ -1,2 +1,2 @@ obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o -thunderbolt-icm-objs := icm_nhi.o +thunderbolt-icm-objs := icm_nhi.o net.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index 984aa7c..578eb14 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -74,6 +74,12 @@ static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { .len = TBT_ICM_RING_MAX_FRAME_SIZE }, [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_LOCAL_ROUTE_STRING] = {.len = sizeof(struct route_string)}, + [NHI_ATTR_LOCAL_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_REMOTE_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_LOCAL_DEPTH] = { .type = NLA_U8, }, + [NHI_ATTR_ENABLE_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MATCH_FRAME_ID] = { .type = NLA_FLAG, }, }; /* NHI genetlink family */ @@ -522,6 +528,29 @@ int nhi_mailbox(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd, u32 data, bool deinit) return 0; } +static inline bool nhi_is_path_disconnected(u32 cmd, u8 num_ports) +{ + return (cmd >= DISCONNECT_PORT_A_INTER_DOMAIN_PATH && + cmd < (DISCONNECT_PORT_A_INTER_DOMAIN_PATH + num_ports)); +} + +static int nhi_mailbox_disconn_path(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd) + __releases(_list_mutex) +{ + struct port_net_dev *port; + u32 port_num = cmd - DISCONNECT_PORT_A_INTER_DOMAIN_PATH; + + port = &(nhi_ctxt->net_devices[port_num]); + mutex_lock(>state_mutex); + + mutex_unlock(_list_mutex); + port->medium_sts = MEDIUM_READY_FOR_APPROVAL; + if (port->net_dev) + negotiation_events(port->net_dev, MEDIUM_DISCONNECTED); + mutex_unlock(>state_mutex); + return 0; +} + static int nhi_mailbox_generic(struct tbt_nhi_ctxt *nhi_ctxt, u32 mb_cmd) __releases(_list_mutex) { @@ -571,13 +600,94 @@ static int nhi_genl_mailbox(__always_unused struct sk_buff *u_skb, return -ERESTART; nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); - if (nhi_ctxt && !nhi_ctxt->d0_exit) - return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + + /* rwsem is released later by the below functions */ + if (nhi_is_path_disconnected(cmd, nhi_ctxt->num_ports)) + return nhi_mailbox_disconn_path(nhi_ctxt, cmd); + else + return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + + } mutex_unlock(_list_mutex); return -ENODEV; } +
[PATCH v7 7/8] thunderbolt: Networking doc
Adding Thunderbolt(TM) networking documentation. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- Documentation/00-INDEX | 2 + Documentation/thunderbolt/networking.txt | 132 +++ 2 files changed, 134 insertions(+) create mode 100644 Documentation/thunderbolt/networking.txt diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index cb9a6c6..a448ba1 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -439,6 +439,8 @@ this_cpu_ops.txt - List rationale behind and the way to use this_cpu operations. thermal/ - directory with information on managing thermal issues (CPU/temp) +thunderbolt/ + - directory with info regarding Thunderbolt. trace/ - directory with info on tracing technologies within linux unaligned-memory-access.txt diff --git a/Documentation/thunderbolt/networking.txt b/Documentation/thunderbolt/networking.txt new file mode 100644 index 000..88d1c12 --- /dev/null +++ b/Documentation/thunderbolt/networking.txt @@ -0,0 +1,132 @@ +Intel Thunderbolt(TM) Networking driver +=== + +Copyright(c) 2013 - 2016 Intel Corporation. + +Contact Information: +Intel Thunderbolt mailing list <thunderbolt-softw...@lists.01.org> +Edited by Amir Levy <amir.jer.l...@intel.com> + +Overview + + +* The Thunderbolt Networking driver enables peer to peer networking on non-Apple + platforms running Linux. + +* The driver creates a virtual Ethernet device that enables computer to computer + communication over the Thunderbolt cable. + +* Using Thunderbolt Networking you can perform high speed file transfers between + computers, perform PC migrations and/or set up small workgroups with shared + storage without compromising any other Thunderbolt functionality. + +* The driver is located in drivers/thunderbolt/icm. + +* This driver will function only on non-Apple platforms with firmware based + Thunderbolt controllers that support Thunderbolt Networking. + + ++++ + |Host 1 ||Host 2 | + |||| + | +---+||+---+ | + | |Network||||Network| | + | |Stack ||||Stack | | + | +---+||+---+ | + | ^||^ | + | |||| | + | v||v | + | +---+ || +---+ | + | |Thunderbolt| || |Thunderbolt| | + | |Networking | || |Networking | | + | |Driver | || |Driver | | + | +---+ || +---+ | + | ^||^ | + | |||| | + | v||v | + | +---+ || +---+ | + | |Thunderbolt| || |Thunderbolt| | + | |Controller |<-++->|Controller | | + | |with ICM | || |with ICM | | + | |enabled| || |enabled| | + | +---+ || +---+ | + ++++ + +Files += + +The following files are located in the drivers/thunderbolt/icm directory: + +- icm_nhi.c/h: These files allow communication with the firmware (Intel + Connection Manager) based controller. They also create an interface for + netlink communication with a user space daemon. + +- net.c/net.h: These files implement the 'eth' interface for the + Thunderbolt(TM) Networking. + +Interface to User Space +=== + +The interface to the user space module is implemented through a Generic Netlink. +This is the communications protocol between the Thunderbolt driver and the user +space application. + +Note that this interface mediates user space communication with ICM. +(Existing Linux tools can be used to configure the network interface.) + +The Thunderbolt Daemon utilizes this interface to communicate with the driver. +To be accessed by the user space module, both kernel and user space modules +have to register with the same GENL_NAME. +For the purpose of the Thunderbolt Network driver, "thunderbolt" is used. +The registration is done at driver initialization time for all instances +of the Thunderbolt controllers. The communication is carried through pre-defined +Thunderbolt messages. Each specific message has a callback function that is +called when the related message is received. + +Message Definitions: +* NHI_CMD_UNSPEC: Not used. +* NHI_CMD_SUBSCRIBE: Subscription request from daemon to driver to open the + communication channel. +* NHI_CMD_UNSUBSCRIBE: Request from daemon to driver to unsubscribe and + to close communication channel. +* NHI_CMD_QUERY_INFORMATION: R
[PATCH v7 6/8] thunderbolt: Networking transmit and receive
This patch provides the handling interface for sending and receiving network packets between the hosts over the full communication route (using the communication path established in the previous patch). The Thunderbolt Network driver interfaces the Linux network stack and the hardware controller configuration to handle packet transmissions: ++++ |Host 1 ||Host 2 | |||| | +---+||+---+ | | |Network||||Network| | | |Stack ||||Stack | | | +---+||+---+ | | ^||^ | | |||| | | v||v | | +---+ || +---+ | | |Thunderbolt| || |Thunderbolt| | | |Networking | || |Networking | | | |Driver | || |Driver | | | +---+ || +---+ | | ^||^ | | |||| | | v||v | | +---+ || +---+ | | |Thunderbolt| || |Thunderbolt| | | |Controller |<-++->|Controller | | | +---+ || +---+ | ++++ Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/icm_nhi.c | 15 + drivers/thunderbolt/icm/net.c | 1471 + 2 files changed, 1486 insertions(+) diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index 578eb14..c181abf 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -1036,6 +1036,7 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) { struct tbt_nhi_ctxt *nhi_ctxt = data; u32 isr0, isr1, imr0, imr1; + int i; /* clear on read */ isr0 = ioread32(nhi_ctxt->iobase + REG_RING_NOTIFY_BASE); @@ -1058,6 +1059,20 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) spin_unlock(_ctxt->lock); + for (i = 0; i < nhi_ctxt->num_ports; ++i) { + struct net_device *net_dev = + nhi_ctxt->net_devices[i].net_dev; + if (net_dev) { + u8 path = PATH_FROM_PORT(nhi_ctxt->num_paths, i); + + if (isr0 & REG_RING_INT_RX_PROCESSED( + path, nhi_ctxt->num_paths)) + tbt_net_rx_msi(net_dev); + if (isr0 & REG_RING_INT_TX_PROCESSED(path)) + tbt_net_tx_msi(net_dev); + } + } + if (isr0 & REG_RING_INT_RX_PROCESSED(TBT_ICM_RING_NUM, nhi_ctxt->num_paths)) schedule_work(_ctxt->icm_msgs_work); diff --git a/drivers/thunderbolt/icm/net.c b/drivers/thunderbolt/icm/net.c index acf30ad..a0f3c4a 100644 --- a/drivers/thunderbolt/icm/net.c +++ b/drivers/thunderbolt/icm/net.c @@ -134,6 +134,17 @@ struct approve_inter_domain_connection_cmd { }; +struct tbt_frame_header { + /* size of the data with the frame */ + __le32 frame_size; + /* running index on the frames */ + __le16 frame_index; + /* ID of the frame to match frames to specific packet */ + __le16 frame_id; + /* how many frames assembles a full packet */ + __le32 frame_count; +}; + enum neg_event { RECEIVE_LOGOUT = NUM_MEDIUM_STATUSES, RECEIVE_LOGIN_RESPONSE, @@ -141,15 +152,81 @@ enum neg_event { NUM_NEG_EVENTS }; +enum frame_status { + GOOD_FRAME, + GOOD_AS_FIRST_FRAME, + GOOD_AS_FIRST_MULTICAST_FRAME, + FRAME_NOT_READY, + FRAME_ERROR, +}; + +enum packet_filter { + /* all multicast MAC addresses */ + PACKET_TYPE_ALL_MULTICAST, + /* all types of MAC addresses: multicast, unicast and broadcast */ + PACKET_TYPE_PROMISCUOUS, + /* all unicast MAC addresses */ + PACKET_TYPE_UNICAST_PROMISCUOUS, +}; + enum disconnect_path_stage { STAGE_1 = BIT(0), STAGE_2 = BIT(1) }; +struct tbt_net_stats { + u64 tx_packets; + u64 tx_bytes; + u64 tx_errors; + u64 rx_packets; + u64 rx_bytes; + u64 rx_length_errors; + u64 rx_over_errors; + u64 rx_crc_errors; + u64 rx_missed_errors; + u64 multicast; +}; + +static const char tbt_net_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_packets", + "tx_bytes", + "tx_errors", + "rx_packets", + "rx_bytes", +
[PATCH v6 8/8] thunderbolt: Adding maintainer entry
Add Amir Levy as maintainer for Thunderbolt(TM) ICM driver Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- MAINTAINERS | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 72f7703..2b6d635 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10193,7 +10193,13 @@ F: include/uapi/linux/stm.h THUNDERBOLT DRIVER M: Andreas Noever <andreas.noe...@gmail.com> S: Maintained -F: drivers/thunderbolt/ +F: drivers/thunderbolt/* + +THUNDERBOLT ICM DRIVER +M: Amir Levy <amir.jer.l...@intel.com> +S: Maintained +F: drivers/thunderbolt/icm/ +F: Documentation/thunderbolt-networking.txt TI BQ27XXX POWER SUPPLY DRIVER R: Andrew F. Davis <a...@ti.com> -- 2.7.4
[PATCH v6 3/8] thunderbolt: Kconfig for Thunderbolt(TM) networking
Updating the Kconfig Thunderbolt(TM) description. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Kconfig | 25 + drivers/thunderbolt/Makefile | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index c121acc..d34b0f5 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -1,13 +1,30 @@ -menuconfig THUNDERBOLT - tristate "Thunderbolt support for Apple devices" +config THUNDERBOLT + tristate "Thunderbolt(TM) support" depends on PCI select CRC32 help - Cactus Ridge Thunderbolt Controller driver + Thunderbolt(TM) Controller driver + +if THUNDERBOLT + +config THUNDERBOLT_APPLE + tristate "Apple hardware support" + help This driver is required if you want to hotplug Thunderbolt devices on Apple hardware. Device chaining is currently not supported. - To compile this driver a module, choose M here. The module will be + To compile this driver as a module, choose M here. The module will be called thunderbolt. + +config THUNDERBOLT_ICM + tristate "Thunderbolt(TM) Networking" + help + This driver is required if you want Thunderbolt(TM) Networking on + non-Apple hardware. + + To compile this driver as a module, choose M here. The module will be + called thunderbolt_icm. + +endif diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 5d1053c..7a85bd1 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,3 @@ -obj-${CONFIG_THUNDERBOLT} := thunderbolt.o +obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o -- 2.7.4
[PATCH v6 1/8] thunderbolt: Macro rename
This first patch updates the registers file to reflect that it isn't only for Cactus Ridge. No functional change intended. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 86b996c..75cf069 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -1,11 +1,11 @@ /* - * Thunderbolt Cactus Ridge driver - NHI registers + * Thunderbolt driver - NHI registers * * Copyright (c) 2014 Andreas Noever <andreas.noe...@gmail.com> */ -#ifndef DSL3510_REGS_H_ -#define DSL3510_REGS_H_ +#ifndef NHI_REGS_H_ +#define NHI_REGS_H_ #include -- 2.7.4
[PATCH v6 2/8] thunderbolt: Updating the register definitions
Adding more Thunderbolt(TM) register definitions and some helper macros. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 109 + 1 file changed, 109 insertions(+) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 75cf069..b8e961f 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -9,6 +9,11 @@ #include +#define NHI_MMIO_BAR 0 + +#define TBT_RING_MIN_NUM_BUFFERS 2 +#define TBT_RING_MAX_FRAME_SIZE(4 * 1024) + enum ring_flags { RING_FLAG_ISOCH_ENABLE = 1 << 27, /* TX only? */ RING_FLAG_E2E_FLOW_CONTROL = 1 << 28, @@ -39,6 +44,33 @@ struct ring_desc { u32 time; /* write zero */ } __packed; +/** + * struct tbt_buf_desc - TX/RX ring buffer descriptor. + * This is same as struct ring_desc, but without the use of bitfields and + * with explicit endianity. + */ +struct tbt_buf_desc { + __le64 phys; + __le32 attributes; + __le32 time; +}; + +#define DESC_ATTR_LEN_SHIFT0 +#define DESC_ATTR_LEN_MASK GENMASK(11, DESC_ATTR_LEN_SHIFT) +#define DESC_ATTR_EOF_SHIFT12 +#define DESC_ATTR_EOF_MASK GENMASK(15, DESC_ATTR_EOF_SHIFT) +#define DESC_ATTR_SOF_SHIFT16 +#define DESC_ATTR_SOF_MASK GENMASK(19, DESC_ATTR_SOF_SHIFT) +#define DESC_ATTR_TX_ISOCH_DMA_EN BIT(20) /* TX */ +#define DESC_ATTR_RX_CRC_ERR BIT(20) /* RX after use */ +#define DESC_ATTR_DESC_DONEBIT(21) +#define DESC_ATTR_REQ_STS BIT(22) /* TX and RX before use */ +#define DESC_ATTR_RX_BUF_OVRN_ERR BIT(22) /* RX after use */ +#define DESC_ATTR_INT_EN BIT(23) +#define DESC_ATTR_OFFSET_SHIFT 24 +#define DESC_ATTR_OFFSET_MASK GENMASK(31, DESC_ATTR_OFFSET_SHIFT) + + /* NHI registers in bar 0 */ /* @@ -60,6 +92,30 @@ struct ring_desc { */ #define REG_RX_RING_BASE 0x08000 +#define REG_RING_STEP 16 +#define REG_RING_PHYS_LO_OFFSET0 +#define REG_RING_PHYS_HI_OFFSET4 +#define REG_RING_CONS_PROD_OFFSET 8 /* cons - RO, prod - RW */ +#define REG_RING_CONS_SHIFT0 +#define REG_RING_CONS_MASK GENMASK(15, REG_RING_CONS_SHIFT) +#define REG_RING_PROD_SHIFT16 +#define REG_RING_PROD_MASK GENMASK(31, REG_RING_PROD_SHIFT) +#define REG_RING_SIZE_OFFSET 12 +#define REG_RING_SIZE_SHIFT0 +#define REG_RING_SIZE_MASK GENMASK(15, REG_RING_SIZE_SHIFT) +#define REG_RING_BUF_SIZE_SHIFT16 +#define REG_RING_BUF_SIZE_MASK GENMASK(27, REG_RING_BUF_SIZE_SHIFT) + +#define TBT_RING_CONS_PROD_REG(iobase, ringbase, ringnumber) \ + ((iobase) + (ringbase) + \ + ((ringnumber) * REG_RING_STEP) + \ + REG_RING_CONS_PROD_OFFSET) + +#define TBT_REG_RING_PROD_EXTRACT(val) (((val) & REG_RING_PROD_MASK) >> \ + REG_RING_PROD_SHIFT) + +#define TBT_REG_RING_CONS_EXTRACT(val) (((val) & REG_RING_CONS_MASK) >> \ + REG_RING_CONS_SHIFT) /* * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) * 00: enum_ring_flags @@ -77,6 +133,19 @@ struct ring_desc { * ..: unknown */ #define REG_RX_OPTIONS_BASE0x29800 +#define REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT12 +#define REG_RX_OPTS_TX_E2E_HOP_ID_MASK \ + GENMASK(22, REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT) +#define REG_RX_OPTS_MASK_OFFSET4 +#define REG_RX_OPTS_MASK_EOF_SHIFT 0 +#define REG_RX_OPTS_MASK_EOF_MASK GENMASK(15, REG_RX_OPTS_MASK_EOF_SHIFT) +#define REG_RX_OPTS_MASK_SOF_SHIFT 16 +#define REG_RX_OPTS_MASK_SOF_MASK GENMASK(31, REG_RX_OPTS_MASK_SOF_SHIFT) + +#define REG_OPTS_STEP 32 +#define REG_OPTS_E2E_ENBIT(28) +#define REG_OPTS_RAW BIT(30) +#define REG_OPTS_VALID BIT(31) /* * three bitfields: tx, rx, rx overflow @@ -86,6 +155,7 @@ struct ring_desc { */ #define REG_RING_NOTIFY_BASE 0x37800 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32) +#define REG_RING_NOTIFY_STEP 4 /* * two bitfields: rx, tx @@ -94,8 +164,47 @@ struct ring_desc { */ #define REG_RING_INTERRUPT_BASE0x38200 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32) +#define REG_RING_INT_TX_PROCESSED(ring_num)BIT(ring_num) +#define REG_RING_INT_RX_PROCESSED(ring_num, num_paths) BIT((ring_num) + \ + (num_paths)) +#define RING_INT_DISABLE(base, val) iowrite32( \ + ioread32((base) + REG_RING_INTERRUPT_BASE) & ~(val), \ + (base) + REG_RING_IN
[PATCH v6 5/8] thunderbolt: Networking state machine
Negotiation states that a peer goes through in order to establish the communication with the second peer. This includes communication with upper layer and additional infrastructure support to communicate with the second peer through ICM. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/Makefile | 2 +- drivers/thunderbolt/icm/icm_nhi.c | 303 ++- drivers/thunderbolt/icm/net.c | 793 ++ drivers/thunderbolt/icm/net.h | 70 4 files changed, 1157 insertions(+), 11 deletions(-) create mode 100644 drivers/thunderbolt/icm/net.c diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile index 3adfc35..624ee31 100644 --- a/drivers/thunderbolt/icm/Makefile +++ b/drivers/thunderbolt/icm/Makefile @@ -25,4 +25,4 @@ obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o -thunderbolt-icm-objs := icm_nhi.o +thunderbolt-icm-objs := icm_nhi.o net.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index bcb5c1b..b083f21c 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -74,6 +74,12 @@ static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { .len = TBT_ICM_RING_MAX_FRAME_SIZE }, [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_LOCAL_ROUTE_STRING] = {.len = sizeof(struct route_string)}, + [NHI_ATTR_LOCAL_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_REMOTE_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_LOCAL_DEPTH] = { .type = NLA_U8, }, + [NHI_ATTR_ENABLE_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MATCH_FRAME_ID] = { .type = NLA_FLAG, }, }; /* NHI genetlink family */ @@ -522,6 +528,29 @@ int nhi_mailbox(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd, u32 data, bool deinit) return 0; } +static inline bool nhi_is_path_disconnected(u32 cmd, u8 num_ports) +{ + return (cmd >= DISCONNECT_PORT_A_INTER_DOMAIN_PATH && + cmd < (DISCONNECT_PORT_A_INTER_DOMAIN_PATH + num_ports)); +} + +static int nhi_mailbox_disconn_path(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd) + __releases(_list_mutex) +{ + struct port_net_dev *port; + u32 port_num = cmd - DISCONNECT_PORT_A_INTER_DOMAIN_PATH; + + port = &(nhi_ctxt->net_devices[port_num]); + mutex_lock(>state_mutex); + + mutex_unlock(_list_mutex); + port->medium_sts = MEDIUM_READY_FOR_APPROVAL; + if (port->net_dev) + negotiation_events(port->net_dev, MEDIUM_DISCONNECTED); + mutex_unlock(>state_mutex); + return 0; +} + static int nhi_mailbox_generic(struct tbt_nhi_ctxt *nhi_ctxt, u32 mb_cmd) __releases(_list_mutex) { @@ -571,13 +600,94 @@ static int nhi_genl_mailbox(__always_unused struct sk_buff *u_skb, return -ERESTART; nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); - if (nhi_ctxt && !nhi_ctxt->d0_exit) - return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + + /* rwsem is released later by the below functions */ + if (nhi_is_path_disconnected(cmd, nhi_ctxt->num_ports)) + return nhi_mailbox_disconn_path(nhi_ctxt, cmd); + else + return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + + } mutex_unlock(_list_mutex); return -ENODEV; } +static int nhi_genl_approve_networking(__always_unused struct sk_buff *u_skb, + struct genl_info *info) +{ + struct tbt_nhi_ctxt *nhi_ctxt; + struct route_string *route_str; + int res = -ENODEV; + u8 port_num; + + if (!info || !info->userhdr || !info->attrs || + !info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING] || + !info->attrs[NHI_ATTR_LOCAL_UUID] || + !info->attrs[NHI_ATTR_REMOTE_UUID] || + !info->attrs[NHI_ATTR_LOCAL_DEPTH]) + return -EINVAL; + + /* +* route_str is an unique topological address +* used for approving remote controller +*/ + route_str = nla_data(info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING]); + /* extracts the port we're connected to */ + port_num = PORT_NUM_FROM_LINK(L0_PORT_NUM(route_str->lo)); + + if (mutex_lock_interruptible(_list_mutex)) + return -ERESTART; + + nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + struct port_net_dev *port; + + if (port_num
[PATCH v6 7/8] thunderbolt: Networking doc
Adding Thunderbolt(TM) networking documentation. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- Documentation/00-INDEX | 2 + Documentation/thunderbolt-networking.txt | 135 +++ 2 files changed, 137 insertions(+) create mode 100644 Documentation/thunderbolt-networking.txt diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index cb9a6c6..80a6706 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -439,6 +439,8 @@ this_cpu_ops.txt - List rationale behind and the way to use this_cpu operations. thermal/ - directory with information on managing thermal issues (CPU/temp) +thunderbolt-networking.txt + - Thunderbolt(TM) Networking driver description. trace/ - directory with info on tracing technologies within linux unaligned-memory-access.txt diff --git a/Documentation/thunderbolt-networking.txt b/Documentation/thunderbolt-networking.txt new file mode 100644 index 000..e112313 --- /dev/null +++ b/Documentation/thunderbolt-networking.txt @@ -0,0 +1,135 @@ +Intel Thunderbolt(TM) Linux driver +== + +Copyright(c) 2013 - 2016 Intel Corporation. + +Contact Information: +Intel Thunderbolt mailing list <thunderbolt-softw...@lists.01.org> +Edited by Michael Jamet <michael.ja...@intel.com> + +Overview + + +Thunderbolt(TM) Networking mode is introduced with this driver. +This kernel code creates an ethernet device utilized in computer to computer +communication over a Thunderbolt cable. +This driver has been added on the top of the existing thunderbolt driver +for systems with firwmare (FW) based Thunderbolt controllers supporting +Thunderbolt Networking. + +Files += + +- icm_nhi.c/h: These files allow communication with the FW (a.k.a ICM) based controller. + In addition, they create an interface for netlink communication with + a user space daemon. + +- net.c/net.h: These files implement the 'eth' interface for the Thunderbolt(TM) + networking. + +Interface to user space +=== + +The interface to the user space module is implemented through a Generic Netlink. +In order to be accessed by the user space module, both kernel and user space +modules have to register with the same GENL_NAME. In our case, this is +simply "thunderbolt". +The registration is done at driver initialization time for all instances of +the Thunderbolt controllers. +The communication is then carried through pre-defined Thunderbolt messages. +Each specific message has a callback function that is called when +the related message is received. + +The messages are defined as follows: +* NHI_CMD_UNSPEC: Not used. +* NHI_CMD_SUBSCRIBE: Subscription request from daemon to driver to open the + communication channel. +* NHI_CMD_UNSUBSCRIBE: Request from daemon to driver to unsubscribe + to close communication channel. +* NHI_CMD_QUERY_INFORMATION: Request information from the driver such as + driver version, FW version offset, number of ports in the controller + and DMA port. +* NHI_CMD_MSG_TO_ICM: Message from user space module to FW. +* NHI_CMD_MSG_FROM_ICM: Response from FW to user space module. +* NHI_CMD_MAILBOX: Message that uses mailbox mechanism such as FW policy + changes or disconnect path. +* NHI_CMD_APPROVE_TBT_NETWORKING: Request from user space + module to FW to establish path. +* NHI_CMD_ICM_IN_SAFE_MODE: Indication that the FW has entered safe mode. + +Communication with ICM (Firmware) += + +The communication with ICM is principally achieved through +a DMA mechanism on Ring 0. +The driver allocates a shared memory that is physically mapped onto +the DMA physical space at Ring 0. + +Interrupts +== + +Thunderbolt relies on MSI-X interrupts. +The MSI-X vector is allocated as follows: +ICM + - Tx: MSI-X vector index 0 + - Rx: MSI-X vector index 1 + +Port 0 + - Tx: MSI-X vector index 2 + - Rx: MSI-X vector index 3 + +Port 1 + - Tx: MSI-X vector index 4 + - Rx: MSI-X vector index 5 + +ICM interrupts are used for communication with ICM only. +Port 0 and Port 1 interrupts are used for Thunderbolt Networking +communications. +In case MSI-X is not available, the driver requests to enable MSI only. + +Mutexes, semaphores and spinlocks += + +The driver should be able to operate in an environment where hardware +is asynchronously accessed by multiple entities such as netlink, +multiple controllers etc. + +* send_sem: This semaphore enforces unique sender (one sender at a time) + to avoid wrong impairing with responses. FW may process one message + at the time. +* d0_exit_send_mutex: This mutex protects D0 exit (D3) situation + to avoid continuing to send messages to FW. +* d0_exit_mailbox_mutex: This mutex protects D0 exit (D3) situation to + avoid continuing to send commands to mailbox. +* mailbo
[PATCH v6 0/8] thunderbolt: Introducing Thunderbolt(TM) networking
This is version 6 of Thunderbolt(TM) driver for non-Apple hardware. Changes since v5: - Removed the padding of short packets in receive - Replaced RW semaphore with mutex - Cleanup These patches were pushed to GitHub where they can be reviewed more comfortably with green/red highlighting: https://github.com/01org/thunderbolt-software-kernel-tree Daemon code: https://github.com/01org/thunderbolt-software-daemon For reference, here's a link to version 5: [v5]: https://lkml.org/lkml/2016/7/28/85 Amir Levy (8): thunderbolt: Macro rename thunderbolt: Updating the register definitions thunderbolt: Kconfig for Thunderbolt(TM) networking thunderbolt: Communication with the ICM (firmware) thunderbolt: Networking state machine thunderbolt: Networking transmit and receive thunderbolt: Networking doc thunderbolt: Adding maintainer entry Documentation/00-INDEX |2 + Documentation/thunderbolt-networking.txt | 135 ++ MAINTAINERS |8 +- drivers/thunderbolt/Kconfig | 25 +- drivers/thunderbolt/Makefile |3 +- drivers/thunderbolt/icm/Makefile | 28 + drivers/thunderbolt/icm/icm_nhi.c| 1622 + drivers/thunderbolt/icm/icm_nhi.h| 93 ++ drivers/thunderbolt/icm/net.c| 2264 ++ drivers/thunderbolt/icm/net.h| 297 drivers/thunderbolt/nhi_regs.h | 115 +- 11 files changed, 4583 insertions(+), 9 deletions(-) create mode 100644 Documentation/thunderbolt-networking.txt create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.c create mode 100644 drivers/thunderbolt/icm/net.h -- 2.7.4
[PATCH v6 4/8] thunderbolt: Communication with the ICM (firmware)
Firmware-based (a.k.a ICM - Intel Connection Manager) controller is used for establishing and maintaining the Thunderbolt Networking connection. We need to be able to communicate with it. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Makefile |1 + drivers/thunderbolt/icm/Makefile | 28 + drivers/thunderbolt/icm/icm_nhi.c | 1324 + drivers/thunderbolt/icm/icm_nhi.h | 93 +++ drivers/thunderbolt/icm/net.h | 227 +++ 5 files changed, 1673 insertions(+) create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.h diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 7a85bd1..b6aa6a3 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,4 @@ obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o +obj-${CONFIG_THUNDERBOLT_ICM} += icm/ diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile new file mode 100644 index 000..3adfc35 --- /dev/null +++ b/drivers/thunderbolt/icm/Makefile @@ -0,0 +1,28 @@ + +# +# Intel Thunderbolt(TM) driver +# Copyright(c) 2014 - 2016 Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# The full GNU General Public License is included in this distribution in +# the file called "COPYING". +# +# Contact Information: +# Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> +# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +# + + +obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o +thunderbolt-icm-objs := icm_nhi.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c new file mode 100644 index 000..bcb5c1b --- /dev/null +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -0,0 +1,1324 @@ +/*** + * + * Intel Thunderbolt(TM) driver + * Copyright(c) 2014 - 2016 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + **/ + +#include +#include +#include +#include +#include "icm_nhi.h" +#include "net.h" + +#define NHI_GENL_VERSION 1 +#define NHI_GENL_NAME DRV_NAME + +#define DEVICE_DATA(num_ports, dma_port, nvm_ver_offset, nvm_auth_on_boot,\ + support_full_e2e) \ + ((num_ports) | ((dma_port) << 4) | ((nvm_ver_offset) << 10) | \ +((nvm_auth_on_boot) << 22) | ((support_full_e2e) << 23)) +#define DEVICE_DATA_NUM_PORTS(device_data) ((device_data) & 0xf) +#define DEVICE_DATA_DMA_PORT(device_data) (((device_data) >> 4) & 0x3f) +#define DEVICE_DATA_NVM_VER_OFFSET(device_data) (((device_data) >> 10) & 0xfff) +#define DEVICE_DATA_NVM_AUTH_ON_BOOT(device_data) (((device_data) >> 22) & 0x1) +#define DEVICE_DATA_SUPPORT_FULL_E2E(device_data) (((device_data) >> 23) & 0x1) + +#define USEC_TO_256_NSECS(usec) DIV_ROUND_UP((usec) * NSEC_PER_USEC, 256) + +/* NHI genetlink commands */ +enum { + NHI_CMD_UNSPEC, + NHI_CMD_SUBSCRIBE, +
[PATCH v5 3/8] thunderbolt: Kconfig for Thunderbolt(TM) networking
Updating the Kconfig Thunderbolt(TM) description. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Kconfig | 25 + drivers/thunderbolt/Makefile | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index c121acc..d34b0f5 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -1,13 +1,30 @@ -menuconfig THUNDERBOLT - tristate "Thunderbolt support for Apple devices" +config THUNDERBOLT + tristate "Thunderbolt(TM) support" depends on PCI select CRC32 help - Cactus Ridge Thunderbolt Controller driver + Thunderbolt(TM) Controller driver + +if THUNDERBOLT + +config THUNDERBOLT_APPLE + tristate "Apple hardware support" + help This driver is required if you want to hotplug Thunderbolt devices on Apple hardware. Device chaining is currently not supported. - To compile this driver a module, choose M here. The module will be + To compile this driver as a module, choose M here. The module will be called thunderbolt. + +config THUNDERBOLT_ICM + tristate "Thunderbolt(TM) Networking" + help + This driver is required if you want Thunderbolt(TM) Networking on + non-Apple hardware. + + To compile this driver as a module, choose M here. The module will be + called thunderbolt_icm. + +endif diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 5d1053c..7a85bd1 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,3 @@ -obj-${CONFIG_THUNDERBOLT} := thunderbolt.o +obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o -- 2.7.4
[PATCH v5 5/8] thunderbolt: Networking state machine
Negotiation states that a peer goes through in order to establish the communication with the second peer. This includes communication with upper layer and additional infrastructure support to communicate with the second peer through ICM. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/Makefile | 2 +- drivers/thunderbolt/icm/icm_nhi.c | 303 ++- drivers/thunderbolt/icm/net.c | 792 ++ drivers/thunderbolt/icm/net.h | 70 4 files changed, 1156 insertions(+), 11 deletions(-) create mode 100644 drivers/thunderbolt/icm/net.c diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile index 3adfc35..624ee31 100644 --- a/drivers/thunderbolt/icm/Makefile +++ b/drivers/thunderbolt/icm/Makefile @@ -25,4 +25,4 @@ obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o -thunderbolt-icm-objs := icm_nhi.o +thunderbolt-icm-objs := icm_nhi.o net.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index 2106dea..e491b0e 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -101,6 +101,12 @@ static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { .len = TBT_ICM_RING_MAX_FRAME_SIZE }, [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_LOCAL_ROUTE_STRING] = {.len = sizeof(struct route_string)}, + [NHI_ATTR_LOCAL_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_REMOTE_UUID] = { .len = sizeof(uuid_be) }, + [NHI_ATTR_LOCAL_DEPTH] = { .type = NLA_U8, }, + [NHI_ATTR_ENABLE_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MATCH_FRAME_ID] = { .type = NLA_FLAG, }, }; /* NHI genetlink family */ @@ -542,6 +548,29 @@ int nhi_mailbox(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd, u32 data, bool deinit) return 0; } +static inline bool nhi_is_path_disconnected(u32 cmd, u8 num_ports) +{ + return (cmd >= DISCONNECT_PORT_A_INTER_DOMAIN_PATH && + cmd < (DISCONNECT_PORT_A_INTER_DOMAIN_PATH + num_ports)); +} + +static int nhi_mailbox_disconn_path(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd) + __releases(_list_rwsem) +{ + struct port_net_dev *port; + u32 port_num = cmd - DISCONNECT_PORT_A_INTER_DOMAIN_PATH; + + port = &(nhi_ctxt->net_devices[port_num]); + mutex_lock(>state_mutex); + + up_read(_list_rwsem); + port->medium_sts = MEDIUM_READY_FOR_APPROVAL; + if (port->net_dev) + negotiation_events(port->net_dev, MEDIUM_DISCONNECTED); + mutex_unlock(>state_mutex); + return 0; +} + static int nhi_mailbox_generic(struct tbt_nhi_ctxt *nhi_ctxt, u32 mb_cmd) __releases(_list_rwsem) { @@ -590,13 +619,93 @@ static int nhi_genl_mailbox(__always_unused struct sk_buff *u_skb, down_read(_list_rwsem); nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); - if (nhi_ctxt && !nhi_ctxt->d0_exit) - return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + + /* rwsem is released later by the below functions */ + if (nhi_is_path_disconnected(cmd, nhi_ctxt->num_ports)) + return nhi_mailbox_disconn_path(nhi_ctxt, cmd); + else + return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + + } up_read(_list_rwsem); return -ENODEV; } +static int nhi_genl_approve_networking(__always_unused struct sk_buff *u_skb, + struct genl_info *info) +{ + struct tbt_nhi_ctxt *nhi_ctxt; + struct route_string *route_str; + int res = -ENODEV; + u8 port_num; + + if (!info || !info->userhdr || !info->attrs || + !info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING] || + !info->attrs[NHI_ATTR_LOCAL_UUID] || + !info->attrs[NHI_ATTR_REMOTE_UUID] || + !info->attrs[NHI_ATTR_LOCAL_DEPTH]) + return -EINVAL; + + /* +* route_str is an unique topological address +* used for approving remote controller +*/ + route_str = nla_data(info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING]); + /* extracts the port we're connected to */ + port_num = PORT_NUM_FROM_LINK(L0_PORT_NUM(route_str->lo)); + + down_read(_list_rwsem); + + nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + struct port_net_dev *port; + + if (port_num >= nhi_ctxt->num_ports) { + res = -EINVAL; +
[PATCH v5 8/8] thunderbolt: Adding maintainer entry
Add Amir Levy as maintainer for Thunderbolt(TM) ICM driver Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- MAINTAINERS | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 771c31c..5f24eb2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -10141,7 +10141,13 @@ F: include/uapi/linux/stm.h THUNDERBOLT DRIVER M: Andreas Noever <andreas.noe...@gmail.com> S: Maintained -F: drivers/thunderbolt/ +F: drivers/thunderbolt/* + +THUNDERBOLT ICM DRIVER +M: Amir Levy <amir.jer.l...@intel.com> +S: Maintained +F: drivers/thunderbolt/icm/ +F: Documentation/thunderbolt-networking.txt TI BQ27XXX POWER SUPPLY DRIVER R: Andrew F. Davis <a...@ti.com> -- 2.7.4
[PATCH v5 4/8] thunderbolt: Communication with the ICM (firmware)
Firmware-based (a.k.a ICM - Intel Connection Manager) controller is used for establishing and maintaining the Thunderbolt Networking connection. We need to be able to communicate with it. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Makefile |1 + drivers/thunderbolt/icm/Makefile | 28 + drivers/thunderbolt/icm/icm_nhi.c | 1343 + drivers/thunderbolt/icm/icm_nhi.h | 93 +++ drivers/thunderbolt/icm/net.h | 200 ++ 5 files changed, 1665 insertions(+) create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.h diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 7a85bd1..b6aa6a3 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,4 @@ obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o +obj-${CONFIG_THUNDERBOLT_ICM} += icm/ diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile new file mode 100644 index 000..3adfc35 --- /dev/null +++ b/drivers/thunderbolt/icm/Makefile @@ -0,0 +1,28 @@ + +# +# Intel Thunderbolt(TM) driver +# Copyright(c) 2014 - 2016 Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# The full GNU General Public License is included in this distribution in +# the file called "COPYING". +# +# Contact Information: +# Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> +# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +# + + +obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o +thunderbolt-icm-objs := icm_nhi.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c new file mode 100644 index 000..2106dea --- /dev/null +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -0,0 +1,1343 @@ +/*** + * + * Intel Thunderbolt(TM) driver + * Copyright(c) 2014 - 2016 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + **/ + +#include +#include +#include +#include +#include "icm_nhi.h" +#include "net.h" + +#define NHI_GENL_VERSION 1 +#define NHI_GENL_NAME DRV_NAME + +#define DEVICE_DATA(num_ports, dma_port, nvm_ver_offset, nvm_auth_on_boot,\ + support_full_e2e) \ + ((num_ports) | ((dma_port) << 4) | ((nvm_ver_offset) << 10) | \ +((nvm_auth_on_boot) << 22) | ((support_full_e2e) << 23)) +#define DEVICE_DATA_NUM_PORTS(device_data) ((device_data) & 0xf) +#define DEVICE_DATA_DMA_PORT(device_data) (((device_data) >> 4) & 0x3f) +#define DEVICE_DATA_NVM_VER_OFFSET(device_data) (((device_data) >> 10) & 0xfff) +#define DEVICE_DATA_NVM_AUTH_ON_BOOT(device_data) (((device_data) >> 22) & 0x1) +#define DEVICE_DATA_SUPPORT_FULL_E2E(device_data) (((device_data) >> 23) & 0x1) + +#define USEC_TO_256_NSECS(usec) DIV_ROUND_UP((usec) * NSEC_PER_USEC, 256) + +/* + * FW->SW responses + * RC = response code + */ +enum { + RC_GET_TBT_
[PATCH v5 7/8] thunderbolt: Networking doc
Adding Thunderbolt(TM) networking documentation. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- Documentation/00-INDEX | 2 + Documentation/thunderbolt-networking.txt | 135 +++ 2 files changed, 137 insertions(+) create mode 100644 Documentation/thunderbolt-networking.txt diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index cb9a6c6..80a6706 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -439,6 +439,8 @@ this_cpu_ops.txt - List rationale behind and the way to use this_cpu operations. thermal/ - directory with information on managing thermal issues (CPU/temp) +thunderbolt-networking.txt + - Thunderbolt(TM) Networking driver description. trace/ - directory with info on tracing technologies within linux unaligned-memory-access.txt diff --git a/Documentation/thunderbolt-networking.txt b/Documentation/thunderbolt-networking.txt new file mode 100644 index 000..b7714cf --- /dev/null +++ b/Documentation/thunderbolt-networking.txt @@ -0,0 +1,135 @@ +Intel Thunderbolt(TM) Linux driver +== + +Copyright(c) 2013 - 2016 Intel Corporation. + +Contact Information: +Intel Thunderbolt mailing list <thunderbolt-softw...@lists.01.org> +Edited by Michael Jamet <michael.ja...@intel.com> + +Overview + + +Thunderbolt(TM) Networking mode is introduced with this driver. +This kernel code creates an ethernet device utilized in computer to computer +communication over a Thunderbolt cable. +This driver has been added on the top of the existing thunderbolt driver +for systems with firwmare (FW) based Thunderbolt controllers supporting +Thunderbolt Networking. + +Files += + +- icm_nhi.c/h: These files allow communication with the FW (a.k.a ICM) based controller. + In addition, they create an interface for netlink communication with + a user space daemon. + +- net.c/net.h: These files implement the 'eth' interface for the Thunderbolt(TM) + networking. + +Interface to user space +=== + +The interface to the user space module is implemented through a Generic Netlink. +In order to be accessed by the user space module, both kernel and user space +modules have to register with the same GENL_NAME. In our case, this is +simply "thunderbolt". +The registration is done at driver initialization time for all instances of +the Thunderbolt controllers. +The communication is then carried through pre-defined Thunderbolt messages. +Each specific message has a callback function that is called when +the related message is received. + +The messages are defined as follows: +* NHI_CMD_UNSPEC: Not used. +* NHI_CMD_SUBSCRIBE: Subscription request from daemon to driver to open the + communication channel. +* NHI_CMD_UNSUBSCRIBE: Request from daemon to driver to unsubscribe + to close communication channel. +* NHI_CMD_QUERY_INFORMATION: Request information from the driver such as + driver version, FW version offset, number of ports in the controller + and DMA port. +* NHI_CMD_MSG_TO_ICM: Message from user space module to FW. +* NHI_CMD_MSG_FROM_ICM: Response from FW to user space module. +* NHI_CMD_MAILBOX: Message that uses mailbox mechanism such as FW policy + changes or disconnect path. +* NHI_CMD_APPROVE_TBT_NETWORKING: Request from user space + module to FW to establish path. +* NHI_CMD_ICM_IN_SAFE_MODE: Indication that the FW has entered safe mode. + +Communication with ICM (Firmware) += + +The communication with ICM is principally achieved through +a DMA mechanism on Ring 0. +The driver allocates a shared memory that is physically mapped onto +the DMA physical space at Ring 0. + +Interrupts +== + +Thunderbolt relies on MSI-X interrupts. +The MSI-X vector is allocated as follows: +ICM + - Tx: MSI-X vector index 0 + - Rx: MSI-X vector index 1 + +Port 0 + - Tx: MSI-X vector index 2 + - Rx: MSI-X vector index 3 + +Port 1 + - Tx: MSI-X vector index 4 + - Rx: MSI-X vector index 5 + +ICM interrupts are used for communication with ICM only. +Port 0 and Port 1 interrupts are used for Thunderbolt Networking +communications. +In case MSI-X is not available, the driver requests to enable MSI only. + +Mutexes, semaphores and spinlocks += + +The driver should be able to operate in an environment where hardware +is asynchronously accessed by multiple entities such as netlink, +multiple controllers etc. + +* send_sem: This semaphore enforces unique sender (one sender at a time) + to avoid wrong impairing with responses. FW may process one message + at the time. +* d0_exit_send_mutex: This mutex protects D0 exit (D3) situation + to avoid continuing to send messages to FW. +* d0_exit_mailbox_mutex: This mutex protects D0 exit (D3) situation to + avoid continuing to send commands to mailbox. +* mailbo
[PATCH v5 2/8] thunderbolt: Updating the register definitions
Adding more Thunderbolt(TM) register definitions and some helper macros. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 109 + 1 file changed, 109 insertions(+) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 75cf069..b8e961f 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -9,6 +9,11 @@ #include +#define NHI_MMIO_BAR 0 + +#define TBT_RING_MIN_NUM_BUFFERS 2 +#define TBT_RING_MAX_FRAME_SIZE(4 * 1024) + enum ring_flags { RING_FLAG_ISOCH_ENABLE = 1 << 27, /* TX only? */ RING_FLAG_E2E_FLOW_CONTROL = 1 << 28, @@ -39,6 +44,33 @@ struct ring_desc { u32 time; /* write zero */ } __packed; +/** + * struct tbt_buf_desc - TX/RX ring buffer descriptor. + * This is same as struct ring_desc, but without the use of bitfields and + * with explicit endianity. + */ +struct tbt_buf_desc { + __le64 phys; + __le32 attributes; + __le32 time; +}; + +#define DESC_ATTR_LEN_SHIFT0 +#define DESC_ATTR_LEN_MASK GENMASK(11, DESC_ATTR_LEN_SHIFT) +#define DESC_ATTR_EOF_SHIFT12 +#define DESC_ATTR_EOF_MASK GENMASK(15, DESC_ATTR_EOF_SHIFT) +#define DESC_ATTR_SOF_SHIFT16 +#define DESC_ATTR_SOF_MASK GENMASK(19, DESC_ATTR_SOF_SHIFT) +#define DESC_ATTR_TX_ISOCH_DMA_EN BIT(20) /* TX */ +#define DESC_ATTR_RX_CRC_ERR BIT(20) /* RX after use */ +#define DESC_ATTR_DESC_DONEBIT(21) +#define DESC_ATTR_REQ_STS BIT(22) /* TX and RX before use */ +#define DESC_ATTR_RX_BUF_OVRN_ERR BIT(22) /* RX after use */ +#define DESC_ATTR_INT_EN BIT(23) +#define DESC_ATTR_OFFSET_SHIFT 24 +#define DESC_ATTR_OFFSET_MASK GENMASK(31, DESC_ATTR_OFFSET_SHIFT) + + /* NHI registers in bar 0 */ /* @@ -60,6 +92,30 @@ struct ring_desc { */ #define REG_RX_RING_BASE 0x08000 +#define REG_RING_STEP 16 +#define REG_RING_PHYS_LO_OFFSET0 +#define REG_RING_PHYS_HI_OFFSET4 +#define REG_RING_CONS_PROD_OFFSET 8 /* cons - RO, prod - RW */ +#define REG_RING_CONS_SHIFT0 +#define REG_RING_CONS_MASK GENMASK(15, REG_RING_CONS_SHIFT) +#define REG_RING_PROD_SHIFT16 +#define REG_RING_PROD_MASK GENMASK(31, REG_RING_PROD_SHIFT) +#define REG_RING_SIZE_OFFSET 12 +#define REG_RING_SIZE_SHIFT0 +#define REG_RING_SIZE_MASK GENMASK(15, REG_RING_SIZE_SHIFT) +#define REG_RING_BUF_SIZE_SHIFT16 +#define REG_RING_BUF_SIZE_MASK GENMASK(27, REG_RING_BUF_SIZE_SHIFT) + +#define TBT_RING_CONS_PROD_REG(iobase, ringbase, ringnumber) \ + ((iobase) + (ringbase) + \ + ((ringnumber) * REG_RING_STEP) + \ + REG_RING_CONS_PROD_OFFSET) + +#define TBT_REG_RING_PROD_EXTRACT(val) (((val) & REG_RING_PROD_MASK) >> \ + REG_RING_PROD_SHIFT) + +#define TBT_REG_RING_CONS_EXTRACT(val) (((val) & REG_RING_CONS_MASK) >> \ + REG_RING_CONS_SHIFT) /* * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) * 00: enum_ring_flags @@ -77,6 +133,19 @@ struct ring_desc { * ..: unknown */ #define REG_RX_OPTIONS_BASE0x29800 +#define REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT12 +#define REG_RX_OPTS_TX_E2E_HOP_ID_MASK \ + GENMASK(22, REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT) +#define REG_RX_OPTS_MASK_OFFSET4 +#define REG_RX_OPTS_MASK_EOF_SHIFT 0 +#define REG_RX_OPTS_MASK_EOF_MASK GENMASK(15, REG_RX_OPTS_MASK_EOF_SHIFT) +#define REG_RX_OPTS_MASK_SOF_SHIFT 16 +#define REG_RX_OPTS_MASK_SOF_MASK GENMASK(31, REG_RX_OPTS_MASK_SOF_SHIFT) + +#define REG_OPTS_STEP 32 +#define REG_OPTS_E2E_ENBIT(28) +#define REG_OPTS_RAW BIT(30) +#define REG_OPTS_VALID BIT(31) /* * three bitfields: tx, rx, rx overflow @@ -86,6 +155,7 @@ struct ring_desc { */ #define REG_RING_NOTIFY_BASE 0x37800 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32) +#define REG_RING_NOTIFY_STEP 4 /* * two bitfields: rx, tx @@ -94,8 +164,47 @@ struct ring_desc { */ #define REG_RING_INTERRUPT_BASE0x38200 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32) +#define REG_RING_INT_TX_PROCESSED(ring_num)BIT(ring_num) +#define REG_RING_INT_RX_PROCESSED(ring_num, num_paths) BIT((ring_num) + \ + (num_paths)) +#define RING_INT_DISABLE(base, val) iowrite32( \ + ioread32((base) + REG_RING_INTERRUPT_BASE) & ~(val), \ + (base) + REG_RING_IN
[PATCH v5 6/8] thunderbolt: Networking transmit and receive
Handling the transmission to second peer and receiving from it. This includes communication with upper layer, the network stack and configuration of Thunderbolt(TM) HW. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/icm_nhi.c | 15 + drivers/thunderbolt/icm/net.c | 1475 + 2 files changed, 1490 insertions(+) diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index e491b0e..efadf9c 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -1055,6 +1055,7 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) { struct tbt_nhi_ctxt *nhi_ctxt = data; u32 isr0, isr1, imr0, imr1; + int i; /* clear on read */ isr0 = ioread32(nhi_ctxt->iobase + REG_RING_NOTIFY_BASE); @@ -1077,6 +1078,20 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) spin_unlock(_ctxt->lock); + for (i = 0; i < nhi_ctxt->num_ports; ++i) { + struct net_device *net_dev = + nhi_ctxt->net_devices[i].net_dev; + if (net_dev) { + u8 path = PATH_FROM_PORT(nhi_ctxt->num_paths, i); + + if (isr0 & REG_RING_INT_RX_PROCESSED( + path, nhi_ctxt->num_paths)) + tbt_net_rx_msi(net_dev); + if (isr0 & REG_RING_INT_TX_PROCESSED(path)) + tbt_net_tx_msi(net_dev); + } + } + if (isr0 & REG_RING_INT_RX_PROCESSED(TBT_ICM_RING_NUM, nhi_ctxt->num_paths)) schedule_work(_ctxt->icm_msgs_work); diff --git a/drivers/thunderbolt/icm/net.c b/drivers/thunderbolt/icm/net.c index 75801b5..6ce7c18 100644 --- a/drivers/thunderbolt/icm/net.c +++ b/drivers/thunderbolt/icm/net.c @@ -134,6 +134,17 @@ struct approve_inter_domain_connection_cmd { }; +struct tbt_frame_header { + /* size of the data with the frame */ + __le32 frame_size; + /* running index on the frames */ + __le16 frame_index; + /* ID of the frame to match frames to specific packet */ + __le16 frame_id; + /* how many frames assembles a full packet */ + __le32 frame_count; +}; + enum neg_event { RECEIVE_LOGOUT = NUM_MEDIUM_STATUSES, RECEIVE_LOGIN_RESPONSE, @@ -141,15 +152,81 @@ enum neg_event { NUM_NEG_EVENTS }; +enum frame_status { + GOOD_FRAME, + GOOD_AS_FIRST_FRAME, + GOOD_AS_FIRST_MULTICAST_FRAME, + FRAME_NOT_READY, + FRAME_ERROR, +}; + +enum packet_filter { + /* all multicast MAC addresses */ + PACKET_TYPE_ALL_MULTICAST, + /* all types of MAC addresses: multicast, unicast and broadcast */ + PACKET_TYPE_PROMISCUOUS, + /* all unicast MAC addresses */ + PACKET_TYPE_UNICAST_PROMISCUOUS, +}; + enum disconnect_path_stage { STAGE_1 = BIT(0), STAGE_2 = BIT(1) }; +struct tbt_net_stats { + u64 tx_packets; + u64 tx_bytes; + u64 tx_errors; + u64 rx_packets; + u64 rx_bytes; + u64 rx_length_errors; + u64 rx_over_errors; + u64 rx_crc_errors; + u64 rx_missed_errors; + u64 multicast; +}; + +static const char tbt_net_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_packets", + "tx_bytes", + "tx_errors", + "rx_packets", + "rx_bytes", + "rx_length_errors", + "rx_over_errors", + "rx_crc_errors", + "rx_missed_errors", + "multicast", +}; + +struct tbt_buffer { + dma_addr_t dma; + union { + struct tbt_frame_header *hdr; + struct page *page; + }; + u32 page_offset; +}; + +struct tbt_desc_ring { + /* pointer to the descriptor ring memory */ + struct tbt_buf_desc *desc; + /* physical address of the descriptor ring */ + dma_addr_t dma; + /* array of buffer structs */ + struct tbt_buffer *buffers; + /* last descriptor that was associated with a buffer */ + u16 last_allocated; + /* next descriptor to check for DD status bit */ + u16 next_to_clean; +}; + /** * struct tbt_port - the basic tbt_port structure * @tbt_nhi_ctxt: context of the nhi controller. * @net_dev: networking device object. +* @napi: network API * @login_retry_work: work queue for sending login requests. * @login_response_work: work queue for sending login responses. * @work_struct logout_work: work queue for sending logout requests. @@ -165,6 +242,11 @@ enum disconnect_path_stage { * @login_retry_count: counts number of login r
[PATCH v5 1/8] thunderbolt: Macro rename
This first patch updates the registers file to reflect that it isn't only for Cactus Ridge. No functional change intended. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 86b996c..75cf069 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -1,11 +1,11 @@ /* - * Thunderbolt Cactus Ridge driver - NHI registers + * Thunderbolt driver - NHI registers * * Copyright (c) 2014 Andreas Noever <andreas.noe...@gmail.com> */ -#ifndef DSL3510_REGS_H_ -#define DSL3510_REGS_H_ +#ifndef NHI_REGS_H_ +#define NHI_REGS_H_ #include -- 2.7.4
[PATCH v5 0/8] thunderbolt: Introducing Thunderbolt(TM) networking
This is version 5 of Thunderbolt(TM) driver for non-Apple hardware. Changes since v4: - Added Amir Levy as maintainer of thunderbolt/icm - Replaced private uuid definitions with uuid_be These patches were pushed to GitHub where they can be reviewed more comfortably with green/red highlighting: https://github.com/01org/thunderbolt-software-kernel-tree Daemon code: https://github.com/01org/thunderbolt-software-daemon For reference, here's a link to version 4: [v4]: https://lkml.org/lkml/2016/7/18/171 Amir Levy (8): thunderbolt: Macro rename thunderbolt: Updating the register definitions thunderbolt: Kconfig for Thunderbolt(TM) networking thunderbolt: Communication with the ICM (firmware) thunderbolt: Networking state machine thunderbolt: Networking transmit and receive thunderbolt: Networking doc thunderbolt: Adding maintainer entry Documentation/00-INDEX |2 + Documentation/thunderbolt-networking.txt | 135 ++ MAINTAINERS |8 +- drivers/thunderbolt/Kconfig | 25 +- drivers/thunderbolt/Makefile |3 +- drivers/thunderbolt/icm/Makefile | 28 + drivers/thunderbolt/icm/icm_nhi.c| 1641 + drivers/thunderbolt/icm/icm_nhi.h| 93 ++ drivers/thunderbolt/icm/net.c| 2267 ++ drivers/thunderbolt/icm/net.h| 270 drivers/thunderbolt/nhi_regs.h | 115 +- 11 files changed, 4578 insertions(+), 9 deletions(-) create mode 100644 Documentation/thunderbolt-networking.txt create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.c create mode 100644 drivers/thunderbolt/icm/net.h -- 2.7.4
[PATCH v4 3/7] thunderbolt: Kconfig for Thunderbolt(TM) networking
Updating the Kconfig Thunderbolt(TM) description. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Kconfig | 25 + drivers/thunderbolt/Makefile | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index c121acc..d34b0f5 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -1,13 +1,30 @@ -menuconfig THUNDERBOLT - tristate "Thunderbolt support for Apple devices" +config THUNDERBOLT + tristate "Thunderbolt(TM) support" depends on PCI select CRC32 help - Cactus Ridge Thunderbolt Controller driver + Thunderbolt(TM) Controller driver + +if THUNDERBOLT + +config THUNDERBOLT_APPLE + tristate "Apple hardware support" + help This driver is required if you want to hotplug Thunderbolt devices on Apple hardware. Device chaining is currently not supported. - To compile this driver a module, choose M here. The module will be + To compile this driver as a module, choose M here. The module will be called thunderbolt. + +config THUNDERBOLT_ICM + tristate "Thunderbolt(TM) Networking" + help + This driver is required if you want Thunderbolt(TM) Networking on + non-Apple hardware. + + To compile this driver as a module, choose M here. The module will be + called thunderbolt_icm. + +endif diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 5d1053c..7a85bd1 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,3 @@ -obj-${CONFIG_THUNDERBOLT} := thunderbolt.o +obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o -- 2.7.4
[PATCH v4 1/7] thunderbolt: Macro rename
This first patch updates the registers file to reflect that it isn't only for Cactus Ridge. No functional change intended. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 86b996c..75cf069 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -1,11 +1,11 @@ /* - * Thunderbolt Cactus Ridge driver - NHI registers + * Thunderbolt driver - NHI registers * * Copyright (c) 2014 Andreas Noever <andreas.noe...@gmail.com> */ -#ifndef DSL3510_REGS_H_ -#define DSL3510_REGS_H_ +#ifndef NHI_REGS_H_ +#define NHI_REGS_H_ #include -- 2.7.4
[PATCH v4 4/7] thunderbolt: Communication with the ICM (firmware)
Firmware-based (a.k.a ICM - Intel Connection Manager) controller is used for establishing and maintaining the Thunderbolt Networking connection. We need to be able to communicate with it. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Makefile |1 + drivers/thunderbolt/icm/Makefile | 28 + drivers/thunderbolt/icm/icm_nhi.c | 1343 + drivers/thunderbolt/icm/icm_nhi.h | 93 +++ drivers/thunderbolt/icm/net.h | 200 ++ 5 files changed, 1665 insertions(+) create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.h diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 7a85bd1..b6aa6a3 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,4 @@ obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o +obj-${CONFIG_THUNDERBOLT_ICM} += icm/ diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile new file mode 100644 index 000..3adfc35 --- /dev/null +++ b/drivers/thunderbolt/icm/Makefile @@ -0,0 +1,28 @@ + +# +# Intel Thunderbolt(TM) driver +# Copyright(c) 2014 - 2016 Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# The full GNU General Public License is included in this distribution in +# the file called "COPYING". +# +# Contact Information: +# Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> +# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +# + + +obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o +thunderbolt-icm-objs := icm_nhi.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c new file mode 100644 index 000..2106dea --- /dev/null +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -0,0 +1,1343 @@ +/*** + * + * Intel Thunderbolt(TM) driver + * Copyright(c) 2014 - 2016 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + **/ + +#include +#include +#include +#include +#include "icm_nhi.h" +#include "net.h" + +#define NHI_GENL_VERSION 1 +#define NHI_GENL_NAME DRV_NAME + +#define DEVICE_DATA(num_ports, dma_port, nvm_ver_offset, nvm_auth_on_boot,\ + support_full_e2e) \ + ((num_ports) | ((dma_port) << 4) | ((nvm_ver_offset) << 10) | \ +((nvm_auth_on_boot) << 22) | ((support_full_e2e) << 23)) +#define DEVICE_DATA_NUM_PORTS(device_data) ((device_data) & 0xf) +#define DEVICE_DATA_DMA_PORT(device_data) (((device_data) >> 4) & 0x3f) +#define DEVICE_DATA_NVM_VER_OFFSET(device_data) (((device_data) >> 10) & 0xfff) +#define DEVICE_DATA_NVM_AUTH_ON_BOOT(device_data) (((device_data) >> 22) & 0x1) +#define DEVICE_DATA_SUPPORT_FULL_E2E(device_data) (((device_data) >> 23) & 0x1) + +#define USEC_TO_256_NSECS(usec) DIV_ROUND_UP((usec) * NSEC_PER_USEC, 256) + +/* + * FW->SW responses + * RC = response code + */ +enum { + RC_GET_TBT_
[PATCH v4 6/7] thunderbolt: Networking transmit and receive
Handling the transmission to second peer and receiving from it. This includes communication with upper layer, the network stack and configuration of Thunderbolt(TM) HW. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/icm_nhi.c | 15 + drivers/thunderbolt/icm/net.c | 1475 + 2 files changed, 1490 insertions(+) diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index 1bee701..052b348 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -1056,6 +1056,7 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) { struct tbt_nhi_ctxt *nhi_ctxt = data; u32 isr0, isr1, imr0, imr1; + int i; /* clear on read */ isr0 = ioread32(nhi_ctxt->iobase + REG_RING_NOTIFY_BASE); @@ -1078,6 +1079,20 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) spin_unlock(_ctxt->lock); + for (i = 0; i < nhi_ctxt->num_ports; ++i) { + struct net_device *net_dev = + nhi_ctxt->net_devices[i].net_dev; + if (net_dev) { + u8 path = PATH_FROM_PORT(nhi_ctxt->num_paths, i); + + if (isr0 & REG_RING_INT_RX_PROCESSED( + path, nhi_ctxt->num_paths)) + tbt_net_rx_msi(net_dev); + if (isr0 & REG_RING_INT_TX_PROCESSED(path)) + tbt_net_tx_msi(net_dev); + } + } + if (isr0 & REG_RING_INT_RX_PROCESSED(TBT_ICM_RING_NUM, nhi_ctxt->num_paths)) schedule_work(_ctxt->icm_msgs_work); diff --git a/drivers/thunderbolt/icm/net.c b/drivers/thunderbolt/icm/net.c index 1ac0b1f..0fd24f5 100644 --- a/drivers/thunderbolt/icm/net.c +++ b/drivers/thunderbolt/icm/net.c @@ -134,6 +134,17 @@ struct approve_inter_domain_connection_cmd { }; +struct tbt_frame_header { + /* size of the data with the frame */ + __le32 frame_size; + /* running index on the frames */ + __le16 frame_index; + /* ID of the frame to match frames to specific packet */ + __le16 frame_id; + /* how many frames assembles a full packet */ + __le32 frame_count; +}; + enum neg_event { RECEIVE_LOGOUT = NUM_MEDIUM_STATUSES, RECEIVE_LOGIN_RESPONSE, @@ -141,15 +152,81 @@ enum neg_event { NUM_NEG_EVENTS }; +enum frame_status { + GOOD_FRAME, + GOOD_AS_FIRST_FRAME, + GOOD_AS_FIRST_MULTICAST_FRAME, + FRAME_NOT_READY, + FRAME_ERROR, +}; + +enum packet_filter { + /* all multicast MAC addresses */ + PACKET_TYPE_ALL_MULTICAST, + /* all types of MAC addresses: multicast, unicast and broadcast */ + PACKET_TYPE_PROMISCUOUS, + /* all unicast MAC addresses */ + PACKET_TYPE_UNICAST_PROMISCUOUS, +}; + enum disconnect_path_stage { STAGE_1 = BIT(0), STAGE_2 = BIT(1) }; +struct tbt_net_stats { + u64 tx_packets; + u64 tx_bytes; + u64 tx_errors; + u64 rx_packets; + u64 rx_bytes; + u64 rx_length_errors; + u64 rx_over_errors; + u64 rx_crc_errors; + u64 rx_missed_errors; + u64 multicast; +}; + +static const char tbt_net_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_packets", + "tx_bytes", + "tx_errors", + "rx_packets", + "rx_bytes", + "rx_length_errors", + "rx_over_errors", + "rx_crc_errors", + "rx_missed_errors", + "multicast", +}; + +struct tbt_buffer { + dma_addr_t dma; + union { + struct tbt_frame_header *hdr; + struct page *page; + }; + u32 page_offset; +}; + +struct tbt_desc_ring { + /* pointer to the descriptor ring memory */ + struct tbt_buf_desc *desc; + /* physical address of the descriptor ring */ + dma_addr_t dma; + /* array of buffer structs */ + struct tbt_buffer *buffers; + /* last descriptor that was associated with a buffer */ + u16 last_allocated; + /* next descriptor to check for DD status bit */ + u16 next_to_clean; +}; + /** * struct tbt_port - the basic tbt_port structure * @tbt_nhi_ctxt: context of the nhi controller. * @net_dev: networking device object. +* @napi: network API * @login_retry_work: work queue for sending login requests. * @login_response_work: work queue for sending login responses. * @work_struct logout_work: work queue for sending logout requests. @@ -165,6 +242,11 @@ enum disconnect_path_stage { * @login_retry_count: counts number of login r
[PATCH v4 2/7] thunderbolt: Updating the register definitions
Adding more Thunderbolt(TM) register definitions and some helper macros. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 109 + 1 file changed, 109 insertions(+) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 75cf069..b8e961f 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -9,6 +9,11 @@ #include +#define NHI_MMIO_BAR 0 + +#define TBT_RING_MIN_NUM_BUFFERS 2 +#define TBT_RING_MAX_FRAME_SIZE(4 * 1024) + enum ring_flags { RING_FLAG_ISOCH_ENABLE = 1 << 27, /* TX only? */ RING_FLAG_E2E_FLOW_CONTROL = 1 << 28, @@ -39,6 +44,33 @@ struct ring_desc { u32 time; /* write zero */ } __packed; +/** + * struct tbt_buf_desc - TX/RX ring buffer descriptor. + * This is same as struct ring_desc, but without the use of bitfields and + * with explicit endianity. + */ +struct tbt_buf_desc { + __le64 phys; + __le32 attributes; + __le32 time; +}; + +#define DESC_ATTR_LEN_SHIFT0 +#define DESC_ATTR_LEN_MASK GENMASK(11, DESC_ATTR_LEN_SHIFT) +#define DESC_ATTR_EOF_SHIFT12 +#define DESC_ATTR_EOF_MASK GENMASK(15, DESC_ATTR_EOF_SHIFT) +#define DESC_ATTR_SOF_SHIFT16 +#define DESC_ATTR_SOF_MASK GENMASK(19, DESC_ATTR_SOF_SHIFT) +#define DESC_ATTR_TX_ISOCH_DMA_EN BIT(20) /* TX */ +#define DESC_ATTR_RX_CRC_ERR BIT(20) /* RX after use */ +#define DESC_ATTR_DESC_DONEBIT(21) +#define DESC_ATTR_REQ_STS BIT(22) /* TX and RX before use */ +#define DESC_ATTR_RX_BUF_OVRN_ERR BIT(22) /* RX after use */ +#define DESC_ATTR_INT_EN BIT(23) +#define DESC_ATTR_OFFSET_SHIFT 24 +#define DESC_ATTR_OFFSET_MASK GENMASK(31, DESC_ATTR_OFFSET_SHIFT) + + /* NHI registers in bar 0 */ /* @@ -60,6 +92,30 @@ struct ring_desc { */ #define REG_RX_RING_BASE 0x08000 +#define REG_RING_STEP 16 +#define REG_RING_PHYS_LO_OFFSET0 +#define REG_RING_PHYS_HI_OFFSET4 +#define REG_RING_CONS_PROD_OFFSET 8 /* cons - RO, prod - RW */ +#define REG_RING_CONS_SHIFT0 +#define REG_RING_CONS_MASK GENMASK(15, REG_RING_CONS_SHIFT) +#define REG_RING_PROD_SHIFT16 +#define REG_RING_PROD_MASK GENMASK(31, REG_RING_PROD_SHIFT) +#define REG_RING_SIZE_OFFSET 12 +#define REG_RING_SIZE_SHIFT0 +#define REG_RING_SIZE_MASK GENMASK(15, REG_RING_SIZE_SHIFT) +#define REG_RING_BUF_SIZE_SHIFT16 +#define REG_RING_BUF_SIZE_MASK GENMASK(27, REG_RING_BUF_SIZE_SHIFT) + +#define TBT_RING_CONS_PROD_REG(iobase, ringbase, ringnumber) \ + ((iobase) + (ringbase) + \ + ((ringnumber) * REG_RING_STEP) + \ + REG_RING_CONS_PROD_OFFSET) + +#define TBT_REG_RING_PROD_EXTRACT(val) (((val) & REG_RING_PROD_MASK) >> \ + REG_RING_PROD_SHIFT) + +#define TBT_REG_RING_CONS_EXTRACT(val) (((val) & REG_RING_CONS_MASK) >> \ + REG_RING_CONS_SHIFT) /* * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) * 00: enum_ring_flags @@ -77,6 +133,19 @@ struct ring_desc { * ..: unknown */ #define REG_RX_OPTIONS_BASE0x29800 +#define REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT12 +#define REG_RX_OPTS_TX_E2E_HOP_ID_MASK \ + GENMASK(22, REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT) +#define REG_RX_OPTS_MASK_OFFSET4 +#define REG_RX_OPTS_MASK_EOF_SHIFT 0 +#define REG_RX_OPTS_MASK_EOF_MASK GENMASK(15, REG_RX_OPTS_MASK_EOF_SHIFT) +#define REG_RX_OPTS_MASK_SOF_SHIFT 16 +#define REG_RX_OPTS_MASK_SOF_MASK GENMASK(31, REG_RX_OPTS_MASK_SOF_SHIFT) + +#define REG_OPTS_STEP 32 +#define REG_OPTS_E2E_ENBIT(28) +#define REG_OPTS_RAW BIT(30) +#define REG_OPTS_VALID BIT(31) /* * three bitfields: tx, rx, rx overflow @@ -86,6 +155,7 @@ struct ring_desc { */ #define REG_RING_NOTIFY_BASE 0x37800 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32) +#define REG_RING_NOTIFY_STEP 4 /* * two bitfields: rx, tx @@ -94,8 +164,47 @@ struct ring_desc { */ #define REG_RING_INTERRUPT_BASE0x38200 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32) +#define REG_RING_INT_TX_PROCESSED(ring_num)BIT(ring_num) +#define REG_RING_INT_RX_PROCESSED(ring_num, num_paths) BIT((ring_num) + \ + (num_paths)) +#define RING_INT_DISABLE(base, val) iowrite32( \ + ioread32((base) + REG_RING_INTERRUPT_BASE) & ~(val), \ + (base) + REG_RING_IN
[PATCH v4 5/7] thunderbolt: Networking state machine
Negotiation states that a peer goes through in order to establish the communication with the second peer. This includes communication with upper layer and additional infrastructure support to communicate with the second peer through ICM. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/Makefile | 2 +- drivers/thunderbolt/icm/icm_nhi.c | 304 ++- drivers/thunderbolt/icm/net.c | 801 ++ drivers/thunderbolt/icm/net.h | 74 4 files changed, 1170 insertions(+), 11 deletions(-) create mode 100644 drivers/thunderbolt/icm/net.c diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile index 3adfc35..624ee31 100644 --- a/drivers/thunderbolt/icm/Makefile +++ b/drivers/thunderbolt/icm/Makefile @@ -25,4 +25,4 @@ obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o -thunderbolt-icm-objs := icm_nhi.o +thunderbolt-icm-objs := icm_nhi.o net.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index 2106dea..1bee701 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -101,6 +101,12 @@ static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { .len = TBT_ICM_RING_MAX_FRAME_SIZE }, [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_LOCAL_ROUTE_STRING] = {.len = sizeof(struct route_string)}, + [NHI_ATTR_LOCAL_UNIQUE_ID] = { .len = sizeof(unique_id) }, + [NHI_ATTR_REMOTE_UNIQUE_ID] = { .len = sizeof(unique_id) }, + [NHI_ATTR_LOCAL_DEPTH] = { .type = NLA_U8, }, + [NHI_ATTR_ENABLE_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MATCH_FRAME_ID] = { .type = NLA_FLAG, }, }; /* NHI genetlink family */ @@ -542,6 +548,29 @@ int nhi_mailbox(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd, u32 data, bool deinit) return 0; } +static inline bool nhi_is_path_disconnected(u32 cmd, u8 num_ports) +{ + return (cmd >= DISCONNECT_PORT_A_INTER_DOMAIN_PATH && + cmd < (DISCONNECT_PORT_A_INTER_DOMAIN_PATH + num_ports)); +} + +static int nhi_mailbox_disconn_path(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd) + __releases(_list_rwsem) +{ + struct port_net_dev *port; + u32 port_num = cmd - DISCONNECT_PORT_A_INTER_DOMAIN_PATH; + + port = &(nhi_ctxt->net_devices[port_num]); + mutex_lock(>state_mutex); + + up_read(_list_rwsem); + port->medium_sts = MEDIUM_READY_FOR_APPROVAL; + if (port->net_dev) + negotiation_events(port->net_dev, MEDIUM_DISCONNECTED); + mutex_unlock(>state_mutex); + return 0; +} + static int nhi_mailbox_generic(struct tbt_nhi_ctxt *nhi_ctxt, u32 mb_cmd) __releases(_list_rwsem) { @@ -590,13 +619,93 @@ static int nhi_genl_mailbox(__always_unused struct sk_buff *u_skb, down_read(_list_rwsem); nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); - if (nhi_ctxt && !nhi_ctxt->d0_exit) - return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + + /* rwsem is released later by the below functions */ + if (nhi_is_path_disconnected(cmd, nhi_ctxt->num_ports)) + return nhi_mailbox_disconn_path(nhi_ctxt, cmd); + else + return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + + } up_read(_list_rwsem); return -ENODEV; } +static int nhi_genl_approve_networking(__always_unused struct sk_buff *u_skb, + struct genl_info *info) +{ + struct tbt_nhi_ctxt *nhi_ctxt; + struct route_string *route_str; + int res = -ENODEV; + u8 port_num; + + if (!info || !info->userhdr || !info->attrs || + !info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING] || + !info->attrs[NHI_ATTR_LOCAL_UNIQUE_ID] || + !info->attrs[NHI_ATTR_REMOTE_UNIQUE_ID] || + !info->attrs[NHI_ATTR_LOCAL_DEPTH]) + return -EINVAL; + + /* +* route_str is an unique topological address +* used for approving remote controller +*/ + route_str = nla_data(info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING]); + /* extracts the port we're connected to */ + port_num = PORT_NUM_FROM_LINK(L0_PORT_NUM(route_str->lo)); + + down_read(_list_rwsem); + + nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + struct port_net_dev *port; + + if (port_num >= nhi_ctxt->num_ports) { + res = -EINVAL; +
[PATCH v4 0/7] thunderbolt: Introducing Thunderbolt(TM) networking
This is version 4 of Thunderbolt(TM) driver for non-Apple hardware. Changes since v3: - Moved new Thunderbolt device IDs from pci_ids.h to icm_nhi.h. - Cleanup and added some comments in code. These patches were pushed to GitHub where they can be reviewed more comfortably with green/red highlighting: https://github.com/01org/thunderbolt-software-kernel-tree Daemon code: https://github.com/01org/thunderbolt-software-daemon For reference, here's a link to version 3: [v3]: https://lkml.org/lkml/2016/7/14/311 Amir Levy (7): thunderbolt: Macro rename thunderbolt: Updating the register definitions thunderbolt: Kconfig for Thunderbolt(TM) networking thunderbolt: Communication with the ICM (firmware) thunderbolt: Networking state machine thunderbolt: Networking transmit and receive thunderbolt: Networking doc Documentation/00-INDEX |2 + Documentation/thunderbolt-networking.txt | 135 ++ drivers/thunderbolt/Kconfig | 25 +- drivers/thunderbolt/Makefile |3 +- drivers/thunderbolt/icm/Makefile | 28 + drivers/thunderbolt/icm/icm_nhi.c| 1642 + drivers/thunderbolt/icm/icm_nhi.h| 93 ++ drivers/thunderbolt/icm/net.c| 2276 ++ drivers/thunderbolt/icm/net.h| 274 drivers/thunderbolt/nhi_regs.h | 115 +- 10 files changed, 4585 insertions(+), 8 deletions(-) create mode 100644 Documentation/thunderbolt-networking.txt create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.c create mode 100644 drivers/thunderbolt/icm/net.h -- 2.7.4
[PATCH v4 7/7] thunderbolt: Networking doc
Adding Thunderbolt(TM) networking documentation. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- Documentation/00-INDEX | 2 + Documentation/thunderbolt-networking.txt | 135 +++ 2 files changed, 137 insertions(+) create mode 100644 Documentation/thunderbolt-networking.txt diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index cd077ca..8cf1717 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -439,6 +439,8 @@ this_cpu_ops.txt - List rationale behind and the way to use this_cpu operations. thermal/ - directory with information on managing thermal issues (CPU/temp) +thunderbolt-networking.txt + - Thunderbolt(TM) Networking driver description. trace/ - directory with info on tracing technologies within linux unaligned-memory-access.txt diff --git a/Documentation/thunderbolt-networking.txt b/Documentation/thunderbolt-networking.txt new file mode 100644 index 000..b7714cf --- /dev/null +++ b/Documentation/thunderbolt-networking.txt @@ -0,0 +1,135 @@ +Intel Thunderbolt(TM) Linux driver +== + +Copyright(c) 2013 - 2016 Intel Corporation. + +Contact Information: +Intel Thunderbolt mailing list <thunderbolt-softw...@lists.01.org> +Edited by Michael Jamet <michael.ja...@intel.com> + +Overview + + +Thunderbolt(TM) Networking mode is introduced with this driver. +This kernel code creates an ethernet device utilized in computer to computer +communication over a Thunderbolt cable. +This driver has been added on the top of the existing thunderbolt driver +for systems with firwmare (FW) based Thunderbolt controllers supporting +Thunderbolt Networking. + +Files += + +- icm_nhi.c/h: These files allow communication with the FW (a.k.a ICM) based controller. + In addition, they create an interface for netlink communication with + a user space daemon. + +- net.c/net.h: These files implement the 'eth' interface for the Thunderbolt(TM) + networking. + +Interface to user space +=== + +The interface to the user space module is implemented through a Generic Netlink. +In order to be accessed by the user space module, both kernel and user space +modules have to register with the same GENL_NAME. In our case, this is +simply "thunderbolt". +The registration is done at driver initialization time for all instances of +the Thunderbolt controllers. +The communication is then carried through pre-defined Thunderbolt messages. +Each specific message has a callback function that is called when +the related message is received. + +The messages are defined as follows: +* NHI_CMD_UNSPEC: Not used. +* NHI_CMD_SUBSCRIBE: Subscription request from daemon to driver to open the + communication channel. +* NHI_CMD_UNSUBSCRIBE: Request from daemon to driver to unsubscribe + to close communication channel. +* NHI_CMD_QUERY_INFORMATION: Request information from the driver such as + driver version, FW version offset, number of ports in the controller + and DMA port. +* NHI_CMD_MSG_TO_ICM: Message from user space module to FW. +* NHI_CMD_MSG_FROM_ICM: Response from FW to user space module. +* NHI_CMD_MAILBOX: Message that uses mailbox mechanism such as FW policy + changes or disconnect path. +* NHI_CMD_APPROVE_TBT_NETWORKING: Request from user space + module to FW to establish path. +* NHI_CMD_ICM_IN_SAFE_MODE: Indication that the FW has entered safe mode. + +Communication with ICM (Firmware) += + +The communication with ICM is principally achieved through +a DMA mechanism on Ring 0. +The driver allocates a shared memory that is physically mapped onto +the DMA physical space at Ring 0. + +Interrupts +== + +Thunderbolt relies on MSI-X interrupts. +The MSI-X vector is allocated as follows: +ICM + - Tx: MSI-X vector index 0 + - Rx: MSI-X vector index 1 + +Port 0 + - Tx: MSI-X vector index 2 + - Rx: MSI-X vector index 3 + +Port 1 + - Tx: MSI-X vector index 4 + - Rx: MSI-X vector index 5 + +ICM interrupts are used for communication with ICM only. +Port 0 and Port 1 interrupts are used for Thunderbolt Networking +communications. +In case MSI-X is not available, the driver requests to enable MSI only. + +Mutexes, semaphores and spinlocks += + +The driver should be able to operate in an environment where hardware +is asynchronously accessed by multiple entities such as netlink, +multiple controllers etc. + +* send_sem: This semaphore enforces unique sender (one sender at a time) + to avoid wrong impairing with responses. FW may process one message + at the time. +* d0_exit_send_mutex: This mutex protects D0 exit (D3) situation + to avoid continuing to send messages to FW. +* d0_exit_mailbox_mutex: This mutex protects D0 exit (D3) situation to + avoid continuing to send commands to mailbox. +* mailbo
[PATCH v3 2/8] thunderbolt: Updating device IDs
Adding the new Thunderbolt(TM) device IDs to the list. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- include/linux/pci_ids.h | 44 ++-- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index c58752f..2d4cc50 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2604,24 +2604,32 @@ #define PCI_DEVICE_ID_INTEL_82441 0x1237 #define PCI_DEVICE_ID_INTEL_82380FB0x124b #define PCI_DEVICE_ID_INTEL_82439 0x1250 -#define PCI_DEVICE_ID_INTEL_LIGHT_RIDGE 0x1513 /* Tbt 1 Gen 1 */ -#define PCI_DEVICE_ID_INTEL_EAGLE_RIDGE 0x151a -#define PCI_DEVICE_ID_INTEL_LIGHT_PEAK 0x151b -#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C 0x1547 /* Tbt 1 Gen 2 */ -#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C 0x1548 -#define PCI_DEVICE_ID_INTEL_PORT_RIDGE 0x1549 -#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI0x1566 /* Tbt 1 Gen 3 */ -#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE 0x1567 -#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI0x1568 -#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE 0x1569 -#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI 0x156a /* Thunderbolt 2 */ -#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE 0x156b -#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI 0x156c -#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE 0x156d -#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI 0x1575 /* Thunderbolt 3 */ -#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576 -#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577 -#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578 +#define PCI_DEVICE_ID_INTEL_LIGHT_RIDGE 0x1513 /* Tbt 1 Gen 1 */ +#define PCI_DEVICE_ID_INTEL_EAGLE_RIDGE 0x151a +#define PCI_DEVICE_ID_INTEL_LIGHT_PEAK 0x151b +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C 0x1547 /* Tbt 1 Gen 2 */ +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C 0x1548 +#define PCI_DEVICE_ID_INTEL_PORT_RIDGE 0x1549 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI 0x1566 /* Tbt 1 Gen 3 */ +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE 0x1567 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI 0x1568 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE 0x1569 +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI 0x156a /* Thunderbolt 2 */ +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE 0x156b +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI 0x156c +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE 0x156d +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI 0x1575 /* Thunderbolt 3 */ +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578 +#define PCI_DEVICE_ID_INTEL_WIN_RIDGE_2C_NHI 0x157d /* Tbt 2 Low Pwr */ +#define PCI_DEVICE_ID_INTEL_WIN_RIDGE_2C_BRIDGE 0x157e +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_NHI 0x15bf /* Tbt 3 Low Pwr */ +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_BRIDGE 0x15c0 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_NHI0x15d2 /* Thunderbolt 3 */ +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_BRIDGE 0x15d3 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_NHI0x15d9 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_BRIDGE 0x15da #define PCI_DEVICE_ID_INTEL_80960_RP 0x1960 #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 -- 2.7.4
[PATCH v3 7/8] thunderbolt: Networking transmit and receive
Handling the transmission to second peer and receiving from it. This includes communication with upper layer, the network stack and configuration of Thunderbolt(TM) HW. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/icm_nhi.c | 15 + drivers/thunderbolt/icm/net.c | 1475 + 2 files changed, 1490 insertions(+) diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index 060bb38..f8b0527 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -1045,6 +1045,7 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) { struct tbt_nhi_ctxt *nhi_ctxt = data; u32 isr0, isr1, imr0, imr1; + int i; /* clear on read */ isr0 = ioread32(nhi_ctxt->iobase + REG_RING_NOTIFY_BASE); @@ -1067,6 +1068,20 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) spin_unlock(_ctxt->lock); + for (i = 0; i < nhi_ctxt->num_ports; ++i) { + struct net_device *net_dev = + nhi_ctxt->net_devices[i].net_dev; + if (net_dev) { + u8 path = PATH_FROM_PORT(nhi_ctxt->num_paths, i); + + if (isr0 & REG_RING_INT_RX_PROCESSED( + path, nhi_ctxt->num_paths)) + tbt_net_rx_msi(net_dev); + if (isr0 & REG_RING_INT_TX_PROCESSED(path)) + tbt_net_tx_msi(net_dev); + } + } + if (isr0 & REG_RING_INT_RX_PROCESSED(TBT_ICM_RING_NUM, nhi_ctxt->num_paths)) schedule_work(_ctxt->icm_msgs_work); diff --git a/drivers/thunderbolt/icm/net.c b/drivers/thunderbolt/icm/net.c index e983dfb..77cc843 100644 --- a/drivers/thunderbolt/icm/net.c +++ b/drivers/thunderbolt/icm/net.c @@ -135,6 +135,17 @@ struct approve_inter_domain_connection_cmd { }; +struct tbt_frame_header { + /* size of the data with the frame */ + __le32 frame_size; + /* running index on the frames */ + __le16 frame_index; + /* ID of the frame to match frames to specific packet */ + __le16 frame_id; + /* how many frames assembles a full packet */ + __le32 frame_count; +}; + enum neg_event { RECEIVE_LOGOUT = NUM_MEDIUM_STATUSES, RECEIVE_LOGIN_RESPONSE, @@ -142,15 +153,81 @@ enum neg_event { NUM_NEG_EVENTS }; +enum frame_status { + GOOD_FRAME, + GOOD_AS_FIRST_FRAME, + GOOD_AS_FIRST_MULTICAST_FRAME, + FRAME_NOT_READY, + FRAME_ERROR, +}; + +enum packet_filter { + /* all multicast MAC addresses */ + PACKET_TYPE_ALL_MULTICAST, + /* all types of MAC addresses: multicast, unicast and broadcast */ + PACKET_TYPE_PROMISCUOUS, + /* all unicast MAC addresses */ + PACKET_TYPE_UNICAST_PROMISCUOUS, +}; + enum disconnect_path_stage { STAGE_1 = BIT(0), STAGE_2 = BIT(1) }; +struct tbt_net_stats { + u64 tx_packets; + u64 tx_bytes; + u64 tx_errors; + u64 rx_packets; + u64 rx_bytes; + u64 rx_length_errors; + u64 rx_over_errors; + u64 rx_crc_errors; + u64 rx_missed_errors; + u64 multicast; +}; + +static const char tbt_net_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_packets", + "tx_bytes", + "tx_errors", + "rx_packets", + "rx_bytes", + "rx_length_errors", + "rx_over_errors", + "rx_crc_errors", + "rx_missed_errors", + "multicast", +}; + +struct tbt_buffer { + dma_addr_t dma; + union { + struct tbt_frame_header *hdr; + struct page *page; + }; + u32 page_offset; +}; + +struct tbt_desc_ring { + /* pointer to the descriptor ring memory */ + struct tbt_buf_desc *desc; + /* physical address of the descriptor ring */ + dma_addr_t dma; + /* array of buffer structs */ + struct tbt_buffer *buffers; + /* last descriptor that was associated with a buffer */ + u16 last_allocated; + /* next descriptor to check for DD status bit */ + u16 next_to_clean; +}; + /** * struct tbt_port - the basic tbt_port structure * @tbt_nhi_ctxt: context of the nhi controller. * @net_dev: networking device object. +* @napi: network API * @login_retry_work: work queue for sending login requests. * @login_response_work: work queue for sending login responses. * @work_struct logout_work: work queue for sending logout requests. @@ -166,6 +243,11 @@ enum disconnect_path_stage { * @login_retry_count: counts number of login r
[PATCH v3 6/8] thunderbolt: Networking state machine
Negotiation states that a peer goes through in order to establish the communication with the second peer. This includes communication with upper layer and additional infrastructure support to communicate with the second peer through ICM. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm/Makefile | 2 +- drivers/thunderbolt/icm/icm_nhi.c | 304 ++- drivers/thunderbolt/icm/net.c | 802 ++ drivers/thunderbolt/icm/net.h | 74 4 files changed, 1171 insertions(+), 11 deletions(-) create mode 100644 drivers/thunderbolt/icm/net.c diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile index 3adfc35..624ee31 100644 --- a/drivers/thunderbolt/icm/Makefile +++ b/drivers/thunderbolt/icm/Makefile @@ -25,4 +25,4 @@ obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o -thunderbolt-icm-objs := icm_nhi.o +thunderbolt-icm-objs := icm_nhi.o net.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c index 9d178a5..060bb38 100644 --- a/drivers/thunderbolt/icm/icm_nhi.c +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -101,6 +101,12 @@ static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { .len = TBT_ICM_RING_MAX_FRAME_SIZE }, [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_LOCAL_ROUTE_STRING] = {.len = sizeof(struct route_string)}, + [NHI_ATTR_LOCAL_UNIQUE_ID] = { .len = sizeof(unique_id) }, + [NHI_ATTR_REMOTE_UNIQUE_ID] = { .len = sizeof(unique_id) }, + [NHI_ATTR_LOCAL_DEPTH] = { .type = NLA_U8, }, + [NHI_ATTR_ENABLE_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MATCH_FRAME_ID] = { .type = NLA_FLAG, }, }; /* NHI genetlink family */ @@ -531,6 +537,29 @@ int nhi_mailbox(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd, u32 data, bool deinit) return 0; } +static inline bool nhi_is_path_disconnected(u32 cmd, u8 num_ports) +{ + return (cmd >= DISCONNECT_PORT_A_INTER_DOMAIN_PATH && + cmd < (DISCONNECT_PORT_A_INTER_DOMAIN_PATH + num_ports)); +} + +static int nhi_mailbox_disconn_path(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd) + __releases(_list_rwsem) +{ + struct port_net_dev *port; + u32 port_num = cmd - DISCONNECT_PORT_A_INTER_DOMAIN_PATH; + + port = &(nhi_ctxt->net_devices[port_num]); + mutex_lock(>state_mutex); + + up_read(_list_rwsem); + port->medium_sts = MEDIUM_READY_FOR_APPROVAL; + if (port->net_dev) + negotiation_events(port->net_dev, MEDIUM_DISCONNECTED); + mutex_unlock(>state_mutex); + return 0; +} + static int nhi_mailbox_generic(struct tbt_nhi_ctxt *nhi_ctxt, u32 mb_cmd) __releases(_list_rwsem) { @@ -579,13 +608,93 @@ static int nhi_genl_mailbox(__always_unused struct sk_buff *u_skb, down_read(_list_rwsem); nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); - if (nhi_ctxt && !nhi_ctxt->d0_exit) - return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + + /* rwsem is released later by the below functions */ + if (nhi_is_path_disconnected(cmd, nhi_ctxt->num_ports)) + return nhi_mailbox_disconn_path(nhi_ctxt, cmd); + else + return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + + } up_read(_list_rwsem); return -ENODEV; } +static int nhi_genl_approve_networking(__always_unused struct sk_buff *u_skb, + struct genl_info *info) +{ + struct tbt_nhi_ctxt *nhi_ctxt; + struct route_string *route_str; + int res = -ENODEV; + u8 port_num; + + if (!info || !info->userhdr || !info->attrs || + !info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING] || + !info->attrs[NHI_ATTR_LOCAL_UNIQUE_ID] || + !info->attrs[NHI_ATTR_REMOTE_UNIQUE_ID] || + !info->attrs[NHI_ATTR_LOCAL_DEPTH]) + return -EINVAL; + + /* +* route_str is an unique topological address +* used for approving remote controller +*/ + route_str = nla_data(info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING]); + /* extracts the port we're connected to */ + port_num = PORT_NUM_FROM_LINK(L0_PORT_NUM(route_str->lo)); + + down_read(_list_rwsem); + + nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + struct port_net_dev *port; + + if (port_num >= nhi_ctxt->num_ports) { + res = -EINVAL; +
[PATCH v3 5/8] thunderbolt: Communication with the ICM (firmware)
Firmware-based (a.k.a ICM - Intel Connection Manager) controller is used for establishing and maintaining the Thunderbolt Networking connection. We need to be able to communicate with it. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Makefile |1 + drivers/thunderbolt/icm/Makefile | 28 + drivers/thunderbolt/icm/icm_nhi.c | 1332 + drivers/thunderbolt/icm/icm_nhi.h | 84 +++ drivers/thunderbolt/icm/net.h | 200 ++ 5 files changed, 1645 insertions(+) create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.h diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 7a85bd1..b6aa6a3 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,4 @@ obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o +obj-${CONFIG_THUNDERBOLT_ICM} += icm/ diff --git a/drivers/thunderbolt/icm/Makefile b/drivers/thunderbolt/icm/Makefile new file mode 100644 index 000..3adfc35 --- /dev/null +++ b/drivers/thunderbolt/icm/Makefile @@ -0,0 +1,28 @@ + +# +# Intel Thunderbolt(TM) driver +# Copyright(c) 2014 - 2016 Intel Corporation. +# +# This program is free software; you can redistribute it and/or modify it +# under the terms and conditions of the GNU General Public License, +# version 2, as published by the Free Software Foundation. +# +# This program is distributed in the hope it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +# more details. +# +# You should have received a copy of the GNU General Public License along +# with this program. If not, see <http://www.gnu.org/licenses/>. +# +# The full GNU General Public License is included in this distribution in +# the file called "COPYING". +# +# Contact Information: +# Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> +# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 +# + + +obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o +thunderbolt-icm-objs := icm_nhi.o diff --git a/drivers/thunderbolt/icm/icm_nhi.c b/drivers/thunderbolt/icm/icm_nhi.c new file mode 100644 index 000..9d178a5 --- /dev/null +++ b/drivers/thunderbolt/icm/icm_nhi.c @@ -0,0 +1,1332 @@ +/*** + * + * Intel Thunderbolt(TM) driver + * Copyright(c) 2014 - 2016 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + **/ + +#include +#include +#include +#include +#include "icm_nhi.h" +#include "net.h" + +#define NHI_GENL_VERSION 1 +#define NHI_GENL_NAME DRV_NAME + +#define DEVICE_DATA(num_ports, dma_port, nvm_ver_offset, nvm_auth_on_boot,\ + support_full_e2e) \ + ((num_ports) | ((dma_port) << 4) | ((nvm_ver_offset) << 10) | \ +((nvm_auth_on_boot) << 22) | ((support_full_e2e) << 23)) +#define DEVICE_DATA_NUM_PORTS(device_data) ((device_data) & 0xf) +#define DEVICE_DATA_DMA_PORT(device_data) (((device_data) >> 4) & 0x3f) +#define DEVICE_DATA_NVM_VER_OFFSET(device_data) (((device_data) >> 10) & 0xfff) +#define DEVICE_DATA_NVM_AUTH_ON_BOOT(device_data) (((device_data) >> 22) & 0x1) +#define DEVICE_DATA_SUPPORT_FULL_E2E(device_data) (((device_data) >> 23) & 0x1) + +#define USEC_TO_256_NSECS(usec) DIV_ROUND_UP((usec) * NSEC_PER_USEC, 256) + +/* + * FW->SW responses + * RC = response code + */ +enum { + RC_GET_TBT_
[PATCH v3 4/8] thunderbolt: Kconfig for Thunderbolt(TM) networking
Updating the Kconfig Thunderbolt(TM) description. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Kconfig | 25 + drivers/thunderbolt/Makefile | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index c121acc..d34b0f5 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -1,13 +1,30 @@ -menuconfig THUNDERBOLT - tristate "Thunderbolt support for Apple devices" +config THUNDERBOLT + tristate "Thunderbolt(TM) support" depends on PCI select CRC32 help - Cactus Ridge Thunderbolt Controller driver + Thunderbolt(TM) Controller driver + +if THUNDERBOLT + +config THUNDERBOLT_APPLE + tristate "Apple hardware support" + help This driver is required if you want to hotplug Thunderbolt devices on Apple hardware. Device chaining is currently not supported. - To compile this driver a module, choose M here. The module will be + To compile this driver as a module, choose M here. The module will be called thunderbolt. + +config THUNDERBOLT_ICM + tristate "Thunderbolt(TM) Networking" + help + This driver is required if you want Thunderbolt(TM) Networking on + non-Apple hardware. + + To compile this driver as a module, choose M here. The module will be + called thunderbolt_icm. + +endif diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 5d1053c..7a85bd1 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,3 @@ -obj-${CONFIG_THUNDERBOLT} := thunderbolt.o +obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o -- 2.7.4
[PATCH v3 1/8] thunderbolt: Macro rename
This first patch updates the registers file to reflect that it isn't only for Cactus Ridge. No functional change intended. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 86b996c..75cf069 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -1,11 +1,11 @@ /* - * Thunderbolt Cactus Ridge driver - NHI registers + * Thunderbolt driver - NHI registers * * Copyright (c) 2014 Andreas Noever <andreas.noe...@gmail.com> */ -#ifndef DSL3510_REGS_H_ -#define DSL3510_REGS_H_ +#ifndef NHI_REGS_H_ +#define NHI_REGS_H_ #include -- 2.7.4
[PATCH v3 0/8] thunderbolt: Introducing Thunderbolt(TM) networking
This is version 3 of Thunderbolt(TM) driver for non-Apple hardware. Changes since v2: - Moved ICM code to subdirectory - thunderbolt/icm These patches were pushed to GitHub where they can be reviewed more comfortably with green/red highlighting: https://github.com/01org/thunderbolt-software-kernel-tree Daemon code: https://github.com/01org/thunderbolt-software-daemon For reference, here's a link to version 2: [v2]: https://lkml.org/lkml/2016/6/29/160 Amir Levy (8): thunderbolt: Macro rename thunderbolt: Updating device IDs thunderbolt: Updating the register definitions thunderbolt: Kconfig for Thunderbolt(TM) networking thunderbolt: Communication with the ICM (firmware) thunderbolt: Networking state machine thunderbolt: Networking transmit and receive thunderbolt: Networking doc Documentation/00-INDEX |2 + Documentation/thunderbolt-networking.txt | 135 ++ drivers/thunderbolt/Kconfig | 25 +- drivers/thunderbolt/Makefile |3 +- drivers/thunderbolt/icm/Makefile | 28 + drivers/thunderbolt/icm/icm_nhi.c| 1631 + drivers/thunderbolt/icm/icm_nhi.h| 84 ++ drivers/thunderbolt/icm/net.c| 2277 ++ drivers/thunderbolt/icm/net.h| 274 drivers/thunderbolt/nhi_regs.h | 115 +- include/linux/pci_ids.h | 44 +- 11 files changed, 4592 insertions(+), 26 deletions(-) create mode 100644 Documentation/thunderbolt-networking.txt create mode 100644 drivers/thunderbolt/icm/Makefile create mode 100644 drivers/thunderbolt/icm/icm_nhi.c create mode 100644 drivers/thunderbolt/icm/icm_nhi.h create mode 100644 drivers/thunderbolt/icm/net.c create mode 100644 drivers/thunderbolt/icm/net.h -- 2.7.4
[PATCH v3 8/8] thunderbolt: Networking doc
Adding Thunderbolt(TM) networking documentation. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- Documentation/00-INDEX | 2 + Documentation/thunderbolt-networking.txt | 135 +++ 2 files changed, 137 insertions(+) create mode 100644 Documentation/thunderbolt-networking.txt diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index cd077ca..8cf1717 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -439,6 +439,8 @@ this_cpu_ops.txt - List rationale behind and the way to use this_cpu operations. thermal/ - directory with information on managing thermal issues (CPU/temp) +thunderbolt-networking.txt + - Thunderbolt(TM) Networking driver description. trace/ - directory with info on tracing technologies within linux unaligned-memory-access.txt diff --git a/Documentation/thunderbolt-networking.txt b/Documentation/thunderbolt-networking.txt new file mode 100644 index 000..b7714cf --- /dev/null +++ b/Documentation/thunderbolt-networking.txt @@ -0,0 +1,135 @@ +Intel Thunderbolt(TM) Linux driver +== + +Copyright(c) 2013 - 2016 Intel Corporation. + +Contact Information: +Intel Thunderbolt mailing list <thunderbolt-softw...@lists.01.org> +Edited by Michael Jamet <michael.ja...@intel.com> + +Overview + + +Thunderbolt(TM) Networking mode is introduced with this driver. +This kernel code creates an ethernet device utilized in computer to computer +communication over a Thunderbolt cable. +This driver has been added on the top of the existing thunderbolt driver +for systems with firwmare (FW) based Thunderbolt controllers supporting +Thunderbolt Networking. + +Files += + +- icm_nhi.c/h: These files allow communication with the FW (a.k.a ICM) based controller. + In addition, they create an interface for netlink communication with + a user space daemon. + +- net.c/net.h: These files implement the 'eth' interface for the Thunderbolt(TM) + networking. + +Interface to user space +=== + +The interface to the user space module is implemented through a Generic Netlink. +In order to be accessed by the user space module, both kernel and user space +modules have to register with the same GENL_NAME. In our case, this is +simply "thunderbolt". +The registration is done at driver initialization time for all instances of +the Thunderbolt controllers. +The communication is then carried through pre-defined Thunderbolt messages. +Each specific message has a callback function that is called when +the related message is received. + +The messages are defined as follows: +* NHI_CMD_UNSPEC: Not used. +* NHI_CMD_SUBSCRIBE: Subscription request from daemon to driver to open the + communication channel. +* NHI_CMD_UNSUBSCRIBE: Request from daemon to driver to unsubscribe + to close communication channel. +* NHI_CMD_QUERY_INFORMATION: Request information from the driver such as + driver version, FW version offset, number of ports in the controller + and DMA port. +* NHI_CMD_MSG_TO_ICM: Message from user space module to FW. +* NHI_CMD_MSG_FROM_ICM: Response from FW to user space module. +* NHI_CMD_MAILBOX: Message that uses mailbox mechanism such as FW policy + changes or disconnect path. +* NHI_CMD_APPROVE_TBT_NETWORKING: Request from user space + module to FW to establish path. +* NHI_CMD_ICM_IN_SAFE_MODE: Indication that the FW has entered safe mode. + +Communication with ICM (Firmware) += + +The communication with ICM is principally achieved through +a DMA mechanism on Ring 0. +The driver allocates a shared memory that is physically mapped onto +the DMA physical space at Ring 0. + +Interrupts +== + +Thunderbolt relies on MSI-X interrupts. +The MSI-X vector is allocated as follows: +ICM + - Tx: MSI-X vector index 0 + - Rx: MSI-X vector index 1 + +Port 0 + - Tx: MSI-X vector index 2 + - Rx: MSI-X vector index 3 + +Port 1 + - Tx: MSI-X vector index 4 + - Rx: MSI-X vector index 5 + +ICM interrupts are used for communication with ICM only. +Port 0 and Port 1 interrupts are used for Thunderbolt Networking +communications. +In case MSI-X is not available, the driver requests to enable MSI only. + +Mutexes, semaphores and spinlocks += + +The driver should be able to operate in an environment where hardware +is asynchronously accessed by multiple entities such as netlink, +multiple controllers etc. + +* send_sem: This semaphore enforces unique sender (one sender at a time) + to avoid wrong impairing with responses. FW may process one message + at the time. +* d0_exit_send_mutex: This mutex protects D0 exit (D3) situation + to avoid continuing to send messages to FW. +* d0_exit_mailbox_mutex: This mutex protects D0 exit (D3) situation to + avoid continuing to send commands to mailbox. +* mailbo
[PATCH v3 3/8] thunderbolt: Updating the register definitions
Adding more Thunderbolt(TM) register definitions and some helper macros. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 109 + 1 file changed, 109 insertions(+) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 75cf069..b8e961f 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -9,6 +9,11 @@ #include +#define NHI_MMIO_BAR 0 + +#define TBT_RING_MIN_NUM_BUFFERS 2 +#define TBT_RING_MAX_FRAME_SIZE(4 * 1024) + enum ring_flags { RING_FLAG_ISOCH_ENABLE = 1 << 27, /* TX only? */ RING_FLAG_E2E_FLOW_CONTROL = 1 << 28, @@ -39,6 +44,33 @@ struct ring_desc { u32 time; /* write zero */ } __packed; +/** + * struct tbt_buf_desc - TX/RX ring buffer descriptor. + * This is same as struct ring_desc, but without the use of bitfields and + * with explicit endianity. + */ +struct tbt_buf_desc { + __le64 phys; + __le32 attributes; + __le32 time; +}; + +#define DESC_ATTR_LEN_SHIFT0 +#define DESC_ATTR_LEN_MASK GENMASK(11, DESC_ATTR_LEN_SHIFT) +#define DESC_ATTR_EOF_SHIFT12 +#define DESC_ATTR_EOF_MASK GENMASK(15, DESC_ATTR_EOF_SHIFT) +#define DESC_ATTR_SOF_SHIFT16 +#define DESC_ATTR_SOF_MASK GENMASK(19, DESC_ATTR_SOF_SHIFT) +#define DESC_ATTR_TX_ISOCH_DMA_EN BIT(20) /* TX */ +#define DESC_ATTR_RX_CRC_ERR BIT(20) /* RX after use */ +#define DESC_ATTR_DESC_DONEBIT(21) +#define DESC_ATTR_REQ_STS BIT(22) /* TX and RX before use */ +#define DESC_ATTR_RX_BUF_OVRN_ERR BIT(22) /* RX after use */ +#define DESC_ATTR_INT_EN BIT(23) +#define DESC_ATTR_OFFSET_SHIFT 24 +#define DESC_ATTR_OFFSET_MASK GENMASK(31, DESC_ATTR_OFFSET_SHIFT) + + /* NHI registers in bar 0 */ /* @@ -60,6 +92,30 @@ struct ring_desc { */ #define REG_RX_RING_BASE 0x08000 +#define REG_RING_STEP 16 +#define REG_RING_PHYS_LO_OFFSET0 +#define REG_RING_PHYS_HI_OFFSET4 +#define REG_RING_CONS_PROD_OFFSET 8 /* cons - RO, prod - RW */ +#define REG_RING_CONS_SHIFT0 +#define REG_RING_CONS_MASK GENMASK(15, REG_RING_CONS_SHIFT) +#define REG_RING_PROD_SHIFT16 +#define REG_RING_PROD_MASK GENMASK(31, REG_RING_PROD_SHIFT) +#define REG_RING_SIZE_OFFSET 12 +#define REG_RING_SIZE_SHIFT0 +#define REG_RING_SIZE_MASK GENMASK(15, REG_RING_SIZE_SHIFT) +#define REG_RING_BUF_SIZE_SHIFT16 +#define REG_RING_BUF_SIZE_MASK GENMASK(27, REG_RING_BUF_SIZE_SHIFT) + +#define TBT_RING_CONS_PROD_REG(iobase, ringbase, ringnumber) \ + ((iobase) + (ringbase) + \ + ((ringnumber) * REG_RING_STEP) + \ + REG_RING_CONS_PROD_OFFSET) + +#define TBT_REG_RING_PROD_EXTRACT(val) (((val) & REG_RING_PROD_MASK) >> \ + REG_RING_PROD_SHIFT) + +#define TBT_REG_RING_CONS_EXTRACT(val) (((val) & REG_RING_CONS_MASK) >> \ + REG_RING_CONS_SHIFT) /* * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) * 00: enum_ring_flags @@ -77,6 +133,19 @@ struct ring_desc { * ..: unknown */ #define REG_RX_OPTIONS_BASE0x29800 +#define REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT12 +#define REG_RX_OPTS_TX_E2E_HOP_ID_MASK \ + GENMASK(22, REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT) +#define REG_RX_OPTS_MASK_OFFSET4 +#define REG_RX_OPTS_MASK_EOF_SHIFT 0 +#define REG_RX_OPTS_MASK_EOF_MASK GENMASK(15, REG_RX_OPTS_MASK_EOF_SHIFT) +#define REG_RX_OPTS_MASK_SOF_SHIFT 16 +#define REG_RX_OPTS_MASK_SOF_MASK GENMASK(31, REG_RX_OPTS_MASK_SOF_SHIFT) + +#define REG_OPTS_STEP 32 +#define REG_OPTS_E2E_ENBIT(28) +#define REG_OPTS_RAW BIT(30) +#define REG_OPTS_VALID BIT(31) /* * three bitfields: tx, rx, rx overflow @@ -86,6 +155,7 @@ struct ring_desc { */ #define REG_RING_NOTIFY_BASE 0x37800 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32) +#define REG_RING_NOTIFY_STEP 4 /* * two bitfields: rx, tx @@ -94,8 +164,47 @@ struct ring_desc { */ #define REG_RING_INTERRUPT_BASE0x38200 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32) +#define REG_RING_INT_TX_PROCESSED(ring_num)BIT(ring_num) +#define REG_RING_INT_RX_PROCESSED(ring_num, num_paths) BIT((ring_num) + \ + (num_paths)) +#define RING_INT_DISABLE(base, val) iowrite32( \ + ioread32((base) + REG_RING_INTERRUPT_BASE) & ~(val), \ + (base) + REG_RING_IN
[PATCH v2 3/8] thunderbolt: Updating the register definitions
Adding more Thunderbolt(TM) register definitions and some helper macros. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 109 + 1 file changed, 109 insertions(+) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 75cf069..b8e961f 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -9,6 +9,11 @@ #include +#define NHI_MMIO_BAR 0 + +#define TBT_RING_MIN_NUM_BUFFERS 2 +#define TBT_RING_MAX_FRAME_SIZE(4 * 1024) + enum ring_flags { RING_FLAG_ISOCH_ENABLE = 1 << 27, /* TX only? */ RING_FLAG_E2E_FLOW_CONTROL = 1 << 28, @@ -39,6 +44,33 @@ struct ring_desc { u32 time; /* write zero */ } __packed; +/** + * struct tbt_buf_desc - TX/RX ring buffer descriptor. + * This is same as struct ring_desc, but without the use of bitfields and + * with explicit endianity. + */ +struct tbt_buf_desc { + __le64 phys; + __le32 attributes; + __le32 time; +}; + +#define DESC_ATTR_LEN_SHIFT0 +#define DESC_ATTR_LEN_MASK GENMASK(11, DESC_ATTR_LEN_SHIFT) +#define DESC_ATTR_EOF_SHIFT12 +#define DESC_ATTR_EOF_MASK GENMASK(15, DESC_ATTR_EOF_SHIFT) +#define DESC_ATTR_SOF_SHIFT16 +#define DESC_ATTR_SOF_MASK GENMASK(19, DESC_ATTR_SOF_SHIFT) +#define DESC_ATTR_TX_ISOCH_DMA_EN BIT(20) /* TX */ +#define DESC_ATTR_RX_CRC_ERR BIT(20) /* RX after use */ +#define DESC_ATTR_DESC_DONEBIT(21) +#define DESC_ATTR_REQ_STS BIT(22) /* TX and RX before use */ +#define DESC_ATTR_RX_BUF_OVRN_ERR BIT(22) /* RX after use */ +#define DESC_ATTR_INT_EN BIT(23) +#define DESC_ATTR_OFFSET_SHIFT 24 +#define DESC_ATTR_OFFSET_MASK GENMASK(31, DESC_ATTR_OFFSET_SHIFT) + + /* NHI registers in bar 0 */ /* @@ -60,6 +92,30 @@ struct ring_desc { */ #define REG_RX_RING_BASE 0x08000 +#define REG_RING_STEP 16 +#define REG_RING_PHYS_LO_OFFSET0 +#define REG_RING_PHYS_HI_OFFSET4 +#define REG_RING_CONS_PROD_OFFSET 8 /* cons - RO, prod - RW */ +#define REG_RING_CONS_SHIFT0 +#define REG_RING_CONS_MASK GENMASK(15, REG_RING_CONS_SHIFT) +#define REG_RING_PROD_SHIFT16 +#define REG_RING_PROD_MASK GENMASK(31, REG_RING_PROD_SHIFT) +#define REG_RING_SIZE_OFFSET 12 +#define REG_RING_SIZE_SHIFT0 +#define REG_RING_SIZE_MASK GENMASK(15, REG_RING_SIZE_SHIFT) +#define REG_RING_BUF_SIZE_SHIFT16 +#define REG_RING_BUF_SIZE_MASK GENMASK(27, REG_RING_BUF_SIZE_SHIFT) + +#define TBT_RING_CONS_PROD_REG(iobase, ringbase, ringnumber) \ + ((iobase) + (ringbase) + \ + ((ringnumber) * REG_RING_STEP) + \ + REG_RING_CONS_PROD_OFFSET) + +#define TBT_REG_RING_PROD_EXTRACT(val) (((val) & REG_RING_PROD_MASK) >> \ + REG_RING_PROD_SHIFT) + +#define TBT_REG_RING_CONS_EXTRACT(val) (((val) & REG_RING_CONS_MASK) >> \ + REG_RING_CONS_SHIFT) /* * 32 bytes per entry, one entry for every hop (REG_HOP_COUNT) * 00: enum_ring_flags @@ -77,6 +133,19 @@ struct ring_desc { * ..: unknown */ #define REG_RX_OPTIONS_BASE0x29800 +#define REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT12 +#define REG_RX_OPTS_TX_E2E_HOP_ID_MASK \ + GENMASK(22, REG_RX_OPTS_TX_E2E_HOP_ID_SHIFT) +#define REG_RX_OPTS_MASK_OFFSET4 +#define REG_RX_OPTS_MASK_EOF_SHIFT 0 +#define REG_RX_OPTS_MASK_EOF_MASK GENMASK(15, REG_RX_OPTS_MASK_EOF_SHIFT) +#define REG_RX_OPTS_MASK_SOF_SHIFT 16 +#define REG_RX_OPTS_MASK_SOF_MASK GENMASK(31, REG_RX_OPTS_MASK_SOF_SHIFT) + +#define REG_OPTS_STEP 32 +#define REG_OPTS_E2E_ENBIT(28) +#define REG_OPTS_RAW BIT(30) +#define REG_OPTS_VALID BIT(31) /* * three bitfields: tx, rx, rx overflow @@ -86,6 +155,7 @@ struct ring_desc { */ #define REG_RING_NOTIFY_BASE 0x37800 #define RING_NOTIFY_REG_COUNT(nhi) ((31 + 3 * nhi->hop_count) / 32) +#define REG_RING_NOTIFY_STEP 4 /* * two bitfields: rx, tx @@ -94,8 +164,47 @@ struct ring_desc { */ #define REG_RING_INTERRUPT_BASE0x38200 #define RING_INTERRUPT_REG_COUNT(nhi) ((31 + 2 * nhi->hop_count) / 32) +#define REG_RING_INT_TX_PROCESSED(ring_num)BIT(ring_num) +#define REG_RING_INT_RX_PROCESSED(ring_num, num_paths) BIT((ring_num) + \ + (num_paths)) +#define RING_INT_DISABLE(base, val) iowrite32( \ + ioread32((base) + REG_RING_INTERRUPT_BASE) & ~(val), \ + (base) + REG_RING_IN
[PATCH v2 2/8] thunderbolt: Updating device IDs
Adding the new Thunderbolt(TM) device IDs to the list. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- include/linux/pci_ids.h | 44 ++-- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index c58752f..2d4cc50 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2604,24 +2604,32 @@ #define PCI_DEVICE_ID_INTEL_82441 0x1237 #define PCI_DEVICE_ID_INTEL_82380FB0x124b #define PCI_DEVICE_ID_INTEL_82439 0x1250 -#define PCI_DEVICE_ID_INTEL_LIGHT_RIDGE 0x1513 /* Tbt 1 Gen 1 */ -#define PCI_DEVICE_ID_INTEL_EAGLE_RIDGE 0x151a -#define PCI_DEVICE_ID_INTEL_LIGHT_PEAK 0x151b -#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C 0x1547 /* Tbt 1 Gen 2 */ -#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C 0x1548 -#define PCI_DEVICE_ID_INTEL_PORT_RIDGE 0x1549 -#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI0x1566 /* Tbt 1 Gen 3 */ -#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE 0x1567 -#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI0x1568 -#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE 0x1569 -#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI 0x156a /* Thunderbolt 2 */ -#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE 0x156b -#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI 0x156c -#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE 0x156d -#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI 0x1575 /* Thunderbolt 3 */ -#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576 -#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577 -#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578 +#define PCI_DEVICE_ID_INTEL_LIGHT_RIDGE 0x1513 /* Tbt 1 Gen 1 */ +#define PCI_DEVICE_ID_INTEL_EAGLE_RIDGE 0x151a +#define PCI_DEVICE_ID_INTEL_LIGHT_PEAK 0x151b +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_4C 0x1547 /* Tbt 1 Gen 2 */ +#define PCI_DEVICE_ID_INTEL_CACTUS_RIDGE_2C 0x1548 +#define PCI_DEVICE_ID_INTEL_PORT_RIDGE 0x1549 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_NHI 0x1566 /* Tbt 1 Gen 3 */ +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_2C_BRIDGE 0x1567 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_NHI 0x1568 +#define PCI_DEVICE_ID_INTEL_REDWOOD_RIDGE_4C_BRIDGE 0x1569 +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_NHI 0x156a /* Thunderbolt 2 */ +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_2C_BRIDGE 0x156b +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_NHI 0x156c +#define PCI_DEVICE_ID_INTEL_FALCON_RIDGE_4C_BRIDGE 0x156d +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_NHI 0x1575 /* Thunderbolt 3 */ +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_2C_BRIDGE 0x1576 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_NHI 0x1577 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_4C_BRIDGE 0x1578 +#define PCI_DEVICE_ID_INTEL_WIN_RIDGE_2C_NHI 0x157d /* Tbt 2 Low Pwr */ +#define PCI_DEVICE_ID_INTEL_WIN_RIDGE_2C_BRIDGE 0x157e +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_NHI 0x15bf /* Tbt 3 Low Pwr */ +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_LP_BRIDGE 0x15c0 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_NHI0x15d2 /* Thunderbolt 3 */ +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_4C_BRIDGE 0x15d3 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_NHI0x15d9 +#define PCI_DEVICE_ID_INTEL_ALPINE_RIDGE_C_2C_BRIDGE 0x15da #define PCI_DEVICE_ID_INTEL_80960_RP 0x1960 #define PCI_DEVICE_ID_INTEL_82840_HB 0x1a21 #define PCI_DEVICE_ID_INTEL_82845_HB 0x1a30 -- 2.7.4
[PATCH v2 0/8] thunderbolt: Introducing Thunderbolt(TM) networking
This is version 2 of Thunderbolt(TM) driver for non-Apple hardware. Changes since v1: - Separation to 2 modules. - Moved ICM specific registers definition to ICM header file. - Added new Thunderbolt device IDs. - Renamed the Thunderbolt networking documentation. - General cleanups These patches were pushed to GitHub where they can be reviewed more comfortably with green/red highlighting: https://github.com/01org/thunderbolt-software-kernel-tree Daemon code: https://github.com/01org/thunderbolt-software-daemon For reference, here's a link to version 1: [v1]: http://www.spinics.net/lists/linux-pci/msg51287.html Amir Levy (8): thunderbolt: Macro rename thunderbolt: Updating device IDs thunderbolt: Updating the register definitions thunderbolt: Kconfig for Thunderbolt(TM) networking thunderbolt: Communication with the ICM (firmware) thunderbolt: Networking state machine thunderbolt: Networking transmit and receive thunderbolt: Networking doc Documentation/00-INDEX |2 + Documentation/thunderbolt-networking.txt | 135 ++ drivers/thunderbolt/Kconfig | 25 +- drivers/thunderbolt/Makefile |4 +- drivers/thunderbolt/icm_nhi.c| 1631 + drivers/thunderbolt/icm_nhi.h| 84 ++ drivers/thunderbolt/net.c| 2277 ++ drivers/thunderbolt/net.h| 274 drivers/thunderbolt/nhi_regs.h | 115 +- include/linux/pci_ids.h | 44 +- 10 files changed, 4565 insertions(+), 26 deletions(-) create mode 100644 Documentation/thunderbolt-networking.txt create mode 100644 drivers/thunderbolt/icm_nhi.c create mode 100644 drivers/thunderbolt/icm_nhi.h create mode 100644 drivers/thunderbolt/net.c create mode 100644 drivers/thunderbolt/net.h -- 2.7.4
[PATCH v2 1/8] thunderbolt: Macro rename
This first patch updates the registers file to reflect that it isn't only for Cactus Ridge. No functional change intended. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/nhi_regs.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/thunderbolt/nhi_regs.h b/drivers/thunderbolt/nhi_regs.h index 86b996c..75cf069 100644 --- a/drivers/thunderbolt/nhi_regs.h +++ b/drivers/thunderbolt/nhi_regs.h @@ -1,11 +1,11 @@ /* - * Thunderbolt Cactus Ridge driver - NHI registers + * Thunderbolt driver - NHI registers * * Copyright (c) 2014 Andreas Noever <andreas.noe...@gmail.com> */ -#ifndef DSL3510_REGS_H_ -#define DSL3510_REGS_H_ +#ifndef NHI_REGS_H_ +#define NHI_REGS_H_ #include -- 2.7.4
[PATCH v2 4/8] thunderbolt: Kconfig for Thunderbolt(TM) networking
Updating the Kconfig Thunderbolt(TM) description. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Kconfig | 25 + drivers/thunderbolt/Makefile | 2 +- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/thunderbolt/Kconfig b/drivers/thunderbolt/Kconfig index c121acc..d34b0f5 100644 --- a/drivers/thunderbolt/Kconfig +++ b/drivers/thunderbolt/Kconfig @@ -1,13 +1,30 @@ -menuconfig THUNDERBOLT - tristate "Thunderbolt support for Apple devices" +config THUNDERBOLT + tristate "Thunderbolt(TM) support" depends on PCI select CRC32 help - Cactus Ridge Thunderbolt Controller driver + Thunderbolt(TM) Controller driver + +if THUNDERBOLT + +config THUNDERBOLT_APPLE + tristate "Apple hardware support" + help This driver is required if you want to hotplug Thunderbolt devices on Apple hardware. Device chaining is currently not supported. - To compile this driver a module, choose M here. The module will be + To compile this driver as a module, choose M here. The module will be called thunderbolt. + +config THUNDERBOLT_ICM + tristate "Thunderbolt(TM) Networking" + help + This driver is required if you want Thunderbolt(TM) Networking on + non-Apple hardware. + + To compile this driver as a module, choose M here. The module will be + called thunderbolt_icm. + +endif diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 5d1053c..7a85bd1 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,3 @@ -obj-${CONFIG_THUNDERBOLT} := thunderbolt.o +obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o -- 2.7.4
[PATCH v2 5/8] thunderbolt: Communication with the ICM (firmware)
Firmware-based (a.k.a ICM - Intel Connection Manager) controller is used for establishing and maintaining the Thunderbolt Networking connection. We need to be able to communicate with it. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Makefile |2 + drivers/thunderbolt/icm_nhi.c | 1332 + drivers/thunderbolt/icm_nhi.h | 84 +++ drivers/thunderbolt/net.h | 200 +++ 4 files changed, 1618 insertions(+) create mode 100644 drivers/thunderbolt/icm_nhi.c create mode 100644 drivers/thunderbolt/icm_nhi.h create mode 100644 drivers/thunderbolt/net.h diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index 7a85bd1..cc91d9a 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -1,3 +1,5 @@ obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o +obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o +thunderbolt-icm-objs := icm_nhi.o diff --git a/drivers/thunderbolt/icm_nhi.c b/drivers/thunderbolt/icm_nhi.c new file mode 100644 index 000..9d178a5 --- /dev/null +++ b/drivers/thunderbolt/icm_nhi.c @@ -0,0 +1,1332 @@ +/*** + * + * Intel Thunderbolt(TM) driver + * Copyright(c) 2014 - 2016 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * Intel Thunderbolt Mailing List <thunderbolt-softw...@lists.01.org> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + * + **/ + +#include +#include +#include +#include +#include "icm_nhi.h" +#include "net.h" + +#define NHI_GENL_VERSION 1 +#define NHI_GENL_NAME DRV_NAME + +#define DEVICE_DATA(num_ports, dma_port, nvm_ver_offset, nvm_auth_on_boot,\ + support_full_e2e) \ + ((num_ports) | ((dma_port) << 4) | ((nvm_ver_offset) << 10) | \ +((nvm_auth_on_boot) << 22) | ((support_full_e2e) << 23)) +#define DEVICE_DATA_NUM_PORTS(device_data) ((device_data) & 0xf) +#define DEVICE_DATA_DMA_PORT(device_data) (((device_data) >> 4) & 0x3f) +#define DEVICE_DATA_NVM_VER_OFFSET(device_data) (((device_data) >> 10) & 0xfff) +#define DEVICE_DATA_NVM_AUTH_ON_BOOT(device_data) (((device_data) >> 22) & 0x1) +#define DEVICE_DATA_SUPPORT_FULL_E2E(device_data) (((device_data) >> 23) & 0x1) + +#define USEC_TO_256_NSECS(usec) DIV_ROUND_UP((usec) * NSEC_PER_USEC, 256) + +/* + * FW->SW responses + * RC = response code + */ +enum { + RC_GET_TBT_TOPOLOGY = 1, + RC_GET_VIDEO_RESOURCES_DATA, + RC_DRV_READY, + RC_APPROVE_PCI_CONNEXION, + RC_CHALLENGE_PCI_CONNEXION, + RC_ADD_DEVICE_AND_KEY, + RC_INTER_DOMAIN_PKT_SENT = 8, + RC_APPROVE_INTER_DOMAIN_CONNEXION = 0x10 +}; + +/* + * FW->SW notifications + * NC = notification code + */ +enum { + NC_DEVICE_CONNECTED = 3, + NC_DEVICE_DISCONNECTED, + NC_DP_DEVICE_CONNECTED_NOT_TUNNELED, + NC_INTER_DOMAIN_CONNECTED, + NC_INTER_DOMAIN_DISCONNECTED +}; + +/* NHI genetlink commands */ +enum { + NHI_CMD_UNSPEC, + NHI_CMD_SUBSCRIBE, + NHI_CMD_UNSUBSCRIBE, + NHI_CMD_QUERY_INFORMATION, + NHI_CMD_MSG_TO_ICM, + NHI_CMD_MSG_FROM_ICM, + NHI_CMD_MAILBOX, + NHI_CMD_APPROVE_TBT_NETWORKING, + NHI_CMD_ICM_IN_SAFE_MODE, + __NHI_CMD_MAX, +}; +#define NHI_CMD_MAX (__NHI_CMD_MAX - 1) + +/* NHI genetlink policy */ +static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { + [NHI_ATTR_DRV_VERSION] = { .type = NLA_NUL_STRING, }, + [NHI_ATTR_NVM_VER_OFFSET] = { .type = NLA_U16, }, + [NHI_ATTR_NUM_PORTS]= { .type = NLA_U8, }, + [NHI_ATTR_DMA_PORT] = { .type = NLA_U8, }, + [NHI_ATTR_SUPPORT_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MAILBOX_CMD] = { .type = NLA_U32, }, + [NHI_ATTR_PDF] = { .type = NLA_U32, }, + [NHI_ATTR_MSG_TO_ICM] = { .type = NLA_BINARY, +
[PATCH v2 6/8] thunderbolt: Networking state machine
Negotiation states that a peer goes through in order to establish the communication with the second peer. This includes communication with upper layer and additional infrastructure support to communicate with the second peer through ICM. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/Makefile | 2 +- drivers/thunderbolt/icm_nhi.c | 304 +++- drivers/thunderbolt/net.c | 802 ++ drivers/thunderbolt/net.h | 74 4 files changed, 1171 insertions(+), 11 deletions(-) create mode 100644 drivers/thunderbolt/net.c diff --git a/drivers/thunderbolt/Makefile b/drivers/thunderbolt/Makefile index cc91d9a..50c1c8b 100644 --- a/drivers/thunderbolt/Makefile +++ b/drivers/thunderbolt/Makefile @@ -2,4 +2,4 @@ obj-${CONFIG_THUNDERBOLT_APPLE} := thunderbolt.o thunderbolt-objs := nhi.o ctl.o tb.o switch.o cap.o path.o tunnel_pci.o eeprom.o obj-${CONFIG_THUNDERBOLT_ICM} += thunderbolt-icm.o -thunderbolt-icm-objs := icm_nhi.o +thunderbolt-icm-objs := icm_nhi.o net.o diff --git a/drivers/thunderbolt/icm_nhi.c b/drivers/thunderbolt/icm_nhi.c index 9d178a5..060bb38 100644 --- a/drivers/thunderbolt/icm_nhi.c +++ b/drivers/thunderbolt/icm_nhi.c @@ -101,6 +101,12 @@ static const struct nla_policy nhi_genl_policy[NHI_ATTR_MAX + 1] = { .len = TBT_ICM_RING_MAX_FRAME_SIZE }, [NHI_ATTR_MSG_FROM_ICM] = { .type = NLA_BINARY, .len = TBT_ICM_RING_MAX_FRAME_SIZE }, + [NHI_ATTR_LOCAL_ROUTE_STRING] = {.len = sizeof(struct route_string)}, + [NHI_ATTR_LOCAL_UNIQUE_ID] = { .len = sizeof(unique_id) }, + [NHI_ATTR_REMOTE_UNIQUE_ID] = { .len = sizeof(unique_id) }, + [NHI_ATTR_LOCAL_DEPTH] = { .type = NLA_U8, }, + [NHI_ATTR_ENABLE_FULL_E2E] = { .type = NLA_FLAG, }, + [NHI_ATTR_MATCH_FRAME_ID] = { .type = NLA_FLAG, }, }; /* NHI genetlink family */ @@ -531,6 +537,29 @@ int nhi_mailbox(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd, u32 data, bool deinit) return 0; } +static inline bool nhi_is_path_disconnected(u32 cmd, u8 num_ports) +{ + return (cmd >= DISCONNECT_PORT_A_INTER_DOMAIN_PATH && + cmd < (DISCONNECT_PORT_A_INTER_DOMAIN_PATH + num_ports)); +} + +static int nhi_mailbox_disconn_path(struct tbt_nhi_ctxt *nhi_ctxt, u32 cmd) + __releases(_list_rwsem) +{ + struct port_net_dev *port; + u32 port_num = cmd - DISCONNECT_PORT_A_INTER_DOMAIN_PATH; + + port = &(nhi_ctxt->net_devices[port_num]); + mutex_lock(>state_mutex); + + up_read(_list_rwsem); + port->medium_sts = MEDIUM_READY_FOR_APPROVAL; + if (port->net_dev) + negotiation_events(port->net_dev, MEDIUM_DISCONNECTED); + mutex_unlock(>state_mutex); + return 0; +} + static int nhi_mailbox_generic(struct tbt_nhi_ctxt *nhi_ctxt, u32 mb_cmd) __releases(_list_rwsem) { @@ -579,13 +608,93 @@ static int nhi_genl_mailbox(__always_unused struct sk_buff *u_skb, down_read(_list_rwsem); nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); - if (nhi_ctxt && !nhi_ctxt->d0_exit) - return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + + /* rwsem is released later by the below functions */ + if (nhi_is_path_disconnected(cmd, nhi_ctxt->num_ports)) + return nhi_mailbox_disconn_path(nhi_ctxt, cmd); + else + return nhi_mailbox_generic(nhi_ctxt, mb_cmd); + + } up_read(_list_rwsem); return -ENODEV; } +static int nhi_genl_approve_networking(__always_unused struct sk_buff *u_skb, + struct genl_info *info) +{ + struct tbt_nhi_ctxt *nhi_ctxt; + struct route_string *route_str; + int res = -ENODEV; + u8 port_num; + + if (!info || !info->userhdr || !info->attrs || + !info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING] || + !info->attrs[NHI_ATTR_LOCAL_UNIQUE_ID] || + !info->attrs[NHI_ATTR_REMOTE_UNIQUE_ID] || + !info->attrs[NHI_ATTR_LOCAL_DEPTH]) + return -EINVAL; + + /* +* route_str is an unique topological address +* used for approving remote controller +*/ + route_str = nla_data(info->attrs[NHI_ATTR_LOCAL_ROUTE_STRING]); + /* extracts the port we're connected to */ + port_num = PORT_NUM_FROM_LINK(L0_PORT_NUM(route_str->lo)); + + down_read(_list_rwsem); + + nhi_ctxt = nhi_search_ctxt(*(u32 *)info->userhdr); + if (nhi_ctxt && !nhi_ctxt->d0_exit) { + struct port_net_dev *port; + + if (port_num >= nhi_ctxt->num_ports) { + res = -EINVAL; +
[PATCH v2 7/8] thunderbolt: Networking transmit and receive
Handling the transmission to second peer and receiving from it. This includes communication with upper layer, the network stack and configuration of Thunderbolt(TM) HW. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- drivers/thunderbolt/icm_nhi.c | 15 + drivers/thunderbolt/net.c | 1475 + 2 files changed, 1490 insertions(+) diff --git a/drivers/thunderbolt/icm_nhi.c b/drivers/thunderbolt/icm_nhi.c index 060bb38..f8b0527 100644 --- a/drivers/thunderbolt/icm_nhi.c +++ b/drivers/thunderbolt/icm_nhi.c @@ -1045,6 +1045,7 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) { struct tbt_nhi_ctxt *nhi_ctxt = data; u32 isr0, isr1, imr0, imr1; + int i; /* clear on read */ isr0 = ioread32(nhi_ctxt->iobase + REG_RING_NOTIFY_BASE); @@ -1067,6 +1068,20 @@ static irqreturn_t nhi_msi(int __always_unused irq, void *data) spin_unlock(_ctxt->lock); + for (i = 0; i < nhi_ctxt->num_ports; ++i) { + struct net_device *net_dev = + nhi_ctxt->net_devices[i].net_dev; + if (net_dev) { + u8 path = PATH_FROM_PORT(nhi_ctxt->num_paths, i); + + if (isr0 & REG_RING_INT_RX_PROCESSED( + path, nhi_ctxt->num_paths)) + tbt_net_rx_msi(net_dev); + if (isr0 & REG_RING_INT_TX_PROCESSED(path)) + tbt_net_tx_msi(net_dev); + } + } + if (isr0 & REG_RING_INT_RX_PROCESSED(TBT_ICM_RING_NUM, nhi_ctxt->num_paths)) schedule_work(_ctxt->icm_msgs_work); diff --git a/drivers/thunderbolt/net.c b/drivers/thunderbolt/net.c index e983dfb..108de28 100644 --- a/drivers/thunderbolt/net.c +++ b/drivers/thunderbolt/net.c @@ -135,6 +135,17 @@ struct approve_inter_domain_connection_cmd { }; +struct tbt_frame_header { + /* size of the data with the frame */ + __le32 frame_size; + /* running index on the frames */ + __le16 frame_index; + /* ID of the frame to match frames to specific packet */ + __le16 frame_id; + /* how many frames assembles a full packet */ + __le32 frame_count; +}; + enum neg_event { RECEIVE_LOGOUT = NUM_MEDIUM_STATUSES, RECEIVE_LOGIN_RESPONSE, @@ -142,15 +153,81 @@ enum neg_event { NUM_NEG_EVENTS }; +enum frame_status { + GOOD_FRAME, + GOOD_AS_FIRST_FRAME, + GOOD_AS_FIRST_MULTICAST_FRAME, + FRAME_NOT_READY, + FRAME_ERROR, +}; + +enum packet_filter { + /* all multicast MAC addresses */ + PACKET_TYPE_ALL_MULTICAST, + /* all types of MAC addresses: multicast, unicast and broadcast */ + PACKET_TYPE_PROMISCUOUS, + /* all unicast MAC addresses */ + PACKET_TYPE_UNICAST_PROMISCUOUS, +}; + enum disconnect_path_stage { STAGE_1 = BIT(0), STAGE_2 = BIT(1) }; +struct tbt_net_stats { + u64 tx_packets; + u64 tx_bytes; + u64 tx_errors; + u64 rx_packets; + u64 rx_bytes; + u64 rx_length_errors; + u64 rx_over_errors; + u64 rx_crc_errors; + u64 rx_missed_errors; + u64 multicast; +}; + +static const char tbt_net_gstrings_stats[][ETH_GSTRING_LEN] = { + "tx_packets", + "tx_bytes", + "tx_errors", + "rx_packets", + "rx_bytes", + "rx_length_errors", + "rx_over_errors", + "rx_crc_errors", + "rx_missed_errors", + "multicast", +}; + +struct tbt_buffer { + dma_addr_t dma; + union { + struct tbt_frame_header *hdr; + struct page *page; + }; + u32 page_offset; +}; + +struct tbt_desc_ring { + /* pointer to the descriptor ring memory */ + struct tbt_buf_desc *desc; + /* physical address of the descriptor ring */ + dma_addr_t dma; + /* array of buffer structs */ + struct tbt_buffer *buffers; + /* last descriptor that was associated with a buffer */ + u16 last_allocated; + /* next descriptor to check for DD status bit */ + u16 next_to_clean; +}; + /** * struct tbt_port - the basic tbt_port structure * @tbt_nhi_ctxt: context of the nhi controller. * @net_dev: networking device object. +* @napi: network API * @login_retry_work: work queue for sending login requests. * @login_response_work: work queue for sending login responses. * @work_struct logout_work: work queue for sending logout requests. @@ -166,6 +243,11 @@ enum disconnect_path_stage { * @login_retry_count: counts number of login retries sent. * @local_depth:
[PATCH v2 8/8] thunderbolt: Networking doc
Adding Thunderbolt(TM) networking documentation. Signed-off-by: Amir Levy <amir.jer.l...@intel.com> --- Documentation/00-INDEX | 2 + Documentation/thunderbolt-networking.txt | 135 +++ 2 files changed, 137 insertions(+) create mode 100644 Documentation/thunderbolt-networking.txt diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index cd077ca..8cf1717 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -439,6 +439,8 @@ this_cpu_ops.txt - List rationale behind and the way to use this_cpu operations. thermal/ - directory with information on managing thermal issues (CPU/temp) +thunderbolt-networking.txt + - Thunderbolt(TM) Networking driver description. trace/ - directory with info on tracing technologies within linux unaligned-memory-access.txt diff --git a/Documentation/thunderbolt-networking.txt b/Documentation/thunderbolt-networking.txt new file mode 100644 index 000..b7714cf --- /dev/null +++ b/Documentation/thunderbolt-networking.txt @@ -0,0 +1,135 @@ +Intel Thunderbolt(TM) Linux driver +== + +Copyright(c) 2013 - 2016 Intel Corporation. + +Contact Information: +Intel Thunderbolt mailing list <thunderbolt-softw...@lists.01.org> +Edited by Michael Jamet <michael.ja...@intel.com> + +Overview + + +Thunderbolt(TM) Networking mode is introduced with this driver. +This kernel code creates an ethernet device utilized in computer to computer +communication over a Thunderbolt cable. +This driver has been added on the top of the existing thunderbolt driver +for systems with firwmare (FW) based Thunderbolt controllers supporting +Thunderbolt Networking. + +Files += + +- icm_nhi.c/h: These files allow communication with the FW (a.k.a ICM) based controller. + In addition, they create an interface for netlink communication with + a user space daemon. + +- net.c/net.h: These files implement the 'eth' interface for the Thunderbolt(TM) + networking. + +Interface to user space +=== + +The interface to the user space module is implemented through a Generic Netlink. +In order to be accessed by the user space module, both kernel and user space +modules have to register with the same GENL_NAME. In our case, this is +simply "thunderbolt". +The registration is done at driver initialization time for all instances of +the Thunderbolt controllers. +The communication is then carried through pre-defined Thunderbolt messages. +Each specific message has a callback function that is called when +the related message is received. + +The messages are defined as follows: +* NHI_CMD_UNSPEC: Not used. +* NHI_CMD_SUBSCRIBE: Subscription request from daemon to driver to open the + communication channel. +* NHI_CMD_UNSUBSCRIBE: Request from daemon to driver to unsubscribe + to close communication channel. +* NHI_CMD_QUERY_INFORMATION: Request information from the driver such as + driver version, FW version offset, number of ports in the controller + and DMA port. +* NHI_CMD_MSG_TO_ICM: Message from user space module to FW. +* NHI_CMD_MSG_FROM_ICM: Response from FW to user space module. +* NHI_CMD_MAILBOX: Message that uses mailbox mechanism such as FW policy + changes or disconnect path. +* NHI_CMD_APPROVE_TBT_NETWORKING: Request from user space + module to FW to establish path. +* NHI_CMD_ICM_IN_SAFE_MODE: Indication that the FW has entered safe mode. + +Communication with ICM (Firmware) += + +The communication with ICM is principally achieved through +a DMA mechanism on Ring 0. +The driver allocates a shared memory that is physically mapped onto +the DMA physical space at Ring 0. + +Interrupts +== + +Thunderbolt relies on MSI-X interrupts. +The MSI-X vector is allocated as follows: +ICM + - Tx: MSI-X vector index 0 + - Rx: MSI-X vector index 1 + +Port 0 + - Tx: MSI-X vector index 2 + - Rx: MSI-X vector index 3 + +Port 1 + - Tx: MSI-X vector index 4 + - Rx: MSI-X vector index 5 + +ICM interrupts are used for communication with ICM only. +Port 0 and Port 1 interrupts are used for Thunderbolt Networking +communications. +In case MSI-X is not available, the driver requests to enable MSI only. + +Mutexes, semaphores and spinlocks += + +The driver should be able to operate in an environment where hardware +is asynchronously accessed by multiple entities such as netlink, +multiple controllers etc. + +* send_sem: This semaphore enforces unique sender (one sender at a time) + to avoid wrong impairing with responses. FW may process one message + at the time. +* d0_exit_send_mutex: This mutex protects D0 exit (D3) situation + to avoid continuing to send messages to FW. +* d0_exit_mailbox_mutex: This mutex protects D0 exit (D3) situation to + avoid continuing to send commands to mailbox. +* mailbo