- 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().
This commit is contained in:
Hidetoshi Shimokawa 2003-02-03 07:33:31 +00:00
parent 1b978d453b
commit 48249fe0c8
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=110269
7 changed files with 52 additions and 41 deletions

View file

@ -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;
}

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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 */

View file

@ -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;
}

View file

@ -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)