OSDN Git Service

scsi: mpt3sas: Register trace buffer based on NVDATA settings
authorSreekanth Reddy <sreekanth.reddy@broadcom.com>
Fri, 13 Sep 2019 13:04:38 +0000 (09:04 -0400)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 1 Oct 2019 02:32:46 +0000 (22:32 -0400)
Currently if user wishes to enable the host trace buffer during driver load
time, then user has to load the driver with module parameter
'diag_buffer_enable' set to one.

Alternatively now the user can enable host trace buffer by enabling the
following fields in manufacturing page11 in NVDATA (nvdata xml is used
while building HBA firmware image):

 * HostTraceBufferMaxSizeKB - Maximum trace buffer size in KB that host can
                              allocate,

 * HostTraceBufferMinSizeKB - Minimum trace buffer size in KB atleast host
                              should allocate,

 * HostTraceBufferDecrementSizeKB - size by which host can reduce from
                              buffer size and retry the buffer allocation
                              when buffer allocation failed with previous
                              calculated buffer size.

The driver will register the trace buffer automatically without any module
parameter during boot time when above fields are enabled in manufacturing
page11 in HBA firmware.

Driver follows the following algorithm for enabling the host trace buffer
during driver load time:

* If user has loaded the driver with module parameter 'diag_buffer_enable'
  set to one, then driver allocates 2MB buffer and registers this buffer
  with HBA firmware for capturing the firmware trace logs.

* Else driver reads manufacture page11 data and checks whether
  HostTraceBufferMaxSizeKB filed is zero or not?

  - If HostTraceBufferMaxSizeKB is non-zero then driver tries to allocate
    HostTraceBufferMaxSizeKB size of memory. If the buffer allocation is
    successful, then it will register this buffer with HBA firmware, else
    in a loop the driver will try again by reducing the current buffer size
    with HostTraceBufferDecrementSizeKB size until memory allocation is
    successful or buffer size falls below HostTraceBufferMinSizeKB. If the
    memory allocation is successful, then the buffer will be registered
    with the firmware. Else, if the buffer size falls below the
    HostTraceBufferMinSizeKB, then driver won't register trace buffer with
    HBA firmware.

  - If HostTraceBufferMaxSizeKB is zero, then driver won't register trace
    buffer with HBA firmware.

Link: https://lore.kernel.org/r/1568379890-18347-2-git-send-email-sreekanth.reddy@broadcom.com
Signed-off-by: Sreekanth Reddy <sreekanth.reddy@broadcom.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/mpt3sas/mpt3sas_base.h
drivers/scsi/mpt3sas/mpt3sas_ctl.c
drivers/scsi/mpt3sas/mpt3sas_scsih.c

index faca0a5..a501c25 100644 (file)
@@ -391,9 +391,12 @@ struct Mpi2ManufacturingPage11_t {
        u8      Reserved6;                      /* 2Fh */
        __le32  Reserved7[7];                   /* 30h - 4Bh */
        u8      NVMeAbortTO;                    /* 4Ch */
-       u8      Reserved8;                      /* 4Dh */
-       u16     Reserved9;                      /* 4Eh */
-       __le32  Reserved10[4];                  /* 50h - 60h */
+       u8      NumPerDevEvents;                /* 4Dh */
+       u8      HostTraceBufferDecrementSizeKB; /* 4Eh */
+       u8      HostTraceBufferFlags;           /* 4Fh */
+       u16     HostTraceBufferMaxSizeKB;       /* 50h */
+       u16     HostTraceBufferMinSizeKB;       /* 52h */
+       __le32  Reserved10[2];                  /* 54h - 5Bh */
 };
 
 /**
index 7d69695..285edd7 100644 (file)
@@ -1669,6 +1669,10 @@ void
 mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
 {
        struct mpt3_diag_register diag_register;
+       u32 ret_val;
+       u32 trace_buff_size = ioc->manu_pg11.HostTraceBufferMaxSizeKB<<10;
+       u32 min_trace_buff_size = 0;
+       u32 decr_trace_buff_size = 0;
 
        memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
 
@@ -1677,10 +1681,61 @@ mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register)
                ioc->diag_trigger_master.MasterData =
                    (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET);
                diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
-               /* register for 2MB buffers  */
-               diag_register.requested_buffer_size = 2 * (1024 * 1024);
                diag_register.unique_id = 0x7075900;
-               _ctl_diag_register_2(ioc,  &diag_register);
+
+               if (trace_buff_size != 0) {
+                       diag_register.requested_buffer_size = trace_buff_size;
+                       min_trace_buff_size =
+                           ioc->manu_pg11.HostTraceBufferMinSizeKB<<10;
+                       decr_trace_buff_size =
+                           ioc->manu_pg11.HostTraceBufferDecrementSizeKB<<10;
+
+                       if (min_trace_buff_size > trace_buff_size) {
+                               /* The buff size is not set correctly */
+                               ioc_err(ioc,
+                                   "Min Trace Buff size (%d KB) greater than Max Trace Buff size (%d KB)\n",
+                                    min_trace_buff_size>>10,
+                                    trace_buff_size>>10);
+                               ioc_err(ioc,
+                                   "Using zero Min Trace Buff Size\n");
+                                   min_trace_buff_size = 0;
+                       }
+
+                       if (decr_trace_buff_size == 0) {
+                               /*
+                                * retry the min size if decrement
+                                * is not available.
+                                */
+                               decr_trace_buff_size =
+                                   trace_buff_size - min_trace_buff_size;
+                       }
+               } else {
+                       /* register for 2MB buffers  */
+                       diag_register.requested_buffer_size = 2 * (1024 * 1024);
+               }
+
+               do {
+                       ret_val = _ctl_diag_register_2(ioc,  &diag_register);
+
+                       if (ret_val == -ENOMEM && min_trace_buff_size &&
+                           (trace_buff_size - decr_trace_buff_size) >=
+                           min_trace_buff_size) {
+                               /* adjust the buffer size */
+                               trace_buff_size -= decr_trace_buff_size;
+                               diag_register.requested_buffer_size =
+                                   trace_buff_size;
+                       } else
+                               break;
+               } while (true);
+
+               if (ret_val == -ENOMEM)
+                       ioc_err(ioc,
+                           "Cannot allocate trace buffer memory. Last memory tried = %d KB\n",
+                           diag_register.requested_buffer_size>>10);
+               else if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE]
+                   & MPT3_DIAG_BUFFER_IS_REGISTERED)
+                       ioc_err(ioc, "Trace buffer memory %d KB allocated\n",
+                           diag_register.requested_buffer_size>>10);
        }
 
        if (bits_to_register & 2) {
@@ -3130,7 +3185,15 @@ host_trace_buffer_enable_store(struct device *cdev,
                memset(&diag_register, 0, sizeof(struct mpt3_diag_register));
                ioc_info(ioc, "posting host trace buffers\n");
                diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE;
-               diag_register.requested_buffer_size = (1024 * 1024);
+
+               if (ioc->manu_pg11.HostTraceBufferMaxSizeKB != 0 &&
+                   ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE] != 0) {
+                       /* post the same buffer allocated previously */
+                       diag_register.requested_buffer_size =
+                           ioc->diag_buffer_sz[MPI2_DIAG_BUF_TYPE_TRACE];
+               } else
+                       diag_register.requested_buffer_size = (1024 * 1024);
+
                diag_register.unique_id = 0x7075900;
                ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0;
                _ctl_diag_register_2(ioc,  &diag_register);
index c8e512b..3f0797e 100644 (file)
@@ -10193,6 +10193,8 @@ scsih_scan_start(struct Scsi_Host *shost)
        int rc;
        if (diag_buffer_enable != -1 && diag_buffer_enable != 0)
                mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable);
+       else if (ioc->manu_pg11.HostTraceBufferMaxSizeKB != 0)
+               mpt3sas_enable_diag_buffer(ioc, 1);
 
        if (disable_discovery > 0)
                return;