^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) * Copyright (c) 2012-2019, Intel Corporation. All rights reserved.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Intel Management Engine Interface (Intel MEI) Linux driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/sched/signal.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mei_cl_bus.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include "mei_dev.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include "client.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define to_mei_cl_driver(d) container_of(d, struct mei_cl_driver, driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * __mei_cl_send - internal client send (write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * @cl: host client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * @buf: buffer to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * @length: buffer length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * @mode: sending mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * Return: written size bytes or < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) unsigned int mode)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct mei_device *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct mei_cl_cb *cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) ssize_t rets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (WARN_ON(!cl || !cl->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) bus = cl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) mutex_lock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) if (bus->dev_state != MEI_DEV_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) rets = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (!mei_cl_is_connected(cl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) rets = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* Check if we have an ME client device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (!mei_me_cl_is_active(cl->me_cl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) rets = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) if (length > mei_cl_mtu(cl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) rets = -EFBIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) while (cl->tx_cb_queued >= bus->tx_queue_limit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) mutex_unlock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) rets = wait_event_interruptible(cl->tx_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) cl->writing_state == MEI_WRITE_COMPLETE ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) (!mei_cl_is_connected(cl)));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) mutex_lock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (rets) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) rets = -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if (!mei_cl_is_connected(cl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) rets = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) if (!cb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) rets = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) cb->internal = !!(mode & MEI_CL_IO_TX_INTERNAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) cb->blocking = !!(mode & MEI_CL_IO_TX_BLOCKING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) memcpy(cb->buf.data, buf, length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) rets = mei_cl_write(cl, cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) mutex_unlock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) return rets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * __mei_cl_recv - internal client receive (read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * @cl: host client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * @buf: buffer to receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * @length: buffer length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * @mode: io mode
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * @timeout: recv timeout, 0 for infinite timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * Return: read size in bytes of < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) unsigned int mode, unsigned long timeout)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) struct mei_device *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) struct mei_cl_cb *cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) size_t r_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) ssize_t rets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) bool nonblock = !!(mode & MEI_CL_IO_RX_NONBLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) if (WARN_ON(!cl || !cl->dev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) bus = cl->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) mutex_lock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) if (bus->dev_state != MEI_DEV_ENABLED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) rets = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) cb = mei_cl_read_cb(cl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) if (cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) goto copy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) rets = mei_cl_read_start(cl, length, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) if (rets && rets != -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) if (nonblock) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) rets = -EAGAIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* wait on event only if there is no other waiter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) /* synchronized under device mutex */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) if (!waitqueue_active(&cl->rx_wait)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) mutex_unlock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) if (timeout) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) rets = wait_event_interruptible_timeout
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) (cl->rx_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) mei_cl_read_cb(cl, NULL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) (!mei_cl_is_connected(cl)),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) msecs_to_jiffies(timeout));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) if (rets == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return -ETIME;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) if (rets < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (wait_event_interruptible
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) (cl->rx_wait,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) mei_cl_read_cb(cl, NULL) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) (!mei_cl_is_connected(cl)))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (signal_pending(current))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) return -EINTR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return -ERESTARTSYS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) mutex_lock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) if (!mei_cl_is_connected(cl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) rets = -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) cb = mei_cl_read_cb(cl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (!cb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) rets = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) copy:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (cb->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) rets = cb->status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) goto free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) r_length = min_t(size_t, length, cb->buf_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) memcpy(buf, cb->buf.data, r_length);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) rets = r_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) mei_cl_del_rd_completed(cl, cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) mutex_unlock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) return rets;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) * mei_cldev_send - me device send (write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * @buf: buffer to send
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) * @length: buffer length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) * Return: written size in bytes or < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) ssize_t mei_cldev_send(struct mei_cl_device *cldev, u8 *buf, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct mei_cl *cl = cldev->cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) return __mei_cl_send(cl, buf, length, MEI_CL_IO_TX_BLOCKING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) EXPORT_SYMBOL_GPL(mei_cldev_send);
^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) * mei_cldev_recv_nonblock - non block client receive (read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) * @buf: buffer to receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) * @length: buffer length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * Return: read size in bytes of < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * -EAGAIN if function will block.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) ssize_t mei_cldev_recv_nonblock(struct mei_cl_device *cldev, u8 *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct mei_cl *cl = cldev->cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) return __mei_cl_recv(cl, buf, length, MEI_CL_IO_RX_NONBLOCK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) EXPORT_SYMBOL_GPL(mei_cldev_recv_nonblock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) * mei_cldev_recv - client receive (read)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) * @buf: buffer to receive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) * @length: buffer length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) * Return: read size in bytes of < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) ssize_t mei_cldev_recv(struct mei_cl_device *cldev, u8 *buf, size_t length)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) struct mei_cl *cl = cldev->cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return __mei_cl_recv(cl, buf, length, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) EXPORT_SYMBOL_GPL(mei_cldev_recv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) * mei_cl_bus_rx_work - dispatch rx event for a bus device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) * @work: work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static void mei_cl_bus_rx_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) struct mei_cl_device *cldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) struct mei_device *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) cldev = container_of(work, struct mei_cl_device, rx_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) bus = cldev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) if (cldev->rx_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) cldev->rx_cb(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) mutex_lock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) mutex_unlock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^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) * mei_cl_bus_notif_work - dispatch FW notif event for a bus device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) * @work: work
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) static void mei_cl_bus_notif_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct mei_cl_device *cldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) cldev = container_of(work, struct mei_cl_device, notif_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) if (cldev->notif_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) cldev->notif_cb(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) * mei_cl_bus_notify_event - schedule notify cb on bus client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) * @cl: host client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) * Return: true if event was scheduled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) * false if the client is not waiting for event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) bool mei_cl_bus_notify_event(struct mei_cl *cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) struct mei_cl_device *cldev = cl->cldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) if (!cldev || !cldev->notif_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) if (!cl->notify_ev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) schedule_work(&cldev->notif_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) cl->notify_ev = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) * mei_cl_bus_rx_event - schedule rx event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) * @cl: host client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) * Return: true if event was scheduled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) * false if the client is not waiting for event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) bool mei_cl_bus_rx_event(struct mei_cl *cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) struct mei_cl_device *cldev = cl->cldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (!cldev || !cldev->rx_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) schedule_work(&cldev->rx_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) * mei_cldev_register_rx_cb - register Rx event callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) * @cldev: me client devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) * @rx_cb: callback function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) * Return: 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) * -EALREADY if an callback is already registered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) * <0 on other errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) int mei_cldev_register_rx_cb(struct mei_cl_device *cldev, mei_cldev_cb_t rx_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) struct mei_device *bus = cldev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) if (!rx_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (cldev->rx_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) return -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) cldev->rx_cb = rx_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) INIT_WORK(&cldev->rx_work, mei_cl_bus_rx_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) mutex_lock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ret = mei_cl_read_start(cldev->cl, mei_cl_mtu(cldev->cl), NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) mutex_unlock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) if (ret && ret != -EBUSY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) EXPORT_SYMBOL_GPL(mei_cldev_register_rx_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) * mei_cldev_register_notif_cb - register FW notification event callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) * @cldev: me client devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) * @notif_cb: callback function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) * Return: 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) * -EALREADY if an callback is already registered
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) * <0 on other errors
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int mei_cldev_register_notif_cb(struct mei_cl_device *cldev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) mei_cldev_cb_t notif_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) struct mei_device *bus = cldev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) if (!notif_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (cldev->notif_cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) return -EALREADY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) cldev->notif_cb = notif_cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) INIT_WORK(&cldev->notif_work, mei_cl_bus_notif_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) mutex_lock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) ret = mei_cl_notify_request(cldev->cl, NULL, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) mutex_unlock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) EXPORT_SYMBOL_GPL(mei_cldev_register_notif_cb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) * mei_cldev_get_drvdata - driver data getter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * @cldev: mei client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) * Return: driver private data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) void *mei_cldev_get_drvdata(const struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) return dev_get_drvdata(&cldev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) EXPORT_SYMBOL_GPL(mei_cldev_get_drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) * mei_cldev_set_drvdata - driver data setter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) * @cldev: mei client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) * @data: data to store
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) void mei_cldev_set_drvdata(struct mei_cl_device *cldev, void *data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) dev_set_drvdata(&cldev->dev, data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) EXPORT_SYMBOL_GPL(mei_cldev_set_drvdata);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) * mei_cldev_uuid - return uuid of the underlying me client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) * @cldev: mei client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) * Return: me client uuid
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) const uuid_le *mei_cldev_uuid(const struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) return mei_me_cl_uuid(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) EXPORT_SYMBOL_GPL(mei_cldev_uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) * mei_cldev_ver - return protocol version of the underlying me client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) * @cldev: mei client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * Return: me client protocol version
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) u8 mei_cldev_ver(const struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return mei_me_cl_ver(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) EXPORT_SYMBOL_GPL(mei_cldev_ver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) * mei_cldev_enabled - check whether the device is enabled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) * @cldev: mei client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) * Return: true if me client is initialized and connected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) bool mei_cldev_enabled(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) return mei_cl_is_connected(cldev->cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) EXPORT_SYMBOL_GPL(mei_cldev_enabled);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) * mei_cl_bus_module_get - acquire module of the underlying
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) * hw driver.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) * @cldev: mei client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * Return: true on success; false if the module was removed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) static bool mei_cl_bus_module_get(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) return try_module_get(cldev->bus->dev->driver->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * mei_cl_bus_module_put - release the underlying hw module.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) * @cldev: mei client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static void mei_cl_bus_module_put(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) module_put(cldev->bus->dev->driver->owner);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) * mei_cl_bus_vtag - get bus vtag entry wrapper
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) * The tag for bus client is always first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) * @cl: host client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) * Return: bus vtag or NULL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) static inline struct mei_cl_vtag *mei_cl_bus_vtag(struct mei_cl *cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) return list_first_entry_or_null(&cl->vtag_map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct mei_cl_vtag, list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) * mei_cl_bus_vtag_alloc - add bus client entry to vtag map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) * Return:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) * * 0 on success
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) * * -ENOMEM if memory allocation failed
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) static int mei_cl_bus_vtag_alloc(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) struct mei_cl *cl = cldev->cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) struct mei_cl_vtag *cl_vtag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) * Bail out if the client does not supports vtags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) * or has already allocated one
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) if (mei_cl_vt_support_check(cl) || mei_cl_bus_vtag(cl))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) cl_vtag = mei_cl_vtag_alloc(NULL, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) if (IS_ERR(cl_vtag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) list_add_tail(&cl_vtag->list, &cl->vtag_map);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) * mei_cl_bus_vtag_free - remove the bus entry from vtag map
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) static void mei_cl_bus_vtag_free(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) struct mei_cl *cl = cldev->cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) struct mei_cl_vtag *cl_vtag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) cl_vtag = mei_cl_bus_vtag(cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) if (!cl_vtag)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) list_del(&cl_vtag->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) kfree(cl_vtag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) * mei_cldev_enable - enable me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) * create connection with me client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * Return: 0 on success and < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) int mei_cldev_enable(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) struct mei_device *bus = cldev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) struct mei_cl *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) cl = cldev->cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) mutex_lock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) if (cl->state == MEI_FILE_UNINITIALIZED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) ret = mei_cl_link(cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) /* update pointers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) cl->cldev = cldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (mei_cl_is_connected(cl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) if (!mei_me_cl_is_active(cldev->me_cl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) dev_err(&cldev->dev, "me client is not active\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) ret = -ENOTTY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) ret = mei_cl_bus_vtag_alloc(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) ret = mei_cl_connect(cl, cldev->me_cl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) dev_err(&cldev->dev, "cannot connect\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) mei_cl_bus_vtag_free(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) mutex_unlock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) EXPORT_SYMBOL_GPL(mei_cldev_enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) * mei_cldev_unregister_callbacks - internal wrapper for unregistering
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) * callbacks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * @cldev: client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) static void mei_cldev_unregister_callbacks(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (cldev->rx_cb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) cancel_work_sync(&cldev->rx_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) cldev->rx_cb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) if (cldev->notif_cb) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) cancel_work_sync(&cldev->notif_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) cldev->notif_cb = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) * mei_cldev_disable - disable me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) * disconnect form the me client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) * Return: 0 on success and < 0 on error
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) int mei_cldev_disable(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) struct mei_device *bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) struct mei_cl *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (!cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) cl = cldev->cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) bus = cldev->bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) mei_cldev_unregister_callbacks(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) mutex_lock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) mei_cl_bus_vtag_free(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (!mei_cl_is_connected(cl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) dev_dbg(bus->dev, "Already disconnected\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) err = mei_cl_disconnect(cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) dev_err(bus->dev, "Could not disconnect from the ME client\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) /* Flush queues and remove any pending read */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) mei_cl_flush_queues(cl, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) mei_cl_unlink(cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) mutex_unlock(&bus->device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) EXPORT_SYMBOL_GPL(mei_cldev_disable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * mei_cl_device_find - find matching entry in the driver id table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * @cldrv: me client driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * Return: id on success; NULL if no id is matching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) static const
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) struct mei_cl_device_id *mei_cl_device_find(struct mei_cl_device *cldev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) struct mei_cl_driver *cldrv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) const struct mei_cl_device_id *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) const uuid_le *uuid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) u8 version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) bool match;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) uuid = mei_me_cl_uuid(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) version = mei_me_cl_ver(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) id = cldrv->id_table;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) while (uuid_le_cmp(NULL_UUID_LE, id->uuid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) if (!uuid_le_cmp(*uuid, id->uuid)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) match = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) if (cldev->name[0])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) if (strncmp(cldev->name, id->name,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) sizeof(id->name)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) match = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (id->version != MEI_CL_VERSION_ANY)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) if (id->version != version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) match = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) if (match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) id++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) * mei_cl_device_match - device match function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) * @dev: device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) * @drv: driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) * Return: 1 if matching device was found 0 otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) static int mei_cl_device_match(struct device *dev, struct device_driver *drv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) struct mei_cl_driver *cldrv = to_mei_cl_driver(drv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) const struct mei_cl_device_id *found_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) if (!cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (!cldev->do_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) if (!cldrv || !cldrv->id_table)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) found_id = mei_cl_device_find(cldev, cldrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) if (found_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * mei_cl_device_probe - bus probe function
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) * @dev: device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) * Return: 0 on success; < 0 otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) static int mei_cl_device_probe(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) struct mei_cl_device *cldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) struct mei_cl_driver *cldrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) const struct mei_cl_device_id *id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) cldrv = to_mei_cl_driver(dev->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) if (!cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (!cldrv || !cldrv->probe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) id = mei_cl_device_find(cldev, cldrv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) if (!id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) if (!mei_cl_bus_module_get(cldev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) dev_err(&cldev->dev, "get hw module failed");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) ret = cldrv->probe(cldev, id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) mei_cl_bus_module_put(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) __module_get(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) * mei_cl_device_remove - remove device from the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) * @dev: device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) * Return: 0 on success; < 0 otherwise
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) static int mei_cl_device_remove(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) struct mei_cl_driver *cldrv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (!cldev || !dev->driver)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) cldrv = to_mei_cl_driver(dev->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) if (cldrv->remove)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) ret = cldrv->remove(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) mei_cldev_unregister_callbacks(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) mei_cl_bus_module_put(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) module_put(THIS_MODULE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) static ssize_t name_show(struct device *dev, struct device_attribute *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) return scnprintf(buf, PAGE_SIZE, "%s", cldev->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) static DEVICE_ATTR_RO(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) static ssize_t uuid_show(struct device *dev, struct device_attribute *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) return sprintf(buf, "%pUl", uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) static DEVICE_ATTR_RO(uuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) static ssize_t version_show(struct device *dev, struct device_attribute *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) u8 version = mei_me_cl_ver(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) return sprintf(buf, "%02X", version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) static DEVICE_ATTR_RO(version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) static ssize_t modalias_show(struct device *dev, struct device_attribute *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) u8 version = mei_me_cl_ver(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) return scnprintf(buf, PAGE_SIZE, "mei:%s:%pUl:%02X:",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) cldev->name, uuid, version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) static DEVICE_ATTR_RO(modalias);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) static ssize_t max_conn_show(struct device *dev, struct device_attribute *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) u8 maxconn = mei_me_cl_max_conn(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) return sprintf(buf, "%d", maxconn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) static DEVICE_ATTR_RO(max_conn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) static ssize_t fixed_show(struct device *dev, struct device_attribute *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) u8 fixed = mei_me_cl_fixed(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return sprintf(buf, "%d", fixed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) static DEVICE_ATTR_RO(fixed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) static ssize_t vtag_show(struct device *dev, struct device_attribute *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) bool vt = mei_me_cl_vt(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) return sprintf(buf, "%d", vt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) static DEVICE_ATTR_RO(vtag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) static ssize_t max_len_show(struct device *dev, struct device_attribute *a,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) u32 maxlen = mei_me_cl_max_len(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) return sprintf(buf, "%u", maxlen);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static DEVICE_ATTR_RO(max_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) static struct attribute *mei_cldev_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) &dev_attr_name.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) &dev_attr_uuid.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) &dev_attr_version.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) &dev_attr_modalias.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) &dev_attr_max_conn.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) &dev_attr_fixed.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) &dev_attr_vtag.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) &dev_attr_max_len.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) ATTRIBUTE_GROUPS(mei_cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) * mei_cl_device_uevent - me client bus uevent handler
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) * @dev: device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) * @env: uevent kobject
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) * Return: 0 on success -ENOMEM on when add_uevent_var fails
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) static int mei_cl_device_uevent(struct device *dev, struct kobj_uevent_env *env)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) u8 version = mei_me_cl_ver(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) if (add_uevent_var(env, "MEI_CL_VERSION=%d", version))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) if (add_uevent_var(env, "MEI_CL_UUID=%pUl", uuid))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (add_uevent_var(env, "MEI_CL_NAME=%s", cldev->name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) if (add_uevent_var(env, "MODALIAS=mei:%s:%pUl:%02X:",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) cldev->name, uuid, version))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) return 0;
^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 struct bus_type mei_cl_bus_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) .name = "mei",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) .dev_groups = mei_cldev_groups,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) .match = mei_cl_device_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) .probe = mei_cl_device_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) .remove = mei_cl_device_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) .uevent = mei_cl_device_uevent,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) static struct mei_device *mei_dev_bus_get(struct mei_device *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) if (bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) get_device(bus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) return bus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) static void mei_dev_bus_put(struct mei_device *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) if (bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) put_device(bus->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) static void mei_cl_bus_dev_release(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) struct mei_cl_device *cldev = to_mei_cl_device(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (!cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) mei_me_cl_put(cldev->me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) mei_dev_bus_put(cldev->bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) mei_cl_unlink(cldev->cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) kfree(cldev->cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) kfree(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) static const struct device_type mei_cl_device_type = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) .release = mei_cl_bus_dev_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) };
^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) * mei_cl_bus_set_name - set device name for me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) * <controller>-<client device>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) * Example: 0000:00:16.0-55213584-9a29-4916-badf-0fb7ed682aeb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) static inline void mei_cl_bus_set_name(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) dev_set_name(&cldev->dev, "%s-%pUl",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) dev_name(cldev->bus->dev),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) mei_me_cl_uuid(cldev->me_cl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) * mei_cl_bus_dev_alloc - initialize and allocate mei client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) * @bus: mei device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) * @me_cl: me client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) * Return: allocated device structur or NULL on allocation failure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) static struct mei_cl_device *mei_cl_bus_dev_alloc(struct mei_device *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) struct mei_me_client *me_cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct mei_cl_device *cldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) struct mei_cl *cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) cldev = kzalloc(sizeof(*cldev), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) if (!cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) cl = mei_cl_allocate(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) if (!cl) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) kfree(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) device_initialize(&cldev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) cldev->dev.parent = bus->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) cldev->dev.bus = &mei_cl_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) cldev->dev.type = &mei_cl_device_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) cldev->bus = mei_dev_bus_get(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) cldev->me_cl = mei_me_cl_get(me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) cldev->cl = cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) mei_cl_bus_set_name(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) cldev->is_added = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) INIT_LIST_HEAD(&cldev->bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) return cldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) * mei_cl_dev_setup - setup me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) * run fix up routines and set the device name
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) * @bus: mei device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) * Return: true if the device is eligible for enumeration
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) static bool mei_cl_bus_dev_setup(struct mei_device *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) cldev->do_match = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) mei_cl_bus_dev_fixup(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) /* the device name can change during fix up */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) if (cldev->do_match)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) mei_cl_bus_set_name(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) return cldev->do_match == 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) * mei_cl_bus_dev_add - add me client devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) * Return: 0 on success; < 0 on failre
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) static int mei_cl_bus_dev_add(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) dev_dbg(cldev->bus->dev, "adding %pUL:%02X\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) mei_me_cl_uuid(cldev->me_cl),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) mei_me_cl_ver(cldev->me_cl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) ret = device_add(&cldev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) if (!ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) cldev->is_added = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) * mei_cl_bus_dev_stop - stop the driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) static void mei_cl_bus_dev_stop(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (cldev->is_added)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) device_release_driver(&cldev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) * mei_cl_bus_dev_destroy - destroy me client devices object
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) * Locking: called under "dev->cl_bus_lock" lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) static void mei_cl_bus_dev_destroy(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) WARN_ON(!mutex_is_locked(&cldev->bus->cl_bus_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if (!cldev->is_added)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) device_del(&cldev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) list_del_init(&cldev->bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) cldev->is_added = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) put_device(&cldev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) * mei_cl_bus_remove_device - remove a devices form the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) * @cldev: me client device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) static void mei_cl_bus_remove_device(struct mei_cl_device *cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) mei_cl_bus_dev_stop(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) mei_cl_bus_dev_destroy(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) * mei_cl_bus_remove_devices - remove all devices form the bus
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) * @bus: mei device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) void mei_cl_bus_remove_devices(struct mei_device *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct mei_cl_device *cldev, *next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) mutex_lock(&bus->cl_bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) list_for_each_entry_safe(cldev, next, &bus->device_list, bus_list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) mei_cl_bus_remove_device(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) mutex_unlock(&bus->cl_bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) * mei_cl_bus_dev_init - allocate and initializes an mei client devices
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) * based on me client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) * @bus: mei device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) * @me_cl: me client
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) * Locking: called under "dev->cl_bus_lock" lock
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) static void mei_cl_bus_dev_init(struct mei_device *bus,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) struct mei_me_client *me_cl)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) struct mei_cl_device *cldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) WARN_ON(!mutex_is_locked(&bus->cl_bus_lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) dev_dbg(bus->dev, "initializing %pUl", mei_me_cl_uuid(me_cl));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (me_cl->bus_added)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) cldev = mei_cl_bus_dev_alloc(bus, me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) if (!cldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) me_cl->bus_added = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) list_add_tail(&cldev->bus_list, &bus->device_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) }
^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) * mei_cl_bus_rescan - scan me clients list and add create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) * devices for eligible clients
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) * @bus: mei device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) static void mei_cl_bus_rescan(struct mei_device *bus)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) struct mei_cl_device *cldev, *n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) struct mei_me_client *me_cl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) mutex_lock(&bus->cl_bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) down_read(&bus->me_clients_rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) list_for_each_entry(me_cl, &bus->me_clients, list)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) mei_cl_bus_dev_init(bus, me_cl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) up_read(&bus->me_clients_rwsem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) list_for_each_entry_safe(cldev, n, &bus->device_list, bus_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) if (!mei_me_cl_is_active(cldev->me_cl)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) mei_cl_bus_remove_device(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) if (cldev->is_added)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) if (mei_cl_bus_dev_setup(bus, cldev))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) mei_cl_bus_dev_add(cldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) list_del_init(&cldev->bus_list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) put_device(&cldev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) mutex_unlock(&bus->cl_bus_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) dev_dbg(bus->dev, "rescan end");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) void mei_cl_bus_rescan_work(struct work_struct *work)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) struct mei_device *bus =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) container_of(work, struct mei_device, bus_rescan_work);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) mei_cl_bus_rescan(bus);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) int __mei_cldev_driver_register(struct mei_cl_driver *cldrv,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) struct module *owner)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) cldrv->driver.name = cldrv->name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) cldrv->driver.owner = owner;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) cldrv->driver.bus = &mei_cl_bus_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) err = driver_register(&cldrv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) pr_debug("mei: driver [%s] registered\n", cldrv->driver.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) EXPORT_SYMBOL_GPL(__mei_cldev_driver_register);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) void mei_cldev_driver_unregister(struct mei_cl_driver *cldrv)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) driver_unregister(&cldrv->driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) pr_debug("mei: driver [%s] unregistered\n", cldrv->driver.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) EXPORT_SYMBOL_GPL(mei_cldev_driver_unregister);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) int __init mei_cl_bus_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) return bus_register(&mei_cl_bus_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) void __exit mei_cl_bus_exit(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) bus_unregister(&mei_cl_bus_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }