++ /* fragments */
++ for (i = 0; i < nr_frags; i++) {
++ struct skb_frag_struct *frag;
++ void *addr;
+
+- tx_desc->sdp = phys;
+- tx_desc->pmap = pmap;
+- tx_ring->phys_tab[index] = phys;
++ index = (index + 1) % TX_DESCS;
+
+- tx_ring->buff_tab[index] = skb;
+- config0 |= FIRST_SEGMENT | LAST_SEGMENT;
+- } else {
+- index = ((index + nr_frags) % TX_DESCS);
+- tx_desc = &(tx_ring)->desc[index];
++ frag = &skb_shinfo(skb)->frags[i];
++ addr = page_address(skb_frag_page(frag)) + frag->page_offset;
+
+- /* fragments */
+- for (i = nr_frags; i > 0; i--) {
+- u32 config;
+- void *addr;
+-
+- frag = &skb_shinfo(skb)->frags[i-1];
+- len = frag->size;
+-
+- addr = page_address(skb_frag_page(frag)) +
+- frag->page_offset;
+- phys = dma_map_single(NULL, addr, len, DMA_TO_DEVICE);
+-
+- tx_desc->sdp = phys;
+-
+- tx_desc->pmap = pmap;
+- tx_ring->phys_tab[index] = phys;
+-
+- config = config0 | len;
+- if (i == nr_frags) {
+- config |= LAST_SEGMENT;
+- tx_ring->buff_tab[index] = skb;
+- }
+- if (index == TX_DESCS - 1)
+- config |= END_OF_RING;
+- tx_desc->config0 = config;
+-
+- if (index == 0) {
+- index = TX_DESCS - 1;
+- tx_desc = &(tx_ring)->desc[index];
+- } else {
+- index--;
+- tx_desc--;
+- }
+- }
++ eth_set_desc(tx_ring, index, index_last, addr, frag->size,
++ config0, pmap);
++ }
+
+- /* header */
+- len = skb->len - skb->data_len;
++ if (nr_frags)
++ len0 = skb->len - skb->data_len;
+
+- phys = dma_map_single(NULL, skb->data, len, DMA_TO_DEVICE);
++ skb_walk_frags(skb, skb1) {
++ index = (index + 1) % TX_DESCS;
++ len0 -= skb1->len;