diff options
Diffstat (limited to 'drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c')
-rw-r--r-- | drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c | 155 |
1 files changed, 48 insertions, 107 deletions
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c index 9dd6cb36f366..28476b982bab 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_main.c @@ -1,8 +1,7 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * QLogic qlcnic NIC Driver * Copyright (c) 2009-2013 QLogic Corporation - * - * See LICENSE.qlcnic for copyright and licensing details. */ #include <linux/vmalloc.h> @@ -305,7 +304,7 @@ int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) if (ret) return ret; - memcpy(netdev->dev_addr, mac_addr, ETH_ALEN); + eth_hw_addr_set(netdev, mac_addr); memcpy(adapter->mac_addr, netdev->dev_addr, netdev->addr_len); /* set station address */ @@ -320,10 +319,8 @@ int qlcnic_read_mac_addr(struct qlcnic_adapter *adapter) static void qlcnic_delete_adapter_mac(struct qlcnic_adapter *adapter) { struct qlcnic_mac_vlan_list *cur; - struct list_head *head; - list_for_each(head, &adapter->mac_list) { - cur = list_entry(head, struct qlcnic_mac_vlan_list, list); + list_for_each_entry(cur, &adapter->mac_list, list) { if (ether_addr_equal_unaligned(adapter->mac_addr, cur->mac_addr)) { qlcnic_sre_macaddr_change(adapter, cur->mac_addr, 0, QLCNIC_MAC_DEL); @@ -359,7 +356,7 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) qlcnic_delete_adapter_mac(adapter); memcpy(adapter->mac_addr, addr->sa_data, netdev->addr_len); - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + eth_hw_addr_set(netdev, addr->sa_data); qlcnic_set_multi(adapter->netdev); if (test_bit(__QLCNIC_DEV_UP, &adapter->state)) { @@ -371,7 +368,8 @@ static int qlcnic_set_mac(struct net_device *netdev, void *p) static int qlcnic_fdb_del(struct ndmsg *ndm, struct nlattr *tb[], struct net_device *netdev, - const unsigned char *addr, u16 vid) + const unsigned char *addr, u16 vid, + struct netlink_ext_ack *extack) { struct qlcnic_adapter *adapter = netdev_priv(netdev); int err = -EOPNOTSUPP; @@ -471,48 +469,29 @@ static int qlcnic_get_phys_port_id(struct net_device *netdev, return 0; } -static void qlcnic_add_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) +static int qlcnic_udp_tunnel_sync(struct net_device *dev, unsigned int table) { - struct qlcnic_adapter *adapter = netdev_priv(netdev); - struct qlcnic_hardware_context *ahw = adapter->ahw; - - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; + struct qlcnic_adapter *adapter = netdev_priv(dev); + struct udp_tunnel_info ti; + int err; - /* Adapter supports only one VXLAN port. Use very first port - * for enabling offload - */ - if (!qlcnic_encap_rx_offload(adapter)) - return; - if (!ahw->vxlan_port_count) { - ahw->vxlan_port_count = 1; - ahw->vxlan_port = ntohs(ti->port); - adapter->flags |= QLCNIC_ADD_VXLAN_PORT; - return; + udp_tunnel_nic_get_port(dev, table, 0, &ti); + if (ti.port) { + err = qlcnic_set_vxlan_port(adapter, ntohs(ti.port)); + if (err) + return err; } - if (ahw->vxlan_port == ntohs(ti->port)) - ahw->vxlan_port_count++; + return qlcnic_set_vxlan_parsing(adapter, ntohs(ti.port)); } -static void qlcnic_del_vxlan_port(struct net_device *netdev, - struct udp_tunnel_info *ti) -{ - struct qlcnic_adapter *adapter = netdev_priv(netdev); - struct qlcnic_hardware_context *ahw = adapter->ahw; - - if (ti->type != UDP_TUNNEL_TYPE_VXLAN) - return; - - if (!qlcnic_encap_rx_offload(adapter) || !ahw->vxlan_port_count || - (ahw->vxlan_port != ntohs(ti->port))) - return; - - ahw->vxlan_port_count--; - if (!ahw->vxlan_port_count) - adapter->flags |= QLCNIC_DEL_VXLAN_PORT; -} +static const struct udp_tunnel_nic_info qlcnic_udp_tunnels = { + .sync_table = qlcnic_udp_tunnel_sync, + .flags = UDP_TUNNEL_NIC_INFO_MAY_SLEEP, + .tables = { + { .n_entries = 1, .tunnel_types = UDP_TUNNEL_TYPE_VXLAN, }, + }, +}; static netdev_features_t qlcnic_features_check(struct sk_buff *skb, struct net_device *dev, @@ -540,8 +519,6 @@ static const struct net_device_ops qlcnic_netdev_ops = { .ndo_fdb_del = qlcnic_fdb_del, .ndo_fdb_dump = qlcnic_fdb_dump, .ndo_get_phys_port_id = qlcnic_get_phys_port_id, - .ndo_udp_tunnel_add = qlcnic_add_vxlan_port, - .ndo_udp_tunnel_del = qlcnic_del_vxlan_port, .ndo_features_check = qlcnic_features_check, #ifdef CONFIG_QLCNIC_SRIOV .ndo_set_vf_mac = qlcnic_sriov_set_vf_mac, @@ -2017,7 +1994,7 @@ qlcnic_attach(struct qlcnic_adapter *adapter) qlcnic_create_sysfs_entries(adapter); if (qlcnic_encap_rx_offload(adapter)) - udp_tunnel_get_rx_info(netdev); + udp_tunnel_nic_reset_ntf(netdev); adapter->is_up = QLCNIC_ADAPTER_UP_MAGIC; return 0; @@ -2282,8 +2259,7 @@ static int qlcnic_set_real_num_queues(struct qlcnic_adapter *adapter, } int -qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, - int pci_using_dac) +qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev) { int err; struct pci_dev *pdev = adapter->pdev; @@ -2302,20 +2278,15 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, netdev->features |= (NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_RXCSUM | NETIF_F_IPV6_CSUM | NETIF_F_GRO | - NETIF_F_HW_VLAN_CTAG_RX); + NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HIGHDMA); netdev->vlan_features |= (NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_IPV6_CSUM); + NETIF_F_IPV6_CSUM | NETIF_F_HIGHDMA); if (QLCNIC_IS_TSO_CAPABLE(adapter)) { netdev->features |= (NETIF_F_TSO | NETIF_F_TSO6); netdev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO6); } - if (pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features |= NETIF_F_HIGHDMA; - } - if (qlcnic_vlan_tx_check(adapter)) netdev->features |= (NETIF_F_HW_VLAN_CTAG_TX); @@ -2335,9 +2306,12 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, NETIF_F_TSO6; } - if (qlcnic_encap_rx_offload(adapter)) + if (qlcnic_encap_rx_offload(adapter)) { netdev->hw_enc_features |= NETIF_F_RXCSUM; + netdev->udp_tunnel_nic_info = &qlcnic_udp_tunnels; + } + netdev->hw_features = netdev->features; netdev->priv_flags |= IFF_UNICAST_FLT; netdev->irq = adapter->msix_entries[0].vector; @@ -2362,22 +2336,6 @@ qlcnic_setup_netdev(struct qlcnic_adapter *adapter, struct net_device *netdev, return 0; } -static int qlcnic_set_dma_mask(struct pci_dev *pdev, int *pci_using_dac) -{ - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) - *pci_using_dac = 1; - else if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) - *pci_using_dac = 0; - else { - dev_err(&pdev->dev, "Unable to set DMA mask, aborting\n"); - return -EIO; - } - - return 0; -} - void qlcnic_free_tx_rings(struct qlcnic_adapter *adapter) { int ring; @@ -2464,8 +2422,8 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) struct net_device *netdev = NULL; struct qlcnic_adapter *adapter = NULL; struct qlcnic_hardware_context *ahw; - int err, pci_using_dac = -1; char board_name[QLCNIC_MAX_BOARD_NAME_LEN + 19]; /* MAC + ": " + name */ + int err; err = pci_enable_device(pdev); if (err) @@ -2476,9 +2434,11 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_disable_pdev; } - err = qlcnic_set_dma_mask(pdev, &pci_using_dac); - if (err) + err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); + if (err) { + dev_err(&pdev->dev, "Unable to set DMA mask, aborting\n"); goto err_out_disable_pdev; + } err = pci_request_regions(pdev, qlcnic_driver_name); if (err) @@ -2509,6 +2469,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) qlcnic_sriov_vf_register_map(ahw); break; default: + err = -EINVAL; goto err_out_free_hw_res; } @@ -2591,7 +2552,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) } else if (qlcnic_83xx_check(adapter)) { qlcnic_83xx_check_vf(adapter, ent); adapter->portnum = adapter->ahw->pci_func; - err = qlcnic_83xx_init(adapter, pci_using_dac); + err = qlcnic_83xx_init(adapter); if (err) { switch (err) { case -ENOTRECOVERABLE: @@ -2655,7 +2616,7 @@ qlcnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) if (adapter->portnum == 0) qlcnic_set_drv_version(adapter); - err = qlcnic_setup_netdev(adapter, netdev, pci_using_dac); + err = qlcnic_setup_netdev(adapter, netdev); if (err) goto err_out_disable_mbx_intr; @@ -2708,6 +2669,7 @@ err_out_free_hw_res: kfree(ahw); err_out_free_res: + pci_disable_pcie_error_reporting(pdev); pci_release_regions(pdev); err_out_disable_pdev: @@ -2811,35 +2773,17 @@ static void qlcnic_shutdown(struct pci_dev *pdev) pci_disable_device(pdev); } -#ifdef CONFIG_PM -static int qlcnic_suspend(struct pci_dev *pdev, pm_message_t state) +static int __maybe_unused qlcnic_suspend(struct device *dev_d) { - int retval; - - retval = __qlcnic_shutdown(pdev); - if (retval) - return retval; - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; + return __qlcnic_shutdown(to_pci_dev(dev_d)); } -static int qlcnic_resume(struct pci_dev *pdev) +static int __maybe_unused qlcnic_resume(struct device *dev_d) { - struct qlcnic_adapter *adapter = pci_get_drvdata(pdev); - int err; - - err = pci_enable_device(pdev); - if (err) - return err; - - pci_set_power_state(pdev, PCI_D0); - pci_set_master(pdev); - pci_restore_state(pdev); + struct qlcnic_adapter *adapter = dev_get_drvdata(dev_d); return __qlcnic_resume(adapter); } -#endif static int qlcnic_open(struct net_device *netdev) { @@ -3379,9 +3323,6 @@ qlcnic_can_start_firmware(struct qlcnic_adapter *adapter) do { msleep(1000); prev_state = QLC_SHARED_REG_RD32(adapter, QLCNIC_CRB_DEV_STATE); - - if (prev_state == QLCNIC_DEV_QUISCENT) - continue; } while ((prev_state != QLCNIC_DEV_READY) && --dev_init_timeo); if (!dev_init_timeo) { @@ -3491,6 +3432,7 @@ wait_npar: adapter->fw_wait_cnt = 0; return; } + break; case QLCNIC_DEV_FAILED: break; default: @@ -4258,15 +4200,14 @@ static const struct pci_error_handlers qlcnic_err_handler = { .resume = qlcnic_io_resume, }; +static SIMPLE_DEV_PM_OPS(qlcnic_pm_ops, qlcnic_suspend, qlcnic_resume); + static struct pci_driver qlcnic_driver = { .name = qlcnic_driver_name, .id_table = qlcnic_pci_tbl, .probe = qlcnic_probe, .remove = qlcnic_remove, -#ifdef CONFIG_PM - .suspend = qlcnic_suspend, - .resume = qlcnic_resume, -#endif + .driver.pm = &qlcnic_pm_ops, .shutdown = qlcnic_shutdown, .err_handler = &qlcnic_err_handler, #ifdef CONFIG_QLCNIC_SRIOV |