Merge tag 'scsi-misc' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-microblaze.git] / drivers / scsi / storvsc_drv.c
index 4fe4f67..ca35309 100644 (file)
@@ -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,20 +135,10 @@ 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
@@ -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))
@@ -452,17 +404,6 @@ struct storvsc_device {
        unsigned char path_id;
        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.
         */
@@ -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) /