Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 23 Mar 2017 07:56:13 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r315831 - stable/10/sys/dev/firewire
Message-ID:  <201703230756.v2N7uDHr085810@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: avg
Date: Thu Mar 23 07:56:13 2017
New Revision: 315831
URL: https://svnweb.freebsd.org/changeset/base/315831

Log:
  MFC r314864: firewire/sbp: try to improve locking, plus a few style nits

Modified:
  stable/10/sys/dev/firewire/sbp.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/firewire/sbp.c
==============================================================================
--- stable/10/sys/dev/firewire/sbp.c	Thu Mar 23 07:56:07 2017	(r315830)
+++ stable/10/sys/dev/firewire/sbp.c	Thu Mar 23 07:56:13 2017	(r315831)
@@ -455,7 +455,6 @@ sbp_alloc_lun(struct sbp_target *target)
 	int maxlun, lun, i;
 
 	sbp = target->sbp;
-	SBP_LOCK_ASSERT(sbp);
 	crom_init_context(&cc, target->fwdev->csrrom);
 	/* XXX shoud parse appropriate unit directories only */
 	maxlun = -1;
@@ -588,7 +587,9 @@ END_DEBUG
 				goto next;
 			}
 			callout_init_mtx(&ocb->timer, &sbp->mtx, 0);
+			SBP_LOCK(sbp);
 			sbp_free_ocb(sdev, ocb);
+			SBP_UNLOCK(sbp);
 		}
 next:
 		crom_next(&cc);
@@ -718,9 +719,8 @@ END_DEBUG
 	&& crom_has_specver((fwdev)->csrrom, CSRVAL_ANSIT10, CSRVAL_T10SBP2))
 
 static void
-sbp_probe_target(void *arg)
+sbp_probe_target(struct sbp_target *target)
 {
-	struct sbp_target *target = (struct sbp_target *)arg;
 	struct sbp_softc *sbp = target->sbp;
 	struct sbp_dev *sdev;
 	int i, alive;
@@ -732,8 +732,6 @@ SBP_DEBUG(1)
 		(!alive) ? " not " : "");
 END_DEBUG
 
-	sbp = target->sbp;
-	SBP_LOCK_ASSERT(sbp);
 	sbp_alloc_lun(target);
 
 	/* XXX untimeout mgm_ocb and dequeue */
@@ -749,7 +747,9 @@ END_DEBUG
 			sbp_probe_lun(sdev);
 			sbp_show_sdev_info(sdev);
 
+			SBP_LOCK(sbp);
 			sbp_abort_all_ocbs(sdev, CAM_SCSI_BUS_RESET);
+			SBP_UNLOCK(sbp);
 			switch (sdev->status) {
 			case SBP_DEV_RESET:
 				/* new or revived target */
@@ -804,9 +804,9 @@ SBP_DEBUG(0)
 	printf("sbp_post_busreset\n");
 END_DEBUG
 	SBP_LOCK(sbp);
-	if ((sbp->sim->flags & SIMQ_FREEZED) == 0) {
+	if ((sbp->flags & SIMQ_FREEZED) == 0) {
 		xpt_freeze_simq(sbp->sim, /*count*/1);
-		sbp->sim->flags |= SIMQ_FREEZED;
+		sbp->flags |= SIMQ_FREEZED;
 	}
 	microtime(&sbp->last_busreset);
 	SBP_UNLOCK(sbp);
@@ -831,19 +831,15 @@ END_DEBUG
 		sbp_cold --;
 
 	SBP_LOCK(sbp);
-#if 0
-	/*
-	 * XXX don't let CAM the bus rest.
-	 * CAM tries to do something with freezed (DEV_RETRY) devices.
-	 */
-	xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL);
-#endif
 
 	/* Garbage Collection */
 	for(i = 0 ; i < SBP_NUM_TARGETS ; i ++){
 		target = &sbp->targets[i];
+		if (target->fwdev == NULL)
+			continue;
+
 		STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link)
-			if (target->fwdev == NULL || target->fwdev == fwdev)
+			if (target->fwdev == fwdev)
 				break;
 		if (fwdev == NULL) {
 			/* device has removed in lower driver */
@@ -851,6 +847,7 @@ END_DEBUG
 			sbp_free_target(target);
 		}
 	}
+
 	/* traverse device list */
 	STAILQ_FOREACH(fwdev, &sbp->fd.fc->devices, link) {
 SBP_DEBUG(0)
@@ -877,12 +874,24 @@ END_DEBUG
 				continue;
 			}
 		}
-		sbp_probe_target((void *)target);
+
+		/*
+		 * It is safe to drop the lock here as the target is already
+		 * reserved, so there should be no contenders for it.
+		 * And the target is not yet exposed, so there should not be
+		 * any other accesses to it.
+		 * Finally, the list being iterated is protected somewhere else.
+		 */
+		SBP_UNLOCK(sbp);
+		sbp_probe_target(target);
+		SBP_LOCK(sbp);
 		if (target->num_lun == 0)
 			sbp_free_target(target);
 	}
-	xpt_release_simq(sbp->sim, /*run queue*/TRUE);
-	sbp->sim->flags &= ~SIMQ_FREEZED;
+	if ((sbp->flags & SIMQ_FREEZED) != 0) {
+		xpt_release_simq(sbp->sim, /*run queue*/TRUE);
+		sbp->flags &= ~SIMQ_FREEZED;
+	}
 	SBP_UNLOCK(sbp);
 }
 
@@ -989,30 +998,36 @@ sbp_next_dev(struct sbp_target *target, 
 static void
 sbp_cam_scan_lun(struct cam_periph *periph, union ccb *ccb)
 {
+	struct sbp_softc *sbp;
 	struct sbp_target *target;
 	struct sbp_dev *sdev;
 
 	sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr;
 	target = sdev->target;
-	SBP_LOCK_ASSERT(target->sbp);
+	sbp = target->sbp;
+	SBP_LOCK(sbp);
 SBP_DEBUG(0)
-	device_printf(sdev->target->sbp->fd.dev,
+	device_printf(sbp->fd.dev,
 		"%s:%s\n", __func__, sdev->bustgtlun);
 END_DEBUG
 	if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP) {
 		sdev->status = SBP_DEV_ATTACHED;
 	} else {
-		device_printf(sdev->target->sbp->fd.dev,
+		device_printf(sbp->fd.dev,
 			"%s:%s failed\n", __func__, sdev->bustgtlun);
 	}
 	sdev = sbp_next_dev(target, sdev->lun_id + 1);
 	if (sdev == NULL) {
+		SBP_UNLOCK(sbp);
 		free(ccb, M_SBP);
 		return;
 	}
 	/* reuse ccb */
 	xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI);
 	ccb->ccb_h.ccb_sdev_ptr = sdev;
+	ccb->ccb_h.flags |= CAM_DEV_QFREEZE;
+	SBP_UNLOCK(sbp);
+
 	xpt_action(ccb);
 	xpt_release_devq(sdev->path, sdev->freeze, TRUE);
 	sdev->freeze = 1;
@@ -1041,6 +1056,8 @@ END_DEBUG
 		printf("sbp_cam_scan_target: malloc failed\n");
 		return;
 	}
+	SBP_UNLOCK(target->sbp);
+
 	xpt_setup_ccb(&ccb->ccb_h, sdev->path, SCAN_PRI);
 	ccb->ccb_h.func_code = XPT_SCAN_LUN;
 	ccb->ccb_h.cbfcnp = sbp_cam_scan_lun;
@@ -1050,6 +1067,8 @@ END_DEBUG
 
 	/* The scan is in progress now. */
 	xpt_action(ccb);
+
+	SBP_LOCK(target->sbp);
 	xpt_release_devq(sdev->path, sdev->freeze, TRUE);
 	sdev->freeze = 1;
 }
@@ -2015,8 +2034,8 @@ END_DEBUG
 	sbp->fd.post_explore = sbp_post_explore;
 
 	if (fc->status != -1) {
-		sbp_post_busreset((void *)sbp);
-		sbp_post_explore((void *)sbp);
+		sbp_post_busreset(sbp);
+		sbp_post_explore(sbp);
 	}
 	SBP_LOCK(sbp);
 	xpt_async(AC_BUS_RESET, sbp->path, /*arg*/ NULL);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201703230756.v2N7uDHr085810>