Skip to content

Commit

Permalink
[intel] Apply PBS/PBA errata workaround only to ICH8 PCI device IDs
Browse files Browse the repository at this point in the history
ICH8 devices have an errata which requires us to reconfigure the
packet buffer size (PBS) register, and correspondingly adjust the
packet buffer allocation (PBA) register.  The "Intel I/O Controller
Hub ICH8/9/10 and 82566/82567/82562V Software Developer's Manual"
notes for the PBS register that:

  10.4.20   Packet Buffer Size - PBS (01008h; R/W)

  Note: The default setting of this register is 20 KB and is
        incorrect. This register must be programmed to 16 KB.

  Initial value: 0014h
                 0018h (ICH9/ICH10)

It is unclear from this comment precisely which devices require the
workaround to be applied.  We currently attempt to err on the side of
caution: if we detect an initial value of either 0x14 or 0x18 then the
workaround will be applied.  If the workaround is applied
unnecessarily, then the effect should be just that we use less than
the full amount of the available packet buffer memory.

Unfortunately this approach does not play nicely with other device
drivers.  For example, the Linux e1000e driver will rewrite PBA while
assuming that PBS still contains the default value, which can result
in inconsistent values between the two registers, and a corresponding
inability to transmit or receive packets.  Even more unfortunately,
the contents of PBS and PBA are not reset by anything less than a
power cycle, meaning that this error condition will survive a hardware
reset.

The Linux driver (written and maintained by Intel) applies the PBS/PBA
errata workaround only for devices in the ICH8 family, identified via
the PCI device ID.  Adopt a similar approach, using the PCI_ROM()
driver data field to indicate when the workaround is required.

Reported-by: Donald Bindner <dbindner@truman.edu>
Debugged-by: Donald Bindner <dbindner@truman.edu>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
mcb30 committed Aug 20, 2014
1 parent d461b8d commit ead70bf
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 13 deletions.
27 changes: 14 additions & 13 deletions src/drivers/net/intel.c
Expand Up @@ -294,10 +294,10 @@ static int intel_reset ( struct intel_nic *intel ) {
/* Force RX and TX packet buffer allocation, to work around an
* errata in ICH devices.
*/
pbs = readl ( intel->regs + INTEL_PBS );
if ( ( pbs == 0x14 ) || ( pbs == 0x18 ) ) {
if ( intel->flags & INTEL_PBS_ERRATA ) {
DBGC ( intel, "INTEL %p WARNING: applying ICH PBS/PBA errata\n",
intel );
pbs = readl ( intel->regs + INTEL_PBS );
pba = readl ( intel->regs + INTEL_PBA );
writel ( 0x08, intel->regs + INTEL_PBA );
writel ( 0x10, intel->regs + INTEL_PBS );
Expand Down Expand Up @@ -816,6 +816,7 @@ static int intel_probe ( struct pci_device *pci ) {
netdev->dev = &pci->dev;
memset ( intel, 0, sizeof ( *intel ) );
intel->port = PCI_FUNC ( pci->busdevfn );
intel->flags = pci->id->driver_data;
intel_init_ring ( &intel->tx, INTEL_NUM_TX_DESC, INTEL_TD );
intel_init_ring ( &intel->rx, INTEL_NUM_RX_DESC, INTEL_RD );

Expand Down Expand Up @@ -911,11 +912,11 @@ static struct pci_device_id intel_nics[] = {
PCI_ROM ( 0x8086, 0x1026, "82545gm", "82545GM", 0 ),
PCI_ROM ( 0x8086, 0x1027, "82545gm-1", "82545GM", 0 ),
PCI_ROM ( 0x8086, 0x1028, "82545gm-2", "82545GM", 0 ),
PCI_ROM ( 0x8086, 0x1049, "82566mm", "82566MM", 0 ),
PCI_ROM ( 0x8086, 0x104a, "82566dm", "82566DM", 0 ),
PCI_ROM ( 0x8086, 0x104b, "82566dc", "82566DC", 0 ),
PCI_ROM ( 0x8086, 0x104c, "82562v", "82562V 10/100", 0 ),
PCI_ROM ( 0x8086, 0x104d, "82566mc", "82566MC", 0 ),
PCI_ROM ( 0x8086, 0x1049, "82566mm", "82566MM", INTEL_PBS_ERRATA ),
PCI_ROM ( 0x8086, 0x104a, "82566dm", "82566DM", INTEL_PBS_ERRATA ),
PCI_ROM ( 0x8086, 0x104b, "82566dc", "82566DC", INTEL_PBS_ERRATA ),
PCI_ROM ( 0x8086, 0x104c, "82562v", "82562V", INTEL_PBS_ERRATA ),
PCI_ROM ( 0x8086, 0x104d, "82566mc", "82566MC", INTEL_PBS_ERRATA ),
PCI_ROM ( 0x8086, 0x105e, "82571eb", "82571EB", 0 ),
PCI_ROM ( 0x8086, 0x105f, "82571eb-1", "82571EB", 0 ),
PCI_ROM ( 0x8086, 0x1060, "82571eb-2", "82571EB", 0 ),
Expand Down Expand Up @@ -948,11 +949,11 @@ static struct pci_device_id intel_nics[] = {
PCI_ROM ( 0x8086, 0x10bc, "82571eb", "82571EB (Copper)", 0 ),
PCI_ROM ( 0x8086, 0x10bd, "82566dm-2", "82566DM-2", 0 ),
PCI_ROM ( 0x8086, 0x10bf, "82567lf", "82567LF", 0 ),
PCI_ROM ( 0x8086, 0x10c0, "82562v-2", "82562V-2 10/100", 0 ),
PCI_ROM ( 0x8086, 0x10c2, "82562g-2", "82562G-2 10/100", 0 ),
PCI_ROM ( 0x8086, 0x10c3, "82562gt-2", "82562GT-2 10/100", 0 ),
PCI_ROM ( 0x8086, 0x10c4, "82562gt", "82562GT 10/100", 0 ),
PCI_ROM ( 0x8086, 0x10c5, "82562g", "82562G 10/100", 0 ),
PCI_ROM ( 0x8086, 0x10c0, "82562v-2", "82562V-2", 0 ),
PCI_ROM ( 0x8086, 0x10c2, "82562g-2", "82562G-2", 0 ),
PCI_ROM ( 0x8086, 0x10c3, "82562gt-2", "82562GT-2", 0 ),
PCI_ROM ( 0x8086, 0x10c4, "82562gt", "82562GT", INTEL_PBS_ERRATA ),
PCI_ROM ( 0x8086, 0x10c5, "82562g", "82562G", INTEL_PBS_ERRATA ),
PCI_ROM ( 0x8086, 0x10c9, "82576", "82576", 0 ),
PCI_ROM ( 0x8086, 0x10cb, "82567v", "82567V", 0 ),
PCI_ROM ( 0x8086, 0x10cc, "82567lm-2", "82567LM-2", 0 ),
Expand All @@ -975,7 +976,7 @@ static struct pci_device_id intel_nics[] = {
PCI_ROM ( 0x8086, 0x10f0, "82578dc", "82578DC", 0 ),
PCI_ROM ( 0x8086, 0x10f5, "82567lm", "82567LM", 0 ),
PCI_ROM ( 0x8086, 0x10f6, "82574l", "82574L", 0 ),
PCI_ROM ( 0x8086, 0x1501, "82567v-3", "82567V-3", 0 ),
PCI_ROM ( 0x8086, 0x1501, "82567v-3", "82567V-3", INTEL_PBS_ERRATA ),
PCI_ROM ( 0x8086, 0x1502, "82579lm", "82579LM", 0 ),
PCI_ROM ( 0x8086, 0x1503, "82579v", "82579V", 0 ),
PCI_ROM ( 0x8086, 0x150a, "82576ns", "82576NS", 0 ),
Expand Down
8 changes: 8 additions & 0 deletions src/drivers/net/intel.h
Expand Up @@ -229,6 +229,8 @@ struct intel_nic {
void *regs;
/** Port number (for multi-port devices) */
unsigned int port;
/** Flags */
unsigned int flags;

/** EEPROM */
struct nvs_device eeprom;
Expand All @@ -245,6 +247,12 @@ struct intel_nic {
struct io_buffer *rx_iobuf[INTEL_NUM_RX_DESC];
};

/** Driver flags */
enum intel_flags {
/** PBS/PBA errata workaround required */
INTEL_PBS_ERRATA = 0x0001,
};

extern int intel_create_ring ( struct intel_nic *intel,
struct intel_ring *ring );
extern void intel_destroy_ring ( struct intel_nic *intel,
Expand Down

0 comments on commit ead70bf

Please sign in to comment.