summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorsimokawa <simokawa@FreeBSD.org>2003-02-03 07:33:31 +0000
committersimokawa <simokawa@FreeBSD.org>2003-02-03 07:33:31 +0000
commitafb9eb67e2cada491999bc9223b413ffd6d32de4 (patch)
tree6c767b449cd12bf15b57f8a07b115bd932661805 /sys
parent3fe8dc7ecfb88fd252d48b18419c1fcb38ec825c (diff)
downloadFreeBSD-src-afb9eb67e2cada491999bc9223b413ffd6d32de4.zip
FreeBSD-src-afb9eb67e2cada491999bc9223b413ffd6d32de4.tar.gz
- Take malloc type as an argument in fw_xfer_alloc().
- Fix overwrite problem of freed buffers. It was rare but could happen when fwohci_arcv() is called before fwohci_txd() is called for the transcation. - Drain AT queues and pend AR queues on SID receive rather than BUS reset to make sure DMA actually stops. - Do agent reset in sbp_timeout().
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/firewire/firewire.c24
-rw-r--r--sys/dev/firewire/firewirereg.h4
-rw-r--r--sys/dev/firewire/fwdev.c6
-rw-r--r--sys/dev/firewire/fwmem.c2
-rw-r--r--sys/dev/firewire/fwohci.c27
-rw-r--r--sys/dev/firewire/if_fwe.c2
-rw-r--r--sys/dev/firewire/sbp.c28
7 files changed, 52 insertions, 41 deletions
diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c
index 77c1ce6..60cc487 100644
--- a/sys/dev/firewire/firewire.c
+++ b/sys/dev/firewire/firewire.c
@@ -66,6 +66,7 @@ SYSCTL_INT(_hw_firewire, OID_AUTO, try_bmr, CTLFLAG_RW, &try_bmr, 0,
"Try to be a bus manager");
MALLOC_DEFINE(M_FW, "firewire", "FireWire");
+MALLOC_DEFINE(M_FWXFER, "fw_xfer", "XFER/FireWire");
#define FW_MAXASYRTY 4
#define FW_MAXDEVRCNT 4
@@ -809,16 +810,17 @@ fw_tl2xfer(struct firewire_comm *fc, int node, int tlabel)
* To allocate IEEE1394 XFER structure.
*/
struct fw_xfer *
-fw_xfer_alloc()
+fw_xfer_alloc(struct malloc_type *type)
{
struct fw_xfer *xfer;
- xfer = malloc(sizeof(struct fw_xfer), M_FW, M_NOWAIT | M_ZERO);
+ xfer = malloc(sizeof(struct fw_xfer), type, M_NOWAIT | M_ZERO);
if (xfer == NULL)
return xfer;
xfer->time = time_second;
xfer->sub = -1;
+ xfer->malloc = type;
return xfer;
}
@@ -881,7 +883,7 @@ fw_xfer_free( struct fw_xfer* xfer)
if(xfer->fc != NULL){
fw_tl_free(xfer->fc, xfer);
}
- free(xfer, M_FW);
+ free(xfer, xfer->malloc);
}
static void
@@ -908,7 +910,7 @@ fw_phy_config(struct firewire_comm *fc, int root_node, int gap_count)
#if 0
DELAY(100000);
#endif
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
xfer->send.len = 12;
xfer->send.off = 0;
xfer->fc = fc;
@@ -1211,7 +1213,7 @@ loop:
fw_bus_explore_callback);
if(xfer == NULL) goto done;
#else
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){
goto done;
}
@@ -1262,7 +1264,7 @@ asyreqq(struct firewire_comm *fc, u_int8_t spd, u_int8_t tl, u_int8_t rt,
struct fw_pkt *fp;
int err;
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){
return NULL;
}
@@ -1707,7 +1709,7 @@ fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u
printf("fw_rcv: cannot response(bus reset)!\n");
goto err;
}
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){
return;
}
@@ -1751,7 +1753,7 @@ fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u
}
switch(bind->xfer->act_type){
case FWACT_XFER:
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL) goto err;
xfer->fc = bind->xfer->fc;
xfer->sc = bind->xfer->sc;
@@ -1775,7 +1777,7 @@ fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u
fc->ir[bind->xfer->sub]->queued);
goto err;
}
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL) goto err;
xfer->recv.buf = buf;
xfer->recv.len = len;
@@ -1808,7 +1810,7 @@ fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u
printf("receive queue is full\n");
goto err;
}
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL) goto err;
xfer->recv.buf = buf;
xfer->recv.len = len;
@@ -1894,7 +1896,7 @@ fw_try_bmr(void *arg)
struct fw_pkt *fp;
int err = 0;
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){
return;
}
diff --git a/sys/dev/firewire/firewirereg.h b/sys/dev/firewire/firewirereg.h
index 7eb9e02..108f967 100644
--- a/sys/dev/firewire/firewirereg.h
+++ b/sys/dev/firewire/firewirereg.h
@@ -298,11 +298,12 @@ struct fw_xfer{
} send, recv;
struct mbuf *mbuf;
STAILQ_ENTRY(fw_xfer) link;
+ struct malloc_type *malloc;
};
void fw_sidrcv __P((struct firewire_comm *, caddr_t, u_int, u_int));
void fw_rcv __P((struct firewire_comm *, caddr_t, u_int, u_int, u_int, u_int));
void fw_xfer_free __P(( struct fw_xfer*));
-struct fw_xfer *fw_xfer_alloc __P((void));
+struct fw_xfer *fw_xfer_alloc __P((struct malloc_type *));
void fw_init __P((struct firewire_comm *));
int fw_tbuf_update __P((struct firewire_comm *, int, int));
int fw_rbuf_update __P((struct firewire_comm *, int, int));
@@ -364,3 +365,4 @@ extern devclass_t firewire_devclass;
#endif /* __alpha__ */
MALLOC_DECLARE(M_FW);
+MALLOC_DECLARE(M_FWXFER);
diff --git a/sys/dev/firewire/fwdev.c b/sys/dev/firewire/fwdev.c
index 1ef9ec4..13c84a3 100644
--- a/sys/dev/firewire/fwdev.c
+++ b/sys/dev/firewire/fwdev.c
@@ -455,7 +455,7 @@ dvloop:
}
#endif
if(xferq != NULL){
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){
err = ENOMEM;
return err;
@@ -734,7 +734,7 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td)
ibufreq->tx.psize = sc->fc->it[sub]->psize;
break;
case FW_ASYREQ:
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){
err = ENOMEM;
return err;
@@ -821,7 +821,7 @@ error:
fwb->start_lo = bindreq->start.lo;
fwb->addrlen = bindreq->len;
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if(xfer == NULL){
err = ENOMEM;
return err;
diff --git a/sys/dev/firewire/fwmem.c b/sys/dev/firewire/fwmem.c
index 2f59253..b755dd2 100644
--- a/sys/dev/firewire/fwmem.c
+++ b/sys/dev/firewire/fwmem.c
@@ -81,7 +81,7 @@ fwmem_xfer_req(
{
struct fw_xfer *xfer;
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if (xfer == NULL)
return NULL;
diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c
index 3889d2e..d3e1000 100644
--- a/sys/dev/firewire/fwohci.c
+++ b/sys/dev/firewire/fwohci.c
@@ -1051,8 +1051,8 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch)
break;
}
}
- dbch->xferq.queued --;
}
+ dbch->xferq.queued --;
tr->xfer = NULL;
packets ++;
@@ -1071,35 +1071,35 @@ out:
static void
fwohci_drain(struct firewire_comm *fc, struct fw_xfer *xfer, struct fwohci_dbch *dbch)
{
- int i, s;
+ int i, s, found=0;
struct fwohcidb_tr *tr;
if(xfer->state != FWXF_START) return;
s = splfw();
tr = dbch->bottom;
- for( i = 0 ; i <= dbch->xferq.queued ; i ++){
+ for (i = 0; i < dbch->xferq.queued; i ++) {
if(tr->xfer == xfer){
- s = splfw();
tr->xfer = NULL;
+#if 0
dbch->xferq.queued --;
-#if 1
/* XXX */
if (tr == dbch->bottom)
dbch->bottom = STAILQ_NEXT(tr, link);
-#endif
if (dbch->flags & FWOHCI_DBCH_FULL) {
printf("fwohci_drain: make slot\n");
dbch->flags &= ~FWOHCI_DBCH_FULL;
fwohci_start((struct fwohci_softc *)fc, dbch);
}
-
- splx(s);
+#endif
+ found ++;
break;
}
tr = STAILQ_NEXT(tr, link);
}
splx(s);
+ if (!found)
+ device_printf(fc->dev, "fwochi_drain: xfer not found\n");
return;
}
@@ -1786,7 +1786,7 @@ fwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count)
#ifndef ACK_ALL
OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
#endif
-#if 1
+#if 0
/* pending all pre-bus_reset packets */
fwohci_txd(sc, &sc->atrq);
fwohci_txd(sc, &sc->atrs);
@@ -1895,6 +1895,13 @@ fwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count)
if(buf == NULL) goto sidout;
bcopy((void *)(uintptr_t)(volatile void *)(fc->sid_buf + 1),
buf, plen);
+#if 1
+ /* pending all pre-bus_reset packets */
+ fwohci_txd(sc, &sc->atrq);
+ fwohci_txd(sc, &sc->atrs);
+ fwohci_arcv(sc, &sc->arrs, -1);
+ fwohci_arcv(sc, &sc->arrq, -1);
+#endif
fw_sidrcv(fc, buf, plen, 0);
}
sidout:
@@ -2740,7 +2747,7 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
stat &= 0x1f;
switch(stat){
case FWOHCIEV_ACKPEND:
-#if 0
+#if 1
printf("fwohci_arcv: ack pending..\n");
#endif
/* fall through */
diff --git a/sys/dev/firewire/if_fwe.c b/sys/dev/firewire/if_fwe.c
index 1b7885d..3f428df 100644
--- a/sys/dev/firewire/if_fwe.c
+++ b/sys/dev/firewire/if_fwe.c
@@ -450,7 +450,7 @@ fwe_as_output(struct fwe_softc *fwe, struct ifnet *ifp)
IF_DEQUEUE(&ifp->if_snd, m);
if (m == NULL)
break;
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_FWXFER);
if (xfer == NULL) {
return;
}
diff --git a/sys/dev/firewire/sbp.c b/sys/dev/firewire/sbp.c
index e37727b..096698d 100644
--- a/sys/dev/firewire/sbp.c
+++ b/sys/dev/firewire/sbp.c
@@ -767,7 +767,7 @@ sbp_cam_callback(struct cam_periph *periph, union ccb *ccb)
{
struct sbp_dev *sdev;
sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr;
-SBP_DEBUG(1)
+SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
printf("sbp_cam_callback\n");
END_DEBUG
@@ -800,7 +800,7 @@ sbp_ping_unit_callback(struct cam_periph *periph, union ccb *ccb)
{
struct sbp_dev *sdev;
sdev = (struct sbp_dev *) ccb->ccb_h.ccb_sdev_ptr;
-SBP_DEBUG(1)
+SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
printf("sbp_ping_unit_callback\n");
END_DEBUG
@@ -841,7 +841,7 @@ sbp_ping_unit(struct sbp_dev *sdev)
inq_buf = (struct scsi_inquiry_data *)
malloc(sizeof(*inq_buf), M_SBP, 0);
-SBP_DEBUG(1)
+SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
printf("sbp_ping_unit\n");
END_DEBUG
@@ -1044,7 +1044,7 @@ sbp_write_cmd(struct sbp_dev *sdev, int tcode, int offset)
struct fw_xfer *xfer;
struct fw_pkt *fp;
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_SBP);
if(xfer == NULL){
return NULL;
}
@@ -1444,8 +1444,6 @@ END_DEBUG
if (sbp_status->dead) {
if (sdev->path)
xpt_freeze_devq(sdev->path, 1);
- sbp_show_sdev_info(sdev, 2);
- printf("reset agent\n");
sbp_agent_reset(sdev, 0);
}
@@ -1675,7 +1673,7 @@ END_DEBUG
return (ENXIO);
}
- xfer = fw_xfer_alloc();
+ xfer = fw_xfer_alloc(M_SBP);
xfer->act.hand = sbp_recv;
xfer->act_type = FWACT_XFER;
#if NEED_RESPONSE
@@ -1714,11 +1712,8 @@ END_DEBUG
continue;
for (j = 0; j < target->num_lun; j++) {
sdev = &target->luns[j];
- if (sdev->status == SBP_DEV_ATTACHED) {
- sbp_show_sdev_info(sdev, 2);
- printf("logout\n");
+ if (sdev->status == SBP_DEV_ATTACHED)
sbp_mgm_orb(sdev, ORB_FUN_LGO);
- }
}
}
return 0;
@@ -1797,16 +1792,21 @@ sbp_timeout(void *arg)
{
struct sbp_ocb *ocb = (struct sbp_ocb *)arg;
struct sbp_dev *sdev = ocb->sdev;
+#if 0
int s;
+#endif
sbp_show_sdev_info(sdev, 2);
printf("request timeout ... requeue\n");
- /* XXX need reset? */
-
+ /* XXX need bus reset? */
+#if 0
s = splfw();
sbp_abort_all_ocbs(sdev, CAM_CMD_TIMEOUT);
splx(s);
+#else
+ sbp_agent_reset(sdev, 0);
+#endif
return;
}
@@ -2307,7 +2307,7 @@ sbp_abort_ocb(struct sbp_ocb *ocb, int status)
struct sbp_dev *sdev;
sdev = ocb->sdev;
-SBP_DEBUG(0)
+SBP_DEBUG(1)
sbp_show_sdev_info(sdev, 2);
printf("sbp_abort_ocb 0x%x\n", status);
if (ocb->ccb != NULL)
OpenPOWER on IntegriCloud