static void hci_h4p_rx_tasklet(unsigned long data) { u8 byte; struct hci_h4p_info *info = (struct hci_h4p_info *)data; NBT_DBG("tasklet woke up\n"); NBT_DBG_TRANSFER("rx_tasklet woke up\ndata "); while (hci_h4p_inb(info, UART_LSR) & UART_LSR_DR) { byte = hci_h4p_inb(info, UART_RX); if (info->garbage_bytes) { info->garbage_bytes--; continue; } if (info->rx_skb == NULL) { info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC | GFP_DMA); if (!info->rx_skb) { dev_err(info->dev, "No memory for new packet\n"); goto finish_rx; } info->rx_state = WAIT_FOR_PKT_TYPE; info->rx_skb->dev = (void *)info->hdev; } info->hdev->stat.byte_rx++; NBT_DBG_TRANSFER_NF("0x%.2x ", byte); hci_h4p_handle_byte(info, byte); } if (!info->rx_enabled) { if (hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT && info->autorts) { __hci_h4p_set_auto_ctsrts(info, 0 , UART_EFR_RTS); info->autorts = 0; } /* Flush posted write to avoid spurious interrupts */ hci_h4p_inb(info, UART_OMAP_SCR); hci_h4p_set_clk(info, &info->rx_clocks_en, 0); } finish_rx: NBT_DBG_TRANSFER_NF("\n"); NBT_DBG("rx_ended\n"); }
static void brf6150_tx_tasklet(unsigned long data) { unsigned int sent = 0; unsigned long flags; struct sk_buff *skb; struct brf6150_info *info = (struct brf6150_info *)data; NBT_DBG_TRANSFER("tx_tasklet woke up\n data "); skb = skb_dequeue(&info->txq); if (!skb) { /* No data in buffer */ brf6150_enable_pm_tx(info); return; } /* Copy data to tx fifo */ while (!(brf6150_inb(info, UART_OMAP_SSR) & UART_OMAP_SSR_TXFULL) && (sent < skb->len)) { NBT_DBG_TRANSFER_NF("0x%.2x ", skb->data[sent]); brf6150_outb(info, UART_TX, skb->data[sent]); sent++; } info->hdev->stat.byte_tx += sent; NBT_DBG_TRANSFER_NF("\n"); if (skb->len == sent) { kfree_skb(skb); clk_disable(info->uart_ck); } else { skb_pull(skb, sent); skb_queue_head(&info->txq, skb); } spin_lock_irqsave(&info->lock, flags); brf6150_outb(info, UART_IER, brf6150_inb(info, UART_IER) | UART_IER_THRI); spin_unlock_irqrestore(&info->lock, flags); }
static void hci_h4p_tx_tasklet(unsigned long data) { unsigned int sent = 0; struct sk_buff *skb; struct hci_h4p_info *info = (struct hci_h4p_info *)data; NBT_DBG("tasklet woke up\n"); NBT_DBG_TRANSFER("tx_tasklet woke up\n data "); if (info->autorts != info->rx_enabled) { if (hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT) { if (info->autorts && !info->rx_enabled) { __hci_h4p_set_auto_ctsrts(info, 0, UART_EFR_RTS); info->autorts = 0; } if (!info->autorts && info->rx_enabled) { __hci_h4p_set_auto_ctsrts(info, 1, UART_EFR_RTS); info->autorts = 1; } } else { hci_h4p_outb(info, UART_OMAP_SCR, hci_h4p_inb(info, UART_OMAP_SCR) | UART_OMAP_SCR_EMPTY_THR); goto finish_tx; } } skb = skb_dequeue(&info->txq); if (!skb) { /* No data in buffer */ NBT_DBG("skb ready\n"); if (hci_h4p_inb(info, UART_LSR) & UART_LSR_TEMT) { hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) & ~UART_IER_THRI); hci_h4p_inb(info, UART_OMAP_SCR); hci_h4p_disable_tx(info); return; } else hci_h4p_outb(info, UART_OMAP_SCR, hci_h4p_inb(info, UART_OMAP_SCR) | UART_OMAP_SCR_EMPTY_THR); goto finish_tx; } /* Copy data to tx fifo */ while (!(hci_h4p_inb(info, UART_OMAP_SSR) & UART_OMAP_SSR_TXFULL) && (sent < skb->len)) { NBT_DBG_TRANSFER_NF("0x%.2x ", skb->data[sent]); hci_h4p_outb(info, UART_TX, skb->data[sent]); sent++; } info->hdev->stat.byte_tx += sent; NBT_DBG_TRANSFER_NF("\n"); if (skb->len == sent) { kfree_skb(skb); } else { skb_pull(skb, sent); skb_queue_head(&info->txq, skb); } hci_h4p_outb(info, UART_OMAP_SCR, hci_h4p_inb(info, UART_OMAP_SCR) & ~UART_OMAP_SCR_EMPTY_THR); hci_h4p_outb(info, UART_IER, hci_h4p_inb(info, UART_IER) | UART_IER_THRI); finish_tx: /* Flush posted write to avoid spurious interrupts */ hci_h4p_inb(info, UART_OMAP_SCR); }
static inline void brf6150_rx(struct brf6150_info *info) { u8 byte; NBT_DBG_TRANSFER("rx_tasklet woke up\ndata "); while (brf6150_inb(info, UART_LSR) & UART_LSR_DR) { if (info->rx_skb == NULL) { info->rx_skb = bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC); if (!info->rx_skb) { printk(KERN_WARNING "brf6150: Can't allocate memory for new packet\n"); return; } info->rx_state = WAIT_FOR_PKT_TYPE; info->rx_skb->dev = (void *)info->hdev; brf6150_disable_pm_rx(info); clk_enable(info->uart_ck); } byte = brf6150_inb(info, UART_RX); if (info->garbage_bytes) { info->garbage_bytes--; info->hdev->stat.err_rx++; continue; } info->hdev->stat.byte_rx++; NBT_DBG_TRANSFER_NF("0x%.2x ", byte); switch (info->rx_state) { case WAIT_FOR_PKT_TYPE: bt_cb(info->rx_skb)->pkt_type = byte; info->rx_count = brf6150_get_hdr_len(byte); if (info->rx_count >= 0) { info->rx_state = WAIT_FOR_HEADER; } else { info->hdev->stat.err_rx++; kfree_skb(info->rx_skb); info->rx_skb = NULL; clk_disable(info->uart_ck); } break; case WAIT_FOR_HEADER: info->rx_count--; *skb_put(info->rx_skb, 1) = byte; if (info->rx_count == 0) { info->rx_count = brf6150_get_data_len(info, info->rx_skb); if (info->rx_count > skb_tailroom(info->rx_skb)) { printk(KERN_WARNING "brf6150: Frame is %ld bytes too long.\n", info->rx_count - skb_tailroom(info->rx_skb)); info->rx_skb = NULL; info->garbage_bytes = info->rx_count - skb_tailroom(info->rx_skb); clk_disable(info->uart_ck); break; } info->rx_state = WAIT_FOR_DATA; if (bt_cb(info->rx_skb)->pkt_type == H4_NEG_PKT) { brf6150_negotiation_packet(info, info->rx_skb); info->rx_skb = NULL; clk_disable(info->uart_ck); return; } if (bt_cb(info->rx_skb)->pkt_type == H4_ALIVE_PKT) { brf6150_alive_packet(info, info->rx_skb); info->rx_skb = NULL; clk_disable(info->uart_ck); return; } } break; case WAIT_FOR_DATA: info->rx_count--; *skb_put(info->rx_skb, 1) = byte; if (info->rx_count == 0) { brf6150_recv_frame(info, info->rx_skb); info->rx_skb = NULL; clk_disable(info->uart_ck); } break; default: WARN_ON(1); break; } } NBT_DBG_TRANSFER_NF("\n"); }