summaryrefslogtreecommitdiffstats
path: root/sys/dev/firewire/if_fwip.c
diff options
context:
space:
mode:
authorsimokawa <simokawa@FreeBSD.org>2007-06-06 14:31:36 +0000
committersimokawa <simokawa@FreeBSD.org>2007-06-06 14:31:36 +0000
commit6052bc5731ca66f7ae519ab26941c42ceef6daaf (patch)
treebda94d3de727b214eea64936b54deb3b46a61f52 /sys/dev/firewire/if_fwip.c
parent27c6e3f25e2c0ab488171e7704cea4e8b215f483 (diff)
downloadFreeBSD-src-6052bc5731ca66f7ae519ab26941c42ceef6daaf.zip
FreeBSD-src-6052bc5731ca66f7ae519ab26941c42ceef6daaf.tar.gz
MFp4: MPSAFE firewire stack.
- lock its own locks and drop Giant. - create its own taskqueue thread. - split interrupt routine - use interrupt filter as a fast interrupt. - run watchdog timer in taskqueue so that it should be serialized with the bottom half. - add extra sanity check for transaction labels. disable ad-hoc workaround for unknown tlabels. - add sleep/wakeup synchronization primitives - don't reset OHCI in fwohci_stop()
Diffstat (limited to 'sys/dev/firewire/if_fwip.c')
-rw-r--r--sys/dev/firewire/if_fwip.c68
1 files changed, 31 insertions, 37 deletions
diff --git a/sys/dev/firewire/if_fwip.c b/sys/dev/firewire/if_fwip.c
index d7b2c31..a9d1f38 100644
--- a/sys/dev/firewire/if_fwip.c
+++ b/sys/dev/firewire/if_fwip.c
@@ -161,6 +161,7 @@ fwip_attach(device_t dev)
if (ifp == NULL)
return (ENOSPC);
+ mtx_init(&fwip->mtx, "fwip", NULL, MTX_DEF);
/* XXX */
fwip->dma_ch = -1;
@@ -197,8 +198,7 @@ fwip_attach(device_t dev)
ifp->if_init = fwip_init;
ifp->if_start = fwip_start;
ifp->if_ioctl = fwip_ioctl;
- ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST|
- IFF_NEEDSGIANT);
+ ifp->if_flags = (IFF_BROADCAST|IFF_SIMPLEX|IFF_MULTICAST);
ifp->if_snd.ifq_maxlen = TX_MAX_QUEUE;
#ifdef DEVICE_POLLING
ifp->if_capabilities |= IFCAP_POLLING;
@@ -282,6 +282,7 @@ fwip_detach(device_t dev)
fwip_stop(fwip);
firewire_ifdetach(ifp);
if_free(ifp);
+ mtx_destroy(&fwip->mtx);
splx(s);
return 0;
@@ -303,17 +304,11 @@ fwip_init(void *arg)
fc = fwip->fd.fc;
#define START 0
if (fwip->dma_ch < 0) {
- for (i = START; i < fc->nisodma; i ++) {
- xferq = fc->ir[i];
- if ((xferq->flag & FWXFERQ_OPEN) == 0)
- goto found;
- }
- printf("no free dma channel\n");
- return;
-found:
- fwip->dma_ch = i;
- /* allocate DMA channel and init packet mode */
- xferq->flag |= FWXFERQ_OPEN | FWXFERQ_EXTBUF |
+ fwip->dma_ch = fw_open_isodma(fc, /* tx */0);
+ if (fwip->dma_ch < 0)
+ return;
+ xferq = fc->ir[fwip->dma_ch];
+ xferq->flag |= FWXFERQ_EXTBUF |
FWXFERQ_HANDLER | FWXFERQ_STREAM;
xferq->flag &= ~0xff;
xferq->flag |= broadcast_channel & 0xff;
@@ -522,8 +517,6 @@ fwip_output_callback(struct fw_xfer *xfer)
struct ifnet *ifp;
int s;
- GIANT_REQUIRED;
-
fwip = (struct fwip_softc *)xfer->sc;
ifp = fwip->fw_softc.fwip_ifp;
/* XXX error check */
@@ -535,12 +528,15 @@ fwip_output_callback(struct fw_xfer *xfer)
fw_xfer_unload(xfer);
s = splimp();
+ FWIP_LOCK(fwip);
STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
+ FWIP_UNLOCK(fwip);
splx(s);
/* for queue full */
- if (ifp->if_snd.ifq_head != NULL)
+ if (ifp->if_snd.ifq_head != NULL) {
fwip_start(ifp);
+ }
}
static void
@@ -549,8 +545,6 @@ fwip_start(struct ifnet *ifp)
struct fwip_softc *fwip = ((struct fwip_eth_softc *)ifp->if_softc)->fwip;
int s;
- GIANT_REQUIRED;
-
FWIPDEBUG(ifp, "starting\n");
if (fwip->dma_ch < 0) {
@@ -603,19 +597,29 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp)
int error;
int i = 0;
- GIANT_REQUIRED;
-
xfer = NULL;
- xferq = fwip->fd.fc->atq;
- while (xferq->queued < xferq->maxq - 1) {
+ xferq = fc->atq;
+ while ((xferq->queued < xferq->maxq - 1) &&
+ (ifp->if_snd.ifq_head != NULL)) {
+ FWIP_LOCK(fwip);
xfer = STAILQ_FIRST(&fwip->xferlist);
if (xfer == NULL) {
+ FWIP_UNLOCK(fwip);
+#if 0
printf("if_fwip: lack of xfer\n");
- return;
+#endif
+ break;
}
+ STAILQ_REMOVE_HEAD(&fwip->xferlist, link);
+ FWIP_UNLOCK(fwip);
+
IF_DEQUEUE(&ifp->if_snd, m);
- if (m == NULL)
+ if (m == NULL) {
+ FWIP_LOCK(fwip);
+ STAILQ_INSERT_HEAD(&fwip->xferlist, xfer, link);
+ FWIP_UNLOCK(fwip);
break;
+ }
/*
* Dig out the link-level address which
@@ -629,7 +633,6 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp)
else
destfw = (struct fw_hwaddr *) (mtag + 1);
- STAILQ_REMOVE_HEAD(&fwip->xferlist, link);
/*
* We don't do any bpf stuff here - the generic code
@@ -722,7 +725,9 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp)
* for later transmission.
*/
xfer->mbuf = 0;
+ FWIP_LOCK(fwip);
STAILQ_INSERT_TAIL(&fwip->xferlist, xfer, link);
+ FWIP_UNLOCK(fwip);
IF_PREPEND(&ifp->if_snd, m);
break;
}
@@ -741,13 +746,8 @@ fwip_async_output(struct fwip_softc *fwip, struct ifnet *ifp)
if (i > 1)
printf("%d queued\n", i);
#endif
- if (i > 0) {
-#if 1
+ if (i > 0)
xferq->start(fc);
-#else
- taskqueue_enqueue(taskqueue_swi_giant, &fwip->start_send);
-#endif
- }
}
static void
@@ -755,7 +755,6 @@ fwip_start_send (void *arg, int count)
{
struct fwip_softc *fwip = arg;
- GIANT_REQUIRED;
fwip->fd.fc->atq->start(fwip->fd.fc);
}
@@ -772,7 +771,6 @@ fwip_stream_input(struct fw_xferq *xferq)
uint16_t src;
uint32_t *p;
- GIANT_REQUIRED;
fwip = (struct fwip_softc *)xferq->sc;
ifp = fwip->fw_softc.fwip_ifp;
@@ -874,8 +872,6 @@ fwip_unicast_input_recycle(struct fwip_softc *fwip, struct fw_xfer *xfer)
{
struct mbuf *m;
- GIANT_REQUIRED;
-
/*
* We have finished with a unicast xfer. Allocate a new
* cluster and stick it on the back of the input queue.
@@ -900,8 +896,6 @@ fwip_unicast_input(struct fw_xfer *xfer)
//struct fw_pkt *sfp;
int rtcode;
- GIANT_REQUIRED;
-
fwip = (struct fwip_softc *)xfer->sc;
ifp = fwip->fw_softc.fwip_ifp;
m = xfer->mbuf;
OpenPOWER on IntegriCloud