From 597f22d6aa46105d69648a5c042d1fabe182c6f6 Mon Sep 17 00:00:00 2001 From: Don Skidmore Date: Tue, 9 Jun 2015 16:52:02 -0700 Subject: [PATCH] ixgbe: add support for interrupts from X550 external PHY This patch adds support for receiving interrupts from a external copper PHY for the X550 part. This includes enabling, detection as well as re-enablement. Signed-off-by: Don Skidmore Tested-by: Krishneil Singh Signed-off-by: Jeff Kirsher --- drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 + drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 636f9e350162..ac3ac2a20386 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h @@ -643,6 +643,7 @@ struct ixgbe_adapter { #define IXGBE_FLAG2_RSS_FIELD_IPV4_UDP (u32)(1 << 8) #define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP (u32)(1 << 9) #define IXGBE_FLAG2_PTP_PPS_ENABLED (u32)(1 << 10) +#define IXGBE_FLAG2_PHY_INTERRUPT (u32)(1 << 11) /* Tx fast path data */ int num_tx_queues; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 30adfb8f0814..1c3477a974bc 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -2388,6 +2388,8 @@ static void ixgbe_check_overtemp_subtask(struct ixgbe_adapter *adapter) break; default: + if (adapter->hw.mac.type >= ixgbe_mac_X540) + return; if (!(eicr & IXGBE_EICR_GPI_SDP0(hw))) return; break; @@ -2572,6 +2574,8 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues, case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + if (adapter->hw.phy.type == ixgbe_phy_x550em_ext_t) + mask |= IXGBE_EICR_GPI_SDP0_X540; mask |= IXGBE_EIMS_ECC; mask |= IXGBE_EIMS_MAILBOX; break; @@ -2626,6 +2630,13 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data) case ixgbe_mac_X540: case ixgbe_mac_X550: case ixgbe_mac_X550EM_x: + if (hw->phy.type == ixgbe_phy_x550em_ext_t && + (eicr & IXGBE_EICR_GPI_SDP0_X540)) { + adapter->flags2 |= IXGBE_FLAG2_PHY_INTERRUPT; + ixgbe_service_event_schedule(adapter); + IXGBE_WRITE_REG(hw, IXGBE_EICR, + IXGBE_EICR_GPI_SDP0_X540); + } if (eicr & IXGBE_EICR_ECC) { e_info(link, "Received ECC Err, initiating reset\n"); adapter->flags2 |= IXGBE_FLAG2_RESET_REQUESTED; @@ -6733,6 +6744,26 @@ static void ixgbe_service_timer(unsigned long data) ixgbe_service_event_schedule(adapter); } +static void ixgbe_phy_interrupt_subtask(struct ixgbe_adapter *adapter) +{ + struct ixgbe_hw *hw = &adapter->hw; + u32 status; + + if (!(adapter->flags2 & IXGBE_FLAG2_PHY_INTERRUPT)) + return; + + adapter->flags2 &= ~IXGBE_FLAG2_PHY_INTERRUPT; + + if (!hw->phy.ops.handle_lasi) + return; + + status = hw->phy.ops.handle_lasi(&adapter->hw); + if (status != IXGBE_ERR_OVERTEMP) + return; + + e_crit(drv, "%s\n", ixgbe_overheat_msg); +} + static void ixgbe_reset_subtask(struct ixgbe_adapter *adapter) { if (!(adapter->flags2 & IXGBE_FLAG2_RESET_REQUESTED)) @@ -6774,6 +6805,7 @@ static void ixgbe_service_task(struct work_struct *work) return; } ixgbe_reset_subtask(adapter); + ixgbe_phy_interrupt_subtask(adapter); ixgbe_sfp_detection_subtask(adapter); ixgbe_sfp_link_config_subtask(adapter); ixgbe_check_overtemp_subtask(adapter); -- 2.30.2