static void tegra_stop_rx(struct uart_port *u) { struct tegra_uart_port *t; unsigned char ier; t = container_of(u, struct tegra_uart_port, uport); if (t->rts_active) set_rts(t, false); if (t->rx_in_progress) { wait_sym_time(t, 1); /* wait a character interval */ ier = t->ier_shadow; ier &= ~(UART_IER_RDI | UART_IER_RLSI | UART_IER_RTOIE | UART_IER_EORD); t->ier_shadow = ier; uart_writeb(t, ier, UART_IER); t->rx_in_progress = 0; if (t->use_rx_dma && t->rx_dma) tegra_dma_dequeue_req(t->rx_dma, &t->rx_dma_req); else do_handle_rx_pio(t); tty_flip_buffer_push(u->state->port.tty); } return; }
/* It is expected that the callers take the UART lock when this API is called. * * There are 2 contexts when this function is called: * * 1. DMA ISR - DMA ISR triggers the threshold complete calback, which calls the * dequue API which in-turn calls this callback. UART lock is taken during * the call to the threshold callback. * * 2. UART ISR - UART calls the dequue API which in-turn will call this API. * In this case, UART ISR takes the UART lock. * */ static void tegra_rx_dma_complete_callback(struct tegra_dma_req *req) { struct tegra_uart_port *t = req->dev; struct uart_port *u = &t->uport; struct tty_struct *tty = u->state->port.tty; /* If we are here, DMA is stopped */ dev_dbg(t->uport.dev, "%s: %d %d\n", __func__, req->bytes_transferred, req->status); if (req->bytes_transferred) { t->uport.icount.rx += req->bytes_transferred; tty_insert_flip_string(tty, ((unsigned char *)(req->virt_addr)), req->bytes_transferred); } do_handle_rx_pio(t); /* Push the read data later in caller place. */ if (req->status == -TEGRA_DMA_REQ_ERROR_ABORTED) return; spin_unlock(&u->lock); tty_flip_buffer_push(u->state->port.tty); spin_lock(&u->lock); }
/* * It is expected that the callers take the UART lock when this API is called. * * There are 2 contexts when this function is called: * * 1. DMA ISR - DMA ISR triggers the threshold complete calback, which calls the * dequue API which in-turn calls this callback. UART lock is taken during * the call to the threshold callback. * * 2. UART ISR - UART calls the dequue API which in-turn will call this API. * In this case, UART ISR takes the UART lock. */ static void tegra_rx_dma_complete_callback(struct tegra_dma_req *req) { struct tegra_uart_port *t = req->dev; struct uart_port *u = &t->uport; struct tty_struct *tty = u->state->port.tty; int copied; /* If we are here, DMA is stopped */ dev_dbg(t->uport.dev, "%s: %d %d\n", __func__, req->bytes_transferred, req->status); if (req->bytes_transferred) { t->uport.icount.rx += req->bytes_transferred; dma_sync_single_for_cpu(t->uport.dev, req->dest_addr, req->size, DMA_FROM_DEVICE); copied = tty_insert_flip_string(tty, ((unsigned char *)(req->virt_addr)), req->bytes_transferred); if (copied != req->bytes_transferred) { WARN_ON(1); dev_err(t->uport.dev, "Not able to copy uart data " "to tty layer Req %d and coped %d\n", req->bytes_transferred, copied); } dma_sync_single_for_device(t->uport.dev, req->dest_addr, req->size, DMA_TO_DEVICE); } do_handle_rx_pio(t); /* Push the read data later in caller place. */ if (req->status == -TEGRA_DMA_REQ_ERROR_ABORTED) return; printk(KERN_ERR "%s: tegra_uart_%d: DMA_REQ: buf_stat(%d),stat(%d)\n", __func__, req->instance, req->buffer_status, req->status); /* Not out of sync err from dma_isr/dbl_dma */ if (req->status != -TEGRA_DMA_REQ_ERROR_STOPPED) spin_unlock(&u->lock); tty_flip_buffer_push(u->state->port.tty); /* Not out of sync err from dma_isr/dbl_dma */ if (req->status != -TEGRA_DMA_REQ_ERROR_STOPPED) spin_lock(&u->lock); }
static irqreturn_t tegra_uart_isr(int irq, void *data) { struct tegra_uart_port *t = data; struct uart_port *u = &t->uport; unsigned char iir; unsigned char ier; bool is_rx_int = false; unsigned long flags; spin_lock_irqsave(&u->lock, flags); t = container_of(u, struct tegra_uart_port, uport); while (1) { iir = uart_readb(t, UART_IIR); if (iir & UART_IIR_NO_INT) { if (likely(t->use_rx_dma) && is_rx_int) { do_handle_rx_dma(t); if (t->rx_in_progress) { ier = t->ier_shadow; ier |= (UART_IER_RLSI | UART_IER_RTOIE | UART_IER_EORD); t->ier_shadow = ier; uart_writeb(t, ier, UART_IER); } } spin_unlock_irqrestore(&u->lock, flags); return IRQ_HANDLED; } dev_dbg(u->dev, "tegra_uart_isr iir = 0x%x (%d)\n", iir, (iir >> 1) & 0x7); switch ((iir >> 1) & 0x7) { case 0: /* Modem signal change interrupt */ do_handle_modem_signal(u); break; case 1: /* Transmit interrupt only triggered when using PIO */ t->ier_shadow &= ~UART_IER_THRI; uart_writeb(t, t->ier_shadow, UART_IER); do_handle_tx_pio(t); break; case 4: /* End of data */ case 6: /* Rx timeout */ case 2: /* Receive */ if (likely(t->use_rx_dma)) { if (!is_rx_int) { is_rx_int = true; /* Disable interrups */ ier = t->ier_shadow; ier |= UART_IER_RDI; uart_writeb(t, ier, UART_IER); ier &= ~(UART_IER_RDI | UART_IER_RLSI | UART_IER_RTOIE | UART_IER_EORD); t->ier_shadow = ier; uart_writeb(t, ier, UART_IER); } } else { do_handle_rx_pio(t); spin_unlock_irqrestore(&u->lock, flags); tty_flip_buffer_push(u->state->port.tty); spin_lock_irqsave(&u->lock, flags); } break; case 3: /* Receive error */ /* FIXME how to handle this? Why do we get here */ do_decode_rx_error(t, uart_readb(t, UART_LSR)); break; case 5: /* break nothing to handle */ case 7: /* break nothing to handle */ break; } } }
static irqreturn_t tegra_uart_isr(int irq, void *data) { struct tegra_uart_port *tup = data; struct uart_port *u = &tup->uport; unsigned long iir; unsigned long ier; bool is_rx_int = false; unsigned long flags; spin_lock_irqsave(&u->lock, flags); while (1) { iir = tegra_uart_read(tup, UART_IIR); if (iir & UART_IIR_NO_INT) { if (!tup->use_rx_pio && is_rx_int) { tegra_uart_handle_rx_dma(tup); if (tup->rx_in_progress) { ier = tup->ier_shadow; ier |= (UART_IER_RLSI | UART_IER_RTOIE | TEGRA_UART_IER_EORD); tup->ier_shadow = ier; tegra_uart_write(tup, ier, UART_IER); } } spin_unlock_irqrestore(&u->lock, flags); return IRQ_HANDLED; } switch ((iir >> 1) & 0x7) { case 0: /* Modem signal change interrupt */ tegra_uart_handle_modem_signal_change(u); break; case 1: /* Transmit interrupt only triggered when using PIO */ tup->ier_shadow &= ~UART_IER_THRI; tegra_uart_write(tup, tup->ier_shadow, UART_IER); tegra_uart_handle_tx_pio(tup); break; case 4: /* End of data */ case 6: /* Rx timeout */ case 2: /* Receive */ if (!tup->use_rx_pio && !is_rx_int) { is_rx_int = true; /* Disable Rx interrupts */ ier = tup->ier_shadow; ier |= UART_IER_RDI; tegra_uart_write(tup, ier, UART_IER); ier &= ~(UART_IER_RDI | UART_IER_RLSI | UART_IER_RTOIE | TEGRA_UART_IER_EORD); tup->ier_shadow = ier; tegra_uart_write(tup, ier, UART_IER); } else do_handle_rx_pio(tup); break; case 3: /* Receive error */ tegra_uart_decode_rx_error(tup, tegra_uart_read(tup, UART_LSR)); break; case 5: /* break nothing to handle */ case 7: /* break nothing to handle */ break; } } }