Date: Thu, 24 Aug 2006 10:36:17 -0700 From: "David Christensen" <davidch@broadcom.com> To: "Gleb Smirnoff" <glebius@FreeBSD.org> Cc: brad@openbsd.org, oleg@FreeBSD.org, net@FreeBSD.org Subject: RE: bge(4) one packet wedge Message-ID: <09BFF2FA5EAB4A45B6655E151BBDD90301D43265@NT-IRVA-0750.brcm.ad.broadcom.com> In-Reply-To: <20060824075253.GH76666@cell.sick.ru>
next in thread | previous in thread | raw e-mail | index | archive | help
> On Wed, Aug 23, 2006 at 12:53:49PM -0700, David Christensen wrote: > D> This "lost interrupt" type of problem is addressed by the=20 > use of the > D> status_tag=20 > D> field in the status block. (Listed as bge_rsvd0 in the=20 > bge_status_block > D> structure).=20 > D> Everytime the status block is updated a new tag value is=20 > written to the > D> status block. =20 > D> When the ISR starts the driver should record the=20 > status_tag value. At > D> the end > D> of the ISR, the driver should compare the current=20 > status_tag value is > D> the status > D> block with the value recorded on entry to the ISR. If the=20 > values are > D> the same > D> then no additional status block updates have occurred so=20 > there shouldn't > D> be > D> any packets hanging around. If the values are different=20 > then additional > D> packets > D> or completions are waiting around so the ISR should loop=20 > around again. > D> At the=20 > D> end of the ISR the driver will write the status_tag value it last > D> handled to a > D> mailbox register, letting the hardware know the last=20 > status block update > D> handled. > D> If necessary the hardware will generate a new interrupt=20 > and start the > D> process over > D> again. > D>=20 > D> This entire process should be included in the Linux=20 > driver, I don't see > D> it being > D> used in the bge driver (bge_intr()). >=20 > In the Linux driver for the not tag capable controllers there=20 > is a following > comment and code: >=20 > /* In INTx mode, it is possible for the interrupt to arrive at > * the CPU before the status block posted prior to=20 > the interrupt. > * Reading the PCI State register will confirm whether the > * interrupt is ours and will flush the status block. > */ > if ((sblk->status & SD_STATUS_UPDATED) || > !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { >=20 > So, I tried to add (void)pci_read_config(sc->bge_dev,=20 > BGE_PCI_PCISTATE, 4) > to the bge_intr(). Unfortunately, this didn't help. >=20 This fix is really designed to handle bridges that haven't posted the status block memory write ahead of the PCI interrupt and I wouldn't expect it to=20 resolve the reported problem. A better solution would be to try and minimize the time between the last status block check and the time the interrupt is re-enabled. Unfortunately I don't think the problem can be completely eliminated with even the most creative coding solutions but I'd be happy to be proven wrong. Dave
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?09BFF2FA5EAB4A45B6655E151BBDD90301D43265>