summaryrefslogtreecommitdiffstats
path: root/sys/dev/mlx/mlx.c
diff options
context:
space:
mode:
authormsmith <msmith@FreeBSD.org>2000-04-20 23:52:33 +0000
committermsmith <msmith@FreeBSD.org>2000-04-20 23:52:33 +0000
commitc7d9c92d843b0337597acdf63c43c53e792ec250 (patch)
tree39d9250a835bf40bfe7e0c3d242288df8da95dda /sys/dev/mlx/mlx.c
parent51d4afa1a6e67d4db34a9651496b097ff3e99402 (diff)
downloadFreeBSD-src-c7d9c92d843b0337597acdf63c43c53e792ec250.zip
FreeBSD-src-c7d9c92d843b0337597acdf63c43c53e792ec250.tar.gz
One minor bugfix:
- Free resources in all the possible attachment failure cases. One critical bugfix: - Fix a race where it was possible to get out of synch with the log messages from the controller, if the controller hung up for any period of time (eg. while resetting a SCSI bus). This would result in an endless string of console errors, bringing the machine to a halt.
Diffstat (limited to 'sys/dev/mlx/mlx.c')
-rw-r--r--sys/dev/mlx/mlx.c22
1 files changed, 18 insertions, 4 deletions
diff --git a/sys/dev/mlx/mlx.c b/sys/dev/mlx/mlx.c
index 128576e..cc226e88 100644
--- a/sys/dev/mlx/mlx.c
+++ b/sys/dev/mlx/mlx.c
@@ -318,6 +318,7 @@ mlx_attach(struct mlx_softc *sc)
sc->mlx_sg_nseg = MLX_NSEG_NEW;
break;
default:
+ mlx_free(sc);
return(ENXIO); /* should never happen */
}
@@ -381,6 +382,7 @@ mlx_attach(struct mlx_softc *sc)
&sc->mlx_buffer_dmat);
if (error != 0) {
device_printf(sc->mlx_dev, "can't allocate buffer DMA tag\n");
+ mlx_free(sc);
return(ENOMEM);
}
@@ -391,12 +393,14 @@ mlx_attach(struct mlx_softc *sc)
error = mlx_sglist_map(sc);
if (error != 0) {
device_printf(sc->mlx_dev, "can't make initial s/g list mapping\n");
+ mlx_free(sc);
return(error);
}
/* send an ENQUIRY2 to the controller */
if ((sc->mlx_enq2 = mlx_enquire(sc, MLX_CMD_ENQUIRY2, sizeof(struct mlx_enquiry2), NULL)) == NULL) {
device_printf(sc->mlx_dev, "ENQUIRY2 failed\n");
+ mlx_free(sc);
return(ENXIO);
}
@@ -414,6 +418,7 @@ mlx_attach(struct mlx_softc *sc)
/* These controllers don't report the firmware version in the ENQUIRY2 response */
if ((meo = mlx_enquire(sc, MLX_CMD_ENQUIRY_OLD, sizeof(struct mlx_enquiry_old), NULL)) == NULL) {
device_printf(sc->mlx_dev, "ENQUIRY_OLD failed\n");
+ mlx_free(sc);
return(ENXIO);
}
sc->mlx_enq2->me_firmware_id = ('0' << 24) | (0 << 16) | (meo->me_fwminor << 8) | meo->me_fwmajor;
@@ -446,6 +451,7 @@ mlx_attach(struct mlx_softc *sc)
}
break;
default:
+ mlx_free(sc);
return(ENXIO); /* should never happen */
}
@@ -457,6 +463,7 @@ mlx_attach(struct mlx_softc *sc)
error = mlx_sglist_map(sc);
if (error != 0) {
device_printf(sc->mlx_dev, "can't make permanent s/g list mapping\n");
+ mlx_free(sc);
return(error);
}
@@ -1115,11 +1122,14 @@ mlx_periodic_enquiry(struct mlx_command *mc)
if (sc->mlx_currevent == -1) {
/* initialise our view of the event log */
sc->mlx_currevent = sc->mlx_lastevent = me->me_event_log_seq_num;
- } else if (me->me_event_log_seq_num != sc->mlx_lastevent) {
+ } else if ((me->me_event_log_seq_num != sc->mlx_lastevent) && !(sc->mlx_flags & MLX_EVENTLOG_BUSY)) {
/* record where current events are up to */
sc->mlx_currevent = me->me_event_log_seq_num;
debug(1, "event log pointer was %d, now %d\n", sc->mlx_lastevent, sc->mlx_currevent);
+ /* mark the event log as busy */
+ atomic_set_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY);
+
/* drain new eventlog entries */
mlx_periodic_eventlog_poll(sc);
}
@@ -1285,8 +1295,8 @@ mlx_periodic_eventlog_respond(struct mlx_command *mc)
}
} else {
device_printf(sc->mlx_dev, "error reading message log - %s\n", mlx_diagnose_command(mc));
- panic("log operation failed: lastevent = %d, currevent = %d",
- sc->mlx_lastevent, sc->mlx_currevent);
+ /* give up on all the outstanding messages, as we may have come unsynched */
+ sc->mlx_lastevent = sc->mlx_currevent;
}
/* dispose of command and data */
@@ -1294,8 +1304,12 @@ mlx_periodic_eventlog_respond(struct mlx_command *mc)
mlx_releasecmd(mc);
/* is there another message to obtain? */
- if (sc->mlx_lastevent != sc->mlx_currevent)
+ if (sc->mlx_lastevent != sc->mlx_currevent) {
mlx_periodic_eventlog_poll(sc);
+ } else {
+ /* clear log-busy status */
+ atomic_clear_int(&sc->mlx_flags, MLX_EVENTLOG_BUSY);
+ }
}
/********************************************************************************
OpenPOWER on IntegriCloud