ixgbe: Improve reset coordination between the PF and the VF
authorGreg Rose <gregory.v.rose@intel.com>
Fri, 22 Jan 2010 22:46:40 +0000 (22:46 +0000)
committerDavid S. Miller <davem@davemloft.net>
Sat, 23 Jan 2010 09:13:55 +0000 (01:13 -0800)
Inadequate coordination between the PF driver and the VF driver results
in tx hangs in the VF driver when you perform certain actions that will
lead to a re-init of the PF.  Add feature to notify active VFs when the PF
is about to re-initialize so that the VFs can take appropriate action.

Signed-off-by: Greg Rose <gregory.v.rose@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ixgbe/ixgbe_main.c
drivers/net/ixgbe/ixgbe_sriov.c
drivers/net/ixgbe/ixgbe_sriov.h

index b96afd98fa3df46d11f7b89620398849dd7c491b..ee41d331a35f67b96aea851e65db981630e21e5f 100644 (file)
@@ -3203,6 +3203,17 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
        /* signal that we are down to the interrupt handler */
        set_bit(__IXGBE_DOWN, &adapter->state);
 
+       /* disable receive for all VFs and wait one second */
+       if (adapter->num_vfs) {
+               for (i = 0 ; i < adapter->num_vfs; i++)
+                       adapter->vfinfo[i].clear_to_send = 0;
+
+               /* ping all the active vfs to let them know we are going down */
+               ixgbe_ping_all_vfs(adapter);
+               /* Disable all VFTE/VFRE TX/RX */
+               ixgbe_disable_tx_rx(adapter);
+       }
+
        /* disable receives */
        rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
        IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl & ~IXGBE_RXCTRL_RXEN);
index 74bca74d57c19ffdbe67c460f8a07fa7fb16060a..d4cd20f301990e576cc12ecf24f71eb1908c5371 100644 (file)
@@ -334,3 +334,29 @@ void ixgbe_msg_task(struct ixgbe_adapter *adapter)
        }
 }
 
+void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+
+       /* disable transmit and receive for all vfs */
+       IXGBE_WRITE_REG(hw, IXGBE_VFTE(0), 0);
+       IXGBE_WRITE_REG(hw, IXGBE_VFTE(1), 0);
+
+       IXGBE_WRITE_REG(hw, IXGBE_VFRE(0), 0);
+       IXGBE_WRITE_REG(hw, IXGBE_VFRE(1), 0);
+}
+
+void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter)
+{
+       struct ixgbe_hw *hw = &adapter->hw;
+       u32 ping;
+       int i;
+
+       for (i = 0 ; i < adapter->num_vfs; i++) {
+               ping = IXGBE_PF_CONTROL_MSG;
+               if (adapter->vfinfo[i].clear_to_send)
+                       ping |= IXGBE_VT_MSGTYPE_CTS;
+               ixgbe_write_mbx(hw, &ping, 1, i);
+       }
+}
+
index 664b237eacb93cb2f2601a41c74fbd9619ee4a2e..51d1106c45a1fec2d3074e4098cbb76e2698a6fc 100644 (file)
@@ -39,6 +39,8 @@ void ixgbe_msg_task(struct ixgbe_adapter *adapter);
 int ixgbe_set_vf_mac(struct ixgbe_adapter *adapter,
                      int vf, unsigned char *mac_addr);
 int ixgbe_vf_configuration(struct pci_dev *pdev, unsigned int event_mask);
+void ixgbe_disable_tx_rx(struct ixgbe_adapter *adapter);
+void ixgbe_ping_all_vfs(struct ixgbe_adapter *adapter);
 void ixgbe_dump_registers(struct ixgbe_adapter *adapter);
 
 #endif /* _IXGBE_SRIOV_H_ */