summaryrefslogtreecommitdiff
path: root/sys/dev/pci/musycc.c
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2005-08-27 13:18:03 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2005-08-27 13:18:03 +0000
commit568b04875d9d783e68f4726ab424be00ca0ae228 (patch)
treecd30a2d9f0ed5d3881c192afd82273f112a73be6 /sys/dev/pci/musycc.c
parent3aeaa70bc28f155c6888807b772b5899765d61f4 (diff)
Timeout service request in the uncommon case that the port is blocked
(there needs to be correct clocking on the port or all service request will be ignored). Without the timeout the interface will just hang till reboot. OK deraadt@
Diffstat (limited to 'sys/dev/pci/musycc.c')
-rw-r--r--sys/dev/pci/musycc.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/sys/dev/pci/musycc.c b/sys/dev/pci/musycc.c
index c1f03b68c68..5b89e0becc6 100644
--- a/sys/dev/pci/musycc.c
+++ b/sys/dev/pci/musycc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: musycc.c,v 1.5 2005/08/27 13:07:56 claudio Exp $ */
+/* $OpenBSD: musycc.c,v 1.6 2005/08/27 13:18:02 claudio Exp $ */
/*
* Copyright (c) 2004,2005 Internet Business Solutions AG, Zurich, Switzerland
@@ -1483,9 +1483,11 @@ musycc_sreq(struct musycc_group *mg, int channel, u_int32_t req, int dir,
mg->mg_hdlc->mc_dev.dv_xname); \
} while (0)
- int needskick;
+ struct timeval tv;
+ int needskick;
needskick = (mg->mg_sreqpend == mg->mg_sreqprod);
+ getmicrouptime(&tv);
ACCOOM_PRINTF(4, ("musycc_sreq: g# %d c# %d req %x dir %x\n",
mg->mg_gnum, channel, req, dir));
@@ -1494,6 +1496,8 @@ musycc_sreq(struct musycc_group *mg, int channel, u_int32_t req, int dir,
req &= ~MUSYCC_SREQ_TXDIR & ~MUSYCC_SREQ_MASK;
req |= MUSYCC_SREQ_CHSET(channel);
mg->mg_sreq[mg->mg_sreqprod].sreq = req;
+ mg->mg_sreq[mg->mg_sreqprod].timeout = tv.tv_sec +
+ MUSYCC_SREQTIMEOUT;
if (dir == MUSYCC_SREQ_RX)
mg->mg_sreq[mg->mg_sreqprod].event = event;
else
@@ -1504,6 +1508,8 @@ musycc_sreq(struct musycc_group *mg, int channel, u_int32_t req, int dir,
req &= ~MUSYCC_SREQ_MASK;
req |= MUSYCC_SREQ_TXDIR;
req |= MUSYCC_SREQ_CHSET(channel);
+ mg->mg_sreq[mg->mg_sreqprod].timeout = tv.tv_sec +
+ MUSYCC_SREQTIMEOUT;
mg->mg_sreq[mg->mg_sreqprod].sreq = req;
mg->mg_sreq[mg->mg_sreqprod].event = event;
MUSYCC_SREQINC(mg->mg_sreqprod, mg->mg_sreqpend);
@@ -1515,8 +1521,29 @@ musycc_sreq(struct musycc_group *mg, int channel, u_int32_t req, int dir,
#undef MUSYCC_SREQINC
}
+void
+musycc_tick(struct channel_softc *cc)
+{
+ struct musycc_group *mg = cc->cc_group;
+ struct timeval tv;
+ if (mg->mg_sreqpend == mg->mg_sreqprod)
+ return;
+ getmicrouptime(&tv);
+ if (mg->mg_sreq[mg->mg_sreqpend].timeout < tv.tv_sec) {
+ log(LOG_ERR, "%s: service request timeout\n",
+ cc->cc_ifp->if_xname);
+ mg->mg_sreqpend++;
+ /* digest all timed out SREQ */
+ while (mg->mg_sreq[mg->mg_sreqpend].timeout < tv.tv_sec &&
+ mg->mg_sreqpend != mg->mg_sreqprod)
+ mg->mg_sreqpend++;
+
+ if (mg->mg_sreqpend != mg->mg_sreqprod)
+ musycc_kick(mg);
+ }
+}
/*
* Extension Bus API