aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/synclink_gt.c
diff options
context:
space:
mode:
authorPaul Fulghum <paulkf@microgate.com>2008-07-22 06:22:14 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-22 16:03:29 -0400
commit814dae031d08d40d34c0403a54d6e659baf0ae71 (patch)
tree5bebba09b13ab00edb15d75ffab973c7b8ade400 /drivers/char/synclink_gt.c
parent993456cdc853a52e1042ebf93fc6e1a12d1216f7 (diff)
synclink_gt: add rx DMA buffer fill level control
Add run time control for receive DMA buffer fill level to allow application to control receive latency when using stream oriented serial protocols that pass receive data to application only after a DMA buffer fills. This was previously a compile time option, but run time control is needed when application changes data rate (and latency requirements) or uses different data rates on different ports. Signed-off-by: Paul Fulghum <paulkf@microgate.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char/synclink_gt.c')
-rw-r--r--drivers/char/synclink_gt.c42
1 files changed, 27 insertions, 15 deletions
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index c8bc69c97d1a..5ffdb364ea40 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -303,7 +303,7 @@ struct slgt_info {
303 u32 idle_mode; 303 u32 idle_mode;
304 u32 max_frame_size; /* as set by device config */ 304 u32 max_frame_size; /* as set by device config */
305 305
306 unsigned int raw_rx_size; 306 unsigned int rbuf_fill_level;
307 unsigned int if_mode; 307 unsigned int if_mode;
308 308
309 /* device status */ 309 /* device status */
@@ -2676,8 +2676,29 @@ static int tx_abort(struct slgt_info *info)
2676static int rx_enable(struct slgt_info *info, int enable) 2676static int rx_enable(struct slgt_info *info, int enable)
2677{ 2677{
2678 unsigned long flags; 2678 unsigned long flags;
2679 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));
2680 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 return -EINVAL;
2691 info->rbuf_fill_level = rbuf_fill_level;
2692 rx_stop(info); /* restart receiver to use new fill level */
2693 }
2694
2695 /*
2696 * enable[1..0] = receiver enable command
2697 * 0 = disable
2698 * 1 = enable
2699 * 2 = enable or force hunt mode if already enabled
2700 */
2701 enable &= 3;
2681 if (enable) { 2702 if (enable) {
2682 if (!info->rx_enabled) 2703 if (!info->rx_enabled)
2683 rx_start(info); 2704 rx_start(info);
@@ -3444,7 +3465,7 @@ static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev
3444 info->magic = MGSL_MAGIC; 3465 info->magic = MGSL_MAGIC;
3445 INIT_WORK(&info->task, bh_handler); 3466 INIT_WORK(&info->task, bh_handler);
3446 info->max_frame_size = 4096; 3467 info->max_frame_size = 4096;
3447 info->raw_rx_size = DMABUFSIZE; 3468 info->rbuf_fill_level = DMABUFSIZE;
3448 info->port.close_delay = 5*HZ/10; 3469 info->port.close_delay = 5*HZ/10;
3449 info->port.closing_wait = 30*HZ; 3470 info->port.closing_wait = 30*HZ;
3450 init_waitqueue_head(&info->status_event_wait_q); 3471 init_waitqueue_head(&info->status_event_wait_q);
@@ -4447,16 +4468,7 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last
4447 while(!done) { 4468 while(!done) {
4448 /* reset current buffer for reuse */ 4469 /* reset current buffer for reuse */
4449 info->rbufs[i].status = 0; 4470 info->rbufs[i].status = 0;
4450 switch(info->params.mode) { 4471 set_desc_count(info->rbufs[i], info->rbuf_fill_level);
4451 case MGSL_MODE_RAW:
4452 case MGSL_MODE_MONOSYNC:
4453 case MGSL_MODE_BISYNC:
4454 set_desc_count(info->rbufs[i], info->raw_rx_size);
4455 break;
4456 default:
4457 set_desc_count(info->rbufs[i], DMABUFSIZE);
4458 }
4459
4460 if (i == last) 4472 if (i == last)
4461 done = 1; 4473 done = 1;
4462 if (++i == info->rbuf_count) 4474 if (++i == info->rbuf_count)
@@ -4563,7 +4575,7 @@ check_again:
4563 4575
4564 DBGBH(("%s rx frame status=%04X size=%d\n", 4576 DBGBH(("%s rx frame status=%04X size=%d\n",
4565 info->device_name, status, framesize)); 4577 info->device_name, status, framesize));
4566 DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, DMABUFSIZE), "rx"); 4578 DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx");
4567 4579
4568 if (framesize) { 4580 if (framesize) {
4569 if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) { 4581 if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
@@ -4583,7 +4595,7 @@ check_again:
4583 info->icount.rxok++; 4595 info->icount.rxok++;
4584 4596
4585 while(copy_count) { 4597 while(copy_count) {
4586 int partial_count = min(copy_count, DMABUFSIZE); 4598 int partial_count = min_t(int, copy_count, info->rbuf_fill_level);
4587 memcpy(p, info->rbufs[i].buf, partial_count); 4599 memcpy(p, info->rbufs[i].buf, partial_count);
4588 p += partial_count; 4600 p += partial_count;
4589 copy_count -= partial_count; 4601 copy_count -= partial_count;