static int rmnet_mhi_xmit(struct sk_buff *skb, struct net_device *dev) { struct rmnet_mhi_private *rmnet_mhi_ptr = *(struct rmnet_mhi_private **)netdev_priv(dev); enum MHI_STATUS res = MHI_STATUS_reserved; unsigned long flags; int retry = 0; struct mhi_skb_priv *tx_priv; rmnet_log(MSG_VERBOSE, "Entered chan %d\n", rmnet_mhi_ptr->tx_channel); tx_priv = (struct mhi_skb_priv *)(skb->cb); tx_priv->dma_size = skb->len; tx_priv->dma_addr = 0; do { retry = 0; res = mhi_queue_xfer(rmnet_mhi_ptr->tx_client_handle, skb->data, skb->len, MHI_EOT); if (-ENOSPC == res) { write_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock, flags); if (!mhi_get_free_desc( rmnet_mhi_ptr->tx_client_handle)) { /* Stop writing until we can write again */ tx_ring_full_count[rmnet_mhi_ptr->dev_index]++; netif_stop_queue(dev); rmnet_log(MSG_VERBOSE, "Stopping Queue\n"); goto rmnet_mhi_xmit_error_cleanup; } else { retry = 1; } write_unlock_irqrestore( &rmnet_mhi_ptr->out_chan_full_lock, flags); } } while (retry); if (MHI_STATUS_SUCCESS != res) { netif_stop_queue(dev); rmnet_log(MSG_CRITICAL, "mhi_queue_xfer failed, error %d\n", res); goto rmnet_mhi_xmit_error_cleanup; } skb_queue_tail(&(rmnet_mhi_ptr->tx_buffers), skb); dev->trans_start = jiffies; tx_queued_packets_count[rmnet_mhi_ptr->dev_index]++; rmnet_log(MSG_VERBOSE, "Exited\n"); return 0; rmnet_mhi_xmit_error_cleanup: rmnet_log(MSG_VERBOSE, "Ring full\n"); write_unlock_irqrestore(&rmnet_mhi_ptr->out_chan_full_lock, flags); return NETDEV_TX_BUSY; }
static int rmnet_mhi_xmit(struct sk_buff *skb, struct net_device *dev) { struct rmnet_mhi_private *rmnet_mhi_ptr = *(struct rmnet_mhi_private **)netdev_priv(dev); enum MHI_STATUS res = MHI_STATUS_reserved; unsigned long flags; int retry = 0; struct tx_buffer_priv *tx_priv; dma_addr_t dma_addr; rmnet_log(MSG_VERBOSE, "Entered\n"); dma_addr = dma_map_single(&(dev->dev), skb->data, skb->len, DMA_TO_DEVICE); if (dma_mapping_error(&(dev->dev), dma_addr)) { rmnet_log(MSG_CRITICAL, "DMA mapping error in transmit function\n"); return NETDEV_TX_BUSY; } /* DMA mapping is OK, need to update the cb field properly */ tx_priv = (struct tx_buffer_priv *)(skb->cb); tx_priv->dma_addr = dma_addr; do { retry = 0; res = mhi_queue_xfer(rmnet_mhi_ptr->tx_client_handle, dma_addr, skb->len, MHI_EOT); if (MHI_STATUS_RING_FULL == res) { write_lock_irqsave(&rmnet_mhi_ptr->out_chan_full_lock, flags); if (!mhi_get_free_desc( rmnet_mhi_ptr->tx_client_handle)) { /* Stop writing until we can write again */ tx_ring_full_count[rmnet_mhi_ptr->dev_index]++; netif_stop_queue(dev); goto rmnet_mhi_xmit_error_cleanup; } else { retry = 1; } write_unlock_irqrestore( &rmnet_mhi_ptr->out_chan_full_lock, flags); } } while (retry); if (MHI_STATUS_SUCCESS != res) { netif_stop_queue(dev); rmnet_log(MSG_CRITICAL, "mhi_queue_xfer failed, error %d\n", res); goto rmnet_mhi_xmit_error_cleanup; } skb_queue_tail(&(rmnet_mhi_ptr->tx_buffers), skb); dev->trans_start = jiffies; tx_queued_packets_count[rmnet_mhi_ptr->dev_index]++; rmnet_log(MSG_VERBOSE, "Exited\n"); return 0; rmnet_mhi_xmit_error_cleanup: dma_unmap_single(&(dev->dev), dma_addr, skb->len, DMA_TO_DEVICE); rmnet_log(MSG_VERBOSE, "Ring full\n"); write_unlock_irqrestore(&rmnet_mhi_ptr->out_chan_full_lock, flags); return NETDEV_TX_BUSY; }