diff options
Diffstat (limited to 'drivers/char/synclink_gt.c')
-rw-r--r-- | drivers/char/synclink_gt.c | 154 |
1 files changed, 105 insertions, 49 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 88083b066261..509c89ac5bd3 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -162,7 +162,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v | |||
162 | static int chars_in_buffer(struct tty_struct *tty); | 162 | static int chars_in_buffer(struct tty_struct *tty); |
163 | static void throttle(struct tty_struct * tty); | 163 | static void throttle(struct tty_struct * tty); |
164 | static void unthrottle(struct tty_struct * tty); | 164 | static void unthrottle(struct tty_struct * tty); |
165 | static void set_break(struct tty_struct *tty, int break_state); | 165 | static int set_break(struct tty_struct *tty, int break_state); |
166 | 166 | ||
167 | /* | 167 | /* |
168 | * generic HDLC support and callbacks | 168 | * generic HDLC support and callbacks |
@@ -211,6 +211,7 @@ struct slgt_desc | |||
211 | char *buf; /* virtual address of data buffer */ | 211 | char *buf; /* virtual address of data buffer */ |
212 | unsigned int pdesc; /* physical address of this descriptor */ | 212 | unsigned int pdesc; /* physical address of this descriptor */ |
213 | dma_addr_t buf_dma_addr; | 213 | dma_addr_t buf_dma_addr; |
214 | unsigned short buf_count; | ||
214 | }; | 215 | }; |
215 | 216 | ||
216 | #define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) | 217 | #define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b)) |
@@ -299,7 +300,7 @@ struct slgt_info { | |||
299 | u32 idle_mode; | 300 | u32 idle_mode; |
300 | u32 max_frame_size; /* as set by device config */ | 301 | u32 max_frame_size; /* as set by device config */ |
301 | 302 | ||
302 | unsigned int raw_rx_size; | 303 | unsigned int rbuf_fill_level; |
303 | unsigned int if_mode; | 304 | unsigned int if_mode; |
304 | 305 | ||
305 | /* device status */ | 306 | /* device status */ |
@@ -462,6 +463,7 @@ static void tx_start(struct slgt_info *info); | |||
462 | static void tx_stop(struct slgt_info *info); | 463 | static void tx_stop(struct slgt_info *info); |
463 | static void tx_set_idle(struct slgt_info *info); | 464 | static void tx_set_idle(struct slgt_info *info); |
464 | static unsigned int free_tbuf_count(struct slgt_info *info); | 465 | static unsigned int free_tbuf_count(struct slgt_info *info); |
466 | static unsigned int tbuf_bytes(struct slgt_info *info); | ||
465 | static void reset_tbufs(struct slgt_info *info); | 467 | static void reset_tbufs(struct slgt_info *info); |
466 | static void tdma_reset(struct slgt_info *info); | 468 | static void tdma_reset(struct slgt_info *info); |
467 | static void tdma_start(struct slgt_info *info); | 469 | static void tdma_start(struct slgt_info *info); |
@@ -509,7 +511,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); | |||
509 | static int tiocmget(struct tty_struct *tty, struct file *file); | 511 | static int tiocmget(struct tty_struct *tty, struct file *file); |
510 | static int tiocmset(struct tty_struct *tty, struct file *file, | 512 | static int tiocmset(struct tty_struct *tty, struct file *file, |
511 | unsigned int set, unsigned int clear); | 513 | unsigned int set, unsigned int clear); |
512 | static void set_break(struct tty_struct *tty, int break_state); | 514 | static int set_break(struct tty_struct *tty, int break_state); |
513 | static int get_interface(struct slgt_info *info, int __user *if_mode); | 515 | static int get_interface(struct slgt_info *info, int __user *if_mode); |
514 | static int set_interface(struct slgt_info *info, int if_mode); | 516 | static int set_interface(struct slgt_info *info, int if_mode); |
515 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | 517 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); |
@@ -845,6 +847,7 @@ static int write(struct tty_struct *tty, | |||
845 | int ret = 0; | 847 | int ret = 0; |
846 | struct slgt_info *info = tty->driver_data; | 848 | struct slgt_info *info = tty->driver_data; |
847 | unsigned long flags; | 849 | unsigned long flags; |
850 | unsigned int bufs_needed; | ||
848 | 851 | ||
849 | if (sanity_check(info, tty->name, "write")) | 852 | if (sanity_check(info, tty->name, "write")) |
850 | goto cleanup; | 853 | goto cleanup; |
@@ -861,25 +864,16 @@ static int write(struct tty_struct *tty, | |||
861 | if (!count) | 864 | if (!count) |
862 | goto cleanup; | 865 | goto cleanup; |
863 | 866 | ||
864 | if (info->params.mode == MGSL_MODE_RAW || | 867 | if (!info->tx_active && info->tx_count) { |
865 | info->params.mode == MGSL_MODE_MONOSYNC || | 868 | /* send accumulated data from send_char() */ |
866 | info->params.mode == MGSL_MODE_BISYNC) { | 869 | tx_load(info, info->tx_buf, info->tx_count); |
867 | unsigned int bufs_needed = (count/DMABUFSIZE); | 870 | goto start; |
868 | unsigned int bufs_free = free_tbuf_count(info); | ||
869 | if (count % DMABUFSIZE) | ||
870 | ++bufs_needed; | ||
871 | if (bufs_needed > bufs_free) | ||
872 | goto cleanup; | ||
873 | } else { | ||
874 | if (info->tx_active) | ||
875 | goto cleanup; | ||
876 | if (info->tx_count) { | ||
877 | /* send accumulated data from send_char() calls */ | ||
878 | /* as frame and wait before accepting more data. */ | ||
879 | tx_load(info, info->tx_buf, info->tx_count); | ||
880 | goto start; | ||
881 | } | ||
882 | } | 871 | } |
872 | bufs_needed = (count/DMABUFSIZE); | ||
873 | if (count % DMABUFSIZE) | ||
874 | ++bufs_needed; | ||
875 | if (bufs_needed > free_tbuf_count(info)) | ||
876 | goto cleanup; | ||
883 | 877 | ||
884 | ret = info->tx_count = count; | 878 | ret = info->tx_count = count; |
885 | tx_load(info, buf, count); | 879 | tx_load(info, buf, count); |
@@ -1392,10 +1386,12 @@ done: | |||
1392 | static int chars_in_buffer(struct tty_struct *tty) | 1386 | static int chars_in_buffer(struct tty_struct *tty) |
1393 | { | 1387 | { |
1394 | struct slgt_info *info = tty->driver_data; | 1388 | struct slgt_info *info = tty->driver_data; |
1389 | int count; | ||
1395 | if (sanity_check(info, tty->name, "chars_in_buffer")) | 1390 | if (sanity_check(info, tty->name, "chars_in_buffer")) |
1396 | return 0; | 1391 | return 0; |
1397 | DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count)); | 1392 | count = tbuf_bytes(info); |
1398 | return info->tx_count; | 1393 | DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count)); |
1394 | return count; | ||
1399 | } | 1395 | } |
1400 | 1396 | ||
1401 | /* | 1397 | /* |
@@ -1448,14 +1444,14 @@ static void unthrottle(struct tty_struct * tty) | |||
1448 | * set or clear transmit break condition | 1444 | * set or clear transmit break condition |
1449 | * break_state -1=set break condition, 0=clear | 1445 | * break_state -1=set break condition, 0=clear |
1450 | */ | 1446 | */ |
1451 | static void set_break(struct tty_struct *tty, int break_state) | 1447 | static int set_break(struct tty_struct *tty, int break_state) |
1452 | { | 1448 | { |
1453 | struct slgt_info *info = tty->driver_data; | 1449 | struct slgt_info *info = tty->driver_data; |
1454 | unsigned short value; | 1450 | unsigned short value; |
1455 | unsigned long flags; | 1451 | unsigned long flags; |
1456 | 1452 | ||
1457 | if (sanity_check(info, tty->name, "set_break")) | 1453 | if (sanity_check(info, tty->name, "set_break")) |
1458 | return; | 1454 | return -EINVAL; |
1459 | DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); | 1455 | DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); |
1460 | 1456 | ||
1461 | spin_lock_irqsave(&info->lock,flags); | 1457 | spin_lock_irqsave(&info->lock,flags); |
@@ -1466,6 +1462,7 @@ static void set_break(struct tty_struct *tty, int break_state) | |||
1466 | value &= ~BIT6; | 1462 | value &= ~BIT6; |
1467 | wr_reg16(info, TCR, value); | 1463 | wr_reg16(info, TCR, value); |
1468 | spin_unlock_irqrestore(&info->lock,flags); | 1464 | spin_unlock_irqrestore(&info->lock,flags); |
1465 | return 0; | ||
1469 | } | 1466 | } |
1470 | 1467 | ||
1471 | #if SYNCLINK_GENERIC_HDLC | 1468 | #if SYNCLINK_GENERIC_HDLC |
@@ -2675,8 +2672,31 @@ static int tx_abort(struct slgt_info *info) | |||
2675 | static int rx_enable(struct slgt_info *info, int enable) | 2672 | static int rx_enable(struct slgt_info *info, int enable) |
2676 | { | 2673 | { |
2677 | unsigned long flags; | 2674 | unsigned long flags; |
2678 | DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable)); | 2675 | unsigned int rbuf_fill_level; |
2676 | DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable)); | ||
2679 | spin_lock_irqsave(&info->lock,flags); | 2677 | spin_lock_irqsave(&info->lock,flags); |
2678 | /* | ||
2679 | * enable[31..16] = receive DMA buffer fill level | ||
2680 | * 0 = noop (leave fill level unchanged) | ||
2681 | * fill level must be multiple of 4 and <= buffer size | ||
2682 | */ | ||
2683 | rbuf_fill_level = ((unsigned int)enable) >> 16; | ||
2684 | if (rbuf_fill_level) { | ||
2685 | if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) { | ||
2686 | spin_unlock_irqrestore(&info->lock, flags); | ||
2687 | return -EINVAL; | ||
2688 | } | ||
2689 | info->rbuf_fill_level = rbuf_fill_level; | ||
2690 | rx_stop(info); /* restart receiver to use new fill level */ | ||
2691 | } | ||
2692 | |||
2693 | /* | ||
2694 | * enable[1..0] = receiver enable command | ||
2695 | * 0 = disable | ||
2696 | * 1 = enable | ||
2697 | * 2 = enable or force hunt mode if already enabled | ||
2698 | */ | ||
2699 | enable &= 3; | ||
2680 | if (enable) { | 2700 | if (enable) { |
2681 | if (!info->rx_enabled) | 2701 | if (!info->rx_enabled) |
2682 | rx_start(info); | 2702 | rx_start(info); |
@@ -3442,7 +3462,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev | |||
3442 | info->magic = MGSL_MAGIC; | 3462 | info->magic = MGSL_MAGIC; |
3443 | INIT_WORK(&info->task, bh_handler); | 3463 | INIT_WORK(&info->task, bh_handler); |
3444 | info->max_frame_size = 4096; | 3464 | info->max_frame_size = 4096; |
3445 | info->raw_rx_size = DMABUFSIZE; | 3465 | info->rbuf_fill_level = DMABUFSIZE; |
3446 | info->port.close_delay = 5*HZ/10; | 3466 | info->port.close_delay = 5*HZ/10; |
3447 | info->port.closing_wait = 30*HZ; | 3467 | info->port.closing_wait = 30*HZ; |
3448 | init_waitqueue_head(&info->status_event_wait_q); | 3468 | init_waitqueue_head(&info->status_event_wait_q); |
@@ -3929,15 +3949,7 @@ static void tdma_start(struct slgt_info *info) | |||
3929 | 3949 | ||
3930 | /* set 1st descriptor address */ | 3950 | /* set 1st descriptor address */ |
3931 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | 3951 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); |
3932 | switch(info->params.mode) { | 3952 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ |
3933 | case MGSL_MODE_RAW: | ||
3934 | case MGSL_MODE_MONOSYNC: | ||
3935 | case MGSL_MODE_BISYNC: | ||
3936 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ | ||
3937 | break; | ||
3938 | default: | ||
3939 | wr_reg32(info, TDCSR, BIT0); /* DMA enable */ | ||
3940 | } | ||
3941 | } | 3953 | } |
3942 | 3954 | ||
3943 | static void tx_stop(struct slgt_info *info) | 3955 | static void tx_stop(struct slgt_info *info) |
@@ -4140,7 +4152,7 @@ static void sync_mode(struct slgt_info *info) | |||
4140 | * 01 enable | 4152 | * 01 enable |
4141 | * 00 auto-CTS enable | 4153 | * 00 auto-CTS enable |
4142 | */ | 4154 | */ |
4143 | val = 0; | 4155 | val = BIT2; |
4144 | 4156 | ||
4145 | switch(info->params.mode) { | 4157 | switch(info->params.mode) { |
4146 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; | 4158 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; |
@@ -4413,6 +4425,8 @@ static void msc_set_vcr(struct slgt_info *info) | |||
4413 | break; | 4425 | break; |
4414 | } | 4426 | } |
4415 | 4427 | ||
4428 | if (info->if_mode & MGSL_INTERFACE_MSB_FIRST) | ||
4429 | val |= BIT4; | ||
4416 | if (info->signals & SerialSignal_DTR) | 4430 | if (info->signals & SerialSignal_DTR) |
4417 | val |= BIT3; | 4431 | val |= BIT3; |
4418 | if (info->signals & SerialSignal_RTS) | 4432 | if (info->signals & SerialSignal_RTS) |
@@ -4451,16 +4465,7 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last | |||
4451 | while(!done) { | 4465 | while(!done) { |
4452 | /* reset current buffer for reuse */ | 4466 | /* reset current buffer for reuse */ |
4453 | info->rbufs[i].status = 0; | 4467 | info->rbufs[i].status = 0; |
4454 | switch(info->params.mode) { | 4468 | set_desc_count(info->rbufs[i], info->rbuf_fill_level); |
4455 | case MGSL_MODE_RAW: | ||
4456 | case MGSL_MODE_MONOSYNC: | ||
4457 | case MGSL_MODE_BISYNC: | ||
4458 | set_desc_count(info->rbufs[i], info->raw_rx_size); | ||
4459 | break; | ||
4460 | default: | ||
4461 | set_desc_count(info->rbufs[i], DMABUFSIZE); | ||
4462 | } | ||
4463 | |||
4464 | if (i == last) | 4469 | if (i == last) |
4465 | done = 1; | 4470 | done = 1; |
4466 | if (++i == info->rbuf_count) | 4471 | if (++i == info->rbuf_count) |
@@ -4567,7 +4572,7 @@ check_again: | |||
4567 | 4572 | ||
4568 | DBGBH(("%s rx frame status=%04X size=%d\n", | 4573 | DBGBH(("%s rx frame status=%04X size=%d\n", |
4569 | info->device_name, status, framesize)); | 4574 | info->device_name, status, framesize)); |
4570 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); | 4575 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx"); |
4571 | 4576 | ||
4572 | if (framesize) { | 4577 | if (framesize) { |
4573 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { | 4578 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { |
@@ -4587,7 +4592,7 @@ check_again: | |||
4587 | info->icount.rxok++; | 4592 | info->icount.rxok++; |
4588 | 4593 | ||
4589 | while(copy_count) { | 4594 | while(copy_count) { |
4590 | int partial_count = min(copy_count, DMABUFSIZE); | 4595 | int partial_count = min_t(int, copy_count, info->rbuf_fill_level); |
4591 | memcpy(p, info->rbufs[i].buf, partial_count); | 4596 | memcpy(p, info->rbufs[i].buf, partial_count); |
4592 | p += partial_count; | 4597 | p += partial_count; |
4593 | copy_count -= partial_count; | 4598 | copy_count -= partial_count; |
@@ -4679,6 +4684,56 @@ static unsigned int free_tbuf_count(struct slgt_info *info) | |||
4679 | } | 4684 | } |
4680 | 4685 | ||
4681 | /* | 4686 | /* |
4687 | * return number of bytes in unsent transmit DMA buffers | ||
4688 | * and the serial controller tx FIFO | ||
4689 | */ | ||
4690 | static unsigned int tbuf_bytes(struct slgt_info *info) | ||
4691 | { | ||
4692 | unsigned int total_count = 0; | ||
4693 | unsigned int i = info->tbuf_current; | ||
4694 | unsigned int reg_value; | ||
4695 | unsigned int count; | ||
4696 | unsigned int active_buf_count = 0; | ||
4697 | |||
4698 | /* | ||
4699 | * Add descriptor counts for all tx DMA buffers. | ||
4700 | * If count is zero (cleared by DMA controller after read), | ||
4701 | * the buffer is complete or is actively being read from. | ||
4702 | * | ||
4703 | * Record buf_count of last buffer with zero count starting | ||
4704 | * from current ring position. buf_count is mirror | ||
4705 | * copy of count and is not cleared by serial controller. | ||
4706 | * If DMA controller is active, that buffer is actively | ||
4707 | * being read so add to total. | ||
4708 | */ | ||
4709 | do { | ||
4710 | count = desc_count(info->tbufs[i]); | ||
4711 | if (count) | ||
4712 | total_count += count; | ||
4713 | else if (!total_count) | ||
4714 | active_buf_count = info->tbufs[i].buf_count; | ||
4715 | if (++i == info->tbuf_count) | ||
4716 | i = 0; | ||
4717 | } while (i != info->tbuf_current); | ||
4718 | |||
4719 | /* read tx DMA status register */ | ||
4720 | reg_value = rd_reg32(info, TDCSR); | ||
4721 | |||
4722 | /* if tx DMA active, last zero count buffer is in use */ | ||
4723 | if (reg_value & BIT0) | ||
4724 | total_count += active_buf_count; | ||
4725 | |||
4726 | /* add tx FIFO count = reg_value[15..8] */ | ||
4727 | total_count += (reg_value >> 8) & 0xff; | ||
4728 | |||
4729 | /* if transmitter active add one byte for shift register */ | ||
4730 | if (info->tx_active) | ||
4731 | total_count++; | ||
4732 | |||
4733 | return total_count; | ||
4734 | } | ||
4735 | |||
4736 | /* | ||
4682 | * load transmit DMA buffer(s) with data | 4737 | * load transmit DMA buffer(s) with data |
4683 | */ | 4738 | */ |
4684 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | 4739 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) |
@@ -4716,6 +4771,7 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | |||
4716 | set_desc_eof(*d, 0); | 4771 | set_desc_eof(*d, 0); |
4717 | 4772 | ||
4718 | set_desc_count(*d, count); | 4773 | set_desc_count(*d, count); |
4774 | d->buf_count = count; | ||
4719 | } | 4775 | } |
4720 | 4776 | ||
4721 | info->tbuf_current = i; | 4777 | info->tbuf_current = i; |