diff options
| -rw-r--r-- | drivers/char/synclink_gt.c | 72 |
1 files changed, 30 insertions, 42 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 1386625fc4ca..a2e67e6df3a1 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
| @@ -467,7 +467,6 @@ static unsigned int free_tbuf_count(struct slgt_info *info); | |||
| 467 | static unsigned int tbuf_bytes(struct slgt_info *info); | 467 | static unsigned int tbuf_bytes(struct slgt_info *info); |
| 468 | static void reset_tbufs(struct slgt_info *info); | 468 | static void reset_tbufs(struct slgt_info *info); |
| 469 | static void tdma_reset(struct slgt_info *info); | 469 | static void tdma_reset(struct slgt_info *info); |
| 470 | static void tdma_start(struct slgt_info *info); | ||
| 471 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); | 470 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int count); |
| 472 | 471 | ||
| 473 | static void get_signals(struct slgt_info *info); | 472 | static void get_signals(struct slgt_info *info); |
| @@ -795,6 +794,18 @@ static void set_termios(struct tty_struct *tty, struct ktermios *old_termios) | |||
| 795 | } | 794 | } |
| 796 | } | 795 | } |
| 797 | 796 | ||
| 797 | static void update_tx_timer(struct slgt_info *info) | ||
| 798 | { | ||
| 799 | /* | ||
| 800 | * use worst case speed of 1200bps to calculate transmit timeout | ||
| 801 | * based on data in buffers (tbuf_bytes) and FIFO (128 bytes) | ||
| 802 | */ | ||
| 803 | if (info->params.mode == MGSL_MODE_HDLC) { | ||
| 804 | int timeout = (tbuf_bytes(info) * 7) + 1000; | ||
| 805 | mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(timeout)); | ||
| 806 | } | ||
| 807 | } | ||
| 808 | |||
| 798 | static int write(struct tty_struct *tty, | 809 | static int write(struct tty_struct *tty, |
| 799 | const unsigned char *buf, int count) | 810 | const unsigned char *buf, int count) |
| 800 | { | 811 | { |
| @@ -838,8 +849,18 @@ start: | |||
| 838 | spin_lock_irqsave(&info->lock,flags); | 849 | spin_lock_irqsave(&info->lock,flags); |
| 839 | if (!info->tx_active) | 850 | if (!info->tx_active) |
| 840 | tx_start(info); | 851 | tx_start(info); |
| 841 | else | 852 | else if (!(rd_reg32(info, TDCSR) & BIT0)) { |
| 842 | tdma_start(info); | 853 | /* transmit still active but transmit DMA stopped */ |
| 854 | unsigned int i = info->tbuf_current; | ||
| 855 | if (!i) | ||
| 856 | i = info->tbuf_count; | ||
| 857 | i--; | ||
| 858 | /* if DMA buf unsent must try later after tx idle */ | ||
| 859 | if (desc_count(info->tbufs[i])) | ||
| 860 | ret = 0; | ||
| 861 | } | ||
| 862 | if (ret > 0) | ||
| 863 | update_tx_timer(info); | ||
| 843 | spin_unlock_irqrestore(&info->lock,flags); | 864 | spin_unlock_irqrestore(&info->lock,flags); |
| 844 | } | 865 | } |
| 845 | 866 | ||
| @@ -1502,10 +1523,9 @@ static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 1502 | /* save start time for transmit timeout detection */ | 1523 | /* save start time for transmit timeout detection */ |
| 1503 | dev->trans_start = jiffies; | 1524 | dev->trans_start = jiffies; |
| 1504 | 1525 | ||
| 1505 | /* start hardware transmitter if necessary */ | ||
| 1506 | spin_lock_irqsave(&info->lock,flags); | 1526 | spin_lock_irqsave(&info->lock,flags); |
| 1507 | if (!info->tx_active) | 1527 | tx_start(info); |
| 1508 | tx_start(info); | 1528 | update_tx_timer(info); |
| 1509 | spin_unlock_irqrestore(&info->lock,flags); | 1529 | spin_unlock_irqrestore(&info->lock,flags); |
| 1510 | 1530 | ||
| 1511 | return 0; | 1531 | return 0; |
| @@ -3946,50 +3966,19 @@ static void tx_start(struct slgt_info *info) | |||
| 3946 | slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); | 3966 | slgt_irq_on(info, IRQ_TXUNDER + IRQ_TXIDLE); |
| 3947 | /* clear tx idle and underrun status bits */ | 3967 | /* clear tx idle and underrun status bits */ |
| 3948 | wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); | 3968 | wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER)); |
| 3949 | if (info->params.mode == MGSL_MODE_HDLC) | ||
| 3950 | mod_timer(&info->tx_timer, jiffies + | ||
| 3951 | msecs_to_jiffies(5000)); | ||
| 3952 | } else { | 3969 | } else { |
| 3953 | slgt_irq_off(info, IRQ_TXDATA); | 3970 | slgt_irq_off(info, IRQ_TXDATA); |
| 3954 | slgt_irq_on(info, IRQ_TXIDLE); | 3971 | slgt_irq_on(info, IRQ_TXIDLE); |
| 3955 | /* clear tx idle status bit */ | 3972 | /* clear tx idle status bit */ |
| 3956 | wr_reg16(info, SSR, IRQ_TXIDLE); | 3973 | wr_reg16(info, SSR, IRQ_TXIDLE); |
| 3957 | } | 3974 | } |
| 3958 | tdma_start(info); | 3975 | /* set 1st descriptor address and start DMA */ |
| 3976 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | ||
| 3977 | wr_reg32(info, TDCSR, BIT2 + BIT0); | ||
| 3959 | info->tx_active = true; | 3978 | info->tx_active = true; |
| 3960 | } | 3979 | } |
| 3961 | } | 3980 | } |
| 3962 | 3981 | ||
| 3963 | /* | ||
| 3964 | * start transmit DMA if inactive and there are unsent buffers | ||
| 3965 | */ | ||
| 3966 | static void tdma_start(struct slgt_info *info) | ||
| 3967 | { | ||
| 3968 | unsigned int i; | ||
| 3969 | |||
| 3970 | if (rd_reg32(info, TDCSR) & BIT0) | ||
| 3971 | return; | ||
| 3972 | |||
| 3973 | /* transmit DMA inactive, check for unsent buffers */ | ||
| 3974 | i = info->tbuf_start; | ||
| 3975 | while (!desc_count(info->tbufs[i])) { | ||
| 3976 | if (++i == info->tbuf_count) | ||
| 3977 | i = 0; | ||
| 3978 | if (i == info->tbuf_current) | ||
| 3979 | return; | ||
| 3980 | } | ||
| 3981 | info->tbuf_start = i; | ||
| 3982 | |||
| 3983 | /* there are unsent buffers, start transmit DMA */ | ||
| 3984 | |||
| 3985 | /* reset needed if previous error condition */ | ||
| 3986 | tdma_reset(info); | ||
| 3987 | |||
| 3988 | /* set 1st descriptor address */ | ||
| 3989 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | ||
| 3990 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ | ||
| 3991 | } | ||
| 3992 | |||
| 3993 | static void tx_stop(struct slgt_info *info) | 3982 | static void tx_stop(struct slgt_info *info) |
| 3994 | { | 3983 | { |
| 3995 | unsigned short val; | 3984 | unsigned short val; |
| @@ -5004,8 +4993,7 @@ static void tx_timeout(unsigned long context) | |||
| 5004 | info->icount.txtimeout++; | 4993 | info->icount.txtimeout++; |
| 5005 | } | 4994 | } |
| 5006 | spin_lock_irqsave(&info->lock,flags); | 4995 | spin_lock_irqsave(&info->lock,flags); |
| 5007 | info->tx_active = false; | 4996 | tx_stop(info); |
| 5008 | info->tx_count = 0; | ||
| 5009 | spin_unlock_irqrestore(&info->lock,flags); | 4997 | spin_unlock_irqrestore(&info->lock,flags); |
| 5010 | 4998 | ||
| 5011 | #if SYNCLINK_GENERIC_HDLC | 4999 | #if SYNCLINK_GENERIC_HDLC |
