1 | // SPDX-License-Identifier: GPL-2.0 |
2 | |
3 | /* |
4 | * IPMB driver to receive a request and send a response |
5 | * |
6 | * Copyright (C) 2019 Mellanox Techologies, Ltd. |
7 | * |
8 | * This was inspired by Brendan Higgins' ipmi-bmc-bt-i2c driver. |
9 | */ |
10 | |
11 | #include <linux/acpi.h> |
12 | #include <linux/errno.h> |
13 | #include <linux/i2c.h> |
14 | #include <linux/miscdevice.h> |
15 | #include <linux/module.h> |
16 | #include <linux/mutex.h> |
17 | #include <linux/poll.h> |
18 | #include <linux/slab.h> |
19 | #include <linux/spinlock.h> |
20 | #include <linux/wait.h> |
21 | |
22 | #define MAX_MSG_LEN 240 |
23 | #define IPMB_REQUEST_LEN_MIN 7 |
24 | #define NETFN_RSP_BIT_MASK 0x4 |
25 | #define REQUEST_QUEUE_MAX_LEN 256 |
26 | |
27 | #define IPMB_MSG_LEN_IDX 0 |
28 | #define RQ_SA_8BIT_IDX 1 |
29 | #define NETFN_LUN_IDX 2 |
30 | |
31 | #define GET_7BIT_ADDR(addr_8bit) (addr_8bit >> 1) |
32 | #define GET_8BIT_ADDR(addr_7bit) ((addr_7bit << 1) & 0xff) |
33 | |
34 | #define IPMB_MSG_PAYLOAD_LEN_MAX (MAX_MSG_LEN - IPMB_REQUEST_LEN_MIN - 1) |
35 | |
36 | #define 2 |
37 | #define SMBUS_MSG_IDX_OFFSET (SMBUS_MSG_HEADER_LENGTH + 1) |
38 | |
39 | struct ipmb_msg { |
40 | u8 len; |
41 | u8 rs_sa; |
42 | u8 netfn_rs_lun; |
43 | u8 checksum1; |
44 | u8 rq_sa; |
45 | u8 rq_seq_rq_lun; |
46 | u8 cmd; |
47 | u8 payload[IPMB_MSG_PAYLOAD_LEN_MAX]; |
48 | /* checksum2 is included in payload */ |
49 | } __packed; |
50 | |
51 | struct ipmb_request_elem { |
52 | struct list_head list; |
53 | struct ipmb_msg request; |
54 | }; |
55 | |
56 | struct ipmb_dev { |
57 | struct i2c_client *client; |
58 | struct miscdevice miscdev; |
59 | struct ipmb_msg request; |
60 | struct list_head request_queue; |
61 | atomic_t request_queue_len; |
62 | size_t msg_idx; |
63 | spinlock_t lock; |
64 | wait_queue_head_t wait_queue; |
65 | struct mutex file_mutex; |
66 | bool is_i2c_protocol; |
67 | }; |
68 | |
69 | static inline struct ipmb_dev *to_ipmb_dev(struct file *file) |
70 | { |
71 | return container_of(file->private_data, struct ipmb_dev, miscdev); |
72 | } |
73 | |
74 | static ssize_t ipmb_read(struct file *file, char __user *buf, size_t count, |
75 | loff_t *ppos) |
76 | { |
77 | struct ipmb_dev *ipmb_dev = to_ipmb_dev(file); |
78 | struct ipmb_request_elem *queue_elem; |
79 | struct ipmb_msg msg; |
80 | ssize_t ret = 0; |
81 | |
82 | memset(&msg, 0, sizeof(msg)); |
83 | |
84 | spin_lock_irq(lock: &ipmb_dev->lock); |
85 | |
86 | while (list_empty(head: &ipmb_dev->request_queue)) { |
87 | spin_unlock_irq(lock: &ipmb_dev->lock); |
88 | |
89 | if (file->f_flags & O_NONBLOCK) |
90 | return -EAGAIN; |
91 | |
92 | ret = wait_event_interruptible(ipmb_dev->wait_queue, |
93 | !list_empty(&ipmb_dev->request_queue)); |
94 | if (ret) |
95 | return ret; |
96 | |
97 | spin_lock_irq(lock: &ipmb_dev->lock); |
98 | } |
99 | |
100 | queue_elem = list_first_entry(&ipmb_dev->request_queue, |
101 | struct ipmb_request_elem, list); |
102 | memcpy(&msg, &queue_elem->request, sizeof(msg)); |
103 | list_del(entry: &queue_elem->list); |
104 | kfree(objp: queue_elem); |
105 | atomic_dec(v: &ipmb_dev->request_queue_len); |
106 | |
107 | spin_unlock_irq(lock: &ipmb_dev->lock); |
108 | |
109 | count = min_t(size_t, count, msg.len + 1); |
110 | if (copy_to_user(to: buf, from: &msg, n: count)) |
111 | ret = -EFAULT; |
112 | |
113 | return ret < 0 ? ret : count; |
114 | } |
115 | |
116 | static int ipmb_i2c_write(struct i2c_client *client, u8 *msg, u8 addr) |
117 | { |
118 | struct i2c_msg i2c_msg; |
119 | |
120 | /* |
121 | * subtract 1 byte (rq_sa) from the length of the msg passed to |
122 | * raw i2c_transfer |
123 | */ |
124 | i2c_msg.len = msg[IPMB_MSG_LEN_IDX] - 1; |
125 | |
126 | /* Assign message to buffer except first 2 bytes (length and address) */ |
127 | i2c_msg.buf = msg + 2; |
128 | |
129 | i2c_msg.addr = addr; |
130 | i2c_msg.flags = client->flags & I2C_CLIENT_PEC; |
131 | |
132 | return i2c_transfer(adap: client->adapter, msgs: &i2c_msg, num: 1); |
133 | } |
134 | |
135 | static ssize_t ipmb_write(struct file *file, const char __user *buf, |
136 | size_t count, loff_t *ppos) |
137 | { |
138 | struct ipmb_dev *ipmb_dev = to_ipmb_dev(file); |
139 | u8 rq_sa, netf_rq_lun, msg_len; |
140 | struct i2c_client *temp_client; |
141 | u8 msg[MAX_MSG_LEN]; |
142 | ssize_t ret; |
143 | |
144 | if (count > sizeof(msg)) |
145 | return -EINVAL; |
146 | |
147 | if (copy_from_user(to: &msg, from: buf, n: count)) |
148 | return -EFAULT; |
149 | |
150 | if (count < msg[0]) |
151 | return -EINVAL; |
152 | |
153 | rq_sa = GET_7BIT_ADDR(msg[RQ_SA_8BIT_IDX]); |
154 | netf_rq_lun = msg[NETFN_LUN_IDX]; |
155 | |
156 | /* Check i2c block transfer vs smbus */ |
157 | if (ipmb_dev->is_i2c_protocol) { |
158 | ret = ipmb_i2c_write(client: ipmb_dev->client, msg, addr: rq_sa); |
159 | return (ret == 1) ? count : ret; |
160 | } |
161 | |
162 | /* |
163 | * subtract rq_sa and netf_rq_lun from the length of the msg. Fill the |
164 | * temporary client. Note that its use is an exception for IPMI. |
165 | */ |
166 | msg_len = msg[IPMB_MSG_LEN_IDX] - SMBUS_MSG_HEADER_LENGTH; |
167 | temp_client = kmemdup(p: ipmb_dev->client, size: sizeof(*temp_client), GFP_KERNEL); |
168 | if (!temp_client) |
169 | return -ENOMEM; |
170 | |
171 | temp_client->addr = rq_sa; |
172 | |
173 | ret = i2c_smbus_write_block_data(client: temp_client, command: netf_rq_lun, length: msg_len, |
174 | values: msg + SMBUS_MSG_IDX_OFFSET); |
175 | kfree(objp: temp_client); |
176 | |
177 | return ret < 0 ? ret : count; |
178 | } |
179 | |
180 | static __poll_t ipmb_poll(struct file *file, poll_table *wait) |
181 | { |
182 | struct ipmb_dev *ipmb_dev = to_ipmb_dev(file); |
183 | __poll_t mask = EPOLLOUT; |
184 | |
185 | mutex_lock(&ipmb_dev->file_mutex); |
186 | poll_wait(filp: file, wait_address: &ipmb_dev->wait_queue, p: wait); |
187 | |
188 | if (atomic_read(v: &ipmb_dev->request_queue_len)) |
189 | mask |= EPOLLIN; |
190 | mutex_unlock(lock: &ipmb_dev->file_mutex); |
191 | |
192 | return mask; |
193 | } |
194 | |
195 | static const struct file_operations ipmb_fops = { |
196 | .owner = THIS_MODULE, |
197 | .read = ipmb_read, |
198 | .write = ipmb_write, |
199 | .poll = ipmb_poll, |
200 | }; |
201 | |
202 | /* Called with ipmb_dev->lock held. */ |
203 | static void ipmb_handle_request(struct ipmb_dev *ipmb_dev) |
204 | { |
205 | struct ipmb_request_elem *queue_elem; |
206 | |
207 | if (atomic_read(v: &ipmb_dev->request_queue_len) >= |
208 | REQUEST_QUEUE_MAX_LEN) |
209 | return; |
210 | |
211 | queue_elem = kmalloc(size: sizeof(*queue_elem), GFP_ATOMIC); |
212 | if (!queue_elem) |
213 | return; |
214 | |
215 | memcpy(&queue_elem->request, &ipmb_dev->request, |
216 | sizeof(struct ipmb_msg)); |
217 | list_add(new: &queue_elem->list, head: &ipmb_dev->request_queue); |
218 | atomic_inc(v: &ipmb_dev->request_queue_len); |
219 | wake_up_all(&ipmb_dev->wait_queue); |
220 | } |
221 | |
222 | static u8 ipmb_verify_checksum1(struct ipmb_dev *ipmb_dev, u8 rs_sa) |
223 | { |
224 | /* The 8 lsb of the sum is 0 when the checksum is valid */ |
225 | return (rs_sa + ipmb_dev->request.netfn_rs_lun + |
226 | ipmb_dev->request.checksum1); |
227 | } |
228 | |
229 | /* |
230 | * Verify if message has proper ipmb header with minimum length |
231 | * and correct checksum byte. |
232 | */ |
233 | static bool is_ipmb_msg(struct ipmb_dev *ipmb_dev, u8 rs_sa) |
234 | { |
235 | if ((ipmb_dev->msg_idx >= IPMB_REQUEST_LEN_MIN) && |
236 | (!ipmb_verify_checksum1(ipmb_dev, rs_sa))) |
237 | return true; |
238 | |
239 | return false; |
240 | } |
241 | |
242 | /* |
243 | * The IPMB protocol only supports I2C Writes so there is no need |
244 | * to support I2C_SLAVE_READ* events. |
245 | * This i2c callback function only monitors IPMB request messages |
246 | * and adds them in a queue, so that they can be handled by |
247 | * receive_ipmb_request. |
248 | */ |
249 | static int ipmb_slave_cb(struct i2c_client *client, |
250 | enum i2c_slave_event event, u8 *val) |
251 | { |
252 | struct ipmb_dev *ipmb_dev = i2c_get_clientdata(client); |
253 | u8 *buf = (u8 *)&ipmb_dev->request; |
254 | unsigned long flags; |
255 | |
256 | spin_lock_irqsave(&ipmb_dev->lock, flags); |
257 | switch (event) { |
258 | case I2C_SLAVE_WRITE_REQUESTED: |
259 | memset(&ipmb_dev->request, 0, sizeof(ipmb_dev->request)); |
260 | ipmb_dev->msg_idx = 0; |
261 | |
262 | /* |
263 | * At index 0, ipmb_msg stores the length of msg, |
264 | * skip it for now. |
265 | * The len will be populated once the whole |
266 | * buf is populated. |
267 | * |
268 | * The I2C bus driver's responsibility is to pass the |
269 | * data bytes to the backend driver; it does not |
270 | * forward the i2c slave address. |
271 | * Since the first byte in the IPMB message is the |
272 | * address of the responder, it is the responsibility |
273 | * of the IPMB driver to format the message properly. |
274 | * So this driver prepends the address of the responder |
275 | * to the received i2c data before the request message |
276 | * is handled in userland. |
277 | */ |
278 | buf[++ipmb_dev->msg_idx] = GET_8BIT_ADDR(client->addr); |
279 | break; |
280 | |
281 | case I2C_SLAVE_WRITE_RECEIVED: |
282 | if (ipmb_dev->msg_idx >= sizeof(struct ipmb_msg) - 1) |
283 | break; |
284 | |
285 | buf[++ipmb_dev->msg_idx] = *val; |
286 | break; |
287 | |
288 | case I2C_SLAVE_STOP: |
289 | ipmb_dev->request.len = ipmb_dev->msg_idx; |
290 | if (is_ipmb_msg(ipmb_dev, GET_8BIT_ADDR(client->addr))) |
291 | ipmb_handle_request(ipmb_dev); |
292 | break; |
293 | |
294 | default: |
295 | break; |
296 | } |
297 | spin_unlock_irqrestore(lock: &ipmb_dev->lock, flags); |
298 | |
299 | return 0; |
300 | } |
301 | |
302 | static int ipmb_probe(struct i2c_client *client) |
303 | { |
304 | struct ipmb_dev *ipmb_dev; |
305 | int ret; |
306 | |
307 | ipmb_dev = devm_kzalloc(dev: &client->dev, size: sizeof(*ipmb_dev), |
308 | GFP_KERNEL); |
309 | if (!ipmb_dev) |
310 | return -ENOMEM; |
311 | |
312 | spin_lock_init(&ipmb_dev->lock); |
313 | init_waitqueue_head(&ipmb_dev->wait_queue); |
314 | atomic_set(v: &ipmb_dev->request_queue_len, i: 0); |
315 | INIT_LIST_HEAD(list: &ipmb_dev->request_queue); |
316 | |
317 | mutex_init(&ipmb_dev->file_mutex); |
318 | |
319 | ipmb_dev->miscdev.minor = MISC_DYNAMIC_MINOR; |
320 | |
321 | ipmb_dev->miscdev.name = devm_kasprintf(dev: &client->dev, GFP_KERNEL, |
322 | fmt: "%s%d" , "ipmb-" , |
323 | client->adapter->nr); |
324 | ipmb_dev->miscdev.fops = &ipmb_fops; |
325 | ipmb_dev->miscdev.parent = &client->dev; |
326 | ret = misc_register(misc: &ipmb_dev->miscdev); |
327 | if (ret) |
328 | return ret; |
329 | |
330 | ipmb_dev->is_i2c_protocol |
331 | = device_property_read_bool(dev: &client->dev, propname: "i2c-protocol" ); |
332 | |
333 | ipmb_dev->client = client; |
334 | i2c_set_clientdata(client, data: ipmb_dev); |
335 | ret = i2c_slave_register(client, slave_cb: ipmb_slave_cb); |
336 | if (ret) { |
337 | misc_deregister(misc: &ipmb_dev->miscdev); |
338 | return ret; |
339 | } |
340 | |
341 | return 0; |
342 | } |
343 | |
344 | static void ipmb_remove(struct i2c_client *client) |
345 | { |
346 | struct ipmb_dev *ipmb_dev = i2c_get_clientdata(client); |
347 | |
348 | i2c_slave_unregister(client); |
349 | misc_deregister(misc: &ipmb_dev->miscdev); |
350 | } |
351 | |
352 | static const struct i2c_device_id ipmb_id[] = { |
353 | { "ipmb-dev" , 0 }, |
354 | {}, |
355 | }; |
356 | MODULE_DEVICE_TABLE(i2c, ipmb_id); |
357 | |
358 | static const struct acpi_device_id acpi_ipmb_id[] = { |
359 | { "IPMB0001" , 0 }, |
360 | {}, |
361 | }; |
362 | MODULE_DEVICE_TABLE(acpi, acpi_ipmb_id); |
363 | |
364 | static struct i2c_driver ipmb_driver = { |
365 | .driver = { |
366 | .name = "ipmb-dev" , |
367 | .acpi_match_table = ACPI_PTR(acpi_ipmb_id), |
368 | }, |
369 | .probe = ipmb_probe, |
370 | .remove = ipmb_remove, |
371 | .id_table = ipmb_id, |
372 | }; |
373 | module_i2c_driver(ipmb_driver); |
374 | |
375 | MODULE_AUTHOR("Mellanox Technologies" ); |
376 | MODULE_DESCRIPTION("IPMB driver" ); |
377 | MODULE_LICENSE("GPL v2" ); |
378 | |