diff options
Diffstat (limited to 'drivers/net/xen-netback/netback.c')
| -rw-r--r-- | drivers/net/xen-netback/netback.c | 86 | 
1 files changed, 63 insertions, 23 deletions
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index 1844a47636b6..c65b636bcab9 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c  | |||
| @@ -1030,14 +1030,21 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue, | |||
| 1030 | { | 1030 | { | 
| 1031 | struct gnttab_map_grant_ref *gop_map = *gopp_map; | 1031 | struct gnttab_map_grant_ref *gop_map = *gopp_map; | 
| 1032 | u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx; | 1032 | u16 pending_idx = XENVIF_TX_CB(skb)->pending_idx; | 
| 1033 | /* This always points to the shinfo of the skb being checked, which | ||
| 1034 | * could be either the first or the one on the frag_list | ||
| 1035 | */ | ||
| 1033 | struct skb_shared_info *shinfo = skb_shinfo(skb); | 1036 | struct skb_shared_info *shinfo = skb_shinfo(skb); | 
| 1037 | /* If this is non-NULL, we are currently checking the frag_list skb, and | ||
| 1038 | * this points to the shinfo of the first one | ||
| 1039 | */ | ||
| 1040 | struct skb_shared_info *first_shinfo = NULL; | ||
| 1034 | int nr_frags = shinfo->nr_frags; | 1041 | int nr_frags = shinfo->nr_frags; | 
| 1042 | const bool sharedslot = nr_frags && | ||
| 1043 | frag_get_pending_idx(&shinfo->frags[0]) == pending_idx; | ||
| 1035 | int i, err; | 1044 | int i, err; | 
| 1036 | struct sk_buff *first_skb = NULL; | ||
| 1037 | 1045 | ||
| 1038 | /* Check status of header. */ | 1046 | /* Check status of header. */ | 
| 1039 | err = (*gopp_copy)->status; | 1047 | err = (*gopp_copy)->status; | 
| 1040 | (*gopp_copy)++; | ||
| 1041 | if (unlikely(err)) { | 1048 | if (unlikely(err)) { | 
| 1042 | if (net_ratelimit()) | 1049 | if (net_ratelimit()) | 
| 1043 | netdev_dbg(queue->vif->dev, | 1050 | netdev_dbg(queue->vif->dev, | 
| @@ -1045,8 +1052,12 @@ static int xenvif_tx_check_gop(struct xenvif_queue *queue, | |||
| 1045 | (*gopp_copy)->status, | 1052 | (*gopp_copy)->status, | 
| 1046 | pending_idx, | 1053 | pending_idx, | 
| 1047 | (*gopp_copy)->source.u.ref); | 1054 | (*gopp_copy)->source.u.ref); | 
| 1048 | xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_ERROR); | 1055 | /* The first frag might still have this slot mapped */ | 
| 1056 | if (!sharedslot) | ||
| 1057 | xenvif_idx_release(queue, pending_idx, | ||
| 1058 | XEN_NETIF_RSP_ERROR); | ||
| 1049 | } | 1059 | } | 
| 1060 | (*gopp_copy)++; | ||
| 1050 | 1061 | ||
| 1051 | check_frags: | 1062 | check_frags: | 
| 1052 | for (i = 0; i < nr_frags; i++, gop_map++) { | 1063 | for (i = 0; i < nr_frags; i++, gop_map++) { | 
| @@ -1062,8 +1073,19 @@ check_frags: | |||
| 1062 | pending_idx, | 1073 | pending_idx, | 
| 1063 | gop_map->handle); | 1074 | gop_map->handle); | 
| 1064 | /* Had a previous error? Invalidate this fragment. */ | 1075 | /* Had a previous error? Invalidate this fragment. */ | 
| 1065 | if (unlikely(err)) | 1076 | if (unlikely(err)) { | 
| 1066 | xenvif_idx_unmap(queue, pending_idx); | 1077 | xenvif_idx_unmap(queue, pending_idx); | 
| 1078 | /* If the mapping of the first frag was OK, but | ||
| 1079 | * the header's copy failed, and they are | ||
| 1080 | * sharing a slot, send an error | ||
| 1081 | */ | ||
| 1082 | if (i == 0 && sharedslot) | ||
| 1083 | xenvif_idx_release(queue, pending_idx, | ||
| 1084 | XEN_NETIF_RSP_ERROR); | ||
| 1085 | else | ||
| 1086 | xenvif_idx_release(queue, pending_idx, | ||
| 1087 | XEN_NETIF_RSP_OKAY); | ||
| 1088 | } | ||
| 1067 | continue; | 1089 | continue; | 
| 1068 | } | 1090 | } | 
| 1069 | 1091 | ||
| @@ -1075,42 +1097,53 @@ check_frags: | |||
| 1075 | gop_map->status, | 1097 | gop_map->status, | 
| 1076 | pending_idx, | 1098 | pending_idx, | 
| 1077 | gop_map->ref); | 1099 | gop_map->ref); | 
| 1100 | |||
| 1078 | xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_ERROR); | 1101 | xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_ERROR); | 
| 1079 | 1102 | ||
| 1080 | /* Not the first error? Preceding frags already invalidated. */ | 1103 | /* Not the first error? Preceding frags already invalidated. */ | 
| 1081 | if (err) | 1104 | if (err) | 
| 1082 | continue; | 1105 | continue; | 
| 1083 | /* First error: invalidate preceding fragments. */ | 1106 | |
| 1107 | /* First error: if the header haven't shared a slot with the | ||
| 1108 | * first frag, release it as well. | ||
| 1109 | */ | ||
| 1110 | if (!sharedslot) | ||
| 1111 | xenvif_idx_release(queue, | ||
| 1112 | XENVIF_TX_CB(skb)->pending_idx, | ||
| 1113 | XEN_NETIF_RSP_OKAY); | ||
| 1114 | |||
| 1115 | /* Invalidate preceding fragments of this skb. */ | ||
| 1084 | for (j = 0; j < i; j++) { | 1116 | for (j = 0; j < i; j++) { | 
| 1085 | pending_idx = frag_get_pending_idx(&shinfo->frags[j]); | 1117 | pending_idx = frag_get_pending_idx(&shinfo->frags[j]); | 
| 1086 | xenvif_idx_unmap(queue, pending_idx); | 1118 | xenvif_idx_unmap(queue, pending_idx); | 
| 1119 | xenvif_idx_release(queue, pending_idx, | ||
| 1120 | XEN_NETIF_RSP_OKAY); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | /* And if we found the error while checking the frag_list, unmap | ||
| 1124 | * the first skb's frags | ||
| 1125 | */ | ||
| 1126 | if (first_shinfo) { | ||
| 1127 | for (j = 0; j < first_shinfo->nr_frags; j++) { | ||
| 1128 | pending_idx = frag_get_pending_idx(&first_shinfo->frags[j]); | ||
| 1129 | xenvif_idx_unmap(queue, pending_idx); | ||
| 1130 | xenvif_idx_release(queue, pending_idx, | ||
| 1131 | XEN_NETIF_RSP_OKAY); | ||
| 1132 | } | ||
| 1087 | } | 1133 | } | 
| 1088 | 1134 | ||
| 1089 | /* Remember the error: invalidate all subsequent fragments. */ | 1135 | /* Remember the error: invalidate all subsequent fragments. */ | 
| 1090 | err = newerr; | 1136 | err = newerr; | 
| 1091 | } | 1137 | } | 
| 1092 | 1138 | ||
| 1093 | if (skb_has_frag_list(skb)) { | 1139 | if (skb_has_frag_list(skb) && !first_shinfo) { | 
| 1094 | first_skb = skb; | 1140 | first_shinfo = skb_shinfo(skb); | 
| 1095 | skb = shinfo->frag_list; | 1141 | shinfo = skb_shinfo(skb_shinfo(skb)->frag_list); | 
| 1096 | shinfo = skb_shinfo(skb); | ||
| 1097 | nr_frags = shinfo->nr_frags; | 1142 | nr_frags = shinfo->nr_frags; | 
| 1098 | 1143 | ||
| 1099 | goto check_frags; | 1144 | goto check_frags; | 
| 1100 | } | 1145 | } | 
| 1101 | 1146 | ||
| 1102 | /* There was a mapping error in the frag_list skb. We have to unmap | ||
| 1103 | * the first skb's frags | ||
| 1104 | */ | ||
| 1105 | if (first_skb && err) { | ||
| 1106 | int j; | ||
| 1107 | shinfo = skb_shinfo(first_skb); | ||
| 1108 | for (j = 0; j < shinfo->nr_frags; j++) { | ||
| 1109 | pending_idx = frag_get_pending_idx(&shinfo->frags[j]); | ||
| 1110 | xenvif_idx_unmap(queue, pending_idx); | ||
| 1111 | } | ||
| 1112 | } | ||
| 1113 | |||
| 1114 | *gopp_map = gop_map; | 1147 | *gopp_map = gop_map; | 
| 1115 | return err; | 1148 | return err; | 
| 1116 | } | 1149 | } | 
| @@ -1518,7 +1551,16 @@ static int xenvif_tx_submit(struct xenvif_queue *queue) | |||
| 1518 | 1551 | ||
| 1519 | /* Check the remap error code. */ | 1552 | /* Check the remap error code. */ | 
| 1520 | if (unlikely(xenvif_tx_check_gop(queue, skb, &gop_map, &gop_copy))) { | 1553 | if (unlikely(xenvif_tx_check_gop(queue, skb, &gop_map, &gop_copy))) { | 
| 1554 | /* If there was an error, xenvif_tx_check_gop is | ||
| 1555 | * expected to release all the frags which were mapped, | ||
| 1556 | * so kfree_skb shouldn't do it again | ||
| 1557 | */ | ||
| 1521 | skb_shinfo(skb)->nr_frags = 0; | 1558 | skb_shinfo(skb)->nr_frags = 0; | 
| 1559 | if (skb_has_frag_list(skb)) { | ||
| 1560 | struct sk_buff *nskb = | ||
| 1561 | skb_shinfo(skb)->frag_list; | ||
| 1562 | skb_shinfo(nskb)->nr_frags = 0; | ||
| 1563 | } | ||
| 1522 | kfree_skb(skb); | 1564 | kfree_skb(skb); | 
| 1523 | continue; | 1565 | continue; | 
| 1524 | } | 1566 | } | 
| @@ -1822,8 +1864,6 @@ void xenvif_idx_unmap(struct xenvif_queue *queue, u16 pending_idx) | |||
| 1822 | tx_unmap_op.status); | 1864 | tx_unmap_op.status); | 
| 1823 | BUG(); | 1865 | BUG(); | 
| 1824 | } | 1866 | } | 
| 1825 | |||
| 1826 | xenvif_idx_release(queue, pending_idx, XEN_NETIF_RSP_OKAY); | ||
| 1827 | } | 1867 | } | 
| 1828 | 1868 | ||
| 1829 | static inline int rx_work_todo(struct xenvif_queue *queue) | 1869 | static inline int rx_work_todo(struct xenvif_queue *queue) | 
