Changeset View
Standalone View
sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
Show First 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | struct hv_storvsc_request { | ||||
struct vstor_packet vstor_packet; | struct vstor_packet vstor_packet; | ||||
hv_vmbus_multipage_buffer data_buf; | hv_vmbus_multipage_buffer data_buf; | ||||
void *sense_data; | void *sense_data; | ||||
uint8_t sense_info_len; | uint8_t sense_info_len; | ||||
uint8_t retries; | uint8_t retries; | ||||
union ccb *ccb; | union ccb *ccb; | ||||
struct storvsc_softc *softc; | struct storvsc_softc *softc; | ||||
struct callout callout; | struct callout callout; | ||||
struct sema synch_sema; /*Synchronize the request/response if needed */ | |||||
struct sglist *bounce_sgl; | struct sglist *bounce_sgl; | ||||
unsigned int bounce_sgl_count; | unsigned int bounce_sgl_count; | ||||
uint64_t not_aligned_seg_bits; | uint64_t not_aligned_seg_bits; | ||||
}; | }; | ||||
struct storvsc_softc { | struct storvsc_softc { | ||||
struct hv_device *hs_dev; | struct hv_device *hs_dev; | ||||
LIST_HEAD(, hv_storvsc_request) hs_free_list; | LIST_HEAD(, hv_storvsc_request) hs_free_list; | ||||
▲ Show 20 Lines • Show All 248 Lines • ▼ Show 20 Lines | storvsc_send_multichannel_request(struct hv_device *dev, int max_chans) | ||||
request = &sc->hs_init_req; | request = &sc->hs_init_req; | ||||
/* Establish a handler for multi-channel */ | /* Establish a handler for multi-channel */ | ||||
dev->channel->sc_creation_callback = storvsc_handle_sc_creation; | dev->channel->sc_creation_callback = storvsc_handle_sc_creation; | ||||
/* request the host to create multi-channel */ | /* request the host to create multi-channel */ | ||||
memset(request, 0, sizeof(struct hv_storvsc_request)); | memset(request, 0, sizeof(struct hv_storvsc_request)); | ||||
sema_init(&request->synch_sema, 0, ("stor_synch_sema")); | |||||
vstor_packet = &request->vstor_packet; | vstor_packet = &request->vstor_packet; | ||||
vstor_packet->operation = VSTOR_OPERATION_CREATE_MULTI_CHANNELS; | vstor_packet->operation = VSTOR_OPERATION_CREATE_MULTI_CHANNELS; | ||||
vstor_packet->flags = REQUEST_COMPLETION_FLAG; | vstor_packet->flags = REQUEST_COMPLETION_FLAG; | ||||
vstor_packet->u.multi_channels_cnt = request_channels_cnt; | vstor_packet->u.multi_channels_cnt = request_channels_cnt; | ||||
ret = hv_vmbus_channel_send_packet( | ret = hv_vmbus_channel_send_packet( | ||||
dev->channel, | dev->channel, | ||||
vstor_packet, | vstor_packet, | ||||
VSTOR_PKT_SIZE, | VSTOR_PKT_SIZE, | ||||
(uint64_t)(uintptr_t)request, | (uint64_t)(uintptr_t)request, | ||||
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | ||||
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||||
/* wait for 5 seconds */ | /* wait for 5 seconds */ | ||||
ret = sema_timedwait(&request->synch_sema, 5 * hz); | ret = msleep(request, &sc->hs_lock, PRIBIO, "CINIT", 5 * hz); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
printf("Storvsc_error: create multi-channel timeout, %d\n", | printf("Storvsc_error: create multi-channel timeout, %d\n", | ||||
ret); | ret); | ||||
return; | return; | ||||
} | } | ||||
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | ||||
vstor_packet->status != 0) { | vstor_packet->status != 0) { | ||||
printf("Storvsc_error: create multi-channel invalid operation " | printf("Storvsc_error: create multi-channel invalid operation " | ||||
Show All 31 Lines | hv_storvsc_channel_init(struct hv_device *dev) | ||||
if (sc == NULL) | if (sc == NULL) | ||||
return (ENODEV); | return (ENODEV); | ||||
request = &sc->hs_init_req; | request = &sc->hs_init_req; | ||||
memset(request, 0, sizeof(struct hv_storvsc_request)); | memset(request, 0, sizeof(struct hv_storvsc_request)); | ||||
vstor_packet = &request->vstor_packet; | vstor_packet = &request->vstor_packet; | ||||
request->softc = sc; | request->softc = sc; | ||||
/** | |||||
* Initiate the vsc/vsp initialization protocol on the open channel | |||||
*/ | |||||
sema_init(&request->synch_sema, 0, ("stor_synch_sema")); | |||||
vstor_packet->operation = VSTOR_OPERATION_BEGININITIALIZATION; | vstor_packet->operation = VSTOR_OPERATION_BEGININITIALIZATION; | ||||
vstor_packet->flags = REQUEST_COMPLETION_FLAG; | vstor_packet->flags = REQUEST_COMPLETION_FLAG; | ||||
ret = hv_vmbus_channel_send_packet( | ret = hv_vmbus_channel_send_packet( | ||||
dev->channel, | dev->channel, | ||||
vstor_packet, | vstor_packet, | ||||
VSTOR_PKT_SIZE, | VSTOR_PKT_SIZE, | ||||
(uint64_t)(uintptr_t)request, | (uint64_t)(uintptr_t)request, | ||||
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | ||||
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||||
if (ret != 0) | if (ret != 0) | ||||
goto cleanup; | goto cleanup; | ||||
/* wait 5 seconds */ | /* wait 5 seconds */ | ||||
ret = sema_timedwait(&request->synch_sema, 5 * hz); | ret = msleep(request, &sc->hs_lock, PRIBIO, "CINIT", 5 * hz); | ||||
if (ret != 0) | if (ret != 0) | ||||
goto cleanup; | goto cleanup; | ||||
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | ||||
vstor_packet->status != 0) { | vstor_packet->status != 0) { | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
Show All 16 Lines | ret = hv_vmbus_channel_send_packet( | ||||
(uint64_t)(uintptr_t)request, | (uint64_t)(uintptr_t)request, | ||||
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | ||||
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||||
if (ret != 0) | if (ret != 0) | ||||
goto cleanup; | goto cleanup; | ||||
/* wait 5 seconds */ | /* wait 5 seconds */ | ||||
ret = sema_timedwait(&request->synch_sema, 5 * hz); | ret = msleep(request, &sc->hs_lock, PRIBIO, "CINIT", 5 * hz); | ||||
if (ret) | if (ret) | ||||
goto cleanup; | goto cleanup; | ||||
/* TODO: Check returned version */ | /* TODO: Check returned version */ | ||||
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | ||||
vstor_packet->status != 0) | vstor_packet->status != 0) | ||||
goto cleanup; | goto cleanup; | ||||
Show All 12 Lines | ret = hv_vmbus_channel_send_packet( | ||||
(uint64_t)(uintptr_t)request, | (uint64_t)(uintptr_t)request, | ||||
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | ||||
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||||
if ( ret != 0) | if ( ret != 0) | ||||
goto cleanup; | goto cleanup; | ||||
/* wait 5 seconds */ | /* wait 5 seconds */ | ||||
ret = sema_timedwait(&request->synch_sema, 5 * hz); | ret = msleep(request, &sc->hs_lock, PRIBIO, "CINIT", 5 * hz); | ||||
if (ret != 0) | if (ret != 0) | ||||
goto cleanup; | goto cleanup; | ||||
/* TODO: Check returned version */ | /* TODO: Check returned version */ | ||||
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | ||||
vstor_packet->status != 0) { | vstor_packet->status != 0) { | ||||
goto cleanup; | goto cleanup; | ||||
Show All 20 Lines | ret = hv_vmbus_channel_send_packet( | ||||
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | ||||
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
/* wait 5 seconds */ | /* wait 5 seconds */ | ||||
ret = sema_timedwait(&request->synch_sema, 5 * hz); | ret = msleep(request, &sc->hs_lock, PRIBIO, "CINIT", 5 * hz); | ||||
if (ret != 0) | if (ret != 0) | ||||
goto cleanup; | goto cleanup; | ||||
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | if (vstor_packet->operation != VSTOR_OPERATION_COMPLETEIO || | ||||
vstor_packet->status != 0) | vstor_packet->status != 0) | ||||
goto cleanup; | goto cleanup; | ||||
/* | /* | ||||
* If multi-channel is supported, send multichannel create | * If multi-channel is supported, send multichannel create | ||||
* request to host. | * request to host. | ||||
*/ | */ | ||||
if (support_multichannel) | if (support_multichannel) | ||||
storvsc_send_multichannel_request(dev, max_chans); | storvsc_send_multichannel_request(dev, max_chans); | ||||
cleanup: | cleanup: | ||||
sema_destroy(&request->synch_sema); | |||||
return (ret); | return (ret); | ||||
} | } | ||||
/** | /** | ||||
* @brief Open channel connection to paraent partition StorVSP driver | * @brief Open channel connection to paraent partition StorVSP driver | ||||
* | * | ||||
* Open and initialize channel connection to parent partition StorVSP driver. | * Open and initialize channel connection to parent partition StorVSP driver. | ||||
* | * | ||||
Show All 23 Lines | ret = hv_vmbus_channel_open( | ||||
sizeof(struct vmstor_chan_props), | sizeof(struct vmstor_chan_props), | ||||
hv_storvsc_on_channel_callback, | hv_storvsc_on_channel_callback, | ||||
dev->channel); | dev->channel); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
return ret; | return ret; | ||||
} | } | ||||
mtx_lock(&sc->hs_lock); | |||||
honzhan_microsoft.com: Which resource need to be protected by this lock? | |||||
decui_microsoft.comUnsubmitted Not Done Inline ActionsIt's to make the msleep() usages work. decui_microsoft.com: It's to make the msleep() usages work.
msleep(xxx, &sc->hslock, xxx,...) assumes the lock has… | |||||
decui_microsoft.comUnsubmitted Not Done Inline Actionstypo.. "required" -> "acquired". decui_microsoft.com: typo.. "required" -> "acquired". | |||||
howard0su_gmail.comAuthorUnsubmitted Not Done Inline ActionsYes. This is due to avoid race condition between sleep and wakeup. In our case, it is not possible but WITNESS requires it anyhow. howard0su_gmail.com: Yes. This is due to avoid race condition between sleep and wakeup. In our case, it is not… | |||||
ret = hv_storvsc_channel_init(dev); | ret = hv_storvsc_channel_init(dev); | ||||
mtx_unlock(&sc->hs_lock); | |||||
return (ret); | return (ret); | ||||
} | } | ||||
#if HVS_HOST_RESET | #if HVS_HOST_RESET | ||||
static int | static int | ||||
hv_storvsc_host_reset(struct hv_device *dev) | hv_storvsc_host_reset(struct hv_device *dev) | ||||
{ | { | ||||
int ret = 0; | int ret = 0; | ||||
struct storvsc_softc *sc; | struct storvsc_softc *sc; | ||||
struct hv_storvsc_request *request; | struct hv_storvsc_request *request; | ||||
struct vstor_packet *vstor_packet; | struct vstor_packet *vstor_packet; | ||||
sc = get_stor_device(dev, TRUE); | sc = get_stor_device(dev, TRUE); | ||||
if (sc == NULL) { | if (sc == NULL) { | ||||
return ENODEV; | return ENODEV; | ||||
} | } | ||||
request = &sc->hs_reset_req; | request = &sc->hs_reset_req; | ||||
request->softc = sc; | request->softc = sc; | ||||
vstor_packet = &request->vstor_packet; | vstor_packet = &request->vstor_packet; | ||||
sema_init(&request->synch_sema, 0, "stor synch sema"); | |||||
vstor_packet->operation = VSTOR_OPERATION_RESETBUS; | vstor_packet->operation = VSTOR_OPERATION_RESETBUS; | ||||
vstor_packet->flags = REQUEST_COMPLETION_FLAG; | vstor_packet->flags = REQUEST_COMPLETION_FLAG; | ||||
ret = hv_vmbus_channel_send_packet(dev->channel, | ret = hv_vmbus_channel_send_packet(dev->channel, | ||||
vstor_packet, | vstor_packet, | ||||
VSTOR_PKT_SIZE, | VSTOR_PKT_SIZE, | ||||
(uint64_t)(uintptr_t)&sc->hs_reset_req, | (uint64_t)(uintptr_t)&sc->hs_reset_req, | ||||
HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | HV_VMBUS_PACKET_TYPE_DATA_IN_BAND, | ||||
HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | HV_VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | ||||
if (ret != 0) { | if (ret != 0) { | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
ret = sema_timedwait(&request->synch_sema, 5 * hz); /* KYS 5 seconds */ | ret = msleep(request, &sc->hs_lock, PRIBIO, "CINIT", 5 * hz); | ||||
if (ret) { | if (ret) { | ||||
goto cleanup; | goto cleanup; | ||||
} | } | ||||
/* | /* | ||||
* At this point, all outstanding requests in the adapter | * At this point, all outstanding requests in the adapter | ||||
* should have been flushed out and return to us | * should have been flushed out and return to us | ||||
*/ | */ | ||||
cleanup: | cleanup: | ||||
sema_destroy(&request->synch_sema); | |||||
return (ret); | return (ret); | ||||
} | } | ||||
#endif /* HVS_HOST_RESET */ | #endif /* HVS_HOST_RESET */ | ||||
/** | /** | ||||
* @brief Function to initiate an I/O request | * @brief Function to initiate an I/O request | ||||
* | * | ||||
* @param device Hyper-V device pointer | * @param device Hyper-V device pointer | ||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | hv_storvsc_on_channel_callback(void *context) | ||||
while ((ret == 0) && (bytes_recvd > 0)) { | while ((ret == 0) && (bytes_recvd > 0)) { | ||||
request = (struct hv_storvsc_request *)(uintptr_t)request_id; | request = (struct hv_storvsc_request *)(uintptr_t)request_id; | ||||
if ((request == &sc->hs_init_req) || | if ((request == &sc->hs_init_req) || | ||||
(request == &sc->hs_reset_req)) { | (request == &sc->hs_reset_req)) { | ||||
memcpy(&request->vstor_packet, packet, | memcpy(&request->vstor_packet, packet, | ||||
sizeof(struct vstor_packet)); | sizeof(struct vstor_packet)); | ||||
sema_post(&request->synch_sema); | wakeup(request); | ||||
} else { | } else { | ||||
vstor_packet = (struct vstor_packet *)packet; | vstor_packet = (struct vstor_packet *)packet; | ||||
switch(vstor_packet->operation) { | switch(vstor_packet->operation) { | ||||
case VSTOR_OPERATION_COMPLETEIO: | case VSTOR_OPERATION_COMPLETEIO: | ||||
if (request == NULL) | if (request == NULL) | ||||
panic("VMBUS: storvsc received a " | panic("VMBUS: storvsc received a " | ||||
"packet with NULL request id in " | "packet with NULL request id in " | ||||
"COMPLETEIO operation."); | "COMPLETEIO operation."); | ||||
▲ Show 20 Lines • Show All 126 Lines • ▼ Show 20 Lines | storvsc_attach(device_t dev) | ||||
sc->hs_dev = hv_dev; | sc->hs_dev = hv_dev; | ||||
device_set_desc(dev, g_drv_props_table[stor_type].drv_desc); | device_set_desc(dev, g_drv_props_table[stor_type].drv_desc); | ||||
LIST_INIT(&sc->hs_free_list); | LIST_INIT(&sc->hs_free_list); | ||||
mtx_init(&sc->hs_lock, "hvslck", NULL, MTX_DEF); | mtx_init(&sc->hs_lock, "hvslck", NULL, MTX_DEF); | ||||
for (i = 0; i < sc->hs_drv_props->drv_max_ios_per_target; ++i) { | for (i = 0; i < sc->hs_drv_props->drv_max_ios_per_target; ++i) { | ||||
reqp = malloc(sizeof(struct hv_storvsc_request), | reqp = malloc(sizeof(struct hv_storvsc_request), | ||||
M_DEVBUF, M_WAITOK|M_ZERO); | M_DEVBUF, M_WAITOK); | ||||
decui_microsoft.comUnsubmitted Not Done Inline ActionsI assume you've checked it's OK to remove the M_ZERO. However, I found the "retries" field of hv_storvsc_request may be used before proper initialization: grep 'retries = ' dev/hyperv/storvsc/ -nrdev/hyperv/storvsc/hv_storvsc_drv_freebsd.c:2027: reqp->retries = 0; We can see it's only initialized once in storvsc_io_done(), but in this function, it's also tested before the initialization. decui_microsoft.com: I assume you've checked it's OK to remove the M_ZERO.
However, I found the "retries" field of… | |||||
howard0su_gmail.comAuthorUnsubmitted Not Done Inline ActionsThis is actual a pre-allocate buf pool. every time, grab one from the pool, we will call bzero to initialize it. so it is not needed to zero it here. howard0su_gmail.com: This is actual a pre-allocate buf pool. every time, grab one from the pool, we will call bzero… | |||||
decui_microsoft.comUnsubmitted Not Done Inline ActionsGot it -- I saw that in storvsc_action()'s case XPT_SCSI_IO. decui_microsoft.com: Got it -- I saw that in storvsc_action()'s case XPT_SCSI_IO. | |||||
reqp->softc = sc; | |||||
decui_microsoft.comUnsubmitted Not Done Inline ActionsWhy is it removed? reqp->softc is used in several places. decui_microsoft.com: Why is it removed? reqp->softc is used in several places. | |||||
howard0su_gmail.comAuthorUnsubmitted Not Done Inline Actionsit will bzero when grab it from the pool. and set softc again. howard0su_gmail.com: it will bzero when grab it from the pool. and set softc again. | |||||
decui_microsoft.comUnsubmitted Not Done Inline ActionsGot it. decui_microsoft.com: Got it. | |||||
LIST_INSERT_HEAD(&sc->hs_free_list, reqp, link); | LIST_INSERT_HEAD(&sc->hs_free_list, reqp, link); | ||||
} | } | ||||
/* create sg-list page pool */ | /* create sg-list page pool */ | ||||
if (FALSE == g_hv_sgl_page_pool.is_init) { | if (FALSE == g_hv_sgl_page_pool.is_init) { | ||||
g_hv_sgl_page_pool.is_init = TRUE; | g_hv_sgl_page_pool.is_init = TRUE; | ||||
LIST_INIT(&g_hv_sgl_page_pool.in_use_sgl_list); | LIST_INIT(&g_hv_sgl_page_pool.in_use_sgl_list); | ||||
▲ Show 20 Lines • Show All 1,122 Lines • Show Last 20 Lines |
Which resource need to be protected by this lock?