xref: /openbmc/linux/drivers/peci/device.c (revision 52857e6828e260b16ac569578705f83cf2a71ac1)
1 // SPDX-License-Identifier: GPL-2.0-only
2 // Copyright (c) 2018-2021 Intel Corporation
3 
4 #include <linux/peci.h>
5 #include <linux/slab.h>
6 
7 #include "internal.h"
8 
9 /*
10  * PECI device can be removed using sysfs, but the removal can also happen as
11  * a result of controller being removed.
12  * Mutex is used to protect PECI device from being double-deleted.
13  */
14 static DEFINE_MUTEX(peci_device_del_lock);
15 
16 static int peci_detect(struct peci_controller *controller, u8 addr)
17 {
18 	/*
19 	 * PECI Ping is a command encoded by tx_len = 0, rx_len = 0.
20 	 * We expect correct Write FCS if the device at the target address
21 	 * is able to respond.
22 	 */
23 	struct peci_request req = { 0 };
24 	int ret;
25 
26 	mutex_lock(&controller->bus_lock);
27 	ret = controller->ops->xfer(controller, addr, &req);
28 	mutex_unlock(&controller->bus_lock);
29 
30 	return ret;
31 }
32 
33 static bool peci_addr_valid(u8 addr)
34 {
35 	return addr >= PECI_BASE_ADDR && addr < PECI_BASE_ADDR + PECI_DEVICE_NUM_MAX;
36 }
37 
38 static int peci_dev_exists(struct device *dev, void *data)
39 {
40 	struct peci_device *device = to_peci_device(dev);
41 	u8 *addr = data;
42 
43 	if (device->addr == *addr)
44 		return -EBUSY;
45 
46 	return 0;
47 }
48 
49 int peci_device_create(struct peci_controller *controller, u8 addr)
50 {
51 	struct peci_device *device;
52 	int ret;
53 
54 	if (!peci_addr_valid(addr))
55 		return -EINVAL;
56 
57 	/* Check if we have already detected this device before. */
58 	ret = device_for_each_child(&controller->dev, &addr, peci_dev_exists);
59 	if (ret)
60 		return 0;
61 
62 	ret = peci_detect(controller, addr);
63 	if (ret) {
64 		/*
65 		 * Device not present or host state doesn't allow successful
66 		 * detection at this time.
67 		 */
68 		if (ret == -EIO || ret == -ETIMEDOUT)
69 			return 0;
70 
71 		return ret;
72 	}
73 
74 	device = kzalloc(sizeof(*device), GFP_KERNEL);
75 	if (!device)
76 		return -ENOMEM;
77 
78 	device_initialize(&device->dev);
79 
80 	device->addr = addr;
81 	device->dev.parent = &controller->dev;
82 	device->dev.bus = &peci_bus_type;
83 	device->dev.type = &peci_device_type;
84 
85 	ret = dev_set_name(&device->dev, "%d-%02x", controller->id, device->addr);
86 	if (ret)
87 		goto err_put;
88 
89 	ret = device_add(&device->dev);
90 	if (ret)
91 		goto err_put;
92 
93 	return 0;
94 
95 err_put:
96 	put_device(&device->dev);
97 
98 	return ret;
99 }
100 
101 void peci_device_destroy(struct peci_device *device)
102 {
103 	mutex_lock(&peci_device_del_lock);
104 	if (!device->deleted) {
105 		device_unregister(&device->dev);
106 		device->deleted = true;
107 	}
108 	mutex_unlock(&peci_device_del_lock);
109 }
110 
111 static void peci_device_release(struct device *dev)
112 {
113 	struct peci_device *device = to_peci_device(dev);
114 
115 	kfree(device);
116 }
117 
118 struct device_type peci_device_type = {
119 	.release	= peci_device_release,
120 };
121