diff options
Diffstat (limited to 'drivers/char/synclink_gt.c')
-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 |