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 2c3e43bb2cc9..3e9058993e41 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
@@ -165,7 +165,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v | |||
165 | static int chars_in_buffer(struct tty_struct *tty); | 165 | static int chars_in_buffer(struct tty_struct *tty); |
166 | static void throttle(struct tty_struct * tty); | 166 | static void throttle(struct tty_struct * tty); |
167 | static void unthrottle(struct tty_struct * tty); | 167 | static void unthrottle(struct tty_struct * tty); |
168 | static void set_break(struct tty_struct *tty, int break_state); | 168 | static int set_break(struct tty_struct *tty, int break_state); |
169 | 169 | ||
170 | /* | 170 | /* |
171 | * generic HDLC support and callbacks | 171 | * generic HDLC support and callbacks |
@@ -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)) |
@@ -302,7 +303,7 @@ struct slgt_info { | |||
302 | u32 idle_mode; | 303 | u32 idle_mode; |
303 | u32 max_frame_size; /* as set by device config */ | 304 | u32 max_frame_size; /* as set by device config */ |
304 | 305 | ||
305 | unsigned int raw_rx_size; | 306 | unsigned int rbuf_fill_level; |
306 | unsigned int if_mode; | 307 | unsigned int if_mode; |
307 | 308 | ||
308 | /* device status */ | 309 | /* device status */ |
@@ -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); |
@@ -513,7 +515,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); | |||
513 | static int tiocmget(struct tty_struct *tty, struct file *file); | 515 | static int tiocmget(struct tty_struct *tty, struct file *file); |
514 | static int tiocmset(struct tty_struct *tty, struct file *file, | 516 | static int tiocmset(struct tty_struct *tty, struct file *file, |
515 | unsigned int set, unsigned int clear); | 517 | unsigned int set, unsigned int clear); |
516 | static void set_break(struct tty_struct *tty, int break_state); | 518 | static int set_break(struct tty_struct *tty, int break_state); |
517 | static int get_interface(struct slgt_info *info, int __user *if_mode); | 519 | static int get_interface(struct slgt_info *info, int __user *if_mode); |
518 | static int set_interface(struct slgt_info *info, int if_mode); | 520 | static int set_interface(struct slgt_info *info, int if_mode); |
519 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); | 521 | static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); |
@@ -849,6 +851,7 @@ static int write(struct tty_struct *tty, | |||
849 | int ret = 0; | 851 | int ret = 0; |
850 | struct slgt_info *info = tty->driver_data; | 852 | struct slgt_info *info = tty->driver_data; |
851 | unsigned long flags; | 853 | unsigned long flags; |
854 | unsigned int bufs_needed; | ||
852 | 855 | ||
853 | if (sanity_check(info, tty->name, "write")) | 856 | if (sanity_check(info, tty->name, "write")) |
854 | goto cleanup; | 857 | goto cleanup; |
@@ -865,25 +868,16 @@ static int write(struct tty_struct *tty, | |||
865 | if (!count) | 868 | if (!count) |
866 | goto cleanup; | 869 | goto cleanup; |
867 | 870 | ||
868 | if (info->params.mode == MGSL_MODE_RAW || | 871 | if (!info->tx_active && info->tx_count) { |
869 | info->params.mode == MGSL_MODE_MONOSYNC || | 872 | /* send accumulated data from send_char() */ |
870 | info->params.mode == MGSL_MODE_BISYNC) { | 873 | tx_load(info, info->tx_buf, info->tx_count); |
871 | unsigned int bufs_needed = (count/DMABUFSIZE); | 874 | goto start; |
872 | unsigned int bufs_free = free_tbuf_count(info); | ||
873 | if (count % DMABUFSIZE) | ||
874 | ++bufs_needed; | ||
875 | if (bufs_needed > bufs_free) | ||
876 | goto cleanup; | ||
877 | } else { | ||
878 | if (info->tx_active) | ||
879 | goto cleanup; | ||
880 | if (info->tx_count) { | ||
881 | /* send accumulated data from send_char() calls */ | ||
882 | /* as frame and wait before accepting more data. */ | ||
883 | tx_load(info, info->tx_buf, info->tx_count); | ||
884 | goto start; | ||
885 | } | ||
886 | } | 875 | } |
876 | bufs_needed = (count/DMABUFSIZE); | ||
877 | if (count % DMABUFSIZE) | ||
878 | ++bufs_needed; | ||
879 | if (bufs_needed > free_tbuf_count(info)) | ||
880 | goto cleanup; | ||
887 | 881 | ||
888 | ret = info->tx_count = count; | 882 | ret = info->tx_count = count; |
889 | tx_load(info, buf, count); | 883 | tx_load(info, buf, count); |
@@ -1396,10 +1390,12 @@ done: | |||
1396 | static int chars_in_buffer(struct tty_struct *tty) | 1390 | static int chars_in_buffer(struct tty_struct *tty) |
1397 | { | 1391 | { |
1398 | struct slgt_info *info = tty->driver_data; | 1392 | struct slgt_info *info = tty->driver_data; |
1393 | int count; | ||
1399 | if (sanity_check(info, tty->name, "chars_in_buffer")) | 1394 | if (sanity_check(info, tty->name, "chars_in_buffer")) |
1400 | return 0; | 1395 | return 0; |
1401 | DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, info->tx_count)); | 1396 | count = tbuf_bytes(info); |
1402 | return info->tx_count; | 1397 | DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count)); |
1398 | return count; | ||
1403 | } | 1399 | } |
1404 | 1400 | ||
1405 | /* | 1401 | /* |
@@ -1452,14 +1448,14 @@ static void unthrottle(struct tty_struct * tty) | |||
1452 | * set or clear transmit break condition | 1448 | * set or clear transmit break condition |
1453 | * break_state -1=set break condition, 0=clear | 1449 | * break_state -1=set break condition, 0=clear |
1454 | */ | 1450 | */ |
1455 | static void set_break(struct tty_struct *tty, int break_state) | 1451 | static int set_break(struct tty_struct *tty, int break_state) |
1456 | { | 1452 | { |
1457 | struct slgt_info *info = tty->driver_data; | 1453 | struct slgt_info *info = tty->driver_data; |
1458 | unsigned short value; | 1454 | unsigned short value; |
1459 | unsigned long flags; | 1455 | unsigned long flags; |
1460 | 1456 | ||
1461 | if (sanity_check(info, tty->name, "set_break")) | 1457 | if (sanity_check(info, tty->name, "set_break")) |
1462 | return; | 1458 | return -EINVAL; |
1463 | DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); | 1459 | DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); |
1464 | 1460 | ||
1465 | spin_lock_irqsave(&info->lock,flags); | 1461 | spin_lock_irqsave(&info->lock,flags); |
@@ -1470,6 +1466,7 @@ static void set_break(struct tty_struct *tty, int break_state) | |||
1470 | value &= ~BIT6; | 1466 | value &= ~BIT6; |
1471 | wr_reg16(info, TCR, value); | 1467 | wr_reg16(info, TCR, value); |
1472 | spin_unlock_irqrestore(&info->lock,flags); | 1468 | spin_unlock_irqrestore(&info->lock,flags); |
1469 | return 0; | ||
1473 | } | 1470 | } |
1474 | 1471 | ||
1475 | #if SYNCLINK_GENERIC_HDLC | 1472 | #if SYNCLINK_GENERIC_HDLC |
@@ -2679,8 +2676,31 @@ static int tx_abort(struct slgt_info *info) | |||
2679 | static int rx_enable(struct slgt_info *info, int enable) | 2676 | static int rx_enable(struct slgt_info *info, int enable) |
2680 | { | 2677 | { |
2681 | unsigned long flags; | 2678 | unsigned long flags; |
2682 | DBGINFO(("%s rx_enable(%d)\n", info->device_name, enable)); | 2679 | unsigned int rbuf_fill_level; |
2680 | DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable)); | ||
2683 | spin_lock_irqsave(&info->lock,flags); | 2681 | spin_lock_irqsave(&info->lock,flags); |
2682 | /* | ||
2683 | * enable[31..16] = receive DMA buffer fill level | ||
2684 | * 0 = noop (leave fill level unchanged) | ||
2685 | * fill level must be multiple of 4 and <= buffer size | ||
2686 | */ | ||
2687 | rbuf_fill_level = ((unsigned int)enable) >> 16; | ||
2688 | if (rbuf_fill_level) { | ||
2689 | if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) { | ||
2690 | spin_unlock_irqrestore(&info->lock, flags); | ||
2691 | return -EINVAL; | ||
2692 | } | ||
2693 | info->rbuf_fill_level = rbuf_fill_level; | ||
2694 | rx_stop(info); /* restart receiver to use new fill level */ | ||
2695 | } | ||
2696 | |||
2697 | /* | ||
2698 | * enable[1..0] = receiver enable command | ||
2699 | * 0 = disable | ||
2700 | * 1 = enable | ||
2701 | * 2 = enable or force hunt mode if already enabled | ||
2702 | */ | ||
2703 | enable &= 3; | ||
2684 | if (enable) { | 2704 | if (enable) { |
2685 | if (!info->rx_enabled) | 2705 | if (!info->rx_enabled) |
2686 | rx_start(info); | 2706 | rx_start(info); |
@@ -3447,7 +3467,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev | |||
3447 | info->magic = MGSL_MAGIC; | 3467 | info->magic = MGSL_MAGIC; |
3448 | INIT_WORK(&info->task, bh_handler); | 3468 | INIT_WORK(&info->task, bh_handler); |
3449 | info->max_frame_size = 4096; | 3469 | info->max_frame_size = 4096; |
3450 | info->raw_rx_size = DMABUFSIZE; | 3470 | info->rbuf_fill_level = DMABUFSIZE; |
3451 | info->port.close_delay = 5*HZ/10; | 3471 | info->port.close_delay = 5*HZ/10; |
3452 | info->port.closing_wait = 30*HZ; | 3472 | info->port.closing_wait = 30*HZ; |
3453 | init_waitqueue_head(&info->status_event_wait_q); | 3473 | init_waitqueue_head(&info->status_event_wait_q); |
@@ -3934,15 +3954,7 @@ static void tdma_start(struct slgt_info *info) | |||
3934 | 3954 | ||
3935 | /* set 1st descriptor address */ | 3955 | /* set 1st descriptor address */ |
3936 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); | 3956 | wr_reg32(info, TDDAR, info->tbufs[info->tbuf_start].pdesc); |
3937 | switch(info->params.mode) { | 3957 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ |
3938 | case MGSL_MODE_RAW: | ||
3939 | case MGSL_MODE_MONOSYNC: | ||
3940 | case MGSL_MODE_BISYNC: | ||
3941 | wr_reg32(info, TDCSR, BIT2 + BIT0); /* IRQ + DMA enable */ | ||
3942 | break; | ||
3943 | default: | ||
3944 | wr_reg32(info, TDCSR, BIT0); /* DMA enable */ | ||
3945 | } | ||
3946 | } | 3958 | } |
3947 | 3959 | ||
3948 | static void tx_stop(struct slgt_info *info) | 3960 | static void tx_stop(struct slgt_info *info) |
@@ -4145,7 +4157,7 @@ static void sync_mode(struct slgt_info *info) | |||
4145 | * 01 enable | 4157 | * 01 enable |
4146 | * 00 auto-CTS enable | 4158 | * 00 auto-CTS enable |
4147 | */ | 4159 | */ |
4148 | val = 0; | 4160 | val = BIT2; |
4149 | 4161 | ||
4150 | switch(info->params.mode) { | 4162 | switch(info->params.mode) { |
4151 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; | 4163 | case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break; |
@@ -4418,6 +4430,8 @@ static void msc_set_vcr(struct slgt_info *info) | |||
4418 | break; | 4430 | break; |
4419 | } | 4431 | } |
4420 | 4432 | ||
4433 | if (info->if_mode & MGSL_INTERFACE_MSB_FIRST) | ||
4434 | val |= BIT4; | ||
4421 | if (info->signals & SerialSignal_DTR) | 4435 | if (info->signals & SerialSignal_DTR) |
4422 | val |= BIT3; | 4436 | val |= BIT3; |
4423 | if (info->signals & SerialSignal_RTS) | 4437 | if (info->signals & SerialSignal_RTS) |
@@ -4456,16 +4470,7 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last | |||
4456 | while(!done) { | 4470 | while(!done) { |
4457 | /* reset current buffer for reuse */ | 4471 | /* reset current buffer for reuse */ |
4458 | info->rbufs[i].status = 0; | 4472 | info->rbufs[i].status = 0; |
4459 | switch(info->params.mode) { | 4473 | set_desc_count(info->rbufs[i], info->rbuf_fill_level); |
4460 | case MGSL_MODE_RAW: | ||
4461 | case MGSL_MODE_MONOSYNC: | ||
4462 | case MGSL_MODE_BISYNC: | ||
4463 | set_desc_count(info->rbufs[i], info->raw_rx_size); | ||
4464 | break; | ||
4465 | default: | ||
4466 | set_desc_count(info->rbufs[i], DMABUFSIZE); | ||
4467 | } | ||
4468 | |||
4469 | if (i == last) | 4474 | if (i == last) |
4470 | done = 1; | 4475 | done = 1; |
4471 | if (++i == info->rbuf_count) | 4476 | if (++i == info->rbuf_count) |
@@ -4572,7 +4577,7 @@ check_again: | |||
4572 | 4577 | ||
4573 | DBGBH(("%s rx frame status=%04X size=%d\n", | 4578 | DBGBH(("%s rx frame status=%04X size=%d\n", |
4574 | info->device_name, status, framesize)); | 4579 | info->device_name, status, framesize)); |
4575 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); | 4580 | DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx"); |
4576 | 4581 | ||
4577 | if (framesize) { | 4582 | if (framesize) { |
4578 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { | 4583 | if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { |
@@ -4592,7 +4597,7 @@ check_again: | |||
4592 | info->icount.rxok++; | 4597 | info->icount.rxok++; |
4593 | 4598 | ||
4594 | while(copy_count) { | 4599 | while(copy_count) { |
4595 | int partial_count = min(copy_count, DMABUFSIZE); | 4600 | int partial_count = min_t(int, copy_count, info->rbuf_fill_level); |
4596 | memcpy(p, info->rbufs[i].buf, partial_count); | 4601 | memcpy(p, info->rbufs[i].buf, partial_count); |
4597 | p += partial_count; | 4602 | p += partial_count; |
4598 | copy_count -= partial_count; | 4603 | copy_count -= partial_count; |
@@ -4684,6 +4689,56 @@ static unsigned int free_tbuf_count(struct slgt_info *info) | |||
4684 | } | 4689 | } |
4685 | 4690 | ||
4686 | /* | 4691 | /* |
4692 | * return number of bytes in unsent transmit DMA buffers | ||
4693 | * and the serial controller tx FIFO | ||
4694 | */ | ||
4695 | static unsigned int tbuf_bytes(struct slgt_info *info) | ||
4696 | { | ||
4697 | unsigned int total_count = 0; | ||
4698 | unsigned int i = info->tbuf_current; | ||
4699 | unsigned int reg_value; | ||
4700 | unsigned int count; | ||
4701 | unsigned int active_buf_count = 0; | ||
4702 | |||
4703 | /* | ||
4704 | * Add descriptor counts for all tx DMA buffers. | ||
4705 | * If count is zero (cleared by DMA controller after read), | ||
4706 | * the buffer is complete or is actively being read from. | ||
4707 | * | ||
4708 | * Record buf_count of last buffer with zero count starting | ||
4709 | * from current ring position. buf_count is mirror | ||
4710 | * copy of count and is not cleared by serial controller. | ||
4711 | * If DMA controller is active, that buffer is actively | ||
4712 | * being read so add to total. | ||
4713 | */ | ||
4714 | do { | ||
4715 | count = desc_count(info->tbufs[i]); | ||
4716 | if (count) | ||
4717 | total_count += count; | ||
4718 | else if (!total_count) | ||
4719 | active_buf_count = info->tbufs[i].buf_count; | ||
4720 | if (++i == info->tbuf_count) | ||
4721 | i = 0; | ||
4722 | } while (i != info->tbuf_current); | ||
4723 | |||
4724 | /* read tx DMA status register */ | ||
4725 | reg_value = rd_reg32(info, TDCSR); | ||
4726 | |||
4727 | /* if tx DMA active, last zero count buffer is in use */ | ||
4728 | if (reg_value & BIT0) | ||
4729 | total_count += active_buf_count; | ||
4730 | |||
4731 | /* add tx FIFO count = reg_value[15..8] */ | ||
4732 | total_count += (reg_value >> 8) & 0xff; | ||
4733 | |||
4734 | /* if transmitter active add one byte for shift register */ | ||
4735 | if (info->tx_active) | ||
4736 | total_count++; | ||
4737 | |||
4738 | return total_count; | ||
4739 | } | ||
4740 | |||
4741 | /* | ||
4687 | * load transmit DMA buffer(s) with data | 4742 | * load transmit DMA buffer(s) with data |
4688 | */ | 4743 | */ |
4689 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | 4744 | static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) |
@@ -4721,6 +4776,7 @@ static void tx_load(struct slgt_info *info, const char *buf, unsigned int size) | |||
4721 | set_desc_eof(*d, 0); | 4776 | set_desc_eof(*d, 0); |
4722 | 4777 | ||
4723 | set_desc_count(*d, count); | 4778 | set_desc_count(*d, count); |
4779 | d->buf_count = count; | ||
4724 | } | 4780 | } |
4725 | 4781 | ||
4726 | info->tbuf_current = i; | 4782 | info->tbuf_current = i; |