|
@@ -151,6 +151,147 @@ static void ixgbe_ipsec_clear_hw_tables(struct ixgbe_adapter *adapter)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * ixgbe_ipsec_stop_data
|
|
|
+ * @adapter: board private structure
|
|
|
+ **/
|
|
|
+static void ixgbe_ipsec_stop_data(struct ixgbe_adapter *adapter)
|
|
|
+{
|
|
|
+ struct ixgbe_hw *hw = &adapter->hw;
|
|
|
+ bool link = adapter->link_up;
|
|
|
+ u32 t_rdy, r_rdy;
|
|
|
+ u32 limit;
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ /* halt data paths */
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
|
|
|
+ reg |= IXGBE_SECTXCTRL_TX_DIS;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, reg);
|
|
|
+
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
|
|
|
+ reg |= IXGBE_SECRXCTRL_RX_DIS;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, reg);
|
|
|
+
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+
|
|
|
+ /* If the tx fifo doesn't have link, but still has data,
|
|
|
+ * we can't clear the tx sec block. Set the MAC loopback
|
|
|
+ * before block clear
|
|
|
+ */
|
|
|
+ if (!link) {
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_MACC);
|
|
|
+ reg |= IXGBE_MACC_FLU;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_MACC, reg);
|
|
|
+
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
|
|
|
+ reg |= IXGBE_HLREG0_LPBK;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg);
|
|
|
+
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+ mdelay(3);
|
|
|
+ }
|
|
|
+
|
|
|
+ /* wait for the paths to empty */
|
|
|
+ limit = 20;
|
|
|
+ do {
|
|
|
+ mdelay(10);
|
|
|
+ t_rdy = IXGBE_READ_REG(hw, IXGBE_SECTXSTAT) &
|
|
|
+ IXGBE_SECTXSTAT_SECTX_RDY;
|
|
|
+ r_rdy = IXGBE_READ_REG(hw, IXGBE_SECRXSTAT) &
|
|
|
+ IXGBE_SECRXSTAT_SECRX_RDY;
|
|
|
+ } while (!t_rdy && !r_rdy && limit--);
|
|
|
+
|
|
|
+ /* undo loopback if we played with it earlier */
|
|
|
+ if (!link) {
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_MACC);
|
|
|
+ reg &= ~IXGBE_MACC_FLU;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_MACC, reg);
|
|
|
+
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_HLREG0);
|
|
|
+ reg &= ~IXGBE_HLREG0_LPBK;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_HLREG0, reg);
|
|
|
+
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ixgbe_ipsec_stop_engine
|
|
|
+ * @adapter: board private structure
|
|
|
+ **/
|
|
|
+static void ixgbe_ipsec_stop_engine(struct ixgbe_adapter *adapter)
|
|
|
+{
|
|
|
+ struct ixgbe_hw *hw = &adapter->hw;
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ ixgbe_ipsec_stop_data(adapter);
|
|
|
+
|
|
|
+ /* disable Rx and Tx SA lookup */
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_IPSTXIDX, 0);
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_IPSRXIDX, 0);
|
|
|
+
|
|
|
+ /* disable the Rx and Tx engines and full packet store-n-forward */
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_SECTXCTRL);
|
|
|
+ reg |= IXGBE_SECTXCTRL_SECTX_DIS;
|
|
|
+ reg &= ~IXGBE_SECTXCTRL_STORE_FORWARD;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, reg);
|
|
|
+
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_SECRXCTRL);
|
|
|
+ reg |= IXGBE_SECRXCTRL_SECRX_DIS;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, reg);
|
|
|
+
|
|
|
+ /* restore the "tx security buffer almost full threshold" to 0x250 */
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXBUFFAF, 0x250);
|
|
|
+
|
|
|
+ /* Set minimum IFG between packets back to the default 0x1 */
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
|
|
|
+ reg = (reg & 0xfffffff0) | 0x1;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg);
|
|
|
+
|
|
|
+ /* final set for normal (no ipsec offload) processing */
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, IXGBE_SECTXCTRL_SECTX_DIS);
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, IXGBE_SECRXCTRL_SECRX_DIS);
|
|
|
+
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * ixgbe_ipsec_start_engine
|
|
|
+ * @adapter: board private structure
|
|
|
+ *
|
|
|
+ * NOTE: this increases power consumption whether being used or not
|
|
|
+ **/
|
|
|
+static void ixgbe_ipsec_start_engine(struct ixgbe_adapter *adapter)
|
|
|
+{
|
|
|
+ struct ixgbe_hw *hw = &adapter->hw;
|
|
|
+ u32 reg;
|
|
|
+
|
|
|
+ ixgbe_ipsec_stop_data(adapter);
|
|
|
+
|
|
|
+ /* Set minimum IFG between packets to 3 */
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_SECTXMINIFG);
|
|
|
+ reg = (reg & 0xfffffff0) | 0x3;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXMINIFG, reg);
|
|
|
+
|
|
|
+ /* Set "tx security buffer almost full threshold" to 0x15 so that the
|
|
|
+ * almost full indication is generated only after buffer contains at
|
|
|
+ * least an entire jumbo packet.
|
|
|
+ */
|
|
|
+ reg = IXGBE_READ_REG(hw, IXGBE_SECTXBUFFAF);
|
|
|
+ reg = (reg & 0xfffffc00) | 0x15;
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXBUFFAF, reg);
|
|
|
+
|
|
|
+ /* restart the data paths by clearing the DISABLE bits */
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECRXCTRL, 0);
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_SECTXCTRL, IXGBE_SECTXCTRL_STORE_FORWARD);
|
|
|
+
|
|
|
+ /* enable Rx and Tx SA lookup */
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_IPSTXIDX, IXGBE_RXTXIDX_IPS_EN);
|
|
|
+ IXGBE_WRITE_REG(hw, IXGBE_IPSRXIDX, IXGBE_RXTXIDX_IPS_EN);
|
|
|
+
|
|
|
+ IXGBE_WRITE_FLUSH(hw);
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ixgbe_init_ipsec_offload - initialize security registers for IPSec operation
|
|
|
* @adapter: board private structure
|
|
@@ -158,4 +299,5 @@ static void ixgbe_ipsec_clear_hw_tables(struct ixgbe_adapter *adapter)
|
|
|
void ixgbe_init_ipsec_offload(struct ixgbe_adapter *adapter)
|
|
|
{
|
|
|
ixgbe_ipsec_clear_hw_tables(adapter);
|
|
|
+ ixgbe_ipsec_stop_engine(adapter);
|
|
|
}
|