tech-kern archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
SCSI changes - PR58452 for review
HI,
I am looking to get the following patch reviewed.
It is also documented in PR/58452.
It does the following:
Abort current transfer on scsi bus reset. This one seems logical as the state
of the transfer is unknown after a bus reset.
Uses retry path for medium errors. Bluescsi-v2 would through medium errors
that would succeed if the transfer was retried.
Biggest change is for ncr5380 which is to stop scsipi_done from being
reentrant in 5380sbc_done, This helps with aborting transfers something which
is common with dse(4). which previously if nested to deep in recursive calls
to scsipi_done would cause a panic.
Finally to downgrade the Aborting 0/0/0 messages to a debug only option as
they are harmless and no longer a warning that requires user intervention or
concern.
I'll wait another two weeks before commiting anything should issues arise.
Best regards,
Nat
diff -r b6eba4068585 sys/dev/ic/ncr5380sbc.c
--- a/sys/dev/ic/ncr5380sbc.c Fri Aug 02 11:45:52 2024 +0000
+++ b/sys/dev/ic/ncr5380sbc.c Sat Aug 03 09:45:54 2024 +1000
@@ -393,6 +393,7 @@ ncr5380_init(struct ncr5380_softc *sc)
static void
ncr5380_reset_scsibus(struct ncr5380_softc *sc)
{
+ struct sci_req *sr;
NCR_TRACE("reset_scsibus, cur=0x%x\n",
(long) sc->sc_current);
@@ -409,6 +410,9 @@ ncr5380_reset_scsibus(struct ncr5380_sof
delay(100000);
/* XXX - Need to cancel disconnected requests. */
+ sr = sc->sc_current;
+ if (sr)
+ ncr5380_abort(sc);
}
@@ -617,9 +621,11 @@ ncr5380_scsipi_request(struct scsipi_cha
/* Terminate any current command. */
sr = sc->sc_current;
if (sr) {
+#ifdef NCR5380_DEBUG
printf("%s: polled request aborting %d/%d\n",
device_xname(sc->sc_dev),
sr->sr_target, sr->sr_lun);
+#endif
ncr5380_abort(sc);
}
if (sc->sc_state != NCR_IDLE) {
@@ -802,7 +808,7 @@ finish:
sc->sc_ncmds--;
/* Tell common SCSI code it is done. */
- scsipi_done(xs);
+ scsipi_done_once(xs);
sc->sc_state = NCR_IDLE;
/* Now ncr5380_sched() may be called again. */
diff -r b6eba4068585 sys/dev/scsipi/scsipi_base.c
--- a/sys/dev/scsipi/scsipi_base.c Fri Aug 02 11:45:52 2024 +0000
+++ b/sys/dev/scsipi/scsipi_base.c Sat Aug 03 09:45:54 2024 +1000
@@ -96,6 +96,8 @@ SDT_PROBE_DEFINE1(scsi, base, xfer, rest
SDT_PROBE_DEFINE1(scsi, base, xfer, free, "struct scsipi_xfer *"/*xs*/);
static int scsipi_complete(struct scsipi_xfer *);
+static struct scsipi_channel*
+ scsipi_done_internal(struct scsipi_xfer *, bool);
static void scsipi_request_sense(struct scsipi_xfer *);
static int scsipi_enqueue(struct scsipi_xfer *);
static void scsipi_run_queue(struct scsipi_channel *chan);
@@ -1056,6 +1058,13 @@ scsipi_interpret_sense(struct scsipi_xfe
case SKEY_VOLUME_OVERFLOW:
error = ENOSPC;
break;
+ case SKEY_MEDIUM_ERROR:
+ if (xs->xs_retries != 0) {
+ xs->xs_retries--;
+ error = ERESTART;
+ } else
+ error = EIO;
+ break;
default:
error = EIO;
break;
@@ -1597,6 +1606,28 @@ scsipi_free_opcodeinfo(struct scsipi_per
void
scsipi_done(struct scsipi_xfer *xs)
{
+ struct scsipi_channel *chan;
+ /*
+ * If there are more xfers on the channel's queue, attempt to
+ * run them.
+ */
+ if ((chan = scsipi_done_internal(xs, true)) != NULL)
+ scsipi_run_queue(chan);
+}
+
+/*
+ * Just like scsipi_done(), but no recursion. Useful if aborting the current
+ * transfer.
+ */
+void
+scsipi_done_once(struct scsipi_xfer *xs)
+{
+ (void)scsipi_done_internal(xs, false);
+}
+
+static struct scsipi_channel*
+scsipi_done_internal(struct scsipi_xfer *xs, bool more)
+{
struct scsipi_periph *periph = xs->xs_periph;
struct scsipi_channel *chan = periph->periph_channel;
int freezecnt;
@@ -1685,7 +1716,7 @@ scsipi_done(struct scsipi_xfer *xs)
*/
if (xs->xs_control & XS_CTL_POLL) {
mutex_exit(chan_mtx(chan));
- return;
+ return NULL;
}
cv_broadcast(xs_cv(xs));
mutex_exit(chan_mtx(chan));
@@ -1697,7 +1728,7 @@ scsipi_done(struct scsipi_xfer *xs)
* without error; no use in taking a context switch
* if we can handle it in interrupt context.
*/
- if (xs->error == XS_NOERROR) {
+ if (xs->error == XS_NOERROR && more == true) {
mutex_exit(chan_mtx(chan));
(void) scsipi_complete(xs);
goto out;
@@ -1712,11 +1743,7 @@ scsipi_done(struct scsipi_xfer *xs)
mutex_exit(chan_mtx(chan));
out:
- /*
- * If there are more xfers on the channel's queue, attempt to
- * run them.
- */
- scsipi_run_queue(chan);
+ return chan;
}
/*
diff -r b6eba4068585 sys/dev/scsipi/scsipiconf.h
--- a/sys/dev/scsipi/scsipiconf.h Fri Aug 02 11:45:52 2024 +0000
+++ b/sys/dev/scsipi/scsipiconf.h Sat Aug 03 09:45:54 2024 +1000
@@ -702,6 +702,7 @@ int scsipi_mode_sense_big(struct scsipi_
struct scsi_mode_parameter_header_10 *, int, int, int, int);
int scsipi_start(struct scsipi_periph *, int, int);
void scsipi_done(struct scsipi_xfer *);
+void scsipi_done_once(struct scsipi_xfer *);
void scsipi_user_done(struct scsipi_xfer *);
int scsipi_interpret_sense(struct scsipi_xfer *);
void scsipi_wait_drain(struct scsipi_periph *);
Home |
Main Index |
Thread Index |
Old Index