diff mbox series

[3/5] megaraid_sas: Early detection of VD deletion through RaidMap update

Message ID 20210317190824.3050-4-chandrakanth.patil@broadcom.com (mailing list archive)
State Changes Requested
Headers show
Series megaraid_sas: Update driver version to 07.717.01.00-rc1 | expand

Commit Message

Chandrakanth Patil March 17, 2021, 7:08 p.m. UTC
Consider in a case, when a VD is deleted and the targetID of
that VD is assigned to a newly created VD. If the sequence of
deletion/addition of VD happens very quickly, there is a possibility
that second event(VD add) occurs even before the driver processes the
first event(VD delete).
As event processing is done in deferred context the device list
remains same(but targetID is re-used) so driver will not learn the
VD deletion/additon and IOs meant for older VD will be directed to
new VD which may lead to data corruption.

In new design, driver will detect the deleted VD as soon as possible
based on the RaidMap update and blocks further IOs to that device.

Signed-off-by: Kashyap Desai <kashyap.desai@broadcom.com>
Signed-off-by: Chandrakanth Patil <chandrakanth.patil@broadcom.com>
---
 drivers/scsi/megaraid/megaraid_sas.h      |  3 ++
 drivers/scsi/megaraid/megaraid_sas_base.c | 61 ++++++++++++++++++++++-
 drivers/scsi/megaraid/megaraid_sas_fp.c   |  6 ++-
 3 files changed, 67 insertions(+), 3 deletions(-)

Comments

kernel test robot March 17, 2021, 8:55 p.m. UTC | #1
Hi Chandrakanth,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v5.12-rc3]
[cannot apply to mkp-scsi/for-next scsi/for-next next-20210317]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Chandrakanth-Patil/megaraid_sas-Update-driver-version-to-07-717-01-00-rc1/20210318-031205
base:    1e28eed17697bcf343c6743f0028cc3b5dd88bf0
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/dadb835ed01309bcd9a8d51a01ad4467dc71aea6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Chandrakanth-Patil/megaraid_sas-Update-driver-version-to-07-717-01-00-rc1/20210318-031205
        git checkout dadb835ed01309bcd9a8d51a01ad4467dc71aea6
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=arm64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

>> drivers/scsi/megaraid/megaraid_sas_base.c:3502:1: warning: no previous prototype for 'megasas_set_sdev_removed_by_fw' [-Wmissing-prototypes]
    3502 | megasas_set_sdev_removed_by_fw(struct megasas_instance *instance)
         | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


vim +/megasas_set_sdev_removed_by_fw +3502 drivers/scsi/megaraid/megaraid_sas_base.c

  3500	
  3501	void
> 3502	megasas_set_sdev_removed_by_fw(struct megasas_instance *instance)
  3503	{
  3504		struct scsi_device *sdev;
  3505		struct MR_PRIV_DEVICE *mr_device_priv_data;
  3506		uint channel, id, i;
  3507	
  3508		for (i = 0; (i < MEGASAS_MAX_LD_IDS); i++) {
  3509			if (instance->ld_ids_prev[i] != 0xff &&
  3510			    instance->ld_ids_from_raidmap[i] == 0xff) {
  3511				channel = MEGASAS_MAX_PD_CHANNELS +
  3512						(instance->ld_ids_prev[i] /
  3513						MEGASAS_MAX_DEV_PER_CHANNEL);
  3514				id = (instance->ld_ids_prev[i] %
  3515					MEGASAS_MAX_DEV_PER_CHANNEL);
  3516	
  3517				if (megasas_dbg_lvl & LD_PD_DEBUG)
  3518					dev_info(&instance->pdev->dev,
  3519						 "index %d old 0x%x new 0x%x from %s\n",
  3520						 i, instance->ld_ids_prev[i],
  3521						 instance->ld_ids_from_raidmap[i],
  3522						 __func__);
  3523	
  3524				sdev = scsi_device_lookup(instance->host, channel, id, 0);
  3525				if (sdev) {
  3526					mr_device_priv_data = sdev->hostdata;
  3527					mr_device_priv_data->device_removed_by_fw = true;
  3528					scsi_device_put(sdev);
  3529				}
  3530			}
  3531		}
  3532	}
  3533	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
kernel test robot March 17, 2021, 10:53 p.m. UTC | #2
Hi Chandrakanth,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on v5.12-rc3]
[cannot apply to mkp-scsi/for-next scsi/for-next next-20210317]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Chandrakanth-Patil/megaraid_sas-Update-driver-version-to-07-717-01-00-rc1/20210318-031205
base:    1e28eed17697bcf343c6743f0028cc3b5dd88bf0
config: x86_64-randconfig-s022-20210317 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce:
        # apt-get install sparse
        # sparse version: v0.6.3-277-gc089cd2d-dirty
        # https://github.com/0day-ci/linux/commit/dadb835ed01309bcd9a8d51a01ad4467dc71aea6
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Chandrakanth-Patil/megaraid_sas-Update-driver-version-to-07-717-01-00-rc1/20210318-031205
        git checkout dadb835ed01309bcd9a8d51a01ad4467dc71aea6
        # save the attached .config to linux build tree
        make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=x86_64 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>


sparse warnings: (new ones prefixed by >>)
   drivers/scsi/megaraid/megaraid_sas_base.c:117:5: sparse: sparse: symbol 'host_tagset_enable' was not declared. Should it be static?
   drivers/scsi/megaraid/megaraid_sas_base.c:4605:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:4605:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:4605:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:4856:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:4856:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:4856:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:6671:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:6671:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:6671:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:4512:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:4512:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:4512:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:282:31: sparse: sparse: restricted __le16 degrades to integer
   drivers/scsi/megaraid/megaraid_sas_base.c:288:31: sparse: sparse: cast from restricted __le16
   drivers/scsi/megaraid/megaraid_sas_base.c:414:29: sparse: sparse: cast to restricted __le32
   drivers/scsi/megaraid/megaraid_sas_base.c:1224:32: sparse: sparse: incorrect type in assignment (different base types) @@     expected unsigned int [usertype] opcode @@     got restricted __le32 [usertype] opcode @@
   drivers/scsi/megaraid/megaraid_sas_base.c:1224:32: sparse:     expected unsigned int [usertype] opcode
   drivers/scsi/megaraid/megaraid_sas_base.c:1224:32: sparse:     got restricted __le32 [usertype] opcode
   drivers/scsi/megaraid/megaraid_sas_base.c:2003:33: sparse: sparse: cast to restricted __le32
   drivers/scsi/megaraid/megaraid_sas_base.c:2044:34: sparse: sparse: cast to restricted __le32
>> drivers/scsi/megaraid/megaraid_sas_base.c:3502:1: sparse: sparse: symbol 'megasas_set_sdev_removed_by_fw' was not declared. Should it be static?
   drivers/scsi/megaraid/megaraid_sas_base.c:4736:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:4736:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:4736:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:4975:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:4975:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:4975:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:5160:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:5160:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:5160:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:5242:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:5242:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:5242:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:6224:42: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/scsi/megaraid/megaraid_sas_base.c:6223:57: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected unsigned int [noderef] [usertype] __iomem * @@     got unsigned int [usertype] * @@
   drivers/scsi/megaraid/megaraid_sas_base.c:6223:57: sparse:     expected unsigned int [noderef] [usertype] __iomem *
   drivers/scsi/megaraid/megaraid_sas_base.c:6223:57: sparse:     got unsigned int [usertype] *
   drivers/scsi/megaraid/megaraid_sas_base.c:6228:34: sparse: sparse: cast removes address space '__iomem' of expression
   drivers/scsi/megaraid/megaraid_sas_base.c:6227:57: sparse: sparse: incorrect type in assignment (different address spaces) @@     expected unsigned int [noderef] [usertype] __iomem * @@     got unsigned int [usertype] * @@
   drivers/scsi/megaraid/megaraid_sas_base.c:6227:57: sparse:     expected unsigned int [noderef] [usertype] __iomem *
   drivers/scsi/megaraid/megaraid_sas_base.c:6227:57: sparse:     got unsigned int [usertype] *
   drivers/scsi/megaraid/megaraid_sas_base.c:6535:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:6535:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:6535:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:6749:21: sparse: sparse: incorrect type in assignment (different base types) @@     expected restricted __le16 [usertype] flags @@     got int @@
   drivers/scsi/megaraid/megaraid_sas_base.c:6749:21: sparse:     expected restricted __le16 [usertype] flags
   drivers/scsi/megaraid/megaraid_sas_base.c:6749:21: sparse:     got int
   drivers/scsi/megaraid/megaraid_sas_base.c:7505:44: sparse: sparse: restricted __le32 degrades to integer
   drivers/scsi/megaraid/megaraid_sas_base.c:8122:23: sparse: sparse: incorrect type in assignment (different base types) @@     expected int crash_support @@     got restricted __le32 @@
   drivers/scsi/megaraid/megaraid_sas_base.c:8122:23: sparse:     expected int crash_support
   drivers/scsi/megaraid/megaraid_sas_base.c:8122:23: sparse:     got restricted __le32
   drivers/scsi/megaraid/megaraid_sas_base.c:8206:31: sparse: sparse: invalid assignment: &=
   drivers/scsi/megaraid/megaraid_sas_base.c:8206:31: sparse:    left side has type restricted __le16
   drivers/scsi/megaraid/megaraid_sas_base.c:8206:31: sparse:    right side has type int
   drivers/scsi/megaraid/megaraid_sas_base.c:8739:46: sparse: sparse: restricted __le32 degrades to integer

Please review and possibly fold the followup patch.

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h
index 0f808d63580e..d7185aa21eb5 100644
--- a/drivers/scsi/megaraid/megaraid_sas.h
+++ b/drivers/scsi/megaraid/megaraid_sas.h
@@ -2023,6 +2023,7 @@  union megasas_frame {
 struct MR_PRIV_DEVICE {
 	bool is_tm_capable;
 	bool tm_busy;
+	bool device_removed_by_fw;
 	atomic_t r1_ldio_hint;
 	u8 interface_type;
 	u8 task_abort_tmo;
@@ -2323,6 +2324,8 @@  struct megasas_instance {
 	struct megasas_pd_list          pd_list[MEGASAS_MAX_PD];
 	struct megasas_pd_list          local_pd_list[MEGASAS_MAX_PD];
 	u8 ld_ids[MEGASAS_MAX_LD_IDS];
+	u8 ld_ids_prev[MEGASAS_MAX_LD_IDS];
+	u8 ld_ids_from_raidmap[MEGASAS_MAX_LD_IDS];
 	s8 init_id;
 
 	u16 max_num_sge;
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 7ab741f03b84..f3716f7e1d10 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -426,6 +426,12 @@  megasas_decode_evt(struct megasas_instance *instance)
 			(class_locale.members.locale),
 			format_class(class_locale.members.class),
 			evt_detail->description);
+
+	if (megasas_dbg_lvl & LD_PD_DEBUG)
+		dev_info(&instance->pdev->dev,
+			 "evt_detail.args.ld.target_id/index %d/%d\n",
+			 evt_detail->args.ld.target_id, evt_detail->args.ld.ld_index);
+
 }
 
 /*
@@ -1802,7 +1808,8 @@  megasas_queue_command(struct Scsi_Host *shost, struct scsi_cmnd *scmd)
 	}
 
 	mr_device_priv_data = scmd->device->hostdata;
-	if (!mr_device_priv_data) {
+	if (!mr_device_priv_data ||
+	    mr_device_priv_data->device_removed_by_fw) {
 		scmd->result = DID_NO_CONNECT << 16;
 		scmd->scsi_done(scmd);
 		return 0;
@@ -3491,6 +3498,39 @@  megasas_complete_abort(struct megasas_instance *instance,
 	}
 }
 
+void
+megasas_set_sdev_removed_by_fw(struct megasas_instance *instance)
+{
+	struct scsi_device *sdev;
+	struct MR_PRIV_DEVICE *mr_device_priv_data;
+	uint channel, id, i;
+
+	for (i = 0; (i < MEGASAS_MAX_LD_IDS); i++) {
+		if (instance->ld_ids_prev[i] != 0xff &&
+		    instance->ld_ids_from_raidmap[i] == 0xff) {
+			channel = MEGASAS_MAX_PD_CHANNELS +
+					(instance->ld_ids_prev[i] /
+					MEGASAS_MAX_DEV_PER_CHANNEL);
+			id = (instance->ld_ids_prev[i] %
+				MEGASAS_MAX_DEV_PER_CHANNEL);
+
+			if (megasas_dbg_lvl & LD_PD_DEBUG)
+				dev_info(&instance->pdev->dev,
+					 "index %d old 0x%x new 0x%x from %s\n",
+					 i, instance->ld_ids_prev[i],
+					 instance->ld_ids_from_raidmap[i],
+					 __func__);
+
+			sdev = scsi_device_lookup(instance->host, channel, id, 0);
+			if (sdev) {
+				mr_device_priv_data = sdev->hostdata;
+				mr_device_priv_data->device_removed_by_fw = true;
+				scsi_device_put(sdev);
+			}
+		}
+	}
+}
+
 /**
  * megasas_complete_cmd -	Completes a command
  * @instance:			Adapter soft state
@@ -3656,6 +3696,10 @@  megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 			megasas_sync_map_info(instance);
 			spin_unlock_irqrestore(instance->host->host_lock,
 					       flags);
+
+			if (instance->adapter_type >= INVADER_SERIES)
+				megasas_set_sdev_removed_by_fw(instance);
+
 			break;
 		}
 		if (opcode == MR_DCMD_CTRL_EVENT_GET_INFO ||
@@ -8764,8 +8808,10 @@  megasas_aen_polling(struct work_struct *work)
 	union megasas_evt_class_locale class_locale;
 	int event_type = 0;
 	u32 seq_num;
+	u16 ld_target_id;
 	int error;
 	u8  dcmd_ret = DCMD_SUCCESS;
+	struct scsi_device *sdev1;
 
 	if (!instance) {
 		printk(KERN_ERR "invalid instance!\n");
@@ -8788,12 +8834,23 @@  megasas_aen_polling(struct work_struct *work)
 			break;
 
 		case MR_EVT_LD_OFFLINE:
-		case MR_EVT_CFG_CLEARED:
 		case MR_EVT_LD_DELETED:
+			ld_target_id = instance->evt_detail->args.ld.target_id;
+			sdev1 = scsi_device_lookup(instance->host,
+						   MEGASAS_MAX_PD_CHANNELS +
+						   (ld_target_id / MEGASAS_MAX_DEV_PER_CHANNEL),
+						   (ld_target_id - MEGASAS_MAX_DEV_PER_CHANNEL),
+						   0);
+			if (sdev1)
+				megasas_remove_scsi_device(sdev1);
+
+			event_type = SCAN_VD_CHANNEL;
+			break;
 		case MR_EVT_LD_CREATED:
 			event_type = SCAN_VD_CHANNEL;
 			break;
 
+		case MR_EVT_CFG_CLEARED:
 		case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED:
 		case MR_EVT_FOREIGN_CFG_IMPORTED:
 		case MR_EVT_LD_STATE_CHANGE:
diff --git a/drivers/scsi/megaraid/megaraid_sas_fp.c b/drivers/scsi/megaraid/megaraid_sas_fp.c
index b6c08d620033..470b9797dd65 100644
--- a/drivers/scsi/megaraid/megaraid_sas_fp.c
+++ b/drivers/scsi/megaraid/megaraid_sas_fp.c
@@ -349,6 +349,10 @@  u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id)
 
 	num_lds = le16_to_cpu(drv_map->raidMap.ldCount);
 
+	memcpy(instance->ld_ids_prev,
+	       instance->ld_ids_from_raidmap,
+	       sizeof(instance->ld_ids_from_raidmap));
+	memset(instance->ld_ids_from_raidmap, 0xff, MEGASAS_MAX_LD_IDS);
 	/*Convert Raid capability values to CPU arch */
 	for (i = 0; (num_lds > 0) && (i < MAX_LOGICAL_DRIVES_EXT); i++) {
 		ld = MR_TargetIdToLdGet(i, drv_map);
@@ -359,7 +363,7 @@  u8 MR_ValidateMapInfo(struct megasas_instance *instance, u64 map_id)
 
 		raid = MR_LdRaidGet(ld, drv_map);
 		le32_to_cpus((u32 *)&raid->capability);
-
+		instance->ld_ids_from_raidmap[ld] = i;
 		num_lds--;
 	}