storvsc: Refactor the code in storvsc_channel_init()

The function storvsc_channel_init() repeatedly interacts with the host
to extract various channel properties. Refactor this code to eliminate
code repetition.

Signed-off-by: K. Y. Srinivasan <kys@microsoft.com>
Reviewed-by: Long Li <longli@microsoft.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Tested-by: Alex Ng <alexng@microsoft.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
K. Y. Srinivasan 2015-12-23 13:15:50 -08:00 committed by Martin K. Petersen
parent dac582417b
commit 59635018f9
1 changed files with 46 additions and 80 deletions

View File

@ -723,29 +723,17 @@ static void cache_wwn(struct storvsc_device *stor_device,
}
}
static int storvsc_channel_init(struct hv_device *device, bool is_fc)
static int storvsc_execute_vstor_op(struct hv_device *device,
struct storvsc_cmd_request *request,
bool status_check)
{
struct storvsc_device *stor_device;
struct storvsc_cmd_request *request;
struct vstor_packet *vstor_packet;
int ret, t, i;
int max_chns;
bool process_sub_channels = false;
int ret, t;
stor_device = get_out_stor_device(device);
if (!stor_device)
return -ENODEV;
request = &stor_device->init_request;
vstor_packet = &request->vstor_packet;
/*
* Now, initiate the vsc/vsp initialization protocol on the open
* channel
*/
memset(request, 0, sizeof(struct storvsc_cmd_request));
init_completion(&request->wait_event);
vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
ret = vmbus_sendpacket(device->channel, vstor_packet,
@ -761,17 +749,50 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc)
if (t == 0)
return -ETIMEDOUT;
if (!status_check)
return ret;
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
vstor_packet->status != 0)
return -EINVAL;
return ret;
}
static int storvsc_channel_init(struct hv_device *device, bool is_fc)
{
struct storvsc_device *stor_device;
struct storvsc_cmd_request *request;
struct vstor_packet *vstor_packet;
int ret, i;
int max_chns;
bool process_sub_channels = false;
stor_device = get_out_stor_device(device);
if (!stor_device)
return -ENODEV;
request = &stor_device->init_request;
vstor_packet = &request->vstor_packet;
/*
* Now, initiate the vsc/vsp initialization protocol on the open
* channel
*/
memset(request, 0, sizeof(struct storvsc_cmd_request));
vstor_packet->operation = VSTOR_OPERATION_BEGIN_INITIALIZATION;
ret = storvsc_execute_vstor_op(device, request, true);
if (ret)
return ret;
/*
* Query host supported protocol version.
*/
for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) {
/* reuse the packet for version range supported */
memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->operation =
VSTOR_OPERATION_QUERY_PROTOCOL_VERSION;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
vstor_packet->version.major_minor =
vmstor_protocols[i].protocol_version;
@ -780,20 +801,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc)
* The revision number is only used in Windows; set it to 0.
*/
vstor_packet->version.revision = 0;
ret = vmbus_sendpacket(device->channel, vstor_packet,
(sizeof(struct vstor_packet) -
vmscsi_size_delta),
(unsigned long)request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
ret = storvsc_execute_vstor_op(device, request, false);
if (ret != 0)
return ret;
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0)
return -ETIMEDOUT;
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO)
return -EINVAL;
@ -817,26 +828,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc)
memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->operation = VSTOR_OPERATION_QUERY_PROPERTIES;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
ret = vmbus_sendpacket(device->channel, vstor_packet,
(sizeof(struct vstor_packet) -
vmscsi_size_delta),
(unsigned long)request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
ret = storvsc_execute_vstor_op(device, request, true);
if (ret != 0)
return ret;
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0)
return -ETIMEDOUT;
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
vstor_packet->status != 0)
return -EINVAL;
/*
* Check to see if multi-channel support is there.
* Hosts that implement protocol version of 5.1 and above
@ -854,28 +849,15 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc)
if (!is_fc)
goto done;
/*
* For FC devices retrieve FC HBA data.
*/
memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->operation = VSTOR_OPERATION_FCHBA_DATA;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
ret = vmbus_sendpacket(device->channel, vstor_packet,
(sizeof(struct vstor_packet) -
vmscsi_size_delta),
(unsigned long)request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
ret = storvsc_execute_vstor_op(device, request, true);
if (ret != 0)
return ret;
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0)
return -ETIMEDOUT;
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
vstor_packet->status != 0)
return -EINVAL;
/*
* Cache the currently active port and node ww names.
*/
@ -885,26 +867,10 @@ done:
memset(vstor_packet, 0, sizeof(struct vstor_packet));
vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
ret = vmbus_sendpacket(device->channel, vstor_packet,
(sizeof(struct vstor_packet) -
vmscsi_size_delta),
(unsigned long)request,
VM_PKT_DATA_INBAND,
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
ret = storvsc_execute_vstor_op(device, request, true);
if (ret != 0)
return ret;
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
if (t == 0)
return -ETIMEDOUT;
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
vstor_packet->status != 0)
return -EINVAL;
if (process_sub_channels)
handle_multichannel_storage(device, max_chns);