diff options
-rw-r--r-- | drivers/char/synclink_gt.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 3cfc9e1f8882..8511e2e43c18 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -214,6 +214,7 @@ struct slgt_desc | |||
214 | char *buf; /* virtual address of data buffer */ | 214 | char *buf; /* virtual address of data buffer */ |
215 | unsigned int pdesc; /* physical address of this descriptor */ | 215 | unsigned int pdesc; /* physical address of this descriptor */ |
216 | dma_addr_t buf_dma_addr; | 216 | dma_addr_t buf_dma_addr; |
217 | unsigned short buf_count; | ||
217 | }; | 218 | }; |
218 | 219 | ||
219 | #define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) | 220 | #define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) |
@@ -466,6 +467,7 @@ static void tx_start(struct slgt_info *info); | |||
466 | static void tx_stop(struct slgt_info *info); | 467 | static void tx_stop(struct slgt_info *info); |
467 | static void tx_set_idle(struct slgt_info *info); | 468 | static void tx_set_idle(struct slgt_info *info); |
468 | static unsigned int free_tbuf_count(struct slgt_info *info); | 469 | static unsigned int free_tbuf_count(struct slgt_info *info); |
470 | static unsigned int tbuf_bytes(struct slgt_info *info); | ||
469 | static void reset_tbufs(struct slgt_info *info); | 471 | static void reset_tbufs(struct slgt_info *info); |
470 | static void tdma_reset(struct slgt_info *info); | 472 | static void tdma_reset(struct slgt_info *info); |
471 | static void tdma_start(struct slgt_info *info); | 473 | static void tdma_start(struct slgt_info *info); |
@@ -1388,10 +1390,12 @@ done: | |||
1388 | static int chars_in_buffer(struct tty_struct *tty) | 1390 | static int chars_in_buffer(struct tty_struct *tty) |
1389 | { | 1391 | { |
1390 | struct slgt_info *info = tty->driver_data; | 1392 | struct slgt_info *info = tty->driver_data; |
1393 | int count; | ||
1391 | if (sanity_check(info, tty->name, "chars_in_buffer")) | 1394 | if (sanity_check(info, tty->name, "chars_in_buffer")) |
1392 | return 0; | 1395 | return 0; |
1393 | DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count)); | 1396 | count = tbuf_bytes(info); |
1394 | return info->tx_count; | 1397 | DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count)); |
1398 | return count; | ||
1395 | } | 1399 | } |
1396 | 1400 | ||
1397 | /* | 1401 | /* |
@@ -4671,6 +4675,56 @@ static unsigned int free_tbuf_count(struct slgt_info *info) | |||
4671 | } | 4675 | } |
4672 | 4676 | ||
4673 | /* | 4677 | /* |
4678 | * return number of bytes in unsent transmit DMA buffers | ||
4679 | * and the serial controller tx FIFO | ||
4680 | */ | ||
4681 | static unsigned int tbuf_bytes(struct slgt_info *info) | ||
4682 | { | ||
4683 | unsigned int total_count = 0; | ||
4684 | unsigned int i = info->tbuf_current; | ||
4685 | unsigned int reg_value; | ||
4686 | unsigned int count; | ||
4687 | unsigned int active_buf_count = 0; | ||
4688 | |||
4689 | /* | ||
4690 | * Add descriptor counts for all tx DMA buffers. | ||
4691 | * If count is zero (cleared by DMA controller after read), | ||
4692 | * the buffer is complete or is actively being read from. | ||
4693 | * | ||
4694 | * Record buf_count of last buffer with zero count starting | ||
4695 | * from current ring position. buf_count is mirror | ||
4696 | * copy of count and is not cleared by serial controller. | ||
4697 | * If DMA controller is active, that buffer is actively | ||
4698 | * being read so add to total. | ||
4699 | */ | ||
4700 | do { | ||
4701 | count = desc_count(info->tbufs[i]); | ||
4702 | if (count) | ||
4703 | total_count += count; | ||
4704 | else if (!total_count) | ||
4705 | active_buf_count = info->tbufs[i].buf_count; | ||
4706 | if (++i == info->tbuf_count) | ||
4707 | i = 0; | ||
4708 | } while (i != info->tbuf_current); | ||
4709 | |||
4710 | /* read tx DMA status register */ | ||
4711 | reg_value = rd_reg32(info, TDCSR); | ||
4712 | |||
4713 | /* if tx DMA active, last zero count buffer is in use */ | ||
4714 | if (reg_value & BIT0) | ||
4715 | total_count += active_buf_count; | ||
4716 | |||
4717 | /* add tx FIFO count = reg_value[15..8] */ | ||
4718 | total_count += (reg_value >> 8) & 0xff; | ||
4719 | |||
4720 | /* if transmitter active add one byte for shift register */ | ||
4721 | if (info->tx_active) | ||
4722 | total_count++; | ||
4723 | |||
4724 | return total_count; | ||
4725 | } | ||
4726 | |||
4727 | /* | ||
4674 | * load transmit DMA buffer(s) with data | 4728 | * load transmit DMA buffer(s) with data |
4675 | */ | 4729 | */ |
4676 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | 4730 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) |
@@ -4708,6 +4762,7 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | |||
4708 | set_desc_eof(*d, 0); | 4762 | set_desc_eof(*d, 0); |
4709 | 4763 | ||
4710 | set_desc_count(*d, count); | 4764 | set_desc_count(*d, count); |
4765 | d->buf_count = count; | ||
4711 | } | 4766 | } |
4712 | 4767 | ||
4713 | info->tbuf_current = i; | 4768 | info->tbuf_current = i; |