[PATCH 1/2] megaraid_sas: Add High Availability clustering support using shared Logical Disks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



James/linux-scsi,

The following patch for megaraid_sas will add support for High
Availability (HA)/clustering using shared Logical Disks.

Signed-off-by: Adam Radford <aradford@xxxxxxxxx>

diff -Naur scsi-misc.old/drivers/scsi/megaraid/megaraid_sas_base.c
scsi-misc.new/drivers/scsi/megaraid/megaraid_sas_base.c
--- scsi-misc.old/drivers/scsi/megaraid/megaraid_sas_base.c 2013-08-31
16:17:56.907172388 -0700
+++ scsi-misc.new/drivers/scsi/megaraid/megaraid_sas_base.c 2013-08-31
16:23:31.077143117 -0700
@@ -92,6 +92,8 @@

 int megasas_transition_to_ready(struct megasas_instance *instance, int ocr);
 static int megasas_get_pd_list(struct megasas_instance *instance);
+static int megasas_ld_list_query(struct megasas_instance *instance,
+ u8 query_type);
 static int megasas_issue_init_mfi(struct megasas_instance *instance);
 static int megasas_register_aen(struct megasas_instance *instance,
  u32 seq_num, u32 class_locale_word);
@@ -3271,6 +3273,84 @@
 }

 /**
+ * megasas_ld_list_query - Returns FW's ld_list structure
+ * @instance: Adapter soft state
+ * @ld_list: ld_list structure
+ *
+ * Issues an internal command (DCMD) to get the FW's controller PD
+ * list structure.  This information is mainly used to find out SYSTEM
+ * supported by the FW.
+ */
+static int
+megasas_ld_list_query(struct megasas_instance *instance, u8 query_type)
+{
+ int ret = 0, ld_index = 0, ids = 0;
+ struct megasas_cmd *cmd;
+ struct megasas_dcmd_frame *dcmd;
+ struct MR_LD_TARGETID_LIST *ci;
+ dma_addr_t ci_h = 0;
+
+ cmd = megasas_get_cmd(instance);
+
+ if (!cmd) {
+ printk(KERN_WARNING
+       "megasas:(megasas_ld_list_query): Failed to get cmd\n");
+ return -ENOMEM;
+ }
+
+ dcmd = &cmd->frame->dcmd;
+
+ ci = pci_alloc_consistent(instance->pdev,
+  sizeof(struct MR_LD_TARGETID_LIST), &ci_h);
+
+ if (!ci) {
+ printk(KERN_WARNING
+       "megasas: Failed to alloc mem for ld_list_query\n");
+ megasas_return_cmd(instance, cmd);
+ return -ENOMEM;
+ }
+
+ memset(ci, 0, sizeof(*ci));
+ memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
+
+ dcmd->mbox.b[0] = query_type;
+
+ dcmd->cmd = MFI_CMD_DCMD;
+ dcmd->cmd_status = 0xFF;
+ dcmd->sge_count = 1;
+ dcmd->flags = MFI_FRAME_DIR_READ;
+ dcmd->timeout = 0;
+ dcmd->data_xfer_len = sizeof(struct MR_LD_TARGETID_LIST);
+ dcmd->opcode = MR_DCMD_LD_LIST_QUERY;
+ dcmd->sgl.sge32[0].phys_addr = ci_h;
+ dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_TARGETID_LIST);
+ dcmd->pad_0  = 0;
+
+ if (!megasas_issue_polled(instance, cmd) && !dcmd->cmd_status) {
+ ret = 0;
+ } else {
+ /* On failure, call older LD list DCMD */
+ ret = 1;
+ }
+
+ if ((ret == 0) && (ci->count <= (MAX_LOGICAL_DRIVES))) {
+ memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
+ for (ld_index = 0; ld_index < ci->count; ld_index++) {
+ ids = ci->targetId[ld_index];
+ instance->ld_ids[ids] = ci->targetId[ld_index];
+ }
+
+ }
+
+ pci_free_consistent(instance->pdev, sizeof(struct MR_LD_TARGETID_LIST),
+    ci, ci_h);
+
+ megasas_return_cmd(instance, cmd);
+
+ return ret;
+}
+
+/**
  * megasas_get_controller_info - Returns FW's controller structure
  * @instance: Adapter soft state
  * @ctrl_info: Controller information structure
@@ -3648,7 +3728,9 @@
  megasas_get_pd_list(instance);

  memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS);
- megasas_get_ld_list(instance);
+ if (megasas_ld_list_query(instance,
+  MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
+ megasas_get_ld_list(instance);

  ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL);

@@ -5389,7 +5471,9 @@
  case MR_EVT_LD_OFFLINE:
  case MR_EVT_CFG_CLEARED:
  case MR_EVT_LD_DELETED:
- megasas_get_ld_list(instance);
+ if (megasas_ld_list_query(instance,
+ MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
+ megasas_get_ld_list(instance);
  for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
  for (j = 0;
  j < MEGASAS_MAX_DEV_PER_CHANNEL;
@@ -5399,7 +5483,7 @@
  (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;

  sdev1 = scsi_device_lookup(host,
- i + MEGASAS_MAX_LD_CHANNELS,
+ MEGASAS_MAX_PD_CHANNELS + i,
  j,
  0);

@@ -5418,7 +5502,9 @@
  doscan = 0;
  break;
  case MR_EVT_LD_CREATED:
- megasas_get_ld_list(instance);
+ if (megasas_ld_list_query(instance,
+ MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
+ megasas_get_ld_list(instance);
  for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
  for (j = 0;
  j < MEGASAS_MAX_DEV_PER_CHANNEL;
@@ -5427,14 +5513,14 @@
  (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;

  sdev1 = scsi_device_lookup(host,
- i+MEGASAS_MAX_LD_CHANNELS,
+ MEGASAS_MAX_PD_CHANNELS + i,
  j, 0);

  if (instance->ld_ids[ld_index] !=
  0xff) {
  if (!sdev1) {
  scsi_add_device(host,
- i + 2,
+ MEGASAS_MAX_PD_CHANNELS + i,
  j, 0);
  }
  }
@@ -5483,18 +5569,20 @@
  }
  }

- megasas_get_ld_list(instance);
+ if (megasas_ld_list_query(instance,
+  MR_LD_QUERY_TYPE_EXPOSED_TO_HOST))
+ megasas_get_ld_list(instance);
  for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
  for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) {
  ld_index =
  (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j;

  sdev1 = scsi_device_lookup(host,
- i+MEGASAS_MAX_LD_CHANNELS, j, 0);
+ MEGASAS_MAX_PD_CHANNELS + i, j, 0);
  if (instance->ld_ids[ld_index] != 0xff) {
  if (!sdev1) {
  scsi_add_device(host,
- i+2,
+ MEGASAS_MAX_PD_CHANNELS + i,
  j, 0);
  } else {
  scsi_device_put(sdev1);
diff -Naur scsi-misc.old/drivers/scsi/megaraid/megaraid_sas_fp.c
scsi-misc.new/drivers/scsi/megaraid/megaraid_sas_fp.c
--- scsi-misc.old/drivers/scsi/megaraid/megaraid_sas_fp.c 2013-08-31
16:17:56.908172637 -0700
+++ scsi-misc.new/drivers/scsi/megaraid/megaraid_sas_fp.c 2013-08-31
16:23:31.078140743 -0700
@@ -126,17 +126,17 @@
  return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx];
 }

-static u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map)
+u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map)
 {
  return map->raidMap.arMapInfo[ar].pd[arm];
 }

-static u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map)
+u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map)
 {
  return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef;
 }

-static u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map)
+u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map)
 {
  return map->raidMap.devHndlInfo[pd].curDevHdl;
 }
@@ -784,7 +784,7 @@
 MR_BuildRaidContext(struct megasas_instance *instance,
     struct IO_REQUEST_INFO *io_info,
     struct RAID_CONTEXT *pRAID_Context,
-    struct MR_FW_RAID_MAP_ALL *map)
+    struct MR_FW_RAID_MAP_ALL *map, u8 **raidLUN)
 {
  struct MR_LD_RAID  *raid;
  u32         ld, stripSize, stripe_mask;
@@ -977,6 +977,9 @@
  pRAID_Context->regLockRowLBA    = regStart;
  pRAID_Context->regLockLength    = regSize;
  pRAID_Context->configSeqNum = raid->seqNum;
+ /* save pointer to raid->LUN array */
+ *raidLUN = raid->LUN;
+

  /*Get Phy Params only if FP capable, or else leave it to MR firmware
   to do the calculation.*/
diff -Naur scsi-misc.old/drivers/scsi/megaraid/megaraid_sas_fusion.c
scsi-misc.new/drivers/scsi/megaraid/megaraid_sas_fusion.c
--- scsi-misc.old/drivers/scsi/megaraid/megaraid_sas_fusion.c
2013-08-31 16:17:56.909172648 -0700
+++ scsi-misc.new/drivers/scsi/megaraid/megaraid_sas_fusion.c
2013-08-31 16:24:51.861078589 -0700
@@ -77,9 +77,12 @@
 MR_BuildRaidContext(struct megasas_instance *instance,
     struct IO_REQUEST_INFO *io_info,
     struct RAID_CONTEXT *pRAID_Context,
-    struct MR_FW_RAID_MAP_ALL *map);
+    struct MR_FW_RAID_MAP_ALL *map, u8 **raidLUN);
 u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map);
 struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
+u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map);
+u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map);
+u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map);

 u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);

@@ -652,6 +655,10 @@
  (instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
  init_frame->driver_operations.
  mfi_capabilities.support_additional_msix = 1;
+ /* driver supports HA / Remote LUN over Fast Path interface */
+ init_frame->driver_operations.mfi_capabilities.support_fp_remote_lun
+ = 1;
+

  init_frame->queue_info_new_phys_addr_lo = ioc_init_handle;
  init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST);
@@ -1410,6 +1417,7 @@
  struct IO_REQUEST_INFO io_info;
  struct fusion_context *fusion;
  struct MR_FW_RAID_MAP_ALL *local_map_ptr;
+ u8 *raidLUN;

  device_id = MEGASAS_DEV_INDEX(instance, scp);

@@ -1494,7 +1502,7 @@
  } else {
  if (MR_BuildRaidContext(instance, &io_info,
  &io_request->RaidContext,
- local_map_ptr))
+ local_map_ptr, &raidLUN))
  fp_possible = io_info.fpOkForIo;
  }

@@ -1537,6 +1545,8 @@
  scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG;
  cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle;
  io_request->DevHandle = io_info.devHandle;
+ /* populate the LUN field */
+ memcpy(io_request->LUN, raidLUN, 8);
  } else {
  io_request->RaidContext.timeoutValue =
  local_map_ptr->raidMap.fpPdIoTimeoutSec;
@@ -1579,6 +1589,11 @@
  u16 pd_index = 0;
  struct MR_FW_RAID_MAP_ALL *local_map_ptr;
  struct fusion_context *fusion = instance->ctrl_context;
+ u8                          span, physArm;
+ u16                         devHandle;
+ u32                         ld, arRef, pd;
+ struct MR_LD_RAID                  *raid;
+ struct RAID_CONTEXT                *pRAID_Context;

  io_request = cmd->io_request;
  device_id = MEGASAS_DEV_INDEX(instance, scmd);
@@ -1586,6 +1601,9 @@
  +scmd->device->id;
  local_map_ptr = fusion->ld_map[(instance->map_id & 1)];

+ io_request->DataLength = scsi_bufflen(scmd);
+
+
  /* Check if this is a system PD I/O */
  if (scmd->device->channel < MEGASAS_MAX_PD_CHANNELS &&
     instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
@@ -1623,6 +1641,54 @@
  scmd->request->timeout / HZ;
  }
  } else {
+ if (scmd->device->channel < MEGASAS_MAX_PD_CHANNELS)
+ goto NonFastPath;
+
+ ld = MR_TargetIdToLdGet(device_id, local_map_ptr);
+ if ((ld >= MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io))
+ goto NonFastPath;
+
+ raid = MR_LdRaidGet(ld, local_map_ptr);
+
+ /* check if this LD is FP capable */
+ if (!(raid->capability.fpNonRWCapable))
+ /* not FP capable, send as non-FP */
+ goto NonFastPath;
+
+ /* get RAID_Context pointer */
+ pRAID_Context = &io_request->RaidContext;
+
+ /* set RAID context values */
+ pRAID_Context->regLockFlags     = REGION_TYPE_SHARED_READ;
+ pRAID_Context->timeoutValue     = raid->fpIoTimeoutForLd;
+ pRAID_Context->VirtualDiskTgtId = device_id;
+ pRAID_Context->regLockRowLBA    = 0;
+ pRAID_Context->regLockLength    = 0;
+ pRAID_Context->configSeqNum     = raid->seqNum;
+
+ /* get the DevHandle for the PD (since this is
+   fpNonRWCapable, this is a single disk RAID0) */
+ span = physArm = 0;
+ arRef = MR_LdSpanArrayGet(ld, span, local_map_ptr);
+ pd = MR_ArPdGet(arRef, physArm, local_map_ptr);
+ devHandle = MR_PdDevHandleGet(pd, local_map_ptr);
+
+ /* build request descriptor */
+ cmd->request_desc->SCSIIO.RequestFlags =
+ (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY <<
+ MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
+ cmd->request_desc->SCSIIO.DevHandle = devHandle;
+
+ /* populate the LUN field */
+ memcpy(io_request->LUN, raid->LUN, 8);
+
+ /* build the raidScsiIO structure */
+ io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+ io_request->DevHandle = devHandle;
+
+ return;
+
+NonFastPath:
  io_request->Function  = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST;
  io_request->DevHandle = device_id;
  cmd->request_desc->SCSIIO.RequestFlags =
@@ -1631,7 +1697,6 @@
  }
  io_request->RaidContext.VirtualDiskTgtId = device_id;
  io_request->LUN[1] = scmd->device->lun;
- io_request->DataLength = scsi_bufflen(scmd);
 }

 /**
diff -Naur scsi-misc.old/drivers/scsi/megaraid/megaraid_sas_fusion.h
scsi-misc.new/drivers/scsi/megaraid/megaraid_sas_fusion.h
--- scsi-misc.old/drivers/scsi/megaraid/megaraid_sas_fusion.h
2013-08-31 16:17:56.909172648 -0700
+++ scsi-misc.new/drivers/scsi/megaraid/megaraid_sas_fusion.h
2013-08-31 16:23:31.079140393 -0700
@@ -527,7 +527,8 @@
  u32     fpReadCapable:1;
  u32     fpWriteAcrossStripe:1;
  u32     fpReadAcrossStripe:1;
- u32     reserved4:8;
+ u32 fpNonRWCapable:1;
+ u32     reserved4:7;
  } capability;
  u32     reserved6;
  u64     size;
@@ -551,7 +552,9 @@
  u32 reserved:31;
  } flags;

- u8      reserved3[0x5C];
+ u8 LUN[8]; /* 0x24 8 byte LUN field used for SCSI IO's */
+ u8 fpIoTimeoutForLd;/*0x2C timeout value used by driver in FP IO*/
+ u8      reserved3[0x80-0x2D]; /* 0x2D */
 };

 struct MR_LD_SPAN_MAP {
diff -Naur scsi-misc.old/drivers/scsi/megaraid/megaraid_sas.h
scsi-misc.new/drivers/scsi/megaraid/megaraid_sas.h
--- scsi-misc.old/drivers/scsi/megaraid/megaraid_sas.h 2013-08-31
16:17:56.910114725 -0700
+++ scsi-misc.new/drivers/scsi/megaraid/megaraid_sas.h 2013-08-31
16:23:31.079140393 -0700
@@ -170,6 +170,7 @@

 #define MR_DCMD_CTRL_GET_INFO 0x01010000
 #define MR_DCMD_LD_GET_LIST 0x03010000
+#define MR_DCMD_LD_LIST_QUERY 0x03010100

 #define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000
 #define MR_FLUSH_CTRL_CACHE 0x01
@@ -345,6 +346,15 @@
  MR_PD_QUERY_TYPE_EXPOSED_TO_HOST    = 5,
 };

+enum MR_LD_QUERY_TYPE {
+ MR_LD_QUERY_TYPE_ALL         = 0,
+ MR_LD_QUERY_TYPE_EXPOSED_TO_HOST = 1,
+ MR_LD_QUERY_TYPE_USED_TGT_IDS    = 2,
+ MR_LD_QUERY_TYPE_CLUSTER_ACCESS  = 3,
+ MR_LD_QUERY_TYPE_CLUSTER_LOCALE  = 4,
+};
+
+
 #define MR_EVT_CFG_CLEARED                              0x0004
 #define MR_EVT_LD_STATE_CHANGE                          0x0051
 #define MR_EVT_PD_INSERTED                              0x005b
@@ -435,6 +445,14 @@
  } ldList[MAX_LOGICAL_DRIVES];
 } __packed;

+struct MR_LD_TARGETID_LIST {
+ u32 size;
+ u32 count;
+ u8 pad[3];
+ u8 targetId[MAX_LOGICAL_DRIVES];
+};
+
+
 /*
  * SAS controller properties
  */
@@ -863,7 +881,7 @@
  * ===============================
  */
 #define MEGASAS_MAX_PD_CHANNELS 2
-#define MEGASAS_MAX_LD_CHANNELS 2
+#define MEGASAS_MAX_LD_CHANNELS 1
 #define MEGASAS_MAX_CHANNELS (MEGASAS_MAX_PD_CHANNELS + \
  MEGASAS_MAX_LD_CHANNELS)
 #define MEGASAS_MAX_DEV_PER_CHANNEL 128

Attachment: megaraid_sas.patch1
Description: Binary data


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]
  Powered by Linux