Linux Audio

Check our new training course

Loading...
v6.8
  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
 40static DEFINE_IDA(mctp_serial_ida);
 41
 42enum 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
 53struct 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
 71static bool needs_escape(unsigned char c)
 72{
 73	return c == BYTE_ESC || c == BYTE_FRAME;
 74}
 75
 76static 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
102static 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
107static 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
232static 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
255out:
256	kfree_skb(skb);
257	return NETDEV_TX_OK;
258}
259
260static 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
267static 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
296static 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
326static 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
350static 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
393static 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
407static 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
414static const struct net_device_ops mctp_serial_netdev_ops = {
415	.ndo_start_xmit = mctp_serial_tx,
416	.ndo_uninit = mctp_serial_uninit,
417};
418
419static 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
438static 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
481free_netdev:
482	free_netdev(ndev);
483
484free_ida:
485	ida_free(&mctp_serial_ida, idx);
486	return rc;
487}
488
489static 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
498static 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
508static int __init mctp_serial_init(void)
509{
510	return tty_register_ldisc(&mctp_ldisc);
511}
512
513static void __exit mctp_serial_exit(void)
514{
515	tty_unregister_ldisc(&mctp_ldisc);
516}
517
518module_init(mctp_serial_init);
519module_exit(mctp_serial_exit);
520
521MODULE_LICENSE("GPL v2");
522MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>");
523MODULE_DESCRIPTION("MCTP Serial transport");
v6.13.7
  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/mctpdevice.h>
 27#include <net/pkt_sched.h>
 28
 29#define MCTP_SERIAL_MTU		68 /* base mtu (64) + mctp header */
 30#define MCTP_SERIAL_FRAME_MTU	(MCTP_SERIAL_MTU + 6) /* + serial framing */
 31
 32#define MCTP_SERIAL_VERSION	0x1 /* DSP0253 defines a single version: 1 */
 33
 34#define BUFSIZE			MCTP_SERIAL_FRAME_MTU
 35
 36#define BYTE_FRAME		0x7e
 37#define BYTE_ESC		0x7d
 38
 39#define FCS_INIT		0xffff
 40
 41static DEFINE_IDA(mctp_serial_ida);
 42
 43enum mctp_serial_state {
 44	STATE_IDLE,
 45	STATE_START,
 46	STATE_HEADER,
 47	STATE_DATA,
 48	STATE_ESCAPE,
 49	STATE_TRAILER,
 50	STATE_DONE,
 51	STATE_ERR,
 52};
 53
 54struct mctp_serial {
 55	struct net_device	*netdev;
 56	struct tty_struct	*tty;
 57
 58	int			idx;
 59
 60	/* protects our rx & tx state machines; held during both paths */
 61	spinlock_t		lock;
 62
 63	struct work_struct	tx_work;
 64	enum mctp_serial_state	txstate, rxstate;
 65	u16			txfcs, rxfcs, rxfcs_rcvd;
 66	unsigned int		txlen, rxlen;
 67	unsigned int		txpos, rxpos;
 68	u8			txbuf[BUFSIZE],
 69				rxbuf[BUFSIZE];
 70};
 71
 72static bool needs_escape(u8 c)
 73{
 74	return c == BYTE_ESC || c == BYTE_FRAME;
 75}
 76
 77static unsigned int next_chunk_len(struct mctp_serial *dev)
 78{
 79	unsigned int i;
 80
 81	/* either we have no bytes to send ... */
 82	if (dev->txpos == dev->txlen)
 83		return 0;
 84
 85	/* ... or the next byte to send is an escaped byte; requiring a
 86	 * single-byte chunk...
 87	 */
 88	if (needs_escape(dev->txbuf[dev->txpos]))
 89		return 1;
 90
 91	/* ... or we have one or more bytes up to the next escape - this chunk
 92	 * will be those non-escaped bytes, and does not include the escaped
 93	 * byte.
 94	 */
 95	for (i = 1; i + dev->txpos < dev->txlen; i++) {
 96		if (needs_escape(dev->txbuf[dev->txpos + i]))
 97			break;
 98	}
 99
100	return i;
101}
102
103static ssize_t write_chunk(struct mctp_serial *dev, u8 *buf, size_t len)
104{
105	return dev->tty->ops->write(dev->tty, buf, len);
106}
107
108static void mctp_serial_tx_work(struct work_struct *work)
109{
110	struct mctp_serial *dev = container_of(work, struct mctp_serial,
111					       tx_work);
 
112	unsigned long flags;
113	ssize_t txlen;
114	unsigned int len;
115	u8 c, buf[3];
116
117	spin_lock_irqsave(&dev->lock, flags);
118
119	/* txstate represents the next thing to send */
120	switch (dev->txstate) {
121	case STATE_START:
122		dev->txpos = 0;
123		fallthrough;
124	case STATE_HEADER:
125		buf[0] = BYTE_FRAME;
126		buf[1] = MCTP_SERIAL_VERSION;
127		buf[2] = dev->txlen;
128
129		if (!dev->txpos)
130			dev->txfcs = crc_ccitt(FCS_INIT, buf + 1, 2);
131
132		txlen = write_chunk(dev, buf + dev->txpos, 3 - dev->txpos);
133		if (txlen <= 0) {
134			dev->txstate = STATE_ERR;
135		} else {
136			dev->txpos += txlen;
137			if (dev->txpos == 3) {
138				dev->txstate = STATE_DATA;
139				dev->txpos = 0;
140			}
141		}
142		break;
143
144	case STATE_ESCAPE:
145		buf[0] = dev->txbuf[dev->txpos] & ~0x20;
146		txlen = write_chunk(dev, buf, 1);
147		if (txlen <= 0) {
148			dev->txstate = STATE_ERR;
149		} else {
150			dev->txpos += txlen;
151			if (dev->txpos == dev->txlen) {
152				dev->txstate = STATE_TRAILER;
153				dev->txpos = 0;
154			}
155		}
156
157		break;
158
159	case STATE_DATA:
160		len = next_chunk_len(dev);
161		if (len) {
162			c = dev->txbuf[dev->txpos];
163			if (len == 1 && needs_escape(c)) {
164				buf[0] = BYTE_ESC;
165				buf[1] = c & ~0x20;
166				dev->txfcs = crc_ccitt_byte(dev->txfcs, c);
167				txlen = write_chunk(dev, buf, 2);
168				if (txlen == 2)
169					dev->txpos++;
170				else if (txlen == 1)
171					dev->txstate = STATE_ESCAPE;
172				else
173					dev->txstate = STATE_ERR;
174			} else {
175				txlen = write_chunk(dev,
176						    dev->txbuf + dev->txpos,
177						    len);
178				if (txlen <= 0) {
179					dev->txstate = STATE_ERR;
180				} else {
181					dev->txfcs = crc_ccitt(dev->txfcs,
182							       dev->txbuf +
183							       dev->txpos,
184							       txlen);
185					dev->txpos += txlen;
186				}
187			}
188			if (dev->txstate == STATE_DATA &&
189			    dev->txpos == dev->txlen) {
190				dev->txstate = STATE_TRAILER;
191				dev->txpos = 0;
192			}
193			break;
194		}
195		dev->txstate = STATE_TRAILER;
196		dev->txpos = 0;
197		fallthrough;
198
199	case STATE_TRAILER:
200		buf[0] = dev->txfcs >> 8;
201		buf[1] = dev->txfcs & 0xff;
202		buf[2] = BYTE_FRAME;
203		txlen = write_chunk(dev, buf + dev->txpos, 3 - dev->txpos);
204		if (txlen <= 0) {
205			dev->txstate = STATE_ERR;
206		} else {
207			dev->txpos += txlen;
208			if (dev->txpos == 3) {
209				dev->txstate = STATE_DONE;
210				dev->txpos = 0;
211			}
212		}
213		break;
214	default:
215		netdev_err_once(dev->netdev, "invalid tx state %d\n",
216				dev->txstate);
217	}
218
219	if (dev->txstate == STATE_DONE) {
220		dev->netdev->stats.tx_packets++;
221		dev->netdev->stats.tx_bytes += dev->txlen;
222		dev->txlen = 0;
223		dev->txpos = 0;
224		clear_bit(TTY_DO_WRITE_WAKEUP, &dev->tty->flags);
225		dev->txstate = STATE_IDLE;
226		spin_unlock_irqrestore(&dev->lock, flags);
227
228		netif_wake_queue(dev->netdev);
229	} else {
230		spin_unlock_irqrestore(&dev->lock, flags);
231	}
232}
233
234static netdev_tx_t mctp_serial_tx(struct sk_buff *skb, struct net_device *ndev)
235{
236	struct mctp_serial *dev = netdev_priv(ndev);
237	unsigned long flags;
238
239	WARN_ON(dev->txstate != STATE_IDLE);
240
241	if (skb->len > MCTP_SERIAL_MTU) {
242		dev->netdev->stats.tx_dropped++;
243		goto out;
244	}
245
246	spin_lock_irqsave(&dev->lock, flags);
247	netif_stop_queue(dev->netdev);
248	skb_copy_bits(skb, 0, dev->txbuf, skb->len);
249	dev->txpos = 0;
250	dev->txlen = skb->len;
251	dev->txstate = STATE_START;
252	spin_unlock_irqrestore(&dev->lock, flags);
253
254	set_bit(TTY_DO_WRITE_WAKEUP, &dev->tty->flags);
255	schedule_work(&dev->tx_work);
256
257out:
258	kfree_skb(skb);
259	return NETDEV_TX_OK;
260}
261
262static void mctp_serial_tty_write_wakeup(struct tty_struct *tty)
263{
264	struct mctp_serial *dev = tty->disc_data;
265
266	schedule_work(&dev->tx_work);
267}
268
269static void mctp_serial_rx(struct mctp_serial *dev)
270{
271	struct mctp_skb_cb *cb;
272	struct sk_buff *skb;
273
274	if (dev->rxfcs != dev->rxfcs_rcvd) {
275		dev->netdev->stats.rx_dropped++;
276		dev->netdev->stats.rx_crc_errors++;
277		return;
278	}
279
280	skb = netdev_alloc_skb(dev->netdev, dev->rxlen);
281	if (!skb) {
282		dev->netdev->stats.rx_dropped++;
283		return;
284	}
285
286	skb->protocol = htons(ETH_P_MCTP);
287	skb_put_data(skb, dev->rxbuf, dev->rxlen);
288	skb_reset_network_header(skb);
289
290	cb = __mctp_cb(skb);
291	cb->halen = 0;
292
293	netif_rx(skb);
294	dev->netdev->stats.rx_packets++;
295	dev->netdev->stats.rx_bytes += dev->rxlen;
296}
297
298static void mctp_serial_push_header(struct mctp_serial *dev, u8 c)
299{
300	switch (dev->rxpos) {
301	case 0:
302		if (c == BYTE_FRAME)
303			dev->rxpos++;
304		else
305			dev->rxstate = STATE_ERR;
306		break;
307	case 1:
308		if (c == MCTP_SERIAL_VERSION) {
309			dev->rxpos++;
310			dev->rxfcs = crc_ccitt_byte(FCS_INIT, c);
311		} else {
312			dev->rxstate = STATE_ERR;
313		}
314		break;
315	case 2:
316		if (c > MCTP_SERIAL_FRAME_MTU) {
317			dev->rxstate = STATE_ERR;
318		} else {
319			dev->rxlen = c;
320			dev->rxpos = 0;
321			dev->rxstate = STATE_DATA;
322			dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
323		}
324		break;
325	}
326}
327
328static void mctp_serial_push_trailer(struct mctp_serial *dev, u8 c)
329{
330	switch (dev->rxpos) {
331	case 0:
332		dev->rxfcs_rcvd = c << 8;
333		dev->rxpos++;
334		break;
335	case 1:
336		dev->rxfcs_rcvd |= c;
337		dev->rxpos++;
338		break;
339	case 2:
340		if (c != BYTE_FRAME) {
341			dev->rxstate = STATE_ERR;
342		} else {
343			mctp_serial_rx(dev);
344			dev->rxlen = 0;
345			dev->rxpos = 0;
346			dev->rxstate = STATE_IDLE;
347		}
348		break;
349	}
350}
351
352static void mctp_serial_push(struct mctp_serial *dev, u8 c)
353{
354	switch (dev->rxstate) {
355	case STATE_IDLE:
356		dev->rxstate = STATE_HEADER;
357		fallthrough;
358	case STATE_HEADER:
359		mctp_serial_push_header(dev, c);
360		break;
361
362	case STATE_ESCAPE:
363		c |= 0x20;
364		fallthrough;
365	case STATE_DATA:
366		if (dev->rxstate != STATE_ESCAPE && c == BYTE_ESC) {
367			dev->rxstate = STATE_ESCAPE;
368		} else {
369			dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
370			dev->rxbuf[dev->rxpos] = c;
371			dev->rxpos++;
372			dev->rxstate = STATE_DATA;
373			if (dev->rxpos == dev->rxlen) {
374				dev->rxpos = 0;
375				dev->rxstate = STATE_TRAILER;
376			}
377		}
378		break;
379
380	case STATE_TRAILER:
381		mctp_serial_push_trailer(dev, c);
382		break;
383
384	case STATE_ERR:
385		if (c == BYTE_FRAME)
386			dev->rxstate = STATE_IDLE;
387		break;
388
389	default:
390		netdev_err_once(dev->netdev, "invalid rx state %d\n",
391				dev->rxstate);
392	}
393}
394
395static void mctp_serial_tty_receive_buf(struct tty_struct *tty, const u8 *c,
396					const u8 *f, size_t len)
397{
398	struct mctp_serial *dev = tty->disc_data;
399	size_t i;
400
401	if (!netif_running(dev->netdev))
402		return;
403
404	/* we don't (currently) use the flag bytes, just data. */
405	for (i = 0; i < len; i++)
406		mctp_serial_push(dev, c[i]);
407}
408
409static void mctp_serial_uninit(struct net_device *ndev)
410{
411	struct mctp_serial *dev = netdev_priv(ndev);
412
413	cancel_work_sync(&dev->tx_work);
414}
415
416static const struct net_device_ops mctp_serial_netdev_ops = {
417	.ndo_start_xmit = mctp_serial_tx,
418	.ndo_uninit = mctp_serial_uninit,
419};
420
421static void mctp_serial_setup(struct net_device *ndev)
422{
423	ndev->type = ARPHRD_MCTP;
424
425	/* we limit at the fixed MTU, which is also the MCTP-standard
426	 * baseline MTU, so is also our minimum
427	 */
428	ndev->mtu = MCTP_SERIAL_MTU;
429	ndev->max_mtu = MCTP_SERIAL_MTU;
430	ndev->min_mtu = MCTP_SERIAL_MTU;
431
432	ndev->hard_header_len = 0;
433	ndev->addr_len = 0;
434	ndev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
435	ndev->flags = IFF_NOARP;
436	ndev->netdev_ops = &mctp_serial_netdev_ops;
437	ndev->needs_free_netdev = true;
438}
439
440static int mctp_serial_open(struct tty_struct *tty)
441{
442	struct mctp_serial *dev;
443	struct net_device *ndev;
444	char name[32];
445	int idx, rc;
446
447	if (!capable(CAP_NET_ADMIN))
448		return -EPERM;
449
450	if (!tty->ops->write)
451		return -EOPNOTSUPP;
452
453	idx = ida_alloc(&mctp_serial_ida, GFP_KERNEL);
454	if (idx < 0)
455		return idx;
456
457	snprintf(name, sizeof(name), "mctpserial%d", idx);
458	ndev = alloc_netdev(sizeof(*dev), name, NET_NAME_ENUM,
459			    mctp_serial_setup);
460	if (!ndev) {
461		rc = -ENOMEM;
462		goto free_ida;
463	}
464
465	dev = netdev_priv(ndev);
466	dev->idx = idx;
467	dev->tty = tty;
468	dev->netdev = ndev;
469	dev->txstate = STATE_IDLE;
470	dev->rxstate = STATE_IDLE;
471	spin_lock_init(&dev->lock);
472	INIT_WORK(&dev->tx_work, mctp_serial_tx_work);
473
474	rc = mctp_register_netdev(ndev, NULL, MCTP_PHYS_BINDING_SERIAL);
475	if (rc)
476		goto free_netdev;
477
478	tty->receive_room = 64 * 1024;
479	tty->disc_data = dev;
480
481	return 0;
482
483free_netdev:
484	free_netdev(ndev);
485
486free_ida:
487	ida_free(&mctp_serial_ida, idx);
488	return rc;
489}
490
491static void mctp_serial_close(struct tty_struct *tty)
492{
493	struct mctp_serial *dev = tty->disc_data;
494	int idx = dev->idx;
495
496	mctp_unregister_netdev(dev->netdev);
497	ida_free(&mctp_serial_ida, idx);
498}
499
500static struct tty_ldisc_ops mctp_ldisc = {
501	.owner		= THIS_MODULE,
502	.num		= N_MCTP,
503	.name		= "mctp",
504	.open		= mctp_serial_open,
505	.close		= mctp_serial_close,
506	.receive_buf	= mctp_serial_tty_receive_buf,
507	.write_wakeup	= mctp_serial_tty_write_wakeup,
508};
509
510static int __init mctp_serial_init(void)
511{
512	return tty_register_ldisc(&mctp_ldisc);
513}
514
515static void __exit mctp_serial_exit(void)
516{
517	tty_unregister_ldisc(&mctp_ldisc);
518}
519
520module_init(mctp_serial_init);
521module_exit(mctp_serial_exit);
522
523MODULE_LICENSE("GPL v2");
524MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>");
525MODULE_DESCRIPTION("MCTP Serial transport");
526
527#if IS_ENABLED(CONFIG_MCTP_SERIAL_TEST)
528#include <kunit/test.h>
529
530#define MAX_CHUNKS 6
531struct test_chunk_tx {
532	u8 input_len;
533	u8 input[MCTP_SERIAL_MTU];
534	u8 chunks[MAX_CHUNKS];
535};
536
537static void test_next_chunk_len(struct kunit *test)
538{
539	struct mctp_serial devx;
540	struct mctp_serial *dev = &devx;
541	int next;
542
543	const struct test_chunk_tx *params = test->param_value;
544
545	memset(dev, 0x0, sizeof(*dev));
546	memcpy(dev->txbuf, params->input, params->input_len);
547	dev->txlen = params->input_len;
548
549	for (size_t i = 0; i < MAX_CHUNKS; i++) {
550		next = next_chunk_len(dev);
551		dev->txpos += next;
552		KUNIT_EXPECT_EQ(test, next, params->chunks[i]);
553
554		if (next == 0) {
555			KUNIT_EXPECT_EQ(test, dev->txpos, dev->txlen);
556			return;
557		}
558	}
559
560	KUNIT_FAIL_AND_ABORT(test, "Ran out of chunks");
561}
562
563static struct test_chunk_tx chunk_tx_tests[] = {
564	{
565		.input_len = 5,
566		.input = { 0x00, 0x11, 0x22, 0x7e, 0x80 },
567		.chunks = { 3, 1, 1, 0},
568	},
569	{
570		.input_len = 5,
571		.input = { 0x00, 0x11, 0x22, 0x7e, 0x7d },
572		.chunks = { 3, 1, 1, 0},
573	},
574	{
575		.input_len = 3,
576		.input = { 0x7e, 0x11, 0x22, },
577		.chunks = { 1, 2, 0},
578	},
579	{
580		.input_len = 3,
581		.input = { 0x7e, 0x7e, 0x7d, },
582		.chunks = { 1, 1, 1, 0},
583	},
584	{
585		.input_len = 4,
586		.input = { 0x7e, 0x7e, 0x00, 0x7d, },
587		.chunks = { 1, 1, 1, 1, 0},
588	},
589	{
590		.input_len = 6,
591		.input = { 0x7e, 0x7e, 0x00, 0x7d, 0x10, 0x10},
592		.chunks = { 1, 1, 1, 1, 2, 0},
593	},
594	{
595		.input_len = 1,
596		.input = { 0x7e },
597		.chunks = { 1, 0 },
598	},
599	{
600		.input_len = 1,
601		.input = { 0x80 },
602		.chunks = { 1, 0 },
603	},
604	{
605		.input_len = 3,
606		.input = { 0x80, 0x80, 0x00 },
607		.chunks = { 3, 0 },
608	},
609	{
610		.input_len = 7,
611		.input = { 0x01, 0x00, 0x08, 0xc8, 0x00, 0x80, 0x02 },
612		.chunks = { 7, 0 },
613	},
614	{
615		.input_len = 7,
616		.input = { 0x01, 0x00, 0x08, 0xc8, 0x7e, 0x80, 0x02 },
617		.chunks = { 4, 1, 2, 0 },
618	},
619};
620
621KUNIT_ARRAY_PARAM(chunk_tx, chunk_tx_tests, NULL);
622
623static struct kunit_case mctp_serial_test_cases[] = {
624	KUNIT_CASE_PARAM(test_next_chunk_len, chunk_tx_gen_params),
625};
626
627static struct kunit_suite mctp_serial_test_suite = {
628	.name = "mctp_serial",
629	.test_cases = mctp_serial_test_cases,
630};
631
632kunit_test_suite(mctp_serial_test_suite);
633
634#endif /* CONFIG_MCTP_SERIAL_TEST */