11f233f32SVijaya Mohan Guvva /**********************************************************************
21f233f32SVijaya Mohan Guvva  * Author: Cavium, Inc.
31f233f32SVijaya Mohan Guvva  *
41f233f32SVijaya Mohan Guvva  * Contact: support@cavium.com
51f233f32SVijaya Mohan Guvva  *          Please include "LiquidIO" in the subject.
61f233f32SVijaya Mohan Guvva  *
71f233f32SVijaya Mohan Guvva  * Copyright (c) 2003-2017 Cavium, Inc.
81f233f32SVijaya Mohan Guvva  *
91f233f32SVijaya Mohan Guvva  * This file is free software; you can redistribute it and/or modify
101f233f32SVijaya Mohan Guvva  * it under the terms of the GNU General Public License, Version 2, as
111f233f32SVijaya Mohan Guvva  * published by the Free Software Foundation.
121f233f32SVijaya Mohan Guvva  *
131f233f32SVijaya Mohan Guvva  * This file is distributed in the hope that it will be useful, but
141f233f32SVijaya Mohan Guvva  * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
151f233f32SVijaya Mohan Guvva  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
161f233f32SVijaya Mohan Guvva  * NONINFRINGEMENT.  See the GNU General Public License for more details.
171f233f32SVijaya Mohan Guvva  ***********************************************************************/
181f233f32SVijaya Mohan Guvva #include <linux/pci.h>
191f233f32SVijaya Mohan Guvva #include <linux/if_vlan.h>
201f233f32SVijaya Mohan Guvva #include "liquidio_common.h"
211f233f32SVijaya Mohan Guvva #include "octeon_droq.h"
221f233f32SVijaya Mohan Guvva #include "octeon_iq.h"
231f233f32SVijaya Mohan Guvva #include "response_manager.h"
241f233f32SVijaya Mohan Guvva #include "octeon_device.h"
251f233f32SVijaya Mohan Guvva #include "octeon_nic.h"
261f233f32SVijaya Mohan Guvva #include "octeon_main.h"
271f233f32SVijaya Mohan Guvva #include "octeon_network.h"
281f233f32SVijaya Mohan Guvva #include "lio_vf_rep.h"
291f233f32SVijaya Mohan Guvva 
301f233f32SVijaya Mohan Guvva static int lio_vf_rep_open(struct net_device *ndev);
311f233f32SVijaya Mohan Guvva static int lio_vf_rep_stop(struct net_device *ndev);
32ac1172deSYueHaibing static netdev_tx_t lio_vf_rep_pkt_xmit(struct sk_buff *skb,
33ac1172deSYueHaibing 				       struct net_device *ndev);
340290bd29SMichael S. Tsirkin static void lio_vf_rep_tx_timeout(struct net_device *netdev, unsigned int txqueue);
351f233f32SVijaya Mohan Guvva static int lio_vf_rep_phys_port_name(struct net_device *dev,
361f233f32SVijaya Mohan Guvva 				     char *buf, size_t len);
371f233f32SVijaya Mohan Guvva static void lio_vf_rep_get_stats64(struct net_device *dev,
381f233f32SVijaya Mohan Guvva 				   struct rtnl_link_stats64 *stats64);
391f233f32SVijaya Mohan Guvva static int lio_vf_rep_change_mtu(struct net_device *ndev, int new_mtu);
40c4bf2450SFlorian Fainelli static int lio_vf_get_port_parent_id(struct net_device *dev,
41c4bf2450SFlorian Fainelli 				     struct netdev_phys_item_id *ppid);
421f233f32SVijaya Mohan Guvva 
431f233f32SVijaya Mohan Guvva static const struct net_device_ops lio_vf_rep_ndev_ops = {
441f233f32SVijaya Mohan Guvva 	.ndo_open = lio_vf_rep_open,
451f233f32SVijaya Mohan Guvva 	.ndo_stop = lio_vf_rep_stop,
461f233f32SVijaya Mohan Guvva 	.ndo_start_xmit = lio_vf_rep_pkt_xmit,
471f233f32SVijaya Mohan Guvva 	.ndo_tx_timeout = lio_vf_rep_tx_timeout,
481f233f32SVijaya Mohan Guvva 	.ndo_get_phys_port_name = lio_vf_rep_phys_port_name,
491f233f32SVijaya Mohan Guvva 	.ndo_get_stats64 = lio_vf_rep_get_stats64,
501f233f32SVijaya Mohan Guvva 	.ndo_change_mtu = lio_vf_rep_change_mtu,
51c4bf2450SFlorian Fainelli 	.ndo_get_port_parent_id = lio_vf_get_port_parent_id,
521f233f32SVijaya Mohan Guvva };
531f233f32SVijaya Mohan Guvva 
541f233f32SVijaya Mohan Guvva static int
lio_vf_rep_send_soft_command(struct octeon_device * oct,void * req,int req_size,void * resp,int resp_size)551f233f32SVijaya Mohan Guvva lio_vf_rep_send_soft_command(struct octeon_device *oct,
561f233f32SVijaya Mohan Guvva 			     void *req, int req_size,
571f233f32SVijaya Mohan Guvva 			     void *resp, int resp_size)
581f233f32SVijaya Mohan Guvva {
591f233f32SVijaya Mohan Guvva 	int tot_resp_size = sizeof(struct lio_vf_rep_resp) + resp_size;
601f233f32SVijaya Mohan Guvva 	struct octeon_soft_command *sc = NULL;
611f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_resp *rep_resp;
621f233f32SVijaya Mohan Guvva 	void *sc_req;
631f233f32SVijaya Mohan Guvva 	int err;
641f233f32SVijaya Mohan Guvva 
651f233f32SVijaya Mohan Guvva 	sc = (struct octeon_soft_command *)
661f233f32SVijaya Mohan Guvva 		octeon_alloc_soft_command(oct, req_size,
676870957eSFelix Manlunas 					  tot_resp_size, 0);
681f233f32SVijaya Mohan Guvva 	if (!sc)
691f233f32SVijaya Mohan Guvva 		return -ENOMEM;
701f233f32SVijaya Mohan Guvva 
716870957eSFelix Manlunas 	init_completion(&sc->complete);
726870957eSFelix Manlunas 	sc->sc_status = OCTEON_REQUEST_PENDING;
731f233f32SVijaya Mohan Guvva 
741f233f32SVijaya Mohan Guvva 	sc_req = (struct lio_vf_rep_req *)sc->virtdptr;
751f233f32SVijaya Mohan Guvva 	memcpy(sc_req, req, req_size);
761f233f32SVijaya Mohan Guvva 
771f233f32SVijaya Mohan Guvva 	rep_resp = (struct lio_vf_rep_resp *)sc->virtrptr;
781f233f32SVijaya Mohan Guvva 	memset(rep_resp, 0, tot_resp_size);
791f233f32SVijaya Mohan Guvva 	WRITE_ONCE(rep_resp->status, 1);
801f233f32SVijaya Mohan Guvva 
811f233f32SVijaya Mohan Guvva 	sc->iq_no = 0;
821f233f32SVijaya Mohan Guvva 	octeon_prepare_soft_command(oct, sc, OPCODE_NIC,
831f233f32SVijaya Mohan Guvva 				    OPCODE_NIC_VF_REP_CMD, 0, 0, 0);
841f233f32SVijaya Mohan Guvva 
851f233f32SVijaya Mohan Guvva 	err = octeon_send_soft_command(oct, sc);
861f233f32SVijaya Mohan Guvva 	if (err == IQ_SEND_FAILED)
871f233f32SVijaya Mohan Guvva 		goto free_buff;
881f233f32SVijaya Mohan Guvva 
896870957eSFelix Manlunas 	err = wait_for_sc_completion_timeout(oct, sc, 0);
906870957eSFelix Manlunas 	if (err)
916870957eSFelix Manlunas 		return err;
926870957eSFelix Manlunas 
931f233f32SVijaya Mohan Guvva 	err = READ_ONCE(rep_resp->status) ? -EBUSY : 0;
941f233f32SVijaya Mohan Guvva 	if (err)
951f233f32SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev, "VF rep send config failed\n");
966870957eSFelix Manlunas 	else if (resp)
971f233f32SVijaya Mohan Guvva 		memcpy(resp, (rep_resp + 1), resp_size);
986870957eSFelix Manlunas 
996870957eSFelix Manlunas 	WRITE_ONCE(sc->caller_is_done, true);
1006870957eSFelix Manlunas 	return err;
1016870957eSFelix Manlunas 
1021f233f32SVijaya Mohan Guvva free_buff:
1031f233f32SVijaya Mohan Guvva 	octeon_free_soft_command(oct, sc);
1041f233f32SVijaya Mohan Guvva 
1051f233f32SVijaya Mohan Guvva 	return err;
1061f233f32SVijaya Mohan Guvva }
1071f233f32SVijaya Mohan Guvva 
1081f233f32SVijaya Mohan Guvva static int
lio_vf_rep_open(struct net_device * ndev)1091f233f32SVijaya Mohan Guvva lio_vf_rep_open(struct net_device *ndev)
1101f233f32SVijaya Mohan Guvva {
1111f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep = netdev_priv(ndev);
1121f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_req rep_cfg;
1131f233f32SVijaya Mohan Guvva 	struct octeon_device *oct;
1141f233f32SVijaya Mohan Guvva 	int ret;
1151f233f32SVijaya Mohan Guvva 
1161f233f32SVijaya Mohan Guvva 	oct = vf_rep->oct;
1171f233f32SVijaya Mohan Guvva 
1181f233f32SVijaya Mohan Guvva 	memset(&rep_cfg, 0, sizeof(rep_cfg));
1191f233f32SVijaya Mohan Guvva 	rep_cfg.req_type = LIO_VF_REP_REQ_STATE;
1201f233f32SVijaya Mohan Guvva 	rep_cfg.ifidx = vf_rep->ifidx;
1211f233f32SVijaya Mohan Guvva 	rep_cfg.rep_state.state = LIO_VF_REP_STATE_UP;
1221f233f32SVijaya Mohan Guvva 
1231f233f32SVijaya Mohan Guvva 	ret = lio_vf_rep_send_soft_command(oct, &rep_cfg,
1241f233f32SVijaya Mohan Guvva 					   sizeof(rep_cfg), NULL, 0);
1251f233f32SVijaya Mohan Guvva 
1261f233f32SVijaya Mohan Guvva 	if (ret) {
1271f233f32SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev,
1281f233f32SVijaya Mohan Guvva 			"VF_REP open failed with err %d\n", ret);
1291f233f32SVijaya Mohan Guvva 		return -EIO;
1301f233f32SVijaya Mohan Guvva 	}
1311f233f32SVijaya Mohan Guvva 
1321f233f32SVijaya Mohan Guvva 	atomic_set(&vf_rep->ifstate, (atomic_read(&vf_rep->ifstate) |
1331f233f32SVijaya Mohan Guvva 				      LIO_IFSTATE_RUNNING));
1341f233f32SVijaya Mohan Guvva 
1351f233f32SVijaya Mohan Guvva 	netif_carrier_on(ndev);
1361f233f32SVijaya Mohan Guvva 	netif_start_queue(ndev);
1371f233f32SVijaya Mohan Guvva 
1381f233f32SVijaya Mohan Guvva 	return 0;
1391f233f32SVijaya Mohan Guvva }
1401f233f32SVijaya Mohan Guvva 
1411f233f32SVijaya Mohan Guvva static int
lio_vf_rep_stop(struct net_device * ndev)1421f233f32SVijaya Mohan Guvva lio_vf_rep_stop(struct net_device *ndev)
1431f233f32SVijaya Mohan Guvva {
1441f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep = netdev_priv(ndev);
1451f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_req rep_cfg;
1461f233f32SVijaya Mohan Guvva 	struct octeon_device *oct;
1471f233f32SVijaya Mohan Guvva 	int ret;
1481f233f32SVijaya Mohan Guvva 
1491f233f32SVijaya Mohan Guvva 	oct = vf_rep->oct;
1501f233f32SVijaya Mohan Guvva 
1511f233f32SVijaya Mohan Guvva 	memset(&rep_cfg, 0, sizeof(rep_cfg));
1521f233f32SVijaya Mohan Guvva 	rep_cfg.req_type = LIO_VF_REP_REQ_STATE;
1531f233f32SVijaya Mohan Guvva 	rep_cfg.ifidx = vf_rep->ifidx;
1541f233f32SVijaya Mohan Guvva 	rep_cfg.rep_state.state = LIO_VF_REP_STATE_DOWN;
1551f233f32SVijaya Mohan Guvva 
1561f233f32SVijaya Mohan Guvva 	ret = lio_vf_rep_send_soft_command(oct, &rep_cfg,
1571f233f32SVijaya Mohan Guvva 					   sizeof(rep_cfg), NULL, 0);
1581f233f32SVijaya Mohan Guvva 
1591f233f32SVijaya Mohan Guvva 	if (ret) {
1601f233f32SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev,
1611f233f32SVijaya Mohan Guvva 			"VF_REP dev stop failed with err %d\n", ret);
1621f233f32SVijaya Mohan Guvva 		return -EIO;
1631f233f32SVijaya Mohan Guvva 	}
1641f233f32SVijaya Mohan Guvva 
1651f233f32SVijaya Mohan Guvva 	atomic_set(&vf_rep->ifstate, (atomic_read(&vf_rep->ifstate) &
1661f233f32SVijaya Mohan Guvva 				      ~LIO_IFSTATE_RUNNING));
1671f233f32SVijaya Mohan Guvva 
1681f233f32SVijaya Mohan Guvva 	netif_tx_disable(ndev);
1691f233f32SVijaya Mohan Guvva 	netif_carrier_off(ndev);
1701f233f32SVijaya Mohan Guvva 
1711f233f32SVijaya Mohan Guvva 	return 0;
1721f233f32SVijaya Mohan Guvva }
1731f233f32SVijaya Mohan Guvva 
1741f233f32SVijaya Mohan Guvva static void
lio_vf_rep_tx_timeout(struct net_device * ndev,unsigned int txqueue)1750290bd29SMichael S. Tsirkin lio_vf_rep_tx_timeout(struct net_device *ndev, unsigned int txqueue)
1761f233f32SVijaya Mohan Guvva {
1771f233f32SVijaya Mohan Guvva 	netif_trans_update(ndev);
1781f233f32SVijaya Mohan Guvva 
1791f233f32SVijaya Mohan Guvva 	netif_wake_queue(ndev);
1801f233f32SVijaya Mohan Guvva }
1811f233f32SVijaya Mohan Guvva 
1821f233f32SVijaya Mohan Guvva static void
lio_vf_rep_get_stats64(struct net_device * dev,struct rtnl_link_stats64 * stats64)1831f233f32SVijaya Mohan Guvva lio_vf_rep_get_stats64(struct net_device *dev,
1841f233f32SVijaya Mohan Guvva 		       struct rtnl_link_stats64 *stats64)
1851f233f32SVijaya Mohan Guvva {
1861f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep = netdev_priv(dev);
1871f233f32SVijaya Mohan Guvva 
18816f4faa4SSrinivas Jampala 	/* Swap tx and rx stats as VF rep is a switch port */
18916f4faa4SSrinivas Jampala 	stats64->tx_packets = vf_rep->stats.rx_packets;
19016f4faa4SSrinivas Jampala 	stats64->tx_bytes   = vf_rep->stats.rx_bytes;
19116f4faa4SSrinivas Jampala 	stats64->tx_dropped = vf_rep->stats.rx_dropped;
1921f233f32SVijaya Mohan Guvva 
19316f4faa4SSrinivas Jampala 	stats64->rx_packets = vf_rep->stats.tx_packets;
19416f4faa4SSrinivas Jampala 	stats64->rx_bytes   = vf_rep->stats.tx_bytes;
19516f4faa4SSrinivas Jampala 	stats64->rx_dropped = vf_rep->stats.tx_dropped;
1961f233f32SVijaya Mohan Guvva }
1971f233f32SVijaya Mohan Guvva 
1981f233f32SVijaya Mohan Guvva static int
lio_vf_rep_change_mtu(struct net_device * ndev,int new_mtu)1991f233f32SVijaya Mohan Guvva lio_vf_rep_change_mtu(struct net_device *ndev, int new_mtu)
2001f233f32SVijaya Mohan Guvva {
2011f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep = netdev_priv(ndev);
2021f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_req rep_cfg;
2031f233f32SVijaya Mohan Guvva 	struct octeon_device *oct;
2041f233f32SVijaya Mohan Guvva 	int ret;
2051f233f32SVijaya Mohan Guvva 
2061f233f32SVijaya Mohan Guvva 	oct = vf_rep->oct;
2071f233f32SVijaya Mohan Guvva 
2081f233f32SVijaya Mohan Guvva 	memset(&rep_cfg, 0, sizeof(rep_cfg));
2091f233f32SVijaya Mohan Guvva 	rep_cfg.req_type = LIO_VF_REP_REQ_MTU;
2101f233f32SVijaya Mohan Guvva 	rep_cfg.ifidx = vf_rep->ifidx;
2111f233f32SVijaya Mohan Guvva 	rep_cfg.rep_mtu.mtu = cpu_to_be32(new_mtu);
2121f233f32SVijaya Mohan Guvva 
2131f233f32SVijaya Mohan Guvva 	ret = lio_vf_rep_send_soft_command(oct, &rep_cfg,
2141f233f32SVijaya Mohan Guvva 					   sizeof(rep_cfg), NULL, 0);
2151f233f32SVijaya Mohan Guvva 	if (ret) {
2161f233f32SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev,
2171f233f32SVijaya Mohan Guvva 			"Change MTU failed with err %d\n", ret);
2181f233f32SVijaya Mohan Guvva 		return -EIO;
2191f233f32SVijaya Mohan Guvva 	}
2201f233f32SVijaya Mohan Guvva 
221*1eb2cdedSEric Dumazet 	WRITE_ONCE(ndev->mtu, new_mtu);
2221f233f32SVijaya Mohan Guvva 
2231f233f32SVijaya Mohan Guvva 	return 0;
2241f233f32SVijaya Mohan Guvva }
2251f233f32SVijaya Mohan Guvva 
2261f233f32SVijaya Mohan Guvva static int
lio_vf_rep_phys_port_name(struct net_device * dev,char * buf,size_t len)2271f233f32SVijaya Mohan Guvva lio_vf_rep_phys_port_name(struct net_device *dev,
2281f233f32SVijaya Mohan Guvva 			  char *buf, size_t len)
2291f233f32SVijaya Mohan Guvva {
2301f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep = netdev_priv(dev);
2311f233f32SVijaya Mohan Guvva 	struct octeon_device *oct = vf_rep->oct;
2321f233f32SVijaya Mohan Guvva 	int ret;
2331f233f32SVijaya Mohan Guvva 
2341f233f32SVijaya Mohan Guvva 	ret = snprintf(buf, len, "pf%dvf%d", oct->pf_num,
2351f233f32SVijaya Mohan Guvva 		       vf_rep->ifidx - oct->pf_num * 64 - 1);
2361f233f32SVijaya Mohan Guvva 	if (ret >= len)
2371f233f32SVijaya Mohan Guvva 		return -EOPNOTSUPP;
2381f233f32SVijaya Mohan Guvva 
2391f233f32SVijaya Mohan Guvva 	return 0;
2401f233f32SVijaya Mohan Guvva }
2411f233f32SVijaya Mohan Guvva 
2421f233f32SVijaya Mohan Guvva static struct net_device *
lio_vf_rep_get_ndev(struct octeon_device * oct,int ifidx)2431f233f32SVijaya Mohan Guvva lio_vf_rep_get_ndev(struct octeon_device *oct, int ifidx)
2441f233f32SVijaya Mohan Guvva {
2451f233f32SVijaya Mohan Guvva 	int vf_id, max_vfs = CN23XX_MAX_VFS_PER_PF + 1;
2461f233f32SVijaya Mohan Guvva 	int vfid_mask = max_vfs - 1;
2471f233f32SVijaya Mohan Guvva 
2481f233f32SVijaya Mohan Guvva 	if (ifidx <= oct->pf_num * max_vfs ||
2491f233f32SVijaya Mohan Guvva 	    ifidx >= oct->pf_num * max_vfs + max_vfs)
2501f233f32SVijaya Mohan Guvva 		return NULL;
2511f233f32SVijaya Mohan Guvva 
2521f233f32SVijaya Mohan Guvva 	/* ifidx 1-63 for PF0 VFs
2531f233f32SVijaya Mohan Guvva 	 * ifidx 65-127 for PF1 VFs
2541f233f32SVijaya Mohan Guvva 	 */
2551f233f32SVijaya Mohan Guvva 	vf_id = (ifidx & vfid_mask) - 1;
2561f233f32SVijaya Mohan Guvva 
2571f233f32SVijaya Mohan Guvva 	return oct->vf_rep_list.ndev[vf_id];
2581f233f32SVijaya Mohan Guvva }
2591f233f32SVijaya Mohan Guvva 
2601f233f32SVijaya Mohan Guvva static void
lio_vf_rep_copy_packet(struct octeon_device * oct,struct sk_buff * skb,int len)2611f233f32SVijaya Mohan Guvva lio_vf_rep_copy_packet(struct octeon_device *oct,
2621f233f32SVijaya Mohan Guvva 		       struct sk_buff *skb,
2631f233f32SVijaya Mohan Guvva 		       int len)
2641f233f32SVijaya Mohan Guvva {
2651f233f32SVijaya Mohan Guvva 	if (likely(len > MIN_SKB_SIZE)) {
2661f233f32SVijaya Mohan Guvva 		struct octeon_skb_page_info *pg_info;
2671f233f32SVijaya Mohan Guvva 		unsigned char *va;
2681f233f32SVijaya Mohan Guvva 
2691f233f32SVijaya Mohan Guvva 		pg_info = ((struct octeon_skb_page_info *)(skb->cb));
2701f233f32SVijaya Mohan Guvva 		if (pg_info->page) {
2711f233f32SVijaya Mohan Guvva 			va = page_address(pg_info->page) +
2721f233f32SVijaya Mohan Guvva 				pg_info->page_offset;
2731f233f32SVijaya Mohan Guvva 			memcpy(skb->data, va, MIN_SKB_SIZE);
2741f233f32SVijaya Mohan Guvva 			skb_put(skb, MIN_SKB_SIZE);
2751f233f32SVijaya Mohan Guvva 		}
2761f233f32SVijaya Mohan Guvva 
2771f233f32SVijaya Mohan Guvva 		skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags,
2781f233f32SVijaya Mohan Guvva 				pg_info->page,
2791f233f32SVijaya Mohan Guvva 				pg_info->page_offset + MIN_SKB_SIZE,
2801f233f32SVijaya Mohan Guvva 				len - MIN_SKB_SIZE,
2811f233f32SVijaya Mohan Guvva 				LIO_RXBUFFER_SZ);
2821f233f32SVijaya Mohan Guvva 	} else {
2831f233f32SVijaya Mohan Guvva 		struct octeon_skb_page_info *pg_info =
2841f233f32SVijaya Mohan Guvva 			((struct octeon_skb_page_info *)(skb->cb));
2851f233f32SVijaya Mohan Guvva 
2861f233f32SVijaya Mohan Guvva 		skb_copy_to_linear_data(skb, page_address(pg_info->page) +
2871f233f32SVijaya Mohan Guvva 					pg_info->page_offset, len);
2881f233f32SVijaya Mohan Guvva 		skb_put(skb, len);
2891f233f32SVijaya Mohan Guvva 		put_page(pg_info->page);
2901f233f32SVijaya Mohan Guvva 	}
2911f233f32SVijaya Mohan Guvva }
2921f233f32SVijaya Mohan Guvva 
2931f233f32SVijaya Mohan Guvva static int
lio_vf_rep_pkt_recv(struct octeon_recv_info * recv_info,void * buf)2941f233f32SVijaya Mohan Guvva lio_vf_rep_pkt_recv(struct octeon_recv_info *recv_info, void *buf)
2951f233f32SVijaya Mohan Guvva {
2961f233f32SVijaya Mohan Guvva 	struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt;
2971f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep;
2981f233f32SVijaya Mohan Guvva 	struct net_device *vf_ndev;
2991f233f32SVijaya Mohan Guvva 	struct octeon_device *oct;
3001f233f32SVijaya Mohan Guvva 	union octeon_rh *rh;
3011f233f32SVijaya Mohan Guvva 	struct sk_buff *skb;
3021f233f32SVijaya Mohan Guvva 	int i, ifidx;
3031f233f32SVijaya Mohan Guvva 
3041f233f32SVijaya Mohan Guvva 	oct = lio_get_device(recv_pkt->octeon_id);
3051f233f32SVijaya Mohan Guvva 	if (!oct)
3061f233f32SVijaya Mohan Guvva 		goto free_buffers;
3071f233f32SVijaya Mohan Guvva 
3081f233f32SVijaya Mohan Guvva 	skb = recv_pkt->buffer_ptr[0];
3091f233f32SVijaya Mohan Guvva 	rh = &recv_pkt->rh;
3101f233f32SVijaya Mohan Guvva 	ifidx = rh->r.ossp;
3111f233f32SVijaya Mohan Guvva 
3121f233f32SVijaya Mohan Guvva 	vf_ndev = lio_vf_rep_get_ndev(oct, ifidx);
3131f233f32SVijaya Mohan Guvva 	if (!vf_ndev)
3141f233f32SVijaya Mohan Guvva 		goto free_buffers;
3151f233f32SVijaya Mohan Guvva 
3161f233f32SVijaya Mohan Guvva 	vf_rep = netdev_priv(vf_ndev);
3171f233f32SVijaya Mohan Guvva 	if (!(atomic_read(&vf_rep->ifstate) & LIO_IFSTATE_RUNNING) ||
3181f233f32SVijaya Mohan Guvva 	    recv_pkt->buffer_count > 1)
3191f233f32SVijaya Mohan Guvva 		goto free_buffers;
3201f233f32SVijaya Mohan Guvva 
3211f233f32SVijaya Mohan Guvva 	skb->dev = vf_ndev;
3221f233f32SVijaya Mohan Guvva 
3231f233f32SVijaya Mohan Guvva 	/* Multiple buffers are not used for vf_rep packets.
3241f233f32SVijaya Mohan Guvva 	 * So just buffer_size[0] is valid.
3251f233f32SVijaya Mohan Guvva 	 */
3261f233f32SVijaya Mohan Guvva 	lio_vf_rep_copy_packet(oct, skb, recv_pkt->buffer_size[0]);
3271f233f32SVijaya Mohan Guvva 
3281f233f32SVijaya Mohan Guvva 	skb_pull(skb, rh->r_dh.len * BYTES_PER_DHLEN_UNIT);
3291f233f32SVijaya Mohan Guvva 	skb->protocol = eth_type_trans(skb, skb->dev);
3301f233f32SVijaya Mohan Guvva 	skb->ip_summed = CHECKSUM_NONE;
3311f233f32SVijaya Mohan Guvva 
3321f233f32SVijaya Mohan Guvva 	netif_rx(skb);
3331f233f32SVijaya Mohan Guvva 
3341f233f32SVijaya Mohan Guvva 	octeon_free_recv_info(recv_info);
3351f233f32SVijaya Mohan Guvva 
3361f233f32SVijaya Mohan Guvva 	return 0;
3371f233f32SVijaya Mohan Guvva 
3381f233f32SVijaya Mohan Guvva free_buffers:
3391f233f32SVijaya Mohan Guvva 	for (i = 0; i < recv_pkt->buffer_count; i++)
3401f233f32SVijaya Mohan Guvva 		recv_buffer_free(recv_pkt->buffer_ptr[i]);
3411f233f32SVijaya Mohan Guvva 
3421f233f32SVijaya Mohan Guvva 	octeon_free_recv_info(recv_info);
3431f233f32SVijaya Mohan Guvva 
3441f233f32SVijaya Mohan Guvva 	return 0;
3451f233f32SVijaya Mohan Guvva }
3461f233f32SVijaya Mohan Guvva 
3471f233f32SVijaya Mohan Guvva static void
lio_vf_rep_packet_sent_callback(struct octeon_device * oct,u32 status,void * buf)3481f233f32SVijaya Mohan Guvva lio_vf_rep_packet_sent_callback(struct octeon_device *oct,
3491f233f32SVijaya Mohan Guvva 				u32 status, void *buf)
3501f233f32SVijaya Mohan Guvva {
3511f233f32SVijaya Mohan Guvva 	struct octeon_soft_command *sc = (struct octeon_soft_command *)buf;
3521f233f32SVijaya Mohan Guvva 	struct sk_buff *skb = sc->ctxptr;
3531f233f32SVijaya Mohan Guvva 	struct net_device *ndev = skb->dev;
354c0f53771SPan Bian 	u32 iq_no;
3551f233f32SVijaya Mohan Guvva 
3561f233f32SVijaya Mohan Guvva 	dma_unmap_single(&oct->pci_dev->dev, sc->dmadptr,
3571f233f32SVijaya Mohan Guvva 			 sc->datasize, DMA_TO_DEVICE);
3581f233f32SVijaya Mohan Guvva 	dev_kfree_skb_any(skb);
359c0f53771SPan Bian 	iq_no = sc->iq_no;
3601f233f32SVijaya Mohan Guvva 	octeon_free_soft_command(oct, sc);
3611f233f32SVijaya Mohan Guvva 
362c0f53771SPan Bian 	if (octnet_iq_is_full(oct, iq_no))
3631f233f32SVijaya Mohan Guvva 		return;
3641f233f32SVijaya Mohan Guvva 
3651f233f32SVijaya Mohan Guvva 	if (netif_queue_stopped(ndev))
3661f233f32SVijaya Mohan Guvva 		netif_wake_queue(ndev);
3671f233f32SVijaya Mohan Guvva }
3681f233f32SVijaya Mohan Guvva 
369ac1172deSYueHaibing static netdev_tx_t
lio_vf_rep_pkt_xmit(struct sk_buff * skb,struct net_device * ndev)3701f233f32SVijaya Mohan Guvva lio_vf_rep_pkt_xmit(struct sk_buff *skb, struct net_device *ndev)
3711f233f32SVijaya Mohan Guvva {
3721f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep = netdev_priv(ndev);
3731f233f32SVijaya Mohan Guvva 	struct net_device *parent_ndev = vf_rep->parent_ndev;
3741f233f32SVijaya Mohan Guvva 	struct octeon_device *oct = vf_rep->oct;
3751f233f32SVijaya Mohan Guvva 	struct octeon_instr_pki_ih3 *pki_ih3;
3761f233f32SVijaya Mohan Guvva 	struct octeon_soft_command *sc;
3771f233f32SVijaya Mohan Guvva 	struct lio *parent_lio;
3781f233f32SVijaya Mohan Guvva 	int status;
3791f233f32SVijaya Mohan Guvva 
3801f233f32SVijaya Mohan Guvva 	parent_lio = GET_LIO(parent_ndev);
3811f233f32SVijaya Mohan Guvva 
3821f233f32SVijaya Mohan Guvva 	if (!(atomic_read(&vf_rep->ifstate) & LIO_IFSTATE_RUNNING) ||
3831f233f32SVijaya Mohan Guvva 	    skb->len <= 0)
3841f233f32SVijaya Mohan Guvva 		goto xmit_failed;
3851f233f32SVijaya Mohan Guvva 
3861f233f32SVijaya Mohan Guvva 	if (octnet_iq_is_full(vf_rep->oct, parent_lio->txq)) {
3871f233f32SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev, "VF rep: Device IQ full\n");
3881f233f32SVijaya Mohan Guvva 		netif_stop_queue(ndev);
3891f233f32SVijaya Mohan Guvva 		return NETDEV_TX_BUSY;
3901f233f32SVijaya Mohan Guvva 	}
3911f233f32SVijaya Mohan Guvva 
3921f233f32SVijaya Mohan Guvva 	sc = (struct octeon_soft_command *)
39364fecd3eSFelix Manlunas 		octeon_alloc_soft_command(oct, 0, 16, 0);
3941f233f32SVijaya Mohan Guvva 	if (!sc) {
3951f233f32SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev, "VF rep: Soft command alloc failed\n");
3961f233f32SVijaya Mohan Guvva 		goto xmit_failed;
3971f233f32SVijaya Mohan Guvva 	}
3981f233f32SVijaya Mohan Guvva 
3991f233f32SVijaya Mohan Guvva 	/* Multiple buffers are not used for vf_rep packets. */
4001f233f32SVijaya Mohan Guvva 	if (skb_shinfo(skb)->nr_frags != 0) {
4011f233f32SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev, "VF rep: nr_frags != 0. Dropping packet\n");
40264fecd3eSFelix Manlunas 		octeon_free_soft_command(oct, sc);
4031f233f32SVijaya Mohan Guvva 		goto xmit_failed;
4041f233f32SVijaya Mohan Guvva 	}
4051f233f32SVijaya Mohan Guvva 
4061f233f32SVijaya Mohan Guvva 	sc->dmadptr = dma_map_single(&oct->pci_dev->dev,
4071f233f32SVijaya Mohan Guvva 				     skb->data, skb->len, DMA_TO_DEVICE);
4081f233f32SVijaya Mohan Guvva 	if (dma_mapping_error(&oct->pci_dev->dev, sc->dmadptr)) {
4091f233f32SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev, "VF rep: DMA mapping failed\n");
41064fecd3eSFelix Manlunas 		octeon_free_soft_command(oct, sc);
4111f233f32SVijaya Mohan Guvva 		goto xmit_failed;
4121f233f32SVijaya Mohan Guvva 	}
4131f233f32SVijaya Mohan Guvva 
4141f233f32SVijaya Mohan Guvva 	sc->virtdptr = skb->data;
4151f233f32SVijaya Mohan Guvva 	sc->datasize = skb->len;
4161f233f32SVijaya Mohan Guvva 	sc->ctxptr = skb;
4171f233f32SVijaya Mohan Guvva 	sc->iq_no = parent_lio->txq;
4181f233f32SVijaya Mohan Guvva 
4191f233f32SVijaya Mohan Guvva 	octeon_prepare_soft_command(oct, sc, OPCODE_NIC, OPCODE_NIC_VF_REP_PKT,
4201f233f32SVijaya Mohan Guvva 				    vf_rep->ifidx, 0, 0);
4211f233f32SVijaya Mohan Guvva 	pki_ih3 = (struct octeon_instr_pki_ih3 *)&sc->cmd.cmd3.pki_ih3;
4221f233f32SVijaya Mohan Guvva 	pki_ih3->tagtype = ORDERED_TAG;
4231f233f32SVijaya Mohan Guvva 
4241f233f32SVijaya Mohan Guvva 	sc->callback = lio_vf_rep_packet_sent_callback;
4251f233f32SVijaya Mohan Guvva 	sc->callback_arg = sc;
4261f233f32SVijaya Mohan Guvva 
4271f233f32SVijaya Mohan Guvva 	status = octeon_send_soft_command(oct, sc);
4281f233f32SVijaya Mohan Guvva 	if (status == IQ_SEND_FAILED) {
4291f233f32SVijaya Mohan Guvva 		dma_unmap_single(&oct->pci_dev->dev, sc->dmadptr,
4301f233f32SVijaya Mohan Guvva 				 sc->datasize, DMA_TO_DEVICE);
43164fecd3eSFelix Manlunas 		octeon_free_soft_command(oct, sc);
4321f233f32SVijaya Mohan Guvva 		goto xmit_failed;
4331f233f32SVijaya Mohan Guvva 	}
4341f233f32SVijaya Mohan Guvva 
4351f233f32SVijaya Mohan Guvva 	if (status == IQ_SEND_STOP)
4361f233f32SVijaya Mohan Guvva 		netif_stop_queue(ndev);
4371f233f32SVijaya Mohan Guvva 
4381f233f32SVijaya Mohan Guvva 	netif_trans_update(ndev);
4391f233f32SVijaya Mohan Guvva 
4401f233f32SVijaya Mohan Guvva 	return NETDEV_TX_OK;
4411f233f32SVijaya Mohan Guvva 
4421f233f32SVijaya Mohan Guvva xmit_failed:
4431f233f32SVijaya Mohan Guvva 	dev_kfree_skb_any(skb);
4441f233f32SVijaya Mohan Guvva 
4451f233f32SVijaya Mohan Guvva 	return NETDEV_TX_OK;
4461f233f32SVijaya Mohan Guvva }
4471f233f32SVijaya Mohan Guvva 
lio_vf_get_port_parent_id(struct net_device * dev,struct netdev_phys_item_id * ppid)448c4bf2450SFlorian Fainelli static int lio_vf_get_port_parent_id(struct net_device *dev,
449c4bf2450SFlorian Fainelli 				     struct netdev_phys_item_id *ppid)
4501f233f32SVijaya Mohan Guvva {
4511f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep = netdev_priv(dev);
4521f233f32SVijaya Mohan Guvva 	struct net_device *parent_ndev = vf_rep->parent_ndev;
4531f233f32SVijaya Mohan Guvva 	struct lio *lio = GET_LIO(parent_ndev);
4541f233f32SVijaya Mohan Guvva 
455c4bf2450SFlorian Fainelli 	ppid->id_len = ETH_ALEN;
456c4bf2450SFlorian Fainelli 	ether_addr_copy(ppid->id, (void *)&lio->linfo.hw_addr + 2);
4571f233f32SVijaya Mohan Guvva 
4581f233f32SVijaya Mohan Guvva 	return 0;
4591f233f32SVijaya Mohan Guvva }
4601f233f32SVijaya Mohan Guvva 
4611f233f32SVijaya Mohan Guvva static void
lio_vf_rep_fetch_stats(struct work_struct * work)4621f233f32SVijaya Mohan Guvva lio_vf_rep_fetch_stats(struct work_struct *work)
4631f233f32SVijaya Mohan Guvva {
4641f233f32SVijaya Mohan Guvva 	struct cavium_wk *wk = (struct cavium_wk *)work;
4651f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep = wk->ctxptr;
4661f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_stats stats;
4671f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_req rep_cfg;
4681f233f32SVijaya Mohan Guvva 	struct octeon_device *oct;
4691f233f32SVijaya Mohan Guvva 	int ret;
4701f233f32SVijaya Mohan Guvva 
4711f233f32SVijaya Mohan Guvva 	oct = vf_rep->oct;
4721f233f32SVijaya Mohan Guvva 
4731f233f32SVijaya Mohan Guvva 	memset(&rep_cfg, 0, sizeof(rep_cfg));
4741f233f32SVijaya Mohan Guvva 	rep_cfg.req_type = LIO_VF_REP_REQ_STATS;
4751f233f32SVijaya Mohan Guvva 	rep_cfg.ifidx = vf_rep->ifidx;
4761f233f32SVijaya Mohan Guvva 
4771f233f32SVijaya Mohan Guvva 	ret = lio_vf_rep_send_soft_command(oct, &rep_cfg, sizeof(rep_cfg),
4781f233f32SVijaya Mohan Guvva 					   &stats, sizeof(stats));
4791f233f32SVijaya Mohan Guvva 
4801f233f32SVijaya Mohan Guvva 	if (!ret) {
4811f233f32SVijaya Mohan Guvva 		octeon_swap_8B_data((u64 *)&stats, (sizeof(stats) >> 3));
4821f233f32SVijaya Mohan Guvva 		memcpy(&vf_rep->stats, &stats, sizeof(stats));
4831f233f32SVijaya Mohan Guvva 	}
4841f233f32SVijaya Mohan Guvva 
4851f233f32SVijaya Mohan Guvva 	schedule_delayed_work(&vf_rep->stats_wk.work,
4861f233f32SVijaya Mohan Guvva 			      msecs_to_jiffies(LIO_VF_REP_STATS_POLL_TIME_MS));
4871f233f32SVijaya Mohan Guvva }
4881f233f32SVijaya Mohan Guvva 
4891f233f32SVijaya Mohan Guvva int
lio_vf_rep_create(struct octeon_device * oct)4901f233f32SVijaya Mohan Guvva lio_vf_rep_create(struct octeon_device *oct)
4911f233f32SVijaya Mohan Guvva {
4921f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep;
4931f233f32SVijaya Mohan Guvva 	struct net_device *ndev;
4941f233f32SVijaya Mohan Guvva 	int i, num_vfs;
4951f233f32SVijaya Mohan Guvva 
496d4be8ebeSVijaya Mohan Guvva 	if (oct->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
497d4be8ebeSVijaya Mohan Guvva 		return 0;
498d4be8ebeSVijaya Mohan Guvva 
4991f233f32SVijaya Mohan Guvva 	if (!oct->sriov_info.sriov_enabled)
5001f233f32SVijaya Mohan Guvva 		return 0;
5011f233f32SVijaya Mohan Guvva 
5021f233f32SVijaya Mohan Guvva 	num_vfs = oct->sriov_info.num_vfs_alloced;
5031f233f32SVijaya Mohan Guvva 
5041f233f32SVijaya Mohan Guvva 	oct->vf_rep_list.num_vfs = 0;
5051f233f32SVijaya Mohan Guvva 	for (i = 0; i < num_vfs; i++) {
5061f233f32SVijaya Mohan Guvva 		ndev = alloc_etherdev(sizeof(struct lio_vf_rep_desc));
5071f233f32SVijaya Mohan Guvva 
5081f233f32SVijaya Mohan Guvva 		if (!ndev) {
5091f233f32SVijaya Mohan Guvva 			dev_err(&oct->pci_dev->dev,
5101f233f32SVijaya Mohan Guvva 				"VF rep device %d creation failed\n", i);
5111f233f32SVijaya Mohan Guvva 			goto cleanup;
5121f233f32SVijaya Mohan Guvva 		}
5131f233f32SVijaya Mohan Guvva 
5141f233f32SVijaya Mohan Guvva 		ndev->min_mtu = LIO_MIN_MTU_SIZE;
5151f233f32SVijaya Mohan Guvva 		ndev->max_mtu = LIO_MAX_MTU_SIZE;
5161f233f32SVijaya Mohan Guvva 		ndev->netdev_ops = &lio_vf_rep_ndev_ops;
5171f233f32SVijaya Mohan Guvva 
5181f233f32SVijaya Mohan Guvva 		vf_rep = netdev_priv(ndev);
5191f233f32SVijaya Mohan Guvva 		memset(vf_rep, 0, sizeof(*vf_rep));
5201f233f32SVijaya Mohan Guvva 
5211f233f32SVijaya Mohan Guvva 		vf_rep->ndev = ndev;
5221f233f32SVijaya Mohan Guvva 		vf_rep->oct = oct;
5231f233f32SVijaya Mohan Guvva 		vf_rep->parent_ndev = oct->props[0].netdev;
5241f233f32SVijaya Mohan Guvva 		vf_rep->ifidx = (oct->pf_num * 64) + i + 1;
5251f233f32SVijaya Mohan Guvva 
5261f233f32SVijaya Mohan Guvva 		eth_hw_addr_random(ndev);
5271f233f32SVijaya Mohan Guvva 
5281f233f32SVijaya Mohan Guvva 		if (register_netdev(ndev)) {
5291f233f32SVijaya Mohan Guvva 			dev_err(&oct->pci_dev->dev, "VF rep nerdev registration failed\n");
5301f233f32SVijaya Mohan Guvva 
5311f233f32SVijaya Mohan Guvva 			free_netdev(ndev);
5321f233f32SVijaya Mohan Guvva 			goto cleanup;
5331f233f32SVijaya Mohan Guvva 		}
5341f233f32SVijaya Mohan Guvva 
5351f233f32SVijaya Mohan Guvva 		netif_carrier_off(ndev);
5361f233f32SVijaya Mohan Guvva 
5371f233f32SVijaya Mohan Guvva 		INIT_DELAYED_WORK(&vf_rep->stats_wk.work,
5381f233f32SVijaya Mohan Guvva 				  lio_vf_rep_fetch_stats);
5391f233f32SVijaya Mohan Guvva 		vf_rep->stats_wk.ctxptr = (void *)vf_rep;
5401f233f32SVijaya Mohan Guvva 		schedule_delayed_work(&vf_rep->stats_wk.work,
5411f233f32SVijaya Mohan Guvva 				      msecs_to_jiffies
5421f233f32SVijaya Mohan Guvva 				      (LIO_VF_REP_STATS_POLL_TIME_MS));
5431f233f32SVijaya Mohan Guvva 		oct->vf_rep_list.num_vfs++;
5441f233f32SVijaya Mohan Guvva 		oct->vf_rep_list.ndev[i] = ndev;
5451f233f32SVijaya Mohan Guvva 	}
5461f233f32SVijaya Mohan Guvva 
5471f233f32SVijaya Mohan Guvva 	if (octeon_register_dispatch_fn(oct, OPCODE_NIC,
5481f233f32SVijaya Mohan Guvva 					OPCODE_NIC_VF_REP_PKT,
5491f233f32SVijaya Mohan Guvva 					lio_vf_rep_pkt_recv, oct)) {
5501f233f32SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev, "VF rep Dispatch func registration failed\n");
5511f233f32SVijaya Mohan Guvva 
5521f233f32SVijaya Mohan Guvva 		goto cleanup;
5531f233f32SVijaya Mohan Guvva 	}
5541f233f32SVijaya Mohan Guvva 
5551f233f32SVijaya Mohan Guvva 	return 0;
5561f233f32SVijaya Mohan Guvva 
5571f233f32SVijaya Mohan Guvva cleanup:
5581f233f32SVijaya Mohan Guvva 	for (i = 0; i < oct->vf_rep_list.num_vfs; i++) {
5591f233f32SVijaya Mohan Guvva 		ndev = oct->vf_rep_list.ndev[i];
5601f233f32SVijaya Mohan Guvva 		oct->vf_rep_list.ndev[i] = NULL;
5611f233f32SVijaya Mohan Guvva 		if (ndev) {
5621f233f32SVijaya Mohan Guvva 			vf_rep = netdev_priv(ndev);
5631f233f32SVijaya Mohan Guvva 			cancel_delayed_work_sync
5641f233f32SVijaya Mohan Guvva 				(&vf_rep->stats_wk.work);
5651f233f32SVijaya Mohan Guvva 			unregister_netdev(ndev);
5661f233f32SVijaya Mohan Guvva 			free_netdev(ndev);
5671f233f32SVijaya Mohan Guvva 		}
5681f233f32SVijaya Mohan Guvva 	}
5691f233f32SVijaya Mohan Guvva 
5701f233f32SVijaya Mohan Guvva 	oct->vf_rep_list.num_vfs = 0;
5711f233f32SVijaya Mohan Guvva 
5721f233f32SVijaya Mohan Guvva 	return -1;
5731f233f32SVijaya Mohan Guvva }
5741f233f32SVijaya Mohan Guvva 
5751f233f32SVijaya Mohan Guvva void
lio_vf_rep_destroy(struct octeon_device * oct)5761f233f32SVijaya Mohan Guvva lio_vf_rep_destroy(struct octeon_device *oct)
5771f233f32SVijaya Mohan Guvva {
5781f233f32SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep;
5791f233f32SVijaya Mohan Guvva 	struct net_device *ndev;
5801f233f32SVijaya Mohan Guvva 	int i;
5811f233f32SVijaya Mohan Guvva 
582d4be8ebeSVijaya Mohan Guvva 	if (oct->eswitch_mode != DEVLINK_ESWITCH_MODE_SWITCHDEV)
583d4be8ebeSVijaya Mohan Guvva 		return;
584d4be8ebeSVijaya Mohan Guvva 
5851f233f32SVijaya Mohan Guvva 	if (!oct->sriov_info.sriov_enabled)
5861f233f32SVijaya Mohan Guvva 		return;
5871f233f32SVijaya Mohan Guvva 
5881f233f32SVijaya Mohan Guvva 	for (i = 0; i < oct->vf_rep_list.num_vfs; i++) {
5891f233f32SVijaya Mohan Guvva 		ndev = oct->vf_rep_list.ndev[i];
5901f233f32SVijaya Mohan Guvva 		oct->vf_rep_list.ndev[i] = NULL;
5911f233f32SVijaya Mohan Guvva 		if (ndev) {
5921f233f32SVijaya Mohan Guvva 			vf_rep = netdev_priv(ndev);
5931f233f32SVijaya Mohan Guvva 			cancel_delayed_work_sync
5941f233f32SVijaya Mohan Guvva 				(&vf_rep->stats_wk.work);
5951f233f32SVijaya Mohan Guvva 			netif_tx_disable(ndev);
5961f233f32SVijaya Mohan Guvva 			netif_carrier_off(ndev);
5971f233f32SVijaya Mohan Guvva 
5981f233f32SVijaya Mohan Guvva 			unregister_netdev(ndev);
5991f233f32SVijaya Mohan Guvva 			free_netdev(ndev);
6001f233f32SVijaya Mohan Guvva 		}
6011f233f32SVijaya Mohan Guvva 	}
6021f233f32SVijaya Mohan Guvva 
6031f233f32SVijaya Mohan Guvva 	oct->vf_rep_list.num_vfs = 0;
6041f233f32SVijaya Mohan Guvva }
605e20f4696SVijaya Mohan Guvva 
606e20f4696SVijaya Mohan Guvva static int
lio_vf_rep_netdev_event(struct notifier_block * nb,unsigned long event,void * ptr)607e20f4696SVijaya Mohan Guvva lio_vf_rep_netdev_event(struct notifier_block *nb,
608e20f4696SVijaya Mohan Guvva 			unsigned long event, void *ptr)
609e20f4696SVijaya Mohan Guvva {
610e20f4696SVijaya Mohan Guvva 	struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
611e20f4696SVijaya Mohan Guvva 	struct lio_vf_rep_desc *vf_rep;
612e20f4696SVijaya Mohan Guvva 	struct lio_vf_rep_req rep_cfg;
613e20f4696SVijaya Mohan Guvva 	struct octeon_device *oct;
614e20f4696SVijaya Mohan Guvva 	int ret;
615e20f4696SVijaya Mohan Guvva 
616e20f4696SVijaya Mohan Guvva 	switch (event) {
617e20f4696SVijaya Mohan Guvva 	case NETDEV_REGISTER:
618e20f4696SVijaya Mohan Guvva 	case NETDEV_CHANGENAME:
619e20f4696SVijaya Mohan Guvva 		break;
620e20f4696SVijaya Mohan Guvva 
621e20f4696SVijaya Mohan Guvva 	default:
622e20f4696SVijaya Mohan Guvva 		return NOTIFY_DONE;
623e20f4696SVijaya Mohan Guvva 	}
624e20f4696SVijaya Mohan Guvva 
625e20f4696SVijaya Mohan Guvva 	if (ndev->netdev_ops != &lio_vf_rep_ndev_ops)
626e20f4696SVijaya Mohan Guvva 		return NOTIFY_DONE;
627e20f4696SVijaya Mohan Guvva 
628e20f4696SVijaya Mohan Guvva 	vf_rep = netdev_priv(ndev);
629e20f4696SVijaya Mohan Guvva 	oct = vf_rep->oct;
630e20f4696SVijaya Mohan Guvva 
631e20f4696SVijaya Mohan Guvva 	if (strlen(ndev->name) > LIO_IF_NAME_SIZE) {
632e20f4696SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev,
633e20f4696SVijaya Mohan Guvva 			"Device name change sync failed as the size is > %d\n",
634e20f4696SVijaya Mohan Guvva 			LIO_IF_NAME_SIZE);
635e20f4696SVijaya Mohan Guvva 		return NOTIFY_DONE;
636e20f4696SVijaya Mohan Guvva 	}
637e20f4696SVijaya Mohan Guvva 
638e20f4696SVijaya Mohan Guvva 	memset(&rep_cfg, 0, sizeof(rep_cfg));
639e20f4696SVijaya Mohan Guvva 	rep_cfg.req_type = LIO_VF_REP_REQ_DEVNAME;
640e20f4696SVijaya Mohan Guvva 	rep_cfg.ifidx = vf_rep->ifidx;
641a1672428SJustin Stitt 	strscpy(rep_cfg.rep_name.name, ndev->name,
642a1672428SJustin Stitt 		sizeof(rep_cfg.rep_name.name));
643e20f4696SVijaya Mohan Guvva 
644e20f4696SVijaya Mohan Guvva 	ret = lio_vf_rep_send_soft_command(oct, &rep_cfg,
645e20f4696SVijaya Mohan Guvva 					   sizeof(rep_cfg), NULL, 0);
646e20f4696SVijaya Mohan Guvva 	if (ret)
647e20f4696SVijaya Mohan Guvva 		dev_err(&oct->pci_dev->dev,
648e20f4696SVijaya Mohan Guvva 			"vf_rep netdev name change failed with err %d\n", ret);
649e20f4696SVijaya Mohan Guvva 
650e20f4696SVijaya Mohan Guvva 	return NOTIFY_DONE;
651e20f4696SVijaya Mohan Guvva }
652e20f4696SVijaya Mohan Guvva 
653e20f4696SVijaya Mohan Guvva static struct notifier_block lio_vf_rep_netdev_notifier = {
654e20f4696SVijaya Mohan Guvva 	.notifier_call = lio_vf_rep_netdev_event,
655e20f4696SVijaya Mohan Guvva };
656e20f4696SVijaya Mohan Guvva 
657e20f4696SVijaya Mohan Guvva int
lio_vf_rep_modinit(void)658e20f4696SVijaya Mohan Guvva lio_vf_rep_modinit(void)
659e20f4696SVijaya Mohan Guvva {
660e20f4696SVijaya Mohan Guvva 	if (register_netdevice_notifier(&lio_vf_rep_netdev_notifier)) {
661e20f4696SVijaya Mohan Guvva 		pr_err("netdev notifier registration failed\n");
662e20f4696SVijaya Mohan Guvva 		return -EFAULT;
663e20f4696SVijaya Mohan Guvva 	}
664e20f4696SVijaya Mohan Guvva 
665e20f4696SVijaya Mohan Guvva 	return 0;
666e20f4696SVijaya Mohan Guvva }
667e20f4696SVijaya Mohan Guvva 
668e20f4696SVijaya Mohan Guvva void
lio_vf_rep_modexit(void)669e20f4696SVijaya Mohan Guvva lio_vf_rep_modexit(void)
670e20f4696SVijaya Mohan Guvva {
671e20f4696SVijaya Mohan Guvva 	if (unregister_netdevice_notifier(&lio_vf_rep_netdev_notifier))
672e20f4696SVijaya Mohan Guvva 		pr_err("netdev notifier unregister failed\n");
673e20f4696SVijaya Mohan Guvva }
674