diff options
Diffstat (limited to 'drivers/net/bfin_mac.c')
-rw-r--r-- | drivers/net/bfin_mac.c | 123 |
1 files changed, 80 insertions, 43 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 368f33313fb..012613fde3f 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
@@ -922,61 +922,73 @@ static void bfin_mac_hwtstamp_init(struct net_device *netdev) | |||
922 | # define bfin_tx_hwtstamp(dev, skb) | 922 | # define bfin_tx_hwtstamp(dev, skb) |
923 | #endif | 923 | #endif |
924 | 924 | ||
925 | static void adjust_tx_list(void) | 925 | static inline void _tx_reclaim_skb(void) |
926 | { | ||
927 | do { | ||
928 | tx_list_head->desc_a.config &= ~DMAEN; | ||
929 | tx_list_head->status.status_word = 0; | ||
930 | if (tx_list_head->skb) { | ||
931 | dev_kfree_skb(tx_list_head->skb); | ||
932 | tx_list_head->skb = NULL; | ||
933 | } | ||
934 | tx_list_head = tx_list_head->next; | ||
935 | |||
936 | } while (tx_list_head->status.status_word != 0); | ||
937 | } | ||
938 | |||
939 | static void tx_reclaim_skb(struct bfin_mac_local *lp) | ||
926 | { | 940 | { |
927 | int timeout_cnt = MAX_TIMEOUT_CNT; | 941 | int timeout_cnt = MAX_TIMEOUT_CNT; |
928 | 942 | ||
929 | if (tx_list_head->status.status_word != 0 && | 943 | if (tx_list_head->status.status_word != 0) |
930 | current_tx_ptr != tx_list_head) { | 944 | _tx_reclaim_skb(); |
931 | goto adjust_head; /* released something, just return; */ | ||
932 | } | ||
933 | 945 | ||
934 | /* | 946 | if (current_tx_ptr->next == tx_list_head) { |
935 | * if nothing released, check wait condition | ||
936 | * current's next can not be the head, | ||
937 | * otherwise the dma will not stop as we want | ||
938 | */ | ||
939 | if (current_tx_ptr->next->next == tx_list_head) { | ||
940 | while (tx_list_head->status.status_word == 0) { | 947 | while (tx_list_head->status.status_word == 0) { |
948 | /* slow down polling to avoid too many queue stop. */ | ||
941 | udelay(10); | 949 | udelay(10); |
942 | if (tx_list_head->status.status_word != 0 || | 950 | /* reclaim skb if DMA is not running. */ |
943 | !(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) { | 951 | if (!(bfin_read_DMA2_IRQ_STATUS() & DMA_RUN)) |
944 | goto adjust_head; | 952 | break; |
945 | } | 953 | if (timeout_cnt-- < 0) |
946 | if (timeout_cnt-- < 0) { | ||
947 | printk(KERN_ERR DRV_NAME | ||
948 | ": wait for adjust tx list head timeout\n"); | ||
949 | break; | 954 | break; |
950 | } | ||
951 | } | ||
952 | if (tx_list_head->status.status_word != 0) { | ||
953 | goto adjust_head; | ||
954 | } | 955 | } |
956 | |||
957 | if (timeout_cnt >= 0) | ||
958 | _tx_reclaim_skb(); | ||
959 | else | ||
960 | netif_stop_queue(lp->ndev); | ||
955 | } | 961 | } |
956 | 962 | ||
957 | return; | 963 | if (current_tx_ptr->next != tx_list_head && |
964 | netif_queue_stopped(lp->ndev)) | ||
965 | netif_wake_queue(lp->ndev); | ||
966 | |||
967 | if (tx_list_head != current_tx_ptr) { | ||
968 | /* shorten the timer interval if tx queue is stopped */ | ||
969 | if (netif_queue_stopped(lp->ndev)) | ||
970 | lp->tx_reclaim_timer.expires = | ||
971 | jiffies + (TX_RECLAIM_JIFFIES >> 4); | ||
972 | else | ||
973 | lp->tx_reclaim_timer.expires = | ||
974 | jiffies + TX_RECLAIM_JIFFIES; | ||
975 | |||
976 | mod_timer(&lp->tx_reclaim_timer, | ||
977 | lp->tx_reclaim_timer.expires); | ||
978 | } | ||
958 | 979 | ||
959 | adjust_head: | ||
960 | do { | ||
961 | tx_list_head->desc_a.config &= ~DMAEN; | ||
962 | tx_list_head->status.status_word = 0; | ||
963 | if (tx_list_head->skb) { | ||
964 | dev_kfree_skb(tx_list_head->skb); | ||
965 | tx_list_head->skb = NULL; | ||
966 | } else { | ||
967 | printk(KERN_ERR DRV_NAME | ||
968 | ": no sk_buff in a transmitted frame!\n"); | ||
969 | } | ||
970 | tx_list_head = tx_list_head->next; | ||
971 | } while (tx_list_head->status.status_word != 0 && | ||
972 | current_tx_ptr != tx_list_head); | ||
973 | return; | 980 | return; |
981 | } | ||
974 | 982 | ||
983 | static void tx_reclaim_skb_timeout(unsigned long lp) | ||
984 | { | ||
985 | tx_reclaim_skb((struct bfin_mac_local *)lp); | ||
975 | } | 986 | } |
976 | 987 | ||
977 | static int bfin_mac_hard_start_xmit(struct sk_buff *skb, | 988 | static int bfin_mac_hard_start_xmit(struct sk_buff *skb, |
978 | struct net_device *dev) | 989 | struct net_device *dev) |
979 | { | 990 | { |
991 | struct bfin_mac_local *lp = netdev_priv(dev); | ||
980 | u16 *data; | 992 | u16 *data; |
981 | u32 data_align = (unsigned long)(skb->data) & 0x3; | 993 | u32 data_align = (unsigned long)(skb->data) & 0x3; |
982 | union skb_shared_tx *shtx = skb_tx(skb); | 994 | union skb_shared_tx *shtx = skb_tx(skb); |
@@ -1009,8 +1021,6 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, | |||
1009 | skb->len); | 1021 | skb->len); |
1010 | current_tx_ptr->desc_a.start_addr = | 1022 | current_tx_ptr->desc_a.start_addr = |
1011 | (u32)current_tx_ptr->packet; | 1023 | (u32)current_tx_ptr->packet; |
1012 | if (current_tx_ptr->status.status_word != 0) | ||
1013 | current_tx_ptr->status.status_word = 0; | ||
1014 | blackfin_dcache_flush_range( | 1024 | blackfin_dcache_flush_range( |
1015 | (u32)current_tx_ptr->packet, | 1025 | (u32)current_tx_ptr->packet, |
1016 | (u32)(current_tx_ptr->packet + skb->len + 2)); | 1026 | (u32)(current_tx_ptr->packet + skb->len + 2)); |
@@ -1022,6 +1032,9 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, | |||
1022 | */ | 1032 | */ |
1023 | SSYNC(); | 1033 | SSYNC(); |
1024 | 1034 | ||
1035 | /* always clear status buffer before start tx dma */ | ||
1036 | current_tx_ptr->status.status_word = 0; | ||
1037 | |||
1025 | /* enable this packet's dma */ | 1038 | /* enable this packet's dma */ |
1026 | current_tx_ptr->desc_a.config |= DMAEN; | 1039 | current_tx_ptr->desc_a.config |= DMAEN; |
1027 | 1040 | ||
@@ -1037,13 +1050,14 @@ static int bfin_mac_hard_start_xmit(struct sk_buff *skb, | |||
1037 | bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); | 1050 | bfin_write_EMAC_OPMODE(bfin_read_EMAC_OPMODE() | TE); |
1038 | 1051 | ||
1039 | out: | 1052 | out: |
1040 | adjust_tx_list(); | ||
1041 | |||
1042 | bfin_tx_hwtstamp(dev, skb); | 1053 | bfin_tx_hwtstamp(dev, skb); |
1043 | 1054 | ||
1044 | current_tx_ptr = current_tx_ptr->next; | 1055 | current_tx_ptr = current_tx_ptr->next; |
1045 | dev->stats.tx_packets++; | 1056 | dev->stats.tx_packets++; |
1046 | dev->stats.tx_bytes += (skb->len); | 1057 | dev->stats.tx_bytes += (skb->len); |
1058 | |||
1059 | tx_reclaim_skb(lp); | ||
1060 | |||
1047 | return NETDEV_TX_OK; | 1061 | return NETDEV_TX_OK; |
1048 | } | 1062 | } |
1049 | 1063 | ||
@@ -1167,8 +1181,11 @@ real_rx: | |||
1167 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1181 | #ifdef CONFIG_NET_POLL_CONTROLLER |
1168 | static void bfin_mac_poll(struct net_device *dev) | 1182 | static void bfin_mac_poll(struct net_device *dev) |
1169 | { | 1183 | { |
1184 | struct bfin_mac_local *lp = netdev_priv(dev); | ||
1185 | |||
1170 | disable_irq(IRQ_MAC_RX); | 1186 | disable_irq(IRQ_MAC_RX); |
1171 | bfin_mac_interrupt(IRQ_MAC_RX, dev); | 1187 | bfin_mac_interrupt(IRQ_MAC_RX, dev); |
1188 | tx_reclaim_skb(lp); | ||
1172 | enable_irq(IRQ_MAC_RX); | 1189 | enable_irq(IRQ_MAC_RX); |
1173 | } | 1190 | } |
1174 | #endif /* CONFIG_NET_POLL_CONTROLLER */ | 1191 | #endif /* CONFIG_NET_POLL_CONTROLLER */ |
@@ -1232,12 +1249,27 @@ static int bfin_mac_enable(void) | |||
1232 | /* Our watchdog timed out. Called by the networking layer */ | 1249 | /* Our watchdog timed out. Called by the networking layer */ |
1233 | static void bfin_mac_timeout(struct net_device *dev) | 1250 | static void bfin_mac_timeout(struct net_device *dev) |
1234 | { | 1251 | { |
1252 | struct bfin_mac_local *lp = netdev_priv(dev); | ||
1253 | |||
1235 | pr_debug("%s: %s\n", dev->name, __func__); | 1254 | pr_debug("%s: %s\n", dev->name, __func__); |
1236 | 1255 | ||
1237 | bfin_mac_disable(); | 1256 | bfin_mac_disable(); |
1238 | 1257 | ||
1239 | /* reset tx queue */ | 1258 | del_timer(&lp->tx_reclaim_timer); |
1240 | tx_list_tail = tx_list_head->next; | 1259 | |
1260 | /* reset tx queue and free skb */ | ||
1261 | while (tx_list_head != current_tx_ptr) { | ||
1262 | tx_list_head->desc_a.config &= ~DMAEN; | ||
1263 | tx_list_head->status.status_word = 0; | ||
1264 | if (tx_list_head->skb) { | ||
1265 | dev_kfree_skb(tx_list_head->skb); | ||
1266 | tx_list_head->skb = NULL; | ||
1267 | } | ||
1268 | tx_list_head = tx_list_head->next; | ||
1269 | } | ||
1270 | |||
1271 | if (netif_queue_stopped(lp->ndev)) | ||
1272 | netif_wake_queue(lp->ndev); | ||
1241 | 1273 | ||
1242 | bfin_mac_enable(); | 1274 | bfin_mac_enable(); |
1243 | 1275 | ||
@@ -1430,6 +1462,7 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) | |||
1430 | SET_NETDEV_DEV(ndev, &pdev->dev); | 1462 | SET_NETDEV_DEV(ndev, &pdev->dev); |
1431 | platform_set_drvdata(pdev, ndev); | 1463 | platform_set_drvdata(pdev, ndev); |
1432 | lp = netdev_priv(ndev); | 1464 | lp = netdev_priv(ndev); |
1465 | lp->ndev = ndev; | ||
1433 | 1466 | ||
1434 | /* Grab the MAC address in the MAC */ | 1467 | /* Grab the MAC address in the MAC */ |
1435 | *(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO()); | 1468 | *(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO()); |
@@ -1485,6 +1518,10 @@ static int __devinit bfin_mac_probe(struct platform_device *pdev) | |||
1485 | ndev->netdev_ops = &bfin_mac_netdev_ops; | 1518 | ndev->netdev_ops = &bfin_mac_netdev_ops; |
1486 | ndev->ethtool_ops = &bfin_mac_ethtool_ops; | 1519 | ndev->ethtool_ops = &bfin_mac_ethtool_ops; |
1487 | 1520 | ||
1521 | init_timer(&lp->tx_reclaim_timer); | ||
1522 | lp->tx_reclaim_timer.data = (unsigned long)lp; | ||
1523 | lp->tx_reclaim_timer.function = tx_reclaim_skb_timeout; | ||
1524 | |||
1488 | spin_lock_init(&lp->lock); | 1525 | spin_lock_init(&lp->lock); |
1489 | 1526 | ||
1490 | /* now, enable interrupts */ | 1527 | /* now, enable interrupts */ |