diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-28 11:39:01 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2022-05-28 11:39:01 -0700 |
commit | f56dbdda4322d33d485f3d30f3aabba71de9098c (patch) | |
tree | 20cd68fd2807e616f162ff3a130e52e56143899a /drivers/scsi | |
parent | 6112bd00e84e5dbffebc3c1e908cbe914ca772ee (diff) | |
parent | d27423bf048dcb5e15f04286d001c66685e30c29 (diff) | |
download | linux-stable-f56dbdda4322d33d485f3d30f3aabba71de9098c.tar.gz linux-stable-f56dbdda4322d33d485f3d30f3aabba71de9098c.tar.bz2 linux-stable-f56dbdda4322d33d485f3d30f3aabba71de9098c.zip |
Merge tag 'hyperv-next-signed-20220528' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux
Pull hyperv updates from Wei Liu:
- Harden hv_sock driver (Andrea Parri)
- Harden Hyper-V PCI driver (Andrea Parri)
- Fix multi-MSI for Hyper-V PCI driver (Jeffrey Hugo)
- Fix Hyper-V PCI to reduce boot time (Dexuan Cui)
- Remove code for long EOL'ed Hyper-V versions (Michael Kelley, Saurabh
Sengar)
- Fix balloon driver error handling (Shradha Gupta)
- Fix a typo in vmbus driver (Julia Lawall)
- Ignore vmbus IMC device (Michael Kelley)
- Add a new error message to Hyper-V DRM driver (Saurabh Sengar)
* tag 'hyperv-next-signed-20220528' of git://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux: (28 commits)
hv_balloon: Fix balloon_probe() and balloon_remove() error handling
scsi: storvsc: Removing Pre Win8 related logic
Drivers: hv: vmbus: fix typo in comment
PCI: hv: Fix synchronization between channel callback and hv_pci_bus_exit()
PCI: hv: Add validation for untrusted Hyper-V values
PCI: hv: Fix interrupt mapping for multi-MSI
PCI: hv: Reuse existing IRTE allocation in compose_msi_msg()
drm/hyperv: Remove support for Hyper-V 2008 and 2008R2/Win7
video: hyperv_fb: Remove support for Hyper-V 2008 and 2008R2/Win7
scsi: storvsc: Remove support for Hyper-V 2008 and 2008R2/Win7
Drivers: hv: vmbus: Remove support for Hyper-V 2008 and Hyper-V 2008R2/Win7
x86/hyperv: Disable hardlockup detector by default in Hyper-V guests
drm/hyperv: Add error message for fb size greater than allocated
PCI: hv: Do not set PCI_COMMAND_MEMORY to reduce VM boot time
PCI: hv: Fix hv_arch_irq_unmask() for multi-MSI
Drivers: hv: vmbus: Refactor the ring-buffer iterator functions
Drivers: hv: vmbus: Accept hv_sock offers in isolated guests
hv_sock: Add validation for untrusted Hyper-V values
hv_sock: Copy packets sent by Hyper-V out of the ring buffer
hv_sock: Check hv_pkt_iter_first_raw()'s return value
...
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/storvsc_drv.c | 191 |
1 files changed, 48 insertions, 143 deletions
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 9a0bba5a51a7..08ed059a738b 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -54,7 +54,6 @@ #define VMSTOR_PROTO_VERSION(MAJOR_, MINOR_) ((((MAJOR_) & 0xff) << 8) | \ (((MINOR_) & 0xff))) - #define VMSTOR_PROTO_VERSION_WIN6 VMSTOR_PROTO_VERSION(2, 0) #define VMSTOR_PROTO_VERSION_WIN7 VMSTOR_PROTO_VERSION(4, 2) #define VMSTOR_PROTO_VERSION_WIN8 VMSTOR_PROTO_VERSION(5, 1) @@ -136,21 +135,11 @@ struct hv_fc_wwn_packet { */ #define STORVSC_MAX_CMD_LEN 0x10 -#define POST_WIN7_STORVSC_SENSE_BUFFER_SIZE 0x14 -#define PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE 0x12 - +/* Sense buffer size is the same for all versions since Windows 8 */ #define STORVSC_SENSE_BUFFER_SIZE 0x14 #define STORVSC_MAX_BUF_LEN_WITH_PADDING 0x14 /* - * Sense buffer size changed in win8; have a run-time - * variable to track the size we should use. This value will - * likely change during protocol negotiation but it is valid - * to start by assuming pre-Win8. - */ -static int sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; - -/* * The storage protocol version is determined during the * initial exchange with the host. It will indicate which * storage functionality is available in the host. @@ -177,18 +166,6 @@ do { \ dev_warn(&(dev)->device, fmt, ##__VA_ARGS__); \ } while (0) -struct vmscsi_win8_extension { - /* - * The following were added in Windows 8 - */ - u16 reserve; - u8 queue_tag; - u8 queue_action; - u32 srb_flags; - u32 time_out_value; - u32 queue_sort_ey; -} __packed; - struct vmscsi_request { u16 length; u8 srb_status; @@ -214,46 +191,23 @@ struct vmscsi_request { /* * The following was added in win8. */ - struct vmscsi_win8_extension win8_extension; + u16 reserve; + u8 queue_tag; + u8 queue_action; + u32 srb_flags; + u32 time_out_value; + u32 queue_sort_ey; } __attribute((packed)); /* - * The list of storage protocols in order of preference. + * The list of windows version in order of preference. */ -struct vmstor_protocol { - int protocol_version; - int sense_buffer_size; - int vmscsi_size_delta; -}; - -static const struct vmstor_protocol vmstor_protocols[] = { - { +static const int protocol_version[] = { VMSTOR_PROTO_VERSION_WIN10, - POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, - 0 - }, - { VMSTOR_PROTO_VERSION_WIN8_1, - POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, - 0 - }, - { VMSTOR_PROTO_VERSION_WIN8, - POST_WIN7_STORVSC_SENSE_BUFFER_SIZE, - 0 - }, - { - VMSTOR_PROTO_VERSION_WIN7, - PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, - sizeof(struct vmscsi_win8_extension), - }, - { - VMSTOR_PROTO_VERSION_WIN6, - PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE, - sizeof(struct vmscsi_win8_extension), - } }; @@ -409,9 +363,7 @@ static void storvsc_on_channel_callback(void *context); #define STORVSC_IDE_MAX_CHANNELS 1 /* - * Upper bound on the size of a storvsc packet. vmscsi_size_delta is not - * included in the calculation because it is set after STORVSC_MAX_PKT_SIZE - * is used in storvsc_connect_to_vsp + * Upper bound on the size of a storvsc packet. */ #define STORVSC_MAX_PKT_SIZE (sizeof(struct vmpacket_descriptor) +\ sizeof(struct vstor_packet)) @@ -453,17 +405,6 @@ struct storvsc_device { unsigned char target_id; /* - * The size of the vmscsi_request has changed in win8. The - * additional size is because of new elements added to the - * structure. These elements are valid only when we are talking - * to a win8 host. - * Track the correction to size we need to apply. This value - * will likely change during protocol negotiation but it is - * valid to start by assuming pre-Win8. - */ - int vmscsi_size_delta; - - /* * Max I/O, the device can support. */ u32 max_transfer_bytes; @@ -795,8 +736,7 @@ static void handle_multichannel_storage(struct hv_device *device, int max_chns) vstor_packet->sub_channel_count = num_sc; ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), VMBUS_RQST_INIT, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -864,8 +804,7 @@ static int storvsc_execute_vstor_op(struct hv_device *device, vstor_packet->flags = REQUEST_COMPLETION_FLAG; ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), VMBUS_RQST_INIT, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -915,14 +854,13 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) * Query host supported protocol version. */ - for (i = 0; i < ARRAY_SIZE(vmstor_protocols); i++) { + for (i = 0; i < ARRAY_SIZE(protocol_version); 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->version.major_minor = - vmstor_protocols[i].protocol_version; + vstor_packet->version.major_minor = protocol_version[i]; /* * The revision number is only used in Windows; set it to 0. @@ -936,21 +874,16 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) return -EINVAL; if (vstor_packet->status == 0) { - vmstor_proto_version = - vmstor_protocols[i].protocol_version; - - sense_buffer_size = - vmstor_protocols[i].sense_buffer_size; - - stor_device->vmscsi_size_delta = - vmstor_protocols[i].vmscsi_size_delta; + vmstor_proto_version = protocol_version[i]; break; } } - if (vstor_packet->status != 0) + if (vstor_packet->status != 0) { + dev_err(&device->device, "Obsolete Hyper-V version\n"); return -EINVAL; + } memset(vstor_packet, 0, sizeof(struct vstor_packet)); @@ -986,11 +919,10 @@ static int storvsc_channel_init(struct hv_device *device, bool is_fc) cpumask_set_cpu(device->channel->target_cpu, &stor_device->alloced_cpus); - if (vmstor_proto_version >= VMSTOR_PROTO_VERSION_WIN8) { - if (vstor_packet->storage_channel_properties.flags & - STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) - process_sub_channels = true; - } + if (vstor_packet->storage_channel_properties.flags & + STORAGE_CHANNEL_SUPPORTS_MULTI_CHANNEL) + process_sub_channels = true; + stor_device->max_transfer_bytes = vstor_packet->storage_channel_properties.max_transfer_bytes; @@ -1197,7 +1129,7 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device, * Copy over the sense_info_length, but limit to the known max * size if Hyper-V returns a bad value. */ - stor_pkt->vm_srb.sense_info_length = min_t(u8, sense_buffer_size, + stor_pkt->vm_srb.sense_info_length = min_t(u8, STORVSC_SENSE_BUFFER_SIZE, vstor_packet->vm_srb.sense_info_length); if (vstor_packet->vm_srb.scsi_status != 0 || @@ -1289,8 +1221,8 @@ static void storvsc_on_channel_callback(void *context) struct storvsc_cmd_request *request = NULL; u32 pktlen = hv_pkt_datalen(desc); u64 rqst_id = desc->trans_id; - u32 minlen = rqst_id ? sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta : sizeof(enum vstor_packet_operation); + u32 minlen = rqst_id ? sizeof(struct vstor_packet) : + sizeof(enum vstor_packet_operation); if (pktlen < minlen) { dev_err(&device->device, @@ -1346,7 +1278,7 @@ static void storvsc_on_channel_callback(void *context) } memcpy(&request->vstor_packet, packet, - (sizeof(struct vstor_packet) - stor_device->vmscsi_size_delta)); + sizeof(struct vstor_packet)); complete(&request->wait_event); } } @@ -1557,11 +1489,10 @@ static int storvsc_do_io(struct hv_device *device, found_channel: vstor_packet->flags |= REQUEST_COMPLETION_FLAG; - vstor_packet->vm_srb.length = (sizeof(struct vmscsi_request) - - stor_device->vmscsi_size_delta); + vstor_packet->vm_srb.length = sizeof(struct vmscsi_request); - vstor_packet->vm_srb.sense_info_length = sense_buffer_size; + vstor_packet->vm_srb.sense_info_length = STORVSC_SENSE_BUFFER_SIZE; vstor_packet->vm_srb.data_transfer_length = @@ -1574,13 +1505,11 @@ found_channel: ret = vmbus_sendpacket_mpb_desc(outgoing_channel, request->payload, request->payload_sz, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), (unsigned long)request); } else { ret = vmbus_sendpacket(outgoing_channel, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), (unsigned long)request, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -1684,8 +1613,7 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) vstor_packet->vm_srb.path_id = stor_device->path_id; ret = vmbus_sendpacket(device->channel, vstor_packet, - (sizeof(struct vstor_packet) - - stor_device->vmscsi_size_delta), + sizeof(struct vstor_packet), VMBUS_RQST_RESET, VM_PKT_DATA_INBAND, VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); @@ -1778,31 +1706,31 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) memset(&cmd_request->vstor_packet, 0, sizeof(struct vstor_packet)); vm_srb = &cmd_request->vstor_packet.vm_srb; - vm_srb->win8_extension.time_out_value = 60; + vm_srb->time_out_value = 60; - vm_srb->win8_extension.srb_flags |= + vm_srb->srb_flags |= SRB_FLAGS_DISABLE_SYNCH_TRANSFER; if (scmnd->device->tagged_supported) { - vm_srb->win8_extension.srb_flags |= + vm_srb->srb_flags |= (SRB_FLAGS_QUEUE_ACTION_ENABLE | SRB_FLAGS_NO_QUEUE_FREEZE); - vm_srb->win8_extension.queue_tag = SP_UNTAGGED; - vm_srb->win8_extension.queue_action = SRB_SIMPLE_TAG_REQUEST; + vm_srb->queue_tag = SP_UNTAGGED; + vm_srb->queue_action = SRB_SIMPLE_TAG_REQUEST; } /* Build the SRB */ switch (scmnd->sc_data_direction) { case DMA_TO_DEVICE: vm_srb->data_in = WRITE_TYPE; - vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT; + vm_srb->srb_flags |= SRB_FLAGS_DATA_OUT; break; case DMA_FROM_DEVICE: vm_srb->data_in = READ_TYPE; - vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN; + vm_srb->srb_flags |= SRB_FLAGS_DATA_IN; break; case DMA_NONE: vm_srb->data_in = UNKNOWN_TYPE; - vm_srb->win8_extension.srb_flags |= SRB_FLAGS_NO_DATA_TRANSFER; + vm_srb->srb_flags |= SRB_FLAGS_NO_DATA_TRANSFER; break; default: /* @@ -1966,34 +1894,16 @@ static int storvsc_probe(struct hv_device *device, bool is_fc = ((dev_id->driver_data == SFC_GUID) ? true : false); int target = 0; struct storvsc_device *stor_device; - int max_luns_per_target; - int max_targets; - int max_channels; int max_sub_channels = 0; /* - * Based on the windows host we are running on, - * set state to properly communicate with the host. + * We support sub-channels for storage on SCSI and FC controllers. + * The number of sub-channels offerred is based on the number of + * VCPUs in the guest. */ - - if (vmbus_proto_version < VERSION_WIN8) { - max_luns_per_target = STORVSC_IDE_MAX_LUNS_PER_TARGET; - max_targets = STORVSC_IDE_MAX_TARGETS; - max_channels = STORVSC_IDE_MAX_CHANNELS; - } else { - max_luns_per_target = STORVSC_MAX_LUNS_PER_TARGET; - max_targets = STORVSC_MAX_TARGETS; - max_channels = STORVSC_MAX_CHANNELS; - /* - * On Windows8 and above, we support sub-channels for storage - * on SCSI and FC controllers. - * The number of sub-channels offerred is based on the number of - * VCPUs in the guest. - */ - if (!dev_is_ide) - max_sub_channels = - (num_cpus - 1) / storvsc_vcpus_per_sub_channel; - } + if (!dev_is_ide) + max_sub_channels = + (num_cpus - 1) / storvsc_vcpus_per_sub_channel; scsi_driver.can_queue = max_outstanding_req_per_channel * (max_sub_channels + 1) * @@ -2022,7 +1932,6 @@ static int storvsc_probe(struct hv_device *device, init_waitqueue_head(&stor_device->waiting_to_drain); stor_device->device = device; stor_device->host = host; - stor_device->vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); spin_lock_init(&stor_device->lock); hv_set_drvdata(device, stor_device); dma_set_min_align_mask(&device->device, HV_HYP_PAGE_SIZE - 1); @@ -2046,9 +1955,9 @@ static int storvsc_probe(struct hv_device *device, break; case SCSI_GUID: - host->max_lun = max_luns_per_target; - host->max_id = max_targets; - host->max_channel = max_channels - 1; + host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; + host->max_id = STORVSC_MAX_TARGETS; + host->max_channel = STORVSC_MAX_CHANNELS - 1; break; default: @@ -2235,10 +2144,6 @@ static int __init storvsc_drv_init(void) * than the ring buffer size since that page is reserved for * the ring buffer indices) by the max request size (which is * vmbus_channel_packet_multipage_buffer + struct vstor_packet + u64) - * - * The computation underestimates max_outstanding_req_per_channel - * for Win7 and older hosts because it does not take into account - * the vmscsi_size_delta correction to the max request size. */ max_outstanding_req_per_channel = ((storvsc_ringbuffer_size - PAGE_SIZE) / |