- if (!skb_shinfo(skb)->nr_frags) {
- if (skb->ip_summed != CHECKSUM_HW) {
- /* Errata BTS #50, IHL must be 5 if no HW checksum */
- pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
- ETH_TX_FIRST_DESC |
- ETH_TX_LAST_DESC |
- 5 << ETH_TX_IHL_SHIFT;
- pkt_info.l4i_chk = 0;
- } else {
- pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT |
- ETH_TX_FIRST_DESC |
- ETH_TX_LAST_DESC |
- ETH_GEN_TCP_UDP_CHECKSUM |
- ETH_GEN_IP_V_4_CHECKSUM |
- skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
- /* CPU already calculated pseudo header checksum. */
- if ((skb->protocol == ETH_P_IP) &&
- (skb->nh.iph->protocol == IPPROTO_UDP) ) {
- pkt_info.cmd_sts |= ETH_UDP_FRAME;
- pkt_info.l4i_chk = skb->h.uh->check;
- } else if ((skb->protocol == ETH_P_IP) &&
- (skb->nh.iph->protocol == IPPROTO_TCP))
- pkt_info.l4i_chk = skb->h.th->check;
- else {
- printk(KERN_ERR
- "%s: chksum proto != IPv4 TCP or UDP\n",
- dev->name);
- spin_unlock_irqrestore(&mp->lock, flags);
- return 1;
- }
- }
- pkt_info.byte_cnt = skb->len;
- pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
- DMA_TO_DEVICE);
- pkt_info.return_info = skb;
- status = eth_port_send(mp, &pkt_info);
- if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
- printk(KERN_ERR "%s: Error on transmitting packet\n",
- dev->name);
- stats->tx_bytes += pkt_info.byte_cnt;
- } else {
- unsigned int frag;
-
- /* first frag which is skb header */
- pkt_info.byte_cnt = skb_headlen(skb);
- pkt_info.buf_ptr = dma_map_single(NULL, skb->data,
- skb_headlen(skb),
- DMA_TO_DEVICE);
- pkt_info.l4i_chk = 0;
- pkt_info.return_info = 0;
-
- if (skb->ip_summed != CHECKSUM_HW)
- /* Errata BTS #50, IHL must be 5 if no HW checksum */
- pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
- 5 << ETH_TX_IHL_SHIFT;
- else {
- pkt_info.cmd_sts = ETH_TX_FIRST_DESC |
- ETH_GEN_TCP_UDP_CHECKSUM |
- ETH_GEN_IP_V_4_CHECKSUM |
- skb->nh.iph->ihl << ETH_TX_IHL_SHIFT;
- /* CPU already calculated pseudo header checksum. */
- if ((skb->protocol == ETH_P_IP) &&
- (skb->nh.iph->protocol == IPPROTO_UDP)) {
- pkt_info.cmd_sts |= ETH_UDP_FRAME;
- pkt_info.l4i_chk = skb->h.uh->check;
- } else if ((skb->protocol == ETH_P_IP) &&
- (skb->nh.iph->protocol == IPPROTO_TCP))
- pkt_info.l4i_chk = skb->h.th->check;
- else {
- printk(KERN_ERR
- "%s: chksum proto != IPv4 TCP or UDP\n",
- dev->name);
- spin_unlock_irqrestore(&mp->lock, flags);
- return 1;
- }
- }
-
- status = eth_port_send(mp, &pkt_info);
- if (status != ETH_OK) {
- if ((status == ETH_ERROR))
- printk(KERN_ERR
- "%s: Error on transmitting packet\n",
- dev->name);
- if (status == ETH_QUEUE_FULL)
- printk("Error on Queue Full \n");
- if (status == ETH_QUEUE_LAST_RESOURCE)
- printk("Tx resource error \n");
- }
- stats->tx_bytes += pkt_info.byte_cnt;
-
- /* Check for the remaining frags */
- for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) {
- skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag];
- pkt_info.l4i_chk = 0x0000;
- pkt_info.cmd_sts = 0x00000000;
-
- /* Last Frag enables interrupt and frees the skb */
- if (frag == (skb_shinfo(skb)->nr_frags - 1)) {
- pkt_info.cmd_sts |= ETH_TX_ENABLE_INTERRUPT |
- ETH_TX_LAST_DESC;
- pkt_info.return_info = skb;
- } else {
- pkt_info.return_info = 0;
- }
- pkt_info.l4i_chk = 0;
- pkt_info.byte_cnt = this_frag->size;
-
- pkt_info.buf_ptr = dma_map_page(NULL, this_frag->page,
- this_frag->page_offset,
- this_frag->size,
- DMA_TO_DEVICE);
-
- status = eth_port_send(mp, &pkt_info);
-
- if (status != ETH_OK) {
- if ((status == ETH_ERROR))
- printk(KERN_ERR "%s: Error on "
- "transmitting packet\n",
- dev->name);
-
- if (status == ETH_QUEUE_LAST_RESOURCE)
- printk("Tx resource error \n");
-
- if (status == ETH_QUEUE_FULL)
- printk("Queue is full \n");
- }
- stats->tx_bytes += pkt_info.byte_cnt;
- }
- }
-#else
- spin_lock_irqsave(&mp->lock, flags);
-
- pkt_info.cmd_sts = ETH_TX_ENABLE_INTERRUPT | ETH_TX_FIRST_DESC |
- ETH_TX_LAST_DESC;
- pkt_info.l4i_chk = 0;
- pkt_info.byte_cnt = skb->len;
- pkt_info.buf_ptr = dma_map_single(NULL, skb->data, skb->len,
- DMA_TO_DEVICE);
- pkt_info.return_info = skb;
- status = eth_port_send(mp, &pkt_info);
- if ((status == ETH_ERROR) || (status == ETH_QUEUE_FULL))
- printk(KERN_ERR "%s: Error on transmitting packet\n",
- dev->name);
- stats->tx_bytes += pkt_info.byte_cnt;
-#endif
-
- /* Check if TX queue can handle another skb. If not, then
- * signal higher layers to stop requesting TX
- */
- if (mp->tx_ring_size <= (mp->tx_ring_skbs + MAX_DESCS_PER_SKB))
- /*
- * Stop getting skb's from upper layers.
- * Getting skb's from upper layers will be enabled again after
- * packets are released.
- */
- netif_stop_queue(dev);
-
- /* Update statistics and start of transmittion time */