diff options
Diffstat (limited to 'drivers/net/ethernet/intel/igc')
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc.h | 48 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_defines.h | 15 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_hw.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/igc/igc_main.c | 471 |
4 files changed, 534 insertions, 1 deletions
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h index 481b2ee694fa..2e819cac19e5 100644 --- a/drivers/net/ethernet/intel/igc/igc.h +++ b/drivers/net/ethernet/intel/igc/igc.h | |||
| @@ -28,15 +28,63 @@ | |||
| 28 | extern char igc_driver_name[]; | 28 | extern char igc_driver_name[]; |
| 29 | extern char igc_driver_version[]; | 29 | extern char igc_driver_version[]; |
| 30 | 30 | ||
| 31 | /* Transmit and receive queues */ | ||
| 32 | #define IGC_MAX_RX_QUEUES 4 | ||
| 33 | #define IGC_MAX_TX_QUEUES 4 | ||
| 34 | |||
| 35 | #define MAX_Q_VECTORS 8 | ||
| 36 | #define MAX_STD_JUMBO_FRAME_SIZE 9216 | ||
| 37 | |||
| 38 | enum igc_state_t { | ||
| 39 | __IGC_TESTING, | ||
| 40 | __IGC_RESETTING, | ||
| 41 | __IGC_DOWN, | ||
| 42 | __IGC_PTP_TX_IN_PROGRESS, | ||
| 43 | }; | ||
| 44 | |||
| 45 | struct igc_q_vector { | ||
| 46 | struct igc_adapter *adapter; /* backlink */ | ||
| 47 | |||
| 48 | struct napi_struct napi; | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct igc_mac_addr { | ||
| 52 | u8 addr[ETH_ALEN]; | ||
| 53 | u8 queue; | ||
| 54 | u8 state; /* bitmask */ | ||
| 55 | }; | ||
| 56 | |||
| 57 | #define IGC_MAC_STATE_DEFAULT 0x1 | ||
| 58 | #define IGC_MAC_STATE_MODIFIED 0x2 | ||
| 59 | #define IGC_MAC_STATE_IN_USE 0x4 | ||
| 60 | |||
| 31 | /* Board specific private data structure */ | 61 | /* Board specific private data structure */ |
| 32 | struct igc_adapter { | 62 | struct igc_adapter { |
| 63 | struct net_device *netdev; | ||
| 64 | |||
| 65 | unsigned long state; | ||
| 66 | unsigned int flags; | ||
| 67 | unsigned int num_q_vectors; | ||
| 68 | u16 link_speed; | ||
| 69 | u16 link_duplex; | ||
| 70 | |||
| 71 | u8 port_num; | ||
| 72 | |||
| 33 | u8 __iomem *io_addr; | 73 | u8 __iomem *io_addr; |
| 74 | struct work_struct watchdog_task; | ||
| 75 | |||
| 76 | int msg_enable; | ||
| 77 | u32 max_frame_size; | ||
| 34 | 78 | ||
| 35 | /* OS defined structs */ | 79 | /* OS defined structs */ |
| 36 | struct pci_dev *pdev; | 80 | struct pci_dev *pdev; |
| 37 | 81 | ||
| 38 | /* structs defined in igc_hw.h */ | 82 | /* structs defined in igc_hw.h */ |
| 39 | struct igc_hw hw; | 83 | struct igc_hw hw; |
| 84 | |||
| 85 | struct igc_q_vector *q_vector[MAX_Q_VECTORS]; | ||
| 86 | |||
| 87 | struct igc_mac_addr *mac_table; | ||
| 40 | }; | 88 | }; |
| 41 | 89 | ||
| 42 | #endif /* _IGC_H_ */ | 90 | #endif /* _IGC_H_ */ |
diff --git a/drivers/net/ethernet/intel/igc/igc_defines.h b/drivers/net/ethernet/intel/igc/igc_defines.h index d19dff1d6b74..c25f75ed9cd4 100644 --- a/drivers/net/ethernet/intel/igc/igc_defines.h +++ b/drivers/net/ethernet/intel/igc/igc_defines.h | |||
| @@ -4,10 +4,22 @@ | |||
| 4 | #ifndef _IGC_DEFINES_H_ | 4 | #ifndef _IGC_DEFINES_H_ |
| 5 | #define _IGC_DEFINES_H_ | 5 | #define _IGC_DEFINES_H_ |
| 6 | 6 | ||
| 7 | #define IGC_CTRL_EXT_DRV_LOAD 0x10000000 /* Drv loaded bit for FW */ | ||
| 8 | |||
| 7 | /* PCI Bus Info */ | 9 | /* PCI Bus Info */ |
| 8 | #define PCIE_DEVICE_CONTROL2 0x28 | 10 | #define PCIE_DEVICE_CONTROL2 0x28 |
| 9 | #define PCIE_DEVICE_CONTROL2_16ms 0x0005 | 11 | #define PCIE_DEVICE_CONTROL2_16ms 0x0005 |
| 10 | 12 | ||
| 13 | /* Receive Address | ||
| 14 | * Number of high/low register pairs in the RAR. The RAR (Receive Address | ||
| 15 | * Registers) holds the directed and multicast addresses that we monitor. | ||
| 16 | * Technically, we have 16 spots. However, we reserve one of these spots | ||
| 17 | * (RAR[15]) for our directed address used by controllers with | ||
| 18 | * manageability enabled, allowing us room for 15 multicast addresses. | ||
| 19 | */ | ||
| 20 | #define IGC_RAH_AV 0x80000000 /* Receive descriptor valid */ | ||
| 21 | #define IGC_RAH_POOL_1 0x00040000 | ||
| 22 | |||
| 11 | /* Error Codes */ | 23 | /* Error Codes */ |
| 12 | #define IGC_SUCCESS 0 | 24 | #define IGC_SUCCESS 0 |
| 13 | #define IGC_ERR_NVM 1 | 25 | #define IGC_ERR_NVM 1 |
| @@ -17,6 +29,9 @@ | |||
| 17 | #define IGC_ERR_MAC_INIT 5 | 29 | #define IGC_ERR_MAC_INIT 5 |
| 18 | #define IGC_ERR_RESET 9 | 30 | #define IGC_ERR_RESET 9 |
| 19 | 31 | ||
| 32 | /* PBA constants */ | ||
| 33 | #define IGC_PBA_34K 0x0022 | ||
| 34 | |||
| 20 | /* Device Status */ | 35 | /* Device Status */ |
| 21 | #define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ | 36 | #define IGC_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ |
| 22 | #define IGC_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ | 37 | #define IGC_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ |
diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h index 84b6067a2476..4cac2e8868e0 100644 --- a/drivers/net/ethernet/intel/igc/igc_hw.h +++ b/drivers/net/ethernet/intel/igc/igc_hw.h | |||
| @@ -59,6 +59,7 @@ struct igc_mac_info { | |||
| 59 | 59 | ||
| 60 | bool autoneg; | 60 | bool autoneg; |
| 61 | bool autoneg_failed; | 61 | bool autoneg_failed; |
| 62 | bool get_link_status; | ||
| 62 | }; | 63 | }; |
| 63 | 64 | ||
| 64 | struct igc_bus_info { | 65 | struct igc_bus_info { |
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c index 6a881753f5ce..7c5b0d2f16bf 100644 --- a/drivers/net/ethernet/intel/igc/igc_main.c +++ b/drivers/net/ethernet/intel/igc/igc_main.c | |||
| @@ -3,6 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/module.h> | 4 | #include <linux/module.h> |
| 5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
| 6 | #include <linux/if_vlan.h> | ||
| 7 | #include <linux/aer.h> | ||
| 6 | 8 | ||
| 7 | #include "igc.h" | 9 | #include "igc.h" |
| 8 | #include "igc_hw.h" | 10 | #include "igc_hw.h" |
| @@ -10,10 +12,14 @@ | |||
| 10 | #define DRV_VERSION "0.0.1-k" | 12 | #define DRV_VERSION "0.0.1-k" |
| 11 | #define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver" | 13 | #define DRV_SUMMARY "Intel(R) 2.5G Ethernet Linux Driver" |
| 12 | 14 | ||
| 15 | static int debug = -1; | ||
| 16 | |||
| 13 | MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); | 17 | MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>"); |
| 14 | MODULE_DESCRIPTION(DRV_SUMMARY); | 18 | MODULE_DESCRIPTION(DRV_SUMMARY); |
| 15 | MODULE_LICENSE("GPL v2"); | 19 | MODULE_LICENSE("GPL v2"); |
| 16 | MODULE_VERSION(DRV_VERSION); | 20 | MODULE_VERSION(DRV_VERSION); |
| 21 | module_param(debug, int, 0); | ||
| 22 | MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); | ||
| 17 | 23 | ||
| 18 | char igc_driver_name[] = "igc"; | 24 | char igc_driver_name[] = "igc"; |
| 19 | char igc_driver_version[] = DRV_VERSION; | 25 | char igc_driver_version[] = DRV_VERSION; |
| @@ -32,6 +38,364 @@ MODULE_DEVICE_TABLE(pci, igc_pci_tbl); | |||
| 32 | 38 | ||
| 33 | /* forward declaration */ | 39 | /* forward declaration */ |
| 34 | static int igc_sw_init(struct igc_adapter *); | 40 | static int igc_sw_init(struct igc_adapter *); |
| 41 | static void igc_configure(struct igc_adapter *adapter); | ||
| 42 | static void igc_power_down_link(struct igc_adapter *adapter); | ||
| 43 | static void igc_set_default_mac_filter(struct igc_adapter *adapter); | ||
| 44 | |||
| 45 | static void igc_reset(struct igc_adapter *adapter) | ||
| 46 | { | ||
| 47 | if (!netif_running(adapter->netdev)) | ||
| 48 | igc_power_down_link(adapter); | ||
| 49 | } | ||
| 50 | |||
| 51 | /** | ||
| 52 | * igc_power_up_link - Power up the phy/serdes link | ||
| 53 | * @adapter: address of board private structure | ||
| 54 | */ | ||
| 55 | static void igc_power_up_link(struct igc_adapter *adapter) | ||
| 56 | { | ||
| 57 | } | ||
| 58 | |||
| 59 | /** | ||
| 60 | * igc_power_down_link - Power down the phy/serdes link | ||
| 61 | * @adapter: address of board private structure | ||
| 62 | */ | ||
| 63 | static void igc_power_down_link(struct igc_adapter *adapter) | ||
| 64 | { | ||
| 65 | } | ||
| 66 | |||
| 67 | /** | ||
| 68 | * igc_release_hw_control - release control of the h/w to f/w | ||
| 69 | * @adapter: address of board private structure | ||
| 70 | * | ||
| 71 | * igc_release_hw_control resets CTRL_EXT:DRV_LOAD bit. | ||
| 72 | * For ASF and Pass Through versions of f/w this means that the | ||
| 73 | * driver is no longer loaded. | ||
| 74 | */ | ||
| 75 | static void igc_release_hw_control(struct igc_adapter *adapter) | ||
| 76 | { | ||
| 77 | struct igc_hw *hw = &adapter->hw; | ||
| 78 | u32 ctrl_ext; | ||
| 79 | |||
| 80 | /* Let firmware take over control of h/w */ | ||
| 81 | ctrl_ext = rd32(IGC_CTRL_EXT); | ||
| 82 | wr32(IGC_CTRL_EXT, | ||
| 83 | ctrl_ext & ~IGC_CTRL_EXT_DRV_LOAD); | ||
| 84 | } | ||
| 85 | |||
| 86 | /** | ||
| 87 | * igc_get_hw_control - get control of the h/w from f/w | ||
| 88 | * @adapter: address of board private structure | ||
| 89 | * | ||
| 90 | * igc_get_hw_control sets CTRL_EXT:DRV_LOAD bit. | ||
| 91 | * For ASF and Pass Through versions of f/w this means that | ||
| 92 | * the driver is loaded. | ||
| 93 | */ | ||
| 94 | static void igc_get_hw_control(struct igc_adapter *adapter) | ||
| 95 | { | ||
| 96 | struct igc_hw *hw = &adapter->hw; | ||
| 97 | u32 ctrl_ext; | ||
| 98 | |||
| 99 | /* Let firmware know the driver has taken over */ | ||
| 100 | ctrl_ext = rd32(IGC_CTRL_EXT); | ||
| 101 | wr32(IGC_CTRL_EXT, | ||
| 102 | ctrl_ext | IGC_CTRL_EXT_DRV_LOAD); | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * igc_set_mac - Change the Ethernet Address of the NIC | ||
| 107 | * @netdev: network interface device structure | ||
| 108 | * @p: pointer to an address structure | ||
| 109 | * | ||
| 110 | * Returns 0 on success, negative on failure | ||
| 111 | */ | ||
| 112 | static int igc_set_mac(struct net_device *netdev, void *p) | ||
| 113 | { | ||
| 114 | struct igc_adapter *adapter = netdev_priv(netdev); | ||
| 115 | struct igc_hw *hw = &adapter->hw; | ||
| 116 | struct sockaddr *addr = p; | ||
| 117 | |||
| 118 | if (!is_valid_ether_addr(addr->sa_data)) | ||
| 119 | return -EADDRNOTAVAIL; | ||
| 120 | |||
| 121 | memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); | ||
| 122 | memcpy(hw->mac.addr, addr->sa_data, netdev->addr_len); | ||
| 123 | |||
| 124 | /* set the correct pool for the new PF MAC address in entry 0 */ | ||
| 125 | igc_set_default_mac_filter(adapter); | ||
| 126 | |||
| 127 | return 0; | ||
| 128 | } | ||
| 129 | |||
| 130 | static netdev_tx_t igc_xmit_frame(struct sk_buff *skb, | ||
| 131 | struct net_device *netdev) | ||
| 132 | { | ||
| 133 | dev_kfree_skb_any(skb); | ||
| 134 | return NETDEV_TX_OK; | ||
| 135 | } | ||
| 136 | |||
| 137 | /** | ||
| 138 | * igc_ioctl - I/O control method | ||
| 139 | * @netdev: network interface device structure | ||
| 140 | * @ifreq: frequency | ||
| 141 | * @cmd: command | ||
| 142 | */ | ||
| 143 | static int igc_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) | ||
| 144 | { | ||
| 145 | switch (cmd) { | ||
| 146 | default: | ||
| 147 | return -EOPNOTSUPP; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 151 | /** | ||
| 152 | * igc_up - Open the interface and prepare it to handle traffic | ||
| 153 | * @adapter: board private structure | ||
| 154 | */ | ||
| 155 | static void igc_up(struct igc_adapter *adapter) | ||
| 156 | { | ||
| 157 | int i = 0; | ||
| 158 | |||
| 159 | /* hardware has been reset, we need to reload some things */ | ||
| 160 | igc_configure(adapter); | ||
| 161 | |||
| 162 | clear_bit(__IGC_DOWN, &adapter->state); | ||
| 163 | |||
| 164 | for (i = 0; i < adapter->num_q_vectors; i++) | ||
| 165 | napi_enable(&adapter->q_vector[i]->napi); | ||
| 166 | } | ||
| 167 | |||
| 168 | /** | ||
| 169 | * igc_update_stats - Update the board statistics counters | ||
| 170 | * @adapter: board private structure | ||
| 171 | */ | ||
| 172 | static void igc_update_stats(struct igc_adapter *adapter) | ||
| 173 | { | ||
| 174 | } | ||
| 175 | |||
| 176 | /** | ||
| 177 | * igc_down - Close the interface | ||
| 178 | * @adapter: board private structure | ||
| 179 | */ | ||
| 180 | static void igc_down(struct igc_adapter *adapter) | ||
| 181 | { | ||
| 182 | struct net_device *netdev = adapter->netdev; | ||
| 183 | int i = 0; | ||
| 184 | |||
| 185 | set_bit(__IGC_DOWN, &adapter->state); | ||
| 186 | |||
| 187 | /* set trans_start so we don't get spurious watchdogs during reset */ | ||
| 188 | netif_trans_update(netdev); | ||
| 189 | |||
| 190 | netif_carrier_off(netdev); | ||
| 191 | netif_tx_stop_all_queues(netdev); | ||
| 192 | |||
| 193 | for (i = 0; i < adapter->num_q_vectors; i++) | ||
| 194 | napi_disable(&adapter->q_vector[i]->napi); | ||
| 195 | |||
| 196 | adapter->link_speed = 0; | ||
| 197 | adapter->link_duplex = 0; | ||
| 198 | } | ||
| 199 | |||
| 200 | /** | ||
| 201 | * igc_change_mtu - Change the Maximum Transfer Unit | ||
| 202 | * @netdev: network interface device structure | ||
| 203 | * @new_mtu: new value for maximum frame size | ||
| 204 | * | ||
| 205 | * Returns 0 on success, negative on failure | ||
| 206 | */ | ||
| 207 | static int igc_change_mtu(struct net_device *netdev, int new_mtu) | ||
| 208 | { | ||
| 209 | int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; | ||
| 210 | struct igc_adapter *adapter = netdev_priv(netdev); | ||
| 211 | struct pci_dev *pdev = adapter->pdev; | ||
| 212 | |||
| 213 | /* adjust max frame to be at least the size of a standard frame */ | ||
| 214 | if (max_frame < (ETH_FRAME_LEN + ETH_FCS_LEN)) | ||
| 215 | max_frame = ETH_FRAME_LEN + ETH_FCS_LEN; | ||
| 216 | |||
| 217 | while (test_and_set_bit(__IGC_RESETTING, &adapter->state)) | ||
| 218 | usleep_range(1000, 2000); | ||
| 219 | |||
| 220 | /* igc_down has a dependency on max_frame_size */ | ||
| 221 | adapter->max_frame_size = max_frame; | ||
| 222 | |||
| 223 | if (netif_running(netdev)) | ||
| 224 | igc_down(adapter); | ||
| 225 | |||
| 226 | dev_info(&pdev->dev, "changing MTU from %d to %d\n", | ||
| 227 | netdev->mtu, new_mtu); | ||
| 228 | netdev->mtu = new_mtu; | ||
| 229 | |||
| 230 | if (netif_running(netdev)) | ||
| 231 | igc_up(adapter); | ||
| 232 | else | ||
| 233 | igc_reset(adapter); | ||
| 234 | |||
| 235 | clear_bit(__IGC_RESETTING, &adapter->state); | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 240 | /** | ||
| 241 | * igc_get_stats - Get System Network Statistics | ||
| 242 | * @netdev: network interface device structure | ||
| 243 | * | ||
| 244 | * Returns the address of the device statistics structure. | ||
| 245 | * The statistics are updated here and also from the timer callback. | ||
| 246 | */ | ||
| 247 | static struct net_device_stats *igc_get_stats(struct net_device *netdev) | ||
| 248 | { | ||
| 249 | struct igc_adapter *adapter = netdev_priv(netdev); | ||
| 250 | |||
| 251 | if (!test_bit(__IGC_RESETTING, &adapter->state)) | ||
| 252 | igc_update_stats(adapter); | ||
| 253 | |||
| 254 | /* only return the current stats */ | ||
| 255 | return &netdev->stats; | ||
| 256 | } | ||
| 257 | |||
| 258 | /** | ||
| 259 | * igc_configure - configure the hardware for RX and TX | ||
| 260 | * @adapter: private board structure | ||
| 261 | */ | ||
| 262 | static void igc_configure(struct igc_adapter *adapter) | ||
| 263 | { | ||
| 264 | igc_get_hw_control(adapter); | ||
| 265 | } | ||
| 266 | |||
| 267 | /** | ||
| 268 | * igc_rar_set_index - Sync RAL[index] and RAH[index] registers with MAC table | ||
| 269 | * @adapter: Pointer to adapter structure | ||
| 270 | * @index: Index of the RAR entry which need to be synced with MAC table | ||
| 271 | */ | ||
| 272 | static void igc_rar_set_index(struct igc_adapter *adapter, u32 index) | ||
| 273 | { | ||
| 274 | u8 *addr = adapter->mac_table[index].addr; | ||
| 275 | struct igc_hw *hw = &adapter->hw; | ||
| 276 | u32 rar_low, rar_high; | ||
| 277 | |||
| 278 | /* HW expects these to be in network order when they are plugged | ||
| 279 | * into the registers which are little endian. In order to guarantee | ||
| 280 | * that ordering we need to do an leXX_to_cpup here in order to be | ||
| 281 | * ready for the byteswap that occurs with writel | ||
| 282 | */ | ||
| 283 | rar_low = le32_to_cpup((__le32 *)(addr)); | ||
| 284 | rar_high = le16_to_cpup((__le16 *)(addr + 4)); | ||
| 285 | |||
| 286 | /* Indicate to hardware the Address is Valid. */ | ||
| 287 | if (adapter->mac_table[index].state & IGC_MAC_STATE_IN_USE) { | ||
| 288 | if (is_valid_ether_addr(addr)) | ||
| 289 | rar_high |= IGC_RAH_AV; | ||
| 290 | |||
| 291 | rar_high |= IGC_RAH_POOL_1 << | ||
| 292 | adapter->mac_table[index].queue; | ||
| 293 | } | ||
| 294 | |||
| 295 | wr32(IGC_RAL(index), rar_low); | ||
| 296 | wrfl(); | ||
| 297 | wr32(IGC_RAH(index), rar_high); | ||
| 298 | wrfl(); | ||
| 299 | } | ||
| 300 | |||
| 301 | /* Set default MAC address for the PF in the first RAR entry */ | ||
| 302 | static void igc_set_default_mac_filter(struct igc_adapter *adapter) | ||
| 303 | { | ||
| 304 | struct igc_mac_addr *mac_table = &adapter->mac_table[0]; | ||
| 305 | |||
| 306 | ether_addr_copy(mac_table->addr, adapter->hw.mac.addr); | ||
| 307 | mac_table->state = IGC_MAC_STATE_DEFAULT | IGC_MAC_STATE_IN_USE; | ||
| 308 | |||
| 309 | igc_rar_set_index(adapter, 0); | ||
| 310 | } | ||
| 311 | |||
| 312 | /** | ||
| 313 | * igc_open - Called when a network interface is made active | ||
| 314 | * @netdev: network interface device structure | ||
| 315 | * | ||
| 316 | * Returns 0 on success, negative value on failure | ||
| 317 | * | ||
| 318 | * The open entry point is called when a network interface is made | ||
| 319 | * active by the system (IFF_UP). At this point all resources needed | ||
| 320 | * for transmit and receive operations are allocated, the interrupt | ||
| 321 | * handler is registered with the OS, the watchdog timer is started, | ||
| 322 | * and the stack is notified that the interface is ready. | ||
| 323 | */ | ||
| 324 | static int __igc_open(struct net_device *netdev, bool resuming) | ||
| 325 | { | ||
| 326 | struct igc_adapter *adapter = netdev_priv(netdev); | ||
| 327 | struct igc_hw *hw = &adapter->hw; | ||
| 328 | int i = 0; | ||
| 329 | |||
| 330 | /* disallow open during test */ | ||
| 331 | |||
| 332 | if (test_bit(__IGC_TESTING, &adapter->state)) { | ||
| 333 | WARN_ON(resuming); | ||
| 334 | return -EBUSY; | ||
| 335 | } | ||
| 336 | |||
| 337 | netif_carrier_off(netdev); | ||
| 338 | |||
| 339 | igc_power_up_link(adapter); | ||
| 340 | |||
| 341 | igc_configure(adapter); | ||
| 342 | |||
| 343 | clear_bit(__IGC_DOWN, &adapter->state); | ||
| 344 | |||
| 345 | for (i = 0; i < adapter->num_q_vectors; i++) | ||
| 346 | napi_enable(&adapter->q_vector[i]->napi); | ||
| 347 | |||
| 348 | /* start the watchdog. */ | ||
| 349 | hw->mac.get_link_status = 1; | ||
| 350 | |||
| 351 | return IGC_SUCCESS; | ||
| 352 | } | ||
| 353 | |||
| 354 | static int igc_open(struct net_device *netdev) | ||
| 355 | { | ||
| 356 | return __igc_open(netdev, false); | ||
| 357 | } | ||
| 358 | |||
| 359 | /** | ||
| 360 | * igc_close - Disables a network interface | ||
| 361 | * @netdev: network interface device structure | ||
| 362 | * | ||
| 363 | * Returns 0, this is not allowed to fail | ||
| 364 | * | ||
| 365 | * The close entry point is called when an interface is de-activated | ||
| 366 | * by the OS. The hardware is still under the driver's control, but | ||
| 367 | * needs to be disabled. A global MAC reset is issued to stop the | ||
| 368 | * hardware, and all transmit and receive resources are freed. | ||
| 369 | */ | ||
| 370 | static int __igc_close(struct net_device *netdev, bool suspending) | ||
| 371 | { | ||
| 372 | struct igc_adapter *adapter = netdev_priv(netdev); | ||
| 373 | |||
| 374 | WARN_ON(test_bit(__IGC_RESETTING, &adapter->state)); | ||
| 375 | |||
| 376 | igc_down(adapter); | ||
| 377 | |||
| 378 | igc_release_hw_control(adapter); | ||
| 379 | |||
| 380 | return 0; | ||
| 381 | } | ||
| 382 | |||
| 383 | static int igc_close(struct net_device *netdev) | ||
| 384 | { | ||
| 385 | if (netif_device_present(netdev) || netdev->dismantle) | ||
| 386 | return __igc_close(netdev, false); | ||
| 387 | return 0; | ||
| 388 | } | ||
| 389 | |||
| 390 | static const struct net_device_ops igc_netdev_ops = { | ||
| 391 | .ndo_open = igc_open, | ||
| 392 | .ndo_stop = igc_close, | ||
| 393 | .ndo_start_xmit = igc_xmit_frame, | ||
| 394 | .ndo_set_mac_address = igc_set_mac, | ||
| 395 | .ndo_change_mtu = igc_change_mtu, | ||
| 396 | .ndo_get_stats = igc_get_stats, | ||
| 397 | .ndo_do_ioctl = igc_ioctl, | ||
| 398 | }; | ||
| 35 | 399 | ||
| 36 | /* PCIe configuration access */ | 400 | /* PCIe configuration access */ |
| 37 | void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value) | 401 | void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value) |
| @@ -78,6 +442,7 @@ s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value) | |||
| 78 | 442 | ||
| 79 | u32 igc_rd32(struct igc_hw *hw, u32 reg) | 443 | u32 igc_rd32(struct igc_hw *hw, u32 reg) |
| 80 | { | 444 | { |
| 445 | struct igc_adapter *igc = container_of(hw, struct igc_adapter, hw); | ||
| 81 | u8 __iomem *hw_addr = READ_ONCE(hw->hw_addr); | 446 | u8 __iomem *hw_addr = READ_ONCE(hw->hw_addr); |
| 82 | u32 value = 0; | 447 | u32 value = 0; |
| 83 | 448 | ||
| @@ -87,8 +452,13 @@ u32 igc_rd32(struct igc_hw *hw, u32 reg) | |||
| 87 | value = readl(&hw_addr[reg]); | 452 | value = readl(&hw_addr[reg]); |
| 88 | 453 | ||
| 89 | /* reads should not return all F's */ | 454 | /* reads should not return all F's */ |
| 90 | if (!(~value) && (!reg || !(~readl(hw_addr)))) | 455 | if (!(~value) && (!reg || !(~readl(hw_addr)))) { |
| 456 | struct net_device *netdev = igc->netdev; | ||
| 457 | |||
| 91 | hw->hw_addr = NULL; | 458 | hw->hw_addr = NULL; |
| 459 | netif_device_detach(netdev); | ||
| 460 | netdev_err(netdev, "PCIe link lost, device now detached\n"); | ||
| 461 | } | ||
| 92 | 462 | ||
| 93 | return value; | 463 | return value; |
| 94 | } | 464 | } |
| @@ -108,6 +478,8 @@ static int igc_probe(struct pci_dev *pdev, | |||
| 108 | const struct pci_device_id *ent) | 478 | const struct pci_device_id *ent) |
| 109 | { | 479 | { |
| 110 | struct igc_adapter *adapter; | 480 | struct igc_adapter *adapter; |
| 481 | struct net_device *netdev; | ||
| 482 | struct igc_hw *hw; | ||
| 111 | int err, pci_using_dac; | 483 | int err, pci_using_dac; |
| 112 | 484 | ||
| 113 | err = pci_enable_device_mem(pdev); | 485 | err = pci_enable_device_mem(pdev); |
| @@ -140,17 +512,94 @@ static int igc_probe(struct pci_dev *pdev, | |||
| 140 | if (err) | 512 | if (err) |
| 141 | goto err_pci_reg; | 513 | goto err_pci_reg; |
| 142 | 514 | ||
| 515 | pci_enable_pcie_error_reporting(pdev); | ||
| 516 | |||
| 143 | pci_set_master(pdev); | 517 | pci_set_master(pdev); |
| 518 | |||
| 519 | err = -ENOMEM; | ||
| 520 | netdev = alloc_etherdev_mq(sizeof(struct igc_adapter), | ||
| 521 | IGC_MAX_TX_QUEUES); | ||
| 522 | |||
| 523 | if (!netdev) | ||
| 524 | goto err_alloc_etherdev; | ||
| 525 | |||
| 526 | SET_NETDEV_DEV(netdev, &pdev->dev); | ||
| 527 | |||
| 528 | pci_set_drvdata(pdev, netdev); | ||
| 529 | adapter = netdev_priv(netdev); | ||
| 530 | adapter->netdev = netdev; | ||
| 531 | adapter->pdev = pdev; | ||
| 532 | hw = &adapter->hw; | ||
| 533 | hw->back = adapter; | ||
| 534 | adapter->port_num = hw->bus.func; | ||
| 535 | adapter->msg_enable = GENMASK(debug - 1, 0); | ||
| 536 | |||
| 144 | err = pci_save_state(pdev); | 537 | err = pci_save_state(pdev); |
| 538 | if (err) | ||
| 539 | goto err_ioremap; | ||
| 540 | |||
| 541 | err = -EIO; | ||
| 542 | adapter->io_addr = ioremap(pci_resource_start(pdev, 0), | ||
| 543 | pci_resource_len(pdev, 0)); | ||
| 544 | if (!adapter->io_addr) | ||
| 545 | goto err_ioremap; | ||
| 546 | |||
| 547 | /* hw->hw_addr can be zeroed, so use adapter->io_addr for unmap */ | ||
| 548 | hw->hw_addr = adapter->io_addr; | ||
| 549 | |||
| 550 | netdev->netdev_ops = &igc_netdev_ops; | ||
| 551 | |||
| 552 | netdev->watchdog_timeo = 5 * HZ; | ||
| 553 | |||
| 554 | netdev->mem_start = pci_resource_start(pdev, 0); | ||
| 555 | netdev->mem_end = pci_resource_end(pdev, 0); | ||
| 556 | |||
| 557 | /* PCI config space info */ | ||
| 558 | hw->vendor_id = pdev->vendor; | ||
| 559 | hw->device_id = pdev->device; | ||
| 560 | hw->revision_id = pdev->revision; | ||
| 561 | hw->subsystem_vendor_id = pdev->subsystem_vendor; | ||
| 562 | hw->subsystem_device_id = pdev->subsystem_device; | ||
| 145 | 563 | ||
| 146 | /* setup the private structure */ | 564 | /* setup the private structure */ |
| 147 | err = igc_sw_init(adapter); | 565 | err = igc_sw_init(adapter); |
| 148 | if (err) | 566 | if (err) |
| 149 | goto err_sw_init; | 567 | goto err_sw_init; |
| 150 | 568 | ||
| 569 | /* MTU range: 68 - 9216 */ | ||
| 570 | netdev->min_mtu = ETH_MIN_MTU; | ||
| 571 | netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE; | ||
| 572 | |||
| 573 | /* reset the hardware with the new settings */ | ||
| 574 | igc_reset(adapter); | ||
| 575 | |||
| 576 | /* let the f/w know that the h/w is now under the control of the | ||
| 577 | * driver. | ||
| 578 | */ | ||
| 579 | igc_get_hw_control(adapter); | ||
| 580 | |||
| 581 | strncpy(netdev->name, "eth%d", IFNAMSIZ); | ||
| 582 | err = register_netdev(netdev); | ||
| 583 | if (err) | ||
| 584 | goto err_register; | ||
| 585 | |||
| 586 | /* carrier off reporting is important to ethtool even BEFORE open */ | ||
| 587 | netif_carrier_off(netdev); | ||
| 588 | |||
| 589 | /* print pcie link status and MAC address */ | ||
| 590 | pcie_print_link_status(pdev); | ||
| 591 | netdev_info(netdev, "MAC: %pM\n", netdev->dev_addr); | ||
| 592 | |||
| 151 | return 0; | 593 | return 0; |
| 152 | 594 | ||
| 595 | err_register: | ||
| 596 | igc_release_hw_control(adapter); | ||
| 153 | err_sw_init: | 597 | err_sw_init: |
| 598 | err_ioremap: | ||
| 599 | free_netdev(netdev); | ||
| 600 | err_alloc_etherdev: | ||
| 601 | pci_release_selected_regions(pdev, | ||
| 602 | pci_select_bars(pdev, IORESOURCE_MEM)); | ||
| 154 | err_pci_reg: | 603 | err_pci_reg: |
| 155 | err_dma: | 604 | err_dma: |
| 156 | pci_disable_device(pdev); | 605 | pci_disable_device(pdev); |
| @@ -168,9 +617,22 @@ err_dma: | |||
| 168 | */ | 617 | */ |
| 169 | static void igc_remove(struct pci_dev *pdev) | 618 | static void igc_remove(struct pci_dev *pdev) |
| 170 | { | 619 | { |
| 620 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
| 621 | struct igc_adapter *adapter = netdev_priv(netdev); | ||
| 622 | |||
| 623 | set_bit(__IGC_DOWN, &adapter->state); | ||
| 624 | flush_scheduled_work(); | ||
| 625 | |||
| 626 | /* Release control of h/w to f/w. If f/w is AMT enabled, this | ||
| 627 | * would have already happened in close and is redundant. | ||
| 628 | */ | ||
| 629 | igc_release_hw_control(adapter); | ||
| 630 | unregister_netdev(netdev); | ||
| 631 | |||
| 171 | pci_release_selected_regions(pdev, | 632 | pci_release_selected_regions(pdev, |
| 172 | pci_select_bars(pdev, IORESOURCE_MEM)); | 633 | pci_select_bars(pdev, IORESOURCE_MEM)); |
| 173 | 634 | ||
| 635 | free_netdev(netdev); | ||
| 174 | pci_disable_device(pdev); | 636 | pci_disable_device(pdev); |
| 175 | } | 637 | } |
| 176 | 638 | ||
| @@ -191,6 +653,7 @@ static struct pci_driver igc_driver = { | |||
| 191 | */ | 653 | */ |
| 192 | static int igc_sw_init(struct igc_adapter *adapter) | 654 | static int igc_sw_init(struct igc_adapter *adapter) |
| 193 | { | 655 | { |
| 656 | struct net_device *netdev = adapter->netdev; | ||
| 194 | struct pci_dev *pdev = adapter->pdev; | 657 | struct pci_dev *pdev = adapter->pdev; |
| 195 | struct igc_hw *hw = &adapter->hw; | 658 | struct igc_hw *hw = &adapter->hw; |
| 196 | 659 | ||
| @@ -205,6 +668,12 @@ static int igc_sw_init(struct igc_adapter *adapter) | |||
| 205 | 668 | ||
| 206 | pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); | 669 | pci_read_config_word(pdev, PCI_COMMAND, &hw->bus.pci_cmd_word); |
| 207 | 670 | ||
| 671 | /* adjust max frame to be at least the size of a standard frame */ | ||
| 672 | adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + | ||
| 673 | VLAN_HLEN; | ||
| 674 | |||
| 675 | set_bit(__IGC_DOWN, &adapter->state); | ||
| 676 | |||
| 208 | return 0; | 677 | return 0; |
| 209 | } | 678 | } |
| 210 | 679 | ||
