diff options
Diffstat (limited to 'drivers/net/ethernet/marvell/mv643xx_eth.c')
| -rw-r--r-- | drivers/net/ethernet/marvell/mv643xx_eth.c | 59 |
1 files changed, 49 insertions, 10 deletions
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index a62fc38f045e..1c75829eb166 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c | |||
| @@ -192,6 +192,10 @@ static char mv643xx_eth_driver_version[] = "1.4"; | |||
| 192 | #define IS_TSO_HEADER(txq, addr) \ | 192 | #define IS_TSO_HEADER(txq, addr) \ |
| 193 | ((addr >= txq->tso_hdrs_dma) && \ | 193 | ((addr >= txq->tso_hdrs_dma) && \ |
| 194 | (addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE)) | 194 | (addr < txq->tso_hdrs_dma + txq->tx_ring_size * TSO_HEADER_SIZE)) |
| 195 | |||
| 196 | #define DESC_DMA_MAP_SINGLE 0 | ||
| 197 | #define DESC_DMA_MAP_PAGE 1 | ||
| 198 | |||
| 195 | /* | 199 | /* |
| 196 | * RX/TX descriptors. | 200 | * RX/TX descriptors. |
| 197 | */ | 201 | */ |
| @@ -362,6 +366,7 @@ struct tx_queue { | |||
| 362 | dma_addr_t tso_hdrs_dma; | 366 | dma_addr_t tso_hdrs_dma; |
| 363 | 367 | ||
| 364 | struct tx_desc *tx_desc_area; | 368 | struct tx_desc *tx_desc_area; |
| 369 | char *tx_desc_mapping; /* array to track the type of the dma mapping */ | ||
| 365 | dma_addr_t tx_desc_dma; | 370 | dma_addr_t tx_desc_dma; |
| 366 | int tx_desc_area_size; | 371 | int tx_desc_area_size; |
| 367 | 372 | ||
| @@ -750,6 +755,7 @@ txq_put_data_tso(struct net_device *dev, struct tx_queue *txq, | |||
| 750 | if (txq->tx_curr_desc == txq->tx_ring_size) | 755 | if (txq->tx_curr_desc == txq->tx_ring_size) |
| 751 | txq->tx_curr_desc = 0; | 756 | txq->tx_curr_desc = 0; |
| 752 | desc = &txq->tx_desc_area[tx_index]; | 757 | desc = &txq->tx_desc_area[tx_index]; |
| 758 | txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE; | ||
| 753 | 759 | ||
| 754 | desc->l4i_chk = 0; | 760 | desc->l4i_chk = 0; |
| 755 | desc->byte_cnt = length; | 761 | desc->byte_cnt = length; |
| @@ -879,14 +885,13 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb) | |||
| 879 | skb_frag_t *this_frag; | 885 | skb_frag_t *this_frag; |
| 880 | int tx_index; | 886 | int tx_index; |
| 881 | struct tx_desc *desc; | 887 | struct tx_desc *desc; |
| 882 | void *addr; | ||
| 883 | 888 | ||
| 884 | this_frag = &skb_shinfo(skb)->frags[frag]; | 889 | this_frag = &skb_shinfo(skb)->frags[frag]; |
| 885 | addr = page_address(this_frag->page.p) + this_frag->page_offset; | ||
| 886 | tx_index = txq->tx_curr_desc++; | 890 | tx_index = txq->tx_curr_desc++; |
| 887 | if (txq->tx_curr_desc == txq->tx_ring_size) | 891 | if (txq->tx_curr_desc == txq->tx_ring_size) |
| 888 | txq->tx_curr_desc = 0; | 892 | txq->tx_curr_desc = 0; |
| 889 | desc = &txq->tx_desc_area[tx_index]; | 893 | desc = &txq->tx_desc_area[tx_index]; |
| 894 | txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_PAGE; | ||
| 890 | 895 | ||
| 891 | /* | 896 | /* |
| 892 | * The last fragment will generate an interrupt | 897 | * The last fragment will generate an interrupt |
| @@ -902,8 +907,9 @@ static void txq_submit_frag_skb(struct tx_queue *txq, struct sk_buff *skb) | |||
| 902 | 907 | ||
| 903 | desc->l4i_chk = 0; | 908 | desc->l4i_chk = 0; |
| 904 | desc->byte_cnt = skb_frag_size(this_frag); | 909 | desc->byte_cnt = skb_frag_size(this_frag); |
| 905 | desc->buf_ptr = dma_map_single(mp->dev->dev.parent, addr, | 910 | desc->buf_ptr = skb_frag_dma_map(mp->dev->dev.parent, |
| 906 | desc->byte_cnt, DMA_TO_DEVICE); | 911 | this_frag, 0, desc->byte_cnt, |
| 912 | DMA_TO_DEVICE); | ||
| 907 | } | 913 | } |
| 908 | } | 914 | } |
| 909 | 915 | ||
| @@ -936,6 +942,7 @@ static int txq_submit_skb(struct tx_queue *txq, struct sk_buff *skb, | |||
| 936 | if (txq->tx_curr_desc == txq->tx_ring_size) | 942 | if (txq->tx_curr_desc == txq->tx_ring_size) |
| 937 | txq->tx_curr_desc = 0; | 943 | txq->tx_curr_desc = 0; |
| 938 | desc = &txq->tx_desc_area[tx_index]; | 944 | desc = &txq->tx_desc_area[tx_index]; |
| 945 | txq->tx_desc_mapping[tx_index] = DESC_DMA_MAP_SINGLE; | ||
| 939 | 946 | ||
| 940 | if (nr_frags) { | 947 | if (nr_frags) { |
| 941 | txq_submit_frag_skb(txq, skb); | 948 | txq_submit_frag_skb(txq, skb); |
| @@ -1047,9 +1054,12 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) | |||
| 1047 | int tx_index; | 1054 | int tx_index; |
| 1048 | struct tx_desc *desc; | 1055 | struct tx_desc *desc; |
| 1049 | u32 cmd_sts; | 1056 | u32 cmd_sts; |
| 1057 | char desc_dma_map; | ||
| 1050 | 1058 | ||
| 1051 | tx_index = txq->tx_used_desc; | 1059 | tx_index = txq->tx_used_desc; |
| 1052 | desc = &txq->tx_desc_area[tx_index]; | 1060 | desc = &txq->tx_desc_area[tx_index]; |
| 1061 | desc_dma_map = txq->tx_desc_mapping[tx_index]; | ||
| 1062 | |||
| 1053 | cmd_sts = desc->cmd_sts; | 1063 | cmd_sts = desc->cmd_sts; |
| 1054 | 1064 | ||
| 1055 | if (cmd_sts & BUFFER_OWNED_BY_DMA) { | 1065 | if (cmd_sts & BUFFER_OWNED_BY_DMA) { |
| @@ -1065,9 +1075,19 @@ static int txq_reclaim(struct tx_queue *txq, int budget, int force) | |||
| 1065 | reclaimed++; | 1075 | reclaimed++; |
| 1066 | txq->tx_desc_count--; | 1076 | txq->tx_desc_count--; |
| 1067 | 1077 | ||
| 1068 | if (!IS_TSO_HEADER(txq, desc->buf_ptr)) | 1078 | if (!IS_TSO_HEADER(txq, desc->buf_ptr)) { |
| 1069 | dma_unmap_single(mp->dev->dev.parent, desc->buf_ptr, | 1079 | |
| 1070 | desc->byte_cnt, DMA_TO_DEVICE); | 1080 | if (desc_dma_map == DESC_DMA_MAP_PAGE) |
| 1081 | dma_unmap_page(mp->dev->dev.parent, | ||
| 1082 | desc->buf_ptr, | ||
| 1083 | desc->byte_cnt, | ||
| 1084 | DMA_TO_DEVICE); | ||
| 1085 | else | ||
| 1086 | dma_unmap_single(mp->dev->dev.parent, | ||
| 1087 | desc->buf_ptr, | ||
| 1088 | desc->byte_cnt, | ||
| 1089 | DMA_TO_DEVICE); | ||
| 1090 | } | ||
| 1071 | 1091 | ||
| 1072 | if (cmd_sts & TX_ENABLE_INTERRUPT) { | 1092 | if (cmd_sts & TX_ENABLE_INTERRUPT) { |
| 1073 | struct sk_buff *skb = __skb_dequeue(&txq->tx_skb); | 1093 | struct sk_buff *skb = __skb_dequeue(&txq->tx_skb); |
| @@ -1996,6 +2016,7 @@ static int txq_init(struct mv643xx_eth_private *mp, int index) | |||
| 1996 | struct tx_queue *txq = mp->txq + index; | 2016 | struct tx_queue *txq = mp->txq + index; |
| 1997 | struct tx_desc *tx_desc; | 2017 | struct tx_desc *tx_desc; |
| 1998 | int size; | 2018 | int size; |
| 2019 | int ret; | ||
| 1999 | int i; | 2020 | int i; |
| 2000 | 2021 | ||
| 2001 | txq->index = index; | 2022 | txq->index = index; |
| @@ -2048,18 +2069,34 @@ static int txq_init(struct mv643xx_eth_private *mp, int index) | |||
| 2048 | nexti * sizeof(struct tx_desc); | 2069 | nexti * sizeof(struct tx_desc); |
| 2049 | } | 2070 | } |
| 2050 | 2071 | ||
| 2072 | txq->tx_desc_mapping = kcalloc(txq->tx_ring_size, sizeof(char), | ||
| 2073 | GFP_KERNEL); | ||
| 2074 | if (!txq->tx_desc_mapping) { | ||
| 2075 | ret = -ENOMEM; | ||
| 2076 | goto err_free_desc_area; | ||
| 2077 | } | ||
| 2078 | |||
| 2051 | /* Allocate DMA buffers for TSO MAC/IP/TCP headers */ | 2079 | /* Allocate DMA buffers for TSO MAC/IP/TCP headers */ |
| 2052 | txq->tso_hdrs = dma_alloc_coherent(mp->dev->dev.parent, | 2080 | txq->tso_hdrs = dma_alloc_coherent(mp->dev->dev.parent, |
| 2053 | txq->tx_ring_size * TSO_HEADER_SIZE, | 2081 | txq->tx_ring_size * TSO_HEADER_SIZE, |
| 2054 | &txq->tso_hdrs_dma, GFP_KERNEL); | 2082 | &txq->tso_hdrs_dma, GFP_KERNEL); |
| 2055 | if (txq->tso_hdrs == NULL) { | 2083 | if (txq->tso_hdrs == NULL) { |
| 2056 | dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size, | 2084 | ret = -ENOMEM; |
| 2057 | txq->tx_desc_area, txq->tx_desc_dma); | 2085 | goto err_free_desc_mapping; |
| 2058 | return -ENOMEM; | ||
| 2059 | } | 2086 | } |
| 2060 | skb_queue_head_init(&txq->tx_skb); | 2087 | skb_queue_head_init(&txq->tx_skb); |
| 2061 | 2088 | ||
| 2062 | return 0; | 2089 | return 0; |
| 2090 | |||
| 2091 | err_free_desc_mapping: | ||
| 2092 | kfree(txq->tx_desc_mapping); | ||
| 2093 | err_free_desc_area: | ||
| 2094 | if (index == 0 && size <= mp->tx_desc_sram_size) | ||
| 2095 | iounmap(txq->tx_desc_area); | ||
| 2096 | else | ||
| 2097 | dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size, | ||
| 2098 | txq->tx_desc_area, txq->tx_desc_dma); | ||
| 2099 | return ret; | ||
| 2063 | } | 2100 | } |
| 2064 | 2101 | ||
| 2065 | static void txq_deinit(struct tx_queue *txq) | 2102 | static void txq_deinit(struct tx_queue *txq) |
| @@ -2077,6 +2114,8 @@ static void txq_deinit(struct tx_queue *txq) | |||
| 2077 | else | 2114 | else |
| 2078 | dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size, | 2115 | dma_free_coherent(mp->dev->dev.parent, txq->tx_desc_area_size, |
| 2079 | txq->tx_desc_area, txq->tx_desc_dma); | 2116 | txq->tx_desc_area, txq->tx_desc_dma); |
| 2117 | kfree(txq->tx_desc_mapping); | ||
| 2118 | |||
| 2080 | if (txq->tso_hdrs) | 2119 | if (txq->tso_hdrs) |
| 2081 | dma_free_coherent(mp->dev->dev.parent, | 2120 | dma_free_coherent(mp->dev->dev.parent, |
| 2082 | txq->tx_ring_size * TSO_HEADER_SIZE, | 2121 | txq->tx_ring_size * TSO_HEADER_SIZE, |
