]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
scsi: megaraid_sas: Send SYNCHRONIZE_CACHE for VD to firmware
authorKashyap Desai <kashyap.desai@broadcom.com>
Fri, 21 Oct 2016 13:33:33 +0000 (06:33 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 8 Nov 2016 22:39:35 +0000 (17:39 -0500)
Until now the megaraid_sas driver has reported successful completion on
SYNCHRONIZE_CACHE commands without sending them down to the controller.
The controller firmware has been responsible for taking care of flushing
disk caches for all drives that belong to a Virtual Disk at the time of
system reboot/shutdown.

There may have been a reason to avoid sending SYNCHRONIZE_CACHE to a VD
in the past but that no longer appears to be valid.

Older versions of MegaRaid firmware (Gen2 and Gen2.5) set the WCE bit
for Virtual Disks but the firmware does not report correct completion
status for a SYNCHRONIZE_CACHE command. As a result, we must use another
method to identify whether it is safe to send the command to the
controller. We use the canHandleSyncCache firmware flag in the scratch
pad register at offset 0xB4.

New SYNCHRONIZE_CACHE behavior:

IF 'JBOD'

Driver sends SYNCHRONIZE_CACHE command to the firmware
Firmware sends SYNCHRONIZE_CACHE to drive
Firmware obtains status from drive and returns same status back to driver

ELSEIF 'VirtualDisk'

IF firmware supports new API bit called canHandleSyncCache
Driver sends SYNCHRONIZE_CACHE command to the firmware
Firmware does not send SYNCHRONIZE_CACHE to drives
Firmware returns SUCCESS
ELSE
Driver does not send SYNCHRONIZE_CACHE command to the firmware
Driver return SUCCESS for that command
ENDIF
ENDIF

[mkp: edited patch description]

Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com>
Signed-off-by: Sumit Saxena <sumit.saxena@broadcom.com>
Reviewed-by: Tomas Henzl <thenzl@redhat.com>
Reviewed-by: Hannes Reinecke <hare@suse.com>
Reviewed-by: Ewan D. Milne <emilne@redhat.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/megaraid/megaraid_sas.h
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/megaraid/megaraid_sas_fusion.c

index ca86c885dfaab4f0fb6ae3595922d6f1a77974be..43fd14fad1a6214cf6fc4c2b82f0a996f5bc9021 100644 (file)
@@ -1429,6 +1429,8 @@ enum FW_BOOT_CONTEXT {
 #define MR_MAX_REPLY_QUEUES_EXT_OFFSET_SHIFT    14
 #define MR_MAX_MSIX_REG_ARRAY                   16
 #define MR_RDPQ_MODE_OFFSET                    0X00800000
+#define MR_CAN_HANDLE_SYNC_CACHE_OFFSET                0X01000000
+
 /*
 * register set for both 1068 and 1078 controllers
 * structure extended for 1078 registers
@@ -2140,6 +2142,7 @@ struct megasas_instance {
        u8 is_imr;
        u8 is_rdpq;
        bool dev_handle;
+       bool fw_sync_cache_support;
 };
 struct MR_LD_VF_MAP {
        u32 size;
index d5410a39d956faf1d129a00b2de007dc7778bb09..f6db7abf150df86d72ad3081daa0b3a9d37cec1f 100644 (file)
@@ -1700,11 +1700,8 @@ megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
                goto out_done;
        }
 
-       /*
-        * FW takes care of flush cache on its own for Virtual Disk.
-        * No need to send it down for VD. For JBOD send SYNCHRONIZE_CACHE to FW.
-        */
-       if ((scmd->cmnd[0] == SYNCHRONIZE_CACHE) && MEGASAS_IS_LOGICAL(scmd)) {
+       if ((scmd->cmnd[0] == SYNCHRONIZE_CACHE) && MEGASAS_IS_LOGICAL(scmd) &&
+               (!instance->fw_sync_cache_support)) {
                scmd->result = DID_OK << 16;
                goto out_done;
        }
index 2159f6ae5a31462ed4890a1f69ea47fd95d147cc..2e61306de9c808b9ea047ae1be04899e3b9d468e 100644 (file)
@@ -748,6 +748,11 @@ megasas_ioc_init_fusion(struct megasas_instance *instance)
                goto fail_fw_init;
        }
 
+       instance->fw_sync_cache_support = (scratch_pad_2 &
+               MR_CAN_HANDLE_SYNC_CACHE_OFFSET) ? 1 : 0;
+       dev_info(&instance->pdev->dev, "FW supports sync cache\t: %s\n",
+                instance->fw_sync_cache_support ? "Yes" : "No");
+
        IOCInitMessage =
          dma_alloc_coherent(&instance->pdev->dev,
                             sizeof(struct MPI2_IOC_INIT_REQUEST),