Author: jimharris
Date: Wed Jun 26 22:08:45 2013
New Revision: 252262
URL: http://svnweb.freebsd.org/changeset/base/252262

Log:
  For ATA_PASSTHROUGH commands, pretend isci(4) supports multiword DMA
  by treating it as UDMA.
  
  This fixes a problem introduced in r249933/r249939, where CAM sends
  ATA_DSM_TRIM to SATA devices using ATA_PASSTHROUGH_16.  scsi_ata_trim()
  sets protocol as DMA (not UDMA) which is for multi-word DMA, even
  though no such mode is selected for the device.  isci(4) would fail
  these commands which is the correct behavior but not consistent with
  other HBAs, namely LSI's.
  
  smh@ did some further testing on an LSI controller, which rejected
  ATA_PASSTHROUGH_16 commands with mode=UDMA_OUT, even though only
  a UDMA mode was selected on the device.  So this precludes adding
  any kind of mode detection in CAM to determine which mode to use on
  a per-device basis.
  
  Sponsored by: Intel
  Discussed with:       scottl, smh
  Reported by:  scottl
  Tested by:    scottl
  MFC after:    3 days

Modified:
  head/sys/dev/isci/scil/sati_passthrough.c

Modified: head/sys/dev/isci/scil/sati_passthrough.c
==============================================================================
--- head/sys/dev/isci/scil/sati_passthrough.c   Wed Jun 26 21:58:28 2013        
(r252261)
+++ head/sys/dev/isci/scil/sati_passthrough.c   Wed Jun 26 22:08:45 2013        
(r252262)
@@ -85,6 +85,7 @@ __FBSDID("$FreeBSD$");
 // Protocols
 #define PASSTHROUGH_PIO_DATA_IN            0x4
 #define PASSTHROUGH_PIO_DATA_OUT           0x5
+#define PASSTHROUGH_DMA                    0x6
 #define PASSTHROUGH_UDMA_DATA_IN           0xA
 #define PASSTHROUGH_UDMA_DATA_OUT          0xB
 #define PASSTHROUGH_RETURN_RESPONSE        0xF
@@ -252,8 +253,8 @@ SATI_STATUS sati_passthrough_check_direc
    U8           * cdb
 )
 {
-   if ((PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_PIO_DATA_IN) ||
-       (PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_UDMA_DATA_IN))
+   if ((sequence->protocol == PASSTHROUGH_PIO_DATA_IN) ||
+       (sequence->protocol == PASSTHROUGH_UDMA_DATA_IN))
    {
       if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x0)
       {
@@ -264,8 +265,8 @@ SATI_STATUS sati_passthrough_check_direc
          sequence->data_direction = SATI_DATA_DIRECTION_IN;
       }
    }
-   else if ((PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_PIO_DATA_OUT) ||
-            (PASSTHROUGH_CDB_PROTOCOL(cdb) == PASSTHROUGH_UDMA_DATA_OUT))
+   else if ((sequence->protocol == PASSTHROUGH_PIO_DATA_OUT) ||
+            (sequence->protocol == PASSTHROUGH_UDMA_DATA_OUT))
    {
       if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x1)
       {
@@ -318,6 +319,26 @@ SATI_STATUS sati_passthrough_12_translat
    sequence->protocol = PASSTHROUGH_CDB_PROTOCOL (cdb);
    register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
 
+   /*
+    * CAM will send passthrough commands with protocol set to multiword
+    * DMA even though no multiword DMA mode is selected on the device.
+    * This is because some controllers (LSI) will only accept
+    * ATA_PASSTHROUGH commands with DMA mode - not UDMA_IN/OUT.
+    *
+    * Since isci does not support multiword DMA, fix this up here.
+    */
+   if (sequence->protocol == PASSTHROUGH_DMA)
+   {
+      if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x1)
+      {
+         sequence->protocol = PASSTHROUGH_UDMA_DATA_IN;
+      }
+      else
+      {
+         sequence->protocol = PASSTHROUGH_UDMA_DATA_OUT;
+      }
+   }
+
    if (sati_passthrough_check_direction(sequence, cdb) != SATI_COMPLETE
        || sati_passthrough_multiple_count_error(cdb)
       )
@@ -376,6 +397,26 @@ SATI_STATUS sati_passthrough_16_translat
    sequence->protocol = PASSTHROUGH_CDB_PROTOCOL(cdb);
    register_fis = sati_cb_get_h2d_register_fis_address(ata_io);
 
+   /*
+    * CAM will send passthrough commands with protocol set to multiword
+    * DMA even though no multiword DMA mode is selected on the device.
+    * This is because some controllers (LSI) will only accept
+    * ATA_PASSTHROUGH commands with DMA mode - not UDMA_IN/OUT.
+    *
+    * Since isci does not support multiword DMA, fix this up here.
+    */
+   if (sequence->protocol == PASSTHROUGH_DMA)
+   {
+      if (PASSTHROUGH_CDB_T_DIR(cdb) == 0x1)
+      {
+         sequence->protocol = PASSTHROUGH_UDMA_DATA_IN;
+      }
+      else
+      {
+         sequence->protocol = PASSTHROUGH_UDMA_DATA_OUT;
+      }
+   }
+
    if (sati_passthrough_check_direction(sequence, cdb) != SATI_COMPLETE
        || sati_passthrough_multiple_count_error(cdb)
       )
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to