^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Thunderbolt XDomain discovery protocol support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2017, Intel Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Authors: Michael Jamet <michael.jamet@intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Mika Westerberg <mika.westerberg@linux.intel.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/kmod.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/utsname.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/uuid.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/workqueue.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "tb.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define XDOMAIN_DEFAULT_TIMEOUT 5000 /* ms */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define XDOMAIN_UUID_RETRIES 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define XDOMAIN_PROPERTIES_RETRIES 60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define XDOMAIN_PROPERTIES_CHANGED_RETRIES 10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) struct xdomain_request_work {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) struct work_struct work;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) struct tb_xdp_header *pkg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct tb *tb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) /* Serializes access to the properties and protocol handlers below */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static DEFINE_MUTEX(xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) /* Properties exposed to the remote domains */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static struct tb_property_dir *xdomain_property_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static u32 *xdomain_property_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static u32 xdomain_property_block_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static u32 xdomain_property_block_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) /* Additional protocol handlers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static LIST_HEAD(protocol_handlers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) /* UUID for XDomain discovery protocol: b638d70e-42ff-40bb-97c2-90e2c0b2ff07 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) static const uuid_t tb_xdp_uuid =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) UUID_INIT(0xb638d70e, 0x42ff, 0x40bb,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) 0x97, 0xc2, 0x90, 0xe2, 0xc0, 0xb2, 0xff, 0x07);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) static bool tb_xdomain_match(const struct tb_cfg_request *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) const struct ctl_pkg *pkg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) switch (pkg->frame.eof) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) case TB_CFG_PKG_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) case TB_CFG_PKG_XDOMAIN_RESP: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) const struct tb_xdp_header *res_hdr = pkg->buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) const struct tb_xdp_header *req_hdr = req->request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) if (pkg->frame.size < req->response_size / 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) /* Make sure route matches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if ((res_hdr->xd_hdr.route_hi & ~BIT(31)) !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) req_hdr->xd_hdr.route_hi)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if ((res_hdr->xd_hdr.route_lo) != req_hdr->xd_hdr.route_lo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* Check that the XDomain protocol matches */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) if (!uuid_equal(&res_hdr->uuid, &req_hdr->uuid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static bool tb_xdomain_copy(struct tb_cfg_request *req,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) const struct ctl_pkg *pkg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) memcpy(req->response, pkg->buffer, req->response_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) req->result.err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static void response_ready(void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) tb_cfg_request_put(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) static int __tb_xdomain_response(struct tb_ctl *ctl, const void *response,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) size_t size, enum tb_cfg_pkg_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) struct tb_cfg_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) req = tb_cfg_request_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) req->match = tb_xdomain_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) req->copy = tb_xdomain_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) req->request = response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) req->request_size = size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) req->request_type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) return tb_cfg_request(ctl, req, response_ready, req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * tb_xdomain_response() - Send a XDomain response message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * @xd: XDomain to send the message
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * @response: Response to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * @size: Size of the response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * @type: PDF type of the response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * This can be used to send a XDomain response message to the other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * domain. No response for the message is expected.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * Return: %0 in case of success and negative errno in case of failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) int tb_xdomain_response(struct tb_xdomain *xd, const void *response,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) size_t size, enum tb_cfg_pkg_type type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return __tb_xdomain_response(xd->tb->ctl, response, size, type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) EXPORT_SYMBOL_GPL(tb_xdomain_response);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) static int __tb_xdomain_request(struct tb_ctl *ctl, const void *request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) size_t request_size, enum tb_cfg_pkg_type request_type, void *response,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) size_t response_size, enum tb_cfg_pkg_type response_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) unsigned int timeout_msec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) struct tb_cfg_request *req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) struct tb_cfg_result res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) req = tb_cfg_request_alloc();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) if (!req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) req->match = tb_xdomain_match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) req->copy = tb_xdomain_copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) req->request = request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) req->request_size = request_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) req->request_type = request_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) req->response = response;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) req->response_size = response_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) req->response_type = response_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) res = tb_cfg_request_sync(ctl, req, timeout_msec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) tb_cfg_request_put(req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) return res.err == 1 ? -EIO : res.err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) * tb_xdomain_request() - Send a XDomain request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) * @xd: XDomain to send the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) * @request: Request to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * @request_size: Size of the request in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * @request_type: PDF type of the request
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * @response: Response is copied here
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) * @response_size: Expected size of the response in bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) * @response_type: Expected PDF type of the response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) * @timeout_msec: Timeout in milliseconds to wait for the response
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) * This function can be used to send XDomain control channel messages to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) * the other domain. The function waits until the response is received
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * or when timeout triggers. Whichever comes first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * Return: %0 in case of success and negative errno in case of failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) int tb_xdomain_request(struct tb_xdomain *xd, const void *request,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) size_t request_size, enum tb_cfg_pkg_type request_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) void *response, size_t response_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) enum tb_cfg_pkg_type response_type, unsigned int timeout_msec)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return __tb_xdomain_request(xd->tb->ctl, request, request_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) request_type, response, response_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) response_type, timeout_msec);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) EXPORT_SYMBOL_GPL(tb_xdomain_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) static inline void tb_xdp_fill_header(struct tb_xdp_header *hdr, u64 route,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) u8 sequence, enum tb_xdp_type type, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) u32 length_sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) length_sn = (size - sizeof(hdr->xd_hdr)) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) length_sn |= (sequence << TB_XDOMAIN_SN_SHIFT) & TB_XDOMAIN_SN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) hdr->xd_hdr.route_hi = upper_32_bits(route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) hdr->xd_hdr.route_lo = lower_32_bits(route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) hdr->xd_hdr.length_sn = length_sn;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) hdr->type = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) memcpy(&hdr->uuid, &tb_xdp_uuid, sizeof(tb_xdp_uuid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) static int tb_xdp_handle_error(const struct tb_xdp_header *hdr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) const struct tb_xdp_error_response *error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (hdr->type != ERROR_RESPONSE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) error = (const struct tb_xdp_error_response *)hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) switch (error->error) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) case ERROR_UNKNOWN_PACKET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) case ERROR_UNKNOWN_DOMAIN:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) case ERROR_NOT_SUPPORTED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) return -ENOTSUPP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) case ERROR_NOT_READY:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) static int tb_xdp_uuid_request(struct tb_ctl *ctl, u64 route, int retry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) uuid_t *uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct tb_xdp_uuid_response res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct tb_xdp_uuid req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) memset(&req, 0, sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) tb_xdp_fill_header(&req.hdr, route, retry % 4, UUID_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) memset(&res, 0, sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) ret = __tb_xdomain_request(ctl, &req, sizeof(req),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) TB_CFG_PKG_XDOMAIN_REQ, &res, sizeof(res),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) TB_CFG_PKG_XDOMAIN_RESP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) XDOMAIN_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) ret = tb_xdp_handle_error(&res.hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) uuid_copy(uuid, &res.src_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) static int tb_xdp_uuid_response(struct tb_ctl *ctl, u64 route, u8 sequence,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) const uuid_t *uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) struct tb_xdp_uuid_response res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) memset(&res, 0, sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) tb_xdp_fill_header(&res.hdr, route, sequence, UUID_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) uuid_copy(&res.src_uuid, uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) res.src_route_hi = upper_32_bits(route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) res.src_route_lo = lower_32_bits(route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return __tb_xdomain_response(ctl, &res, sizeof(res),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) TB_CFG_PKG_XDOMAIN_RESP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static int tb_xdp_error_response(struct tb_ctl *ctl, u64 route, u8 sequence,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) enum tb_xdp_error error)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) struct tb_xdp_error_response res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) memset(&res, 0, sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) tb_xdp_fill_header(&res.hdr, route, sequence, ERROR_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) res.error = error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return __tb_xdomain_response(ctl, &res, sizeof(res),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) TB_CFG_PKG_XDOMAIN_RESP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) static int tb_xdp_properties_request(struct tb_ctl *ctl, u64 route,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) const uuid_t *src_uuid, const uuid_t *dst_uuid, int retry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) u32 **block, u32 *generation)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct tb_xdp_properties_response *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) struct tb_xdp_properties req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) u16 data_len, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) size_t total_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) u32 *data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) total_size = sizeof(*res) + TB_XDP_PROPERTIES_MAX_DATA_LENGTH * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) res = kzalloc(total_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) memset(&req, 0, sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) tb_xdp_fill_header(&req.hdr, route, retry % 4, PROPERTIES_REQUEST,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) memcpy(&req.src_uuid, src_uuid, sizeof(*src_uuid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) memcpy(&req.dst_uuid, dst_uuid, sizeof(*dst_uuid));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) data_len = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) ret = __tb_xdomain_request(ctl, &req, sizeof(req),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) TB_CFG_PKG_XDOMAIN_REQ, res,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) total_size, TB_CFG_PKG_XDOMAIN_RESP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) XDOMAIN_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ret = tb_xdp_handle_error(&res->hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) * Package length includes the whole payload without the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) * XDomain header. Validate first that the package is at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * least size of the response structure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) len = res->hdr.xd_hdr.length_sn & TB_XDOMAIN_LENGTH_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (len < sizeof(*res) / 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) len += sizeof(res->hdr.xd_hdr) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) len -= sizeof(*res) / 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (res->offset != req.offset) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) * First time allocate block that has enough space for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) * the whole properties block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) if (!data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) data_len = res->data_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) if (data_len > TB_XDP_PROPERTIES_MAX_LENGTH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) ret = -E2BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) data = kcalloc(data_len, sizeof(u32), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) if (!data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) goto err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) memcpy(data + req.offset, res->data, len * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) req.offset += len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) } while (!data_len || req.offset < data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) *block = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) *generation = res->generation;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) return data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) err:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) kfree(data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) static int tb_xdp_properties_response(struct tb *tb, struct tb_ctl *ctl,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) u64 route, u8 sequence, const uuid_t *src_uuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) const struct tb_xdp_properties *req)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct tb_xdp_properties_response *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) size_t total_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) u16 len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) * Currently we expect all requests to be directed to us. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) * protocol supports forwarding, though which we might add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) * support later on.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!uuid_equal(src_uuid, &req->dst_uuid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) tb_xdp_error_response(ctl, route, sequence,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) ERROR_UNKNOWN_DOMAIN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) mutex_lock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) if (req->offset >= xdomain_property_block_len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) len = xdomain_property_block_len - req->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) len = min_t(u16, len, TB_XDP_PROPERTIES_MAX_DATA_LENGTH);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) total_size = sizeof(*res) + len * 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) res = kzalloc(total_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) if (!res) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) tb_xdp_fill_header(&res->hdr, route, sequence, PROPERTIES_RESPONSE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) total_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) res->generation = xdomain_property_block_gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) res->data_length = xdomain_property_block_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) res->offset = req->offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) uuid_copy(&res->src_uuid, src_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) uuid_copy(&res->dst_uuid, &req->src_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) memcpy(res->data, &xdomain_property_block[req->offset], len * 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) ret = __tb_xdomain_response(ctl, res, total_size,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) TB_CFG_PKG_XDOMAIN_RESP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) kfree(res);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) static int tb_xdp_properties_changed_request(struct tb_ctl *ctl, u64 route,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) int retry, const uuid_t *uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) struct tb_xdp_properties_changed_response res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) struct tb_xdp_properties_changed req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) memset(&req, 0, sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) tb_xdp_fill_header(&req.hdr, route, retry % 4,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) PROPERTIES_CHANGED_REQUEST, sizeof(req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) uuid_copy(&req.src_uuid, uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) memset(&res, 0, sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) ret = __tb_xdomain_request(ctl, &req, sizeof(req),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) TB_CFG_PKG_XDOMAIN_REQ, &res, sizeof(res),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) TB_CFG_PKG_XDOMAIN_RESP,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) XDOMAIN_DEFAULT_TIMEOUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) return tb_xdp_handle_error(&res.hdr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) tb_xdp_properties_changed_response(struct tb_ctl *ctl, u64 route, u8 sequence)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) struct tb_xdp_properties_changed_response res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) memset(&res, 0, sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) tb_xdp_fill_header(&res.hdr, route, sequence,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) PROPERTIES_CHANGED_RESPONSE, sizeof(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return __tb_xdomain_response(ctl, &res, sizeof(res),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) TB_CFG_PKG_XDOMAIN_RESP);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * tb_register_protocol_handler() - Register protocol handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) * @handler: Handler to register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) * This allows XDomain service drivers to hook into incoming XDomain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) * messages. After this function is called the service driver needs to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) * be able to handle calls to callback whenever a package with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) * registered protocol is received.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) int tb_register_protocol_handler(struct tb_protocol_handler *handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) if (!handler->uuid || !handler->callback)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) if (uuid_equal(handler->uuid, &tb_xdp_uuid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) mutex_lock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) list_add_tail(&handler->list, &protocol_handlers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) EXPORT_SYMBOL_GPL(tb_register_protocol_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * tb_unregister_protocol_handler() - Unregister protocol handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) * @handler: Handler to unregister
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) * Removes the previously registered protocol handler.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) void tb_unregister_protocol_handler(struct tb_protocol_handler *handler)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) mutex_lock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) list_del_init(&handler->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) EXPORT_SYMBOL_GPL(tb_unregister_protocol_handler);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static int rebuild_property_block(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) u32 *block, len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) ret = tb_property_format_dir(xdomain_property_dir, NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) len = ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) block = kcalloc(len, sizeof(u32), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) if (!block)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) ret = tb_property_format_dir(xdomain_property_dir, block, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) kfree(block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) kfree(xdomain_property_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) xdomain_property_block = block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) xdomain_property_block_len = len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) xdomain_property_block_gen++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) static void finalize_property_block(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) const struct tb_property *nodename;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) * On first XDomain connection we set up the the system
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) * nodename. This delayed here because userspace may not have it
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) * set when the driver is first probed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) mutex_lock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) nodename = tb_property_find(xdomain_property_dir, "deviceid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) TB_PROPERTY_TYPE_TEXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) if (!nodename) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) tb_property_add_text(xdomain_property_dir, "deviceid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) utsname()->nodename);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) rebuild_property_block();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) static void tb_xdp_handle_request(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) struct xdomain_request_work *xw = container_of(work, typeof(*xw), work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) const struct tb_xdp_header *pkg = xw->pkg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) const struct tb_xdomain_header *xhdr = &pkg->xd_hdr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) struct tb *tb = xw->tb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) struct tb_ctl *ctl = tb->ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) const uuid_t *uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) u32 sequence;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) u64 route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) route = ((u64)xhdr->route_hi << 32 | xhdr->route_lo) & ~BIT_ULL(63);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) sequence = xhdr->length_sn & TB_XDOMAIN_SN_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) sequence >>= TB_XDOMAIN_SN_SHIFT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) mutex_lock(&tb->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) if (tb->root_switch)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) uuid = tb->root_switch->uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) uuid = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) mutex_unlock(&tb->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) if (!uuid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) tb_xdp_error_response(ctl, route, sequence, ERROR_NOT_READY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) finalize_property_block();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) switch (pkg->type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) case PROPERTIES_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) ret = tb_xdp_properties_response(tb, ctl, route, sequence, uuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) (const struct tb_xdp_properties *)pkg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) case PROPERTIES_CHANGED_REQUEST: {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) const struct tb_xdp_properties_changed *xchg =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) (const struct tb_xdp_properties_changed *)pkg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct tb_xdomain *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) ret = tb_xdp_properties_changed_response(ctl, route, sequence);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * Since the properties have been changed, let's update
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) * the xdomain related to this connection as well in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) * case there is a change in services it offers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) xd = tb_xdomain_find_by_uuid_locked(tb, &xchg->src_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (xd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) queue_delayed_work(tb->wq, &xd->get_properties_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) msecs_to_jiffies(50));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) tb_xdomain_put(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) case UUID_REQUEST_OLD:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) case UUID_REQUEST:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) ret = tb_xdp_uuid_response(ctl, route, sequence, uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) tb_xdp_error_response(ctl, route, sequence,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) ERROR_NOT_SUPPORTED);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) tb_warn(tb, "failed to send XDomain response for %#x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) pkg->type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) kfree(xw->pkg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) kfree(xw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) tb_domain_put(tb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) tb_xdp_schedule_request(struct tb *tb, const struct tb_xdp_header *hdr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) struct xdomain_request_work *xw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) xw = kmalloc(sizeof(*xw), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) if (!xw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) INIT_WORK(&xw->work, tb_xdp_handle_request);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) xw->pkg = kmemdup(hdr, size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (!xw->pkg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) kfree(xw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) xw->tb = tb_domain_get(tb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) schedule_work(&xw->work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) * tb_register_service_driver() - Register XDomain service driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) * @drv: Driver to register
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * Registers new service driver from @drv to the bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) int tb_register_service_driver(struct tb_service_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) drv->driver.bus = &tb_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) return driver_register(&drv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) EXPORT_SYMBOL_GPL(tb_register_service_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) * tb_unregister_service_driver() - Unregister XDomain service driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) * @xdrv: Driver to unregister
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * Unregisters XDomain service driver from the bus.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) void tb_unregister_service_driver(struct tb_service_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) driver_unregister(&drv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) EXPORT_SYMBOL_GPL(tb_unregister_service_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) static ssize_t key_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) struct tb_service *svc = container_of(dev, struct tb_service, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * It should be null terminated but anything else is pretty much
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * allowed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return sprintf(buf, "%*pE\n", (int)strlen(svc->key), svc->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static DEVICE_ATTR_RO(key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) static int get_modalias(struct tb_service *svc, char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) return snprintf(buf, size, "tbsvc:k%sp%08Xv%08Xr%08X", svc->key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) svc->prtcid, svc->prtcvers, svc->prtcrevs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) struct tb_service *svc = container_of(dev, struct tb_service, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) /* Full buffer size except new line and null termination */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) get_modalias(svc, buf, PAGE_SIZE - 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) return sprintf(buf, "%s\n", buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) static DEVICE_ATTR_RO(modalias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) static ssize_t prtcid_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) struct tb_service *svc = container_of(dev, struct tb_service, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) return sprintf(buf, "%u\n", svc->prtcid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) static DEVICE_ATTR_RO(prtcid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) static ssize_t prtcvers_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) struct tb_service *svc = container_of(dev, struct tb_service, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) return sprintf(buf, "%u\n", svc->prtcvers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) static DEVICE_ATTR_RO(prtcvers);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) static ssize_t prtcrevs_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) struct tb_service *svc = container_of(dev, struct tb_service, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return sprintf(buf, "%u\n", svc->prtcrevs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) static DEVICE_ATTR_RO(prtcrevs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) static ssize_t prtcstns_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) struct tb_service *svc = container_of(dev, struct tb_service, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return sprintf(buf, "0x%08x\n", svc->prtcstns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) static DEVICE_ATTR_RO(prtcstns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) static struct attribute *tb_service_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) &dev_attr_key.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) &dev_attr_modalias.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) &dev_attr_prtcid.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) &dev_attr_prtcvers.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) &dev_attr_prtcrevs.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) &dev_attr_prtcstns.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) static struct attribute_group tb_service_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) .attrs = tb_service_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) static const struct attribute_group *tb_service_attr_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) &tb_service_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static int tb_service_uevent(struct device *dev, struct kobj_uevent_env *env)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) struct tb_service *svc = container_of(dev, struct tb_service, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) char modalias[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) get_modalias(svc, modalias, sizeof(modalias));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) return add_uevent_var(env, "MODALIAS=%s", modalias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) static void tb_service_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) struct tb_service *svc = container_of(dev, struct tb_service, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) struct tb_xdomain *xd = tb_service_parent(svc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) ida_simple_remove(&xd->service_ids, svc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) kfree(svc->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) kfree(svc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) struct device_type tb_service_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) .name = "thunderbolt_service",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) .groups = tb_service_attr_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) .uevent = tb_service_uevent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) .release = tb_service_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) EXPORT_SYMBOL_GPL(tb_service_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) static int remove_missing_service(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) struct tb_xdomain *xd = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) struct tb_service *svc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) svc = tb_to_service(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) if (!svc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (!tb_property_find(xd->properties, svc->key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) TB_PROPERTY_TYPE_DIRECTORY))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) device_unregister(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) static int find_service(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) const struct tb_property *p = data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) struct tb_service *svc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) svc = tb_to_service(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) if (!svc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) return !strcmp(svc->key, p->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) static int populate_service(struct tb_service *svc,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) struct tb_property *property)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) struct tb_property_dir *dir = property->value.dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct tb_property *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) /* Fill in standard properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) p = tb_property_find(dir, "prtcid", TB_PROPERTY_TYPE_VALUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) svc->prtcid = p->value.immediate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) p = tb_property_find(dir, "prtcvers", TB_PROPERTY_TYPE_VALUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) svc->prtcvers = p->value.immediate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) p = tb_property_find(dir, "prtcrevs", TB_PROPERTY_TYPE_VALUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) svc->prtcrevs = p->value.immediate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) p = tb_property_find(dir, "prtcstns", TB_PROPERTY_TYPE_VALUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) svc->prtcstns = p->value.immediate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) svc->key = kstrdup(property->key, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) if (!svc->key)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) static void enumerate_services(struct tb_xdomain *xd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct tb_service *svc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) struct tb_property *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) int id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) * First remove all services that are not available anymore in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) * the updated property block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) device_for_each_child_reverse(&xd->dev, xd, remove_missing_service);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) /* Then re-enumerate properties creating new services as we go */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) tb_property_for_each(xd->properties, p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (p->type != TB_PROPERTY_TYPE_DIRECTORY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) /* If the service exists already we are fine */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) dev = device_find_child(&xd->dev, p, find_service);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) if (dev) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) put_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) svc = kzalloc(sizeof(*svc), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) if (!svc)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) if (populate_service(svc, p)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) kfree(svc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) id = ida_simple_get(&xd->service_ids, 0, 0, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (id < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) kfree(svc->key);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) kfree(svc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) svc->id = id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) svc->dev.bus = &tb_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) svc->dev.type = &tb_service_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) svc->dev.parent = &xd->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) dev_set_name(&svc->dev, "%s.%d", dev_name(&xd->dev), svc->id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) if (device_register(&svc->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) put_device(&svc->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static int populate_properties(struct tb_xdomain *xd,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct tb_property_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) const struct tb_property *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) /* Required properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) p = tb_property_find(dir, "deviceid", TB_PROPERTY_TYPE_VALUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) xd->device = p->value.immediate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) p = tb_property_find(dir, "vendorid", TB_PROPERTY_TYPE_VALUE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) if (!p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) xd->vendor = p->value.immediate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) kfree(xd->device_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) xd->device_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) kfree(xd->vendor_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) xd->vendor_name = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* Optional properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) p = tb_property_find(dir, "deviceid", TB_PROPERTY_TYPE_TEXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) xd->device_name = kstrdup(p->value.text, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) p = tb_property_find(dir, "vendorid", TB_PROPERTY_TYPE_TEXT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) xd->vendor_name = kstrdup(p->value.text, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) /* Called with @xd->lock held */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) static void tb_xdomain_restore_paths(struct tb_xdomain *xd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (!xd->resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) xd->resume = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (xd->transmit_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) dev_dbg(&xd->dev, "re-establishing DMA path\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) tb_domain_approve_xdomain_paths(xd->tb, xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) static void tb_xdomain_get_uuid(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) struct tb_xdomain *xd = container_of(work, typeof(*xd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) get_uuid_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) struct tb *tb = xd->tb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) uuid_t uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) ret = tb_xdp_uuid_request(tb->ctl, xd->route, xd->uuid_retries, &uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (xd->uuid_retries-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) queue_delayed_work(xd->tb->wq, &xd->get_uuid_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) msecs_to_jiffies(100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) dev_dbg(&xd->dev, "failed to read remote UUID\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (uuid_equal(&uuid, xd->local_uuid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) dev_dbg(&xd->dev, "intra-domain loop detected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) * If the UUID is different, there is another domain connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) * so mark this one unplugged and wait for the connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) * manager to replace it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) if (xd->remote_uuid && !uuid_equal(&uuid, xd->remote_uuid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) dev_dbg(&xd->dev, "remote UUID is different, unplugging\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) xd->is_unplugged = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) /* First time fill in the missing UUID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) if (!xd->remote_uuid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) xd->remote_uuid = kmemdup(&uuid, sizeof(uuid_t), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) if (!xd->remote_uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) /* Now we can start the normal properties exchange */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) msecs_to_jiffies(100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) queue_delayed_work(xd->tb->wq, &xd->get_properties_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) msecs_to_jiffies(1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) static void tb_xdomain_get_properties(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) struct tb_xdomain *xd = container_of(work, typeof(*xd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) get_properties_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) struct tb_property_dir *dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) struct tb *tb = xd->tb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) bool update = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) u32 *block = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) u32 gen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) ret = tb_xdp_properties_request(tb->ctl, xd->route, xd->local_uuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) xd->remote_uuid, xd->properties_retries,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) &block, &gen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) if (xd->properties_retries-- > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) queue_delayed_work(xd->tb->wq, &xd->get_properties_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) msecs_to_jiffies(1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* Give up now */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) dev_err(&xd->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) "failed read XDomain properties from %pUb\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) xd->remote_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) xd->properties_retries = XDOMAIN_PROPERTIES_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) mutex_lock(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) /* Only accept newer generation properties */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (xd->properties && gen <= xd->property_block_gen) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) * On resume it is likely that the properties block is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) * not changed (unless the other end added or removed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) * services). However, we need to make sure the existing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) * DMA paths are restored properly.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) tb_xdomain_restore_paths(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) goto err_free_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) dir = tb_property_parse_dir(block, ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (!dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) dev_err(&xd->dev, "failed to parse XDomain properties\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) goto err_free_block;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) ret = populate_properties(xd, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) dev_err(&xd->dev, "missing XDomain properties in response\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) goto err_free_dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) /* Release the existing one */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (xd->properties) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) tb_property_free_dir(xd->properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) update = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) xd->properties = dir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) xd->property_block_gen = gen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) tb_xdomain_restore_paths(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) mutex_unlock(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) kfree(block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * Now the device should be ready enough so we can add it to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * bus and let userspace know about it. If the device is already
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * registered, we notify the userspace that it has changed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) if (!update) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) if (device_add(&xd->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) dev_err(&xd->dev, "failed to add XDomain device\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) kobject_uevent(&xd->dev.kobj, KOBJ_CHANGE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) enumerate_services(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) err_free_dir:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) tb_property_free_dir(dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) err_free_block:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) kfree(block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) mutex_unlock(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) static void tb_xdomain_properties_changed(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) struct tb_xdomain *xd = container_of(work, typeof(*xd),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) properties_changed_work.work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) ret = tb_xdp_properties_changed_request(xd->tb->ctl, xd->route,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) xd->properties_changed_retries, xd->local_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) if (xd->properties_changed_retries-- > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) queue_delayed_work(xd->tb->wq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) &xd->properties_changed_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) msecs_to_jiffies(1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) xd->properties_changed_retries = XDOMAIN_PROPERTIES_CHANGED_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) static ssize_t device_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) return sprintf(buf, "%#x\n", xd->device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) static DEVICE_ATTR_RO(device);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) device_name_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) if (mutex_lock_interruptible(&xd->lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) ret = sprintf(buf, "%s\n", xd->device_name ? xd->device_name : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) mutex_unlock(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) static DEVICE_ATTR_RO(device_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) static ssize_t vendor_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return sprintf(buf, "%#x\n", xd->vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) static DEVICE_ATTR_RO(vendor);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) vendor_name_show(struct device *dev, struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) if (mutex_lock_interruptible(&xd->lock))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) ret = sprintf(buf, "%s\n", xd->vendor_name ? xd->vendor_name : "");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) mutex_unlock(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) static DEVICE_ATTR_RO(vendor_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) static ssize_t unique_id_show(struct device *dev, struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) return sprintf(buf, "%pUb\n", xd->remote_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) static DEVICE_ATTR_RO(unique_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) static struct attribute *xdomain_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) &dev_attr_device.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) &dev_attr_device_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) &dev_attr_unique_id.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) &dev_attr_vendor.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) &dev_attr_vendor_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) static struct attribute_group xdomain_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) .attrs = xdomain_attrs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) static const struct attribute_group *xdomain_attr_groups[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) &xdomain_attr_group,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) static void tb_xdomain_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) struct tb_xdomain *xd = container_of(dev, struct tb_xdomain, dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) put_device(xd->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) tb_property_free_dir(xd->properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) ida_destroy(&xd->service_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) kfree(xd->local_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) kfree(xd->remote_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) kfree(xd->device_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) kfree(xd->vendor_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) kfree(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) static void start_handshake(struct tb_xdomain *xd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) xd->uuid_retries = XDOMAIN_UUID_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) xd->properties_retries = XDOMAIN_PROPERTIES_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) xd->properties_changed_retries = XDOMAIN_PROPERTIES_CHANGED_RETRIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) if (xd->needs_uuid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) queue_delayed_work(xd->tb->wq, &xd->get_uuid_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) msecs_to_jiffies(100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) /* Start exchanging properties with the other host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) msecs_to_jiffies(100));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) queue_delayed_work(xd->tb->wq, &xd->get_properties_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) msecs_to_jiffies(1000));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) static void stop_handshake(struct tb_xdomain *xd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) xd->uuid_retries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) xd->properties_retries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) xd->properties_changed_retries = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) cancel_delayed_work_sync(&xd->get_uuid_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) cancel_delayed_work_sync(&xd->get_properties_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) cancel_delayed_work_sync(&xd->properties_changed_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) static int __maybe_unused tb_xdomain_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) stop_handshake(tb_to_xdomain(dev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) static int __maybe_unused tb_xdomain_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) struct tb_xdomain *xd = tb_to_xdomain(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) * Ask tb_xdomain_get_properties() restore any existing DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) * paths after properties are re-read.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) xd->resume = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) start_handshake(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) static const struct dev_pm_ops tb_xdomain_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) SET_SYSTEM_SLEEP_PM_OPS(tb_xdomain_suspend, tb_xdomain_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) struct device_type tb_xdomain_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) .name = "thunderbolt_xdomain",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) .release = tb_xdomain_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) .pm = &tb_xdomain_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) EXPORT_SYMBOL_GPL(tb_xdomain_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) * tb_xdomain_alloc() - Allocate new XDomain object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) * @tb: Domain where the XDomain belongs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) * @parent: Parent device (the switch through the connection to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) * other domain is reached).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) * @route: Route string used to reach the other domain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) * @local_uuid: Our local domain UUID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) * @remote_uuid: UUID of the other domain (optional)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) * Allocates new XDomain structure and returns pointer to that. The
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) * object must be released by calling tb_xdomain_put().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) struct tb_xdomain *tb_xdomain_alloc(struct tb *tb, struct device *parent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) u64 route, const uuid_t *local_uuid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) const uuid_t *remote_uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) struct tb_switch *parent_sw = tb_to_switch(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) struct tb_xdomain *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) struct tb_port *down;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) /* Make sure the downstream domain is accessible */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) down = tb_port_at(route, parent_sw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) tb_port_unlock(down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) xd = kzalloc(sizeof(*xd), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) if (!xd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) xd->tb = tb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) xd->route = route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) ida_init(&xd->service_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) mutex_init(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) INIT_DELAYED_WORK(&xd->get_uuid_work, tb_xdomain_get_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) INIT_DELAYED_WORK(&xd->get_properties_work, tb_xdomain_get_properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) INIT_DELAYED_WORK(&xd->properties_changed_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) tb_xdomain_properties_changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) xd->local_uuid = kmemdup(local_uuid, sizeof(uuid_t), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) if (!xd->local_uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) if (remote_uuid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) xd->remote_uuid = kmemdup(remote_uuid, sizeof(uuid_t),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) if (!xd->remote_uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) goto err_free_local_uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) xd->needs_uuid = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) device_initialize(&xd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) xd->dev.parent = get_device(parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) xd->dev.bus = &tb_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) xd->dev.type = &tb_xdomain_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) xd->dev.groups = xdomain_attr_groups;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) dev_set_name(&xd->dev, "%u-%llx", tb->index, route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) * This keeps the DMA powered on as long as we have active
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) * connection to another host.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) pm_runtime_set_active(&xd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) pm_runtime_get_noresume(&xd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) pm_runtime_enable(&xd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) return xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) err_free_local_uuid:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) kfree(xd->local_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) kfree(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) * tb_xdomain_add() - Add XDomain to the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) * @xd: XDomain to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) * This function starts XDomain discovery protocol handshake and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) * eventually adds the XDomain to the bus. After calling this function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) * the caller needs to call tb_xdomain_remove() in order to remove and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) * release the object regardless whether the handshake succeeded or not.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) void tb_xdomain_add(struct tb_xdomain *xd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) /* Start exchanging properties with the other host */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) start_handshake(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) static int unregister_service(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) device_unregister(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) * tb_xdomain_remove() - Remove XDomain from the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) * @xd: XDomain to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) * This will stop all ongoing configuration work and remove the XDomain
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) * along with any services from the bus. When the last reference to @xd
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) * is released the object will be released as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) void tb_xdomain_remove(struct tb_xdomain *xd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) stop_handshake(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) device_for_each_child_reverse(&xd->dev, xd, unregister_service);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) * Undo runtime PM here explicitly because it is possible that
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) * the XDomain was never added to the bus and thus device_del()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) * is not called for it (device_del() would handle this otherwise).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) pm_runtime_disable(&xd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) pm_runtime_put_noidle(&xd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) pm_runtime_set_suspended(&xd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) if (!device_is_registered(&xd->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) put_device(&xd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) device_unregister(&xd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) * tb_xdomain_enable_paths() - Enable DMA paths for XDomain connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) * @xd: XDomain connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) * @transmit_path: HopID of the transmit path the other end is using to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) * send packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) * @transmit_ring: DMA ring used to receive packets from the other end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) * @receive_path: HopID of the receive path the other end is using to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) * receive packets
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) * @receive_ring: DMA ring used to send packets to the other end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) * The function enables DMA paths accordingly so that after successful
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) * return the caller can send and receive packets using high-speed DMA
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) * path.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) * Return: %0 in case of success and negative errno in case of error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) int tb_xdomain_enable_paths(struct tb_xdomain *xd, u16 transmit_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) u16 transmit_ring, u16 receive_path,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) u16 receive_ring)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) mutex_lock(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) if (xd->transmit_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) ret = xd->transmit_path == transmit_path ? 0 : -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) goto exit_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413) xd->transmit_path = transmit_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) xd->transmit_ring = transmit_ring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) xd->receive_path = receive_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) xd->receive_ring = receive_ring;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) ret = tb_domain_approve_xdomain_paths(xd->tb, xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) exit_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) mutex_unlock(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) EXPORT_SYMBOL_GPL(tb_xdomain_enable_paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) * tb_xdomain_disable_paths() - Disable DMA paths for XDomain connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) * @xd: XDomain connection
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) * This does the opposite of tb_xdomain_enable_paths(). After call to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) * this the caller is not expected to use the rings anymore.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) * Return: %0 in case of success and negative errno in case of error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) int tb_xdomain_disable_paths(struct tb_xdomain *xd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) mutex_lock(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) if (xd->transmit_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) xd->transmit_path = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) xd->transmit_ring = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444) xd->receive_path = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) xd->receive_ring = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) ret = tb_domain_disconnect_xdomain_paths(xd->tb, xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449) mutex_unlock(&xd->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) EXPORT_SYMBOL_GPL(tb_xdomain_disable_paths);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455) struct tb_xdomain_lookup {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) const uuid_t *uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) u8 link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) u8 depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459) u64 route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) static struct tb_xdomain *switch_find_xdomain(struct tb_switch *sw,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) const struct tb_xdomain_lookup *lookup)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) struct tb_port *port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467) tb_switch_for_each_port(sw, port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) struct tb_xdomain *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) if (port->xdomain) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) xd = port->xdomain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) if (lookup->uuid) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474) if (xd->remote_uuid &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) uuid_equal(xd->remote_uuid, lookup->uuid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) return xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) } else if (lookup->link &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) lookup->link == xd->link &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) lookup->depth == xd->depth) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) return xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) } else if (lookup->route &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) lookup->route == xd->route) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) return xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) } else if (tb_port_has_remote(port)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) xd = switch_find_xdomain(port->remote->sw, lookup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487) if (xd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) return xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) * tb_xdomain_find_by_uuid() - Find an XDomain by UUID
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) * @tb: Domain where the XDomain belongs to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) * @uuid: UUID to look for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) * Finds XDomain by walking through the Thunderbolt topology below @tb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) * The returned XDomain will have its reference count increased so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) * caller needs to call tb_xdomain_put() when it is done with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) * object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) * This will find all XDomains including the ones that are not yet added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) * to the bus (handshake is still in progress).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) * The caller needs to hold @tb->lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) struct tb_xdomain *tb_xdomain_find_by_uuid(struct tb *tb, const uuid_t *uuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) struct tb_xdomain_lookup lookup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) struct tb_xdomain *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) memset(&lookup, 0, sizeof(lookup));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) lookup.uuid = uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) xd = switch_find_xdomain(tb->root_switch, &lookup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) return tb_xdomain_get(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) EXPORT_SYMBOL_GPL(tb_xdomain_find_by_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) * tb_xdomain_find_by_link_depth() - Find an XDomain by link and depth
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) * @tb: Domain where the XDomain belongs to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) * @link: Root switch link number
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) * @depth: Depth in the link
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) * Finds XDomain by walking through the Thunderbolt topology below @tb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) * The returned XDomain will have its reference count increased so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) * caller needs to call tb_xdomain_put() when it is done with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) * object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534) * This will find all XDomains including the ones that are not yet added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) * to the bus (handshake is still in progress).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) * The caller needs to hold @tb->lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539) struct tb_xdomain *tb_xdomain_find_by_link_depth(struct tb *tb, u8 link,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) u8 depth)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) struct tb_xdomain_lookup lookup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) struct tb_xdomain *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) memset(&lookup, 0, sizeof(lookup));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) lookup.link = link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) lookup.depth = depth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) xd = switch_find_xdomain(tb->root_switch, &lookup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) return tb_xdomain_get(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) * tb_xdomain_find_by_route() - Find an XDomain by route string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) * @tb: Domain where the XDomain belongs to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) * @route: XDomain route string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) * Finds XDomain by walking through the Thunderbolt topology below @tb.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) * The returned XDomain will have its reference count increased so the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560) * caller needs to call tb_xdomain_put() when it is done with the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) * object.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) * This will find all XDomains including the ones that are not yet added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564) * to the bus (handshake is still in progress).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) * The caller needs to hold @tb->lock.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568) struct tb_xdomain *tb_xdomain_find_by_route(struct tb *tb, u64 route)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) struct tb_xdomain_lookup lookup;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571) struct tb_xdomain *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) memset(&lookup, 0, sizeof(lookup));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) lookup.route = route;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) xd = switch_find_xdomain(tb->root_switch, &lookup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) return tb_xdomain_get(xd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) EXPORT_SYMBOL_GPL(tb_xdomain_find_by_route);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) bool tb_xdomain_handle_request(struct tb *tb, enum tb_cfg_pkg_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) const void *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) const struct tb_protocol_handler *handler, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585) const struct tb_xdp_header *hdr = buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) unsigned int length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589) /* We expect the packet is at least size of the header */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) length = hdr->xd_hdr.length_sn & TB_XDOMAIN_LENGTH_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) if (length != size / 4 - sizeof(hdr->xd_hdr) / 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) if (length < sizeof(*hdr) / 4 - sizeof(hdr->xd_hdr) / 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) * Handle XDomain discovery protocol packets directly here. For
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) * other protocols (based on their UUID) we call registered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599) * handlers in turn.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) if (uuid_equal(&hdr->uuid, &tb_xdp_uuid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) if (type == TB_CFG_PKG_XDOMAIN_REQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) return tb_xdp_schedule_request(tb, hdr, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) mutex_lock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) list_for_each_entry_safe(handler, tmp, &protocol_handlers, list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) if (!uuid_equal(&hdr->uuid, handler->uuid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) ret = handler->callback(buf, size, handler->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) mutex_lock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621) return ret > 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) static int update_xdomain(struct device *dev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) struct tb_xdomain *xd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) xd = tb_to_xdomain(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) if (xd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) queue_delayed_work(xd->tb->wq, &xd->properties_changed_work,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) msecs_to_jiffies(50));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637) static void update_all_xdomains(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) bus_for_each_dev(&tb_bus_type, NULL, NULL, update_xdomain);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) static bool remove_directory(const char *key, const struct tb_property_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644) struct tb_property *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) p = tb_property_find(xdomain_property_dir, key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) TB_PROPERTY_TYPE_DIRECTORY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) if (p && p->value.dir == dir) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649) tb_property_remove(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) * tb_register_property_dir() - Register property directory to the host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) * @key: Key (name) of the directory to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) * @dir: Directory to add
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) * Service drivers can use this function to add new property directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661) * to the host available properties. The other connected hosts are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) * notified so they can re-read properties of this host if they are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1663) * interested.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1664) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1665) * Return: %0 on success and negative errno on failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1666) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1667) int tb_register_property_dir(const char *key, struct tb_property_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1668) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1669) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1670)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1671) if (WARN_ON(!xdomain_property_dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1672) return -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1674) if (!key || strlen(key) > 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1675) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1676)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1677) mutex_lock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1678) if (tb_property_find(xdomain_property_dir, key,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1679) TB_PROPERTY_TYPE_DIRECTORY)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1680) ret = -EEXIST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1681) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1682) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1683)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1684) ret = tb_property_add_dir(xdomain_property_dir, key, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1685) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1686) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1687)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1688) ret = rebuild_property_block();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1689) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1690) remove_directory(key, dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1691) goto err_unlock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1692) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1693)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1694) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1695) update_all_xdomains();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1696) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1697)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1698) err_unlock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1699) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1700) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1701) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1702) EXPORT_SYMBOL_GPL(tb_register_property_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1704) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1705) * tb_unregister_property_dir() - Removes property directory from host
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1706) * @key: Key (name) of the directory
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1707) * @dir: Directory to remove
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1708) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1709) * This will remove the existing directory from this host and notify the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1710) * connected hosts about the change.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1711) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1712) void tb_unregister_property_dir(const char *key, struct tb_property_dir *dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1713) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1714) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1716) mutex_lock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1717) if (remove_directory(key, dir))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1718) ret = rebuild_property_block();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1719) mutex_unlock(&xdomain_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1720)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1721) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1722) update_all_xdomains();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1723) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1724) EXPORT_SYMBOL_GPL(tb_unregister_property_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1725)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1726) int tb_xdomain_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1727) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1728) xdomain_property_dir = tb_property_create_dir(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1729) if (!xdomain_property_dir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1730) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1732) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1733) * Initialize standard set of properties without any service
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1734) * directories. Those will be added by service drivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1735) * themselves when they are loaded.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1736) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1737) * We also add node name later when first connection is made.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1738) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1739) tb_property_add_immediate(xdomain_property_dir, "vendorid",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1740) PCI_VENDOR_ID_INTEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1741) tb_property_add_text(xdomain_property_dir, "vendorid", "Intel Corp.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1742) tb_property_add_immediate(xdomain_property_dir, "deviceid", 0x1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1743) tb_property_add_immediate(xdomain_property_dir, "devicerv", 0x80000100);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1745) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1746) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1747)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1748) void tb_xdomain_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1749) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1750) kfree(xdomain_property_block);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1751) tb_property_free_dir(xdomain_property_dir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1752) }