summaryrefslogtreecommitdiffstats
path: root/sys/cam/scsi/scsi_sa.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/cam/scsi/scsi_sa.c')
-rw-r--r--sys/cam/scsi/scsi_sa.c118
1 files changed, 47 insertions, 71 deletions
diff --git a/sys/cam/scsi/scsi_sa.c b/sys/cam/scsi/scsi_sa.c
index 013e421..170d35c 100644
--- a/sys/cam/scsi/scsi_sa.c
+++ b/sys/cam/scsi/scsi_sa.c
@@ -447,37 +447,33 @@ saopen(struct cdev *dev, int flags, int fmt, struct thread *td)
struct sa_softc *softc;
int unit;
int error;
- int s;
unit = SAUNIT(dev);
- s = splsoftcam();
periph = (struct cam_periph *)dev->si_drv1;
- if (periph == NULL) {
- (void) splx(s);
- return (ENXIO);
+ if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
+ return (ENXIO);
}
+
+ cam_periph_lock(periph);
+
softc = (struct sa_softc *)periph->softc;
- if ((error = cam_periph_lock(periph, PRIBIO|PCATCH)) != 0) {
- splx(s);
- return (error);
- }
- splx(s);
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
("saopen(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
- if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
- cam_periph_unlock(periph);
- return (ENXIO);
- }
-
if (SA_IS_CTRL(dev)) {
softc->ctrl_mode = 1;
cam_periph_unlock(periph);
return (0);
}
+ if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
+ cam_periph_unlock(periph);
+ cam_periph_release(periph);
+ return (error);
+ }
+
if (softc->flags & SA_FLAG_OPEN) {
error = EBUSY;
} else if (softc->flags & SA_FLAG_INVALID) {
@@ -499,17 +495,23 @@ saopen(struct cdev *dev, int flags, int fmt, struct thread *td)
if (error && (flags & O_NONBLOCK)) {
softc->flags |= SA_FLAG_OPEN;
softc->open_pending_mount = 1;
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
return (0);
}
}
if (error) {
+ cam_periph_unhold(periph);
+ cam_periph_unlock(periph);
cam_periph_release(periph);
- } else {
- saprevent(periph, PR_PREVENT);
- softc->flags |= SA_FLAG_OPEN;
+ return (error);
}
+
+ saprevent(periph, PR_PREVENT);
+ softc->flags |= SA_FLAG_OPEN;
+
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
return (error);
}
@@ -528,32 +530,35 @@ saclose(struct cdev *dev, int flag, int fmt, struct thread *td)
if (periph == NULL)
return (ENXIO);
+ cam_periph_lock(periph);
+
softc = (struct sa_softc *)periph->softc;
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE|CAM_DEBUG_INFO,
("saclose(%d): dev=0x%x softc=0x%x\n", unit, unit, softc->flags));
- if ((error = cam_periph_lock(periph, PRIBIO)) != 0) {
- return (error);
- }
-
softc->open_rdonly = 0;
if (SA_IS_CTRL(dev)) {
softc->ctrl_mode = 0;
- cam_periph_release(periph);
cam_periph_unlock(periph);
+ cam_periph_release(periph);
return (0);
}
if (softc->open_pending_mount) {
softc->flags &= ~SA_FLAG_OPEN;
softc->open_pending_mount = 0;
- cam_periph_release(periph);
cam_periph_unlock(periph);
+ cam_periph_release(periph);
return (0);
}
+ if ((error = cam_periph_hold(periph, PRIBIO)) != 0) {
+ cam_periph_unlock(periph);
+ return (error);
+ }
+
/*
* Were we writing the tape?
*/
@@ -661,6 +666,7 @@ saclose(struct cdev *dev, int flag, int fmt, struct thread *td)
if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0)
sareservereleaseunit(periph, FALSE);
+ cam_periph_unhold(periph);
cam_periph_unlock(periph);
cam_periph_release(periph);
@@ -677,7 +683,6 @@ sastrategy(struct bio *bp)
{
struct cam_periph *periph;
struct sa_softc *softc;
- int s;
bp->bio_resid = bp->bio_bcount;
if (SA_IS_CTRL(bp->bio_dev)) {
@@ -689,18 +694,18 @@ sastrategy(struct bio *bp)
biofinish(bp, NULL, ENXIO);
return;
}
- softc = (struct sa_softc *)periph->softc;
+ cam_periph_lock(periph);
- s = splsoftcam();
+ softc = (struct sa_softc *)periph->softc;
if (softc->flags & SA_FLAG_INVALID) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, ENXIO);
return;
}
if (softc->flags & SA_FLAG_TAPE_FROZEN) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, EPERM);
return;
}
@@ -711,16 +716,15 @@ sastrategy(struct bio *bp)
* file descriptor.
*/
if (bp->bio_cmd == BIO_WRITE && softc->open_rdonly) {
- splx(s);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, EBADF);
return;
}
- splx(s);
-
if (softc->open_pending_mount) {
int error = samount(periph, 0, bp->bio_dev);
if (error) {
+ cam_periph_unlock(periph);
biofinish(bp, NULL, ENXIO);
return;
}
@@ -733,6 +737,7 @@ sastrategy(struct bio *bp)
* If it's a null transfer, return immediately
*/
if (bp->bio_bcount == 0) {
+ cam_periph_unlock(periph);
biodone(bp);
return;
}
@@ -750,6 +755,7 @@ sastrategy(struct bio *bp)
xpt_print(periph->path, "Invalid request. Fixed block "
"device requests must be a multiple of %d bytes\n",
softc->min_blk);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, EINVAL);
return;
}
@@ -765,18 +771,12 @@ sastrategy(struct bio *bp)
}
printf("between %d and %d bytes\n", softc->min_blk,
softc->max_blk);
+ cam_periph_unlock(periph);
biofinish(bp, NULL, EINVAL);
return;
}
/*
- * Mask interrupts so that the device cannot be invalidated until
- * after we are in the queue. Otherwise, we might not properly
- * clean up one of the buffers.
- */
- s = splbio();
-
- /*
* Place it at the end of the queue.
*/
bioq_insert_tail(&softc->bio_queue, bp);
@@ -791,12 +791,12 @@ sastrategy(struct bio *bp)
CAM_DEBUG(periph->path, CAM_DEBUG_INFO,
("sastrategy: queue count now %d\n", softc->queue_count));
}
- splx(s);
/*
* Schedule ourselves for performing the work.
*/
xpt_schedule(periph, 1);
+ cam_periph_unlock(periph);
return;
}
@@ -819,7 +819,6 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
struct sa_softc *softc;
scsi_space_code spaceop;
int didlockperiph = 0;
- int s;
int mode;
int error = 0;
@@ -831,6 +830,7 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
if (periph == NULL)
return (ENXIO);
+ cam_periph_lock(periph);
softc = (struct sa_softc *)periph->softc;
/*
@@ -856,13 +856,10 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
* other thread that has this device open to do
* an MTIOCERRSTAT that would clear latched status.
*/
- s = splsoftcam();
if ((periph->flags & CAM_PERIPH_LOCKED) == 0) {
- error = cam_periph_lock(periph, PRIBIO|PCATCH);
- if (error != 0) {
- splx(s);
+ error = cam_periph_hold(periph, PRIBIO|PCATCH);
+ if (error != 0)
return (error);
- }
didlockperiph = 1;
}
break;
@@ -895,12 +892,9 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
* than at open time because we are sharing writable
* access to data structures.
*/
- s = splsoftcam();
- error = cam_periph_lock(periph, PRIBIO|PCATCH);
- if (error != 0) {
- splx(s);
+ error = cam_periph_hold(periph, PRIBIO|PCATCH);
+ if (error != 0)
return (error);
- }
didlockperiph = 1;
break;
@@ -1327,8 +1321,9 @@ saioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, struct thread *td)
}
}
if (didlockperiph) {
- cam_periph_unlock(periph);
+ cam_periph_unhold(periph);
}
+ cam_periph_unlock(periph);
return (error);
}
@@ -1371,7 +1366,6 @@ saoninvalidate(struct cam_periph *periph)
{
struct sa_softc *softc;
struct ccb_setasync csa;
- int s;
softc = (struct sa_softc *)periph->softc;
@@ -1389,20 +1383,12 @@ saoninvalidate(struct cam_periph *periph)
softc->flags |= SA_FLAG_INVALID;
/*
- * Although the oninvalidate() routines are always called at
- * splsoftcam, we need to be at splbio() here to keep the buffer
- * queue from being modified while we traverse it.
- */
- s = splbio();
-
- /*
* Return all queued I/O with ENXIO.
* XXX Handle any transactions queued to the card
* with XPT_ABORT_CCB.
*/
bioq_flush(&softc->bio_queue, NULL, ENXIO);
softc->queue_count = 0;
- splx(s);
xpt_print(periph->path, "lost device\n");
@@ -1609,12 +1595,10 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
{
/* Pull a buffer from the queue and get going on it */
struct bio *bp;
- int s;
/*
* See if there is a buf with work for us to do..
*/
- s = splbio();
bp = bioq_first(&softc->bio_queue);
if (periph->immediate_priority <= periph->pinfo.priority) {
CAM_DEBUG_PRINT(CAM_DEBUG_SUBTRACE,
@@ -1623,10 +1607,8 @@ sastart(struct cam_periph *periph, union ccb *start_ccb)
SLIST_INSERT_HEAD(&periph->ccb_list, &start_ccb->ccb_h,
periph_links.sle);
periph->immediate_priority = CAM_PRIORITY_NONE;
- splx(s);
wakeup(&periph->ccb_list);
} else if (bp == NULL) {
- splx(s);
xpt_release_ccb(start_ccb);
} else if ((softc->flags & SA_FLAG_ERR_PENDING) != 0) {
struct bio *done_bp;
@@ -1669,7 +1651,6 @@ again:
"%d more buffers queued up\n",
(softc->flags & SA_FLAG_ERR_PENDING),
(bp != NULL)? "not " : " ", softc->queue_count));
- splx(s);
xpt_release_ccb(start_ccb);
biodone(done_bp);
} else {
@@ -1689,7 +1670,6 @@ again:
bp->bio_error = EIO;
xpt_print(periph->path, "zero blocksize"
" for FIXED length writes?\n");
- splx(s);
biodone(bp);
break;
}
@@ -1740,7 +1720,6 @@ again:
Set_CCB_Type(start_ccb, SA_CCB_BUFFER_IO);
start_ccb->ccb_h.ccb_bp = bp;
bp = bioq_first(&softc->bio_queue);
- splx(s);
xpt_action(start_ccb);
}
@@ -1785,7 +1764,6 @@ sadone(struct cam_periph *periph, union ccb *done_ccb)
}
if (error == EIO) {
- int s;
/*
* Catastrophic error. Mark the tape as frozen
@@ -1798,10 +1776,8 @@ sadone(struct cam_periph *periph, union ccb *done_ccb)
*
*/
- s = splbio();
softc->flags |= SA_FLAG_TAPE_FROZEN;
bioq_flush(&softc->bio_queue, NULL, EIO);
- splx(s);
}
if (error != 0) {
bp->bio_resid = bp->bio_bcount;
OpenPOWER on IntegriCloud