Lines 48-54
Link Here
|
48 |
#include "hv_rndis.h" |
48 |
#include "hv_rndis.h" |
49 |
#include "hv_rndis_filter.h" |
49 |
#include "hv_rndis_filter.h" |
50 |
|
50 |
|
51 |
MALLOC_DEFINE(M_NETVSC, "netvsc", "Hyper-V netvsc driver"); |
|
|
52 |
|
51 |
|
53 |
/* |
52 |
/* |
54 |
* Forward declarations |
53 |
* Forward declarations |
Lines 59-69
Link Here
|
59 |
static int hv_nv_destroy_send_buffer(netvsc_dev *net_dev); |
58 |
static int hv_nv_destroy_send_buffer(netvsc_dev *net_dev); |
60 |
static int hv_nv_destroy_rx_buffer(netvsc_dev *net_dev); |
59 |
static int hv_nv_destroy_rx_buffer(netvsc_dev *net_dev); |
61 |
static int hv_nv_connect_to_vsp(struct hv_device *device); |
60 |
static int hv_nv_connect_to_vsp(struct hv_device *device); |
62 |
static void hv_nv_on_send_completion(netvsc_dev *net_dev, |
61 |
static void hv_nv_on_send_completion(struct hv_device *device, |
63 |
struct hv_device *device, hv_vm_packet_descriptor *pkt); |
62 |
hv_vm_packet_descriptor *pkt); |
64 |
static void hv_nv_on_receive(netvsc_dev *net_dev, |
63 |
static void hv_nv_on_receive(struct hv_device *device, |
65 |
struct hv_device *device, hv_vm_packet_descriptor *pkt); |
64 |
hv_vm_packet_descriptor *pkt); |
|
|
65 |
static void hv_nv_send_receive_completion(struct hv_device *device, |
66 |
uint64_t tid); |
66 |
|
67 |
|
|
|
68 |
|
67 |
/* |
69 |
/* |
68 |
* |
70 |
* |
69 |
*/ |
71 |
*/ |
Lines 73-79
Link Here
|
73 |
netvsc_dev *net_dev; |
75 |
netvsc_dev *net_dev; |
74 |
hn_softc_t *sc = device_get_softc(device->device); |
76 |
hn_softc_t *sc = device_get_softc(device->device); |
75 |
|
77 |
|
76 |
net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_NOWAIT | M_ZERO); |
78 |
net_dev = malloc(sizeof(netvsc_dev), M_DEVBUF, M_NOWAIT | M_ZERO); |
77 |
if (net_dev == NULL) { |
79 |
if (net_dev == NULL) { |
78 |
return (NULL); |
80 |
return (NULL); |
79 |
} |
81 |
} |
Lines 125-158
Link Here
|
125 |
return (net_dev); |
127 |
return (net_dev); |
126 |
} |
128 |
} |
127 |
|
129 |
|
128 |
int |
|
|
129 |
hv_nv_get_next_send_section(netvsc_dev *net_dev) |
130 |
{ |
131 |
unsigned long bitsmap_words = net_dev->bitsmap_words; |
132 |
unsigned long *bitsmap = net_dev->send_section_bitsmap; |
133 |
unsigned long idx; |
134 |
int ret = NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX; |
135 |
int i; |
136 |
|
137 |
for (i = 0; i < bitsmap_words; i++) { |
138 |
idx = ffs(~bitsmap[i]); |
139 |
if (0 == idx) |
140 |
continue; |
141 |
|
142 |
idx--; |
143 |
if (i * BITS_PER_LONG + idx >= net_dev->send_section_count) |
144 |
return (ret); |
145 |
|
146 |
if (synch_test_and_set_bit(idx, &bitsmap[i])) |
147 |
continue; |
148 |
|
149 |
ret = i * BITS_PER_LONG + idx; |
150 |
break; |
151 |
} |
152 |
|
153 |
return (ret); |
154 |
} |
155 |
|
156 |
/* |
130 |
/* |
157 |
* Net VSC initialize receive buffer with net VSP |
131 |
* Net VSC initialize receive buffer with net VSP |
158 |
* |
132 |
* |
Lines 171-178
Link Here
|
171 |
return (ENODEV); |
145 |
return (ENODEV); |
172 |
} |
146 |
} |
173 |
|
147 |
|
174 |
net_dev->rx_buf = contigmalloc(net_dev->rx_buf_size, M_NETVSC, |
148 |
net_dev->rx_buf = contigmalloc(net_dev->rx_buf_size, M_DEVBUF, |
175 |
M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); |
149 |
M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); |
|
|
150 |
if (net_dev->rx_buf == NULL) { |
151 |
ret = ENOMEM; |
152 |
goto cleanup; |
153 |
} |
176 |
|
154 |
|
177 |
/* |
155 |
/* |
178 |
* Establish the GPADL handle for this buffer on this channel. |
156 |
* Establish the GPADL handle for this buffer on this channel. |
Lines 223-229
Link Here
|
223 |
init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections; |
201 |
init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections; |
224 |
|
202 |
|
225 |
net_dev->rx_sections = malloc(net_dev->rx_section_count * |
203 |
net_dev->rx_sections = malloc(net_dev->rx_section_count * |
226 |
sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_NOWAIT); |
204 |
sizeof(nvsp_1_rx_buf_section), M_DEVBUF, M_NOWAIT); |
227 |
if (net_dev->rx_sections == NULL) { |
205 |
if (net_dev->rx_sections == NULL) { |
228 |
ret = EINVAL; |
206 |
ret = EINVAL; |
229 |
goto cleanup; |
207 |
goto cleanup; |
Lines 267-273
Link Here
|
267 |
return (ENODEV); |
245 |
return (ENODEV); |
268 |
} |
246 |
} |
269 |
|
247 |
|
270 |
net_dev->send_buf = contigmalloc(net_dev->send_buf_size, M_NETVSC, |
248 |
net_dev->send_buf = contigmalloc(net_dev->send_buf_size, M_DEVBUF, |
271 |
M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); |
249 |
M_ZERO, 0UL, BUS_SPACE_MAXADDR, PAGE_SIZE, 0); |
272 |
if (net_dev->send_buf == NULL) { |
250 |
if (net_dev->send_buf == NULL) { |
273 |
ret = ENOMEM; |
251 |
ret = ENOMEM; |
Lines 280-286
Link Here
|
280 |
* channel to establish the gpadl handle. |
258 |
* channel to establish the gpadl handle. |
281 |
*/ |
259 |
*/ |
282 |
ret = hv_vmbus_channel_establish_gpadl(device->channel, |
260 |
ret = hv_vmbus_channel_establish_gpadl(device->channel, |
283 |
net_dev->send_buf, net_dev->send_buf_size, |
261 |
net_dev->send_buf, net_dev->send_buf_size, |
284 |
&net_dev->send_buf_gpadl_handle); |
262 |
&net_dev->send_buf_gpadl_handle); |
285 |
if (ret != 0) { |
263 |
if (ret != 0) { |
286 |
goto cleanup; |
264 |
goto cleanup; |
Lines 301-307
Link Here
|
301 |
/* Send the gpadl notification request */ |
279 |
/* Send the gpadl notification request */ |
302 |
|
280 |
|
303 |
ret = hv_vmbus_channel_send_packet(device->channel, init_pkt, |
281 |
ret = hv_vmbus_channel_send_packet(device->channel, init_pkt, |
304 |
sizeof(nvsp_msg), (uint64_t)init_pkt, |
282 |
sizeof(nvsp_msg), (uint64_t)(uintptr_t)init_pkt, |
305 |
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, |
283 |
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, |
306 |
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
284 |
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
307 |
if (ret != 0) { |
285 |
if (ret != 0) { |
Lines 319-335
Link Here
|
319 |
|
297 |
|
320 |
net_dev->send_section_size = |
298 |
net_dev->send_section_size = |
321 |
init_pkt->msgs.vers_1_msgs.send_send_buf_complete.section_size; |
299 |
init_pkt->msgs.vers_1_msgs.send_send_buf_complete.section_size; |
322 |
net_dev->send_section_count = |
|
|
323 |
net_dev->send_buf_size / net_dev->send_section_size; |
324 |
net_dev->bitsmap_words = howmany(net_dev->send_section_count, |
325 |
BITS_PER_LONG); |
326 |
net_dev->send_section_bitsmap = |
327 |
malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC, |
328 |
M_NOWAIT | M_ZERO); |
329 |
if (NULL == net_dev->send_section_bitsmap) { |
330 |
ret = ENOMEM; |
331 |
goto cleanup; |
332 |
} |
333 |
|
300 |
|
334 |
goto exit; |
301 |
goto exit; |
335 |
|
302 |
|
Lines 394-405
Link Here
|
394 |
|
361 |
|
395 |
if (net_dev->rx_buf) { |
362 |
if (net_dev->rx_buf) { |
396 |
/* Free up the receive buffer */ |
363 |
/* Free up the receive buffer */ |
397 |
contigfree(net_dev->rx_buf, net_dev->rx_buf_size, M_NETVSC); |
364 |
contigfree(net_dev->rx_buf, net_dev->rx_buf_size, M_DEVBUF); |
398 |
net_dev->rx_buf = NULL; |
365 |
net_dev->rx_buf = NULL; |
399 |
} |
366 |
} |
400 |
|
367 |
|
401 |
if (net_dev->rx_sections) { |
368 |
if (net_dev->rx_sections) { |
402 |
free(net_dev->rx_sections, M_NETVSC); |
369 |
free(net_dev->rx_sections, M_DEVBUF); |
403 |
net_dev->rx_sections = NULL; |
370 |
net_dev->rx_sections = NULL; |
404 |
net_dev->rx_section_count = 0; |
371 |
net_dev->rx_section_count = 0; |
405 |
} |
372 |
} |
Lines 462-475
Link Here
|
462 |
|
429 |
|
463 |
if (net_dev->send_buf) { |
430 |
if (net_dev->send_buf) { |
464 |
/* Free up the receive buffer */ |
431 |
/* Free up the receive buffer */ |
465 |
contigfree(net_dev->send_buf, net_dev->send_buf_size, M_NETVSC); |
432 |
contigfree(net_dev->send_buf, net_dev->send_buf_size, M_DEVBUF); |
466 |
net_dev->send_buf = NULL; |
433 |
net_dev->send_buf = NULL; |
467 |
} |
434 |
} |
468 |
|
435 |
|
469 |
if (net_dev->send_section_bitsmap) { |
|
|
470 |
free(net_dev->send_section_bitsmap, M_NETVSC); |
471 |
} |
472 |
|
473 |
return (ret); |
436 |
return (ret); |
474 |
} |
437 |
} |
475 |
|
438 |
|
Lines 483-489
Link Here
|
483 |
*/ |
446 |
*/ |
484 |
static int |
447 |
static int |
485 |
hv_nv_negotiate_nvsp_protocol(struct hv_device *device, netvsc_dev *net_dev, |
448 |
hv_nv_negotiate_nvsp_protocol(struct hv_device *device, netvsc_dev *net_dev, |
486 |
uint32_t nvsp_ver) |
449 |
uint32_t nvsp_ver) |
487 |
{ |
450 |
{ |
488 |
nvsp_msg *init_pkt; |
451 |
nvsp_msg *init_pkt; |
489 |
int ret; |
452 |
int ret; |
Lines 560-572
Link Here
|
560 |
{ |
523 |
{ |
561 |
netvsc_dev *net_dev; |
524 |
netvsc_dev *net_dev; |
562 |
nvsp_msg *init_pkt; |
525 |
nvsp_msg *init_pkt; |
|
|
526 |
uint32_t nvsp_vers; |
563 |
uint32_t ndis_version; |
527 |
uint32_t ndis_version; |
564 |
uint32_t protocol_list[] = { NVSP_PROTOCOL_VERSION_1, |
|
|
565 |
NVSP_PROTOCOL_VERSION_2, |
566 |
NVSP_PROTOCOL_VERSION_4, |
567 |
NVSP_PROTOCOL_VERSION_5 }; |
568 |
int i; |
569 |
int protocol_number = nitems(protocol_list); |
570 |
int ret = 0; |
528 |
int ret = 0; |
571 |
device_t dev = device->device; |
529 |
device_t dev = device->device; |
572 |
hn_softc_t *sc = device_get_softc(dev); |
530 |
hn_softc_t *sc = device_get_softc(dev); |
Lines 578-608
Link Here
|
578 |
} |
536 |
} |
579 |
|
537 |
|
580 |
/* |
538 |
/* |
581 |
* Negotiate the NVSP version. Try the latest NVSP first. |
539 |
* Negotiate the NVSP version. Try NVSP v2 first. |
582 |
*/ |
540 |
*/ |
583 |
for (i = protocol_number - 1; i >= 0; i--) { |
541 |
nvsp_vers = NVSP_PROTOCOL_VERSION_2; |
584 |
if (hv_nv_negotiate_nvsp_protocol(device, net_dev, |
542 |
ret = hv_nv_negotiate_nvsp_protocol(device, net_dev, nvsp_vers); |
585 |
protocol_list[i]) == 0) { |
543 |
if (ret != 0) { |
586 |
net_dev->nvsp_version = protocol_list[i]; |
544 |
/* NVSP v2 failed, try NVSP v1 */ |
587 |
if (bootverbose) |
545 |
nvsp_vers = NVSP_PROTOCOL_VERSION_1; |
588 |
device_printf(dev, "Netvsc: got version 0x%x\n", |
546 |
ret = hv_nv_negotiate_nvsp_protocol(device, net_dev, nvsp_vers); |
589 |
net_dev->nvsp_version); |
547 |
if (ret != 0) { |
590 |
break; |
548 |
/* NVSP v1 failed, return bad status */ |
|
|
549 |
return (ret); |
591 |
} |
550 |
} |
592 |
} |
551 |
} |
|
|
552 |
net_dev->nvsp_version = nvsp_vers; |
593 |
|
553 |
|
594 |
if (i < 0) { |
|
|
595 |
if (bootverbose) |
596 |
device_printf(dev, "failed to negotiate a valid " |
597 |
"protocol.\n"); |
598 |
return (EPROTO); |
599 |
} |
600 |
|
601 |
/* |
554 |
/* |
602 |
* Set the MTU if supported by this NVSP protocol version |
555 |
* Set the MTU if supported by this NVSP protocol version |
603 |
* This needs to be right after the NVSP init message per Haiyang |
556 |
* This needs to be right after the NVSP init message per Haiyang |
604 |
*/ |
557 |
*/ |
605 |
if (net_dev->nvsp_version >= NVSP_PROTOCOL_VERSION_2) |
558 |
if (nvsp_vers >= NVSP_PROTOCOL_VERSION_2) |
606 |
ret = hv_nv_send_ndis_config(device, ifp->if_mtu); |
559 |
ret = hv_nv_send_ndis_config(device, ifp->if_mtu); |
607 |
|
560 |
|
608 |
/* |
561 |
/* |
Lines 612-622
Link Here
|
612 |
|
565 |
|
613 |
memset(init_pkt, 0, sizeof(nvsp_msg)); |
566 |
memset(init_pkt, 0, sizeof(nvsp_msg)); |
614 |
|
567 |
|
615 |
if (net_dev->nvsp_version <= NVSP_PROTOCOL_VERSION_4) { |
568 |
/* |
616 |
ndis_version = NDIS_VERSION_6_1; |
569 |
* Updated to version 5.1, minimum, for VLAN per Haiyang |
617 |
} else { |
570 |
*/ |
618 |
ndis_version = NDIS_VERSION_6_30; |
571 |
ndis_version = NDIS_VERSION; |
619 |
} |
|
|
620 |
|
572 |
|
621 |
init_pkt->hdr.msg_type = nvsp_msg_1_type_send_ndis_vers; |
573 |
init_pkt->hdr.msg_type = nvsp_msg_1_type_send_ndis_vers; |
622 |
init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_major_vers = |
574 |
init_pkt->msgs.vers_1_msgs.send_ndis_vers.ndis_major_vers = |
Lines 668-674
Link Here
|
668 |
hv_nv_on_device_add(struct hv_device *device, void *additional_info) |
620 |
hv_nv_on_device_add(struct hv_device *device, void *additional_info) |
669 |
{ |
621 |
{ |
670 |
netvsc_dev *net_dev; |
622 |
netvsc_dev *net_dev; |
671 |
int ret = 0; |
623 |
netvsc_packet *packet; |
|
|
624 |
netvsc_packet *next_packet; |
625 |
int i, ret = 0; |
672 |
|
626 |
|
673 |
net_dev = hv_nv_alloc_net_device(device); |
627 |
net_dev = hv_nv_alloc_net_device(device); |
674 |
if (!net_dev) |
628 |
if (!net_dev) |
Lines 676-684
Link Here
|
676 |
|
630 |
|
677 |
/* Initialize the NetVSC channel extension */ |
631 |
/* Initialize the NetVSC channel extension */ |
678 |
net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; |
632 |
net_dev->rx_buf_size = NETVSC_RECEIVE_BUFFER_SIZE; |
|
|
633 |
mtx_init(&net_dev->rx_pkt_list_lock, "HV-RPL", NULL, |
634 |
MTX_SPIN | MTX_RECURSE); |
679 |
|
635 |
|
680 |
net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE; |
636 |
net_dev->send_buf_size = NETVSC_SEND_BUFFER_SIZE; |
681 |
|
637 |
|
|
|
638 |
/* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */ |
639 |
STAILQ_INIT(&net_dev->myrx_packet_list); |
640 |
|
641 |
/* |
642 |
* malloc a sufficient number of netvsc_packet buffers to hold |
643 |
* a packet list. Add them to the netvsc device packet queue. |
644 |
*/ |
645 |
for (i=0; i < NETVSC_RECEIVE_PACKETLIST_COUNT; i++) { |
646 |
packet = malloc(sizeof(netvsc_packet) + |
647 |
(NETVSC_RECEIVE_SG_COUNT * sizeof(hv_vmbus_page_buffer)), |
648 |
M_DEVBUF, M_NOWAIT | M_ZERO); |
649 |
if (!packet) { |
650 |
break; |
651 |
} |
652 |
STAILQ_INSERT_TAIL(&net_dev->myrx_packet_list, packet, |
653 |
mylist_entry); |
654 |
} |
655 |
|
682 |
sema_init(&net_dev->channel_init_sema, 0, "netdev_sema"); |
656 |
sema_init(&net_dev->channel_init_sema, 0, "netdev_sema"); |
683 |
|
657 |
|
684 |
/* |
658 |
/* |
Lines 711-717
Link Here
|
711 |
*/ |
685 |
*/ |
712 |
if (net_dev) { |
686 |
if (net_dev) { |
713 |
sema_destroy(&net_dev->channel_init_sema); |
687 |
sema_destroy(&net_dev->channel_init_sema); |
714 |
free(net_dev, M_NETVSC); |
688 |
|
|
|
689 |
packet = STAILQ_FIRST(&net_dev->myrx_packet_list); |
690 |
while (packet != NULL) { |
691 |
next_packet = STAILQ_NEXT(packet, mylist_entry); |
692 |
free(packet, M_DEVBUF); |
693 |
packet = next_packet; |
694 |
} |
695 |
/* Reset the list to initial state */ |
696 |
STAILQ_INIT(&net_dev->myrx_packet_list); |
697 |
|
698 |
mtx_destroy(&net_dev->rx_pkt_list_lock); |
699 |
|
700 |
free(net_dev, M_DEVBUF); |
715 |
} |
701 |
} |
716 |
|
702 |
|
717 |
return (NULL); |
703 |
return (NULL); |
Lines 723-728
Link Here
|
723 |
int |
709 |
int |
724 |
hv_nv_on_device_remove(struct hv_device *device, boolean_t destroy_channel) |
710 |
hv_nv_on_device_remove(struct hv_device *device, boolean_t destroy_channel) |
725 |
{ |
711 |
{ |
|
|
712 |
netvsc_packet *net_vsc_pkt; |
713 |
netvsc_packet *next_net_vsc_pkt; |
726 |
hn_softc_t *sc = device_get_softc(device->device); |
714 |
hn_softc_t *sc = device_get_softc(device->device); |
727 |
netvsc_dev *net_dev = sc->net_dev;; |
715 |
netvsc_dev *net_dev = sc->net_dev;; |
728 |
|
716 |
|
Lines 749-756
Link Here
|
749 |
|
737 |
|
750 |
hv_vmbus_channel_close(device->channel); |
738 |
hv_vmbus_channel_close(device->channel); |
751 |
|
739 |
|
|
|
740 |
/* Release all resources */ |
741 |
net_vsc_pkt = STAILQ_FIRST(&net_dev->myrx_packet_list); |
742 |
while (net_vsc_pkt != NULL) { |
743 |
next_net_vsc_pkt = STAILQ_NEXT(net_vsc_pkt, mylist_entry); |
744 |
free(net_vsc_pkt, M_DEVBUF); |
745 |
net_vsc_pkt = next_net_vsc_pkt; |
746 |
} |
747 |
|
748 |
/* Reset the list to initial state */ |
749 |
STAILQ_INIT(&net_dev->myrx_packet_list); |
750 |
|
751 |
mtx_destroy(&net_dev->rx_pkt_list_lock); |
752 |
sema_destroy(&net_dev->channel_init_sema); |
752 |
sema_destroy(&net_dev->channel_init_sema); |
753 |
free(net_dev, M_NETVSC); |
753 |
free(net_dev, M_DEVBUF); |
754 |
|
754 |
|
755 |
return (0); |
755 |
return (0); |
756 |
} |
756 |
} |
Lines 758-770
Link Here
|
758 |
/* |
758 |
/* |
759 |
* Net VSC on send completion |
759 |
* Net VSC on send completion |
760 |
*/ |
760 |
*/ |
761 |
static void |
761 |
static void |
762 |
hv_nv_on_send_completion(netvsc_dev *net_dev, |
762 |
hv_nv_on_send_completion(struct hv_device *device, hv_vm_packet_descriptor *pkt) |
763 |
struct hv_device *device, hv_vm_packet_descriptor *pkt) |
|
|
764 |
{ |
763 |
{ |
|
|
764 |
netvsc_dev *net_dev; |
765 |
nvsp_msg *nvsp_msg_pkt; |
765 |
nvsp_msg *nvsp_msg_pkt; |
766 |
netvsc_packet *net_vsc_pkt; |
766 |
netvsc_packet *net_vsc_pkt; |
767 |
|
767 |
|
|
|
768 |
net_dev = hv_nv_get_inbound_net_device(device); |
769 |
if (!net_dev) { |
770 |
return; |
771 |
} |
772 |
|
768 |
nvsp_msg_pkt = |
773 |
nvsp_msg_pkt = |
769 |
(nvsp_msg *)((unsigned long)pkt + (pkt->data_offset8 << 3)); |
774 |
(nvsp_msg *)((unsigned long)pkt + (pkt->data_offset8 << 3)); |
770 |
|
775 |
|
Lines 775-799
Link Here
|
775 |
== nvsp_msg_1_type_send_send_buf_complete) { |
780 |
== nvsp_msg_1_type_send_send_buf_complete) { |
776 |
/* Copy the response back */ |
781 |
/* Copy the response back */ |
777 |
memcpy(&net_dev->channel_init_packet, nvsp_msg_pkt, |
782 |
memcpy(&net_dev->channel_init_packet, nvsp_msg_pkt, |
778 |
sizeof(nvsp_msg)); |
783 |
sizeof(nvsp_msg)); |
779 |
sema_post(&net_dev->channel_init_sema); |
784 |
sema_post(&net_dev->channel_init_sema); |
780 |
} else if (nvsp_msg_pkt->hdr.msg_type == |
785 |
} else if (nvsp_msg_pkt->hdr.msg_type == |
781 |
nvsp_msg_1_type_send_rndis_pkt_complete) { |
786 |
nvsp_msg_1_type_send_rndis_pkt_complete) { |
782 |
/* Get the send context */ |
787 |
/* Get the send context */ |
783 |
net_vsc_pkt = |
788 |
net_vsc_pkt = |
784 |
(netvsc_packet *)(unsigned long)pkt->transaction_id; |
789 |
(netvsc_packet *)(unsigned long)pkt->transaction_id; |
785 |
if (NULL != net_vsc_pkt) { |
|
|
786 |
if (net_vsc_pkt->send_buf_section_idx != |
787 |
NVSP_1_CHIMNEY_SEND_INVALID_SECTION_INDEX) { |
788 |
synch_change_bit(net_vsc_pkt->send_buf_section_idx, |
789 |
net_dev->send_section_bitsmap); |
790 |
} |
791 |
|
792 |
/* Notify the layer above us */ |
793 |
net_vsc_pkt->compl.send.on_send_completion( |
794 |
net_vsc_pkt->compl.send.send_completion_context); |
795 |
|
790 |
|
796 |
} |
791 |
/* Notify the layer above us */ |
|
|
792 |
net_vsc_pkt->compl.send.on_send_completion( |
793 |
net_vsc_pkt->compl.send.send_completion_context); |
797 |
|
794 |
|
798 |
atomic_subtract_int(&net_dev->num_outstanding_sends, 1); |
795 |
atomic_subtract_int(&net_dev->num_outstanding_sends, 1); |
799 |
} |
796 |
} |
Lines 824-833
Link Here
|
824 |
send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 1; |
821 |
send_msg.msgs.vers_1_msgs.send_rndis_pkt.chan_type = 1; |
825 |
} |
822 |
} |
826 |
|
823 |
|
|
|
824 |
/* Not using send buffer section */ |
827 |
send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_idx = |
825 |
send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_idx = |
828 |
pkt->send_buf_section_idx; |
826 |
0xFFFFFFFF; |
829 |
send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size = |
827 |
send_msg.msgs.vers_1_msgs.send_rndis_pkt.send_buf_section_size = 0; |
830 |
pkt->send_buf_section_size; |
|
|
831 |
|
828 |
|
832 |
if (pkt->page_buf_count) { |
829 |
if (pkt->page_buf_count) { |
833 |
ret = hv_vmbus_channel_send_packet_pagebuffer(device->channel, |
830 |
ret = hv_vmbus_channel_send_packet_pagebuffer(device->channel, |
Lines 853-933
Link Here
|
853 |
* In the FreeBSD Hyper-V virtual world, this function deals exclusively |
850 |
* In the FreeBSD Hyper-V virtual world, this function deals exclusively |
854 |
* with virtual addresses. |
851 |
* with virtual addresses. |
855 |
*/ |
852 |
*/ |
856 |
static void |
853 |
static void |
857 |
hv_nv_on_receive(netvsc_dev *net_dev, struct hv_device *device, |
854 |
hv_nv_on_receive(struct hv_device *device, hv_vm_packet_descriptor *pkt) |
858 |
hv_vm_packet_descriptor *pkt) |
|
|
859 |
{ |
855 |
{ |
|
|
856 |
netvsc_dev *net_dev; |
860 |
hv_vm_transfer_page_packet_header *vm_xfer_page_pkt; |
857 |
hv_vm_transfer_page_packet_header *vm_xfer_page_pkt; |
861 |
nvsp_msg *nvsp_msg_pkt; |
858 |
nvsp_msg *nvsp_msg_pkt; |
862 |
netvsc_packet vsc_pkt; |
859 |
netvsc_packet *net_vsc_pkt = NULL; |
863 |
netvsc_packet *net_vsc_pkt = &vsc_pkt; |
860 |
unsigned long start; |
864 |
device_t dev = device->device; |
861 |
xfer_page_packet *xfer_page_pkt = NULL; |
|
|
862 |
STAILQ_HEAD(PKT_LIST, netvsc_packet_) mylist_head = |
863 |
STAILQ_HEAD_INITIALIZER(mylist_head); |
865 |
int count = 0; |
864 |
int count = 0; |
866 |
int i = 0; |
865 |
int i = 0; |
867 |
int status = nvsp_status_success; |
|
|
868 |
|
866 |
|
|
|
867 |
net_dev = hv_nv_get_inbound_net_device(device); |
868 |
if (!net_dev) |
869 |
return; |
870 |
|
869 |
/* |
871 |
/* |
870 |
* All inbound packets other than send completion should be |
872 |
* All inbound packets other than send completion should be |
871 |
* xfer page packet. |
873 |
* xfer page packet. |
872 |
*/ |
874 |
*/ |
873 |
if (pkt->type != HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES) { |
875 |
if (pkt->type != HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES) |
874 |
device_printf(dev, "packet type %d is invalid!\n", pkt->type); |
|
|
875 |
return; |
876 |
return; |
876 |
} |
|
|
877 |
|
877 |
|
878 |
nvsp_msg_pkt = (nvsp_msg *)((unsigned long)pkt |
878 |
nvsp_msg_pkt = (nvsp_msg *)((unsigned long)pkt |
879 |
+ (pkt->data_offset8 << 3)); |
879 |
+ (pkt->data_offset8 << 3)); |
880 |
|
880 |
|
881 |
/* Make sure this is a valid nvsp packet */ |
881 |
/* Make sure this is a valid nvsp packet */ |
882 |
if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) { |
882 |
if (nvsp_msg_pkt->hdr.msg_type != nvsp_msg_1_type_send_rndis_pkt) |
883 |
device_printf(dev, "packet hdr type %d is invalid!\n", |
|
|
884 |
pkt->type); |
885 |
return; |
883 |
return; |
886 |
} |
|
|
887 |
|
884 |
|
888 |
vm_xfer_page_pkt = (hv_vm_transfer_page_packet_header *)pkt; |
885 |
vm_xfer_page_pkt = (hv_vm_transfer_page_packet_header *)pkt; |
889 |
|
886 |
|
890 |
if (vm_xfer_page_pkt->transfer_page_set_id != |
887 |
if (vm_xfer_page_pkt->transfer_page_set_id |
891 |
NETVSC_RECEIVE_BUFFER_ID) { |
888 |
!= NETVSC_RECEIVE_BUFFER_ID) { |
892 |
device_printf(dev, "transfer_page_set_id %d is invalid!\n", |
|
|
893 |
vm_xfer_page_pkt->transfer_page_set_id); |
894 |
return; |
889 |
return; |
895 |
} |
890 |
} |
896 |
|
891 |
|
897 |
count = vm_xfer_page_pkt->range_count; |
892 |
STAILQ_INIT(&mylist_head); |
898 |
net_vsc_pkt->device = device; |
|
|
899 |
|
893 |
|
|
|
894 |
/* |
895 |
* Grab free packets (range count + 1) to represent this xfer page |
896 |
* packet. +1 to represent the xfer page packet itself. We grab it |
897 |
* here so that we know exactly how many we can fulfill. |
898 |
*/ |
899 |
mtx_lock_spin(&net_dev->rx_pkt_list_lock); |
900 |
while (!STAILQ_EMPTY(&net_dev->myrx_packet_list)) { |
901 |
net_vsc_pkt = STAILQ_FIRST(&net_dev->myrx_packet_list); |
902 |
STAILQ_REMOVE_HEAD(&net_dev->myrx_packet_list, mylist_entry); |
903 |
|
904 |
STAILQ_INSERT_TAIL(&mylist_head, net_vsc_pkt, mylist_entry); |
905 |
|
906 |
if (++count == vm_xfer_page_pkt->range_count + 1) |
907 |
break; |
908 |
} |
909 |
|
910 |
mtx_unlock_spin(&net_dev->rx_pkt_list_lock); |
911 |
|
912 |
/* |
913 |
* We need at least 2 netvsc pkts (1 to represent the xfer page |
914 |
* and at least 1 for the range) i.e. we can handle some of the |
915 |
* xfer page packet ranges... |
916 |
*/ |
917 |
if (count < 2) { |
918 |
/* Return netvsc packet to the freelist */ |
919 |
mtx_lock_spin(&net_dev->rx_pkt_list_lock); |
920 |
for (i=count; i != 0; i--) { |
921 |
net_vsc_pkt = STAILQ_FIRST(&mylist_head); |
922 |
STAILQ_REMOVE_HEAD(&mylist_head, mylist_entry); |
923 |
|
924 |
STAILQ_INSERT_TAIL(&net_dev->myrx_packet_list, |
925 |
net_vsc_pkt, mylist_entry); |
926 |
} |
927 |
mtx_unlock_spin(&net_dev->rx_pkt_list_lock); |
928 |
|
929 |
hv_nv_send_receive_completion(device, |
930 |
vm_xfer_page_pkt->d.transaction_id); |
931 |
|
932 |
return; |
933 |
} |
934 |
|
935 |
/* Take the first packet in the list */ |
936 |
xfer_page_pkt = (xfer_page_packet *)STAILQ_FIRST(&mylist_head); |
937 |
STAILQ_REMOVE_HEAD(&mylist_head, mylist_entry); |
938 |
|
939 |
/* This is how many data packets we can supply */ |
940 |
xfer_page_pkt->count = count - 1; |
941 |
|
900 |
/* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */ |
942 |
/* Each range represents 1 RNDIS pkt that contains 1 Ethernet frame */ |
901 |
for (i = 0; i < count; i++) { |
943 |
for (i=0; i < (count - 1); i++) { |
902 |
net_vsc_pkt->status = nvsp_status_success; |
944 |
net_vsc_pkt = STAILQ_FIRST(&mylist_head); |
903 |
net_vsc_pkt->data = (void *)((unsigned long)net_dev->rx_buf + |
945 |
STAILQ_REMOVE_HEAD(&mylist_head, mylist_entry); |
904 |
vm_xfer_page_pkt->ranges[i].byte_offset); |
946 |
|
905 |
net_vsc_pkt->tot_data_buf_len = |
947 |
/* |
|
|
948 |
* Initialize the netvsc packet |
949 |
*/ |
950 |
net_vsc_pkt->xfer_page_pkt = xfer_page_pkt; |
951 |
net_vsc_pkt->compl.rx.rx_completion_context = net_vsc_pkt; |
952 |
net_vsc_pkt->device = device; |
953 |
/* Save this so that we can send it back */ |
954 |
net_vsc_pkt->compl.rx.rx_completion_tid = |
955 |
vm_xfer_page_pkt->d.transaction_id; |
956 |
|
957 |
net_vsc_pkt->tot_data_buf_len = |
906 |
vm_xfer_page_pkt->ranges[i].byte_count; |
958 |
vm_xfer_page_pkt->ranges[i].byte_count; |
|
|
959 |
net_vsc_pkt->page_buf_count = 1; |
907 |
|
960 |
|
908 |
hv_rf_on_receive(net_dev, device, net_vsc_pkt); |
961 |
net_vsc_pkt->page_buffers[0].length = |
909 |
if (net_vsc_pkt->status != nvsp_status_success) { |
962 |
vm_xfer_page_pkt->ranges[i].byte_count; |
910 |
status = nvsp_status_failure; |
963 |
|
911 |
} |
964 |
/* The virtual address of the packet in the receive buffer */ |
|
|
965 |
start = ((unsigned long)net_dev->rx_buf + |
966 |
vm_xfer_page_pkt->ranges[i].byte_offset); |
967 |
start = ((unsigned long)start) & ~(PAGE_SIZE - 1); |
968 |
|
969 |
/* Page number of the virtual page containing packet start */ |
970 |
net_vsc_pkt->page_buffers[0].pfn = start >> PAGE_SHIFT; |
971 |
|
972 |
/* Calculate the page relative offset */ |
973 |
net_vsc_pkt->page_buffers[0].offset = |
974 |
vm_xfer_page_pkt->ranges[i].byte_offset & (PAGE_SIZE - 1); |
975 |
|
976 |
/* |
977 |
* In this implementation, we are dealing with virtual |
978 |
* addresses exclusively. Since we aren't using physical |
979 |
* addresses at all, we don't care if a packet crosses a |
980 |
* page boundary. For this reason, the original code to |
981 |
* check for and handle page crossings has been removed. |
982 |
*/ |
983 |
|
984 |
/* |
985 |
* Pass it to the upper layer. The receive completion call |
986 |
* has been moved into this function. |
987 |
*/ |
988 |
hv_rf_on_receive(device, net_vsc_pkt); |
989 |
|
990 |
/* |
991 |
* Moved completion call back here so that all received |
992 |
* messages (not just data messages) will trigger a response |
993 |
* message back to the host. |
994 |
*/ |
995 |
hv_nv_on_receive_completion(net_vsc_pkt); |
912 |
} |
996 |
} |
913 |
|
|
|
914 |
/* |
915 |
* Moved completion call back here so that all received |
916 |
* messages (not just data messages) will trigger a response |
917 |
* message back to the host. |
918 |
*/ |
919 |
hv_nv_on_receive_completion(device, vm_xfer_page_pkt->d.transaction_id, |
920 |
status); |
921 |
} |
997 |
} |
922 |
|
998 |
|
923 |
/* |
999 |
/* |
924 |
* Net VSC on receive completion |
1000 |
* Net VSC send receive completion |
925 |
* |
|
|
926 |
* Send a receive completion packet to RNDIS device (ie NetVsp) |
927 |
*/ |
1001 |
*/ |
928 |
void |
1002 |
static void |
929 |
hv_nv_on_receive_completion(struct hv_device *device, uint64_t tid, |
1003 |
hv_nv_send_receive_completion(struct hv_device *device, uint64_t tid) |
930 |
uint32_t status) |
|
|
931 |
{ |
1004 |
{ |
932 |
nvsp_msg rx_comp_msg; |
1005 |
nvsp_msg rx_comp_msg; |
933 |
int retries = 0; |
1006 |
int retries = 0; |
Lines 937-943
Link Here
|
937 |
|
1010 |
|
938 |
/* Pass in the status */ |
1011 |
/* Pass in the status */ |
939 |
rx_comp_msg.msgs.vers_1_msgs.send_rndis_pkt_complete.status = |
1012 |
rx_comp_msg.msgs.vers_1_msgs.send_rndis_pkt_complete.status = |
940 |
status; |
1013 |
nvsp_status_success; |
941 |
|
1014 |
|
942 |
retry_send_cmplt: |
1015 |
retry_send_cmplt: |
943 |
/* Send the completion */ |
1016 |
/* Send the completion */ |
Lines 958-984
Link Here
|
958 |
} |
1031 |
} |
959 |
|
1032 |
|
960 |
/* |
1033 |
/* |
|
|
1034 |
* Net VSC on receive completion |
1035 |
* |
1036 |
* Send a receive completion packet to RNDIS device (ie NetVsp) |
1037 |
*/ |
1038 |
void |
1039 |
hv_nv_on_receive_completion(void *context) |
1040 |
{ |
1041 |
netvsc_packet *packet = (netvsc_packet *)context; |
1042 |
struct hv_device *device = (struct hv_device *)packet->device; |
1043 |
netvsc_dev *net_dev; |
1044 |
uint64_t tid = 0; |
1045 |
boolean_t send_rx_completion = FALSE; |
1046 |
|
1047 |
/* |
1048 |
* Even though it seems logical to do a hv_nv_get_outbound_net_device() |
1049 |
* here to send out receive completion, we are using |
1050 |
* hv_nv_get_inbound_net_device() since we may have disabled |
1051 |
* outbound traffic already. |
1052 |
*/ |
1053 |
net_dev = hv_nv_get_inbound_net_device(device); |
1054 |
if (net_dev == NULL) |
1055 |
return; |
1056 |
|
1057 |
/* Overloading use of the lock. */ |
1058 |
mtx_lock_spin(&net_dev->rx_pkt_list_lock); |
1059 |
|
1060 |
packet->xfer_page_pkt->count--; |
1061 |
|
1062 |
/* |
1063 |
* Last one in the line that represent 1 xfer page packet. |
1064 |
* Return the xfer page packet itself to the free list. |
1065 |
*/ |
1066 |
if (packet->xfer_page_pkt->count == 0) { |
1067 |
send_rx_completion = TRUE; |
1068 |
tid = packet->compl.rx.rx_completion_tid; |
1069 |
STAILQ_INSERT_TAIL(&net_dev->myrx_packet_list, |
1070 |
(netvsc_packet *)(packet->xfer_page_pkt), mylist_entry); |
1071 |
} |
1072 |
|
1073 |
/* Put the packet back on the free list */ |
1074 |
STAILQ_INSERT_TAIL(&net_dev->myrx_packet_list, packet, mylist_entry); |
1075 |
mtx_unlock_spin(&net_dev->rx_pkt_list_lock); |
1076 |
|
1077 |
/* Send a receive completion for the xfer page packet */ |
1078 |
if (send_rx_completion) |
1079 |
hv_nv_send_receive_completion(device, tid); |
1080 |
} |
1081 |
|
1082 |
/* |
961 |
* Net VSC on channel callback |
1083 |
* Net VSC on channel callback |
962 |
*/ |
1084 |
*/ |
963 |
static void |
1085 |
static void |
964 |
hv_nv_on_channel_callback(void *context) |
1086 |
hv_nv_on_channel_callback(void *context) |
965 |
{ |
1087 |
{ |
|
|
1088 |
/* Fixme: Magic number */ |
1089 |
const int net_pkt_size = 2048; |
966 |
struct hv_device *device = (struct hv_device *)context; |
1090 |
struct hv_device *device = (struct hv_device *)context; |
967 |
netvsc_dev *net_dev; |
1091 |
netvsc_dev *net_dev; |
968 |
device_t dev = device->device; |
|
|
969 |
uint32_t bytes_rxed; |
1092 |
uint32_t bytes_rxed; |
970 |
uint64_t request_id; |
1093 |
uint64_t request_id; |
971 |
hv_vm_packet_descriptor *desc; |
1094 |
uint8_t *packet; |
|
|
1095 |
hv_vm_packet_descriptor *desc; |
972 |
uint8_t *buffer; |
1096 |
uint8_t *buffer; |
973 |
int bufferlen = NETVSC_PACKET_SIZE; |
1097 |
int bufferlen = net_pkt_size; |
974 |
int ret = 0; |
1098 |
int ret = 0; |
975 |
|
1099 |
|
|
|
1100 |
packet = malloc(net_pkt_size * sizeof(uint8_t), M_DEVBUF, M_NOWAIT); |
1101 |
if (!packet) |
1102 |
return; |
1103 |
|
1104 |
buffer = packet; |
1105 |
|
976 |
net_dev = hv_nv_get_inbound_net_device(device); |
1106 |
net_dev = hv_nv_get_inbound_net_device(device); |
977 |
if (net_dev == NULL) |
1107 |
if (net_dev == NULL) |
978 |
return; |
1108 |
goto out; |
979 |
|
1109 |
|
980 |
buffer = net_dev->callback_buf; |
|
|
981 |
|
982 |
do { |
1110 |
do { |
983 |
ret = hv_vmbus_channel_recv_packet_raw(device->channel, |
1111 |
ret = hv_vmbus_channel_recv_packet_raw(device->channel, |
984 |
buffer, bufferlen, &bytes_rxed, &request_id); |
1112 |
buffer, bufferlen, &bytes_rxed, &request_id); |
Lines 987-1001
Link Here
|
987 |
desc = (hv_vm_packet_descriptor *)buffer; |
1115 |
desc = (hv_vm_packet_descriptor *)buffer; |
988 |
switch (desc->type) { |
1116 |
switch (desc->type) { |
989 |
case HV_VMBUS_PACKET_TYPE_COMPLETION: |
1117 |
case HV_VMBUS_PACKET_TYPE_COMPLETION: |
990 |
hv_nv_on_send_completion(net_dev, device, desc); |
1118 |
hv_nv_on_send_completion(device, desc); |
991 |
break; |
1119 |
break; |
992 |
case HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES: |
1120 |
case HV_VMBUS_PACKET_TYPE_DATA_USING_TRANSFER_PAGES: |
993 |
hv_nv_on_receive(net_dev, device, desc); |
1121 |
hv_nv_on_receive(device, desc); |
994 |
break; |
1122 |
break; |
995 |
default: |
1123 |
default: |
996 |
device_printf(dev, |
|
|
997 |
"hv_cb recv unknow type %d " |
998 |
" packet\n", desc->type); |
999 |
break; |
1124 |
break; |
1000 |
} |
1125 |
} |
1001 |
} else { |
1126 |
} else { |
Lines 1003-1020
Link Here
|
1003 |
} |
1128 |
} |
1004 |
} else if (ret == ENOBUFS) { |
1129 |
} else if (ret == ENOBUFS) { |
1005 |
/* Handle large packet */ |
1130 |
/* Handle large packet */ |
1006 |
if (bufferlen > NETVSC_PACKET_SIZE) { |
1131 |
free(buffer, M_DEVBUF); |
1007 |
free(buffer, M_NETVSC); |
1132 |
buffer = malloc(bytes_rxed, M_DEVBUF, M_NOWAIT); |
1008 |
buffer = NULL; |
|
|
1009 |
} |
1010 |
|
1011 |
/* alloc new buffer */ |
1012 |
buffer = malloc(bytes_rxed, M_NETVSC, M_NOWAIT); |
1013 |
if (buffer == NULL) { |
1133 |
if (buffer == NULL) { |
1014 |
device_printf(dev, |
|
|
1015 |
"hv_cb malloc buffer failed, len=%u\n", |
1016 |
bytes_rxed); |
1017 |
bufferlen = 0; |
1018 |
break; |
1134 |
break; |
1019 |
} |
1135 |
} |
1020 |
bufferlen = bytes_rxed; |
1136 |
bufferlen = bytes_rxed; |
Lines 1021-1026
Link Here
|
1021 |
} |
1137 |
} |
1022 |
} while (1); |
1138 |
} while (1); |
1023 |
|
1139 |
|
1024 |
if (bufferlen > NETVSC_PACKET_SIZE) |
1140 |
out: |
1025 |
free(buffer, M_NETVSC); |
1141 |
free(buffer, M_DEVBUF); |
1026 |
} |
1142 |
} |
|
|
1143 |
|