1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-26 11:47:31 +00:00

firewire/fwohci

- Drain fwohci TX queue first then drain xfer queue which has not started.
- Check validity of the received packet length.
- Don't allocate too large buffer for xfer receive buf.

sbp
- Fix panic for some CROM which doesn't have a text leaf.
	This could fix the PR kern/48129 but no feedback has been gotten from
	the originator yet.
- Put back some M_NOWAIT flags into malloc which could be called
	in interrupt context for 4-stable.
This commit is contained in:
Hidetoshi Shimokawa 2003-02-13 13:35:57 +00:00
parent ba5014037c
commit 627d85fbdd
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=110798
4 changed files with 75 additions and 50 deletions

View File

@ -505,7 +505,7 @@ firewire_shutdown( device_t dev )
static void
firewire_xferq_drain(struct fw_xferq *xferq)
fw_xferq_drain(struct fw_xferq *xferq)
{
struct fw_xfer *xfer;
@ -524,6 +524,17 @@ firewire_xferq_drain(struct fw_xferq *xferq)
}
}
void
fw_drain_txq(struct firewire_comm *fc)
{
int i;
fw_xferq_drain(fc->atq);
fw_xferq_drain(fc->ats);
for(i = 0; i < fc->nisodma; i++)
fw_xferq_drain(fc->it[i]);
}
/*
* Called after bus reset.
*/
@ -540,12 +551,6 @@ fw_busreset(struct firewire_comm *fc)
break;
}
fc->status = FWBUSRESET;
/* XXX: discard all queued packet */
firewire_xferq_drain(fc->atq);
firewire_xferq_drain(fc->ats);
for(i = 0; i < fc->nisodma; i++)
firewire_xferq_drain(fc->it[i]);
CSRARC(fc, STATE_CLEAR)
= 1 << 23 | 0 << 17 | 1 << 16 | 1 << 15 | 1 << 14 ;
CSRARC(fc, STATE_SET) = CSRARC(fc, STATE_CLEAR);
@ -1772,7 +1777,7 @@ fw_rcv(struct firewire_comm* fc, caddr_t buf, u_int len, u_int sub, u_int off, u
ntohl(fp->mode.rreqq.dest_lo),
fp->mode.common.tcode);
if (fc->status == FWBUSRESET) {
printf("fw_rcv: cannot response(bus reset)!\n");
printf("fw_rcv: cannot respond(bus reset)!\n");
goto err;
}
xfer = fw_xfer_alloc(M_FWXFER);

View File

@ -326,6 +326,7 @@ void fw_asy_callback __P((struct fw_xfer *));
struct fw_device *fw_noderesolve_nodeid __P((struct firewire_comm *, int));
struct fw_device *fw_noderesolve_eui64 __P((struct firewire_comm *, struct fw_eui64 *));
struct fw_bind *fw_bindlookup __P((struct firewire_comm *, u_int32_t, u_int32_t));
void fw_drain_txq __P((struct firewire_comm *));
extern int firewire_debug;

View File

@ -1774,27 +1774,10 @@ fwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count)
OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN);
sc->atrs.xferq.flag &= ~FWXFERQ_RUNNING;
#if 0
for( i = 0 ; i < fc->nisodma ; i ++ ){
OWRITE(sc, OHCI_IRCTLCLR(i), OHCI_CNTL_DMA_RUN);
OWRITE(sc, OHCI_ITCTLCLR(i), OHCI_CNTL_DMA_RUN);
}
#endif
fw_busreset(fc);
/* XXX need to wait DMA to stop */
#ifndef ACK_ALL
OWRITE(sc, FWOHCI_INTSTATCLR, OHCI_INT_PHY_BUS_R);
#endif
#if 0
/* 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_busreset(fc);
OWRITE(sc, OHCI_AREQHI, 1 << 31);
/* XXX insecure ?? */
@ -1902,6 +1885,7 @@ fwohci_intr_body(struct fwohci_softc *sc, u_int32_t stat, int count)
fwohci_txd(sc, &sc->atrs);
fwohci_arcv(sc, &sc->arrs, -1);
fwohci_arcv(sc, &sc->arrq, -1);
fw_drain_txq(fc);
#endif
fw_sidrcv(fc, buf, plen, 0);
}
@ -2564,11 +2548,11 @@ device_printf(sc->fc.dev, "%04x %2x 0x%08x 0x%08x 0x%08x 0x%08x\n", len,
fwohci_irx_enable(fc, dmach);
}
#define PLEN(x) (((ntohs(x))+0x3) & ~0x3)
#define PLEN(x) roundup2(ntohs(x), sizeof(u_int32_t))
static int
fwohci_get_plen(struct fwohci_softc *sc, struct fw_pkt *fp, int hlen)
fwohci_get_plen(struct fwohci_softc *sc, struct fwohci_dbch *dbch, struct fw_pkt *fp, int hlen)
{
int i;
int i, r;
for( i = 4; i < hlen ; i+=4){
fp->mode.ld[i/4] = htonl(fp->mode.ld[i/4]);
@ -2576,32 +2560,49 @@ fwohci_get_plen(struct fwohci_softc *sc, struct fw_pkt *fp, int hlen)
switch(fp->mode.common.tcode){
case FWTCODE_RREQQ:
return sizeof(fp->mode.rreqq) + sizeof(u_int32_t);
r = sizeof(fp->mode.rreqq) + sizeof(u_int32_t);
break;
case FWTCODE_WRES:
return sizeof(fp->mode.wres) + sizeof(u_int32_t);
r = sizeof(fp->mode.wres) + sizeof(u_int32_t);
break;
case FWTCODE_WREQQ:
return sizeof(fp->mode.wreqq) + sizeof(u_int32_t);
r = sizeof(fp->mode.wreqq) + sizeof(u_int32_t);
break;
case FWTCODE_RREQB:
return sizeof(fp->mode.rreqb) + sizeof(u_int32_t);
r = sizeof(fp->mode.rreqb) + sizeof(u_int32_t);
break;
case FWTCODE_RRESQ:
return sizeof(fp->mode.rresq) + sizeof(u_int32_t);
r = sizeof(fp->mode.rresq) + sizeof(u_int32_t);
break;
case FWTCODE_WREQB:
return sizeof(struct fw_asyhdr) + PLEN(fp->mode.wreqb.len)
r = sizeof(struct fw_asyhdr) + PLEN(fp->mode.wreqb.len)
+ sizeof(u_int32_t);
break;
case FWTCODE_LREQ:
return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lreq.len)
r = sizeof(struct fw_asyhdr) + PLEN(fp->mode.lreq.len)
+ sizeof(u_int32_t);
break;
case FWTCODE_RRESB:
return sizeof(struct fw_asyhdr) + PLEN(fp->mode.rresb.len)
r = sizeof(struct fw_asyhdr) + PLEN(fp->mode.rresb.len)
+ sizeof(u_int32_t);
break;
case FWTCODE_LRES:
return sizeof(struct fw_asyhdr) + PLEN(fp->mode.lres.len)
r = sizeof(struct fw_asyhdr) + PLEN(fp->mode.lres.len)
+ sizeof(u_int32_t);
break;
case FWOHCITCODE_PHY:
return 16;
r = 16;
break;
default:
device_printf(sc->fc.dev, "Unknown tcode %d\n",
fp->mode.common.tcode);
r = 0;
}
device_printf(sc->fc.dev, "Unknown tcode %d\n", fp->mode.common.tcode);
return 0;
if (r > dbch->xferq.psize) {
device_printf(sc->fc.dev, "Invalid packet length %d\n", r);
/* panic ? */
}
return r;
}
static void
@ -2655,7 +2656,8 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
#endif
fp=(struct fw_pkt *)dbch->frag.buf;
dbch->frag.plen
= fwohci_get_plen(sc, fp, hlen);
= fwohci_get_plen(sc,
dbch, fp, hlen);
if (dbch->frag.plen == 0)
goto out;
}
@ -2695,7 +2697,8 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
goto out;
}
if (len >= hlen) {
plen = fwohci_get_plen(sc, fp, hlen);
plen = fwohci_get_plen(sc,
dbch, fp, hlen);
if (plen == 0)
goto out;
plen = (plen + 3) & ~3;
@ -2705,8 +2708,7 @@ fwohci_arcv(struct fwohci_softc *sc, struct fwohci_dbch *dbch, int count)
len -= hlen;
}
if(resCount > 0 || len > 0){
buf = malloc( dbch->xferq.psize,
M_FW, M_NOWAIT);
buf = malloc(plen, M_FW, M_NOWAIT);
if(buf == NULL){
printf("cannot malloc!\n");
free(db_tr->buf, M_FW);

View File

@ -521,13 +521,13 @@ sbp_get_text_leaf(struct fw_device *fwdev, int key, char *buf, int len)
chdr = (struct csrhdr *)&fwdev->csrrom[0];
creg = (struct csrreg *)chdr;
creg += chdr->info_len;
for( i = chdr->info_len + 4; i <= fwdev->rommax; i+=4){
for( i = chdr->info_len + 4; i <= fwdev->rommax - 4; i+=4){
if((creg++)->key == key){
found = 1;
break;
}
}
if (!found) {
if (!found || creg->key != CROM_TEXTLEAF) {
strncpy(buf, nullstr, len);
return;
}
@ -780,7 +780,13 @@ END_DEBUG
static void
sbp_cam_scan_lun(struct sbp_dev *sdev)
{
union ccb *ccb = malloc(sizeof(union ccb), M_SBP, M_ZERO);
union ccb *ccb;
ccb = malloc(sizeof(union ccb), M_SBP, M_NOWAIT | M_ZERO);
if (ccb == NULL) {
printf("sbp_cam_scan_lun: malloc failed\n");
return;
}
SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);
@ -840,9 +846,20 @@ sbp_ping_unit(struct sbp_dev *sdev)
union ccb *ccb;
struct scsi_inquiry_data *inq_buf;
ccb = malloc(sizeof(union ccb), M_SBP, M_ZERO);
ccb = malloc(sizeof(union ccb), M_SBP, M_NOWAIT | M_ZERO);
if (ccb == NULL) {
printf("sbp_ping_unit: malloc failed\n");
return;
}
inq_buf = (struct scsi_inquiry_data *)
malloc(sizeof(*inq_buf), M_SBP, 0);
malloc(sizeof(*inq_buf), M_SBP, M_NOWAIT);
if (inq_buf == NULL) {
free(ccb, M_SBP);
printf("sbp_ping_unit: malloc failed\n");
return;
}
SBP_DEBUG(0)
sbp_show_sdev_info(sdev, 2);