diff options
author | David S. Miller <davem@davemloft.net> | 2013-11-20 15:10:24 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-11-20 15:10:24 -0500 |
commit | 4f837c3b117c4fdae72d901034d0565d16af7966 (patch) | |
tree | 6246b460c504e3119025b5adcfbe518d1d9992d5 | |
parent | b4789b8e6be3151a955ade74872822f30e8cd914 (diff) | |
parent | 500b6d7e1ed80f697571cd976e385c3476effc86 (diff) |
Merge branch 'r8152'
Hayes Wang says:
====================
r8152 bug fixes
For the patch #3, I add netif_tx_lock() before checking the
netif_queue_stopped(). Besides, I add checking the skb queue
length before waking the tx queue.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/usb/r8152.c | 114 |
1 files changed, 50 insertions, 64 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index f3fce412c0c1..51073721e224 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/ipv6.h> | 24 | #include <linux/ipv6.h> |
25 | 25 | ||
26 | /* Version Information */ | 26 | /* Version Information */ |
27 | #define DRIVER_VERSION "v1.01.0 (2013/08/12)" | 27 | #define DRIVER_VERSION "v1.02.0 (2013/10/28)" |
28 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" | 28 | #define DRIVER_AUTHOR "Realtek linux nic maintainers <nic_swsd@realtek.com>" |
29 | #define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters" | 29 | #define DRIVER_DESC "Realtek RTL8152 Based USB 2.0 Ethernet Adapters" |
30 | #define MODULENAME "r8152" | 30 | #define MODULENAME "r8152" |
@@ -307,22 +307,22 @@ enum rtl8152_flags { | |||
307 | #define MCU_TYPE_USB 0x0000 | 307 | #define MCU_TYPE_USB 0x0000 |
308 | 308 | ||
309 | struct rx_desc { | 309 | struct rx_desc { |
310 | u32 opts1; | 310 | __le32 opts1; |
311 | #define RX_LEN_MASK 0x7fff | 311 | #define RX_LEN_MASK 0x7fff |
312 | u32 opts2; | 312 | __le32 opts2; |
313 | u32 opts3; | 313 | __le32 opts3; |
314 | u32 opts4; | 314 | __le32 opts4; |
315 | u32 opts5; | 315 | __le32 opts5; |
316 | u32 opts6; | 316 | __le32 opts6; |
317 | }; | 317 | }; |
318 | 318 | ||
319 | struct tx_desc { | 319 | struct tx_desc { |
320 | u32 opts1; | 320 | __le32 opts1; |
321 | #define TX_FS (1 << 31) /* First segment of a packet */ | 321 | #define TX_FS (1 << 31) /* First segment of a packet */ |
322 | #define TX_LS (1 << 30) /* Final segment of a packet */ | 322 | #define TX_LS (1 << 30) /* Final segment of a packet */ |
323 | #define TX_LEN_MASK 0x3ffff | 323 | #define TX_LEN_MASK 0x3ffff |
324 | 324 | ||
325 | u32 opts2; | 325 | __le32 opts2; |
326 | #define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */ | 326 | #define UDP_CS (1 << 31) /* Calculate UDP/IP checksum */ |
327 | #define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */ | 327 | #define TCP_CS (1 << 30) /* Calculate TCP/IP checksum */ |
328 | #define IPV4_CS (1 << 29) /* Calculate IPv4 checksum */ | 328 | #define IPV4_CS (1 << 29) /* Calculate IPv4 checksum */ |
@@ -365,6 +365,7 @@ struct r8152 { | |||
365 | struct mii_if_info mii; | 365 | struct mii_if_info mii; |
366 | int intr_interval; | 366 | int intr_interval; |
367 | u32 msg_enable; | 367 | u32 msg_enable; |
368 | u32 tx_qlen; | ||
368 | u16 ocp_base; | 369 | u16 ocp_base; |
369 | u8 *intr_buff; | 370 | u8 *intr_buff; |
370 | u8 version; | 371 | u8 version; |
@@ -876,7 +877,7 @@ static void write_bulk_callback(struct urb *urb) | |||
876 | static void intr_callback(struct urb *urb) | 877 | static void intr_callback(struct urb *urb) |
877 | { | 878 | { |
878 | struct r8152 *tp; | 879 | struct r8152 *tp; |
879 | __u16 *d; | 880 | __le16 *d; |
880 | int status = urb->status; | 881 | int status = urb->status; |
881 | int res; | 882 | int res; |
882 | 883 | ||
@@ -1136,14 +1137,14 @@ r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb) | |||
1136 | 1137 | ||
1137 | static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) | 1138 | static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) |
1138 | { | 1139 | { |
1139 | u32 remain; | 1140 | int remain; |
1140 | u8 *tx_data; | 1141 | u8 *tx_data; |
1141 | 1142 | ||
1142 | tx_data = agg->head; | 1143 | tx_data = agg->head; |
1143 | agg->skb_num = agg->skb_len = 0; | 1144 | agg->skb_num = agg->skb_len = 0; |
1144 | remain = rx_buf_sz - sizeof(struct tx_desc); | 1145 | remain = rx_buf_sz; |
1145 | 1146 | ||
1146 | while (remain >= ETH_ZLEN) { | 1147 | while (remain >= ETH_ZLEN + sizeof(struct tx_desc)) { |
1147 | struct tx_desc *tx_desc; | 1148 | struct tx_desc *tx_desc; |
1148 | struct sk_buff *skb; | 1149 | struct sk_buff *skb; |
1149 | unsigned int len; | 1150 | unsigned int len; |
@@ -1152,12 +1153,14 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) | |||
1152 | if (!skb) | 1153 | if (!skb) |
1153 | break; | 1154 | break; |
1154 | 1155 | ||
1156 | remain -= sizeof(*tx_desc); | ||
1155 | len = skb->len; | 1157 | len = skb->len; |
1156 | if (remain < len) { | 1158 | if (remain < len) { |
1157 | skb_queue_head(&tp->tx_queue, skb); | 1159 | skb_queue_head(&tp->tx_queue, skb); |
1158 | break; | 1160 | break; |
1159 | } | 1161 | } |
1160 | 1162 | ||
1163 | tx_data = tx_agg_align(tx_data); | ||
1161 | tx_desc = (struct tx_desc *)tx_data; | 1164 | tx_desc = (struct tx_desc *)tx_data; |
1162 | tx_data += sizeof(*tx_desc); | 1165 | tx_data += sizeof(*tx_desc); |
1163 | 1166 | ||
@@ -1167,11 +1170,18 @@ static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg) | |||
1167 | agg->skb_len += len; | 1170 | agg->skb_len += len; |
1168 | dev_kfree_skb_any(skb); | 1171 | dev_kfree_skb_any(skb); |
1169 | 1172 | ||
1170 | tx_data = tx_agg_align(tx_data + len); | 1173 | tx_data += len; |
1171 | remain = rx_buf_sz - sizeof(*tx_desc) - | 1174 | remain = rx_buf_sz - (int)(tx_agg_align(tx_data) - agg->head); |
1172 | (u32)((void *)tx_data - agg->head); | ||
1173 | } | 1175 | } |
1174 | 1176 | ||
1177 | netif_tx_lock(tp->netdev); | ||
1178 | |||
1179 | if (netif_queue_stopped(tp->netdev) && | ||
1180 | skb_queue_len(&tp->tx_queue) < tp->tx_qlen) | ||
1181 | netif_wake_queue(tp->netdev); | ||
1182 | |||
1183 | netif_tx_unlock(tp->netdev); | ||
1184 | |||
1175 | usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), | 1185 | usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), |
1176 | agg->head, (int)(tx_data - (u8 *)agg->head), | 1186 | agg->head, (int)(tx_data - (u8 *)agg->head), |
1177 | (usb_complete_t)write_bulk_callback, agg); | 1187 | (usb_complete_t)write_bulk_callback, agg); |
@@ -1188,7 +1198,6 @@ static void rx_bottom(struct r8152 *tp) | |||
1188 | list_for_each_safe(cursor, next, &tp->rx_done) { | 1198 | list_for_each_safe(cursor, next, &tp->rx_done) { |
1189 | struct rx_desc *rx_desc; | 1199 | struct rx_desc *rx_desc; |
1190 | struct rx_agg *agg; | 1200 | struct rx_agg *agg; |
1191 | unsigned pkt_len; | ||
1192 | int len_used = 0; | 1201 | int len_used = 0; |
1193 | struct urb *urb; | 1202 | struct urb *urb; |
1194 | u8 *rx_data; | 1203 | u8 *rx_data; |
@@ -1204,17 +1213,22 @@ static void rx_bottom(struct r8152 *tp) | |||
1204 | 1213 | ||
1205 | rx_desc = agg->head; | 1214 | rx_desc = agg->head; |
1206 | rx_data = agg->head; | 1215 | rx_data = agg->head; |
1207 | pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; | 1216 | len_used += sizeof(struct rx_desc); |
1208 | len_used += sizeof(struct rx_desc) + pkt_len; | ||
1209 | 1217 | ||
1210 | while (urb->actual_length >= len_used) { | 1218 | while (urb->actual_length > len_used) { |
1211 | struct net_device *netdev = tp->netdev; | 1219 | struct net_device *netdev = tp->netdev; |
1212 | struct net_device_stats *stats; | 1220 | struct net_device_stats *stats; |
1221 | unsigned int pkt_len; | ||
1213 | struct sk_buff *skb; | 1222 | struct sk_buff *skb; |
1214 | 1223 | ||
1224 | pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; | ||
1215 | if (pkt_len < ETH_ZLEN) | 1225 | if (pkt_len < ETH_ZLEN) |
1216 | break; | 1226 | break; |
1217 | 1227 | ||
1228 | len_used += pkt_len; | ||
1229 | if (urb->actual_length < len_used) | ||
1230 | break; | ||
1231 | |||
1218 | stats = rtl8152_get_stats(netdev); | 1232 | stats = rtl8152_get_stats(netdev); |
1219 | 1233 | ||
1220 | pkt_len -= 4; /* CRC */ | 1234 | pkt_len -= 4; /* CRC */ |
@@ -1234,9 +1248,8 @@ static void rx_bottom(struct r8152 *tp) | |||
1234 | 1248 | ||
1235 | rx_data = rx_agg_align(rx_data + pkt_len + 4); | 1249 | rx_data = rx_agg_align(rx_data + pkt_len + 4); |
1236 | rx_desc = (struct rx_desc *)rx_data; | 1250 | rx_desc = (struct rx_desc *)rx_data; |
1237 | pkt_len = le32_to_cpu(rx_desc->opts1) & RX_LEN_MASK; | ||
1238 | len_used = (int)(rx_data - (u8 *)agg->head); | 1251 | len_used = (int)(rx_data - (u8 *)agg->head); |
1239 | len_used += sizeof(struct rx_desc) + pkt_len; | 1252 | len_used += sizeof(struct rx_desc); |
1240 | } | 1253 | } |
1241 | 1254 | ||
1242 | submit: | 1255 | submit: |
@@ -1384,53 +1397,17 @@ static netdev_tx_t rtl8152_start_xmit(struct sk_buff *skb, | |||
1384 | struct net_device *netdev) | 1397 | struct net_device *netdev) |
1385 | { | 1398 | { |
1386 | struct r8152 *tp = netdev_priv(netdev); | 1399 | struct r8152 *tp = netdev_priv(netdev); |
1387 | struct net_device_stats *stats = rtl8152_get_stats(netdev); | ||
1388 | unsigned long flags; | ||
1389 | struct tx_agg *agg = NULL; | ||
1390 | struct tx_desc *tx_desc; | ||
1391 | unsigned int len; | ||
1392 | u8 *tx_data; | ||
1393 | int res; | ||
1394 | 1400 | ||
1395 | skb_tx_timestamp(skb); | 1401 | skb_tx_timestamp(skb); |
1396 | 1402 | ||
1397 | /* If tx_queue is not empty, it means at least one previous packt */ | 1403 | skb_queue_tail(&tp->tx_queue, skb); |
1398 | /* is waiting for sending. Don't send current one before it. */ | ||
1399 | if (skb_queue_empty(&tp->tx_queue)) | ||
1400 | agg = r8152_get_tx_agg(tp); | ||
1401 | |||
1402 | if (!agg) { | ||
1403 | skb_queue_tail(&tp->tx_queue, skb); | ||
1404 | return NETDEV_TX_OK; | ||
1405 | } | ||
1406 | 1404 | ||
1407 | tx_desc = (struct tx_desc *)agg->head; | 1405 | if (list_empty(&tp->tx_free) && |
1408 | tx_data = agg->head + sizeof(*tx_desc); | 1406 | skb_queue_len(&tp->tx_queue) > tp->tx_qlen) |
1409 | agg->skb_num = agg->skb_len = 0; | 1407 | netif_stop_queue(netdev); |
1410 | 1408 | ||
1411 | len = skb->len; | 1409 | if (!list_empty(&tp->tx_free)) |
1412 | r8152_tx_csum(tp, tx_desc, skb); | 1410 | tasklet_schedule(&tp->tl); |
1413 | memcpy(tx_data, skb->data, len); | ||
1414 | dev_kfree_skb_any(skb); | ||
1415 | agg->skb_num++; | ||
1416 | agg->skb_len += len; | ||
1417 | usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2), | ||
1418 | agg->head, len + sizeof(*tx_desc), | ||
1419 | (usb_complete_t)write_bulk_callback, agg); | ||
1420 | res = usb_submit_urb(agg->urb, GFP_ATOMIC); | ||
1421 | if (res) { | ||
1422 | /* Can we get/handle EPIPE here? */ | ||
1423 | if (res == -ENODEV) { | ||
1424 | netif_device_detach(tp->netdev); | ||
1425 | } else { | ||
1426 | netif_warn(tp, tx_err, netdev, | ||
1427 | "failed tx_urb %d\n", res); | ||
1428 | stats->tx_dropped++; | ||
1429 | spin_lock_irqsave(&tp->tx_lock, flags); | ||
1430 | list_add_tail(&agg->list, &tp->tx_free); | ||
1431 | spin_unlock_irqrestore(&tp->tx_lock, flags); | ||
1432 | } | ||
1433 | } | ||
1434 | 1411 | ||
1435 | return NETDEV_TX_OK; | 1412 | return NETDEV_TX_OK; |
1436 | } | 1413 | } |
@@ -1459,6 +1436,14 @@ static void rtl8152_nic_reset(struct r8152 *tp) | |||
1459 | } | 1436 | } |
1460 | } | 1437 | } |
1461 | 1438 | ||
1439 | static void set_tx_qlen(struct r8152 *tp) | ||
1440 | { | ||
1441 | struct net_device *netdev = tp->netdev; | ||
1442 | |||
1443 | tp->tx_qlen = rx_buf_sz / (netdev->mtu + VLAN_ETH_HLEN + VLAN_HLEN + | ||
1444 | sizeof(struct tx_desc)); | ||
1445 | } | ||
1446 | |||
1462 | static inline u8 rtl8152_get_speed(struct r8152 *tp) | 1447 | static inline u8 rtl8152_get_speed(struct r8152 *tp) |
1463 | { | 1448 | { |
1464 | return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); | 1449 | return ocp_read_byte(tp, MCU_TYPE_PLA, PLA_PHYSTATUS); |
@@ -1470,6 +1455,7 @@ static int rtl8152_enable(struct r8152 *tp) | |||
1470 | int i, ret; | 1455 | int i, ret; |
1471 | u8 speed; | 1456 | u8 speed; |
1472 | 1457 | ||
1458 | set_tx_qlen(tp); | ||
1473 | speed = rtl8152_get_speed(tp); | 1459 | speed = rtl8152_get_speed(tp); |
1474 | if (speed & _10bps) { | 1460 | if (speed & _10bps) { |
1475 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); | 1461 | ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_EEEP_CR); |