// SPDX-License-Identifier: GPL-2.0 /* * Thunderbolt bus support * * Copyright (C) 2017, Intel Corporation * Author: Mika Westerberg <[email protected]> */ #include <linux/device.h> #include <linux/idr.h> #include <linux/module.h> #include <linux/pm_runtime.h> #include <linux/slab.h> #include <linux/random.h> #include <crypto/hash.h> #include "tb.h" static DEFINE_IDA(tb_domain_ida); static bool match_service_id(const struct tb_service_id *id, const struct tb_service *svc) { … } static const struct tb_service_id *__tb_service_match(struct device *dev, const struct device_driver *drv) { … } static int tb_service_match(struct device *dev, const struct device_driver *drv) { … } static int tb_service_probe(struct device *dev) { … } static void tb_service_remove(struct device *dev) { … } static void tb_service_shutdown(struct device *dev) { … } static const char * const tb_security_names[] = …; static ssize_t boot_acl_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static ssize_t boot_acl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { … } static DEVICE_ATTR_RW(boot_acl); static ssize_t deauthorization_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static DEVICE_ATTR_RO(deauthorization); static ssize_t iommu_dma_protection_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static DEVICE_ATTR_RO(iommu_dma_protection); static ssize_t security_show(struct device *dev, struct device_attribute *attr, char *buf) { … } static DEVICE_ATTR_RO(security); static struct attribute *domain_attrs[] = …; static umode_t domain_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n) { … } static const struct attribute_group domain_attr_group = …; static const struct attribute_group *domain_attr_groups[] = …; const struct bus_type tb_bus_type = …; static void tb_domain_release(struct device *dev) { … } const struct device_type tb_domain_type = …; static bool tb_domain_event_cb(void *data, enum tb_cfg_pkg_type type, const void *buf, size_t size) { … } /** * tb_domain_alloc() - Allocate a domain * @nhi: Pointer to the host controller * @timeout_msec: Control channel timeout for non-raw messages * @privsize: Size of the connection manager private data * * Allocates and initializes a new Thunderbolt domain. Connection * managers are expected to call this and then fill in @cm_ops * accordingly. * * Call tb_domain_put() to release the domain before it has been added * to the system. * * Return: allocated domain structure on %NULL in case of error */ struct tb *tb_domain_alloc(struct tb_nhi *nhi, int timeout_msec, size_t privsize) { … } /** * tb_domain_add() - Add domain to the system * @tb: Domain to add * @reset: Issue reset to the host router * * Starts the domain and adds it to the system. Hotplugging devices will * work after this has been returned successfully. In order to remove * and release the domain after this function has been called, call * tb_domain_remove(). * * Return: %0 in case of success and negative errno in case of error */ int tb_domain_add(struct tb *tb, bool reset) { … } /** * tb_domain_remove() - Removes and releases a domain * @tb: Domain to remove * * Stops the domain, removes it from the system and releases all * resources once the last reference has been released. */ void tb_domain_remove(struct tb *tb) { … } /** * tb_domain_suspend_noirq() - Suspend a domain * @tb: Domain to suspend * * Suspends all devices in the domain and stops the control channel. */ int tb_domain_suspend_noirq(struct tb *tb) { … } /** * tb_domain_resume_noirq() - Resume a domain * @tb: Domain to resume * * Re-starts the control channel, and resumes all devices connected to * the domain. */ int tb_domain_resume_noirq(struct tb *tb) { … } int tb_domain_suspend(struct tb *tb) { … } int tb_domain_freeze_noirq(struct tb *tb) { … } int tb_domain_thaw_noirq(struct tb *tb) { … } void tb_domain_complete(struct tb *tb) { … } int tb_domain_runtime_suspend(struct tb *tb) { … } int tb_domain_runtime_resume(struct tb *tb) { … } /** * tb_domain_disapprove_switch() - Disapprove switch * @tb: Domain the switch belongs to * @sw: Switch to disapprove * * This will disconnect PCIe tunnel from parent to this @sw. * * Return: %0 on success and negative errno in case of failure. */ int tb_domain_disapprove_switch(struct tb *tb, struct tb_switch *sw) { … } /** * tb_domain_approve_switch() - Approve switch * @tb: Domain the switch belongs to * @sw: Switch to approve * * This will approve switch by connection manager specific means. In * case of success the connection manager will create PCIe tunnel from * parent to @sw. */ int tb_domain_approve_switch(struct tb *tb, struct tb_switch *sw) { … } /** * tb_domain_approve_switch_key() - Approve switch and add key * @tb: Domain the switch belongs to * @sw: Switch to approve * * For switches that support secure connect, this function first adds * key to the switch NVM using connection manager specific means. If * adding the key is successful, the switch is approved and connected. * * Return: %0 on success and negative errno in case of failure. */ int tb_domain_approve_switch_key(struct tb *tb, struct tb_switch *sw) { … } /** * tb_domain_challenge_switch_key() - Challenge and approve switch * @tb: Domain the switch belongs to * @sw: Switch to approve * * For switches that support secure connect, this function generates * random challenge and sends it to the switch. The switch responds to * this and if the response matches our random challenge, the switch is * approved and connected. * * Return: %0 on success and negative errno in case of failure. */ int tb_domain_challenge_switch_key(struct tb *tb, struct tb_switch *sw) { … } /** * tb_domain_disconnect_pcie_paths() - Disconnect all PCIe paths * @tb: Domain whose PCIe paths to disconnect * * This needs to be called in preparation for NVM upgrade of the host * controller. Makes sure all PCIe paths are disconnected. * * Return %0 on success and negative errno in case of error. */ int tb_domain_disconnect_pcie_paths(struct tb *tb) { … } /** * tb_domain_approve_xdomain_paths() - Enable DMA paths for XDomain * @tb: Domain enabling the DMA paths * @xd: XDomain DMA paths are created to * @transmit_path: HopID we are using to send out packets * @transmit_ring: DMA ring used to send out packets * @receive_path: HopID the other end is using to send packets to us * @receive_ring: DMA ring used to receive packets from @receive_path * * Calls connection manager specific method to enable DMA paths to the * XDomain in question. * * Return: 0% in case of success and negative errno otherwise. In * particular returns %-ENOTSUPP if the connection manager * implementation does not support XDomains. */ int tb_domain_approve_xdomain_paths(struct tb *tb, struct tb_xdomain *xd, int transmit_path, int transmit_ring, int receive_path, int receive_ring) { … } /** * tb_domain_disconnect_xdomain_paths() - Disable DMA paths for XDomain * @tb: Domain disabling the DMA paths * @xd: XDomain whose DMA paths are disconnected * @transmit_path: HopID we are using to send out packets * @transmit_ring: DMA ring used to send out packets * @receive_path: HopID the other end is using to send packets to us * @receive_ring: DMA ring used to receive packets from @receive_path * * Calls connection manager specific method to disconnect DMA paths to * the XDomain in question. * * Return: 0% in case of success and negative errno otherwise. In * particular returns %-ENOTSUPP if the connection manager * implementation does not support XDomains. */ int tb_domain_disconnect_xdomain_paths(struct tb *tb, struct tb_xdomain *xd, int transmit_path, int transmit_ring, int receive_path, int receive_ring) { … } static int disconnect_xdomain(struct device *dev, void *data) { … } /** * tb_domain_disconnect_all_paths() - Disconnect all paths for the domain * @tb: Domain whose paths are disconnected * * This function can be used to disconnect all paths (PCIe, XDomain) for * example in preparation for host NVM firmware upgrade. After this is * called the paths cannot be established without resetting the switch. * * Return: %0 in case of success and negative errno otherwise. */ int tb_domain_disconnect_all_paths(struct tb *tb) { … } int tb_domain_init(void) { … } void tb_domain_exit(void) { … }