brintos

brintos / linux-shallow public Read only

0
0
Text · 6.2 KiB · b15db70 Raw
271 lines · c
1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)2/* Copyright 2017-2019 NXP */3 4#include <linux/module.h>5#include "enetc.h"6 7#define ENETC_DRV_NAME_STR "ENETC VF driver"8 9/* Messaging */10static void enetc_msg_vsi_write_msg(struct enetc_hw *hw,11				    struct enetc_msg_swbd *msg)12{13	u32 val;14 15	val = enetc_vsi_set_msize(msg->size) | lower_32_bits(msg->dma);16	enetc_wr(hw, ENETC_VSIMSGSNDAR1, upper_32_bits(msg->dma));17	enetc_wr(hw, ENETC_VSIMSGSNDAR0, val);18}19 20static int enetc_msg_vsi_send(struct enetc_si *si, struct enetc_msg_swbd *msg)21{22	int timeout = 100;23	u32 vsimsgsr;24 25	enetc_msg_vsi_write_msg(&si->hw, msg);26 27	do {28		vsimsgsr = enetc_rd(&si->hw, ENETC_VSIMSGSR);29		if (!(vsimsgsr & ENETC_VSIMSGSR_MB))30			break;31 32		usleep_range(1000, 2000);33	} while (--timeout);34 35	if (!timeout)36		return -ETIMEDOUT;37 38	/* check for message delivery error */39	if (vsimsgsr & ENETC_VSIMSGSR_MS) {40		dev_err(&si->pdev->dev, "VSI command execute error: %d\n",41			ENETC_SIMSGSR_GET_MC(vsimsgsr));42		return -EIO;43	}44 45	return 0;46}47 48static int enetc_msg_vsi_set_primary_mac_addr(struct enetc_ndev_priv *priv,49					      struct sockaddr *saddr)50{51	struct enetc_msg_cmd_set_primary_mac *cmd;52	struct enetc_msg_swbd msg;53	int err;54 55	msg.size = ALIGN(sizeof(struct enetc_msg_cmd_set_primary_mac), 64);56	msg.vaddr = dma_alloc_coherent(priv->dev, msg.size, &msg.dma,57				       GFP_KERNEL);58	if (!msg.vaddr) {59		dev_err(priv->dev, "Failed to alloc Tx msg (size: %d)\n",60			msg.size);61		return -ENOMEM;62	}63 64	cmd = (struct enetc_msg_cmd_set_primary_mac *)msg.vaddr;65	cmd->header.type = ENETC_MSG_CMD_MNG_MAC;66	cmd->header.id = ENETC_MSG_CMD_MNG_ADD;67	memcpy(&cmd->mac, saddr, sizeof(struct sockaddr));68 69	/* send the command and wait */70	err = enetc_msg_vsi_send(priv->si, &msg);71 72	dma_free_coherent(priv->dev, msg.size, msg.vaddr, msg.dma);73 74	return err;75}76 77static int enetc_vf_set_mac_addr(struct net_device *ndev, void *addr)78{79	struct enetc_ndev_priv *priv = netdev_priv(ndev);80	struct sockaddr *saddr = addr;81	int err;82 83	if (!is_valid_ether_addr(saddr->sa_data))84		return -EADDRNOTAVAIL;85 86	err = enetc_msg_vsi_set_primary_mac_addr(priv, saddr);87	if (err)88		return err;89 90	eth_hw_addr_set(ndev, saddr->sa_data);91 92	return 0;93}94 95static int enetc_vf_set_features(struct net_device *ndev,96				 netdev_features_t features)97{98	enetc_set_features(ndev, features);99 100	return 0;101}102 103static int enetc_vf_setup_tc(struct net_device *ndev, enum tc_setup_type type,104			     void *type_data)105{106	switch (type) {107	case TC_SETUP_QDISC_MQPRIO:108		return enetc_setup_tc_mqprio(ndev, type_data);109	default:110		return -EOPNOTSUPP;111	}112}113 114/* Probing/ Init */115static const struct net_device_ops enetc_ndev_ops = {116	.ndo_open		= enetc_open,117	.ndo_stop		= enetc_close,118	.ndo_start_xmit		= enetc_xmit,119	.ndo_get_stats		= enetc_get_stats,120	.ndo_set_mac_address	= enetc_vf_set_mac_addr,121	.ndo_set_features	= enetc_vf_set_features,122	.ndo_eth_ioctl		= enetc_ioctl,123	.ndo_setup_tc		= enetc_vf_setup_tc,124};125 126static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,127				  const struct net_device_ops *ndev_ops)128{129	struct enetc_ndev_priv *priv = netdev_priv(ndev);130 131	SET_NETDEV_DEV(ndev, &si->pdev->dev);132	priv->ndev = ndev;133	priv->si = si;134	priv->dev = &si->pdev->dev;135	si->ndev = ndev;136 137	priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1;138	ndev->netdev_ops = ndev_ops;139	enetc_set_ethtool_ops(ndev);140	ndev->watchdog_timeo = 5 * HZ;141	ndev->max_mtu = ENETC_MAX_MTU;142 143	ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |144			    NETIF_F_HW_VLAN_CTAG_TX |145			    NETIF_F_HW_VLAN_CTAG_RX |146			    NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;147	ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |148			 NETIF_F_HW_VLAN_CTAG_TX |149			 NETIF_F_HW_VLAN_CTAG_RX |150			 NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;151	ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |152			      NETIF_F_TSO | NETIF_F_TSO6;153 154	if (si->num_rss)155		ndev->hw_features |= NETIF_F_RXHASH;156 157	/* pick up primary MAC address from SI */158	enetc_load_primary_mac_addr(&si->hw, ndev);159}160 161static int enetc_vf_probe(struct pci_dev *pdev,162			  const struct pci_device_id *ent)163{164	struct enetc_ndev_priv *priv;165	struct net_device *ndev;166	struct enetc_si *si;167	int err;168 169	err = enetc_pci_probe(pdev, KBUILD_MODNAME, 0);170	if (err)171		return dev_err_probe(&pdev->dev, err, "PCI probing failed\n");172 173	si = pci_get_drvdata(pdev);174 175	enetc_get_si_caps(si);176 177	ndev = alloc_etherdev_mq(sizeof(*priv), ENETC_MAX_NUM_TXQS);178	if (!ndev) {179		err = -ENOMEM;180		dev_err(&pdev->dev, "netdev creation failed\n");181		goto err_alloc_netdev;182	}183 184	enetc_vf_netdev_setup(si, ndev, &enetc_ndev_ops);185 186	priv = netdev_priv(ndev);187 188	enetc_init_si_rings_params(priv);189 190	err = enetc_setup_cbdr(priv->dev, &si->hw, ENETC_CBDR_DEFAULT_SIZE,191			       &si->cbd_ring);192	if (err)193		goto err_setup_cbdr;194 195	err = enetc_alloc_si_resources(priv);196	if (err) {197		dev_err(&pdev->dev, "SI resource alloc failed\n");198		goto err_alloc_si_res;199	}200 201	err = enetc_configure_si(priv);202	if (err) {203		dev_err(&pdev->dev, "Failed to configure SI\n");204		goto err_config_si;205	}206 207	err = enetc_alloc_msix(priv);208	if (err) {209		dev_err(&pdev->dev, "MSIX alloc failed\n");210		goto err_alloc_msix;211	}212 213	err = register_netdev(ndev);214	if (err)215		goto err_reg_netdev;216 217	netif_carrier_off(ndev);218 219	return 0;220 221err_reg_netdev:222	enetc_free_msix(priv);223err_config_si:224err_alloc_msix:225	enetc_free_si_resources(priv);226err_alloc_si_res:227	enetc_teardown_cbdr(&si->cbd_ring);228err_setup_cbdr:229	si->ndev = NULL;230	free_netdev(ndev);231err_alloc_netdev:232	enetc_pci_remove(pdev);233 234	return err;235}236 237static void enetc_vf_remove(struct pci_dev *pdev)238{239	struct enetc_si *si = pci_get_drvdata(pdev);240	struct enetc_ndev_priv *priv;241 242	priv = netdev_priv(si->ndev);243	unregister_netdev(si->ndev);244 245	enetc_free_msix(priv);246 247	enetc_free_si_resources(priv);248	enetc_teardown_cbdr(&si->cbd_ring);249 250	free_netdev(si->ndev);251 252	enetc_pci_remove(pdev);253}254 255static const struct pci_device_id enetc_vf_id_table[] = {256	{ PCI_DEVICE(PCI_VENDOR_ID_FREESCALE, ENETC_DEV_ID_VF) },257	{ 0, } /* End of table. */258};259MODULE_DEVICE_TABLE(pci, enetc_vf_id_table);260 261static struct pci_driver enetc_vf_driver = {262	.name = KBUILD_MODNAME,263	.id_table = enetc_vf_id_table,264	.probe = enetc_vf_probe,265	.remove = enetc_vf_remove,266};267module_pci_driver(enetc_vf_driver);268 269MODULE_DESCRIPTION(ENETC_DRV_NAME_STR);270MODULE_LICENSE("Dual BSD/GPL");271