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:
parent
ba5014037c
commit
627d85fbdd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=110798
sys/dev/firewire
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user