From patchwork Sun Dec 13 20:28:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: KY Srinivasan X-Patchwork-Id: 7839601 Return-Path: X-Original-To: patchwork-linux-scsi@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 1728DBEEE1 for ; Sun, 13 Dec 2015 18:56:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E3F622034B for ; Sun, 13 Dec 2015 18:56:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 92F1C20320 for ; Sun, 13 Dec 2015 18:56:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752463AbbLMSzt (ORCPT ); Sun, 13 Dec 2015 13:55:49 -0500 Received: from p3plsmtps2ded03.prod.phx3.secureserver.net ([208.109.80.60]:50411 "EHLO p3plsmtps2ded03.prod.phx3.secureserver.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752335AbbLMSzB (ORCPT ); Sun, 13 Dec 2015 13:55:01 -0500 Received: from linuxonhyperv.com ([72.167.245.219]) by : HOSTING RELAY : with SMTP id 8BnQazFUTsHQS8BnQa37Mn; Sun, 13 Dec 2015 11:55:00 -0700 x-originating-ip: 72.167.245.219 Received: by linuxonhyperv.com (Postfix, from userid 507) id 79BAD1901E5; Sun, 13 Dec 2015 12:28:33 -0800 (PST) From: "K. Y. Srinivasan" To: gregkh@linuxfoundation.org, linux-kernel@vger.kernel.org, devel@linuxdriverproject.org, ohering@suse.com, jbottomley@parallels.com, hch@infradead.org, linux-scsi@vger.kernel.org, apw@canonical.com, vkuznets@redhat.com, jasowang@redhat.com, martin.petersen@oracle.com Cc: "K. Y. Srinivasan" Subject: [PATCH V3 2/4] scsi: storvsc: Properly support Fibre Channel devices Date: Sun, 13 Dec 2015 12:28:30 -0800 Message-Id: <1450038512-19252-2-git-send-email-kys@microsoft.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1450038512-19252-1-git-send-email-kys@microsoft.com> References: <1450038486-19211-1-git-send-email-kys@microsoft.com> <1450038512-19252-1-git-send-email-kys@microsoft.com> X-CMAE-Envelope: MS4wfLxUuLQu/Lq//y7T9I23AhI8tYFz7jduo8FIWZaJjH1I18JDECZIJaGQZ/UqE0tXbv8+D+pbLPF7v5b7GGppAmLk7fMOe6I5CUvqDgBNMB04GAHvnVVE xbuV0v7L/kBXTO6dbssLns4cTyZZEy7/QjhS1X8/QQC77KVqz7PD0nX8tegI/dMVsATiwM0tlBKEHXRxrIVGPQX5RuKb7pVq8RkQ2soJpyj8FUxpbhIClYK4 6exQq8n6l8yxn1Vx1hC6doh+Myj7lVZo3IU/VE25FkB4Fuuo96OkxH0OJCqImv8u5sxKKjjSGCO5LfwIdewaBopt/n5vmwihlfOvzfzmMaijNmwN1mauvdZy lrARk6lT6iUtsuq8kWtnoO+N1JYwwo4dDCdl0PSb1PcZF4jmvQNUZoFGWKQegmeE/WkNitp1vG7MN4vBY1A7fZ2tLJkDMlPkOVEG1XN1Rkm42GZB/4RMai9G QrshM9Ia/UBSzDNoF+lR1Sg/HLJVAD1BfTzkgW0DvqHiB7/RMwIUaZjLaTDzAiQEWPAfSqKFFlCvZh7An0s2Oz9aKfhMtV61MSfTIA== Sender: linux-scsi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-scsi@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 Reviewed-by: Long Li Tested-by: Alex Ng --- V2: Fixed error paths - Dan Carpenter V3: Fixed build issues reported by kbuild test robot drivers/scsi/storvsc_drv.c | 181 ++++++++++++++++++++++++++++++++----------- 1 files changed, 134 insertions(+), 47 deletions(-) diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 00bb4bd..220b794 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -41,6 +41,7 @@ #include #include #include +#include /* * All wire protocol details (storage protocol between the guest and the host) @@ -397,6 +398,9 @@ static int storvsc_timeout = 180; static int msft_blist_flags = BLIST_TRY_VPD_PAGES; +#ifdef CONFIG_SCSI_FC_ATTRS +static struct scsi_transport_template *fc_transport_template; +#endif static void storvsc_on_channel_callback(void *context); @@ -456,6 +460,11 @@ struct storvsc_device { /* Used for vsc/vsp channel reset process */ struct storvsc_cmd_request init_request; struct storvsc_cmd_request reset_request; + /* + * Currently active port and node names for FC devices. + */ + u64 node_name; + u64 port_name; }; struct hv_host_device { @@ -695,7 +704,26 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) vmbus_are_subchannels_present(device->channel); } -static int storvsc_channel_init(struct hv_device *device) +static void cache_wwn(struct storvsc_device *stor_device, + struct vstor_packet *vstor_packet) +{ + /* + * Cache the currently active port and node ww names. + */ + if (vstor_packet->wwn_packet.primary_active) { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.primary_port_wwn); + } else { + stor_device->node_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_node_wwn); + stor_device->port_name = + wwn_to_u64(vstor_packet->wwn_packet.secondary_port_wwn); + } +} + +static int storvsc_channel_init(struct hv_device *device, bool is_fc) { struct storvsc_device *stor_device; struct storvsc_cmd_request *request; @@ -727,19 +755,15 @@ static int storvsc_channel_init(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + vstor_packet->status != 0) + return -EINVAL; for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { @@ -764,18 +788,14 @@ static int storvsc_channel_init(struct hv_device *device) VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; - if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) { - ret = -EINVAL; - goto cleanup; - } + if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO) + return -EINVAL; if (vstor_packet->status == 0) { vmstor_proto_version = @@ -791,10 +811,8 @@ static int storvsc_channel_init(struct hv_device *device) } } - if (vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + if (vstor_packet->status != 0) + return -EINVAL; memset(vstor_packet, 0, sizeof(struct vstor_packet)); @@ -809,19 +827,15 @@ static int storvsc_channel_init(struct hv_device *device) VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + vstor_packet->status != 0) + return -EINVAL; /* * Check to see if multi-channel support is there. @@ -837,6 +851,38 @@ static int storvsc_channel_init(struct hv_device *device) stor_device->max_transfer_bytes = vstor_packet->storage_channel_properties.max_transfer_bytes; + if (!is_fc) + goto done; + + 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); + + 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. + */ + cache_wwn(stor_device, vstor_packet); + +done: + memset(vstor_packet, 0, sizeof(struct vstor_packet)); vstor_packet->operation = VSTOR_OPERATION_END_INITIALIZATION; vstor_packet->flags = REQUEST_COMPLETION_FLAG; @@ -849,25 +895,19 @@ static int storvsc_channel_init(struct hv_device *device) VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); if (ret != 0) - goto cleanup; + return ret; t = wait_for_completion_timeout(&request->wait_event, 5*HZ); - if (t == 0) { - ret = -ETIMEDOUT; - goto cleanup; - } + if (t == 0) + return -ETIMEDOUT; if (vstor_packet->operation != VSTOR_OPERATION_COMPLETE_IO || - vstor_packet->status != 0) { - ret = -EINVAL; - goto cleanup; - } + vstor_packet->status != 0) + return -EINVAL; if (process_sub_channels) handle_multichannel_storage(device, max_chns); - -cleanup: return ret; } @@ -1076,6 +1116,14 @@ static void storvsc_on_receive(struct hv_device *device, schedule_work(&work->work); break; + case VSTOR_OPERATION_FCHBA_DATA: + stor_device = get_in_stor_device(device); + cache_wwn(stor_device, vstor_packet); +#ifdef CONFIG_SCSI_FC_ATTRS + fc_host_node_name(stor_device->host) = stor_device->node_name; + fc_host_port_name(stor_device->host) = stor_device->port_name; +#endif + break; default: break; } @@ -1131,7 +1179,8 @@ static void storvsc_on_channel_callback(void *context) return; } -static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) +static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size, + bool is_fc) { struct vmstorage_channel_properties props; int ret; @@ -1148,7 +1197,7 @@ static int storvsc_connect_to_vsp(struct hv_device *device, u32 ring_size) if (ret != 0) return ret; - ret = storvsc_channel_init(device); + ret = storvsc_channel_init(device, is_fc); return ret; } @@ -1573,6 +1622,7 @@ static int storvsc_probe(struct hv_device *device, struct Scsi_Host *host; struct hv_host_device *host_dev; bool dev_is_ide = ((dev_id->driver_data == IDE_GUID) ? true : false); + bool is_fc = ((dev_id->driver_data == SFC_GUID) ? true : false); int target = 0; struct storvsc_device *stor_device; int max_luns_per_target; @@ -1630,7 +1680,7 @@ static int storvsc_probe(struct hv_device *device, hv_set_drvdata(device, stor_device); stor_device->port_number = host->host_no; - ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size); + ret = storvsc_connect_to_vsp(device, storvsc_ringbuffer_size, is_fc); if (ret) goto err_out1; @@ -1642,6 +1692,9 @@ static int storvsc_probe(struct hv_device *device, host->max_lun = STORVSC_FC_MAX_LUNS_PER_TARGET; host->max_id = STORVSC_FC_MAX_TARGETS; host->max_channel = STORVSC_FC_MAX_CHANNELS - 1; +#ifdef CONFIG_SCSI_FC_ATTRS + host->transportt = fc_transport_template; +#endif break; case SCSI_GUID: @@ -1681,6 +1734,12 @@ static int storvsc_probe(struct hv_device *device, goto err_out2; } } +#ifdef CONFIG_SCSI_FC_ATTRS + if (host->transportt == fc_transport_template) { + fc_host_node_name(host) = stor_device->node_name; + fc_host_port_name(host) = stor_device->port_name; + } +#endif return 0; err_out2: @@ -1706,6 +1765,10 @@ static int storvsc_remove(struct hv_device *dev) struct storvsc_device *stor_device = hv_get_drvdata(dev); struct Scsi_Host *host = stor_device->host; +#ifdef CONFIG_SCSI_FC_ATTRS + if (host->transportt == fc_transport_template) + fc_remove_host(host); +#endif scsi_remove_host(host); storvsc_dev_remove(dev); scsi_host_put(host); @@ -1720,8 +1783,16 @@ static struct hv_driver storvsc_drv = { .remove = storvsc_remove, }; +#ifdef CONFIG_SCSI_FC_ATTRS +static struct fc_function_template fc_transport_functions = { + .show_host_node_name = 1, + .show_host_port_name = 1, +}; +#endif + static int __init storvsc_drv_init(void) { + int ret; /* * Divide the ring buffer data size (which is 1 page less @@ -1736,12 +1807,28 @@ static int __init storvsc_drv_init(void) vmscsi_size_delta, sizeof(u64))); - return vmbus_driver_register(&storvsc_drv); +#ifdef CONFIG_SCSI_FC_ATTRS + fc_transport_template = fc_attach_transport(&fc_transport_functions); + if (!fc_transport_template) + return -ENODEV; +#endif + + ret = vmbus_driver_register(&storvsc_drv); + +#ifdef CONFIG_SCSI_FC_ATTRS + if (ret) + fc_release_transport(fc_transport_template); +#endif + + return ret; } static void __exit storvsc_drv_exit(void) { vmbus_driver_unregister(&storvsc_drv); +#ifdef CONFIG_SCSI_FC_ATTRS + fc_release_transport(fc_transport_template); +#endif } MODULE_LICENSE("GPL");