0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <linux/idr.h>
0017 #include <linux/if_arp.h>
0018 #include <linux/module.h>
0019 #include <linux/skbuff.h>
0020 #include <linux/tty.h>
0021 #include <linux/workqueue.h>
0022 #include <linux/crc-ccitt.h>
0023
0024 #include <linux/mctp.h>
0025 #include <net/mctp.h>
0026 #include <net/pkt_sched.h>
0027
0028 #define MCTP_SERIAL_MTU 68
0029 #define MCTP_SERIAL_FRAME_MTU (MCTP_SERIAL_MTU + 6)
0030
0031 #define MCTP_SERIAL_VERSION 0x1
0032
0033 #define BUFSIZE MCTP_SERIAL_FRAME_MTU
0034
0035 #define BYTE_FRAME 0x7e
0036 #define BYTE_ESC 0x7d
0037
0038 static DEFINE_IDA(mctp_serial_ida);
0039
0040 enum mctp_serial_state {
0041 STATE_IDLE,
0042 STATE_START,
0043 STATE_HEADER,
0044 STATE_DATA,
0045 STATE_ESCAPE,
0046 STATE_TRAILER,
0047 STATE_DONE,
0048 STATE_ERR,
0049 };
0050
0051 struct mctp_serial {
0052 struct net_device *netdev;
0053 struct tty_struct *tty;
0054
0055 int idx;
0056
0057
0058 spinlock_t lock;
0059
0060 struct work_struct tx_work;
0061 enum mctp_serial_state txstate, rxstate;
0062 u16 txfcs, rxfcs, rxfcs_rcvd;
0063 unsigned int txlen, rxlen;
0064 unsigned int txpos, rxpos;
0065 unsigned char txbuf[BUFSIZE],
0066 rxbuf[BUFSIZE];
0067 };
0068
0069 static bool needs_escape(unsigned char c)
0070 {
0071 return c == BYTE_ESC || c == BYTE_FRAME;
0072 }
0073
0074 static int next_chunk_len(struct mctp_serial *dev)
0075 {
0076 int i;
0077
0078
0079 if (dev->txpos == dev->txlen)
0080 return 0;
0081
0082
0083
0084
0085 if (needs_escape(dev->txbuf[dev->txpos]))
0086 return 1;
0087
0088
0089
0090
0091
0092 for (i = 1; i + dev->txpos + 1 < dev->txlen; i++) {
0093 if (needs_escape(dev->txbuf[dev->txpos + i + 1]))
0094 break;
0095 }
0096
0097 return i;
0098 }
0099
0100 static int write_chunk(struct mctp_serial *dev, unsigned char *buf, int len)
0101 {
0102 return dev->tty->ops->write(dev->tty, buf, len);
0103 }
0104
0105 static void mctp_serial_tx_work(struct work_struct *work)
0106 {
0107 struct mctp_serial *dev = container_of(work, struct mctp_serial,
0108 tx_work);
0109 unsigned char c, buf[3];
0110 unsigned long flags;
0111 int len, txlen;
0112
0113 spin_lock_irqsave(&dev->lock, flags);
0114
0115
0116 switch (dev->txstate) {
0117 case STATE_START:
0118 dev->txpos = 0;
0119 fallthrough;
0120 case STATE_HEADER:
0121 buf[0] = BYTE_FRAME;
0122 buf[1] = MCTP_SERIAL_VERSION;
0123 buf[2] = dev->txlen;
0124
0125 if (!dev->txpos)
0126 dev->txfcs = crc_ccitt(0, buf + 1, 2);
0127
0128 txlen = write_chunk(dev, buf + dev->txpos, 3 - dev->txpos);
0129 if (txlen <= 0) {
0130 dev->txstate = STATE_ERR;
0131 } else {
0132 dev->txpos += txlen;
0133 if (dev->txpos == 3) {
0134 dev->txstate = STATE_DATA;
0135 dev->txpos = 0;
0136 }
0137 }
0138 break;
0139
0140 case STATE_ESCAPE:
0141 buf[0] = dev->txbuf[dev->txpos] & ~0x20;
0142 txlen = write_chunk(dev, buf, 1);
0143 if (txlen <= 0) {
0144 dev->txstate = STATE_ERR;
0145 } else {
0146 dev->txpos += txlen;
0147 if (dev->txpos == dev->txlen) {
0148 dev->txstate = STATE_TRAILER;
0149 dev->txpos = 0;
0150 }
0151 }
0152
0153 break;
0154
0155 case STATE_DATA:
0156 len = next_chunk_len(dev);
0157 if (len) {
0158 c = dev->txbuf[dev->txpos];
0159 if (len == 1 && needs_escape(c)) {
0160 buf[0] = BYTE_ESC;
0161 buf[1] = c & ~0x20;
0162 dev->txfcs = crc_ccitt_byte(dev->txfcs, c);
0163 txlen = write_chunk(dev, buf, 2);
0164 if (txlen == 2)
0165 dev->txpos++;
0166 else if (txlen == 1)
0167 dev->txstate = STATE_ESCAPE;
0168 else
0169 dev->txstate = STATE_ERR;
0170 } else {
0171 txlen = write_chunk(dev,
0172 dev->txbuf + dev->txpos,
0173 len);
0174 if (txlen <= 0) {
0175 dev->txstate = STATE_ERR;
0176 } else {
0177 dev->txfcs = crc_ccitt(dev->txfcs,
0178 dev->txbuf +
0179 dev->txpos,
0180 txlen);
0181 dev->txpos += txlen;
0182 }
0183 }
0184 if (dev->txstate == STATE_DATA &&
0185 dev->txpos == dev->txlen) {
0186 dev->txstate = STATE_TRAILER;
0187 dev->txpos = 0;
0188 }
0189 break;
0190 }
0191 dev->txstate = STATE_TRAILER;
0192 dev->txpos = 0;
0193 fallthrough;
0194
0195 case STATE_TRAILER:
0196 buf[0] = dev->txfcs >> 8;
0197 buf[1] = dev->txfcs & 0xff;
0198 buf[2] = BYTE_FRAME;
0199 txlen = write_chunk(dev, buf + dev->txpos, 3 - dev->txpos);
0200 if (txlen <= 0) {
0201 dev->txstate = STATE_ERR;
0202 } else {
0203 dev->txpos += txlen;
0204 if (dev->txpos == 3) {
0205 dev->txstate = STATE_DONE;
0206 dev->txpos = 0;
0207 }
0208 }
0209 break;
0210 default:
0211 netdev_err_once(dev->netdev, "invalid tx state %d\n",
0212 dev->txstate);
0213 }
0214
0215 if (dev->txstate == STATE_DONE) {
0216 dev->netdev->stats.tx_packets++;
0217 dev->netdev->stats.tx_bytes += dev->txlen;
0218 dev->txlen = 0;
0219 dev->txpos = 0;
0220 clear_bit(TTY_DO_WRITE_WAKEUP, &dev->tty->flags);
0221 dev->txstate = STATE_IDLE;
0222 spin_unlock_irqrestore(&dev->lock, flags);
0223
0224 netif_wake_queue(dev->netdev);
0225 } else {
0226 spin_unlock_irqrestore(&dev->lock, flags);
0227 }
0228 }
0229
0230 static netdev_tx_t mctp_serial_tx(struct sk_buff *skb, struct net_device *ndev)
0231 {
0232 struct mctp_serial *dev = netdev_priv(ndev);
0233 unsigned long flags;
0234
0235 WARN_ON(dev->txstate != STATE_IDLE);
0236
0237 if (skb->len > MCTP_SERIAL_MTU) {
0238 dev->netdev->stats.tx_dropped++;
0239 goto out;
0240 }
0241
0242 spin_lock_irqsave(&dev->lock, flags);
0243 netif_stop_queue(dev->netdev);
0244 skb_copy_bits(skb, 0, dev->txbuf, skb->len);
0245 dev->txpos = 0;
0246 dev->txlen = skb->len;
0247 dev->txstate = STATE_START;
0248 spin_unlock_irqrestore(&dev->lock, flags);
0249
0250 set_bit(TTY_DO_WRITE_WAKEUP, &dev->tty->flags);
0251 schedule_work(&dev->tx_work);
0252
0253 out:
0254 kfree_skb(skb);
0255 return NETDEV_TX_OK;
0256 }
0257
0258 static void mctp_serial_tty_write_wakeup(struct tty_struct *tty)
0259 {
0260 struct mctp_serial *dev = tty->disc_data;
0261
0262 schedule_work(&dev->tx_work);
0263 }
0264
0265 static void mctp_serial_rx(struct mctp_serial *dev)
0266 {
0267 struct mctp_skb_cb *cb;
0268 struct sk_buff *skb;
0269
0270 if (dev->rxfcs != dev->rxfcs_rcvd) {
0271 dev->netdev->stats.rx_dropped++;
0272 dev->netdev->stats.rx_crc_errors++;
0273 return;
0274 }
0275
0276 skb = netdev_alloc_skb(dev->netdev, dev->rxlen);
0277 if (!skb) {
0278 dev->netdev->stats.rx_dropped++;
0279 return;
0280 }
0281
0282 skb->protocol = htons(ETH_P_MCTP);
0283 skb_put_data(skb, dev->rxbuf, dev->rxlen);
0284 skb_reset_network_header(skb);
0285
0286 cb = __mctp_cb(skb);
0287 cb->halen = 0;
0288
0289 netif_rx(skb);
0290 dev->netdev->stats.rx_packets++;
0291 dev->netdev->stats.rx_bytes += dev->rxlen;
0292 }
0293
0294 static void mctp_serial_push_header(struct mctp_serial *dev, unsigned char c)
0295 {
0296 switch (dev->rxpos) {
0297 case 0:
0298 if (c == BYTE_FRAME)
0299 dev->rxpos++;
0300 else
0301 dev->rxstate = STATE_ERR;
0302 break;
0303 case 1:
0304 if (c == MCTP_SERIAL_VERSION) {
0305 dev->rxpos++;
0306 dev->rxfcs = crc_ccitt_byte(0, c);
0307 } else {
0308 dev->rxstate = STATE_ERR;
0309 }
0310 break;
0311 case 2:
0312 if (c > MCTP_SERIAL_FRAME_MTU) {
0313 dev->rxstate = STATE_ERR;
0314 } else {
0315 dev->rxlen = c;
0316 dev->rxpos = 0;
0317 dev->rxstate = STATE_DATA;
0318 dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
0319 }
0320 break;
0321 }
0322 }
0323
0324 static void mctp_serial_push_trailer(struct mctp_serial *dev, unsigned char c)
0325 {
0326 switch (dev->rxpos) {
0327 case 0:
0328 dev->rxfcs_rcvd = c << 8;
0329 dev->rxpos++;
0330 break;
0331 case 1:
0332 dev->rxfcs_rcvd |= c;
0333 dev->rxpos++;
0334 break;
0335 case 2:
0336 if (c != BYTE_FRAME) {
0337 dev->rxstate = STATE_ERR;
0338 } else {
0339 mctp_serial_rx(dev);
0340 dev->rxlen = 0;
0341 dev->rxpos = 0;
0342 dev->rxstate = STATE_IDLE;
0343 }
0344 break;
0345 }
0346 }
0347
0348 static void mctp_serial_push(struct mctp_serial *dev, unsigned char c)
0349 {
0350 switch (dev->rxstate) {
0351 case STATE_IDLE:
0352 dev->rxstate = STATE_HEADER;
0353 fallthrough;
0354 case STATE_HEADER:
0355 mctp_serial_push_header(dev, c);
0356 break;
0357
0358 case STATE_ESCAPE:
0359 c |= 0x20;
0360 fallthrough;
0361 case STATE_DATA:
0362 if (dev->rxstate != STATE_ESCAPE && c == BYTE_ESC) {
0363 dev->rxstate = STATE_ESCAPE;
0364 } else {
0365 dev->rxfcs = crc_ccitt_byte(dev->rxfcs, c);
0366 dev->rxbuf[dev->rxpos] = c;
0367 dev->rxpos++;
0368 dev->rxstate = STATE_DATA;
0369 if (dev->rxpos == dev->rxlen) {
0370 dev->rxpos = 0;
0371 dev->rxstate = STATE_TRAILER;
0372 }
0373 }
0374 break;
0375
0376 case STATE_TRAILER:
0377 mctp_serial_push_trailer(dev, c);
0378 break;
0379
0380 case STATE_ERR:
0381 if (c == BYTE_FRAME)
0382 dev->rxstate = STATE_IDLE;
0383 break;
0384
0385 default:
0386 netdev_err_once(dev->netdev, "invalid rx state %d\n",
0387 dev->rxstate);
0388 }
0389 }
0390
0391 static void mctp_serial_tty_receive_buf(struct tty_struct *tty,
0392 const unsigned char *c,
0393 const char *f, int len)
0394 {
0395 struct mctp_serial *dev = tty->disc_data;
0396 int i;
0397
0398 if (!netif_running(dev->netdev))
0399 return;
0400
0401
0402 for (i = 0; i < len; i++)
0403 mctp_serial_push(dev, c[i]);
0404 }
0405
0406 static void mctp_serial_uninit(struct net_device *ndev)
0407 {
0408 struct mctp_serial *dev = netdev_priv(ndev);
0409
0410 cancel_work_sync(&dev->tx_work);
0411 }
0412
0413 static const struct net_device_ops mctp_serial_netdev_ops = {
0414 .ndo_start_xmit = mctp_serial_tx,
0415 .ndo_uninit = mctp_serial_uninit,
0416 };
0417
0418 static void mctp_serial_setup(struct net_device *ndev)
0419 {
0420 ndev->type = ARPHRD_MCTP;
0421
0422
0423
0424
0425 ndev->mtu = MCTP_SERIAL_MTU;
0426 ndev->max_mtu = MCTP_SERIAL_MTU;
0427 ndev->min_mtu = MCTP_SERIAL_MTU;
0428
0429 ndev->hard_header_len = 0;
0430 ndev->addr_len = 0;
0431 ndev->tx_queue_len = DEFAULT_TX_QUEUE_LEN;
0432 ndev->flags = IFF_NOARP;
0433 ndev->netdev_ops = &mctp_serial_netdev_ops;
0434 ndev->needs_free_netdev = true;
0435 }
0436
0437 static int mctp_serial_open(struct tty_struct *tty)
0438 {
0439 struct mctp_serial *dev;
0440 struct net_device *ndev;
0441 char name[32];
0442 int idx, rc;
0443
0444 if (!capable(CAP_NET_ADMIN))
0445 return -EPERM;
0446
0447 if (!tty->ops->write)
0448 return -EOPNOTSUPP;
0449
0450 idx = ida_alloc(&mctp_serial_ida, GFP_KERNEL);
0451 if (idx < 0)
0452 return idx;
0453
0454 snprintf(name, sizeof(name), "mctpserial%d", idx);
0455 ndev = alloc_netdev(sizeof(*dev), name, NET_NAME_ENUM,
0456 mctp_serial_setup);
0457 if (!ndev) {
0458 rc = -ENOMEM;
0459 goto free_ida;
0460 }
0461
0462 dev = netdev_priv(ndev);
0463 dev->idx = idx;
0464 dev->tty = tty;
0465 dev->netdev = ndev;
0466 dev->txstate = STATE_IDLE;
0467 dev->rxstate = STATE_IDLE;
0468 spin_lock_init(&dev->lock);
0469 INIT_WORK(&dev->tx_work, mctp_serial_tx_work);
0470
0471 rc = register_netdev(ndev);
0472 if (rc)
0473 goto free_netdev;
0474
0475 tty->receive_room = 64 * 1024;
0476 tty->disc_data = dev;
0477
0478 return 0;
0479
0480 free_netdev:
0481 free_netdev(ndev);
0482
0483 free_ida:
0484 ida_free(&mctp_serial_ida, idx);
0485 return rc;
0486 }
0487
0488 static void mctp_serial_close(struct tty_struct *tty)
0489 {
0490 struct mctp_serial *dev = tty->disc_data;
0491 int idx = dev->idx;
0492
0493 unregister_netdev(dev->netdev);
0494 ida_free(&mctp_serial_ida, idx);
0495 }
0496
0497 static struct tty_ldisc_ops mctp_ldisc = {
0498 .owner = THIS_MODULE,
0499 .num = N_MCTP,
0500 .name = "mctp",
0501 .open = mctp_serial_open,
0502 .close = mctp_serial_close,
0503 .receive_buf = mctp_serial_tty_receive_buf,
0504 .write_wakeup = mctp_serial_tty_write_wakeup,
0505 };
0506
0507 static int __init mctp_serial_init(void)
0508 {
0509 return tty_register_ldisc(&mctp_ldisc);
0510 }
0511
0512 static void __exit mctp_serial_exit(void)
0513 {
0514 tty_unregister_ldisc(&mctp_ldisc);
0515 }
0516
0517 module_init(mctp_serial_init);
0518 module_exit(mctp_serial_exit);
0519
0520 MODULE_LICENSE("GPL v2");
0521 MODULE_AUTHOR("Jeremy Kerr <jk@codeconstruct.com.au>");
0522 MODULE_DESCRIPTION("MCTP Serial transport");