/********************************************************************** * Author: Cavium, Inc. * * Contact: support@cavium.com * Please include "LiquidIO" in the subject. * * Copyright (c) 2003-2015 Cavium, Inc. * * This file is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License, Version 2, as * published by the Free Software Foundation. * * This file is distributed in the hope that it will be useful, but * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or * NONINFRINGEMENT. See the GNU General Public License for more * details. * * This file may also be available under a different license from Cavium. * Contact Cavium, Inc. for more information **********************************************************************/ #include #include #include "liquidio_common.h" #include "octeon_droq.h" #include "octeon_iq.h" #include "response_manager.h" #include "octeon_device.h" #include "octeon_nic.h" #include "octeon_main.h" #include "octeon_network.h" int liquidio_set_feature(struct net_device *netdev, int cmd, u16 param1) { struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; struct octnic_ctrl_pkt nctrl; int ret = 0; memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); nctrl.ncmd.u64 = 0; nctrl.ncmd.s.cmd = cmd; nctrl.ncmd.s.param1 = param1; nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; nctrl.wait_time = 100; nctrl.netpndev = (u64)netdev; nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); if (ret < 0) { dev_err(&oct->pci_dev->dev, "Feature change failed in core (ret: 0x%x)\n", ret); } return ret; } void octeon_report_tx_completion_to_bql(void *txq, unsigned int pkts_compl, unsigned int bytes_compl) { struct netdev_queue *netdev_queue = txq; netdev_tx_completed_queue(netdev_queue, pkts_compl, bytes_compl); } void octeon_update_tx_completion_counters(void *buf, int reqtype, unsigned int *pkts_compl, unsigned int *bytes_compl) { struct octnet_buf_free_info *finfo; struct sk_buff *skb = NULL; struct octeon_soft_command *sc; switch (reqtype) { case REQTYPE_NORESP_NET: case REQTYPE_NORESP_NET_SG: finfo = buf; skb = finfo->skb; break; case REQTYPE_RESP_NET_SG: case REQTYPE_RESP_NET: sc = buf; skb = sc->callback_arg; break; default: return; } (*pkts_compl)++; /*TODO, Use some other pound define to suggest * the fact that iqs are not tied to netdevs * and can take traffic from different netdevs * hence bql reporting is done per packet * than in bulk. Usage of NO_NAPI in txq completion is * a little confusing */ *bytes_compl += skb->len; } void octeon_report_sent_bytes_to_bql(void *buf, int reqtype) { struct octnet_buf_free_info *finfo; struct sk_buff *skb; struct octeon_soft_command *sc; struct netdev_queue *txq; switch (reqtype) { case REQTYPE_NORESP_NET: case REQTYPE_NORESP_NET_SG: finfo = buf; skb = finfo->skb; break; case REQTYPE_RESP_NET_SG: case REQTYPE_RESP_NET: sc = buf; skb = sc->callback_arg; break; default: return; } txq = netdev_get_tx_queue(skb->dev, skb_get_queue_mapping(skb)); netdev_tx_sent_queue(txq, skb->len); } void liquidio_link_ctrl_cmd_completion(void *nctrl_ptr) { struct octnic_ctrl_pkt *nctrl = (struct octnic_ctrl_pkt *)nctrl_ptr; struct net_device *netdev = (struct net_device *)nctrl->netpndev; struct lio *lio = GET_LIO(netdev); struct octeon_device *oct = lio->oct_dev; u8 *mac; switch (nctrl->ncmd.s.cmd) { case OCTNET_CMD_CHANGE_DEVFLAGS: case OCTNET_CMD_SET_MULTI_LIST: break; case OCTNET_CMD_CHANGE_MACADDR: mac = ((u8 *)&nctrl->udd[0]) + 2; netif_info(lio, probe, lio->netdev, "MACAddr changed to %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); break; case OCTNET_CMD_CHANGE_MTU: /* If command is successful, change the MTU. */ netif_info(lio, probe, lio->netdev, "MTU Changed from %d to %d\n", netdev->mtu, nctrl->ncmd.s.param1); dev_info(&oct->pci_dev->dev, "%s MTU Changed from %d to %d\n", netdev->name, netdev->mtu, nctrl->ncmd.s.param1); netdev->mtu = nctrl->ncmd.s.param1; queue_delayed_work(lio->link_status_wq.wq, &lio->link_status_wq.wk.work, 0); break; case OCTNET_CMD_GPIO_ACCESS: netif_info(lio, probe, lio->netdev, "LED Flashing visual identification\n"); break; case OCTNET_CMD_ID_ACTIVE: netif_info(lio, probe, lio->netdev, "LED Flashing visual identification\n"); break; case OCTNET_CMD_LRO_ENABLE: dev_info(&oct->pci_dev->dev, "%s LRO Enabled\n", netdev->name); break; case OCTNET_CMD_LRO_DISABLE: dev_info(&oct->pci_dev->dev, "%s LRO Disabled\n", netdev->name); break; case OCTNET_CMD_VERBOSE_ENABLE: dev_info(&oct->pci_dev->dev, "%s Firmware debug enabled\n", netdev->name); break; case OCTNET_CMD_VERBOSE_DISABLE: dev_info(&oct->pci_dev->dev, "%s Firmware debug disabled\n", netdev->name); break; case OCTNET_CMD_ENABLE_VLAN_FILTER: dev_info(&oct->pci_dev->dev, "%s VLAN filter enabled\n", netdev->name); break; case OCTNET_CMD_ADD_VLAN_FILTER: dev_info(&oct->pci_dev->dev, "%s VLAN filter %d added\n", netdev->name, nctrl->ncmd.s.param1); break; case OCTNET_CMD_DEL_VLAN_FILTER: dev_info(&oct->pci_dev->dev, "%s VLAN filter %d removed\n", netdev->name, nctrl->ncmd.s.param1); break; case OCTNET_CMD_SET_SETTINGS: dev_info(&oct->pci_dev->dev, "%s settings changed\n", netdev->name); break; /* Case to handle "OCTNET_CMD_TNL_RX_CSUM_CTL" * Command passed by NIC driver */ case OCTNET_CMD_TNL_RX_CSUM_CTL: if (nctrl->ncmd.s.param1 == OCTNET_CMD_RXCSUM_ENABLE) { netif_info(lio, probe, lio->netdev, "RX Checksum Offload Enabled\n"); } else if (nctrl->ncmd.s.param1 == OCTNET_CMD_RXCSUM_DISABLE) { netif_info(lio, probe, lio->netdev, "RX Checksum Offload Disabled\n"); } break; /* Case to handle "OCTNET_CMD_TNL_TX_CSUM_CTL" * Command passed by NIC driver */ case OCTNET_CMD_TNL_TX_CSUM_CTL: if (nctrl->ncmd.s.param1 == OCTNET_CMD_TXCSUM_ENABLE) { netif_info(lio, probe, lio->netdev, "TX Checksum Offload Enabled\n"); } else if (nctrl->ncmd.s.param1 == OCTNET_CMD_TXCSUM_DISABLE) { netif_info(lio, probe, lio->netdev, "TX Checksum Offload Disabled\n"); } break; /* Case to handle "OCTNET_CMD_VXLAN_PORT_CONFIG" * Command passed by NIC driver */ case OCTNET_CMD_VXLAN_PORT_CONFIG: if (nctrl->ncmd.s.more == OCTNET_CMD_VXLAN_PORT_ADD) { netif_info(lio, probe, lio->netdev, "VxLAN Destination UDP PORT:%d ADDED\n", nctrl->ncmd.s.param1); } else if (nctrl->ncmd.s.more == OCTNET_CMD_VXLAN_PORT_DEL) { netif_info(lio, probe, lio->netdev, "VxLAN Destination UDP PORT:%d DELETED\n", nctrl->ncmd.s.param1); } break; case OCTNET_CMD_SET_FLOW_CTL: netif_info(lio, probe, lio->netdev, "Set RX/TX flow control parameters\n"); break; default: dev_err(&oct->pci_dev->dev, "%s Unknown cmd %d\n", __func__, nctrl->ncmd.s.cmd); } } void octeon_pf_changed_vf_macaddr(struct octeon_device *oct, u8 *mac) { bool macaddr_changed = false; struct net_device *netdev; struct lio *lio; rtnl_lock(); netdev = oct->props[0].netdev; lio = GET_LIO(netdev); lio->linfo.macaddr_is_admin_asgnd = true; if (!ether_addr_equal(netdev->dev_addr, mac)) { macaddr_changed = true; ether_addr_copy(netdev->dev_addr, mac); ether_addr_copy(((u8 *)&lio->linfo.hw_addr) + 2, mac); call_netdevice_notifiers(NETDEV_CHANGEADDR, netdev); } rtnl_unlock(); if (macaddr_changed) dev_info(&oct->pci_dev->dev, "PF changed VF's MAC address to %pM\n", mac); /* no need to notify the firmware of the macaddr change because * the PF did that already */ }