Commit 04b374d0 authored by Paul Fulghum's avatar Paul Fulghum Committed by Linus Torvalds

[PATCH] add synclink_gt crc return feature

Add ability to return HDLC CRC to user application.
Signed-off-by: default avatarPaul Fulghum <paulkf@microgate.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 643f3319
...@@ -3077,7 +3077,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -3077,7 +3077,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
static int alloc_tmp_rbuf(struct slgt_info *info) static int alloc_tmp_rbuf(struct slgt_info *info)
{ {
info->tmp_rbuf = kmalloc(info->max_frame_size, GFP_KERNEL); info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL);
if (info->tmp_rbuf == NULL) if (info->tmp_rbuf == NULL)
return -ENOMEM; return -ENOMEM;
return 0; return 0;
...@@ -4011,7 +4011,7 @@ static void hdlc_mode(struct slgt_info *info) ...@@ -4011,7 +4011,7 @@ static void hdlc_mode(struct slgt_info *info)
case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
} }
switch (info->params.crc_type) switch (info->params.crc_type & HDLC_CRC_MASK)
{ {
case HDLC_CRC_16_CCITT: val |= BIT9; break; case HDLC_CRC_16_CCITT: val |= BIT9; break;
case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
...@@ -4072,7 +4072,7 @@ static void hdlc_mode(struct slgt_info *info) ...@@ -4072,7 +4072,7 @@ static void hdlc_mode(struct slgt_info *info)
case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break; case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
} }
switch (info->params.crc_type) switch (info->params.crc_type & HDLC_CRC_MASK)
{ {
case HDLC_CRC_16_CCITT: val |= BIT9; break; case HDLC_CRC_16_CCITT: val |= BIT9; break;
case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break; case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
...@@ -4333,6 +4333,12 @@ static int rx_get_frame(struct slgt_info *info) ...@@ -4333,6 +4333,12 @@ static int rx_get_frame(struct slgt_info *info)
unsigned long flags; unsigned long flags;
struct tty_struct *tty = info->tty; struct tty_struct *tty = info->tty;
unsigned char addr_field = 0xff; unsigned char addr_field = 0xff;
unsigned int crc_size = 0;
switch (info->params.crc_type & HDLC_CRC_MASK) {
case HDLC_CRC_16_CCITT: crc_size = 2; break;
case HDLC_CRC_32_CCITT: crc_size = 4; break;
}
check_again: check_again:
...@@ -4377,7 +4383,7 @@ static int rx_get_frame(struct slgt_info *info) ...@@ -4377,7 +4383,7 @@ static int rx_get_frame(struct slgt_info *info)
status = desc_status(info->rbufs[end]); status = desc_status(info->rbufs[end]);
/* ignore CRC bit if not using CRC (bit is undefined) */ /* ignore CRC bit if not using CRC (bit is undefined) */
if (info->params.crc_type == HDLC_CRC_NONE) if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE)
status &= ~BIT1; status &= ~BIT1;
if (framesize == 0 || if (framesize == 0 ||
...@@ -4386,34 +4392,34 @@ static int rx_get_frame(struct slgt_info *info) ...@@ -4386,34 +4392,34 @@ static int rx_get_frame(struct slgt_info *info)
goto check_again; goto check_again;
} }
if (framesize < 2 || status & (BIT1+BIT0)) { if (framesize < (2 + crc_size) || status & BIT0) {
if (framesize < 2 || (status & BIT0)) info->icount.rxshort++;
info->icount.rxshort++;
else
info->icount.rxcrc++;
framesize = 0; framesize = 0;
} else if (status & BIT1) {
info->icount.rxcrc++;
if (!(info->params.crc_type & HDLC_CRC_RETURN_EX))
framesize = 0;
}
#ifdef CONFIG_HDLC #ifdef CONFIG_HDLC
{ if (framesize == 0) {
struct net_device_stats *stats = hdlc_stats(info->netdev); struct net_device_stats *stats = hdlc_stats(info->netdev);
stats->rx_errors++; stats->rx_errors++;
stats->rx_frame_errors++; stats->rx_frame_errors++;
}
#endif
} else {
/* adjust frame size for CRC, if any */
if (info->params.crc_type == HDLC_CRC_16_CCITT)
framesize -= 2;
else if (info->params.crc_type == HDLC_CRC_32_CCITT)
framesize -= 4;
} }
#endif
DBGBH(("%s rx frame status=%04X size=%d\n", DBGBH(("%s rx frame status=%04X size=%d\n",
info->device_name, status, framesize)); info->device_name, status, framesize));
DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx");
if (framesize) { if (framesize) {
if (framesize > info->max_frame_size) if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
framesize -= crc_size;
crc_size = 0;
}
if (framesize > info->max_frame_size + crc_size)
info->icount.rxlong++; info->icount.rxlong++;
else { else {
/* copy dma buffer(s) to contiguous temp buffer */ /* copy dma buffer(s) to contiguous temp buffer */
...@@ -4433,6 +4439,11 @@ static int rx_get_frame(struct slgt_info *info) ...@@ -4433,6 +4439,11 @@ static int rx_get_frame(struct slgt_info *info)
i = 0; i = 0;
} }
if (info->params.crc_type & HDLC_CRC_RETURN_EX) {
*p = (status & BIT1) ? RX_CRC_ERROR : RX_OK;
framesize++;
}
#ifdef CONFIG_HDLC #ifdef CONFIG_HDLC
if (info->netcount) if (info->netcount)
hdlcdev_rx(info,info->tmp_rbuf, framesize); hdlcdev_rx(info,info->tmp_rbuf, framesize);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment