From: <he...@us...> - 2005-03-17 21:02:27
|
Update of /cvsroot/gc-linux/linux/drivers/exi In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv30376 Modified Files: exi-hw.c Log Message: Clean post_cmd only after a real use, and not everytime. Use DMA too for a corner case in the transfer function. Fixed the event triggering function, which I inadvertently broke. Index: exi-hw.c =================================================================== RCS file: /cvsroot/gc-linux/linux/drivers/exi/exi-hw.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- exi-hw.c 15 Mar 2005 23:39:01 -0000 1.6 +++ exi-hw.c 17 Mar 2005 21:02:15 -0000 1.7 @@ -289,6 +289,7 @@ writel(readl(csr_reg) | EXI_CSR_TCINTMASK, csr_reg); spin_unlock_irqrestore(&exi_channel->io_lock, flags); + /* start the transfer */ writel(EXI_CR_TSTART | EXI_CR_DMA | (mode&7), io_base + EXI_CR); } @@ -459,6 +460,7 @@ cmd->done_data = post_cmd->done_data; cmd->done = post_cmd->done; + exi_op_nop(post_cmd, exi_channel); exi_command_done(cmd); } @@ -476,6 +478,8 @@ */ static int exi_cmd_transfer(struct exi_command *cmd) { + static u8 exi_aligned_transfer_buf[EXI_DMA_ALIGN+1] + __attribute__ ((aligned (EXI_DMA_ALIGN+1))); struct exi_channel *exi_channel = cmd->exi_channel; struct exi_command *post_cmd = &exi_channel->post_cmd; void *pre_data, *data, *post_data; @@ -524,21 +528,31 @@ len = post_data - data; /* - * Coalesce pre and post data transfers if no DMA transfer is done. + * Coalesce pre and post data transfers if no DMA transfer is possible. */ if (!len) { /* - * Maximum transfer size here is 62 bytes. - * - * XXX + * Maximum transfer size here is 31+31=62 bytes. + */ + + /* * On transfer sizes greater than or equal to 32 bytes - * we could optimize the transfer by performing a 32-byte + * we can optimize the transfer by performing a 32-byte * DMA transfer using a specially aligned temporary buffer, * followed by a non-DMA transfer for the remaining bytes. */ - exi_transfer_raw(exi_channel, pre_data, pre_len+post_len, - opcode); - goto done; + if ( pre_len + post_len > EXI_DMA_ALIGN ) { + post_len = pre_len + post_len - (EXI_DMA_ALIGN+1); + post_data = pre_data + EXI_DMA_ALIGN+1; + len = EXI_DMA_ALIGN+1; + data = exi_aligned_transfer_buf; + memcpy(data, pre_data, EXI_DMA_ALIGN+1); + pre_len = 0; + } else { + exi_transfer_raw(exi_channel, pre_data, + pre_len + post_len, opcode); + goto done; + } } /* @@ -565,8 +579,6 @@ post_cmd->done = cmd->done; cmd->done_data = NULL; cmd->done = exi_cmd_post_transfer; - } else { - exi_op_nop(post_cmd, exi_channel); } exi_channel->dma_cmd = cmd; @@ -815,10 +827,12 @@ static inline int exi_trigger_event(struct exi_channel *exi_channel, unsigned int event_id) { + struct exi_event_handler *event; exi_event_handler_t handler; int retval = 0; - handler = exi_channel->events[event_id].handler; + event = &exi_channel->events[event_id]; + handler = event->handler; if (handler) { retval = handler(exi_channel, event_id, event->data); } |