Loading...
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");
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 */