diff options
Diffstat (limited to 'drivers/net/xen-netback/hash.c')
-rw-r--r-- | drivers/net/xen-netback/hash.c | 51 |
1 files changed, 36 insertions, 15 deletions
diff --git a/drivers/net/xen-netback/hash.c b/drivers/net/xen-netback/hash.c index 3c4c58b9fe76..0ccb021f1e78 100644 --- a/drivers/net/xen-netback/hash.c +++ b/drivers/net/xen-netback/hash.c | |||
@@ -324,7 +324,8 @@ u32 xenvif_set_hash_mapping_size(struct xenvif *vif, u32 size) | |||
324 | return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; | 324 | return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; |
325 | 325 | ||
326 | vif->hash.size = size; | 326 | vif->hash.size = size; |
327 | memset(vif->hash.mapping, 0, sizeof(u32) * size); | 327 | memset(vif->hash.mapping[vif->hash.mapping_sel], 0, |
328 | sizeof(u32) * size); | ||
328 | 329 | ||
329 | return XEN_NETIF_CTRL_STATUS_SUCCESS; | 330 | return XEN_NETIF_CTRL_STATUS_SUCCESS; |
330 | } | 331 | } |
@@ -332,31 +333,49 @@ u32 xenvif_set_hash_mapping_size(struct xenvif *vif, u32 size) | |||
332 | u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len, | 333 | u32 xenvif_set_hash_mapping(struct xenvif *vif, u32 gref, u32 len, |
333 | u32 off) | 334 | u32 off) |
334 | { | 335 | { |
335 | u32 *mapping = &vif->hash.mapping[off]; | 336 | u32 *mapping = vif->hash.mapping[!vif->hash.mapping_sel]; |
336 | struct gnttab_copy copy_op = { | 337 | unsigned int nr = 1; |
338 | struct gnttab_copy copy_op[2] = {{ | ||
337 | .source.u.ref = gref, | 339 | .source.u.ref = gref, |
338 | .source.domid = vif->domid, | 340 | .source.domid = vif->domid, |
339 | .dest.u.gmfn = virt_to_gfn(mapping), | ||
340 | .dest.domid = DOMID_SELF, | 341 | .dest.domid = DOMID_SELF, |
341 | .dest.offset = xen_offset_in_page(mapping), | 342 | .len = len * sizeof(*mapping), |
342 | .len = len * sizeof(u32), | ||
343 | .flags = GNTCOPY_source_gref | 343 | .flags = GNTCOPY_source_gref |
344 | }; | 344 | }}; |
345 | 345 | ||
346 | if ((off + len > vif->hash.size) || copy_op.len > XEN_PAGE_SIZE) | 346 | if ((off + len < off) || (off + len > vif->hash.size) || |
347 | len > XEN_PAGE_SIZE / sizeof(*mapping)) | ||
347 | return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; | 348 | return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; |
348 | 349 | ||
349 | while (len-- != 0) | 350 | copy_op[0].dest.u.gmfn = virt_to_gfn(mapping + off); |
350 | if (mapping[off++] >= vif->num_queues) | 351 | copy_op[0].dest.offset = xen_offset_in_page(mapping + off); |
351 | return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; | 352 | if (copy_op[0].dest.offset + copy_op[0].len > XEN_PAGE_SIZE) { |
353 | copy_op[1] = copy_op[0]; | ||
354 | copy_op[1].source.offset = XEN_PAGE_SIZE - copy_op[0].dest.offset; | ||
355 | copy_op[1].dest.u.gmfn = virt_to_gfn(mapping + off + len); | ||
356 | copy_op[1].dest.offset = 0; | ||
357 | copy_op[1].len = copy_op[0].len - copy_op[1].source.offset; | ||
358 | copy_op[0].len = copy_op[1].source.offset; | ||
359 | nr = 2; | ||
360 | } | ||
352 | 361 | ||
353 | if (copy_op.len != 0) { | 362 | memcpy(mapping, vif->hash.mapping[vif->hash.mapping_sel], |
354 | gnttab_batch_copy(©_op, 1); | 363 | vif->hash.size * sizeof(*mapping)); |
355 | 364 | ||
356 | if (copy_op.status != GNTST_okay) | 365 | if (copy_op[0].len != 0) { |
366 | gnttab_batch_copy(copy_op, nr); | ||
367 | |||
368 | if (copy_op[0].status != GNTST_okay || | ||
369 | copy_op[nr - 1].status != GNTST_okay) | ||
357 | return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; | 370 | return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; |
358 | } | 371 | } |
359 | 372 | ||
373 | while (len-- != 0) | ||
374 | if (mapping[off++] >= vif->num_queues) | ||
375 | return XEN_NETIF_CTRL_STATUS_INVALID_PARAMETER; | ||
376 | |||
377 | vif->hash.mapping_sel = !vif->hash.mapping_sel; | ||
378 | |||
360 | return XEN_NETIF_CTRL_STATUS_SUCCESS; | 379 | return XEN_NETIF_CTRL_STATUS_SUCCESS; |
361 | } | 380 | } |
362 | 381 | ||
@@ -408,6 +427,8 @@ void xenvif_dump_hash_info(struct xenvif *vif, struct seq_file *m) | |||
408 | } | 427 | } |
409 | 428 | ||
410 | if (vif->hash.size != 0) { | 429 | if (vif->hash.size != 0) { |
430 | const u32 *mapping = vif->hash.mapping[vif->hash.mapping_sel]; | ||
431 | |||
411 | seq_puts(m, "\nHash Mapping:\n"); | 432 | seq_puts(m, "\nHash Mapping:\n"); |
412 | 433 | ||
413 | for (i = 0; i < vif->hash.size; ) { | 434 | for (i = 0; i < vif->hash.size; ) { |
@@ -420,7 +441,7 @@ void xenvif_dump_hash_info(struct xenvif *vif, struct seq_file *m) | |||
420 | seq_printf(m, "[%4u - %4u]: ", i, i + n - 1); | 441 | seq_printf(m, "[%4u - %4u]: ", i, i + n - 1); |
421 | 442 | ||
422 | for (j = 0; j < n; j++, i++) | 443 | for (j = 0; j < n; j++, i++) |
423 | seq_printf(m, "%4u ", vif->hash.mapping[i]); | 444 | seq_printf(m, "%4u ", mapping[i]); |
424 | 445 | ||
425 | seq_puts(m, "\n"); | 446 | seq_puts(m, "\n"); |
426 | } | 447 | } |