Skip to content

Commit dac5824

Browse files
kattisrinivasanmartinkpetersen
authored andcommitted
storvsc: Properly support Fibre Channel devices
For FC devices managed by this driver, atttach the appropriate transport template. This will allow us to create the appropriate sysfs files for these devices. With this we can publish the wwn for both the port and the node. Signed-off-by: K. Y. Srinivasan <kys@microsoft.com> Reviewed-by: Long Li <longli@microsoft.com> Tested-by: Alex Ng <alexng@microsoft.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 83d1e8b commit dac5824

File tree

1 file changed

+134
-47
lines changed

1 file changed

+134
-47
lines changed

drivers/scsi/storvsc_drv.c

Lines changed: 134 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <scsi/scsi_eh.h>
4242
#include <scsi/scsi_devinfo.h>
4343
#include <scsi/scsi_dbg.h>
44+
#include <scsi/scsi_transport_fc.h>
4445

4546
/*
4647
* All wire protocol details (storage protocol between the guest and the host)
@@ -397,6 +398,9 @@ static int storvsc_timeout = 180;
397398

398399
static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
399400

401+
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
402+
static struct scsi_transport_template *fc_transport_template;
403+
#endif
400404

401405
static void storvsc_on_channel_callback(void *context);
402406

@@ -456,6 +460,11 @@ struct storvsc_device {
456460
/* Used for vsc/vsp channel reset process */
457461
struct storvsc_cmd_request init_request;
458462
struct storvsc_cmd_request reset_request;
463+
/*
464+
* Currently active port and node names for FC devices.
465+
*/
466+
u64 node_name;
467+
u64 port_name;
459468
};
460469

461470
struct hv_host_device {
@@ -695,7 +704,26 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns)
695704
vmbus_are_subchannels_present(device->channel);
696705
}
697706

698-
static int storvsc_channel_init(struct hv_device *device)
707+
static void cache_wwn(struct storvsc_device *stor_device,
708+
struct vstor_packet *vstor_packet)
709+
{
710+
/*
711+
* Cache the currently active port and node ww names.
712+
*/
713+
if (vstor_packet->wwn_packet.primary_active) {
714+
stor_device->node_name =
715+
wwn_to_u64(vstor_packet->wwn_packet.primary_node_wwn);
716+
stor_device->port_name =
717+
wwn_to_u64(vstor_packet->wwn_packet.primary_port_wwn);
718+
} else {
719+
stor_device->node_name =
720+
wwn_to_u64(vstor_packet->wwn_packet.secondary_node_wwn);
721+
stor_device->port_name =
722+
wwn_to_u64(vstor_packet->wwn_packet.secondary_port_wwn);
723+
}
724+
}
725+
726+
static int storvsc_channel_init(struct hv_device *device, bool is_fc)
699727
{
700728
struct storvsc_device *stor_device;
701729
struct storvsc_cmd_request *request;
@@ -727,19 +755,15 @@ static int storvsc_channel_init(struct hv_device *device)
727755
VM_PKT_DATA_INBAND,
728756
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
729757
if (ret != 0)
730-
goto cleanup;
758+
return ret;
731759

732760
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
733-
if (t == 0) {
734-
ret = -ETIMEDOUT;
735-
goto cleanup;
736-
}
761+
if (t == 0)
762+
return -ETIMEDOUT;
737763

738764
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
739-
vstor_packet->status != 0) {
740-
ret = -EINVAL;
741-
goto cleanup;
742-
}
765+
vstor_packet->status != 0)
766+
return -EINVAL;
743767

744768

745769
for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) {
@@ -764,18 +788,14 @@ static int storvsc_channel_init(struct hv_device *device)
764788
VM_PKT_DATA_INBAND,
765789
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
766790
if (ret != 0)
767-
goto cleanup;
791+
return ret;
768792

769793
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
770-
if (t == 0) {
771-
ret = -ETIMEDOUT;
772-
goto cleanup;
773-
}
794+
if (t == 0)
795+
return -ETIMEDOUT;
774796

775-
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) {
776-
ret = -EINVAL;
777-
goto cleanup;
778-
}
797+
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO)
798+
return -EINVAL;
779799

780800
if (vstor_packet->status == 0) {
781801
vmstor_proto_version =
@@ -791,10 +811,8 @@ static int storvsc_channel_init(struct hv_device *device)
791811
}
792812
}
793813

794-
if (vstor_packet->status != 0) {
795-
ret = -EINVAL;
796-
goto cleanup;
797-
}
814+
if (vstor_packet->status != 0)
815+
return -EINVAL;
798816

799817

800818
memset(vstor_packet, 0, sizeof(struct vstor_packet));
@@ -809,19 +827,15 @@ static int storvsc_channel_init(struct hv_device *device)
809827
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
810828

811829
if (ret != 0)
812-
goto cleanup;
830+
return ret;
813831

814832
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
815-
if (t == 0) {
816-
ret = -ETIMEDOUT;
817-
goto cleanup;
818-
}
833+
if (t == 0)
834+
return -ETIMEDOUT;
819835

820836
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
821-
vstor_packet->status != 0) {
822-
ret = -EINVAL;
823-
goto cleanup;
824-
}
837+
vstor_packet->status != 0)
838+
return -EINVAL;
825839

826840
/*
827841
* Check to see if multi-channel support is there.
@@ -837,6 +851,38 @@ static int storvsc_channel_init(struct hv_device *device)
837851
stor_device->max_transfer_bytes =
838852
vstor_packet->storage_channel_properties.max_transfer_bytes;
839853

854+
if (!is_fc)
855+
goto done;
856+
857+
memset(vstor_packet, 0, sizeof(struct vstor_packet));
858+
vstor_packet->operation = VSTOR_OPERATION_FCHBA_DATA;
859+
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
860+
861+
ret = vmbus_sendpacket(device->channel, vstor_packet,
862+
(sizeof(struct vstor_packet) -
863+
vmscsi_size_delta),
864+
(unsigned long)request,
865+
VM_PKT_DATA_INBAND,
866+
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
867+
868+
if (ret != 0)
869+
return ret;
870+
871+
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
872+
if (t == 0)
873+
return -ETIMEDOUT;
874+
875+
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
876+
vstor_packet->status != 0)
877+
return -EINVAL;
878+
879+
/*
880+
* Cache the currently active port and node ww names.
881+
*/
882+
cache_wwn(stor_device, vstor_packet);
883+
884+
done:
885+
840886
memset(vstor_packet, 0, sizeof(struct vstor_packet));
841887
vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION;
842888
vstor_packet->flags = REQUEST_COMPLETION_FLAG;
@@ -849,25 +895,19 @@ static int storvsc_channel_init(struct hv_device *device)
849895
VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
850896

851897
if (ret != 0)
852-
goto cleanup;
898+
return ret;
853899

854900
t = wait_for_completion_timeout(&request->wait_event, 5*HZ);
855-
if (t == 0) {
856-
ret = -ETIMEDOUT;
857-
goto cleanup;
858-
}
901+
if (t == 0)
902+
return -ETIMEDOUT;
859903

860904
if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO ||
861-
vstor_packet->status != 0) {
862-
ret = -EINVAL;
863-
goto cleanup;
864-
}
905+
vstor_packet->status != 0)
906+
return -EINVAL;
865907

866908
if (process_sub_channels)
867909
handle_multichannel_storage(device, max_chns);
868910

869-
870-
cleanup:
871911
return ret;
872912
}
873913

@@ -1076,6 +1116,14 @@ static void storvsc_on_receive(struct hv_device *device,
10761116
schedule_work(&work->work);
10771117
break;
10781118

1119+
case VSTOR_OPERATION_FCHBA_DATA:
1120+
stor_device = get_in_stor_device(device);
1121+
cache_wwn(stor_device, vstor_packet);
1122+
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
1123+
fc_host_node_name(stor_device->host) = stor_device->node_name;
1124+
fc_host_port_name(stor_device->host) = stor_device->port_name;
1125+
#endif
1126+
break;
10791127
default:
10801128
break;
10811129
}
@@ -1131,7 +1179,8 @@ static void storvsc_on_channel_callback(void *context)
11311179
return;
11321180
}
11331181

1134-
static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
1182+
static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size,
1183+
bool is_fc)
11351184
{
11361185
struct vmstorage_channel_properties props;
11371186
int ret;
@@ -1148,7 +1197,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size)
11481197
if (ret != 0)
11491198
return ret;
11501199

1151-
ret = storvsc_channel_init(device);
1200+
ret = storvsc_channel_init(device, is_fc);
11521201

11531202
return ret;
11541203
}
@@ -1573,6 +1622,7 @@ static int storvsc_probe(struct hv_device *device,
15731622
struct Scsi_Host *host;
15741623
struct hv_host_device *host_dev;
15751624
bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false);
1625+
bool is_fc = ((dev_id->driver_data == SFC_GUID) ? true : false);
15761626
int target = 0;
15771627
struct storvsc_device *stor_device;
15781628
int max_luns_per_target;
@@ -1630,7 +1680,7 @@ static int storvsc_probe(struct hv_device *device,
16301680
hv_set_drvdata(device, stor_device);
16311681

16321682
stor_device->port_number = host->host_no;
1633-
ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size);
1683+
ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size, is_fc);
16341684
if (ret)
16351685
goto err_out1;
16361686

@@ -1642,6 +1692,9 @@ static int storvsc_probe(struct hv_device *device,
16421692
host->max_lun = STORVSC_FC_MAX_LUNS_PER_TARGET;
16431693
host->max_id = STORVSC_FC_MAX_TARGETS;
16441694
host->max_channel = STORVSC_FC_MAX_CHANNELS - 1;
1695+
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
1696+
host->transportt = fc_transport_template;
1697+
#endif
16451698
break;
16461699

16471700
case SCSI_GUID:
@@ -1681,6 +1734,12 @@ static int storvsc_probe(struct hv_device *device,
16811734
goto err_out2;
16821735
}
16831736
}
1737+
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
1738+
if (host->transportt == fc_transport_template) {
1739+
fc_host_node_name(host) = stor_device->node_name;
1740+
fc_host_port_name(host) = stor_device->port_name;
1741+
}
1742+
#endif
16841743
return 0;
16851744

16861745
err_out2:
@@ -1706,6 +1765,10 @@ static int storvsc_remove(struct hv_device *dev)
17061765
struct storvsc_device *stor_device = hv_get_drvdata(dev);
17071766
struct Scsi_Host *host = stor_device->host;
17081767

1768+
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
1769+
if (host->transportt == fc_transport_template)
1770+
fc_remove_host(host);
1771+
#endif
17091772
scsi_remove_host(host);
17101773
storvsc_dev_remove(dev);
17111774
scsi_host_put(host);
@@ -1720,8 +1783,16 @@ static struct hv_driver storvsc_drv = {
17201783
.remove = storvsc_remove,
17211784
};
17221785

1786+
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
1787+
static struct fc_function_template fc_transport_functions = {
1788+
.show_host_node_name = 1,
1789+
.show_host_port_name = 1,
1790+
};
1791+
#endif
1792+
17231793
static int __init storvsc_drv_init(void)
17241794
{
1795+
int ret;
17251796

17261797
/*
17271798
* Divide the ring buffer data size (which is 1 page less
@@ -1736,12 +1807,28 @@ static int __init storvsc_drv_init(void)
17361807
vmscsi_size_delta,
17371808
sizeof(u64)));
17381809

1739-
return vmbus_driver_register(&storvsc_drv);
1810+
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
1811+
fc_transport_template = fc_attach_transport(&fc_transport_functions);
1812+
if (!fc_transport_template)
1813+
return -ENODEV;
1814+
#endif
1815+
1816+
ret = vmbus_driver_register(&storvsc_drv);
1817+
1818+
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
1819+
if (ret)
1820+
fc_release_transport(fc_transport_template);
1821+
#endif
1822+
1823+
return ret;
17401824
}
17411825

17421826
static void __exit storvsc_drv_exit(void)
17431827
{
17441828
vmbus_driver_unregister(&storvsc_drv);
1829+
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
1830+
fc_release_transport(fc_transport_template);
1831+
#endif
17451832
}
17461833

17471834
MODULE_LICENSE("GPL");

0 commit comments

Comments
 (0)