diff options
Diffstat (limited to 'drivers/char/synclink_gt.c')
-rw-r--r-- | drivers/char/synclink_gt.c | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 6f93a0149fbf..03a7f20db49a 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -3077,7 +3077,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, | |||
3077 | 3077 | ||
3078 | static int alloc_tmp_rbuf(struct slgt_info *info) | 3078 | static int alloc_tmp_rbuf(struct slgt_info *info) |
3079 | { | 3079 | { |
3080 | info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL); | 3080 | info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL); |
3081 | if (info->tmp_rbuf == NULL) | 3081 | if (info->tmp_rbuf == NULL) |
3082 | return -ENOMEM; | 3082 | return -ENOMEM; |
3083 | return 0; | 3083 | return 0; |
@@ -4011,7 +4011,7 @@ static void hdlc_mode(struct slgt_info *info) | |||
4011 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; | 4011 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; |
4012 | } | 4012 | } |
4013 | 4013 | ||
4014 | switch (info->params.crc_type) | 4014 | switch (info->params.crc_type & HDLC_CRC_MASK) |
4015 | { | 4015 | { |
4016 | case HDLC_CRC_16_CCITT: val |= BIT9; break; | 4016 | case HDLC_CRC_16_CCITT: val |= BIT9; break; |
4017 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; | 4017 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; |
@@ -4072,7 +4072,7 @@ static void hdlc_mode(struct slgt_info *info) | |||
4072 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; | 4072 | case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; |
4073 | } | 4073 | } |
4074 | 4074 | ||
4075 | switch (info->params.crc_type) | 4075 | switch (info->params.crc_type & HDLC_CRC_MASK) |
4076 | { | 4076 | { |
4077 | case HDLC_CRC_16_CCITT: val |= BIT9; break; | 4077 | case HDLC_CRC_16_CCITT: val |= BIT9; break; |
4078 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; | 4078 | case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; |
@@ -4333,6 +4333,12 @@ static int rx_get_frame(struct slgt_info *info) | |||
4333 | unsigned long flags; | 4333 | unsigned long flags; |
4334 | struct tty_struct *tty = info->tty; | 4334 | struct tty_struct *tty = info->tty; |
4335 | unsigned char addr_field = 0xff; | 4335 | unsigned char addr_field = 0xff; |
4336 | unsigned int crc_size = 0; | ||
4337 | |||
4338 | switch (info->params.crc_type & HDLC_CRC_MASK) { | ||
4339 | case HDLC_CRC_16_CCITT: crc_size = 2; break; | ||
4340 | case HDLC_CRC_32_CCITT: crc_size = 4; break; | ||
4341 | } | ||
4336 | 4342 | ||
4337 | check_again: | 4343 | check_again: |
4338 | 4344 | ||
@@ -4377,7 +4383,7 @@ check_again: | |||
4377 | status = desc_status(info->rbufs[end]); | 4383 | status = desc_status(info->rbufs[end]); |
4378 | 4384 | ||
4379 | /* ignore CRC bit if not using CRC (bit is undefined) */ | 4385 | /* ignore CRC bit if not using CRC (bit is undefined) */ |
4380 | if (info->params.crc_type == HDLC_CRC_NONE) | 4386 | if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE) |
4381 | status &= ~BIT1; | 4387 | status &= ~BIT1; |
4382 | 4388 | ||
4383 | if (framesize == 0 || | 4389 | if (framesize == 0 || |
@@ -4386,34 +4392,34 @@ check_again: | |||
4386 | goto check_again; | 4392 | goto check_again; |
4387 | } | 4393 | } |
4388 | 4394 | ||
4389 | if (framesize < 2 || status & (BIT1+BIT0)) { | 4395 | if (framesize < (2 + crc_size) || status & BIT0) { |
4390 | if (framesize < 2 || (status & BIT0)) | 4396 | info->icount.rxshort++; |
4391 | info->icount.rxshort++; | ||
4392 | else | ||
4393 | info->icount.rxcrc++; | ||
4394 | framesize = 0; | 4397 | framesize = 0; |
4398 | } else if (status & BIT1) { | ||
4399 | info->icount.rxcrc++; | ||
4400 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) | ||
4401 | framesize = 0; | ||
4402 | } | ||
4395 | 4403 | ||
4396 | #ifdef CONFIG_HDLC | 4404 | #ifdef CONFIG_HDLC |
4397 | { | 4405 | if (framesize == 0) { |
4398 | struct net_device_stats *stats = hdlc_stats(info->netdev); | 4406 | struct net_device_stats *stats = hdlc_stats(info->netdev); |
4399 | stats->rx_errors++; | 4407 | stats->rx_errors++; |
4400 | stats->rx_frame_errors++; | 4408 | stats->rx_frame_errors++; |
4401 | } | ||
4402 | #endif | ||
4403 | } else { | ||
4404 | /* adjust frame size for CRC, if any */ | ||
4405 | if (info->params.crc_type == HDLC_CRC_16_CCITT) | ||
4406 | framesize -= 2; | ||
4407 | else if (info->params.crc_type == HDLC_CRC_32_CCITT) | ||
4408 | framesize -= 4; | ||
4409 | } | 4409 | } |
4410 | #endif | ||
4410 | 4411 | ||
4411 | DBGBH(("%s rx frame status=%04X size=%d\n", | 4412 | DBGBH(("%s rx frame status=%04X size=%d\n", |
4412 | info->device_name, status, framesize)); | 4413 | info->device_name, status, framesize)); |
4413 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); | 4414 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); |
4414 | 4415 | ||
4415 | if (framesize) { | 4416 | if (framesize) { |
4416 | if (framesize > info->max_frame_size) | 4417 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { |
4418 | framesize -= crc_size; | ||
4419 | crc_size = 0; | ||
4420 | } | ||
4421 | |||
4422 | if (framesize > info->max_frame_size + crc_size) | ||
4417 | info->icount.rxlong++; | 4423 | info->icount.rxlong++; |
4418 | else { | 4424 | else { |
4419 | /* copy dma buffer(s) to contiguous temp buffer */ | 4425 | /* copy dma buffer(s) to contiguous temp buffer */ |
@@ -4433,6 +4439,11 @@ check_again: | |||
4433 | i = 0; | 4439 | i = 0; |
4434 | } | 4440 | } |
4435 | 4441 | ||
4442 | if (info->params.crc_type & HDLC_CRC_RETURN_EX) { | ||
4443 | *p = (status & BIT1) ? RX_CRC_ERROR : RX_OK; | ||
4444 | framesize++; | ||
4445 | } | ||
4446 | |||
4436 | #ifdef CONFIG_HDLC | 4447 | #ifdef CONFIG_HDLC |
4437 | if (info->netcount) | 4448 | if (info->netcount) |
4438 | hdlcdev_rx(info,info->tmp_rbuf, framesize); | 4449 | hdlcdev_rx(info,info->tmp_rbuf, framesize); |