xref: /openbmc/linux/drivers/net/mctp/mctp-serial.c (revision 892bc209)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Management Component Transport Protocol (MCTP) - serial transport
4  * binding. This driver is an implementation of the DMTF specificiation
5  * "DSP0253 - Management Component Transport Protocol (MCTP) Serial Transport
6  * Binding", available at:
7  *
8  *  https://www.dmtf.org/sites/default/files/standards/documents/DSP0253_1.0.0.pdf
9  *
10  * This driver provides DSP0253-type MCTP-over-serial transport using a Linux
11  * tty device, by setting the N_MCTP line discipline on the tty.
12  *
13  * Copyright (c) 2021 Code Construct
14  */
15 
16 #include <linux/idr.h>
17 #include <linux/if_arp.h>
18 #include <linux/module.h>
19 #include <linux/skbuff.h>
20 #include <linux/tty.h>
21 #include <linux/workqueue.h>
22 #include <linux/crc-ccitt.h>
23 
24 #include <linux/mctp.h>
25 #include <net/mctp.h>
26 #include <net/pkt_sched.h>
27 
28 #define MCTP_SERIAL_MTU		68 /* base mtu (64) + mctp header */
29 #define MCTP_SERIAL_FRAME_MTU	(MCTP_SERIAL_MTU + 6) /* + serial framing */
30 
31 #define MCTP_SERIAL_VERSION	0x1 /* DSP0253 defines a single version: 1 */
32 
33 #define BUFSIZE			MCTP_SERIAL_FRAME_MTU
34 
35 #define BYTE_FRAME		0x7e
36 #define BYTE_ESC		0x7d
37 
38 #define FCS_INIT		0xffff
39 
40 static DEFINE_IDA(mctp_serial_ida);
41 
42 enum mctp_serial_state {
43 	STATE_IDLE,
44 	STATE_START,
45 	STATE_HEADER,
46 	STATE_DATA,
47 	STATE_ESCAPE,
48 	STATE_TRAILER,
49 	STATE_DONE,
50 	STATE_ERR,
51 };
52 
53 struct mctp_serial {
54 	struct net_device	*netdev;
55 	struct tty_struct	*tty;
56 
57 	int			idx;
58 
59 	/* protects our rx & tx state machines; held during both paths */
60 	spinlock_t		lock;
61 
62 	struct work_struct	tx_work;
63 	enum mctp_serial_state	txstate, rxstate;
64 	u16			txfcs, rxfcs, rxfcs_rcvd;
65 	unsigned int		txlen, rxlen;
66 	unsigned int		txpos, rxpos;
67 	unsigned char		txbuf[BUFSIZE],
68 				rxbuf[BUFSIZE];
69 };
70 
needs_escape(unsigned char c)71 static bool needs_escape(unsigned char c)
72 {
73 	return c == BYTE_ESC || c == BYTE_FRAME;
74 }
75 
next_chunk_len(struct mctp_serial * dev)76 static int next_chunk_len(struct mctp_serial *dev)
77 {
78 	int i;
79 
80 	/* either we have no bytes to send ... */
81 	if (dev->txpos == dev->txlen)
82 		return 0;
83 
84 	/* ... or the next byte to send is an escaped byte; requiring a
85 	 * single-byte chunk...
86 	 */
87 	if (needs_escape(dev->txbuf[dev->txpos]))
88 		return 1;
89 
90 	/* ... or we have one or more bytes up to the next escape - this chunk
91 	 * will be those non-escaped bytes, and does not include the escaped
92 	 * byte.
93 	 */
94 	for (i = 1; i + dev->txpos + 1 < dev->txlen; i++) {
95 		if (needs_escape(dev->txbuf[dev->txpos + i + 1]))
96 			break;
97 	}
98 
99 	return i;
100 }
101 
write_chunk(struct mctp_serial * dev,unsigned char * buf,int len)102 static int write_chunk(struct mctp_serial *dev, unsigned char *buf, int len)
103 {
104 	return dev->tty->ops->write(dev->tty, buf, len);
105 }
106 
mctp_serial_tx_work(struct work_struct * work)107 static void mctp_serial_tx_work(struct work_struct *work)
108 {
109 	struct mctp_serial *dev = container_of(work, struct mctp_serial,
110 					       tx_work);
111 	unsigned char c, buf[3];
112 	unsigned long flags;
113 	int len, txlen;
114 
115 	spin_lock_irqsave(&dev->lock, flags);
116 
117 	/* txstate represents the next thing to send */
118 	switch (dev->txstate) {
119 	case STATE_START:
120 		dev->txpos = 0;
121 		fallthrough;
122 	case STATE_HEADER:
123 		buf[0] = BYTE_FRAME;
124 		buf[1] = MCTP_SERIAL_VERSION;
125 		buf[2] = dev->txlen;
126 
127 		if (!dev->txpos)
128 			dev->txfcs = crc_ccitt(FCS_INIT, buf + 1, 2);
129 
130 		txlen = write_chunk(dev, buf + dev->txpos, 3 - dev->txpos);
131 		if (txlen <= 0) {
132 			dev->txstate = STATE_ERR;
133 		} else {
134 			dev->txpos += txlen;
135 			if (dev->txpos == 3) {
136 				dev->txstate = STATE_DATA;
137 				dev->txpos = 0;
138 			}
139 		}
140 		break;
141 
142 	case STATE_ESCAPE:
143 		buf[0] = dev->txbuf[dev->txpos] & ~0x20;
144 		txlen = write_chunk(dev, buf, 1);
145 		if (txlen <= 0) {
146 			dev->txstate = STATE_ERR;
147 		} else {
148 			dev->txpos += txlen;
149 			if (dev->txpos == dev->txlen) {
150 				dev->txstate = STATE_TRAILER;
151 				dev->txpos = 0;
152 			}
153 		}
154 
155 		break;
156 
157 	case STATE_DATA:
158 		len = next_chunk_len(dev);
159 		if (len) {
160 			c = dev->txbuf[dev->txpos];
161 			if (len == 1 && needs_escape(c)) {
162 				buf[0] = BYTE_ESC;
163 				buf[1] = c & ~0x20;
164 				dev->txfcs = crc_ccitt_byte(dev->txfcs, c);
165 				txlen = write_chunk(dev, buf, 2);
166 				if (txlen == 2)
167 					dev->txpos++;
168 				else if (txlen == 1)
169 					dev->txstate = STATE_ESCAPE;
170 				else
171 					dev->txstate = STATE_ERR;
172 			} else {
173 				txlen = write_chunk(dev,
174 						    dev->txbuf + dev->txpos,
175 						    len);
176 				if (txlen <= 0) {
177 					dev->txstate = STATE_ERR;
178 				} else {
179 					dev->txfcs = crc_ccitt(dev->txfcs,
180 							       dev->txbuf +
181 							       dev->txpos,
182 							       txlen);
183 					dev->txpos += txlen;
184 				}
185 			}
186 			if (dev->txstate == STATE_DATA &&
187 			    dev->txpos == dev->txlen) {
188 				dev->txstate = STATE_TRAILER;
189 				dev->txpos = 0;
190 			}
191 			break;
192 		}
193 		dev->txstate = STATE_TRAILER;
194 		dev->txpos = 0;
195 		fallthrough;
196 
197 	case STATE_TRAILER:
198 		buf[0] = dev->txfcs >> 8;
199 		buf[1] = dev->txfcs & 0xff;
200 		buf[2] = BYTE_FRAME;
201 		txlen = write_chunk(dev, buf + dev->txpos, 3 - dev->txpos);
202 		if (txlen <= 0) {
203 			dev->txstate = STATE_ERR;
204 		} else {
205 			dev->txpos += txlen;
206 			if (dev->txpos == 3) {
207 				dev->txstate = STATE_DONE;
208 				dev->txpos = 0;
209 			}
210 		}
211 		break;
212 	default:
213 		netdev_err_once(dev->netdev, "invalid tx state %d\n",
214 				dev->txstate);
215 	}
216 
217 	if (dev->txstate == STATE_DONE) {
218 		dev->netdev->stats.tx_packets++;
219 		dev->netdev->stats.tx_bytes += dev->txlen;
220 		dev->txlen = 0;
221 		dev->txpos = 0;
222 		clear_bit(TTY_DO_WRITE_WAKEUP, &dev->tty->flags);
223 		dev->txstate = STATE_IDLE;
224 		spin_unlock_irqrestore(&dev->lock, flags);
225 
226 		netif_wake_queue(dev->netdev);
227 	} else {
228 		spin_unlock_irqrestore(&dev->lock, flags);
229 	}
230 }
231 
mctp_serial_tx(struct sk_buff * skb,struct net_device * ndev)232 static netdev_tx_t mctp_serial_tx(struct sk_buff *skb, struct net_device *ndev)
233 {
234 	struct mctp_serial *dev = netdev_priv(ndev);
235 	unsigned long flags;
236 
237 	WARN_ON(dev->txstate != STATE_IDLE);
238 
239 	if (skb->len > MCTP_SERIAL_MTU) {
240 		dev->netdev->stats.tx_dropped++;
241 		goto out;
242 	}
243 
244 	spin_lock_irqsave(&dev->lock, flags);
245 	netif_stop_queue(dev->netdev);
246 	skb_copy_bits(skb, 0, dev->txbuf, skb->len);
247 	dev->txpos = 0;
248 	dev->txlen = skb->len;
249 	dev->txstate = STATE_START;
250 	spin_unlock_irqrestore(&dev->lock, flags);
251 
252 	set_bit(TTY_DO_WRITE_WAKEUP, &dev->tty->flags);
253 	schedule_work(&dev->tx_work);
254 
255 out:
256 	kfree_skb(skb);
257 	return NETDEV_TX_OK;
258 }
259 
mctp_serial_tty_write_wakeup(struct tty_struct * tty)260 static void mctp_serial_tty_write_wakeup(struct tty_struct *tty)
261 {
262 	struct mctp_serial *dev = tty->disc_data;
263 
264 	schedule_work(&dev->tx_work);
265 }
266 
mctp_serial_rx(struct mctp_serial * dev)267 static void mctp_serial_rx(struct mctp_serial *dev)
268 {
269 	struct mctp_skb_cb *cb;
270 	struct sk_buff *skb;
271 
272 	if (dev->rxfcs != dev->rxfcs_rcvd) {
273 		dev->netdev->stats.rx_dropped++;
274 		dev->netdev->stats.rx_crc_errors++;
275 		return;
276 	}
277 
278 	skb = netdev_alloc_skb(dev->netdev, dev->rxlen);
279 	if (!skb) {
280 		dev->netdev->stats.rx_dropped++;
281 		return;
282 	}
283 
284 	skb->protocol = htons(ETH_P_MCTP);
285 	skb_put_data(skb, dev->rxbuf, dev->rxlen);
286 	skb_reset_network_header(skb);
287 
288 	cb = __mctp_cb(skb);
289 	cb->halen = 0;
290 
291 	netif_rx(skb);
292 	dev->netdev->stats.rx_packets++;
293 	dev->netdev->stats.rx_bytes += dev->rxlen;
294 }
295 
mctp_serial_push_header(struct mctp_serial * dev,unsigned char c)296 static void mctp_serial_push_header(struct mctp_serial *dev, unsigned char c)
297 {
298 	switch (dev->rxpos) {
299 	case 0:
300 		if (c == BYTE_FRAME)
301 			dev->rxpos++;
302 		else
303 			dev->rxstate = STATE_ERR;
304 		break;
305 	case 1:
306 		if (c == MCTP_SERIAL_VERSION) {
307 			dev->rxpos++;
308 			dev->rxfcs = crc_ccitt_byte(FCS_INIT, c);
309 		} else {
310 			dev->rxstate = STATE_ERR;
311 		}
312 		break;
313 	case 2:
314 		if (c > MCTP_SERIAL_FRAME_MTU) {
315 			dev->rxstate = STATE_ERR;
316 		} else {
317 			dev->rxlen = c;
318 			dev->rxpos = 0;
319 			dev->rxstate = STATE_DATA;
320 			dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
321 		}
322 		break;
323 	}
324 }
325 
mctp_serial_push_trailer(struct mctp_serial * dev,unsigned char c)326 static void mctp_serial_push_trailer(struct mctp_serial *dev, unsigned char c)
327 {
328 	switch (dev->rxpos) {
329 	case 0:
330 		dev->rxfcs_rcvd = c << 8;
331 		dev->rxpos++;
332 		break;
333 	case 1:
334 		dev->rxfcs_rcvd |= c;
335 		dev->rxpos++;
336 		break;
337 	case 2:
338 		if (c != BYTE_FRAME) {
339 			dev->rxstate = STATE_ERR;
340 		} else {
341 			mctp_serial_rx(dev);
342 			dev->rxlen = 0;
343 			dev->rxpos = 0;
344 			dev->rxstate = STATE_IDLE;
345 		}
346 		break;
347 	}
348 }
349 
mctp_serial_push(struct mctp_serial * dev,unsigned char c)350 static void mctp_serial_push(struct mctp_serial *dev, unsigned char c)
351 {
352 	switch (dev->rxstate) {
353 	case STATE_IDLE:
354 		dev->rxstate = STATE_HEADER;
355 		fallthrough;
356 	case STATE_HEADER:
357 		mctp_serial_push_header(dev, c);
358 		break;
359 
360 	case STATE_ESCAPE:
361 		c |= 0x20;
362 		fallthrough;
363 	case STATE_DATA:
364 		if (dev->rxstate != STATE_ESCAPE && c == BYTE_ESC) {
365 			dev->rxstate = STATE_ESCAPE;
366 		} else {
367 			dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
368 			dev->rxbuf[dev->rxpos] = c;
369 			dev->rxpos++;
370 			dev->rxstate = STATE_DATA;
371 			if (dev->rxpos == dev->rxlen) {
372 				dev->rxpos = 0;
373 				dev->rxstate = STATE_TRAILER;
374 			}
375 		}
376 		break;
377 
378 	case STATE_TRAILER:
379 		mctp_serial_push_trailer(dev, c);
380 		break;
381 
382 	case STATE_ERR:
383 		if (c == BYTE_FRAME)
384 			dev->rxstate = STATE_IDLE;
385 		break;
386 
387 	default:
388 		netdev_err_once(dev->netdev, "invalid rx state %d\n",
389 				dev->rxstate);
390 	}
391 }
392 
mctp_serial_tty_receive_buf(struct tty_struct * tty,const u8 * c,const u8 * f,size_t len)393 static void mctp_serial_tty_receive_buf(struct tty_struct *tty, const u8 *c,
394 					const u8 *f, size_t len)
395 {
396 	struct mctp_serial *dev = tty->disc_data;
397 	int i;
398 
399 	if (!netif_running(dev->netdev))
400 		return;
401 
402 	/* we don't (currently) use the flag bytes, just data. */
403 	for (i = 0; i < len; i++)
404 		mctp_serial_push(dev, c[i]);
405 }
406 
mctp_serial_uninit(struct net_device * ndev)407 static void mctp_serial_uninit(struct net_device *ndev)
408 {
409 	struct mctp_serial *dev = netdev_priv(ndev);
410 
411 	cancel_work_sync(&dev->tx_work);
412 }
413 
414 static const struct net_device_ops mctp_serial_netdev_ops = {
415 	.ndo_start_xmit = mctp_serial_tx,
416 	.ndo_uninit = mctp_serial_uninit,
417 };
418 
mctp_serial_setup(struct net_device * ndev)419 static void mctp_serial_setup(struct net_device *ndev)
420 {
421 	ndev->type = ARPHRD_MCTP;
422 
423 	/* we limit at the fixed MTU, which is also the MCTP-standard
424 	 * baseline MTU, so is also our minimum
425 	 */
426 	ndev->mtu = MCTP_SERIAL_MTU;
427 	ndev->max_mtu = MCTP_SERIAL_MTU;
428 	ndev->min_mtu = MCTP_SERIAL_MTU;
429 
430 	ndev->hard_header_len = 0;
431 	ndev->addr_len = 0;
432 	ndev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
433 	ndev->flags = IFF_NOARP;
434 	ndev->netdev_ops = &mctp_serial_netdev_ops;
435 	ndev->needs_free_netdev = true;
436 }
437 
mctp_serial_open(struct tty_struct * tty)438 static int mctp_serial_open(struct tty_struct *tty)
439 {
440 	struct mctp_serial *dev;
441 	struct net_device *ndev;
442 	char name[32];
443 	int idx, rc;
444 
445 	if (!capable(CAP_NET_ADMIN))
446 		return -EPERM;
447 
448 	if (!tty->ops->write)
449 		return -EOPNOTSUPP;
450 
451 	idx = ida_alloc(&mctp_serial_ida, GFP_KERNEL);
452 	if (idx < 0)
453 		return idx;
454 
455 	snprintf(name, sizeof(name), "mctpserial%d", idx);
456 	ndev = alloc_netdev(sizeof(*dev), name, NET_NAME_ENUM,
457 			    mctp_serial_setup);
458 	if (!ndev) {
459 		rc = -ENOMEM;
460 		goto free_ida;
461 	}
462 
463 	dev = netdev_priv(ndev);
464 	dev->idx = idx;
465 	dev->tty = tty;
466 	dev->netdev = ndev;
467 	dev->txstate = STATE_IDLE;
468 	dev->rxstate = STATE_IDLE;
469 	spin_lock_init(&dev->lock);
470 	INIT_WORK(&dev->tx_work, mctp_serial_tx_work);
471 
472 	rc = register_netdev(ndev);
473 	if (rc)
474 		goto free_netdev;
475 
476 	tty->receive_room = 64 * 1024;
477 	tty->disc_data = dev;
478 
479 	return 0;
480 
481 free_netdev:
482 	free_netdev(ndev);
483 
484 free_ida:
485 	ida_free(&mctp_serial_ida, idx);
486 	return rc;
487 }
488 
mctp_serial_close(struct tty_struct * tty)489 static void mctp_serial_close(struct tty_struct *tty)
490 {
491 	struct mctp_serial *dev = tty->disc_data;
492 	int idx = dev->idx;
493 
494 	unregister_netdev(dev->netdev);
495 	ida_free(&mctp_serial_ida, idx);
496 }
497 
498 static struct tty_ldisc_ops mctp_ldisc = {
499 	.owner		= THIS_MODULE,
500 	.num		= N_MCTP,
501 	.name		= "mctp",
502 	.open		= mctp_serial_open,
503 	.close		= mctp_serial_close,
504 	.receive_buf	= mctp_serial_tty_receive_buf,
505 	.write_wakeup	= mctp_serial_tty_write_wakeup,
506 };
507 
mctp_serial_init(void)508 static int __init mctp_serial_init(void)
509 {
510 	return tty_register_ldisc(&mctp_ldisc);
511 }
512 
mctp_serial_exit(void)513 static void __exit mctp_serial_exit(void)
514 {
515 	tty_unregister_ldisc(&mctp_ldisc);
516 }
517 
518 module_init(mctp_serial_init);
519 module_exit(mctp_serial_exit);
520 
521 MODULE_LICENSE("GPL v2");
522 MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>");
523 MODULE_DESCRIPTION("MCTP Serial transport");
524