hyperv: Use WAITOK in the places where we can wait

And convert rndis non-hot path spinlock to mutex.

Submitted by:	Jun Su <junsu microsoft com>
Reviewed by:	adrian, sephe
Approved by:	adrian (mentor)
MFC after:	1 week
Sponsored by:	Microsoft OSTC
Differential Revision:	https://reviews.freebsd.org/D5081
This commit is contained in:
Sepherosa Ziehau 2016-02-05 07:20:31 +00:00
parent f11ef33f0d
commit 27cc90ebb1
5 changed files with 22 additions and 83 deletions

View File

@ -74,10 +74,7 @@ hv_nv_alloc_net_device(struct hv_device *device)
netvsc_dev *net_dev; netvsc_dev *net_dev;
hn_softc_t *sc = device_get_softc(device->device); hn_softc_t *sc = device_get_softc(device->device);
net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_NOWAIT | M_ZERO); net_dev = malloc(sizeof(netvsc_dev), M_NETVSC, M_WAITOK | M_ZERO);
if (net_dev == NULL) {
return (NULL);
}
net_dev->dev = device; net_dev->dev = device;
net_dev->destroy = FALSE; net_dev->destroy = FALSE;
@ -224,11 +221,7 @@ hv_nv_init_rx_buffer_with_net_vsp(struct hv_device *device)
init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections; init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.num_sections;
net_dev->rx_sections = malloc(net_dev->rx_section_count * net_dev->rx_sections = malloc(net_dev->rx_section_count *
sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_NOWAIT); sizeof(nvsp_1_rx_buf_section), M_NETVSC, M_WAITOK);
if (net_dev->rx_sections == NULL) {
ret = EINVAL;
goto cleanup;
}
memcpy(net_dev->rx_sections, memcpy(net_dev->rx_sections,
init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections, init_pkt->msgs.vers_1_msgs.send_rx_buf_complete.sections,
net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section)); net_dev->rx_section_count * sizeof(nvsp_1_rx_buf_section));
@ -326,11 +319,7 @@ hv_nv_init_send_buffer_with_net_vsp(struct hv_device *device)
BITS_PER_LONG); BITS_PER_LONG);
net_dev->send_section_bitsmap = net_dev->send_section_bitsmap =
malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC, malloc(net_dev->bitsmap_words * sizeof(long), M_NETVSC,
M_NOWAIT | M_ZERO); M_WAITOK | M_ZERO);
if (NULL == net_dev->send_section_bitsmap) {
ret = ENOMEM;
goto cleanup;
}
goto exit; goto exit;

View File

@ -135,12 +135,9 @@ hv_get_rndis_device(void)
{ {
rndis_device *device; rndis_device *device;
device = malloc(sizeof(rndis_device), M_NETVSC, M_NOWAIT | M_ZERO); device = malloc(sizeof(rndis_device), M_NETVSC, M_WAITOK | M_ZERO);
if (device == NULL) {
return (NULL);
}
mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_SPIN | MTX_RECURSE); mtx_init(&device->req_lock, "HV-FRL", NULL, MTX_DEF);
/* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */ /* Same effect as STAILQ_HEAD_INITIALIZER() static initializer */
STAILQ_INIT(&device->myrequest_list); STAILQ_INIT(&device->myrequest_list);
@ -171,10 +168,7 @@ hv_rndis_request(rndis_device *device, uint32_t message_type,
rndis_msg *rndis_mesg; rndis_msg *rndis_mesg;
rndis_set_request *set; rndis_set_request *set;
request = malloc(sizeof(rndis_request), M_NETVSC, M_NOWAIT | M_ZERO); request = malloc(sizeof(rndis_request), M_NETVSC, M_WAITOK | M_ZERO);
if (request == NULL) {
return (NULL);
}
sema_init(&request->wait_sema, 0, "rndis sema"); sema_init(&request->wait_sema, 0, "rndis sema");
@ -193,9 +187,9 @@ hv_rndis_request(rndis_device *device, uint32_t message_type,
set->request_id += 1; set->request_id += 1;
/* Add to the request list */ /* Add to the request list */
mtx_lock_spin(&device->req_lock); mtx_lock(&device->req_lock);
STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry); STAILQ_INSERT_TAIL(&device->myrequest_list, request, mylist_entry);
mtx_unlock_spin(&device->req_lock); mtx_unlock(&device->req_lock);
return (request); return (request);
} }
@ -206,14 +200,14 @@ hv_rndis_request(rndis_device *device, uint32_t message_type,
static inline void static inline void
hv_put_rndis_request(rndis_device *device, rndis_request *request) hv_put_rndis_request(rndis_device *device, rndis_request *request)
{ {
mtx_lock_spin(&device->req_lock); mtx_lock(&device->req_lock);
/* Fixme: Has O(n) performance */ /* Fixme: Has O(n) performance */
/* /*
* XXXKYS: Use Doubly linked lists. * XXXKYS: Use Doubly linked lists.
*/ */
STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_, STAILQ_REMOVE(&device->myrequest_list, request, rndis_request_,
mylist_entry); mylist_entry);
mtx_unlock_spin(&device->req_lock); mtx_unlock(&device->req_lock);
sema_destroy(&request->wait_sema); sema_destroy(&request->wait_sema);
free(request, M_NETVSC); free(request, M_NETVSC);
@ -270,7 +264,7 @@ hv_rf_receive_response(rndis_device *device, rndis_msg *response)
rndis_request *next_request; rndis_request *next_request;
boolean_t found = FALSE; boolean_t found = FALSE;
mtx_lock_spin(&device->req_lock); mtx_lock(&device->req_lock);
request = STAILQ_FIRST(&device->myrequest_list); request = STAILQ_FIRST(&device->myrequest_list);
while (request != NULL) { while (request != NULL) {
/* /*
@ -285,7 +279,7 @@ hv_rf_receive_response(rndis_device *device, rndis_msg *response)
next_request = STAILQ_NEXT(request, mylist_entry); next_request = STAILQ_NEXT(request, mylist_entry);
request = next_request; request = next_request;
} }
mtx_unlock_spin(&device->req_lock); mtx_unlock(&device->req_lock);
if (found) { if (found) {
if (response->msg_len <= sizeof(rndis_msg)) { if (response->msg_len <= sizeof(rndis_msg)) {

View File

@ -88,8 +88,7 @@ hv_vmbus_negotiate_version(hv_vmbus_channel_msg_info *msg_info,
msg->monitor_page_1 = hv_get_phys_addr( msg->monitor_page_1 = hv_get_phys_addr(
hv_vmbus_g_connection.monitor_pages); hv_vmbus_g_connection.monitor_pages);
msg->monitor_page_2 = msg->monitor_page_2 = hv_get_phys_addr(
hv_get_phys_addr(
((uint8_t *) hv_vmbus_g_connection.monitor_pages ((uint8_t *) hv_vmbus_g_connection.monitor_pages
+ PAGE_SIZE)); + PAGE_SIZE));
@ -179,16 +178,9 @@ hv_vmbus_connect(void) {
*/ */
hv_vmbus_g_connection.interrupt_page = contigmalloc( hv_vmbus_g_connection.interrupt_page = contigmalloc(
PAGE_SIZE, M_DEVBUF, PAGE_SIZE, M_DEVBUF,
M_NOWAIT | M_ZERO, 0UL, M_WAITOK | M_ZERO, 0UL,
BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
PAGE_SIZE, 0); PAGE_SIZE, 0);
KASSERT(hv_vmbus_g_connection.interrupt_page != NULL,
("Error VMBUS: malloc failed to allocate Channel"
" Request Event message!"));
if (hv_vmbus_g_connection.interrupt_page == NULL) {
ret = ENOMEM;
goto cleanup;
}
hv_vmbus_g_connection.recv_interrupt_page = hv_vmbus_g_connection.recv_interrupt_page =
hv_vmbus_g_connection.interrupt_page; hv_vmbus_g_connection.interrupt_page;
@ -204,28 +196,16 @@ hv_vmbus_connect(void) {
hv_vmbus_g_connection.monitor_pages = contigmalloc( hv_vmbus_g_connection.monitor_pages = contigmalloc(
2 * PAGE_SIZE, 2 * PAGE_SIZE,
M_DEVBUF, M_DEVBUF,
M_NOWAIT | M_ZERO, M_WAITOK | M_ZERO,
0UL, 0UL,
BUS_SPACE_MAXADDR, BUS_SPACE_MAXADDR,
PAGE_SIZE, PAGE_SIZE,
0); 0);
KASSERT(hv_vmbus_g_connection.monitor_pages != NULL,
("Error VMBUS: malloc failed to allocate Monitor Pages!"));
if (hv_vmbus_g_connection.monitor_pages == NULL) {
ret = ENOMEM;
goto cleanup;
}
msg_info = (hv_vmbus_channel_msg_info*) msg_info = (hv_vmbus_channel_msg_info*)
malloc(sizeof(hv_vmbus_channel_msg_info) + malloc(sizeof(hv_vmbus_channel_msg_info) +
sizeof(hv_vmbus_channel_initiate_contact), sizeof(hv_vmbus_channel_initiate_contact),
M_DEVBUF, M_NOWAIT | M_ZERO); M_DEVBUF, M_WAITOK | M_ZERO);
KASSERT(msg_info != NULL,
("Error VMBUS: malloc failed for Initiate Contact message!"));
if (msg_info == NULL) {
ret = ENOMEM;
goto cleanup;
}
hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) * hv_vmbus_g_connection.channels = malloc(sizeof(hv_vmbus_channel*) *
HV_CHANNEL_MAX_COUNT, HV_CHANNEL_MAX_COUNT,
@ -301,19 +281,11 @@ hv_vmbus_connect(void) {
int int
hv_vmbus_disconnect(void) { hv_vmbus_disconnect(void) {
int ret = 0; int ret = 0;
hv_vmbus_channel_unload* msg; hv_vmbus_channel_unload msg;
msg = malloc(sizeof(hv_vmbus_channel_unload), msg.message_type = HV_CHANNEL_MESSAGE_UNLOAD;
M_DEVBUF, M_NOWAIT | M_ZERO);
KASSERT(msg != NULL,
("Error VMBUS: malloc failed to allocate Channel Unload Msg!"));
if (msg == NULL)
return (ENOMEM);
msg->message_type = HV_CHANNEL_MESSAGE_UNLOAD;
ret = hv_vmbus_post_message(msg, sizeof(hv_vmbus_channel_unload));
ret = hv_vmbus_post_message(&msg, sizeof(hv_vmbus_channel_unload));
contigfree(hv_vmbus_g_connection.interrupt_page, PAGE_SIZE, M_DEVBUF); contigfree(hv_vmbus_g_connection.interrupt_page, PAGE_SIZE, M_DEVBUF);
@ -322,8 +294,6 @@ hv_vmbus_disconnect(void) {
free(hv_vmbus_g_connection.channels, M_DEVBUF); free(hv_vmbus_g_connection.channels, M_DEVBUF);
hv_vmbus_g_connection.connect_state = HV_DISCONNECTED; hv_vmbus_g_connection.connect_state = HV_DISCONNECTED;
free(msg, M_DEVBUF);
return (ret); return (ret);
} }

View File

@ -189,11 +189,7 @@ hv_vmbus_init(void)
* See if the hypercall page is already set * See if the hypercall page is already set
*/ */
hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL); hypercall_msr.as_uint64_t = rdmsr(HV_X64_MSR_HYPERCALL);
virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); virt_addr = malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
KASSERT(virt_addr != NULL,
("Error VMBUS: malloc failed to allocate page during init!"));
if (virt_addr == NULL)
goto cleanup;
hypercall_msr.u.enable = 1; hypercall_msr.u.enable = 1;
hypercall_msr.u.guest_physical_address = hypercall_msr.u.guest_physical_address =

View File

@ -291,12 +291,7 @@ hv_vmbus_child_device_create(
* Allocate the new child device * Allocate the new child device
*/ */
child_dev = malloc(sizeof(hv_device), M_DEVBUF, child_dev = malloc(sizeof(hv_device), M_DEVBUF,
M_NOWAIT | M_ZERO); M_WAITOK | M_ZERO);
KASSERT(child_dev != NULL,
("Error VMBUS: malloc failed to allocate hv_device!"));
if (child_dev == NULL)
return (NULL);
child_dev->channel = channel; child_dev->channel = channel;
memcpy(&child_dev->class_id, &type, sizeof(hv_guid)); memcpy(&child_dev->class_id, &type, sizeof(hv_guid));
@ -548,12 +543,7 @@ vmbus_bus_init(void)
*/ */
for(i = 0; i < 2; i++) { for(i = 0; i < 2; i++) {
setup_args.page_buffers[2 * j + i] = setup_args.page_buffers[2 * j + i] =
malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT | M_ZERO); malloc(PAGE_SIZE, M_DEVBUF, M_WAITOK | M_ZERO);
if (setup_args.page_buffers[2 * j + i] == NULL) {
KASSERT(setup_args.page_buffers[2 * j + i] != NULL,
("Error VMBUS: malloc failed!"));
goto cleanup1;
}
} }
} }