1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* Copyright (c) 2021 IBM Corp. */
3 
4 #include <linux/delay.h>
5 #include <linux/device.h>
6 #include <linux/errno.h>
7 #include <linux/fs.h>
8 #include <linux/list.h>
9 #include <linux/miscdevice.h>
10 #include <linux/module.h>
11 #include <linux/poll.h>
12 
13 #include "kcs_bmc_client.h"
14 
15 #define DEVICE_NAME "raw-kcs"
16 
17 struct kcs_bmc_raw {
18 	struct list_head entry;
19 
20 	struct kcs_bmc_client client;
21 
22 	wait_queue_head_t queue;
23 	u8 events;
24 	bool writable;
25 	bool readable;
26 	u8 idr;
27 
28 	struct miscdevice miscdev;
29 };
30 
31 static inline struct kcs_bmc_raw *client_to_kcs_bmc_raw(struct kcs_bmc_client *client)
32 {
33 	return container_of(client, struct kcs_bmc_raw, client);
34 }
35 
36 /* Call under priv->queue.lock */
37 static void kcs_bmc_raw_update_event_mask(struct kcs_bmc_raw *priv, u8 mask, u8 state)
38 {
39 	kcs_bmc_update_event_mask(priv->client.dev, mask, state);
40 	priv->events &= ~mask;
41 	priv->events |= state & mask;
42 }
43 
44 static irqreturn_t kcs_bmc_raw_event(struct kcs_bmc_client *client)
45 {
46 	struct kcs_bmc_raw *priv;
47 	struct device *dev;
48 	u8 status, handled;
49 
50 	priv = client_to_kcs_bmc_raw(client);
51 	dev = priv->miscdev.this_device;
52 
53 	spin_lock(&priv->queue.lock);
54 
55 	status = kcs_bmc_read_status(client->dev);
56 	handled = 0;
57 
58 	if ((priv->events & KCS_BMC_EVENT_TYPE_IBF) && (status & KCS_BMC_STR_IBF)) {
59 		if (priv->readable)
60 			dev_err(dev, "Unexpected IBF IRQ, dropping data");
61 
62 		dev_dbg(dev, "Disabling IDR events for back-pressure\n");
63 		kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_IBF, 0);
64 		priv->idr = kcs_bmc_read_data(client->dev);
65 		priv->readable = true;
66 
67 		dev_dbg(dev, "IDR read, waking waiters\n");
68 		wake_up_locked(&priv->queue);
69 
70 		handled |= KCS_BMC_EVENT_TYPE_IBF;
71 	}
72 
73 	if ((priv->events & KCS_BMC_EVENT_TYPE_OBE) && !(status & KCS_BMC_STR_OBF)) {
74 		kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_OBE, 0);
75 		priv->writable = true;
76 
77 		dev_dbg(dev, "ODR writable, waking waiters\n");
78 		wake_up_locked(&priv->queue);
79 
80 		handled |= KCS_BMC_EVENT_TYPE_OBE;
81 	}
82 
83 	spin_unlock(&priv->queue.lock);
84 
85 	return handled ? IRQ_HANDLED : IRQ_NONE;
86 }
87 
88 static const struct kcs_bmc_client_ops kcs_bmc_raw_client_ops = {
89 	.event = kcs_bmc_raw_event,
90 };
91 
92 static inline struct kcs_bmc_raw *file_to_kcs_bmc_raw(struct file *filp)
93 {
94 	return container_of(filp->private_data, struct kcs_bmc_raw, miscdev);
95 }
96 
97 static int kcs_bmc_raw_open(struct inode *inode, struct file *filp)
98 {
99 	struct kcs_bmc_raw *priv = file_to_kcs_bmc_raw(filp);
100 	int rc;
101 
102 	priv->events = KCS_BMC_EVENT_TYPE_IBF;
103 	rc = kcs_bmc_enable_device(priv->client.dev, &priv->client);
104 	if (rc)
105 		priv->events = 0;
106 
107 	return rc;
108 }
109 
110 static bool kcs_bmc_raw_prepare_obe(struct kcs_bmc_raw *priv)
111 {
112 	bool writable;
113 
114 	/* Enable the OBE event so we can catch the host clearing OBF */
115 	kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_OBE, KCS_BMC_EVENT_TYPE_OBE);
116 
117 	/* Now that we'll catch an OBE event, check if it's already occurred */
118 	writable = !(kcs_bmc_read_status(priv->client.dev) & KCS_BMC_STR_OBF);
119 
120 	/* If OBF is clear we've missed the OBE event, so disable it */
121 	if (writable)
122 		kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_OBE, 0);
123 
124 	return writable;
125 }
126 
127 static __poll_t kcs_bmc_raw_poll(struct file *filp, poll_table *wait)
128 {
129 	struct kcs_bmc_raw *priv;
130 	__poll_t events = 0;
131 
132 	priv = file_to_kcs_bmc_raw(filp);
133 
134 	poll_wait(filp, &priv->queue, wait);
135 
136 	spin_lock_irq(&priv->queue.lock);
137 	if (kcs_bmc_raw_prepare_obe(priv))
138 		events |= (EPOLLOUT | EPOLLWRNORM);
139 
140 	if (priv->readable || (kcs_bmc_read_status(priv->client.dev) & KCS_BMC_STR_IBF))
141 		events |= (EPOLLIN | EPOLLRDNORM);
142 	spin_unlock_irq(&priv->queue.lock);
143 
144 	return events;
145 }
146 
147 static ssize_t kcs_bmc_raw_read(struct file *filp, char __user *buf,
148 			     size_t count, loff_t *ppos)
149 {
150 	struct kcs_bmc_device *kcs_bmc;
151 	struct kcs_bmc_raw *priv;
152 	bool read_idr, read_str;
153 	struct device *dev;
154 	u8 idr, str;
155 	ssize_t rc;
156 
157 	priv = file_to_kcs_bmc_raw(filp);
158 	kcs_bmc = priv->client.dev;
159 	dev = priv->miscdev.this_device;
160 
161 	if (!count)
162 		return 0;
163 
164 	if (count > 2 || *ppos > 1)
165 		return -EINVAL;
166 
167 	if (*ppos + count > 2)
168 		return -EINVAL;
169 
170 	read_idr = (*ppos == 0);
171 	read_str = (*ppos == 1) || (count == 2);
172 
173 	spin_lock_irq(&priv->queue.lock);
174 	if (read_idr) {
175 		dev_dbg(dev, "Waiting for IBF\n");
176 		str = kcs_bmc_read_status(kcs_bmc);
177 		if ((filp->f_flags & O_NONBLOCK) && (str & KCS_BMC_STR_IBF)) {
178 			rc = -EWOULDBLOCK;
179 			goto out;
180 		}
181 
182 		rc = wait_event_interruptible_locked(priv->queue,
183 						     priv->readable || (str & KCS_BMC_STR_IBF));
184 		if (rc < 0)
185 			goto out;
186 
187 		if (signal_pending(current)) {
188 			dev_dbg(dev, "Interrupted waiting for IBF\n");
189 			rc = -EINTR;
190 			goto out;
191 		}
192 
193 		/*
194 		 * Re-enable events prior to possible read of IDR (which clears
195 		 * IBF) to ensure we receive interrupts for subsequent writes
196 		 * to IDR. Writes to IDR by the host should not occur while IBF
197 		 * is set.
198 		 */
199 		dev_dbg(dev, "Woken by IBF, enabling IRQ\n");
200 		kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_IBF,
201 					      KCS_BMC_EVENT_TYPE_IBF);
202 
203 		/* Read data out of IDR into internal storage if necessary */
204 		if (!priv->readable) {
205 			WARN(!(str & KCS_BMC_STR_IBF), "Unknown reason for wakeup!");
206 
207 			priv->idr = kcs_bmc_read_data(kcs_bmc);
208 		}
209 
210 		/* Copy data from internal storage to userspace */
211 		idr = priv->idr;
212 
213 		/* We're done consuming the internally stored value */
214 		priv->readable = false;
215 	}
216 
217 	if (read_str) {
218 		str = kcs_bmc_read_status(kcs_bmc);
219 		if (*ppos == 0 || priv->readable)
220 			/*
221 			 * If we got this far with `*ppos == 0` then we've read
222 			 * data out of IDR, so set IBF when reporting back to
223 			 * userspace so userspace knows the IDR value is valid.
224 			 */
225 			str |= KCS_BMC_STR_IBF;
226 
227 		dev_dbg(dev, "Read status 0x%x\n", str);
228 
229 	}
230 
231 	rc = count;
232 out:
233 	spin_unlock_irq(&priv->queue.lock);
234 
235 	if (rc < 0)
236 		return rc;
237 
238 	/* Now copy the data in to the userspace buffer */
239 
240 	if (read_idr)
241 		if (copy_to_user(buf++, &idr, sizeof(idr)))
242 			return -EFAULT;
243 
244 	if (read_str)
245 		if (copy_to_user(buf, &str, sizeof(str)))
246 			return -EFAULT;
247 
248 	return count;
249 }
250 
251 static ssize_t kcs_bmc_raw_write(struct file *filp, const char __user *buf,
252 			      size_t count, loff_t *ppos)
253 {
254 	struct kcs_bmc_device *kcs_bmc;
255 	bool write_odr, write_str;
256 	struct kcs_bmc_raw *priv;
257 	struct device *dev;
258 	ssize_t result;
259 	u8 data[2];
260 	u8 str;
261 
262 	priv = file_to_kcs_bmc_raw(filp);
263 	kcs_bmc = priv->client.dev;
264 	dev = priv->miscdev.this_device;
265 
266 	if (!count)
267 		return count;
268 
269 	if (count > 2)
270 		return -EINVAL;
271 
272 	if (*ppos >= 2)
273 		return -EINVAL;
274 
275 	if (*ppos + count > 2)
276 		return -EINVAL;
277 
278 	if (copy_from_user(data, buf, count))
279 		return -EFAULT;
280 
281 	write_odr = (*ppos == 0);
282 	write_str = (*ppos == 1) || (count == 2);
283 
284 	spin_lock_irq(&priv->queue.lock);
285 
286 	/* Always write status before data, we generate the SerIRQ by writing ODR */
287 	if (write_str) {
288 		/* The index of STR in the userspace buffer depends on whether ODR is written */
289 		str = data[*ppos == 0];
290 		if (!(str & KCS_BMC_STR_OBF))
291 			dev_warn(dev, "Clearing OBF with status write: 0x%x\n", str);
292 		dev_dbg(dev, "Writing status 0x%x\n", str);
293 		kcs_bmc_write_status(kcs_bmc, str);
294 	}
295 
296 	if (write_odr) {
297 		/* If we're writing ODR it's always the first byte in the buffer */
298 		u8 odr = data[0];
299 
300 		str = kcs_bmc_read_status(kcs_bmc);
301 		if (str & KCS_BMC_STR_OBF) {
302 			if (filp->f_flags & O_NONBLOCK) {
303 				result = -EWOULDBLOCK;
304 				goto out;
305 			}
306 
307 			priv->writable = kcs_bmc_raw_prepare_obe(priv);
308 
309 			/* Now either OBF is already clear, or we'll get an OBE event to wake us */
310 			dev_dbg(dev, "Waiting for OBF to clear\n");
311 			wait_event_interruptible_locked(priv->queue, priv->writable);
312 
313 			if (signal_pending(current)) {
314 				kcs_bmc_raw_update_event_mask(priv, KCS_BMC_EVENT_TYPE_OBE, 0);
315 				result = -EINTR;
316 				goto out;
317 			}
318 
319 			WARN_ON(kcs_bmc_read_status(kcs_bmc) & KCS_BMC_STR_OBF);
320 		}
321 
322 		dev_dbg(dev, "Writing 0x%x to ODR\n", odr);
323 		kcs_bmc_write_data(kcs_bmc, odr);
324 	}
325 
326 	result = count;
327 out:
328 	spin_unlock_irq(&priv->queue.lock);
329 
330 	return result;
331 }
332 
333 static int kcs_bmc_raw_release(struct inode *inode, struct file *filp)
334 {
335 	struct kcs_bmc_raw *priv = file_to_kcs_bmc_raw(filp);
336 
337 	kcs_bmc_disable_device(priv->client.dev, &priv->client);
338 	priv->events = 0;
339 
340 	return 0;
341 }
342 
343 static const struct file_operations kcs_bmc_raw_fops = {
344 	.owner          = THIS_MODULE,
345 	.open		= kcs_bmc_raw_open,
346 	.llseek		= no_seek_end_llseek,
347 	.read           = kcs_bmc_raw_read,
348 	.write          = kcs_bmc_raw_write,
349 	.poll		= kcs_bmc_raw_poll,
350 	.release	= kcs_bmc_raw_release,
351 };
352 
353 static DEFINE_SPINLOCK(kcs_bmc_raw_instances_lock);
354 static LIST_HEAD(kcs_bmc_raw_instances);
355 
356 static int kcs_bmc_raw_add_device(struct kcs_bmc_device *kcs_bmc)
357 {
358 	struct kcs_bmc_raw *priv;
359 	int rc;
360 
361 	priv = devm_kzalloc(kcs_bmc->dev, sizeof(*priv), GFP_KERNEL);
362 	if (!priv)
363 		return -ENOMEM;
364 
365 	priv->client.dev = kcs_bmc;
366 	priv->client.ops = &kcs_bmc_raw_client_ops;
367 
368 	init_waitqueue_head(&priv->queue);
369 	priv->writable = false;
370 	priv->readable = false;
371 
372 	priv->miscdev.minor = MISC_DYNAMIC_MINOR;
373 	priv->miscdev.name = devm_kasprintf(kcs_bmc->dev, GFP_KERNEL, "%s%u", DEVICE_NAME,
374 					   kcs_bmc->channel);
375 	if (!priv->miscdev.name)
376 		return -EINVAL;
377 
378 	priv->miscdev.fops = &kcs_bmc_raw_fops;
379 
380 	/* Disable interrupts until userspace opens the the chardev */
381 	kcs_bmc_raw_update_event_mask(priv, (KCS_BMC_EVENT_TYPE_IBF | KCS_BMC_EVENT_TYPE_OBE), 0);
382 
383 	rc = misc_register(&priv->miscdev);
384 	if (rc) {
385 		dev_err(kcs_bmc->dev, "Unable to register device\n");
386 		return rc;
387 	}
388 
389 	spin_lock_irq(&kcs_bmc_raw_instances_lock);
390 	list_add(&priv->entry, &kcs_bmc_raw_instances);
391 	spin_unlock_irq(&kcs_bmc_raw_instances_lock);
392 
393 	dev_info(kcs_bmc->dev, "Initialised raw client for channel %d", kcs_bmc->channel);
394 
395 	return 0;
396 }
397 
398 static int kcs_bmc_raw_remove_device(struct kcs_bmc_device *kcs_bmc)
399 {
400 	struct kcs_bmc_raw *priv = NULL, *pos;
401 
402 	spin_lock_irq(&kcs_bmc_raw_instances_lock);
403 	list_for_each_entry(pos, &kcs_bmc_raw_instances, entry) {
404 		if (pos->client.dev == kcs_bmc) {
405 			priv = pos;
406 			list_del(&pos->entry);
407 			break;
408 		}
409 	}
410 	spin_unlock_irq(&kcs_bmc_raw_instances_lock);
411 
412 	if (!priv)
413 		return -ENODEV;
414 
415 	misc_deregister(&priv->miscdev);
416 	kcs_bmc_disable_device(kcs_bmc, &priv->client);
417 	devm_kfree(priv->client.dev->dev, priv);
418 
419 	return 0;
420 }
421 
422 static const struct kcs_bmc_driver_ops kcs_bmc_raw_driver_ops = {
423 	.add_device = kcs_bmc_raw_add_device,
424 	.remove_device = kcs_bmc_raw_remove_device,
425 };
426 
427 static struct kcs_bmc_driver kcs_bmc_raw_driver = {
428 	.ops = &kcs_bmc_raw_driver_ops,
429 };
430 
431 static int kcs_bmc_raw_init(void)
432 {
433 	kcs_bmc_register_driver(&kcs_bmc_raw_driver);
434 
435 	return 0;
436 }
437 module_init(kcs_bmc_raw_init);
438 
439 static void kcs_bmc_raw_exit(void)
440 {
441 	kcs_bmc_unregister_driver(&kcs_bmc_raw_driver);
442 }
443 module_exit(kcs_bmc_raw_exit);
444 
445 MODULE_LICENSE("GPL v2");
446 MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");
447 MODULE_DESCRIPTION("Character device for raw access to a KCS device");
448