diff options
author | Dale Farnsworth <dale@farnsworth.org> | 2006-03-03 12:02:51 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-03-03 12:12:36 -0500 |
commit | ff561eef9fb37c7180085e08418acfc009a9ada7 (patch) | |
tree | 97010ae360fdb25238698ad811c22f6d901e1fde /drivers/net/mv643xx_eth.c | |
parent | c8aaea25e0b069e9572caa74f984e109899c1765 (diff) |
[PATCH] mv643xx_eth: Refactor/clean up tx queue handling
Signed-off-by: Dale Farnsworth <dale@farnsworth.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/mv643xx_eth.c')
-rw-r--r-- | drivers/net/mv643xx_eth.c | 257 |
1 files changed, 84 insertions, 173 deletions
diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 260be8048d3c..8a24b39f3ccb 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c | |||
@@ -62,6 +62,9 @@ | |||
62 | #define WRAP HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN | 62 | #define WRAP HW_IP_ALIGN + ETH_HLEN + VLAN_HLEN + FCS_LEN |
63 | #define RX_SKB_SIZE ((dev->mtu + WRAP + 7) & ~0x7) | 63 | #define RX_SKB_SIZE ((dev->mtu + WRAP + 7) & ~0x7) |
64 | 64 | ||
65 | #define ETH_RX_QUEUES_ENABLED (1 << 0) /* use only Q0 for receive */ | ||
66 | #define ETH_TX_QUEUES_ENABLED (1 << 0) /* use only Q0 for transmit */ | ||
67 | |||
65 | #define INT_UNMASK_ALL 0x0007ffff | 68 | #define INT_UNMASK_ALL 0x0007ffff |
66 | #define INT_UNMASK_ALL_EXT 0x0011ffff | 69 | #define INT_UNMASK_ALL_EXT 0x0011ffff |
67 | #define INT_MASK_ALL 0x00000000 | 70 | #define INT_MASK_ALL 0x00000000 |
@@ -333,49 +336,78 @@ static void mv643xx_eth_tx_timeout_task(struct net_device *dev) | |||
333 | netif_device_attach(dev); | 336 | netif_device_attach(dev); |
334 | } | 337 | } |
335 | 338 | ||
336 | /* | 339 | /** |
337 | * mv643xx_eth_free_tx_queue | 340 | * mv643xx_eth_free_tx_descs - Free the tx desc data for completed descriptors |
338 | * | ||
339 | * Input : dev - a pointer to the required interface | ||
340 | * | 341 | * |
341 | * Output : 0 if was able to release skb , nonzero otherwise | 342 | * If force is non-zero, frees uncompleted descriptors as well |
342 | */ | 343 | */ |
343 | static int mv643xx_eth_free_tx_queue(struct net_device *dev, | 344 | int mv643xx_eth_free_tx_descs(struct net_device *dev, int force) |
344 | unsigned int eth_int_cause_ext) | ||
345 | { | 345 | { |
346 | struct mv643xx_private *mp = netdev_priv(dev); | 346 | struct mv643xx_private *mp = netdev_priv(dev); |
347 | struct net_device_stats *stats = &mp->stats; | 347 | struct eth_tx_desc *desc; |
348 | struct pkt_info pkt_info; | 348 | u32 cmd_sts; |
349 | int released = 1; | 349 | struct sk_buff *skb; |
350 | unsigned long flags; | ||
351 | int tx_index; | ||
352 | dma_addr_t addr; | ||
353 | int count; | ||
354 | int released = 0; | ||
350 | 355 | ||
351 | if (!(eth_int_cause_ext & (BIT0 | BIT8))) | 356 | while (mp->tx_desc_count > 0) { |
352 | return released; | 357 | spin_lock_irqsave(&mp->lock, flags); |
358 | tx_index = mp->tx_used_desc_q; | ||
359 | desc = &mp->p_tx_desc_area[tx_index]; | ||
360 | cmd_sts = desc->cmd_sts; | ||
361 | |||
362 | if (!force && (cmd_sts & ETH_BUFFER_OWNED_BY_DMA)) { | ||
363 | spin_unlock_irqrestore(&mp->lock, flags); | ||
364 | return released; | ||
365 | } | ||
366 | |||
367 | mp->tx_used_desc_q = (tx_index + 1) % mp->tx_ring_size; | ||
368 | mp->tx_desc_count--; | ||
369 | |||
370 | addr = desc->buf_ptr; | ||
371 | count = desc->byte_cnt; | ||
372 | skb = mp->tx_skb[tx_index]; | ||
373 | if (skb) | ||
374 | mp->tx_skb[tx_index] = NULL; | ||
375 | |||
376 | spin_unlock_irqrestore(&mp->lock, flags); | ||
353 | 377 | ||
354 | /* Check only queue 0 */ | 378 | if (cmd_sts & BIT0) { |
355 | while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) { | ||
356 | if (pkt_info.cmd_sts & BIT0) { | ||
357 | printk("%s: Error in TX\n", dev->name); | 379 | printk("%s: Error in TX\n", dev->name); |
358 | stats->tx_errors++; | 380 | mp->stats.tx_errors++; |
359 | } | 381 | } |
360 | 382 | ||
361 | if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC) | 383 | if (cmd_sts & ETH_TX_FIRST_DESC) |
362 | dma_unmap_single(NULL, pkt_info.buf_ptr, | 384 | dma_unmap_single(NULL, addr, count, DMA_TO_DEVICE); |
363 | pkt_info.byte_cnt, | ||
364 | DMA_TO_DEVICE); | ||
365 | else | 385 | else |
366 | dma_unmap_page(NULL, pkt_info.buf_ptr, | 386 | dma_unmap_page(NULL, addr, count, DMA_TO_DEVICE); |
367 | pkt_info.byte_cnt, | ||
368 | DMA_TO_DEVICE); | ||
369 | 387 | ||
370 | if (pkt_info.return_info) { | 388 | if (skb) |
371 | dev_kfree_skb_irq(pkt_info.return_info); | 389 | dev_kfree_skb_irq(skb); |
372 | released = 0; | 390 | |
373 | } | 391 | released = 1; |
374 | } | 392 | } |
375 | 393 | ||
376 | return released; | 394 | return released; |
377 | } | 395 | } |
378 | 396 | ||
397 | static void mv643xx_eth_free_completed_tx_descs(struct net_device *dev) | ||
398 | { | ||
399 | struct mv643xx_private *mp = netdev_priv(dev); | ||
400 | |||
401 | if (mv643xx_eth_free_tx_descs(dev, 0) && | ||
402 | mp->tx_ring_size - mp->tx_desc_count >= MAX_DESCS_PER_SKB) | ||
403 | netif_wake_queue(dev); | ||
404 | } | ||
405 | |||
406 | static void mv643xx_eth_free_all_tx_descs(struct net_device *dev) | ||
407 | { | ||
408 | mv643xx_eth_free_tx_descs(dev, 1); | ||
409 | } | ||
410 | |||
379 | /* | 411 | /* |
380 | * mv643xx_eth_receive | 412 | * mv643xx_eth_receive |
381 | * | 413 | * |
@@ -547,15 +579,13 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, | |||
547 | */ | 579 | */ |
548 | mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), | 580 | mv_write(MV643XX_ETH_INTERRUPT_CAUSE_REG(port_num), |
549 | ~eth_int_cause); | 581 | ~eth_int_cause); |
550 | if (eth_int_cause_ext != 0x0) | 582 | if (eth_int_cause_ext != 0x0) { |
551 | mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG | 583 | mv_write(MV643XX_ETH_INTERRUPT_CAUSE_EXTEND_REG |
552 | (port_num), ~eth_int_cause_ext); | 584 | (port_num), ~eth_int_cause_ext); |
553 | 585 | /* UDP change : We may need this */ | |
554 | /* UDP change : We may need this */ | 586 | if (eth_int_cause_ext & (BIT0 | BIT8)) |
555 | if ((eth_int_cause_ext & 0x0000ffff) && | 587 | mv643xx_eth_free_completed_tx_descs(dev); |
556 | (mv643xx_eth_free_tx_queue(dev, eth_int_cause_ext) == 0) && | 588 | } |
557 | (mp->tx_ring_size - mp->tx_desc_count > MAX_DESCS_PER_SKB)) | ||
558 | netif_wake_queue(dev); | ||
559 | #ifdef MV643XX_NAPI | 589 | #ifdef MV643XX_NAPI |
560 | } else { | 590 | } else { |
561 | if (netif_rx_schedule_prep(dev)) { | 591 | if (netif_rx_schedule_prep(dev)) { |
@@ -596,14 +626,13 @@ static irqreturn_t mv643xx_eth_int_handler(int irq, void *dev_id, | |||
596 | if (mii_link_ok(&mp->mii)) { | 626 | if (mii_link_ok(&mp->mii)) { |
597 | mii_ethtool_gset(&mp->mii, &cmd); | 627 | mii_ethtool_gset(&mp->mii, &cmd); |
598 | mv643xx_eth_update_pscr(dev, &cmd); | 628 | mv643xx_eth_update_pscr(dev, &cmd); |
629 | mv643xx_eth_port_enable_tx(port_num, | ||
630 | ETH_TX_QUEUES_ENABLED); | ||
599 | if (!netif_carrier_ok(dev)) { | 631 | if (!netif_carrier_ok(dev)) { |
600 | netif_carrier_on(dev); | 632 | netif_carrier_on(dev); |
601 | if (mp->tx_ring_size - mp->tx_desc_count > | 633 | if (mp->tx_ring_size - mp->tx_desc_count >= |
602 | MAX_DESCS_PER_SKB) { | 634 | MAX_DESCS_PER_SKB) |
603 | netif_wake_queue(dev); | 635 | netif_wake_queue(dev); |
604 | /* Start TX queue */ | ||
605 | mv643xx_eth_port_enable_tx(port_num, mp->port_tx_queue_command); | ||
606 | } | ||
607 | } | 636 | } |
608 | } else if (netif_carrier_ok(dev)) { | 637 | } else if (netif_carrier_ok(dev)) { |
609 | netif_stop_queue(dev); | 638 | netif_stop_queue(dev); |
@@ -735,9 +764,6 @@ static void ether_init_rx_desc_ring(struct mv643xx_private *mp) | |||
735 | mp->rx_used_desc_q = 0; | 764 | mp->rx_used_desc_q = 0; |
736 | 765 | ||
737 | mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc); | 766 | mp->rx_desc_area_size = rx_desc_num * sizeof(struct eth_rx_desc); |
738 | |||
739 | /* Enable queue 0 for this port */ | ||
740 | mp->port_rx_queue_command = 1; | ||
741 | } | 767 | } |
742 | 768 | ||
743 | /* | 769 | /* |
@@ -779,9 +805,6 @@ static void ether_init_tx_desc_ring(struct mv643xx_private *mp) | |||
779 | mp->tx_used_desc_q = 0; | 805 | mp->tx_used_desc_q = 0; |
780 | 806 | ||
781 | mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc); | 807 | mp->tx_desc_area_size = tx_desc_num * sizeof(struct eth_tx_desc); |
782 | |||
783 | /* Enable queue 0 for this port */ | ||
784 | mp->port_tx_queue_command = 1; | ||
785 | } | 808 | } |
786 | 809 | ||
787 | static int mv643xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 810 | static int mv643xx_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
@@ -963,25 +986,14 @@ out_free_irq: | |||
963 | static void mv643xx_eth_free_tx_rings(struct net_device *dev) | 986 | static void mv643xx_eth_free_tx_rings(struct net_device *dev) |
964 | { | 987 | { |
965 | struct mv643xx_private *mp = netdev_priv(dev); | 988 | struct mv643xx_private *mp = netdev_priv(dev); |
966 | unsigned int port_num = mp->port_num; | ||
967 | unsigned int curr; | ||
968 | struct sk_buff *skb; | ||
969 | 989 | ||
970 | /* Stop Tx Queues */ | 990 | /* Stop Tx Queues */ |
971 | mv643xx_eth_port_disable_tx(port_num); | 991 | mv643xx_eth_port_disable_tx(mp->port_num); |
972 | 992 | ||
973 | /* Free outstanding skb's on TX rings */ | 993 | /* Free outstanding skb's on TX ring */ |
974 | for (curr = 0; mp->tx_desc_count && curr < mp->tx_ring_size; curr++) { | 994 | mv643xx_eth_free_all_tx_descs(dev); |
975 | skb = mp->tx_skb[curr]; | 995 | |
976 | if (skb) { | 996 | BUG_ON(mp->tx_used_desc_q != mp->tx_curr_desc_q); |
977 | mp->tx_desc_count -= skb_shinfo(skb)->nr_frags; | ||
978 | dev_kfree_skb(skb); | ||
979 | mp->tx_desc_count--; | ||
980 | } | ||
981 | } | ||
982 | if (mp->tx_desc_count) | ||
983 | printk("%s: Error on Tx descriptor free - could not free %d" | ||
984 | " descriptors\n", dev->name, mp->tx_desc_count); | ||
985 | 997 | ||
986 | /* Free TX ring */ | 998 | /* Free TX ring */ |
987 | if (mp->tx_sram_size) | 999 | if (mp->tx_sram_size) |
@@ -1062,30 +1074,6 @@ static int mv643xx_eth_stop(struct net_device *dev) | |||
1062 | } | 1074 | } |
1063 | 1075 | ||
1064 | #ifdef MV643XX_NAPI | 1076 | #ifdef MV643XX_NAPI |
1065 | static void mv643xx_tx(struct net_device *dev) | ||
1066 | { | ||
1067 | struct mv643xx_private *mp = netdev_priv(dev); | ||
1068 | struct pkt_info pkt_info; | ||
1069 | |||
1070 | while (eth_tx_return_desc(mp, &pkt_info) == ETH_OK) { | ||
1071 | if (pkt_info.cmd_sts & ETH_TX_FIRST_DESC) | ||
1072 | dma_unmap_single(NULL, pkt_info.buf_ptr, | ||
1073 | pkt_info.byte_cnt, | ||
1074 | DMA_TO_DEVICE); | ||
1075 | else | ||
1076 | dma_unmap_page(NULL, pkt_info.buf_ptr, | ||
1077 | pkt_info.byte_cnt, | ||
1078 | DMA_TO_DEVICE); | ||
1079 | |||
1080 | if (pkt_info.return_info) | ||
1081 | dev_kfree_skb_irq(pkt_info.return_info); | ||
1082 | } | ||
1083 | |||
1084 | if (netif_queue_stopped(dev) && | ||
1085 | mp->tx_ring_size - mp->tx_desc_count > MAX_DESCS_PER_SKB) | ||
1086 | netif_wake_queue(dev); | ||
1087 | } | ||
1088 | |||
1089 | /* | 1077 | /* |
1090 | * mv643xx_poll | 1078 | * mv643xx_poll |
1091 | * | 1079 | * |
@@ -1099,7 +1087,7 @@ static int mv643xx_poll(struct net_device *dev, int *budget) | |||
1099 | 1087 | ||
1100 | #ifdef MV643XX_TX_FAST_REFILL | 1088 | #ifdef MV643XX_TX_FAST_REFILL |
1101 | if (++mp->tx_clean_threshold > 5) { | 1089 | if (++mp->tx_clean_threshold > 5) { |
1102 | mv643xx_tx(dev); | 1090 | mv643xx_eth_free_completed_tx_descs(dev); |
1103 | mp->tx_clean_threshold = 0; | 1091 | mp->tx_clean_threshold = 0; |
1104 | } | 1092 | } |
1105 | #endif | 1093 | #endif |
@@ -1156,11 +1144,9 @@ static int eth_alloc_tx_desc_index(struct mv643xx_private *mp) | |||
1156 | { | 1144 | { |
1157 | int tx_desc_curr; | 1145 | int tx_desc_curr; |
1158 | 1146 | ||
1159 | tx_desc_curr = mp->tx_curr_desc_q; | ||
1160 | |||
1161 | BUG_ON(mp->tx_desc_count >= mp->tx_ring_size); | 1147 | BUG_ON(mp->tx_desc_count >= mp->tx_ring_size); |
1162 | mp->tx_desc_count++; | ||
1163 | 1148 | ||
1149 | tx_desc_curr = mp->tx_curr_desc_q; | ||
1164 | mp->tx_curr_desc_q = (tx_desc_curr + 1) % mp->tx_ring_size; | 1150 | mp->tx_curr_desc_q = (tx_desc_curr + 1) % mp->tx_ring_size; |
1165 | 1151 | ||
1166 | BUG_ON(mp->tx_curr_desc_q == mp->tx_used_desc_q); | 1152 | BUG_ON(mp->tx_curr_desc_q == mp->tx_used_desc_q); |
@@ -1180,7 +1166,6 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, | |||
1180 | int frag; | 1166 | int frag; |
1181 | int tx_index; | 1167 | int tx_index; |
1182 | struct eth_tx_desc *desc; | 1168 | struct eth_tx_desc *desc; |
1183 | struct net_device_stats *stats = &mp->stats; | ||
1184 | 1169 | ||
1185 | for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { | 1170 | for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { |
1186 | skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag]; | 1171 | skb_frag_t *this_frag = &skb_shinfo(skb)->frags[frag]; |
@@ -1205,7 +1190,6 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, | |||
1205 | this_frag->page_offset, | 1190 | this_frag->page_offset, |
1206 | this_frag->size, | 1191 | this_frag->size, |
1207 | DMA_TO_DEVICE); | 1192 | DMA_TO_DEVICE); |
1208 | stats->tx_bytes += this_frag->size; | ||
1209 | } | 1193 | } |
1210 | } | 1194 | } |
1211 | 1195 | ||
@@ -1215,21 +1199,21 @@ static void eth_tx_fill_frag_descs(struct mv643xx_private *mp, | |||
1215 | * Ensure the data for an skb to be transmitted is mapped properly, | 1199 | * Ensure the data for an skb to be transmitted is mapped properly, |
1216 | * then fill in descriptors in the tx hw queue and start the hardware. | 1200 | * then fill in descriptors in the tx hw queue and start the hardware. |
1217 | */ | 1201 | */ |
1218 | static int eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, | 1202 | static void eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, |
1219 | struct sk_buff *skb) | 1203 | struct sk_buff *skb) |
1220 | { | 1204 | { |
1221 | int tx_index; | 1205 | int tx_index; |
1222 | struct eth_tx_desc *desc; | 1206 | struct eth_tx_desc *desc; |
1223 | u32 cmd_sts; | 1207 | u32 cmd_sts; |
1224 | int length; | 1208 | int length; |
1225 | int tx_bytes = 0; | 1209 | int nr_frags = skb_shinfo(skb)->nr_frags; |
1226 | 1210 | ||
1227 | cmd_sts = ETH_TX_FIRST_DESC | ETH_GEN_CRC | ETH_BUFFER_OWNED_BY_DMA; | 1211 | cmd_sts = ETH_TX_FIRST_DESC | ETH_GEN_CRC | ETH_BUFFER_OWNED_BY_DMA; |
1228 | 1212 | ||
1229 | tx_index = eth_alloc_tx_desc_index(mp); | 1213 | tx_index = eth_alloc_tx_desc_index(mp); |
1230 | desc = &mp->p_tx_desc_area[tx_index]; | 1214 | desc = &mp->p_tx_desc_area[tx_index]; |
1231 | 1215 | ||
1232 | if (skb_shinfo(skb)->nr_frags) { | 1216 | if (nr_frags) { |
1233 | eth_tx_fill_frag_descs(mp, skb); | 1217 | eth_tx_fill_frag_descs(mp, skb); |
1234 | 1218 | ||
1235 | length = skb_headlen(skb); | 1219 | length = skb_headlen(skb); |
@@ -1244,7 +1228,6 @@ static int eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, | |||
1244 | 1228 | ||
1245 | desc->byte_cnt = length; | 1229 | desc->byte_cnt = length; |
1246 | desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); | 1230 | desc->buf_ptr = dma_map_single(NULL, skb->data, length, DMA_TO_DEVICE); |
1247 | tx_bytes += length; | ||
1248 | 1231 | ||
1249 | if (skb->ip_summed == CHECKSUM_HW) { | 1232 | if (skb->ip_summed == CHECKSUM_HW) { |
1250 | BUG_ON(skb->protocol != ETH_P_IP); | 1233 | BUG_ON(skb->protocol != ETH_P_IP); |
@@ -1276,9 +1259,9 @@ static int eth_tx_submit_descs_for_skb(struct mv643xx_private *mp, | |||
1276 | 1259 | ||
1277 | /* ensure all descriptors are written before poking hardware */ | 1260 | /* ensure all descriptors are written before poking hardware */ |
1278 | wmb(); | 1261 | wmb(); |
1279 | mv643xx_eth_port_enable_tx(mp->port_num, mp->port_tx_queue_command); | 1262 | mv643xx_eth_port_enable_tx(mp->port_num, ETH_TX_QUEUES_ENABLED); |
1280 | 1263 | ||
1281 | return tx_bytes; | 1264 | mp->tx_desc_count += nr_frags + 1; |
1282 | } | 1265 | } |
1283 | 1266 | ||
1284 | /** | 1267 | /** |
@@ -1306,7 +1289,8 @@ static int mv643xx_eth_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1306 | 1289 | ||
1307 | spin_lock_irqsave(&mp->lock, flags); | 1290 | spin_lock_irqsave(&mp->lock, flags); |
1308 | 1291 | ||
1309 | stats->tx_bytes = eth_tx_submit_descs_for_skb(mp, skb); | 1292 | eth_tx_submit_descs_for_skb(mp, skb); |
1293 | stats->tx_bytes = skb->len; | ||
1310 | stats->tx_packets++; | 1294 | stats->tx_packets++; |
1311 | dev->trans_start = jiffies; | 1295 | dev->trans_start = jiffies; |
1312 | 1296 | ||
@@ -1893,7 +1877,7 @@ static void eth_port_start(struct net_device *dev) | |||
1893 | MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE); | 1877 | MV643XX_ETH_PORT_SDMA_CONFIG_DEFAULT_VALUE); |
1894 | 1878 | ||
1895 | /* Enable port Rx. */ | 1879 | /* Enable port Rx. */ |
1896 | mv643xx_eth_port_enable_rx(port_num, mp->port_rx_queue_command); | 1880 | mv643xx_eth_port_enable_rx(port_num, ETH_RX_QUEUES_ENABLED); |
1897 | 1881 | ||
1898 | /* Disable port bandwidth limits by clearing MTU register */ | 1882 | /* Disable port bandwidth limits by clearing MTU register */ |
1899 | mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); | 1883 | mv_write(MV643XX_ETH_MAXIMUM_TRANSMIT_UNIT(port_num), 0); |
@@ -2602,79 +2586,6 @@ static void mv643xx_mdio_write(struct net_device *dev, int phy_id, int location, | |||
2602 | } | 2586 | } |
2603 | 2587 | ||
2604 | /* | 2588 | /* |
2605 | * eth_tx_return_desc - Free all used Tx descriptors | ||
2606 | * | ||
2607 | * DESCRIPTION: | ||
2608 | * This routine returns the transmitted packet information to the caller. | ||
2609 | * It uses the 'first' index to support Tx desc return in case a transmit | ||
2610 | * of a packet spanned over multiple buffer still in process. | ||
2611 | * In case the Tx queue was in "resource error" condition, where there are | ||
2612 | * no available Tx resources, the function resets the resource error flag. | ||
2613 | * | ||
2614 | * INPUT: | ||
2615 | * struct mv643xx_private *mp Ethernet Port Control srtuct. | ||
2616 | * struct pkt_info *p_pkt_info User packet buffer. | ||
2617 | * | ||
2618 | * OUTPUT: | ||
2619 | * Tx ring 'first' and 'used' indexes are updated. | ||
2620 | * | ||
2621 | * RETURN: | ||
2622 | * ETH_OK on success | ||
2623 | * ETH_ERROR otherwise. | ||
2624 | * | ||
2625 | */ | ||
2626 | static ETH_FUNC_RET_STATUS eth_tx_return_desc(struct mv643xx_private *mp, | ||
2627 | struct pkt_info *p_pkt_info) | ||
2628 | { | ||
2629 | int tx_desc_used; | ||
2630 | struct eth_tx_desc *p_tx_desc_used; | ||
2631 | unsigned int command_status; | ||
2632 | unsigned long flags; | ||
2633 | int err = ETH_OK; | ||
2634 | |||
2635 | spin_lock_irqsave(&mp->lock, flags); | ||
2636 | |||
2637 | BUG_ON(mp->tx_desc_count < 0); | ||
2638 | if (mp->tx_desc_count == 0) { | ||
2639 | /* no more tx descs in use */ | ||
2640 | err = ETH_ERROR; | ||
2641 | goto out; | ||
2642 | } | ||
2643 | |||
2644 | /* Get the Tx Desc ring indexes */ | ||
2645 | tx_desc_used = mp->tx_used_desc_q; | ||
2646 | |||
2647 | p_tx_desc_used = &mp->p_tx_desc_area[tx_desc_used]; | ||
2648 | |||
2649 | BUG_ON(p_tx_desc_used == NULL); | ||
2650 | |||
2651 | command_status = p_tx_desc_used->cmd_sts; | ||
2652 | if (command_status & (ETH_BUFFER_OWNED_BY_DMA)) { | ||
2653 | /* Still transmitting... */ | ||
2654 | err = ETH_ERROR; | ||
2655 | goto out; | ||
2656 | } | ||
2657 | |||
2658 | /* Pass the packet information to the caller */ | ||
2659 | p_pkt_info->cmd_sts = command_status; | ||
2660 | p_pkt_info->return_info = mp->tx_skb[tx_desc_used]; | ||
2661 | p_pkt_info->buf_ptr = p_tx_desc_used->buf_ptr; | ||
2662 | p_pkt_info->byte_cnt = p_tx_desc_used->byte_cnt; | ||
2663 | mp->tx_skb[tx_desc_used] = NULL; | ||
2664 | |||
2665 | /* Update the next descriptor to release. */ | ||
2666 | mp->tx_used_desc_q = (tx_desc_used + 1) % mp->tx_ring_size; | ||
2667 | |||
2668 | BUG_ON(mp->tx_desc_count == 0); | ||
2669 | mp->tx_desc_count--; | ||
2670 | |||
2671 | out: | ||
2672 | spin_unlock_irqrestore(&mp->lock, flags); | ||
2673 | |||
2674 | return err; | ||
2675 | } | ||
2676 | |||
2677 | /* | ||
2678 | * eth_port_receive - Get received information from Rx ring. | 2589 | * eth_port_receive - Get received information from Rx ring. |
2679 | * | 2590 | * |
2680 | * DESCRIPTION: | 2591 | * DESCRIPTION: |