- 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:
parent
1b978d453b
commit
48249fe0c8
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user