/** * txgbe_enumerate_functions - Get the number of ports this device has * @wx: wx structure * * This function enumerates the phsyical functions co-located on a single slot, * in order to determine how many ports a device has. This is most useful in * determining the required GT/s of PCIe bandwidth necessary for optimal * performance.
**/ staticint txgbe_enumerate_functions(struct wx *wx)
{ struct pci_dev *entry, *pdev = wx->pdev; int physfns = 0;
list_for_each_entry(entry, &pdev->bus->devices, bus_list) { /* When the devices on the bus don't all match our device ID, * we can't reliably determine the correct number of * functions. This can occur if a function has been direct * attached to a virtual machine using VT-d.
*/ if (entry->vendor != pdev->vendor ||
entry->device != pdev->device) return -EINVAL;
physfns++;
}
return physfns;
}
staticvoid txgbe_sfp_detection_subtask(struct wx *wx)
{ int err;
if (!test_bit(WX_FLAG_NEED_SFP_RESET, wx->flags)) return;
/* wait for SFP module ready */
msleep(200);
err = txgbe_identify_sfp(wx); if (err) return;
clear_bit(WX_FLAG_NEED_SFP_RESET, wx->flags);
}
staticvoid txgbe_link_config_subtask(struct wx *wx)
{ int err;
if (!test_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags)) return;
err = txgbe_set_phy_link(wx); if (err) return;
clear_bit(WX_FLAG_NEED_LINK_CONFIG, wx->flags);
}
/** * txgbe_service_task - manages and runs subtasks * @work: pointer to work_struct containing our data
**/ staticvoid txgbe_service_task(struct work_struct *work)
{ struct wx *wx = container_of(work, struct wx, service_task);
/* Set PF Reset Done bit so PF/VF Mail Ops can work */
wr32m(wx, WX_CFG_PORT_CTL, WX_CFG_PORT_CTL_PFRSTD,
WX_CFG_PORT_CTL_PFRSTD); /* update setting rx tx for all active vfs */
wx_set_all_vfs(wx);
}
wx_start_hw(wx); /* do not flush user set addresses */
memcpy(old_addr, &wx->mac_table[0].addr, netdev->addr_len);
wx_flush_sw_mac_table(wx);
wx_mac_set_default_filter(wx, old_addr);
if (test_bit(WX_STATE_PTP_RUNNING, wx->state))
wx_ptp_reset(wx);
}
/* disable all enabled rx queues */ for (i = 0; i < wx->num_rx_queues; i++) /* this call also flushes the previous write */
wx_disable_rx_queue(wx, wx->rx_ring[i]);
if (wx->bus.func < 2)
wr32m(wx, TXGBE_MIS_PRB_CTL, TXGBE_MIS_PRB_CTL_LAN_UP(wx->bus.func), 0); else
wx_err(wx, "%s: invalid bus lan id %d\n",
__func__, wx->bus.func);
if (wx->num_vfs) { /* Clear EITR Select mapping */
wr32(wx, WX_PX_ITRSEL, 0); /* Mark all the VFs as inactive */ for (i = 0; i < wx->num_vfs; i++)
wx->vfinfo[i].clear_to_send = 0; /* update setting rx tx for all active vfs */
wx_set_all_vfs(wx);
}
switch (wx->device_id) { case TXGBE_DEV_ID_SP1000: case TXGBE_DEV_ID_WX1820:
wx->mac.type = wx_mac_sp; break; case TXGBE_DEV_ID_AML5010: case TXGBE_DEV_ID_AML5110: case TXGBE_DEV_ID_AML5025: case TXGBE_DEV_ID_AML5125:
wx->mac.type = wx_mac_aml; break; case TXGBE_DEV_ID_AML5040: case TXGBE_DEV_ID_AML5140:
wx->mac.type = wx_mac_aml40; break; default:
wx->mac.type = wx_mac_unknown; break;
}
switch (device_type) { case TXGBE_ID_SFP:
wx->media_type = wx_media_fiber; break; case TXGBE_ID_XAUI: case TXGBE_ID_SGMII:
wx->media_type = wx_media_copper; break; case TXGBE_ID_KR_KX_KX4: case TXGBE_ID_MAC_XAUI: case TXGBE_ID_MAC_SGMII:
wx->media_type = wx_media_backplane; break; case TXGBE_ID_SFI_XAUI: if (wx->bus.func == 0)
wx->media_type = wx_media_fiber; else
wx->media_type = wx_media_copper; break; default:
wx->media_type = wx_media_unknown; break;
}
}
/** * txgbe_sw_init - Initialize general software structures (struct wx) * @wx: board private structure to initialize
**/ staticint txgbe_sw_init(struct wx *wx)
{
u16 msix_count = 0; int err;
/* PCI config space info */
err = wx_sw_init(wx); if (err < 0) return err;
txgbe_init_type_code(wx);
/* Set common capability flags and settings */
wx->max_q_vectors = TXGBE_MAX_MSIX_VECTORS;
err = wx_get_pcie_msix_counts(wx, &msix_count, TXGBE_MAX_MSIX_VECTORS); if (err)
wx_err(wx, "Do not support MSI-X\n");
wx->mac.max_msix_vectors = msix_count;
/** * txgbe_open - Called when a network interface is made active * @netdev: network interface device structure * * Returns 0 on success, negative value on failure * * The open entry point is called when a network interface is made * active by the system (IFF_UP).
**/ staticint txgbe_open(struct net_device *netdev)
{ struct wx *wx = netdev_priv(netdev); int err;
err = wx_setup_resources(wx); if (err) goto err_reset;
wx_configure(wx);
err = txgbe_setup_misc_irq(wx->priv); if (err) goto err_free_resources;
err = txgbe_request_queue_irqs(wx); if (err) goto err_free_misc_irq;
/* Notify the stack of the actual queue counts. */
err = netif_set_real_num_tx_queues(netdev, wx->num_tx_queues); if (err) goto err_free_irq;
err = netif_set_real_num_rx_queues(netdev, wx->num_rx_queues); if (err) goto err_free_irq;
/** * txgbe_close_suspend - actions necessary to both suspend and close flows * @wx: the private wx struct * * This function should contain the necessary work common to both suspending * and closing of the device.
*/ staticvoid txgbe_close_suspend(struct wx *wx)
{
wx_ptp_suspend(wx);
txgbe_disable_device(wx);
wx_free_resources(wx);
}
/** * txgbe_close - Disables a network interface * @netdev: network interface device structure * * Returns 0, this is not allowed to fail * * The close entry point is called when an interface is de-activated * by the OS. The hardware is still under the drivers control, but * needs to be disabled. A global MAC reset is issued to stop the * hardware, and all transmit and receive resources are freed.
**/ staticint txgbe_close(struct net_device *netdev)
{ struct wx *wx = netdev_priv(netdev);
/** * txgbe_setup_tc - routine to configure net_device for multiple traffic * classes. * * @dev: net device to configure * @tc: number of traffic classes to enable
*/ int txgbe_setup_tc(struct net_device *dev, u8 tc)
{ struct wx *wx = netdev_priv(dev);
/* Hardware has to reinitialize queues and interrupts to * match packet buffer alignment. Unfortunately, the * hardware is not flexible enough to do this dynamically.
*/ if (netif_running(dev))
txgbe_close(dev); else
txgbe_reset(wx);
wx_clear_interrupt_scheme(wx);
if (tc)
netdev_set_num_tc(dev, tc); else
netdev_reset_tc(dev);
wx_init_interrupt_scheme(wx);
if (netif_running(dev))
txgbe_open(dev);
return 0;
}
staticvoid txgbe_reinit_locked(struct wx *wx)
{ int err = 0;
/* The sapphire supports up to 63 VFs per pf, but physical * function also need one pool for basic networking.
*/
pci_sriov_set_totalvfs(pdev, TXGBE_MAX_VFS_DRV_LIMIT);
wx->driver_name = txgbe_driver_name;
txgbe_set_ethtool_ops(netdev);
netdev->netdev_ops = &txgbe_netdev_ops;
netdev->udp_tunnel_nic_info = &txgbe_udp_tunnels;
/* setup the private structure */
err = txgbe_sw_init(wx); if (err) goto err_pci_release_regions;
/* check if flash load is done after hw power up */
err = wx_check_flash_load(wx, TXGBE_SPI_ILDR_STATUS_PERST); if (err) goto err_free_mac_table;
err = wx_check_flash_load(wx, TXGBE_SPI_ILDR_STATUS_PWRRST); if (err) goto err_free_mac_table;
err = wx_mng_present(wx); if (err) {
dev_err(&pdev->dev, "Management capability is not present\n"); goto err_free_mac_table;
}
/* make sure the EEPROM is good */
err = txgbe_validate_eeprom_checksum(wx, NULL); if (err != 0) {
dev_err(&pdev->dev, "The EEPROM Checksum Is Not Valid\n");
wr32(wx, WX_MIS_RST, WX_MIS_RST_SW_RST);
err = -EIO; goto err_free_mac_table;
}
err = wx_init_interrupt_scheme(wx); if (err) goto err_cancel_service;
/* Save off EEPROM version number and Option Rom version which * together make a unique identify for the eeprom
*/
wx_read_ee_hostif(wx,
wx->eeprom.sw_region_offset + TXGBE_EEPROM_VERSION_H,
&eeprom_verh);
wx_read_ee_hostif(wx,
wx->eeprom.sw_region_offset + TXGBE_EEPROM_VERSION_L,
&eeprom_verl);
etrack_id = (eeprom_verh << 16) | eeprom_verl;
err = txgbe_init_phy(txgbe); if (err) goto err_release_hw;
err = register_netdev(netdev); if (err) goto err_remove_phy;
pci_set_drvdata(pdev, wx);
netif_tx_stop_all_queues(netdev);
/* calculate the expected PCIe bandwidth required for optimal * performance. Note that some older parts will never have enough * bandwidth due to being older generation PCIe parts. We clamp these * parts to ensure that no warning is displayed, as this could confuse * users otherwise.
*/
expected_gts = txgbe_enumerate_functions(wx) * 10;
/* don't check link if we failed to enumerate functions */ if (expected_gts > 0)
txgbe_check_minimum_link(wx); else
dev_warn(&pdev->dev, "Failed to enumerate PF devices.\n");
/** * txgbe_remove - Device Removal Routine * @pdev: PCI device information struct * * txgbe_remove is called by the PCI subsystem to alert the driver * that it should release a PCI device. The could be caused by a * Hot-Plug event, or because the driver is going to be removed from * memory.
**/ staticvoid txgbe_remove(struct pci_dev *pdev)
{ struct wx *wx = pci_get_drvdata(pdev); struct txgbe *txgbe = wx->priv; struct net_device *netdev;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.