PERFORCE change 116448 for review

Scott Long scottl at FreeBSD.org
Fri Mar 23 21:25:47 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=116448

Change 116448 by scottl at scottl-x64 on 2007/03/23 21:25:11

	Finalize the API for cam_periph_lock/unlock and
	cam_periph_acquire/release.  cam_periph_lock() locks the periph
	using the SIM mutex.  cam_periph_acquire() increments the refcount
	on the periph using the XPT topology lock.  More work is needed to
	make the topology lock cover everything that is needed so that
	periph and SIM removal is safe.  It may also be prudent for
	cam_periph_acquire() to look up the periph in the global list to
	make sure it's still valid.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/cam_periph.c#16 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_periph.h#9 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_cd.c#9 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_ch.c#7 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_da.c#23 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_pass.c#17 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_pt.c#6 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_sa.c#9 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_ses.c#10 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sys/cam/cam_periph.c#16 (text+ko) ====

@@ -280,15 +280,13 @@
 cam_status
 cam_periph_acquire(struct cam_periph *periph)
 {
-	int s;
 
 	if (periph == NULL)
 		return(CAM_REQ_CMP_ERR);
 
-	s = splsoftcam();
-	mtx_assert(periph->sim->mtx, MA_OWNED);
+	xpt_lock_buses();
 	periph->refcount++;
-	splx(s);
+	xpt_unlock_buses();
 
 	return(CAM_REQ_CMP);
 }
@@ -296,18 +294,16 @@
 void
 cam_periph_release(struct cam_periph *periph)
 {
-	int s;
 
 	if (periph == NULL)
 		return;
 
-	s = splsoftcam();
-	mtx_assert(periph->sim->mtx, MA_OWNED);
+	xpt_lock_buses();
 	if ((--periph->refcount == 0)
 	 && (periph->flags & CAM_PERIPH_INVALID)) {
 		camperiphfree(periph);
 	}
-	splx(s);
+	xpt_unlock_buses();
 
 }
 
@@ -430,9 +426,7 @@
 void
 cam_periph_invalidate(struct cam_periph *periph)
 {
-	int s;
 
-	s = splsoftcam();
 	/*
 	 * We only call this routine the first time a peripheral is
 	 * invalidated.  The oninvalidate() routine is always called at
@@ -445,11 +439,12 @@
 	periph->flags |= CAM_PERIPH_INVALID;
 	periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND;
 
+	xpt_lock_buses();
 	if (periph->refcount == 0)
 		camperiphfree(periph);
 	else if (periph->refcount < 0)
 		printf("cam_invalidate_periph: refcount < 0!!\n");
-	splx(s);
+	xpt_unlock_buses();
 }
 
 static void
@@ -508,34 +503,12 @@
 /*
  * Wait interruptibly for an exclusive lock.
  */
-int
-cam_periph_lock(struct cam_periph *periph, int priority)
+void
+cam_periph_lock(struct cam_periph *periph)
 {
 
-	/*
-	 * Interlock the SIM lock with the XPT lock to protect against the
-	 * SIM going away unexpectedly while we are trying reference it.
-	xpt_lock_buses();
-	 */
-
-	/*
-	 * Now it's safe to take the SIM lock.
-	 */
 	mtx_lock(periph->sim->mtx);
-	/*
-	xpt_unlock_buses();
-	 */
-
-	/*
-	 * Increment the reference count on the peripheral.
-	 */
-	if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
-		mtx_unlock(periph->sim->mtx);
-		return(ENXIO);
-	}
-
 	periph->flags |= CAM_PERIPH_LOCKED;
-	return 0;
 }
 
 /*
@@ -544,9 +517,8 @@
 void
 cam_periph_unlock(struct cam_periph *periph)
 {
+
 	periph->flags &= ~CAM_PERIPH_LOCKED;
-
-	cam_periph_release(periph);
 	mtx_unlock(periph->sim->mtx);
 }
 
@@ -760,13 +732,10 @@
 {
 	struct ccb_hdr *ccb_h;
 	struct mtx *mtx;
-	int s;
 
+	mtx_assert(periph->sim->mtx, MA_OWNED);
 	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdgetccb\n"));
-	mtx_assert(periph->sim->mtx, MA_OWNED);
 
-	s = splsoftcam();
-	
 	while (SLIST_FIRST(&periph->ccb_list) == NULL) {
 		if (periph->immediate_priority > priority)
 			periph->immediate_priority = priority;
@@ -784,7 +753,6 @@
 
 	ccb_h = SLIST_FIRST(&periph->ccb_list);
 	SLIST_REMOVE_HEAD(&periph->ccb_list, periph_links.sle);
-	splx(s);
 	return ((union ccb *)ccb_h);
 }
 
@@ -881,10 +849,10 @@
 	struct cam_sim *sim;
 	int error;
  
+	mtx_assert(sim->mtx, MA_OWNED);
 	error = 0;
 	sim = xpt_path_sim(ccb->ccb_h.path);
 
-	mtx_assert(sim->mtx, MA_OWNED);
 	/*
 	 * If the user has supplied a stats structure, and if we understand
 	 * this particular type of ccb, record the transaction start.

==== //depot/projects/scottl-camlock/src/sys/cam/cam_periph.h#9 (text+ko) ====

@@ -141,7 +141,7 @@
 			    char *name, cam_periph_type type, struct cam_path *,
 			    ac_callback_t *, ac_code, void *arg);
 struct cam_periph *cam_periph_find(struct cam_path *path, char *name);
-int		cam_periph_lock(struct cam_periph *periph, int priority);
+void		cam_periph_lock(struct cam_periph *periph);
 void		cam_periph_unlock(struct cam_periph *periph);
 cam_status	cam_periph_acquire(struct cam_periph *periph);
 void		cam_periph_release(struct cam_periph *periph);

==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_cd.c#9 (text+ko) ====

@@ -978,9 +978,8 @@
 
 cdregisterexit:
 
-	/* Lock this peripheral until we are setup */
-	/* Can't block */
-	cam_periph_lock(periph, PRIBIO); 
+	/* Refcount this periph now that it's been created. */
+	(void)cam_periph_acquire(periph); 
 
 	if ((softc->flags & CD_FLAG_CHANGER) == 0)
 		xpt_schedule(periph, /*priority*/5);
@@ -995,8 +994,6 @@
 {
 	struct cam_periph *periph;
 	struct cd_softc *softc;
-	int error;
-	int s;
 
 	periph = (struct cam_periph *)dp->d_drv1;
 	if (periph == NULL)
@@ -1007,22 +1004,15 @@
 	/*
 	 * Grab splsoftcam and hold it until we lock the peripheral.
 	 */
-	s = splsoftcam();
 	if (softc->flags & CD_FLAG_INVALID) {
-		splx(s);
 		return(ENXIO);
 	}
 
-	if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) {
-		splx(s);
-		return (error);
-	}
-
-	splx(s);
-
 	if (cam_periph_acquire(periph) != CAM_REQ_CMP)
 		return(ENXIO);
 
+	cam_periph_lock(periph);
+
 	/*
 	 * Check for media, and set the appropriate flags.  We don't bail
 	 * if we don't have media, but then we don't allow anything but the
@@ -1030,11 +1020,10 @@
 	 */
 	cdcheckmedia(periph);
 
+	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n"));
 	cam_periph_unlock(periph);
 
-	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n"));
-
-	return (error);
+	return (0);
 }
 
 static int
@@ -1042,7 +1031,6 @@
 {
 	struct 	cam_periph *periph;
 	struct	cd_softc *softc;
-	int	error;
 
 	periph = (struct cam_periph *)dp->d_drv1;
 	if (periph == NULL)
@@ -1050,8 +1038,7 @@
 
 	softc = (struct cd_softc *)periph->softc;
 
-	if ((error = cam_periph_lock(periph, PRIBIO)) != 0)
-		return (error);
+	cam_periph_lock(periph);
 
 	if ((softc->flags & CD_FLAG_DISC_REMOVABLE) != 0)
 		cdprevent(periph, PR_ALLOW);
@@ -1905,7 +1892,7 @@
 
 	struct 	cam_periph *periph;
 	struct	cd_softc *softc;
-	int	error, nocopyout;
+	int	nocopyout, error = 0;
 
 	periph = (struct cam_periph *)dp->d_drv1;
 	if (periph == NULL)
@@ -1915,13 +1902,10 @@
 
 	softc = (struct cd_softc *)periph->softc;
 
+	cam_periph_lock(periph);
 	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, 
 		  ("trying to do ioctl %#lx\n", cmd));
 
-	error = cam_periph_lock(periph, PRIBIO | PCATCH);
-
-	if (error != 0)
-		return(error);
 	/*
 	 * If we don't have media loaded, check for it.  If still don't
 	 * have media loaded, we can only do a load or eject.
@@ -1936,11 +1920,10 @@
 	  && (cmd != CDIOCEJECT))
 	 && (IOCGROUP(cmd) == 'c')) {
 		error = cdcheckmedia(periph);
-		if (error != 0) {
-			cam_periph_unlock(periph);
-			return (error);
-		}
 	}
+	cam_periph_unlock(periph);
+	if (error != 0)
+		return (error);
 
 	nocopyout = 0;
 	switch (cmd) {
@@ -1956,12 +1939,14 @@
 			params.mode_buf = malloc(params.alloc_len, M_TEMP,
 						 M_WAITOK | M_ZERO);
 
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCPLAYTRACKS\n"));
 
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -1970,8 +1955,10 @@
 			page->audio.flags |= CD_PA_IMMED;
 			error = cdsetmode(periph, &params);
 			free(params.mode_buf, M_TEMP);
-			if (error)
+			if (error) {
+				cam_periph_unlock(periph);
 				break;
+			}
 
 			/*
 			 * This was originally implemented with the PLAY
@@ -2033,6 +2020,7 @@
 						     args->end_track,
 						     args->end_index);
 			}
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCPLAYMSF:
@@ -2046,12 +2034,14 @@
 			params.mode_buf = malloc(params.alloc_len, M_TEMP,
 						 M_WAITOK | M_ZERO);
 
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCPLAYMSF\n"));
 
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2060,8 +2050,10 @@
 			page->audio.flags |= CD_PA_IMMED;
 			error = cdsetmode(periph, &params);
 			free(params.mode_buf, M_TEMP);
-			if (error)
+			if (error) {
+				cam_periph_unlock(periph);
 				break;
+			}
 			error = cdplaymsf(periph,
 					  args->start_m,
 					  args->start_s,
@@ -2069,6 +2061,7 @@
 					  args->end_m,
 					  args->end_s,
 					  args->end_f);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCPLAYBLOCKS:
@@ -2078,16 +2071,19 @@
 			struct cd_mode_params params;
 			union cd_pages *page;
 
+			params.alloc_len = sizeof(union cd_mode_data_6_10);
+			params.mode_buf = malloc(params.alloc_len, M_TEMP,
+						 M_WAITOK | M_ZERO);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCPLAYBLOCKS\n"));
 
-			params.alloc_len = sizeof(union cd_mode_data_6_10);
-			params.mode_buf = malloc(params.alloc_len, M_TEMP,
-						 M_WAITOK | M_ZERO);
 
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2096,9 +2092,12 @@
 			page->audio.flags |= CD_PA_IMMED;
 			error = cdsetmode(periph, &params);
 			free(params.mode_buf, M_TEMP);
-			if (error)
+			if (error) {
+				cam_periph_unlock(periph);
 				break;
+			}
 			error = cdplay(periph, args->blk, args->len);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCREADSUBCHANNEL_SYSSPACE:
@@ -2111,12 +2110,13 @@
 			struct cd_sub_channel_info *data;
 			u_int32_t len = args->data_len;
 
+			data = malloc(sizeof(struct cd_sub_channel_info), 
+				      M_TEMP, M_WAITOK);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCREADSUBCHANNEL\n"));
 
-			data = malloc(sizeof(struct cd_sub_channel_info), 
-				      M_TEMP, M_WAITOK);
-
 			if ((len > sizeof(struct cd_sub_channel_info)) ||
 			    (len < sizeof(struct cd_sub_channel_header))) {
 				printf(
@@ -2125,6 +2125,7 @@
 					len);
 				error = EINVAL;
 				free(data, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 
@@ -2136,6 +2137,7 @@
 
 			if (error) {
 				free(data, M_TEMP);
+				cam_periph_unlock(periph);
 	 			break;
 			}
 			if (softc->quirks & CD_Q_BCD_TRACKS)
@@ -2144,6 +2146,7 @@
 			len = min(len, ((data->header.data_len[0] << 8) +
 				data->header.data_len[1] +
 				sizeof(struct cd_sub_channel_header)));
+			cam_periph_unlock(periph);
 			if (nocopyout == 0) {
 				if (copyout(data, args->data, len) != 0) {
 					error = EFAULT;
@@ -2159,15 +2162,18 @@
 		{
 			struct ioc_toc_header *th;
 
+			th = malloc(sizeof(struct ioc_toc_header), M_TEMP,
+				    M_WAITOK);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOREADTOCHEADER\n"));
 
-			th = malloc(sizeof(struct ioc_toc_header), M_TEMP,
-				    M_WAITOK);
 			error = cdreadtoc(periph, 0, 0, (u_int8_t *)th, 
 				          sizeof (*th), /*sense_flags*/0);
 			if (error) {
 				free(th, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			if (softc->quirks & CD_Q_BCD_TRACKS) {
@@ -2181,6 +2187,7 @@
 			th->len = ntohs(th->len);
 			bcopy(th, addr, sizeof(*th));
 			free(th, M_TEMP);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOREADTOCENTRYS:
@@ -2193,12 +2200,13 @@
 			u_int32_t len, readlen, idx, num;
 			u_int32_t starting_track = te->starting_track;
 
+			data = malloc(sizeof(*data), M_TEMP, M_WAITOK);
+			lead = malloc(sizeof(*lead), M_TEMP, M_WAITOK);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOREADTOCENTRYS\n"));
 
-			data = malloc(sizeof(*data), M_TEMP, M_WAITOK);
-			lead = malloc(sizeof(*lead), M_TEMP, M_WAITOK);
-
 			if (te->data_len < sizeof(struct cd_toc_entry)
 			 || (te->data_len % sizeof(struct cd_toc_entry)) != 0
 			 || (te->address_format != CD_MSF_FORMAT
@@ -2208,6 +2216,7 @@
 				       "returning EINVAL\n");
 				free(data, M_TEMP);
 				free(lead, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 
@@ -2217,6 +2226,7 @@
 			if (error) {
 				free(data, M_TEMP);
 				free(lead, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 
@@ -2239,6 +2249,7 @@
 				       "returning EINVAL\n");
 				free(data, M_TEMP);
 				free(lead, M_TEMP);
+				cam_periph_unlock(periph);
 				error = EINVAL;
 				break;
 			}
@@ -2260,6 +2271,7 @@
 				error = EINVAL;
 				free(data, M_TEMP);
 				free(lead, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			num = len / sizeof(struct cd_toc_entry);
@@ -2273,6 +2285,7 @@
 				if (error) {
 					free(data, M_TEMP);
 					free(lead, M_TEMP);
+					cam_periph_unlock(periph);
 					break;
 				}
 			}
@@ -2289,6 +2302,7 @@
 				if (error) {
 					free(data, M_TEMP);
 					free(lead, M_TEMP);
+					cam_periph_unlock(periph);
 					break;
 				}
 				data->entries[idx - starting_track] = 
@@ -2301,6 +2315,7 @@
 				}
 			}
 
+			cam_periph_unlock(periph);
 			error = copyout(data->entries, te->data, len);
 			free(data, M_TEMP);
 			free(lead, M_TEMP);
@@ -2314,17 +2329,19 @@
 			struct ioc_toc_header *th;
 			u_int32_t track;
 
+			data = malloc(sizeof(*data), M_TEMP, M_WAITOK);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOREADTOCENTRY\n"));
 
-			data = malloc(sizeof(*data), M_TEMP, M_WAITOK);
-
 			if (te->address_format != CD_MSF_FORMAT
 			    && te->address_format != CD_LBA_FORMAT) {
 				printf("error in readtocentry, "
 				       " returning EINVAL\n");
 				free(data, M_TEMP);
 				error = EINVAL;
+				cam_periph_unlock(periph);
 				break;
 			}
 
@@ -2333,6 +2350,7 @@
 					  sizeof (*th), /*sense_flags*/0);
 			if (error) {
 				free(data, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 
@@ -2355,6 +2373,7 @@
 				       " returning EINVAL\n");
 				free(data, M_TEMP);
 				error = EINVAL;
+				cam_periph_unlock(periph);
 				break;
 			}
 
@@ -2363,6 +2382,7 @@
 					  /*sense_flags*/0);
 			if (error) {
 				free(data, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 
@@ -2371,6 +2391,7 @@
 			bcopy(&data->entry, &te->entry,
 			      sizeof(struct cd_toc_entry));
 			free(data, M_TEMP);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCSETPATCH:
@@ -2379,15 +2400,18 @@
 			struct cd_mode_params params;
 			union cd_pages *page;
 
+			params.alloc_len = sizeof(union cd_mode_data_6_10);
+			params.mode_buf = malloc(params.alloc_len, M_TEMP, 
+						 M_WAITOK | M_ZERO);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCSETPATCH\n"));
 
-			params.alloc_len = sizeof(union cd_mode_data_6_10);
-			params.mode_buf = malloc(params.alloc_len, M_TEMP, 
-						 M_WAITOK | M_ZERO);
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2400,6 +2424,7 @@
 			page->audio.port[3].channels = arg->patch[3];
 			error = cdsetmode(periph, &params);
 			free(params.mode_buf, M_TEMP);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCGETVOL:
@@ -2408,15 +2433,18 @@
 			struct cd_mode_params params;
 			union cd_pages *page;
 
+			params.alloc_len = sizeof(union cd_mode_data_6_10);
+			params.mode_buf = malloc(params.alloc_len, M_TEMP, 
+						 M_WAITOK | M_ZERO);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCGETVOL\n"));
 
-			params.alloc_len = sizeof(union cd_mode_data_6_10);
-			params.mode_buf = malloc(params.alloc_len, M_TEMP, 
-						 M_WAITOK | M_ZERO);
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2428,6 +2456,7 @@
 			arg->vol[2] = page->audio.port[2].volume;
 			arg->vol[3] = page->audio.port[3].volume;
 			free(params.mode_buf, M_TEMP);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCSETVOL:
@@ -2436,15 +2465,18 @@
 			struct cd_mode_params params;
 			union cd_pages *page;
 
+			params.alloc_len = sizeof(union cd_mode_data_6_10);
+			params.mode_buf = malloc(params.alloc_len, M_TEMP, 
+						 M_WAITOK | M_ZERO);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCSETVOL\n"));
 
-			params.alloc_len = sizeof(union cd_mode_data_6_10);
-			params.mode_buf = malloc(params.alloc_len, M_TEMP, 
-						 M_WAITOK | M_ZERO);
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2458,6 +2490,7 @@
 			page->audio.port[2].volume = arg->vol[2];
 			page->audio.port[3].volume = arg->vol[3];
 			error = cdsetmode(periph, &params);
+			cam_periph_unlock(periph);
 			free(params.mode_buf, M_TEMP);
 		}
 		break;
@@ -2466,15 +2499,18 @@
 			struct cd_mode_params params;
 			union cd_pages *page;
 
+			params.alloc_len = sizeof(union cd_mode_data_6_10);
+			params.mode_buf = malloc(params.alloc_len, M_TEMP,
+						 M_WAITOK | M_ZERO);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCSETMONO\n"));
 
-			params.alloc_len = sizeof(union cd_mode_data_6_10);
-			params.mode_buf = malloc(params.alloc_len, M_TEMP,
-						 M_WAITOK | M_ZERO);
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2486,6 +2522,7 @@
 			page->audio.port[2].channels = 0;
 			page->audio.port[3].channels = 0;
 			error = cdsetmode(periph, &params);
+			cam_periph_unlock(periph);
 			free(params.mode_buf, M_TEMP);
 		}
 		break;
@@ -2494,15 +2531,18 @@
 			struct cd_mode_params params;
 			union cd_pages *page;
 
+			params.alloc_len = sizeof(union cd_mode_data_6_10);
+			params.mode_buf = malloc(params.alloc_len, M_TEMP,
+						 M_WAITOK | M_ZERO);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCSETSTEREO\n"));
 
-			params.alloc_len = sizeof(union cd_mode_data_6_10);
-			params.mode_buf = malloc(params.alloc_len, M_TEMP,
-						 M_WAITOK | M_ZERO);
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2515,6 +2555,7 @@
 			page->audio.port[3].channels = 0;
 			error = cdsetmode(periph, &params);
 			free(params.mode_buf, M_TEMP);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCSETMUTE:
@@ -2522,15 +2563,18 @@
 			struct cd_mode_params params;
 			union cd_pages *page;
 
+			params.alloc_len = sizeof(union cd_mode_data_6_10);
+			params.mode_buf = malloc(params.alloc_len, M_TEMP,
+						 M_WAITOK | M_ZERO);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCSETMUTE\n"));
 
-			params.alloc_len = sizeof(union cd_mode_data_6_10);
-			params.mode_buf = malloc(params.alloc_len, M_TEMP,
-						 M_WAITOK | M_ZERO);
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(&params, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2541,6 +2585,7 @@
 			page->audio.port[3].channels = 0;
 			error = cdsetmode(periph, &params);
 			free(params.mode_buf, M_TEMP);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCSETLEFT:
@@ -2548,16 +2593,18 @@
 			struct cd_mode_params params;
 			union cd_pages *page;
 
+			params.alloc_len = sizeof(union cd_mode_data_6_10);
+			params.mode_buf = malloc(params.alloc_len, M_TEMP,
+						 M_WAITOK | M_ZERO);
+
+			cam_periph_lock(periph);
 			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
 				  ("trying to do CDIOCSETLEFT\n"));
 
-			params.alloc_len = sizeof(union cd_mode_data_6_10);
-			params.mode_buf = malloc(params.alloc_len, M_TEMP,
-						 M_WAITOK | M_ZERO);
-			
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2568,6 +2615,7 @@
 			page->audio.port[3].channels = 0;
 			error = cdsetmode(periph, &params);
 			free(params.mode_buf, M_TEMP);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCSETRIGHT:
@@ -2575,16 +2623,18 @@
 			struct cd_mode_params params;
 			union cd_pages *page;
 
-			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
-				  ("trying to do CDIOCSETRIGHT\n"));
-
 			params.alloc_len = sizeof(union cd_mode_data_6_10);
 			params.mode_buf = malloc(params.alloc_len, M_TEMP,
 						 M_WAITOK | M_ZERO);
 
+			cam_periph_lock(periph);
+			CAM_DEBUG(periph->path, CAM_DEBUG_SUBTRACE, 
+				  ("trying to do CDIOCSETRIGHT\n"));
+
 			error = cdgetmode(periph, &params, AUDIO_PAGE);
 			if (error) {
 				free(params.mode_buf, M_TEMP);
+				cam_periph_unlock(periph);
 				break;
 			}
 			page = cdgetpage(&params);
@@ -2595,31 +2645,48 @@
 			page->audio.port[3].channels = 0;
 			error = cdsetmode(periph, &params);
 			free(params.mode_buf, M_TEMP);
+			cam_periph_unlock(periph);
 		}
 		break;
 	case CDIOCRESUME:
+		cam_periph_lock(periph);
 		error = cdpause(periph, 1);
+		cam_periph_unlock(periph);
 		break;
 	case CDIOCPAUSE:
+		cam_periph_lock(periph);
 		error = cdpause(periph, 0);
+		cam_periph_unlock(periph);
 		break;
 	case CDIOCSTART:
+		cam_periph_lock(periph);
 		error = cdstartunit(periph, 0);
+		cam_periph_unlock(periph);
 		break;
 	case CDIOCCLOSE:
+		cam_periph_lock(periph);
 		error = cdstartunit(periph, 1);
+		cam_periph_unlock(periph);
 		break;
 	case CDIOCSTOP:
+		cam_periph_lock(periph);
 		error = cdstopunit(periph, 0);
+		cam_periph_unlock(periph);
 		break;
 	case CDIOCEJECT:
+		cam_periph_lock(periph);
 		error = cdstopunit(periph, 1);
+		cam_periph_unlock(periph);
 		break;
 	case CDIOCALLOW:
+		cam_periph_lock(periph);
 		cdprevent(periph, PR_ALLOW);
+		cam_periph_unlock(periph);
 		break;
 	case CDIOCPREVENT:
+		cam_periph_lock(periph);
 		cdprevent(periph, PR_PREVENT);
+		cam_periph_unlock(periph);
 		break;
 	case CDIOCSETDEBUG:
 		/* sc_link->flags |= (SDEV_DB1 | SDEV_DB2); */
@@ -2634,10 +2701,14 @@
 		error = ENOTTY;
 		break;
 	case CDRIOCREADSPEED:
+		cam_periph_lock(periph);
 		error = cdsetspeed(periph, *(u_int32_t *)addr, CDR_MAX_SPEED);
+		cam_periph_unlock(periph);
 		break;
 	case CDRIOCWRITESPEED:
+		cam_periph_lock(periph);
 		error = cdsetspeed(periph, CDR_MAX_SPEED, *(u_int32_t *)addr);
+		cam_periph_unlock(periph);
 		break;
 	case DVDIOCSENDKEY:
 	case DVDIOCREPORTKEY: {
@@ -2645,10 +2716,12 @@
 
 		authinfo = (struct dvd_authinfo *)addr;
 
+		cam_periph_lock(periph);
 		if (cmd == DVDIOCREPORTKEY)
 			error = cdreportkey(periph, authinfo);
 		else
 			error = cdsendkey(periph, authinfo);
+		cam_periph_unlock(periph);
 		break;
 		}
 	case DVDIOCREADSTRUCTURE: {
@@ -2656,18 +2729,19 @@
 
 		dvdstruct = (struct dvd_struct *)addr;
 
+		cam_periph_lock(periph);
 		error = cdreaddvdstructure(periph, dvdstruct);
+		cam_periph_unlock(periph);
 
 		break;
 	}
 	default:
+		cam_periph_lock(periph);
 		error = cam_periph_ioctl(periph, cmd, addr, cderror);
+		cam_periph_unlock(periph);
 		break;
 	}
 
-	cam_periph_unlock(periph);
-
-	CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdioctl\n"));
 	if (error && bootverbose) {
 		printf("scsi_cd.c::ioctl cmd=%08lx error=%d\n", cmd, error);
 	}

==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_ch.c#7 (text+ko) ====

@@ -392,11 +392,8 @@
 	csa.callback_arg = periph;
 	xpt_action((union ccb *)&csa);
 
-	/*
-	 * Lock this peripheral until we are setup.
-	 * This first call can't block
-	 */
-	(void)cam_periph_lock(periph, PRIBIO);
+	/* Refcount this periph now that it's been created. */
+	(void)cam_periph_acquire(periph);
 	xpt_schedule(periph, /*priority*/5);
 
 	return(CAM_REQ_CMP);
@@ -408,7 +405,6 @@
 	struct cam_periph *periph;
 	struct ch_softc *softc;
 	int error;
-	int s;
 
 	periph = (struct cam_periph *)dev->si_drv1;
 	if (periph == NULL)
@@ -416,25 +412,18 @@
 
 	softc = (struct ch_softc *)periph->softc;
 
-	s = splsoftcam();
 	if (softc->flags & CH_FLAG_INVALID) {
-		splx(s);
 		return(ENXIO);
 	}
 
-	if ((error = cam_periph_lock(periph, PRIBIO | PCATCH)) != 0) {
-		splx(s);
-		return (error);
-	}
-	
-	splx(s);
-
 	if ((softc->flags & CH_FLAG_OPEN) == 0) {
 		if (cam_periph_acquire(periph) != CAM_REQ_CMP)
 			return(ENXIO);
 		softc->flags |= CH_FLAG_OPEN;
 	}
 
+	cam_periph_lock(periph);
+	
 	/*
 	 * Load information about this changer device into the softc.
 	 */
@@ -465,8 +454,7 @@
 
 	softc = (struct ch_softc *)periph->softc;
 
-	if ((error = cam_periph_lock(periph, PRIBIO)) != 0)

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list