Author: sephe
Date: Thu Jan  5 06:21:14 2017
New Revision: 311374
URL: https://svnweb.freebsd.org/changeset/base/311374

Log:
  MFC 309726,309728
  
  309726
  
      hyperv/storvsc: Fix the SCSI disk attachment issue.
  
      On pre-WS2016 Hyper-V, if the only LUNs > 7 are used, then all disks
      fails to attach.  Mainly because those versions of Hyper-V do not set
      SRB_STATUS properly and deliver junky INQUERY responses.
  
      Submitted by:   Hongjiang Zhang <honzhan microsoft com>
      Reported by:    Hongxiong Xian <v-hoxian microsoft com>
      Sponsored by:   Microsoft
      Differential Revision:  https://reviews.freebsd.org/D8724
  
  309728
      hyperv/storvsc: Minor style changes; no functional changes.
  
      Reported by:    rpokala
      Sponsored by:   Microsoft

Modified:
  stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c
==============================================================================
--- stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c   Thu Jan  5 
06:19:07 2017        (r311373)
+++ stable/11/sys/dev/hyperv/storvsc/hv_storvsc_drv_freebsd.c   Thu Jan  5 
06:21:14 2017        (r311374)
@@ -2053,6 +2053,19 @@ create_storvsc_request(union ccb *ccb, s
        return(0);
 }
 
+static uint32_t
+is_scsi_valid(const struct scsi_inquiry_data *inq_data)
+{
+       u_int8_t type;
+
+       type = SID_TYPE(inq_data);
+       if (type == T_NODEVICE)
+               return (0);
+       if (SID_QUAL(inq_data) == SID_QUAL_BAD_LU)
+               return (0);
+       return (1);
+}
+
 /**
  * @brief completion function before returning to CAM
  *
@@ -2071,6 +2084,7 @@ storvsc_io_done(struct hv_storvsc_reques
        struct vmscsi_req *vm_srb = &reqp->vstor_packet.u.vm_srb;
        bus_dma_segment_t *ori_sglist = NULL;
        int ori_sg_count = 0;
+
        /* destroy bounce buffer if it is used */
        if (reqp->bounce_sgl_count) {
                ori_sglist = (bus_dma_segment_t *)ccb->csio.data_ptr;
@@ -2125,6 +2139,7 @@ storvsc_io_done(struct hv_storvsc_reques
        ccb->ccb_h.status &= ~CAM_STATUS_MASK;
        if (vm_srb->scsi_status == SCSI_STATUS_OK) {
                const struct scsi_generic *cmd;
+
                cmd = (const struct scsi_generic *)
                    ((ccb->ccb_h.flags & CAM_CDB_POINTER) ?
                     csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes);
@@ -2164,32 +2179,47 @@ storvsc_io_done(struct hv_storvsc_reques
                        ccb->ccb_h.status |= CAM_REQ_CMP;
                }
 
-               if (cmd->opcode == INQUIRY) {
+               if (cmd->opcode == INQUIRY &&
+                   vm_srb->srb_status == SRB_STATUS_SUCCESS) {
+                       int resp_xfer_len, resp_buf_len, data_len;
+                       uint8_t *resp_buf = (uint8_t *)csio->data_ptr;
                        struct scsi_inquiry_data *inq_data =
                            (struct scsi_inquiry_data *)csio->data_ptr;
-                       uint8_t *resp_buf = (uint8_t *)csio->data_ptr;
-                       int resp_xfer_len, resp_buf_len, data_len;
 
                        /* Get the buffer length reported by host */
                        resp_xfer_len = vm_srb->transfer_len;
+
                        /* Get the available buffer length */
                        resp_buf_len = resp_xfer_len >= 5 ? resp_buf[4] + 5 : 0;
                        data_len = (resp_buf_len < resp_xfer_len) ?
                            resp_buf_len : resp_xfer_len;
-
                        if (bootverbose && data_len >= 5) {
                                xpt_print(ccb->ccb_h.path, "storvsc inquiry "
                                    "(%d) [%x %x %x %x %x ... ]\n", data_len,
                                    resp_buf[0], resp_buf[1], resp_buf[2],
                                    resp_buf[3], resp_buf[4]);
                        }
-                       if (vm_srb->srb_status == SRB_STATUS_SUCCESS &&
-                           data_len >= SHORT_INQUIRY_LENGTH) {
+                       /*
+                        * XXX: Manually fix the wrong response returned from 
WS2012
+                        */
+                       if (!is_scsi_valid(inq_data) &&
+                           (vmstor_proto_version == 
VMSTOR_PROTOCOL_VERSION_WIN8_1 ||
+                           vmstor_proto_version == 
VMSTOR_PROTOCOL_VERSION_WIN8 ||
+                           vmstor_proto_version == 
VMSTOR_PROTOCOL_VERSION_WIN7)) {
+                               if (data_len >= 4 &&
+                                   (resp_buf[2] == 0 || resp_buf[3] == 0)) {
+                                       resp_buf[2] = 5; // verion=5 means SPC-3
+                                       resp_buf[3] = 2; // resp fmt must be 2
+                                       if (bootverbose)
+                                               xpt_print(ccb->ccb_h.path,
+                                                   "fix version and resp fmt 
for 0x%x\n",
+                                                   vmstor_proto_version);
+                               }
+                       } else if (data_len >= SHORT_INQUIRY_LENGTH) {
                                char vendor[16];
 
                                cam_strvis(vendor, inq_data->vendor,
                                    sizeof(inq_data->vendor), sizeof(vendor));
-
                                /*
                                 * XXX: Upgrade SPC2 to SPC3 if host is WIN8 or
                                 * WIN2012 R2 in order to support UNMAP feature.
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to