diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/net/xen-netback/netback.c | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'drivers/net/xen-netback/netback.c')
-rw-r--r-- | drivers/net/xen-netback/netback.c | 211 |
1 files changed, 113 insertions, 98 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index f2d6b78d901..fd00f25d985 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -40,7 +40,6 @@ | |||
40 | 40 | ||
41 | #include <net/tcp.h> | 41 | #include <net/tcp.h> |
42 | 42 | ||
43 | #include <xen/xen.h> | ||
44 | #include <xen/events.h> | 43 | #include <xen/events.h> |
45 | #include <xen/interface/memory.h> | 44 | #include <xen/interface/memory.h> |
46 | 45 | ||
@@ -61,9 +60,6 @@ struct netbk_rx_meta { | |||
61 | 60 | ||
62 | #define MAX_PENDING_REQS 256 | 61 | #define MAX_PENDING_REQS 256 |
63 | 62 | ||
64 | /* Discriminate from any valid pending_idx value. */ | ||
65 | #define INVALID_PENDING_IDX 0xFFFF | ||
66 | |||
67 | #define MAX_BUFFER_OFFSET PAGE_SIZE | 63 | #define MAX_BUFFER_OFFSET PAGE_SIZE |
68 | 64 | ||
69 | /* extra field used in struct page */ | 65 | /* extra field used in struct page */ |
@@ -159,13 +155,13 @@ static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif, | |||
159 | u16 flags); | 155 | u16 flags); |
160 | 156 | ||
161 | static inline unsigned long idx_to_pfn(struct xen_netbk *netbk, | 157 | static inline unsigned long idx_to_pfn(struct xen_netbk *netbk, |
162 | u16 idx) | 158 | unsigned int idx) |
163 | { | 159 | { |
164 | return page_to_pfn(netbk->mmap_pages[idx]); | 160 | return page_to_pfn(netbk->mmap_pages[idx]); |
165 | } | 161 | } |
166 | 162 | ||
167 | static inline unsigned long idx_to_kaddr(struct xen_netbk *netbk, | 163 | static inline unsigned long idx_to_kaddr(struct xen_netbk *netbk, |
168 | u16 idx) | 164 | unsigned int idx) |
169 | { | 165 | { |
170 | return (unsigned long)pfn_to_kaddr(idx_to_pfn(netbk, idx)); | 166 | return (unsigned long)pfn_to_kaddr(idx_to_pfn(netbk, idx)); |
171 | } | 167 | } |
@@ -219,16 +215,6 @@ static int get_page_ext(struct page *pg, | |||
219 | sizeof(struct iphdr) + MAX_IPOPTLEN + \ | 215 | sizeof(struct iphdr) + MAX_IPOPTLEN + \ |
220 | sizeof(struct tcphdr) + MAX_TCP_OPTION_SPACE) | 216 | sizeof(struct tcphdr) + MAX_TCP_OPTION_SPACE) |
221 | 217 | ||
222 | static u16 frag_get_pending_idx(skb_frag_t *frag) | ||
223 | { | ||
224 | return (u16)frag->page_offset; | ||
225 | } | ||
226 | |||
227 | static void frag_set_pending_idx(skb_frag_t *frag, u16 pending_idx) | ||
228 | { | ||
229 | frag->page_offset = pending_idx; | ||
230 | } | ||
231 | |||
232 | static inline pending_ring_idx_t pending_index(unsigned i) | 218 | static inline pending_ring_idx_t pending_index(unsigned i) |
233 | { | 219 | { |
234 | return i & (MAX_PENDING_REQS-1); | 220 | return i & (MAX_PENDING_REQS-1); |
@@ -326,7 +312,8 @@ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb) | |||
326 | unsigned int count; | 312 | unsigned int count; |
327 | int i, copy_off; | 313 | int i, copy_off; |
328 | 314 | ||
329 | count = DIV_ROUND_UP(skb_headlen(skb), PAGE_SIZE); | 315 | count = DIV_ROUND_UP( |
316 | offset_in_page(skb->data)+skb_headlen(skb), PAGE_SIZE); | ||
330 | 317 | ||
331 | copy_off = skb_headlen(skb) % PAGE_SIZE; | 318 | copy_off = skb_headlen(skb) % PAGE_SIZE; |
332 | 319 | ||
@@ -334,36 +321,22 @@ unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb) | |||
334 | count++; | 321 | count++; |
335 | 322 | ||
336 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | 323 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { |
337 | unsigned long size = skb_frag_size(&skb_shinfo(skb)->frags[i]); | 324 | unsigned long size = skb_shinfo(skb)->frags[i].size; |
338 | unsigned long offset = skb_shinfo(skb)->frags[i].page_offset; | ||
339 | unsigned long bytes; | 325 | unsigned long bytes; |
340 | |||
341 | offset &= ~PAGE_MASK; | ||
342 | |||
343 | while (size > 0) { | 326 | while (size > 0) { |
344 | BUG_ON(offset >= PAGE_SIZE); | ||
345 | BUG_ON(copy_off > MAX_BUFFER_OFFSET); | 327 | BUG_ON(copy_off > MAX_BUFFER_OFFSET); |
346 | 328 | ||
347 | bytes = PAGE_SIZE - offset; | 329 | if (start_new_rx_buffer(copy_off, size, 0)) { |
348 | |||
349 | if (bytes > size) | ||
350 | bytes = size; | ||
351 | |||
352 | if (start_new_rx_buffer(copy_off, bytes, 0)) { | ||
353 | count++; | 330 | count++; |
354 | copy_off = 0; | 331 | copy_off = 0; |
355 | } | 332 | } |
356 | 333 | ||
334 | bytes = size; | ||
357 | if (copy_off + bytes > MAX_BUFFER_OFFSET) | 335 | if (copy_off + bytes > MAX_BUFFER_OFFSET) |
358 | bytes = MAX_BUFFER_OFFSET - copy_off; | 336 | bytes = MAX_BUFFER_OFFSET - copy_off; |
359 | 337 | ||
360 | copy_off += bytes; | 338 | copy_off += bytes; |
361 | |||
362 | offset += bytes; | ||
363 | size -= bytes; | 339 | size -= bytes; |
364 | |||
365 | if (offset == PAGE_SIZE) | ||
366 | offset = 0; | ||
367 | } | 340 | } |
368 | } | 341 | } |
369 | return count; | 342 | return count; |
@@ -409,7 +382,7 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, | |||
409 | struct gnttab_copy *copy_gop; | 382 | struct gnttab_copy *copy_gop; |
410 | struct netbk_rx_meta *meta; | 383 | struct netbk_rx_meta *meta; |
411 | /* | 384 | /* |
412 | * These variables are used iff get_page_ext returns true, | 385 | * These variables a used iff get_page_ext returns true, |
413 | * in which case they are guaranteed to be initialized. | 386 | * in which case they are guaranteed to be initialized. |
414 | */ | 387 | */ |
415 | unsigned int uninitialized_var(group), uninitialized_var(idx); | 388 | unsigned int uninitialized_var(group), uninitialized_var(idx); |
@@ -417,24 +390,14 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, | |||
417 | unsigned long bytes; | 390 | unsigned long bytes; |
418 | 391 | ||
419 | /* Data must not cross a page boundary. */ | 392 | /* Data must not cross a page boundary. */ |
420 | BUG_ON(size + offset > PAGE_SIZE<<compound_order(page)); | 393 | BUG_ON(size + offset > PAGE_SIZE); |
421 | 394 | ||
422 | meta = npo->meta + npo->meta_prod - 1; | 395 | meta = npo->meta + npo->meta_prod - 1; |
423 | 396 | ||
424 | /* Skip unused frames from start of page */ | ||
425 | page += offset >> PAGE_SHIFT; | ||
426 | offset &= ~PAGE_MASK; | ||
427 | |||
428 | while (size > 0) { | 397 | while (size > 0) { |
429 | BUG_ON(offset >= PAGE_SIZE); | ||
430 | BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET); | 398 | BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET); |
431 | 399 | ||
432 | bytes = PAGE_SIZE - offset; | 400 | if (start_new_rx_buffer(npo->copy_off, size, *head)) { |
433 | |||
434 | if (bytes > size) | ||
435 | bytes = size; | ||
436 | |||
437 | if (start_new_rx_buffer(npo->copy_off, bytes, *head)) { | ||
438 | /* | 401 | /* |
439 | * Netfront requires there to be some data in the head | 402 | * Netfront requires there to be some data in the head |
440 | * buffer. | 403 | * buffer. |
@@ -444,6 +407,7 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, | |||
444 | meta = get_next_rx_buffer(vif, npo); | 407 | meta = get_next_rx_buffer(vif, npo); |
445 | } | 408 | } |
446 | 409 | ||
410 | bytes = size; | ||
447 | if (npo->copy_off + bytes > MAX_BUFFER_OFFSET) | 411 | if (npo->copy_off + bytes > MAX_BUFFER_OFFSET) |
448 | bytes = MAX_BUFFER_OFFSET - npo->copy_off; | 412 | bytes = MAX_BUFFER_OFFSET - npo->copy_off; |
449 | 413 | ||
@@ -476,13 +440,6 @@ static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb, | |||
476 | offset += bytes; | 440 | offset += bytes; |
477 | size -= bytes; | 441 | size -= bytes; |
478 | 442 | ||
479 | /* Next frame */ | ||
480 | if (offset == PAGE_SIZE && size) { | ||
481 | BUG_ON(!PageCompound(page)); | ||
482 | page++; | ||
483 | offset = 0; | ||
484 | } | ||
485 | |||
486 | /* Leave a gap for the GSO descriptor. */ | 443 | /* Leave a gap for the GSO descriptor. */ |
487 | if (*head && skb_shinfo(skb)->gso_size && !vif->gso_prefix) | 444 | if (*head && skb_shinfo(skb)->gso_size && !vif->gso_prefix) |
488 | vif->rx.req_cons++; | 445 | vif->rx.req_cons++; |
@@ -555,8 +512,8 @@ static int netbk_gop_skb(struct sk_buff *skb, | |||
555 | 512 | ||
556 | for (i = 0; i < nr_frags; i++) { | 513 | for (i = 0; i < nr_frags; i++) { |
557 | netbk_gop_frag_copy(vif, skb, npo, | 514 | netbk_gop_frag_copy(vif, skb, npo, |
558 | skb_frag_page(&skb_shinfo(skb)->frags[i]), | 515 | skb_shinfo(skb)->frags[i].page, |
559 | skb_frag_size(&skb_shinfo(skb)->frags[i]), | 516 | skb_shinfo(skb)->frags[i].size, |
560 | skb_shinfo(skb)->frags[i].page_offset, | 517 | skb_shinfo(skb)->frags[i].page_offset, |
561 | &head); | 518 | &head); |
562 | } | 519 | } |
@@ -666,7 +623,9 @@ static void xen_netbk_rx_action(struct xen_netbk *netbk) | |||
666 | return; | 623 | return; |
667 | 624 | ||
668 | BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op)); | 625 | BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op)); |
669 | gnttab_batch_copy(netbk->grant_copy_op, npo.copy_prod); | 626 | ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, &netbk->grant_copy_op, |
627 | npo.copy_prod); | ||
628 | BUG_ON(ret != 0); | ||
670 | 629 | ||
671 | while ((skb = __skb_dequeue(&rxq)) != NULL) { | 630 | while ((skb = __skb_dequeue(&rxq)) != NULL) { |
672 | sco = (struct skb_cb_overlay *)skb->cb; | 631 | sco = (struct skb_cb_overlay *)skb->cb; |
@@ -931,7 +890,7 @@ static int netbk_count_requests(struct xenvif *vif, | |||
931 | 890 | ||
932 | static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk, | 891 | static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk, |
933 | struct sk_buff *skb, | 892 | struct sk_buff *skb, |
934 | u16 pending_idx) | 893 | unsigned long pending_idx) |
935 | { | 894 | { |
936 | struct page *page; | 895 | struct page *page; |
937 | page = alloc_page(GFP_KERNEL|__GFP_COLD); | 896 | page = alloc_page(GFP_KERNEL|__GFP_COLD); |
@@ -950,11 +909,11 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, | |||
950 | { | 909 | { |
951 | struct skb_shared_info *shinfo = skb_shinfo(skb); | 910 | struct skb_shared_info *shinfo = skb_shinfo(skb); |
952 | skb_frag_t *frags = shinfo->frags; | 911 | skb_frag_t *frags = shinfo->frags; |
953 | u16 pending_idx = *((u16 *)skb->data); | 912 | unsigned long pending_idx = *((u16 *)skb->data); |
954 | int i, start; | 913 | int i, start; |
955 | 914 | ||
956 | /* Skip first skb fragment if it is on same page as header fragment. */ | 915 | /* Skip first skb fragment if it is on same page as header fragment. */ |
957 | start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); | 916 | start = ((unsigned long)shinfo->frags[0].page == pending_idx); |
958 | 917 | ||
959 | for (i = start; i < shinfo->nr_frags; i++, txp++) { | 918 | for (i = start; i < shinfo->nr_frags; i++, txp++) { |
960 | struct page *page; | 919 | struct page *page; |
@@ -968,6 +927,8 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, | |||
968 | if (!page) | 927 | if (!page) |
969 | return NULL; | 928 | return NULL; |
970 | 929 | ||
930 | netbk->mmap_pages[pending_idx] = page; | ||
931 | |||
971 | gop->source.u.ref = txp->gref; | 932 | gop->source.u.ref = txp->gref; |
972 | gop->source.domid = vif->domid; | 933 | gop->source.domid = vif->domid; |
973 | gop->source.offset = txp->offset; | 934 | gop->source.offset = txp->offset; |
@@ -984,7 +945,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, | |||
984 | memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp)); | 945 | memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp)); |
985 | xenvif_get(vif); | 946 | xenvif_get(vif); |
986 | pending_tx_info[pending_idx].vif = vif; | 947 | pending_tx_info[pending_idx].vif = vif; |
987 | frag_set_pending_idx(&frags[i], pending_idx); | 948 | frags[i].page = (void *)pending_idx; |
988 | } | 949 | } |
989 | 950 | ||
990 | return gop; | 951 | return gop; |
@@ -995,7 +956,7 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | |||
995 | struct gnttab_copy **gopp) | 956 | struct gnttab_copy **gopp) |
996 | { | 957 | { |
997 | struct gnttab_copy *gop = *gopp; | 958 | struct gnttab_copy *gop = *gopp; |
998 | u16 pending_idx = *((u16 *)skb->data); | 959 | int pending_idx = *((u16 *)skb->data); |
999 | struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; | 960 | struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; |
1000 | struct xenvif *vif = pending_tx_info[pending_idx].vif; | 961 | struct xenvif *vif = pending_tx_info[pending_idx].vif; |
1001 | struct xen_netif_tx_request *txp; | 962 | struct xen_netif_tx_request *txp; |
@@ -1015,13 +976,13 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | |||
1015 | } | 976 | } |
1016 | 977 | ||
1017 | /* Skip first skb fragment if it is on same page as header fragment. */ | 978 | /* Skip first skb fragment if it is on same page as header fragment. */ |
1018 | start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); | 979 | start = ((unsigned long)shinfo->frags[0].page == pending_idx); |
1019 | 980 | ||
1020 | for (i = start; i < nr_frags; i++) { | 981 | for (i = start; i < nr_frags; i++) { |
1021 | int j, newerr; | 982 | int j, newerr; |
1022 | pending_ring_idx_t index; | 983 | pending_ring_idx_t index; |
1023 | 984 | ||
1024 | pending_idx = frag_get_pending_idx(&shinfo->frags[i]); | 985 | pending_idx = (unsigned long)shinfo->frags[i].page; |
1025 | 986 | ||
1026 | /* Check error status: if okay then remember grant handle. */ | 987 | /* Check error status: if okay then remember grant handle. */ |
1027 | newerr = (++gop)->status; | 988 | newerr = (++gop)->status; |
@@ -1047,7 +1008,7 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | |||
1047 | pending_idx = *((u16 *)skb->data); | 1008 | pending_idx = *((u16 *)skb->data); |
1048 | xen_netbk_idx_release(netbk, pending_idx); | 1009 | xen_netbk_idx_release(netbk, pending_idx); |
1049 | for (j = start; j < i; j++) { | 1010 | for (j = start; j < i; j++) { |
1050 | pending_idx = frag_get_pending_idx(&shinfo->frags[j]); | 1011 | pending_idx = (unsigned long)shinfo->frags[i].page; |
1051 | xen_netbk_idx_release(netbk, pending_idx); | 1012 | xen_netbk_idx_release(netbk, pending_idx); |
1052 | } | 1013 | } |
1053 | 1014 | ||
@@ -1068,14 +1029,15 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) | |||
1068 | for (i = 0; i < nr_frags; i++) { | 1029 | for (i = 0; i < nr_frags; i++) { |
1069 | skb_frag_t *frag = shinfo->frags + i; | 1030 | skb_frag_t *frag = shinfo->frags + i; |
1070 | struct xen_netif_tx_request *txp; | 1031 | struct xen_netif_tx_request *txp; |
1071 | struct page *page; | 1032 | unsigned long pending_idx; |
1072 | u16 pending_idx; | ||
1073 | 1033 | ||
1074 | pending_idx = frag_get_pending_idx(frag); | 1034 | pending_idx = (unsigned long)frag->page; |
1075 | 1035 | ||
1076 | txp = &netbk->pending_tx_info[pending_idx].req; | 1036 | txp = &netbk->pending_tx_info[pending_idx].req; |
1077 | page = virt_to_page(idx_to_kaddr(netbk, pending_idx)); | 1037 | frag->page = virt_to_page(idx_to_kaddr(netbk, pending_idx)); |
1078 | __skb_fill_page_desc(skb, i, page, txp->offset, txp->size); | 1038 | frag->size = txp->size; |
1039 | frag->page_offset = txp->offset; | ||
1040 | |||
1079 | skb->len += txp->size; | 1041 | skb->len += txp->size; |
1080 | skb->data_len += txp->size; | 1042 | skb->data_len += txp->size; |
1081 | skb->truesize += txp->size; | 1043 | skb->truesize += txp->size; |
@@ -1362,6 +1324,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1362 | continue; | 1324 | continue; |
1363 | } | 1325 | } |
1364 | 1326 | ||
1327 | netbk->mmap_pages[pending_idx] = page; | ||
1328 | |||
1365 | gop->source.u.ref = txreq.gref; | 1329 | gop->source.u.ref = txreq.gref; |
1366 | gop->source.domid = vif->domid; | 1330 | gop->source.domid = vif->domid; |
1367 | gop->source.offset = txreq.offset; | 1331 | gop->source.offset = txreq.offset; |
@@ -1385,13 +1349,15 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1385 | skb_shinfo(skb)->nr_frags = ret; | 1349 | skb_shinfo(skb)->nr_frags = ret; |
1386 | if (data_len < txreq.size) { | 1350 | if (data_len < txreq.size) { |
1387 | skb_shinfo(skb)->nr_frags++; | 1351 | skb_shinfo(skb)->nr_frags++; |
1388 | frag_set_pending_idx(&skb_shinfo(skb)->frags[0], | 1352 | skb_shinfo(skb)->frags[0].page = |
1389 | pending_idx); | 1353 | (void *)(unsigned long)pending_idx; |
1390 | } else { | 1354 | } else { |
1391 | frag_set_pending_idx(&skb_shinfo(skb)->frags[0], | 1355 | /* Discriminate from any valid pending_idx value. */ |
1392 | INVALID_PENDING_IDX); | 1356 | skb_shinfo(skb)->frags[0].page = (void *)~0UL; |
1393 | } | 1357 | } |
1394 | 1358 | ||
1359 | __skb_queue_tail(&netbk->tx_queue, skb); | ||
1360 | |||
1395 | netbk->pending_cons++; | 1361 | netbk->pending_cons++; |
1396 | 1362 | ||
1397 | request_gop = xen_netbk_get_requests(netbk, vif, | 1363 | request_gop = xen_netbk_get_requests(netbk, vif, |
@@ -1403,8 +1369,6 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1403 | } | 1369 | } |
1404 | gop = request_gop; | 1370 | gop = request_gop; |
1405 | 1371 | ||
1406 | __skb_queue_tail(&netbk->tx_queue, skb); | ||
1407 | |||
1408 | vif->tx.req_cons = idx; | 1372 | vif->tx.req_cons = idx; |
1409 | xen_netbk_check_rx_xenvif(vif); | 1373 | xen_netbk_check_rx_xenvif(vif); |
1410 | 1374 | ||
@@ -1489,15 +1453,18 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) | |||
1489 | static void xen_netbk_tx_action(struct xen_netbk *netbk) | 1453 | static void xen_netbk_tx_action(struct xen_netbk *netbk) |
1490 | { | 1454 | { |
1491 | unsigned nr_gops; | 1455 | unsigned nr_gops; |
1456 | int ret; | ||
1492 | 1457 | ||
1493 | nr_gops = xen_netbk_tx_build_gops(netbk); | 1458 | nr_gops = xen_netbk_tx_build_gops(netbk); |
1494 | 1459 | ||
1495 | if (nr_gops == 0) | 1460 | if (nr_gops == 0) |
1496 | return; | 1461 | return; |
1497 | 1462 | ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, | |
1498 | gnttab_batch_copy(netbk->tx_copy_ops, nr_gops); | 1463 | netbk->tx_copy_ops, nr_gops); |
1464 | BUG_ON(ret); | ||
1499 | 1465 | ||
1500 | xen_netbk_tx_submit(netbk); | 1466 | xen_netbk_tx_submit(netbk); |
1467 | |||
1501 | } | 1468 | } |
1502 | 1469 | ||
1503 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) | 1470 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) |
@@ -1610,42 +1577,88 @@ static int xen_netbk_kthread(void *data) | |||
1610 | 1577 | ||
1611 | void xen_netbk_unmap_frontend_rings(struct xenvif *vif) | 1578 | void xen_netbk_unmap_frontend_rings(struct xenvif *vif) |
1612 | { | 1579 | { |
1613 | if (vif->tx.sring) | 1580 | struct gnttab_unmap_grant_ref op; |
1614 | xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif), | 1581 | |
1615 | vif->tx.sring); | 1582 | if (vif->tx.sring) { |
1616 | if (vif->rx.sring) | 1583 | gnttab_set_unmap_op(&op, (unsigned long)vif->tx_comms_area->addr, |
1617 | xenbus_unmap_ring_vfree(xenvif_to_xenbus_device(vif), | 1584 | GNTMAP_host_map, vif->tx_shmem_handle); |
1618 | vif->rx.sring); | 1585 | |
1586 | if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) | ||
1587 | BUG(); | ||
1588 | } | ||
1589 | |||
1590 | if (vif->rx.sring) { | ||
1591 | gnttab_set_unmap_op(&op, (unsigned long)vif->rx_comms_area->addr, | ||
1592 | GNTMAP_host_map, vif->rx_shmem_handle); | ||
1593 | |||
1594 | if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1)) | ||
1595 | BUG(); | ||
1596 | } | ||
1597 | if (vif->rx_comms_area) | ||
1598 | free_vm_area(vif->rx_comms_area); | ||
1599 | if (vif->tx_comms_area) | ||
1600 | free_vm_area(vif->tx_comms_area); | ||
1619 | } | 1601 | } |
1620 | 1602 | ||
1621 | int xen_netbk_map_frontend_rings(struct xenvif *vif, | 1603 | int xen_netbk_map_frontend_rings(struct xenvif *vif, |
1622 | grant_ref_t tx_ring_ref, | 1604 | grant_ref_t tx_ring_ref, |
1623 | grant_ref_t rx_ring_ref) | 1605 | grant_ref_t rx_ring_ref) |
1624 | { | 1606 | { |
1625 | void *addr; | 1607 | struct gnttab_map_grant_ref op; |
1626 | struct xen_netif_tx_sring *txs; | 1608 | struct xen_netif_tx_sring *txs; |
1627 | struct xen_netif_rx_sring *rxs; | 1609 | struct xen_netif_rx_sring *rxs; |
1628 | 1610 | ||
1629 | int err = -ENOMEM; | 1611 | int err = -ENOMEM; |
1630 | 1612 | ||
1631 | err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif), | 1613 | vif->tx_comms_area = alloc_vm_area(PAGE_SIZE); |
1632 | tx_ring_ref, &addr); | 1614 | if (vif->tx_comms_area == NULL) |
1633 | if (err) | ||
1634 | goto err; | 1615 | goto err; |
1635 | 1616 | ||
1636 | txs = (struct xen_netif_tx_sring *)addr; | 1617 | vif->rx_comms_area = alloc_vm_area(PAGE_SIZE); |
1637 | BACK_RING_INIT(&vif->tx, txs, PAGE_SIZE); | 1618 | if (vif->rx_comms_area == NULL) |
1619 | goto err; | ||
1620 | |||
1621 | gnttab_set_map_op(&op, (unsigned long)vif->tx_comms_area->addr, | ||
1622 | GNTMAP_host_map, tx_ring_ref, vif->domid); | ||
1638 | 1623 | ||
1639 | err = xenbus_map_ring_valloc(xenvif_to_xenbus_device(vif), | 1624 | if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) |
1640 | rx_ring_ref, &addr); | 1625 | BUG(); |
1641 | if (err) | 1626 | |
1627 | if (op.status) { | ||
1628 | netdev_warn(vif->dev, | ||
1629 | "failed to map tx ring. err=%d status=%d\n", | ||
1630 | err, op.status); | ||
1631 | err = op.status; | ||
1642 | goto err; | 1632 | goto err; |
1633 | } | ||
1643 | 1634 | ||
1644 | rxs = (struct xen_netif_rx_sring *)addr; | 1635 | vif->tx_shmem_ref = tx_ring_ref; |
1645 | BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE); | 1636 | vif->tx_shmem_handle = op.handle; |
1637 | |||
1638 | txs = (struct xen_netif_tx_sring *)vif->tx_comms_area->addr; | ||
1639 | BACK_RING_INIT(&vif->tx, txs, PAGE_SIZE); | ||
1640 | |||
1641 | gnttab_set_map_op(&op, (unsigned long)vif->rx_comms_area->addr, | ||
1642 | GNTMAP_host_map, rx_ring_ref, vif->domid); | ||
1643 | |||
1644 | if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1)) | ||
1645 | BUG(); | ||
1646 | 1646 | ||
1647 | if (op.status) { | ||
1648 | netdev_warn(vif->dev, | ||
1649 | "failed to map rx ring. err=%d status=%d\n", | ||
1650 | err, op.status); | ||
1651 | err = op.status; | ||
1652 | goto err; | ||
1653 | } | ||
1654 | |||
1655 | vif->rx_shmem_ref = rx_ring_ref; | ||
1656 | vif->rx_shmem_handle = op.handle; | ||
1647 | vif->rx_req_cons_peek = 0; | 1657 | vif->rx_req_cons_peek = 0; |
1648 | 1658 | ||
1659 | rxs = (struct xen_netif_rx_sring *)vif->rx_comms_area->addr; | ||
1660 | BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE); | ||
1661 | |||
1649 | return 0; | 1662 | return 0; |
1650 | 1663 | ||
1651 | err: | 1664 | err: |
@@ -1659,13 +1672,15 @@ static int __init netback_init(void) | |||
1659 | int rc = 0; | 1672 | int rc = 0; |
1660 | int group; | 1673 | int group; |
1661 | 1674 | ||
1662 | if (!xen_domain()) | 1675 | if (!xen_pv_domain()) |
1663 | return -ENODEV; | 1676 | return -ENODEV; |
1664 | 1677 | ||
1665 | xen_netbk_group_nr = num_online_cpus(); | 1678 | xen_netbk_group_nr = num_online_cpus(); |
1666 | xen_netbk = vzalloc(sizeof(struct xen_netbk) * xen_netbk_group_nr); | 1679 | xen_netbk = vzalloc(sizeof(struct xen_netbk) * xen_netbk_group_nr); |
1667 | if (!xen_netbk) | 1680 | if (!xen_netbk) { |
1681 | printk(KERN_ALERT "%s: out of memory\n", __func__); | ||
1668 | return -ENOMEM; | 1682 | return -ENOMEM; |
1683 | } | ||
1669 | 1684 | ||
1670 | for (group = 0; group < xen_netbk_group_nr; group++) { | 1685 | for (group = 0; group < xen_netbk_group_nr; group++) { |
1671 | struct xen_netbk *netbk = &xen_netbk[group]; | 1686 | struct xen_netbk *netbk = &xen_netbk[group]; |
@@ -1687,7 +1702,7 @@ static int __init netback_init(void) | |||
1687 | "netback/%u", group); | 1702 | "netback/%u", group); |
1688 | 1703 | ||
1689 | if (IS_ERR(netbk->task)) { | 1704 | if (IS_ERR(netbk->task)) { |
1690 | printk(KERN_ALERT "kthread_create() fails at netback\n"); | 1705 | printk(KERN_ALERT "kthread_run() fails at netback\n"); |
1691 | del_timer(&netbk->net_timer); | 1706 | del_timer(&netbk->net_timer); |
1692 | rc = PTR_ERR(netbk->task); | 1707 | rc = PTR_ERR(netbk->task); |
1693 | goto failed_init; | 1708 | goto failed_init; |