scsi: aacraid: Retrieve Queue Depth from Adapter FW
authorRaghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Thu, 2 Feb 2017 23:53:26 +0000 (15:53 -0800)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 3 Feb 2017 15:35:03 +0000 (10:35 -0500)
Retrieved queue depth from fw and saved it for future use.
Only applicable for HBA1000 drives.

Signed-off-by: Raghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: Dave Carroll <David.Carroll@microsemi.com>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/aacraid/aachba.c
drivers/scsi/aacraid/aacraid.h

index b854c4928f6f2ca304834488a654794098dd7e09..20908a19ff90b1bbb27be1c6fbf07d984377b8f0 100644 (file)
@@ -1516,6 +1516,77 @@ static int aac_scsi_32_64(struct fib * fib, struct scsi_cmnd * cmd)
        return aac_scsi_32(fib, cmd);
 }
 
+int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target)
+{
+       struct fib *fibptr;
+       struct aac_srb *srbcmd;
+       struct sgmap64 *sg64;
+       struct aac_ciss_identify_pd *identify_resp;
+       dma_addr_t addr;
+       u32 vbus, vid;
+       u16 fibsize, datasize;
+       int rcode = -ENOMEM;
+
+       fibptr = aac_fib_alloc(dev);
+       if (!fibptr)
+               goto out;
+
+       fibsize = sizeof(struct aac_srb) -
+                       sizeof(struct sgentry) + sizeof(struct sgentry64);
+       datasize = sizeof(struct aac_ciss_identify_pd);
+
+       identify_resp =  pci_alloc_consistent(dev->pdev, datasize, &addr);
+
+       if (!identify_resp)
+               goto fib_free_ptr;
+
+       vbus = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceBus);
+       vid = (u32)le16_to_cpu(dev->supplement_adapter_info.VirtDeviceTarget);
+
+       aac_fib_init(fibptr);
+
+       srbcmd = (struct aac_srb *) fib_data(fibptr);
+       srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
+       srbcmd->channel  = cpu_to_le32(vbus);
+       srbcmd->id       = cpu_to_le32(vid);
+       srbcmd->lun      = 0;
+       srbcmd->flags    = cpu_to_le32(SRB_DataIn);
+       srbcmd->timeout  = cpu_to_le32(10);
+       srbcmd->retry_limit = 0;
+       srbcmd->cdb_size = cpu_to_le32(12);
+       srbcmd->count = cpu_to_le32(datasize);
+
+       memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
+       srbcmd->cdb[0] = 0x26;
+       srbcmd->cdb[2] = (u8)((AAC_MAX_LUN + target) & 0x00FF);
+       srbcmd->cdb[6] = CISS_IDENTIFY_PHYSICAL_DEVICE;
+
+       sg64 = (struct sgmap64 *)&srbcmd->sg;
+       sg64->count = cpu_to_le32(1);
+       sg64->sg[0].addr[1] = cpu_to_le32((u32)(((addr) >> 16) >> 16));
+       sg64->sg[0].addr[0] = cpu_to_le32((u32)(addr & 0xffffffff));
+       sg64->sg[0].count = cpu_to_le32(datasize);
+
+       rcode = aac_fib_send(ScsiPortCommand64,
+               fibptr, fibsize, FsaNormal, 1, 1, NULL, NULL);
+
+       if (identify_resp->current_queue_depth_limit <= 0 ||
+               identify_resp->current_queue_depth_limit > 32)
+               dev->hba_map[bus][target].qd_limit = 32;
+       else
+               dev->hba_map[bus][target].qd_limit =
+                       identify_resp->current_queue_depth_limit;
+
+       pci_free_consistent(dev->pdev, datasize, (void *)identify_resp, addr);
+
+       aac_fib_complete(fibptr);
+
+fib_free_ptr:
+       aac_fib_free(fibptr);
+out:
+       return rcode;
+}
+
 /**
  *     aac_update hba_map()-   update current hba map with data from FW
  *     @dev:   aac_dev structure
@@ -1565,6 +1636,9 @@ void aac_update_hba_map(struct aac_dev *dev,
                if (devtype != AAC_DEVTYPE_NATIVE_RAW)
                        goto update_devtype;
 
+               if (aac_issue_bmic_identify(dev, bus, target) < 0)
+                       dev->hba_map[bus][target].qd_limit = 32;
+
 update_devtype:
                dev->hba_map[bus][target].devtype = devtype;
        }
@@ -1711,8 +1785,10 @@ int aac_get_adapter_info(struct aac_dev* dev)
 
        /* reset all previous mapped devices (i.e. for init. after IOP_RESET) */
        for (bus = 0; bus < AAC_MAX_BUSES; bus++) {
-               for (target = 0; target < AAC_MAX_TARGETS; target++)
+               for (target = 0; target < AAC_MAX_TARGETS; target++) {
                        dev->hba_map[bus][target].devtype = 0;
+                       dev->hba_map[bus][target].qd_limit = 0;
+               }
        }
 
        /*
index 05884e62672b524ad36603fa8ca633765dc1bc11..02b0279bc91b7ba1566ee783a2dba1839f91b531 100644 (file)
@@ -74,7 +74,7 @@ enum {
 #define AAC_NUM_IO_FIB         (1024 - AAC_NUM_MGT_FIB)
 #define AAC_NUM_FIB            (AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB)
 
-#define AAC_MAX_LUN            (8)
+#define AAC_MAX_LUN            (256)
 
 #define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
 #define AAC_MAX_32BIT_SGBCOUNT ((unsigned short)256)
@@ -89,6 +89,7 @@ enum {
 
 #define CISS_REPORT_PHYSICAL_LUNS      0xc3
 #define WRITE_HOST_WELLNESS            0xa5
+#define CISS_IDENTIFY_PHYSICAL_DEVICE  0x15
 #define BMIC_IN                        0x26
 #define BMIC_OUT                       0x27
 
@@ -110,6 +111,82 @@ struct aac_ciss_phys_luns_resp {
  */
 #define AAC_MAX_HRRQ           64
 
+struct aac_ciss_identify_pd {
+       u8 scsi_bus;                    /* SCSI Bus number on controller */
+       u8 scsi_id;                     /* SCSI ID on this bus */
+       u16 block_size;                 /* sector size in bytes */
+       u32 total_blocks;               /* number for sectors on drive */
+       u32 reserved_blocks;            /* controller reserved (RIS) */
+       u8 model[40];                   /* Physical Drive Model */
+       u8 serial_number[40];           /* Drive Serial Number */
+       u8 firmware_revision[8];        /* drive firmware revision */
+       u8 scsi_inquiry_bits;           /* inquiry byte 7 bits */
+       u8 compaq_drive_stamp;          /* 0 means drive not stamped */
+       u8 last_failure_reason;
+
+       u8  flags;
+       u8  more_flags;
+       u8  scsi_lun;                   /* SCSI LUN for phys drive */
+       u8  yet_more_flags;
+       u8  even_more_flags;
+       u32 spi_speed_rules;            /* SPI Speed :Ultra disable diagnose */
+       u8  phys_connector[2];          /* connector number on controller */
+       u8  phys_box_on_bus;            /* phys enclosure this drive resides */
+       u8  phys_bay_in_box;            /* phys drv bay this drive resides */
+       u32 rpm;                        /* Drive rotational speed in rpm */
+       u8  device_type;                /* type of drive */
+       u8  sata_version;               /* only valid when drive_type is SATA */
+       u64 big_total_block_count;
+       u64 ris_starting_lba;
+       u32 ris_size;
+       u8  wwid[20];
+       u8  controller_phy_map[32];
+       u16 phy_count;
+       u8  phy_connected_dev_type[256];
+       u8  phy_to_drive_bay_num[256];
+       u16 phy_to_attached_dev_index[256];
+       u8  box_index;
+       u8  spitfire_support;
+       u16 extra_physical_drive_flags;
+       u8  negotiated_link_rate[256];
+       u8  phy_to_phy_map[256];
+       u8  redundant_path_present_map;
+       u8  redundant_path_failure_map;
+       u8  active_path_number;
+       u16 alternate_paths_phys_connector[8];
+       u8  alternate_paths_phys_box_on_port[8];
+       u8  multi_lun_device_lun_count;
+       u8  minimum_good_fw_revision[8];
+       u8  unique_inquiry_bytes[20];
+       u8  current_temperature_degreesC;
+       u8  temperature_threshold_degreesC;
+       u8  max_temperature_degreesC;
+       u8  logical_blocks_per_phys_block_exp;  /* phyblocksize = 512 * 2^exp */
+       u16 current_queue_depth_limit;
+       u8  switch_name[10];
+       u16 switch_port;
+       u8  alternate_paths_switch_name[40];
+       u8  alternate_paths_switch_port[8];
+       u16 power_on_hours;             /* valid only if gas gauge supported */
+       u16 percent_endurance_used;     /* valid only if gas gauge supported. */
+       u8  drive_authentication;
+       u8  smart_carrier_authentication;
+       u8  smart_carrier_app_fw_version;
+       u8  smart_carrier_bootloader_fw_version;
+       u8  SanitizeSecureEraseSupport;
+       u8  DriveKeyFlags;
+       u8  encryption_key_name[64];
+       u32 misc_drive_flags;
+       u16 dek_index;
+       u16 drive_encryption_flags;
+       u8  sanitize_maximum_time[6];
+       u8  connector_info_mode;
+       u8  connector_info_number[4];
+       u8  long_connector_name[64];
+       u8  device_unique_identifier[16];
+       u8  padto_2K[17];
+} __packed;
+
 /*
  * These macros convert from physical channels to virtual channels
  */
@@ -1032,6 +1109,7 @@ struct aac_hba_map_info {
        u8              devtype;        /* device type */
        u8              reset_state;    /* 0 - no reset, 1..x - */
                                        /* after xth TM LUN reset */
+       u16             qd_limit;
        u8              expose;         /*checks if to expose or not*/
 };
 
@@ -2240,6 +2318,7 @@ static inline unsigned int cap_to_cyls(sector_t capacity, unsigned divisor)
 int aac_acquire_irq(struct aac_dev *dev);
 void aac_free_irq(struct aac_dev *dev);
 int aac_report_phys_luns(struct aac_dev *dev, struct fib *fibptr);
+int aac_issue_bmic_identify(struct aac_dev *dev, u32 bus, u32 target);
 const char *aac_driverinfo(struct Scsi_Host *);
 void aac_fib_vector_assign(struct aac_dev *dev);
 struct fib *aac_fib_alloc(struct aac_dev *dev);