diff options
| -rw-r--r-- | drivers/net/hyperv/netvsc_drv.c | 153 |
1 files changed, 114 insertions, 39 deletions
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index 9ef6be90a81c..1f7b12f9e6fb 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
| @@ -140,21 +140,123 @@ static void netvsc_xmit_completion(void *context) | |||
| 140 | dev_kfree_skb_any(skb); | 140 | dev_kfree_skb_any(skb); |
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | static u32 fill_pg_buf(struct page *page, u32 offset, u32 len, | ||
| 144 | struct hv_page_buffer *pb) | ||
| 145 | { | ||
| 146 | int j = 0; | ||
| 147 | |||
| 148 | /* Deal with compund pages by ignoring unused part | ||
| 149 | * of the page. | ||
| 150 | */ | ||
| 151 | page += (offset >> PAGE_SHIFT); | ||
| 152 | offset &= ~PAGE_MASK; | ||
| 153 | |||
| 154 | while (len > 0) { | ||
| 155 | unsigned long bytes; | ||
| 156 | |||
| 157 | bytes = PAGE_SIZE - offset; | ||
| 158 | if (bytes > len) | ||
| 159 | bytes = len; | ||
| 160 | pb[j].pfn = page_to_pfn(page); | ||
| 161 | pb[j].offset = offset; | ||
| 162 | pb[j].len = bytes; | ||
| 163 | |||
| 164 | offset += bytes; | ||
| 165 | len -= bytes; | ||
| 166 | |||
| 167 | if (offset == PAGE_SIZE && len) { | ||
| 168 | page++; | ||
| 169 | offset = 0; | ||
| 170 | j++; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | |||
| 174 | return j + 1; | ||
| 175 | } | ||
| 176 | |||
| 177 | static void init_page_array(void *hdr, u32 len, struct sk_buff *skb, | ||
| 178 | struct hv_page_buffer *pb) | ||
| 179 | { | ||
| 180 | u32 slots_used = 0; | ||
| 181 | char *data = skb->data; | ||
| 182 | int frags = skb_shinfo(skb)->nr_frags; | ||
| 183 | int i; | ||
| 184 | |||
| 185 | /* The packet is laid out thus: | ||
| 186 | * 1. hdr | ||
| 187 | * 2. skb linear data | ||
| 188 | * 3. skb fragment data | ||
| 189 | */ | ||
| 190 | if (hdr != NULL) | ||
| 191 | slots_used += fill_pg_buf(virt_to_page(hdr), | ||
| 192 | offset_in_page(hdr), | ||
| 193 | len, &pb[slots_used]); | ||
| 194 | |||
| 195 | slots_used += fill_pg_buf(virt_to_page(data), | ||
| 196 | offset_in_page(data), | ||
| 197 | skb_headlen(skb), &pb[slots_used]); | ||
| 198 | |||
| 199 | for (i = 0; i < frags; i++) { | ||
| 200 | skb_frag_t *frag = skb_shinfo(skb)->frags + i; | ||
| 201 | |||
| 202 | slots_used += fill_pg_buf(skb_frag_page(frag), | ||
| 203 | frag->page_offset, | ||
| 204 | skb_frag_size(frag), &pb[slots_used]); | ||
| 205 | } | ||
| 206 | } | ||
| 207 | |||
| 208 | static int count_skb_frag_slots(struct sk_buff *skb) | ||
| 209 | { | ||
| 210 | int i, frags = skb_shinfo(skb)->nr_frags; | ||
| 211 | int pages = 0; | ||
| 212 | |||
| 213 | for (i = 0; i < frags; i++) { | ||
| 214 | skb_frag_t *frag = skb_shinfo(skb)->frags + i; | ||
| 215 | unsigned long size = skb_frag_size(frag); | ||
| 216 | unsigned long offset = frag->page_offset; | ||
| 217 | |||
| 218 | /* Skip unused frames from start of page */ | ||
| 219 | offset &= ~PAGE_MASK; | ||
| 220 | pages += PFN_UP(offset + size); | ||
| 221 | } | ||
| 222 | return pages; | ||
| 223 | } | ||
| 224 | |||
| 225 | static int netvsc_get_slots(struct sk_buff *skb) | ||
| 226 | { | ||
| 227 | char *data = skb->data; | ||
| 228 | unsigned int offset = offset_in_page(data); | ||
| 229 | unsigned int len = skb_headlen(skb); | ||
| 230 | int slots; | ||
| 231 | int frag_slots; | ||
| 232 | |||
| 233 | slots = DIV_ROUND_UP(offset + len, PAGE_SIZE); | ||
| 234 | frag_slots = count_skb_frag_slots(skb); | ||
| 235 | return slots + frag_slots; | ||
| 236 | } | ||
| 237 | |||
| 143 | static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) | 238 | static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) |
| 144 | { | 239 | { |
| 145 | struct net_device_context *net_device_ctx = netdev_priv(net); | 240 | struct net_device_context *net_device_ctx = netdev_priv(net); |
| 146 | struct hv_netvsc_packet *packet; | 241 | struct hv_netvsc_packet *packet; |
| 147 | int ret; | 242 | int ret; |
| 148 | unsigned int i, num_pages, npg_data; | 243 | unsigned int num_data_pages; |
| 149 | 244 | ||
| 150 | /* Add multipages for skb->data and additional 2 for RNDIS */ | 245 | /* We will atmost need two pages to describe the rndis |
| 151 | npg_data = (((unsigned long)skb->data + skb_headlen(skb) - 1) | 246 | * header. We can only transmit MAX_PAGE_BUFFER_COUNT number |
| 152 | >> PAGE_SHIFT) - ((unsigned long)skb->data >> PAGE_SHIFT) + 1; | 247 | * of pages in a single packet. |
| 153 | num_pages = skb_shinfo(skb)->nr_frags + npg_data + 2; | 248 | */ |
| 249 | num_data_pages = netvsc_get_slots(skb) + 2; | ||
| 250 | if (num_data_pages > MAX_PAGE_BUFFER_COUNT) { | ||
| 251 | netdev_err(net, "Packet too big: %u\n", skb->len); | ||
| 252 | dev_kfree_skb(skb); | ||
| 253 | net->stats.tx_dropped++; | ||
| 254 | return NETDEV_TX_OK; | ||
| 255 | } | ||
| 154 | 256 | ||
| 155 | /* Allocate a netvsc packet based on # of frags. */ | 257 | /* Allocate a netvsc packet based on # of frags. */ |
| 156 | packet = kzalloc(sizeof(struct hv_netvsc_packet) + | 258 | packet = kzalloc(sizeof(struct hv_netvsc_packet) + |
| 157 | (num_pages * sizeof(struct hv_page_buffer)) + | 259 | (num_data_pages * sizeof(struct hv_page_buffer)) + |
| 158 | sizeof(struct rndis_message) + | 260 | sizeof(struct rndis_message) + |
| 159 | NDIS_VLAN_PPI_SIZE, GFP_ATOMIC); | 261 | NDIS_VLAN_PPI_SIZE, GFP_ATOMIC); |
| 160 | if (!packet) { | 262 | if (!packet) { |
| @@ -169,44 +271,17 @@ static int netvsc_start_xmit(struct sk_buff *skb, struct net_device *net) | |||
| 169 | packet->vlan_tci = skb->vlan_tci; | 271 | packet->vlan_tci = skb->vlan_tci; |
| 170 | 272 | ||
| 171 | packet->extension = (void *)(unsigned long)packet + | 273 | packet->extension = (void *)(unsigned long)packet + |
| 172 | sizeof(struct hv_netvsc_packet) + | 274 | sizeof(struct hv_netvsc_packet) + |
| 173 | (num_pages * sizeof(struct hv_page_buffer)); | 275 | (num_data_pages * sizeof(struct hv_page_buffer)); |
| 174 | 276 | ||
| 175 | /* If the rndis msg goes beyond 1 page, we will add 1 later */ | 277 | /* If the rndis msg goes beyond 1 page, we will add 1 later */ |
| 176 | packet->page_buf_cnt = num_pages - 1; | 278 | packet->page_buf_cnt = num_data_pages - 1; |
| 177 | 279 | ||
| 178 | /* Initialize it from the skb */ | 280 | /* Initialize it from the skb */ |
| 179 | packet->total_data_buflen = skb->len; | 281 | packet->total_data_buflen = skb->len; |
| 180 | 282 | ||
| 181 | /* Start filling in the page buffers starting after RNDIS buffer. */ | 283 | /* Start filling in the page buffers starting after RNDIS buffer. */ |
| 182 | packet->page_buf[1].pfn = virt_to_phys(skb->data) >> PAGE_SHIFT; | 284 | init_page_array(NULL, 0, skb, &packet->page_buf[1]); |
| 183 | packet->page_buf[1].offset | ||
| 184 | = (unsigned long)skb->data & (PAGE_SIZE - 1); | ||
| 185 | if (npg_data == 1) | ||
| 186 | packet->page_buf[1].len = skb_headlen(skb); | ||
| 187 | else | ||
| 188 | packet->page_buf[1].len = PAGE_SIZE | ||
| 189 | - packet->page_buf[1].offset; | ||
| 190 | |||
| 191 | for (i = 2; i <= npg_data; i++) { | ||
| 192 | packet->page_buf[i].pfn = virt_to_phys(skb->data | ||
| 193 | + PAGE_SIZE * (i-1)) >> PAGE_SHIFT; | ||
| 194 | packet->page_buf[i].offset = 0; | ||
| 195 | packet->page_buf[i].len = PAGE_SIZE; | ||
| 196 | } | ||
| 197 | if (npg_data > 1) | ||
| 198 | packet->page_buf[npg_data].len = (((unsigned long)skb->data | ||
| 199 | + skb_headlen(skb) - 1) & (PAGE_SIZE - 1)) + 1; | ||
| 200 | |||
| 201 | /* Additional fragments are after SKB data */ | ||
| 202 | for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { | ||
| 203 | const skb_frag_t *f = &skb_shinfo(skb)->frags[i]; | ||
| 204 | |||
| 205 | packet->page_buf[i+npg_data+1].pfn = | ||
| 206 | page_to_pfn(skb_frag_page(f)); | ||
| 207 | packet->page_buf[i+npg_data+1].offset = f->page_offset; | ||
| 208 | packet->page_buf[i+npg_data+1].len = skb_frag_size(f); | ||
| 209 | } | ||
| 210 | 285 | ||
| 211 | /* Set the completion routine */ | 286 | /* Set the completion routine */ |
| 212 | packet->completion.send.send_completion = netvsc_xmit_completion; | 287 | packet->completion.send.send_completion = netvsc_xmit_completion; |
| @@ -451,8 +526,8 @@ static int netvsc_probe(struct hv_device *dev, | |||
| 451 | net->netdev_ops = &device_ops; | 526 | net->netdev_ops = &device_ops; |
| 452 | 527 | ||
| 453 | /* TODO: Add GSO and Checksum offload */ | 528 | /* TODO: Add GSO and Checksum offload */ |
| 454 | net->hw_features = 0; | 529 | net->hw_features = NETIF_F_SG; |
| 455 | net->features = NETIF_F_HW_VLAN_CTAG_TX; | 530 | net->features = NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG; |
| 456 | 531 | ||
| 457 | SET_ETHTOOL_OPS(net, ðtool_ops); | 532 | SET_ETHTOOL_OPS(net, ðtool_ops); |
| 458 | SET_NETDEV_DEV(net, &dev->device); | 533 | SET_NETDEV_DEV(net, &dev->device); |
