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; |
