aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/usb
diff options
context:
space:
mode:
authorhayeswang <hayeswang@realtek.com>2013-08-16 04:09:37 -0400
committerDavid S. Miller <davem@davemloft.net>2013-08-20 03:08:22 -0400
commitb1379d9a20167c41b682e96841b34aab32ec50a5 (patch)
treee8e6f0cb11f84fbdfd916456b84b684173ba98f1 /drivers/net/usb
parent43a4478d65ffaa1c2def8ffceafbc3a3f1e99b82 (diff)
r8152: adjust tx_bottom function
Split some parts of code into another function to simplify tx_bottom(). Use while loop to replace the goto loop. Signed-off-by: Hayes Wang <hayeswang@realtek.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/usb')
-rw-r--r--drivers/net/usb/r8152.c134
1 files changed, 68 insertions, 66 deletions
diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index 0a88f647f075..825edfe8c088 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -1131,6 +1131,51 @@ r8152_tx_csum(struct r8152 *tp, struct tx_desc *desc, struct sk_buff *skb)
1131 } 1131 }
1132} 1132}
1133 1133
1134static int r8152_tx_agg_fill(struct r8152 *tp, struct tx_agg *agg)
1135{
1136 u32 remain;
1137 u8 *tx_data;
1138
1139 tx_data = agg->head;
1140 agg->skb_num = agg->skb_len = 0;
1141 remain = rx_buf_sz - sizeof(struct tx_desc);
1142
1143 while (remain >= ETH_ZLEN) {
1144 struct tx_desc *tx_desc;
1145 struct sk_buff *skb;
1146 unsigned int len;
1147
1148 skb = skb_dequeue(&tp->tx_queue);
1149 if (!skb)
1150 break;
1151
1152 len = skb->len;
1153 if (remain < len) {
1154 skb_queue_head(&tp->tx_queue, skb);
1155 break;
1156 }
1157
1158 tx_desc = (struct tx_desc *)tx_data;
1159 tx_data += sizeof(*tx_desc);
1160
1161 r8152_tx_csum(tp, tx_desc, skb);
1162 memcpy(tx_data, skb->data, len);
1163 agg->skb_num++;
1164 agg->skb_len += len;
1165 dev_kfree_skb_any(skb);
1166
1167 tx_data = tx_agg_align(tx_data + len);
1168 remain = rx_buf_sz - sizeof(*tx_desc) -
1169 (u32)((void *)tx_data - agg->head);
1170 }
1171
1172 usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
1173 agg->head, (int)(tx_data - (u8 *)agg->head),
1174 (usb_complete_t)write_bulk_callback, agg);
1175
1176 return usb_submit_urb(agg->urb, GFP_ATOMIC);
1177}
1178
1134static void rx_bottom(struct r8152 *tp) 1179static void rx_bottom(struct r8152 *tp)
1135{ 1180{
1136 unsigned long flags; 1181 unsigned long flags;
@@ -1204,82 +1249,39 @@ submit:
1204 1249
1205static void tx_bottom(struct r8152 *tp) 1250static void tx_bottom(struct r8152 *tp)
1206{ 1251{
1207 struct net_device_stats *stats;
1208 struct net_device *netdev;
1209 struct tx_agg *agg;
1210 unsigned long flags;
1211 u32 remain, total;
1212 u8 *tx_data;
1213 int res; 1252 int res;
1214 1253
1215 netdev = tp->netdev; 1254 do {
1216 1255 struct tx_agg *agg;
1217next_agg:
1218 agg = NULL;
1219 if (skb_queue_empty(&tp->tx_queue))
1220 return;
1221 1256
1222 agg = r8152_get_tx_agg(tp); 1257 if (skb_queue_empty(&tp->tx_queue))
1223 if (!agg)
1224 return;
1225
1226 tx_data = agg->head;
1227 agg->skb_num = agg->skb_len = 0;
1228 remain = rx_buf_sz - sizeof(struct tx_desc);
1229 total = 0;
1230
1231 while (remain >= ETH_ZLEN) {
1232 struct tx_desc *tx_desc;
1233 struct sk_buff *skb;
1234 unsigned int len;
1235
1236 skb = skb_dequeue(&tp->tx_queue);
1237 if (!skb)
1238 break; 1258 break;
1239 1259
1240 len = skb->len; 1260 agg = r8152_get_tx_agg(tp);
1241 if (remain < len) { 1261 if (!agg)
1242 skb_queue_head(&tp->tx_queue, skb);
1243 break; 1262 break;
1244 }
1245
1246 tx_data = tx_agg_align(tx_data);
1247 tx_desc = (struct tx_desc *)tx_data;
1248 tx_data += sizeof(*tx_desc);
1249 1263
1250 r8152_tx_csum(tp, tx_desc, skb); 1264 res = r8152_tx_agg_fill(tp, agg);
1251 memcpy(tx_data, skb->data, len); 1265 if (res) {
1252 agg->skb_num++; 1266 struct net_device_stats *stats;
1253 agg->skb_len += len; 1267 struct net_device *netdev;
1254 dev_kfree_skb_any(skb); 1268 unsigned long flags;
1255
1256 tx_data += len;
1257 remain = rx_buf_sz - sizeof(*tx_desc) -
1258 (u32)(tx_agg_align(tx_data) - agg->head);
1259 }
1260
1261 usb_fill_bulk_urb(agg->urb, tp->udev, usb_sndbulkpipe(tp->udev, 2),
1262 agg->head, (int)(tx_data - (u8 *)agg->head),
1263 (usb_complete_t)write_bulk_callback, agg);
1264 res = usb_submit_urb(agg->urb, GFP_ATOMIC);
1265 1269
1266 stats = rtl8152_get_stats(netdev); 1270 netdev = tp->netdev;
1271 stats = rtl8152_get_stats(netdev);
1267 1272
1268 if (res) { 1273 if (res == -ENODEV) {
1269 /* Can we get/handle EPIPE here? */ 1274 netif_device_detach(netdev);
1270 if (res == -ENODEV) { 1275 } else {
1271 netif_device_detach(netdev); 1276 netif_warn(tp, tx_err, netdev,
1272 } else { 1277 "failed tx_urb %d\n", res);
1273 netif_warn(tp, tx_err, netdev, 1278 stats->tx_dropped += agg->skb_num;
1274 "failed tx_urb %d\n", res); 1279 spin_lock_irqsave(&tp->tx_lock, flags);
1275 stats->tx_dropped += agg->skb_num; 1280 list_add_tail(&agg->list, &tp->tx_free);
1276 spin_lock_irqsave(&tp->tx_lock, flags); 1281 spin_unlock_irqrestore(&tp->tx_lock, flags);
1277 list_add_tail(&agg->list, &tp->tx_free); 1282 }
1278 spin_unlock_irqrestore(&tp->tx_lock, flags);
1279 } 1283 }
1280 return; 1284 } while (res == 0);
1281 }
1282 goto next_agg;
1283} 1285}
1284 1286
1285static void bottom_half(unsigned long data) 1287static void bottom_half(unsigned long data)