aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeff Kirsher <jeffrey.t.kirsher@intel.com>2008-11-14 06:45:23 +0000
committerGreg Kroah-Hartman <gregkh@suse.de>2009-01-18 10:35:40 -0800
commit47ac4b80b1f4d83d66ff6b2417eec1992ac7fa63 (patch)
tree8a357a0e9615d90fae7f0cb594d82b518e866c39
parent3414be979fa6166cc6c296d0b1dc1f694fceb2ed (diff)
e1000e: fix IPMI traffic
commit eb7c3adb1ca92450870dbb0d347fc986cd5e2af4 upstream. Some users reported that they have machines with BMCs enabled that cannot receive IPMI traffic after e1000e is loaded. http://marc.info/?l=e1000-devel&m=121909039127414&w=2 http://marc.info/?l=e1000-devel&m=121365543823387&w=2 This fixes the issue if they load with the new parameter = 0 by disabling crc stripping, but leaves the performance feature on for most users. Based on work done by Hong Zhang. Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: Jesse Brandeburg <jesse.brandeburg@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net> Cc: Bryon Roche <kain@kain.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/net/e1000e/e1000.h5
-rw-r--r--drivers/net/e1000e/netdev.c23
-rw-r--r--drivers/net/e1000e/param.c25
3 files changed, 51 insertions, 2 deletions
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 5ea6b60fa37..4ee3d974af4 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -283,6 +283,7 @@ struct e1000_adapter {
unsigned long led_status;
unsigned int flags;
+ unsigned int flags2;
struct work_struct downshift_task;
struct work_struct update_phy_task;
};
@@ -290,6 +291,7 @@ struct e1000_adapter {
struct e1000_info {
enum e1000_mac_type mac;
unsigned int flags;
+ unsigned int flags2;
u32 pba;
s32 (*get_variants)(struct e1000_adapter *);
struct e1000_mac_operations *mac_ops;
@@ -330,6 +332,9 @@ struct e1000_info {
#define FLAG_RX_RESTART_NOW (1 << 30)
#define FLAG_MSI_TEST_FAILED (1 << 31)
+/* CRC Stripping defines */
+#define FLAG2_CRC_STRIPPING (1 << 0)
+
#define E1000_RX_DESC_PS(R, i) \
(&(((union e1000_rx_desc_packet_split *)((R).desc))[i]))
#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i]))
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c
index 660c85a070b..c4769828364 100644
--- a/drivers/net/e1000e/netdev.c
+++ b/drivers/net/e1000e/netdev.c
@@ -497,6 +497,10 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter,
goto next_desc;
}
+ /* adjust length to remove Ethernet CRC */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
+ length -= 4;
+
total_rx_bytes += length;
total_rx_packets++;
@@ -802,6 +806,10 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
pci_dma_sync_single_for_device(pdev, ps_page->dma,
PAGE_SIZE, PCI_DMA_FROMDEVICE);
+ /* remove the CRC */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
+ l1 -= 4;
+
skb_put(skb, l1);
goto copydone;
} /* if */
@@ -823,6 +831,12 @@ static bool e1000_clean_rx_irq_ps(struct e1000_adapter *adapter,
skb->truesize += length;
}
+ /* strip the ethernet crc, problem is we're using pages now so
+ * this whole operation can get a little cpu intensive
+ */
+ if (!(adapter->flags2 & FLAG2_CRC_STRIPPING))
+ pskb_trim(skb, skb->len - 4);
+
copydone:
total_rx_bytes += skb->len;
total_rx_packets++;
@@ -1987,8 +2001,12 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
else
rctl |= E1000_RCTL_LPE;
- /* Enable hardware CRC frame stripping */
- rctl |= E1000_RCTL_SECRC;
+ /* Some systems expect that the CRC is included in SMBUS traffic. The
+ * hardware strips the CRC before sending to both SMBUS (BMC) and to
+ * host memory when this is enabled
+ */
+ if (adapter->flags2 & FLAG2_CRC_STRIPPING)
+ rctl |= E1000_RCTL_SECRC;
/* Setup buffer sizes */
rctl &= ~E1000_RCTL_SZ_4096;
@@ -4412,6 +4430,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
adapter->ei = ei;
adapter->pba = ei->pba;
adapter->flags = ei->flags;
+ adapter->flags2 = ei->flags2;
adapter->hw.adapter = adapter;
adapter->hw.mac.type = ei->mac;
adapter->msg_enable = (1 << NETIF_MSG_DRV | NETIF_MSG_PROBE) - 1;
diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c
index d91dbf7ba43..a7c8b995893 100644
--- a/drivers/net/e1000e/param.c
+++ b/drivers/net/e1000e/param.c
@@ -142,6 +142,16 @@ E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround");
*/
E1000_PARAM(WriteProtectNVM, "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]");
+/*
+ * Enable CRC Stripping
+ *
+ * Valid Range: 0, 1
+ *
+ * Default Value: 1 (enabled)
+ */
+E1000_PARAM(CrcStripping, "Enable CRC Stripping, disable if your BMC needs " \
+ "the CRC");
+
struct e1000_option {
enum { enable_option, range_option, list_option } type;
const char *name;
@@ -377,6 +387,21 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter)
adapter->flags |= FLAG_SMART_POWER_DOWN;
}
}
+ { /* CRC Stripping */
+ const struct e1000_option opt = {
+ .type = enable_option,
+ .name = "CRC Stripping",
+ .err = "defaulting to enabled",
+ .def = OPTION_ENABLED
+ };
+
+ if (num_CrcStripping > bd) {
+ unsigned int crc_stripping = CrcStripping[bd];
+ e1000_validate_option(&crc_stripping, &opt, adapter);
+ if (crc_stripping == OPTION_ENABLED)
+ adapter->flags2 |= FLAG2_CRC_STRIPPING;
+ }
+ }
{ /* Kumeran Lock Loss Workaround */
const struct e1000_option opt = {
.type = enable_option,