From 48249fe0c8fa01065bd10c670795af4db458846c Mon Sep 17 00:00:00 2001 From: Hidetoshi Shimokawa Date: Mon, 3 Feb 2003 07:33:31 +0000 Subject: [PATCH] - 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(). --- sys/dev/firewire/firewire.c | 24 +++++++++++++----------- sys/dev/firewire/firewirereg.h | 4 +++- sys/dev/firewire/fwdev.c | 6 +++--- sys/dev/firewire/fwmem.c | 2 +- sys/dev/firewire/fwohci.c | 27 +++++++++++++++++---------- sys/dev/firewire/if_fwe.c | 2 +- sys/dev/firewire/sbp.c | 28 ++++++++++++++-------------- 7 files changed, 52 insertions(+), 41 deletions(-) diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c index 77c1ce67fee9..60cc4873ee50 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 @@ fw_bus_explore(struct firewire_comm *fc ) 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 7eb9e024e99f..108f967ec231 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 1ef9ec4460bb..13c84a3849fe 100644 --- a/sys/dev/firewire/fwdev.c +++ b/sys/dev/firewire/fwdev.c @@ -455,7 +455,7 @@ fw_write (dev_t dev, struct uio *uio, int ioflag) } #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 @@ fw_ioctl (dev_t dev, u_long cmd, caddr_t data, int flag, fw_proc *td) 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 2f59253d5c87..b755dd2bb62b 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 3889d2e90be6..d3e100019a2d 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 @@ fwohci_txd(struct fwohci_softc *sc, struct fwohci_dbch *dbch) 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 1b7885db43fe..3f428df45fde 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 e37727b7aa87..096698d029d4 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)