1111fc64aSRaghu Vatsavayi /********************************************************************** 2111fc64aSRaghu Vatsavayi * Author: Cavium, Inc. 3111fc64aSRaghu Vatsavayi * 4111fc64aSRaghu Vatsavayi * Contact: support@cavium.com 5111fc64aSRaghu Vatsavayi * Please include "LiquidIO" in the subject. 6111fc64aSRaghu Vatsavayi * 7111fc64aSRaghu Vatsavayi * Copyright (c) 2003-2016 Cavium, Inc. 8111fc64aSRaghu Vatsavayi * 9111fc64aSRaghu Vatsavayi * This file is free software; you can redistribute it and/or modify 10111fc64aSRaghu Vatsavayi * it under the terms of the GNU General Public License, Version 2, as 11111fc64aSRaghu Vatsavayi * published by the Free Software Foundation. 12111fc64aSRaghu Vatsavayi * 13111fc64aSRaghu Vatsavayi * This file is distributed in the hope that it will be useful, but 14111fc64aSRaghu Vatsavayi * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty 15111fc64aSRaghu Vatsavayi * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or 16111fc64aSRaghu Vatsavayi * NONINFRINGEMENT. See the GNU General Public License for more details. 17111fc64aSRaghu Vatsavayi ***********************************************************************/ 18e3bfc6e7SRussell King #include <linux/module.h> 19282ccf6eSFlorian Westphal #include <linux/interrupt.h> 20111fc64aSRaghu Vatsavayi #include <linux/pci.h> 21111fc64aSRaghu Vatsavayi #include <net/vxlan.h> 22111fc64aSRaghu Vatsavayi #include "liquidio_common.h" 23111fc64aSRaghu Vatsavayi #include "octeon_droq.h" 24111fc64aSRaghu Vatsavayi #include "octeon_iq.h" 25111fc64aSRaghu Vatsavayi #include "response_manager.h" 26111fc64aSRaghu Vatsavayi #include "octeon_device.h" 27846b4687SRaghu Vatsavayi #include "octeon_nic.h" 2869c69da3SRaghu Vatsavayi #include "octeon_main.h" 29846b4687SRaghu Vatsavayi #include "octeon_network.h" 3069c69da3SRaghu Vatsavayi #include "cn23xx_vf_device.h" 31111fc64aSRaghu Vatsavayi 32111fc64aSRaghu Vatsavayi MODULE_AUTHOR("Cavium Networks, <support@cavium.com>"); 33111fc64aSRaghu Vatsavayi MODULE_DESCRIPTION("Cavium LiquidIO Intelligent Server Adapter Virtual Function Driver"); 34111fc64aSRaghu Vatsavayi MODULE_LICENSE("GPL"); 35111fc64aSRaghu Vatsavayi MODULE_VERSION(LIQUIDIO_VERSION); 36111fc64aSRaghu Vatsavayi 37846b4687SRaghu Vatsavayi static int debug = -1; 38846b4687SRaghu Vatsavayi module_param(debug, int, 0644); 39846b4687SRaghu Vatsavayi MODULE_PARM_DESC(debug, "NETIF_MSG debug bits"); 40846b4687SRaghu Vatsavayi 41846b4687SRaghu Vatsavayi #define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_LINK) 42846b4687SRaghu Vatsavayi 43f625fe62SRaghu Vatsavayi struct oct_timestamp_resp { 44f625fe62SRaghu Vatsavayi u64 rh; 45f625fe62SRaghu Vatsavayi u64 timestamp; 46f625fe62SRaghu Vatsavayi u64 status; 47f625fe62SRaghu Vatsavayi }; 48f625fe62SRaghu Vatsavayi 499981328aSRaghu Vatsavayi union tx_info { 509981328aSRaghu Vatsavayi u64 u64; 519981328aSRaghu Vatsavayi struct { 529981328aSRaghu Vatsavayi #ifdef __BIG_ENDIAN_BITFIELD 539981328aSRaghu Vatsavayi u16 gso_size; 549981328aSRaghu Vatsavayi u16 gso_segs; 559981328aSRaghu Vatsavayi u32 reserved; 569981328aSRaghu Vatsavayi #else 579981328aSRaghu Vatsavayi u32 reserved; 589981328aSRaghu Vatsavayi u16 gso_segs; 599981328aSRaghu Vatsavayi u16 gso_size; 609981328aSRaghu Vatsavayi #endif 619981328aSRaghu Vatsavayi } s; 629981328aSRaghu Vatsavayi }; 639981328aSRaghu Vatsavayi 64846b4687SRaghu Vatsavayi #define OCTNIC_GSO_MAX_HEADER_SIZE 128 65846b4687SRaghu Vatsavayi #define OCTNIC_GSO_MAX_SIZE \ 66846b4687SRaghu Vatsavayi (CN23XX_DEFAULT_INPUT_JABBER - OCTNIC_GSO_MAX_HEADER_SIZE) 67846b4687SRaghu Vatsavayi 68111fc64aSRaghu Vatsavayi static int 69111fc64aSRaghu Vatsavayi liquidio_vf_probe(struct pci_dev *pdev, const struct pci_device_id *ent); 70111fc64aSRaghu Vatsavayi static void liquidio_vf_remove(struct pci_dev *pdev); 7169c69da3SRaghu Vatsavayi static int octeon_device_init(struct octeon_device *oct); 72846b4687SRaghu Vatsavayi static int liquidio_stop(struct net_device *netdev); 73111fc64aSRaghu Vatsavayi 74b3c35973SRaghu Vatsavayi static int lio_wait_for_oq_pkts(struct octeon_device *oct) 75b3c35973SRaghu Vatsavayi { 76b3c35973SRaghu Vatsavayi struct octeon_device_priv *oct_priv = 77b3c35973SRaghu Vatsavayi (struct octeon_device_priv *)oct->priv; 78e65a8ccbSIntiyaz Basha int retry = MAX_IO_PENDING_PKT_COUNT; 79b3c35973SRaghu Vatsavayi int pkt_cnt = 0, pending_pkts; 80b3c35973SRaghu Vatsavayi int i; 81b3c35973SRaghu Vatsavayi 82b3c35973SRaghu Vatsavayi do { 83b3c35973SRaghu Vatsavayi pending_pkts = 0; 84b3c35973SRaghu Vatsavayi 85b3c35973SRaghu Vatsavayi for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) { 86b3c35973SRaghu Vatsavayi if (!(oct->io_qmask.oq & BIT_ULL(i))) 87b3c35973SRaghu Vatsavayi continue; 88b3c35973SRaghu Vatsavayi pkt_cnt += octeon_droq_check_hw_for_pkts(oct->droq[i]); 89b3c35973SRaghu Vatsavayi } 90b3c35973SRaghu Vatsavayi if (pkt_cnt > 0) { 91b3c35973SRaghu Vatsavayi pending_pkts += pkt_cnt; 92b3c35973SRaghu Vatsavayi tasklet_schedule(&oct_priv->droq_tasklet); 93b3c35973SRaghu Vatsavayi } 94b3c35973SRaghu Vatsavayi pkt_cnt = 0; 95b3c35973SRaghu Vatsavayi schedule_timeout_uninterruptible(1); 96b3c35973SRaghu Vatsavayi 97b3c35973SRaghu Vatsavayi } while (retry-- && pending_pkts); 98b3c35973SRaghu Vatsavayi 99b3c35973SRaghu Vatsavayi return pkt_cnt; 100b3c35973SRaghu Vatsavayi } 101b3c35973SRaghu Vatsavayi 102b3c35973SRaghu Vatsavayi /** 103b0d66369SRaghu Vatsavayi * \brief Cause device to go quiet so it can be safely removed/reset/etc 104b0d66369SRaghu Vatsavayi * @param oct Pointer to Octeon device 105b0d66369SRaghu Vatsavayi */ 106b0d66369SRaghu Vatsavayi static void pcierror_quiesce_device(struct octeon_device *oct) 107b0d66369SRaghu Vatsavayi { 108b0d66369SRaghu Vatsavayi int i; 109b0d66369SRaghu Vatsavayi 110b0d66369SRaghu Vatsavayi /* Disable the input and output queues now. No more packets will 111b0d66369SRaghu Vatsavayi * arrive from Octeon, but we should wait for all packet processing 112b0d66369SRaghu Vatsavayi * to finish. 113b0d66369SRaghu Vatsavayi */ 114b0d66369SRaghu Vatsavayi 115b0d66369SRaghu Vatsavayi /* To allow for in-flight requests */ 116b0d66369SRaghu Vatsavayi schedule_timeout_uninterruptible(100); 117b0d66369SRaghu Vatsavayi 118b0d66369SRaghu Vatsavayi if (wait_for_pending_requests(oct)) 119b0d66369SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "There were pending requests\n"); 120b0d66369SRaghu Vatsavayi 121b0d66369SRaghu Vatsavayi /* Force all requests waiting to be fetched by OCTEON to complete. */ 122b0d66369SRaghu Vatsavayi for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) { 123b0d66369SRaghu Vatsavayi struct octeon_instr_queue *iq; 124b0d66369SRaghu Vatsavayi 125b0d66369SRaghu Vatsavayi if (!(oct->io_qmask.iq & BIT_ULL(i))) 126b0d66369SRaghu Vatsavayi continue; 127b0d66369SRaghu Vatsavayi iq = oct->instr_queue[i]; 128b0d66369SRaghu Vatsavayi 129b0d66369SRaghu Vatsavayi if (atomic_read(&iq->instr_pending)) { 130b0d66369SRaghu Vatsavayi spin_lock_bh(&iq->lock); 131b0d66369SRaghu Vatsavayi iq->fill_cnt = 0; 132b0d66369SRaghu Vatsavayi iq->octeon_read_index = iq->host_write_index; 133b0d66369SRaghu Vatsavayi iq->stats.instr_processed += 134b0d66369SRaghu Vatsavayi atomic_read(&iq->instr_pending); 135b0d66369SRaghu Vatsavayi lio_process_iq_request_list(oct, iq, 0); 136b0d66369SRaghu Vatsavayi spin_unlock_bh(&iq->lock); 137b0d66369SRaghu Vatsavayi } 138b0d66369SRaghu Vatsavayi } 139b0d66369SRaghu Vatsavayi 140b0d66369SRaghu Vatsavayi /* Force all pending ordered list requests to time out. */ 141b0d66369SRaghu Vatsavayi lio_process_ordered_list(oct, 1); 142b0d66369SRaghu Vatsavayi 143b0d66369SRaghu Vatsavayi /* We do not need to wait for output queue packets to be processed. */ 144b0d66369SRaghu Vatsavayi } 145b0d66369SRaghu Vatsavayi 146b0d66369SRaghu Vatsavayi /** 147b0d66369SRaghu Vatsavayi * \brief Cleanup PCI AER uncorrectable error status 148b0d66369SRaghu Vatsavayi * @param dev Pointer to PCI device 149b0d66369SRaghu Vatsavayi */ 150b0d66369SRaghu Vatsavayi static void cleanup_aer_uncorrect_error_status(struct pci_dev *dev) 151b0d66369SRaghu Vatsavayi { 152b0d66369SRaghu Vatsavayi u32 status, mask; 153b0d66369SRaghu Vatsavayi int pos = 0x100; 154b0d66369SRaghu Vatsavayi 155b0d66369SRaghu Vatsavayi pr_info("%s :\n", __func__); 156b0d66369SRaghu Vatsavayi 157b0d66369SRaghu Vatsavayi pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, &status); 158b0d66369SRaghu Vatsavayi pci_read_config_dword(dev, pos + PCI_ERR_UNCOR_SEVER, &mask); 159b0d66369SRaghu Vatsavayi if (dev->error_state == pci_channel_io_normal) 160b0d66369SRaghu Vatsavayi status &= ~mask; /* Clear corresponding nonfatal bits */ 161b0d66369SRaghu Vatsavayi else 162b0d66369SRaghu Vatsavayi status &= mask; /* Clear corresponding fatal bits */ 163b0d66369SRaghu Vatsavayi pci_write_config_dword(dev, pos + PCI_ERR_UNCOR_STATUS, status); 164b0d66369SRaghu Vatsavayi } 165b0d66369SRaghu Vatsavayi 166b0d66369SRaghu Vatsavayi /** 167b0d66369SRaghu Vatsavayi * \brief Stop all PCI IO to a given device 168b0d66369SRaghu Vatsavayi * @param dev Pointer to Octeon device 169b0d66369SRaghu Vatsavayi */ 170b0d66369SRaghu Vatsavayi static void stop_pci_io(struct octeon_device *oct) 171b0d66369SRaghu Vatsavayi { 172b0d66369SRaghu Vatsavayi struct msix_entry *msix_entries; 173b0d66369SRaghu Vatsavayi int i; 174b0d66369SRaghu Vatsavayi 175b0d66369SRaghu Vatsavayi /* No more instructions will be forwarded. */ 176b0d66369SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_IN_RESET); 177b0d66369SRaghu Vatsavayi 178b0d66369SRaghu Vatsavayi for (i = 0; i < oct->ifcount; i++) 179b0d66369SRaghu Vatsavayi netif_device_detach(oct->props[i].netdev); 180b0d66369SRaghu Vatsavayi 181b0d66369SRaghu Vatsavayi /* Disable interrupts */ 182b0d66369SRaghu Vatsavayi oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); 183b0d66369SRaghu Vatsavayi 184b0d66369SRaghu Vatsavayi pcierror_quiesce_device(oct); 185b0d66369SRaghu Vatsavayi if (oct->msix_on) { 186b0d66369SRaghu Vatsavayi msix_entries = (struct msix_entry *)oct->msix_entries; 187b0d66369SRaghu Vatsavayi for (i = 0; i < oct->num_msix_irqs; i++) { 188b0d66369SRaghu Vatsavayi /* clear the affinity_cpumask */ 189b0d66369SRaghu Vatsavayi irq_set_affinity_hint(msix_entries[i].vector, 190b0d66369SRaghu Vatsavayi NULL); 191b0d66369SRaghu Vatsavayi free_irq(msix_entries[i].vector, 192b0d66369SRaghu Vatsavayi &oct->ioq_vector[i]); 193b0d66369SRaghu Vatsavayi } 194b0d66369SRaghu Vatsavayi pci_disable_msix(oct->pci_dev); 195b0d66369SRaghu Vatsavayi kfree(oct->msix_entries); 196b0d66369SRaghu Vatsavayi oct->msix_entries = NULL; 197b0d66369SRaghu Vatsavayi octeon_free_ioq_vector(oct); 198b0d66369SRaghu Vatsavayi } 199b0d66369SRaghu Vatsavayi dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n", 200b0d66369SRaghu Vatsavayi lio_get_state_string(&oct->status)); 201b0d66369SRaghu Vatsavayi 202b0d66369SRaghu Vatsavayi /* making it a common function for all OCTEON models */ 203b0d66369SRaghu Vatsavayi cleanup_aer_uncorrect_error_status(oct->pci_dev); 204b0d66369SRaghu Vatsavayi 205b0d66369SRaghu Vatsavayi pci_disable_device(oct->pci_dev); 206b0d66369SRaghu Vatsavayi } 207b0d66369SRaghu Vatsavayi 208b0d66369SRaghu Vatsavayi /** 209b0d66369SRaghu Vatsavayi * \brief called when PCI error is detected 210b0d66369SRaghu Vatsavayi * @param pdev Pointer to PCI device 211b0d66369SRaghu Vatsavayi * @param state The current pci connection state 212b0d66369SRaghu Vatsavayi * 213b0d66369SRaghu Vatsavayi * This function is called after a PCI bus error affecting 214b0d66369SRaghu Vatsavayi * this device has been detected. 215b0d66369SRaghu Vatsavayi */ 216b0d66369SRaghu Vatsavayi static pci_ers_result_t liquidio_pcie_error_detected(struct pci_dev *pdev, 217b0d66369SRaghu Vatsavayi pci_channel_state_t state) 218b0d66369SRaghu Vatsavayi { 219b0d66369SRaghu Vatsavayi struct octeon_device *oct = pci_get_drvdata(pdev); 220b0d66369SRaghu Vatsavayi 221b0d66369SRaghu Vatsavayi /* Non-correctable Non-fatal errors */ 222b0d66369SRaghu Vatsavayi if (state == pci_channel_io_normal) { 223b0d66369SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Non-correctable non-fatal error reported:\n"); 224b0d66369SRaghu Vatsavayi cleanup_aer_uncorrect_error_status(oct->pci_dev); 225b0d66369SRaghu Vatsavayi return PCI_ERS_RESULT_CAN_RECOVER; 226b0d66369SRaghu Vatsavayi } 227b0d66369SRaghu Vatsavayi 228b0d66369SRaghu Vatsavayi /* Non-correctable Fatal errors */ 229b0d66369SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Non-correctable FATAL reported by PCI AER driver\n"); 230b0d66369SRaghu Vatsavayi stop_pci_io(oct); 231b0d66369SRaghu Vatsavayi 232b0d66369SRaghu Vatsavayi return PCI_ERS_RESULT_DISCONNECT; 233b0d66369SRaghu Vatsavayi } 234b0d66369SRaghu Vatsavayi 235b0d66369SRaghu Vatsavayi /* For PCI-E Advanced Error Recovery (AER) Interface */ 236b0d66369SRaghu Vatsavayi static const struct pci_error_handlers liquidio_vf_err_handler = { 237b0d66369SRaghu Vatsavayi .error_detected = liquidio_pcie_error_detected, 238b0d66369SRaghu Vatsavayi }; 239b0d66369SRaghu Vatsavayi 240111fc64aSRaghu Vatsavayi static const struct pci_device_id liquidio_vf_pci_tbl[] = { 241111fc64aSRaghu Vatsavayi { 242111fc64aSRaghu Vatsavayi PCI_VENDOR_ID_CAVIUM, OCTEON_CN23XX_VF_VID, 243111fc64aSRaghu Vatsavayi PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 244111fc64aSRaghu Vatsavayi }, 245111fc64aSRaghu Vatsavayi { 246111fc64aSRaghu Vatsavayi 0, 0, 0, 0, 0, 0, 0 247111fc64aSRaghu Vatsavayi } 248111fc64aSRaghu Vatsavayi }; 249111fc64aSRaghu Vatsavayi MODULE_DEVICE_TABLE(pci, liquidio_vf_pci_tbl); 250111fc64aSRaghu Vatsavayi 251111fc64aSRaghu Vatsavayi static struct pci_driver liquidio_vf_pci_driver = { 252111fc64aSRaghu Vatsavayi .name = "LiquidIO_VF", 253111fc64aSRaghu Vatsavayi .id_table = liquidio_vf_pci_tbl, 254111fc64aSRaghu Vatsavayi .probe = liquidio_vf_probe, 255111fc64aSRaghu Vatsavayi .remove = liquidio_vf_remove, 256b0d66369SRaghu Vatsavayi .err_handler = &liquidio_vf_err_handler, /* For AER */ 257111fc64aSRaghu Vatsavayi }; 258111fc64aSRaghu Vatsavayi 259846b4687SRaghu Vatsavayi /** 2603cd25e48SRaghu Vatsavayi * \brief Print link information 2613cd25e48SRaghu Vatsavayi * @param netdev network device 2623cd25e48SRaghu Vatsavayi */ 2633cd25e48SRaghu Vatsavayi static void print_link_info(struct net_device *netdev) 2643cd25e48SRaghu Vatsavayi { 2653cd25e48SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 2663cd25e48SRaghu Vatsavayi 267d18ca7dfSIntiyaz Basha if (!ifstate_check(lio, LIO_IFSTATE_RESETTING) && 268d18ca7dfSIntiyaz Basha ifstate_check(lio, LIO_IFSTATE_REGISTERED)) { 2693cd25e48SRaghu Vatsavayi struct oct_link_info *linfo = &lio->linfo; 2703cd25e48SRaghu Vatsavayi 2713cd25e48SRaghu Vatsavayi if (linfo->link.s.link_up) { 2723cd25e48SRaghu Vatsavayi netif_info(lio, link, lio->netdev, "%d Mbps %s Duplex UP\n", 2733cd25e48SRaghu Vatsavayi linfo->link.s.speed, 2743cd25e48SRaghu Vatsavayi (linfo->link.s.duplex) ? "Full" : "Half"); 2753cd25e48SRaghu Vatsavayi } else { 2763cd25e48SRaghu Vatsavayi netif_info(lio, link, lio->netdev, "Link Down\n"); 2773cd25e48SRaghu Vatsavayi } 2783cd25e48SRaghu Vatsavayi } 2793cd25e48SRaghu Vatsavayi } 2803cd25e48SRaghu Vatsavayi 2813cd25e48SRaghu Vatsavayi /** 2823cd25e48SRaghu Vatsavayi * \brief Routine to notify MTU change 2833cd25e48SRaghu Vatsavayi * @param work work_struct data structure 2843cd25e48SRaghu Vatsavayi */ 2853cd25e48SRaghu Vatsavayi static void octnet_link_status_change(struct work_struct *work) 2863cd25e48SRaghu Vatsavayi { 2873cd25e48SRaghu Vatsavayi struct cavium_wk *wk = (struct cavium_wk *)work; 2883cd25e48SRaghu Vatsavayi struct lio *lio = (struct lio *)wk->ctxptr; 2893cd25e48SRaghu Vatsavayi 29087a7c4b3SVeerasenareddy Burru /* lio->linfo.link.s.mtu always contains max MTU of the lio interface. 29187a7c4b3SVeerasenareddy Burru * this API is invoked only when new max-MTU of the interface is 29287a7c4b3SVeerasenareddy Burru * less than current MTU. 29387a7c4b3SVeerasenareddy Burru */ 2943cd25e48SRaghu Vatsavayi rtnl_lock(); 29587a7c4b3SVeerasenareddy Burru dev_set_mtu(lio->netdev, lio->linfo.link.s.mtu); 2963cd25e48SRaghu Vatsavayi rtnl_unlock(); 2973cd25e48SRaghu Vatsavayi } 2983cd25e48SRaghu Vatsavayi 2993cd25e48SRaghu Vatsavayi /** 3003cd25e48SRaghu Vatsavayi * \brief Sets up the mtu status change work 3013cd25e48SRaghu Vatsavayi * @param netdev network device 3023cd25e48SRaghu Vatsavayi */ 3033cd25e48SRaghu Vatsavayi static int setup_link_status_change_wq(struct net_device *netdev) 3043cd25e48SRaghu Vatsavayi { 3053cd25e48SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 3063cd25e48SRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 3073cd25e48SRaghu Vatsavayi 3083cd25e48SRaghu Vatsavayi lio->link_status_wq.wq = alloc_workqueue("link-status", 3093cd25e48SRaghu Vatsavayi WQ_MEM_RECLAIM, 0); 3103cd25e48SRaghu Vatsavayi if (!lio->link_status_wq.wq) { 3113cd25e48SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "unable to create cavium link status wq\n"); 3123cd25e48SRaghu Vatsavayi return -1; 3133cd25e48SRaghu Vatsavayi } 3143cd25e48SRaghu Vatsavayi INIT_DELAYED_WORK(&lio->link_status_wq.wk.work, 3153cd25e48SRaghu Vatsavayi octnet_link_status_change); 3163cd25e48SRaghu Vatsavayi lio->link_status_wq.wk.ctxptr = lio; 3173cd25e48SRaghu Vatsavayi 3183cd25e48SRaghu Vatsavayi return 0; 3193cd25e48SRaghu Vatsavayi } 3203cd25e48SRaghu Vatsavayi 3213cd25e48SRaghu Vatsavayi static void cleanup_link_status_change_wq(struct net_device *netdev) 3223cd25e48SRaghu Vatsavayi { 3233cd25e48SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 3243cd25e48SRaghu Vatsavayi 3253cd25e48SRaghu Vatsavayi if (lio->link_status_wq.wq) { 3263cd25e48SRaghu Vatsavayi cancel_delayed_work_sync(&lio->link_status_wq.wk.work); 3273cd25e48SRaghu Vatsavayi destroy_workqueue(lio->link_status_wq.wq); 3283cd25e48SRaghu Vatsavayi } 3293cd25e48SRaghu Vatsavayi } 3303cd25e48SRaghu Vatsavayi 3313cd25e48SRaghu Vatsavayi /** 3323cd25e48SRaghu Vatsavayi * \brief Update link status 3333cd25e48SRaghu Vatsavayi * @param netdev network device 3343cd25e48SRaghu Vatsavayi * @param ls link status structure 3353cd25e48SRaghu Vatsavayi * 3363cd25e48SRaghu Vatsavayi * Called on receipt of a link status response from the core application to 3373cd25e48SRaghu Vatsavayi * update each interface's link status. 3383cd25e48SRaghu Vatsavayi */ 3393cd25e48SRaghu Vatsavayi static void update_link_status(struct net_device *netdev, 3403cd25e48SRaghu Vatsavayi union oct_link_status *ls) 3413cd25e48SRaghu Vatsavayi { 3423cd25e48SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 34387a7c4b3SVeerasenareddy Burru int current_max_mtu = lio->linfo.link.s.mtu; 3443cd25e48SRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 3453cd25e48SRaghu Vatsavayi 3463cd25e48SRaghu Vatsavayi if ((lio->intf_open) && (lio->linfo.link.u64 != ls->u64)) { 3473cd25e48SRaghu Vatsavayi lio->linfo.link.u64 = ls->u64; 3483cd25e48SRaghu Vatsavayi 3493cd25e48SRaghu Vatsavayi print_link_info(netdev); 3503cd25e48SRaghu Vatsavayi lio->link_changes++; 3513cd25e48SRaghu Vatsavayi 3523cd25e48SRaghu Vatsavayi if (lio->linfo.link.s.link_up) { 3533cd25e48SRaghu Vatsavayi netif_carrier_on(netdev); 354a96d8ad3SIntiyaz Basha wake_txqs(netdev); 3553cd25e48SRaghu Vatsavayi } else { 3563cd25e48SRaghu Vatsavayi netif_carrier_off(netdev); 357736b7ea5SIntiyaz Basha stop_txqs(netdev); 3583cd25e48SRaghu Vatsavayi } 3593cd25e48SRaghu Vatsavayi 36087a7c4b3SVeerasenareddy Burru if (lio->linfo.link.s.mtu != current_max_mtu) { 36187a7c4b3SVeerasenareddy Burru dev_info(&oct->pci_dev->dev, 36287a7c4b3SVeerasenareddy Burru "Max MTU Changed from %d to %d\n", 36387a7c4b3SVeerasenareddy Burru current_max_mtu, lio->linfo.link.s.mtu); 364251564f6SVeerasenareddy Burru netdev->max_mtu = lio->linfo.link.s.mtu; 365251564f6SVeerasenareddy Burru } 366251564f6SVeerasenareddy Burru 3673cd25e48SRaghu Vatsavayi if (lio->linfo.link.s.mtu < netdev->mtu) { 3683cd25e48SRaghu Vatsavayi dev_warn(&oct->pci_dev->dev, 36987a7c4b3SVeerasenareddy Burru "Current MTU is higher than new max MTU; Reducing the current mtu from %d to %d\n", 3703cd25e48SRaghu Vatsavayi netdev->mtu, lio->linfo.link.s.mtu); 3713cd25e48SRaghu Vatsavayi queue_delayed_work(lio->link_status_wq.wq, 3723cd25e48SRaghu Vatsavayi &lio->link_status_wq.wk.work, 0); 3733cd25e48SRaghu Vatsavayi } 3743cd25e48SRaghu Vatsavayi } 3753cd25e48SRaghu Vatsavayi } 3763cd25e48SRaghu Vatsavayi 377cf39faf5SRaghu Vatsavayi /** 378111fc64aSRaghu Vatsavayi * \brief PCI probe handler 379111fc64aSRaghu Vatsavayi * @param pdev PCI device structure 380111fc64aSRaghu Vatsavayi * @param ent unused 381111fc64aSRaghu Vatsavayi */ 382111fc64aSRaghu Vatsavayi static int 383111fc64aSRaghu Vatsavayi liquidio_vf_probe(struct pci_dev *pdev, 384111fc64aSRaghu Vatsavayi const struct pci_device_id *ent __attribute__((unused))) 385111fc64aSRaghu Vatsavayi { 386111fc64aSRaghu Vatsavayi struct octeon_device *oct_dev = NULL; 387111fc64aSRaghu Vatsavayi 388111fc64aSRaghu Vatsavayi oct_dev = octeon_allocate_device(pdev->device, 389111fc64aSRaghu Vatsavayi sizeof(struct octeon_device_priv)); 390111fc64aSRaghu Vatsavayi 391111fc64aSRaghu Vatsavayi if (!oct_dev) { 392111fc64aSRaghu Vatsavayi dev_err(&pdev->dev, "Unable to allocate device\n"); 393111fc64aSRaghu Vatsavayi return -ENOMEM; 394111fc64aSRaghu Vatsavayi } 395cf39faf5SRaghu Vatsavayi oct_dev->msix_on = LIO_FLAG_MSIX_ENABLED; 396111fc64aSRaghu Vatsavayi 397111fc64aSRaghu Vatsavayi dev_info(&pdev->dev, "Initializing device %x:%x.\n", 398111fc64aSRaghu Vatsavayi (u32)pdev->vendor, (u32)pdev->device); 399111fc64aSRaghu Vatsavayi 400111fc64aSRaghu Vatsavayi /* Assign octeon_device for this device to the private data area. */ 401111fc64aSRaghu Vatsavayi pci_set_drvdata(pdev, oct_dev); 402111fc64aSRaghu Vatsavayi 403111fc64aSRaghu Vatsavayi /* set linux specific device pointer */ 404111fc64aSRaghu Vatsavayi oct_dev->pci_dev = pdev; 405111fc64aSRaghu Vatsavayi 40618b338f5SWeilin Chang oct_dev->subsystem_id = pdev->subsystem_vendor | 40718b338f5SWeilin Chang (pdev->subsystem_device << 16); 40818b338f5SWeilin Chang 40969c69da3SRaghu Vatsavayi if (octeon_device_init(oct_dev)) { 41069c69da3SRaghu Vatsavayi liquidio_vf_remove(pdev); 41169c69da3SRaghu Vatsavayi return -ENOMEM; 41269c69da3SRaghu Vatsavayi } 41369c69da3SRaghu Vatsavayi 41469c69da3SRaghu Vatsavayi dev_dbg(&oct_dev->pci_dev->dev, "Device is ready\n"); 41569c69da3SRaghu Vatsavayi 416111fc64aSRaghu Vatsavayi return 0; 417111fc64aSRaghu Vatsavayi } 418111fc64aSRaghu Vatsavayi 419111fc64aSRaghu Vatsavayi /** 42069c69da3SRaghu Vatsavayi * \brief PCI FLR for each Octeon device. 42169c69da3SRaghu Vatsavayi * @param oct octeon device 42269c69da3SRaghu Vatsavayi */ 42369c69da3SRaghu Vatsavayi static void octeon_pci_flr(struct octeon_device *oct) 42469c69da3SRaghu Vatsavayi { 42569c69da3SRaghu Vatsavayi pci_save_state(oct->pci_dev); 42669c69da3SRaghu Vatsavayi 42769c69da3SRaghu Vatsavayi pci_cfg_access_lock(oct->pci_dev); 42869c69da3SRaghu Vatsavayi 42969c69da3SRaghu Vatsavayi /* Quiesce the device completely */ 43069c69da3SRaghu Vatsavayi pci_write_config_word(oct->pci_dev, PCI_COMMAND, 43169c69da3SRaghu Vatsavayi PCI_COMMAND_INTX_DISABLE); 43269c69da3SRaghu Vatsavayi 4339ad09803SChristoph Hellwig pcie_flr(oct->pci_dev); 43469c69da3SRaghu Vatsavayi 43569c69da3SRaghu Vatsavayi pci_cfg_access_unlock(oct->pci_dev); 43669c69da3SRaghu Vatsavayi 43769c69da3SRaghu Vatsavayi pci_restore_state(oct->pci_dev); 43869c69da3SRaghu Vatsavayi } 43969c69da3SRaghu Vatsavayi 44069c69da3SRaghu Vatsavayi /** 44169c69da3SRaghu Vatsavayi *\brief Destroy resources associated with octeon device 44269c69da3SRaghu Vatsavayi * @param pdev PCI device structure 44369c69da3SRaghu Vatsavayi * @param ent unused 44469c69da3SRaghu Vatsavayi */ 44569c69da3SRaghu Vatsavayi static void octeon_destroy_resources(struct octeon_device *oct) 44669c69da3SRaghu Vatsavayi { 447fe2d22b1SIntiyaz Basha struct octeon_device_priv *oct_priv = 448fe2d22b1SIntiyaz Basha (struct octeon_device_priv *)oct->priv; 449cf39faf5SRaghu Vatsavayi struct msix_entry *msix_entries; 4509003baf0SRaghu Vatsavayi int i; 4519003baf0SRaghu Vatsavayi 45269c69da3SRaghu Vatsavayi switch (atomic_read(&oct->status)) { 453b3c35973SRaghu Vatsavayi case OCT_DEV_RUNNING: 454b3c35973SRaghu Vatsavayi case OCT_DEV_CORE_OK: 455b3c35973SRaghu Vatsavayi /* No more instructions will be forwarded. */ 456b3c35973SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_IN_RESET); 457b3c35973SRaghu Vatsavayi 458846b4687SRaghu Vatsavayi oct->app_mode = CVM_DRV_INVALID_APP; 459b3c35973SRaghu Vatsavayi dev_dbg(&oct->pci_dev->dev, "Device state is now %s\n", 460b3c35973SRaghu Vatsavayi lio_get_state_string(&oct->status)); 461b3c35973SRaghu Vatsavayi 462b3c35973SRaghu Vatsavayi schedule_timeout_uninterruptible(HZ / 10); 463b3c35973SRaghu Vatsavayi 464b3c35973SRaghu Vatsavayi /* fallthrough */ 465b3c35973SRaghu Vatsavayi case OCT_DEV_HOST_OK: 466b3c35973SRaghu Vatsavayi /* fallthrough */ 467b3c35973SRaghu Vatsavayi case OCT_DEV_IO_QUEUES_DONE: 468b3c35973SRaghu Vatsavayi if (lio_wait_for_instr_fetch(oct)) 469b3c35973SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "IQ had pending instructions\n"); 470b3c35973SRaghu Vatsavayi 471c9aec052SFelix Manlunas if (wait_for_pending_requests(oct)) 472c9aec052SFelix Manlunas dev_err(&oct->pci_dev->dev, "There were pending requests\n"); 473c9aec052SFelix Manlunas 474b3c35973SRaghu Vatsavayi /* Disable the input and output queues now. No more packets will 475b3c35973SRaghu Vatsavayi * arrive from Octeon, but we should wait for all packet 476b3c35973SRaghu Vatsavayi * processing to finish. 477b3c35973SRaghu Vatsavayi */ 478b3c35973SRaghu Vatsavayi oct->fn_list.disable_io_queues(oct); 479b3c35973SRaghu Vatsavayi 480b3c35973SRaghu Vatsavayi if (lio_wait_for_oq_pkts(oct)) 481b3c35973SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "OQ had pending packets\n"); 482c9aec052SFelix Manlunas 483c9aec052SFelix Manlunas /* Force all requests waiting to be fetched by OCTEON to 484c9aec052SFelix Manlunas * complete. 485c9aec052SFelix Manlunas */ 486c9aec052SFelix Manlunas for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) { 487c9aec052SFelix Manlunas struct octeon_instr_queue *iq; 488c9aec052SFelix Manlunas 489c9aec052SFelix Manlunas if (!(oct->io_qmask.iq & BIT_ULL(i))) 490c9aec052SFelix Manlunas continue; 491c9aec052SFelix Manlunas iq = oct->instr_queue[i]; 492c9aec052SFelix Manlunas 493c9aec052SFelix Manlunas if (atomic_read(&iq->instr_pending)) { 494c9aec052SFelix Manlunas spin_lock_bh(&iq->lock); 495c9aec052SFelix Manlunas iq->fill_cnt = 0; 496c9aec052SFelix Manlunas iq->octeon_read_index = iq->host_write_index; 497c9aec052SFelix Manlunas iq->stats.instr_processed += 498c9aec052SFelix Manlunas atomic_read(&iq->instr_pending); 499c9aec052SFelix Manlunas lio_process_iq_request_list(oct, iq, 0); 500c9aec052SFelix Manlunas spin_unlock_bh(&iq->lock); 501c9aec052SFelix Manlunas } 502c9aec052SFelix Manlunas } 503c9aec052SFelix Manlunas 504c9aec052SFelix Manlunas lio_process_ordered_list(oct, 1); 505c9aec052SFelix Manlunas octeon_free_sc_done_list(oct); 506c9aec052SFelix Manlunas octeon_free_sc_zombie_list(oct); 507c9aec052SFelix Manlunas 50848acc9e8SGustavo A. R. Silva /* fall through */ 509cf39faf5SRaghu Vatsavayi case OCT_DEV_INTR_SET_DONE: 510cf39faf5SRaghu Vatsavayi /* Disable interrupts */ 511cf39faf5SRaghu Vatsavayi oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); 512cf39faf5SRaghu Vatsavayi 513cf39faf5SRaghu Vatsavayi if (oct->msix_on) { 514cf39faf5SRaghu Vatsavayi msix_entries = (struct msix_entry *)oct->msix_entries; 515cf39faf5SRaghu Vatsavayi for (i = 0; i < oct->num_msix_irqs; i++) { 516a82457f1SIntiyaz Basha if (oct->ioq_vector[i].vector) { 517a82457f1SIntiyaz Basha irq_set_affinity_hint( 518a82457f1SIntiyaz Basha msix_entries[i].vector, 519cf39faf5SRaghu Vatsavayi NULL); 520cf39faf5SRaghu Vatsavayi free_irq(msix_entries[i].vector, 521cf39faf5SRaghu Vatsavayi &oct->ioq_vector[i]); 522a82457f1SIntiyaz Basha oct->ioq_vector[i].vector = 0; 523a82457f1SIntiyaz Basha } 524cf39faf5SRaghu Vatsavayi } 525cf39faf5SRaghu Vatsavayi pci_disable_msix(oct->pci_dev); 526cf39faf5SRaghu Vatsavayi kfree(oct->msix_entries); 527cf39faf5SRaghu Vatsavayi oct->msix_entries = NULL; 5280c88a761SRick Farrington kfree(oct->irq_name_storage); 5290c88a761SRick Farrington oct->irq_name_storage = NULL; 530cf39faf5SRaghu Vatsavayi } 531cf39faf5SRaghu Vatsavayi /* Soft reset the octeon device before exiting */ 532cf39faf5SRaghu Vatsavayi if (oct->pci_dev->reset_fn) 533cf39faf5SRaghu Vatsavayi octeon_pci_flr(oct); 534cf39faf5SRaghu Vatsavayi else 535cf39faf5SRaghu Vatsavayi cn23xx_vf_ask_pf_to_do_flr(oct); 536cf39faf5SRaghu Vatsavayi 537cf39faf5SRaghu Vatsavayi /* fallthrough */ 538cf39faf5SRaghu Vatsavayi case OCT_DEV_MSIX_ALLOC_VECTOR_DONE: 539cf39faf5SRaghu Vatsavayi octeon_free_ioq_vector(oct); 540cf39faf5SRaghu Vatsavayi 541cf39faf5SRaghu Vatsavayi /* fallthrough */ 542f7cdd64bSRaghu Vatsavayi case OCT_DEV_MBOX_SETUP_DONE: 543f7cdd64bSRaghu Vatsavayi oct->fn_list.free_mbox(oct); 544f7cdd64bSRaghu Vatsavayi 545f7cdd64bSRaghu Vatsavayi /* fallthrough */ 5469003baf0SRaghu Vatsavayi case OCT_DEV_IN_RESET: 5479003baf0SRaghu Vatsavayi case OCT_DEV_DROQ_INIT_DONE: 5489003baf0SRaghu Vatsavayi mdelay(100); 5499003baf0SRaghu Vatsavayi for (i = 0; i < MAX_OCTEON_OUTPUT_QUEUES(oct); i++) { 5509003baf0SRaghu Vatsavayi if (!(oct->io_qmask.oq & BIT_ULL(i))) 5519003baf0SRaghu Vatsavayi continue; 5529003baf0SRaghu Vatsavayi octeon_delete_droq(oct, i); 5539003baf0SRaghu Vatsavayi } 5549003baf0SRaghu Vatsavayi 5559003baf0SRaghu Vatsavayi /* fallthrough */ 5569003baf0SRaghu Vatsavayi case OCT_DEV_RESP_LIST_INIT_DONE: 5579003baf0SRaghu Vatsavayi octeon_delete_response_list(oct); 5589003baf0SRaghu Vatsavayi 5599003baf0SRaghu Vatsavayi /* fallthrough */ 5609003baf0SRaghu Vatsavayi case OCT_DEV_INSTR_QUEUE_INIT_DONE: 5619003baf0SRaghu Vatsavayi for (i = 0; i < MAX_OCTEON_INSTR_QUEUES(oct); i++) { 5629003baf0SRaghu Vatsavayi if (!(oct->io_qmask.iq & BIT_ULL(i))) 5639003baf0SRaghu Vatsavayi continue; 5649003baf0SRaghu Vatsavayi octeon_delete_instr_queue(oct, i); 5659003baf0SRaghu Vatsavayi } 5669003baf0SRaghu Vatsavayi 5679003baf0SRaghu Vatsavayi /* fallthrough */ 5689003baf0SRaghu Vatsavayi case OCT_DEV_SC_BUFF_POOL_INIT_DONE: 5699003baf0SRaghu Vatsavayi octeon_free_sc_buffer_pool(oct); 5709003baf0SRaghu Vatsavayi 5719003baf0SRaghu Vatsavayi /* fallthrough */ 5729003baf0SRaghu Vatsavayi case OCT_DEV_DISPATCH_INIT_DONE: 5739003baf0SRaghu Vatsavayi octeon_delete_dispatch_list(oct); 5749003baf0SRaghu Vatsavayi cancel_delayed_work_sync(&oct->nic_poll_work.work); 5759003baf0SRaghu Vatsavayi 5769003baf0SRaghu Vatsavayi /* fallthrough */ 57769c69da3SRaghu Vatsavayi case OCT_DEV_PCI_MAP_DONE: 57869c69da3SRaghu Vatsavayi octeon_unmap_pci_barx(oct, 0); 57969c69da3SRaghu Vatsavayi octeon_unmap_pci_barx(oct, 1); 58069c69da3SRaghu Vatsavayi 58169c69da3SRaghu Vatsavayi /* fallthrough */ 58269c69da3SRaghu Vatsavayi case OCT_DEV_PCI_ENABLE_DONE: 58369c69da3SRaghu Vatsavayi pci_clear_master(oct->pci_dev); 58469c69da3SRaghu Vatsavayi /* Disable the device, releasing the PCI INT */ 58569c69da3SRaghu Vatsavayi pci_disable_device(oct->pci_dev); 58669c69da3SRaghu Vatsavayi 58769c69da3SRaghu Vatsavayi /* fallthrough */ 58869c69da3SRaghu Vatsavayi case OCT_DEV_BEGIN_STATE: 58969c69da3SRaghu Vatsavayi /* Nothing to be done here either */ 59069c69da3SRaghu Vatsavayi break; 59169c69da3SRaghu Vatsavayi } 592fe2d22b1SIntiyaz Basha 593fe2d22b1SIntiyaz Basha tasklet_kill(&oct_priv->droq_tasklet); 59469c69da3SRaghu Vatsavayi } 59569c69da3SRaghu Vatsavayi 59669c69da3SRaghu Vatsavayi /** 5979217c3cfSRaghu Vatsavayi * \brief Send Rx control command 5989217c3cfSRaghu Vatsavayi * @param lio per-network private data 5999217c3cfSRaghu Vatsavayi * @param start_stop whether to start or stop 6009217c3cfSRaghu Vatsavayi */ 6019217c3cfSRaghu Vatsavayi static void send_rx_ctrl_cmd(struct lio *lio, int start_stop) 6029217c3cfSRaghu Vatsavayi { 6039217c3cfSRaghu Vatsavayi struct octeon_device *oct = (struct octeon_device *)lio->oct_dev; 6049217c3cfSRaghu Vatsavayi struct octeon_soft_command *sc; 6059217c3cfSRaghu Vatsavayi union octnet_cmd *ncmd; 6069217c3cfSRaghu Vatsavayi int retval; 6079217c3cfSRaghu Vatsavayi 6089217c3cfSRaghu Vatsavayi if (oct->props[lio->ifidx].rx_on == start_stop) 6099217c3cfSRaghu Vatsavayi return; 6109217c3cfSRaghu Vatsavayi 6119217c3cfSRaghu Vatsavayi sc = (struct octeon_soft_command *) 6129217c3cfSRaghu Vatsavayi octeon_alloc_soft_command(oct, OCTNET_CMD_SIZE, 61364fecd3eSFelix Manlunas 16, 0); 6149217c3cfSRaghu Vatsavayi 6159217c3cfSRaghu Vatsavayi ncmd = (union octnet_cmd *)sc->virtdptr; 6169217c3cfSRaghu Vatsavayi 6179217c3cfSRaghu Vatsavayi ncmd->u64 = 0; 6189217c3cfSRaghu Vatsavayi ncmd->s.cmd = OCTNET_CMD_RX_CTL; 6199217c3cfSRaghu Vatsavayi ncmd->s.param1 = start_stop; 6209217c3cfSRaghu Vatsavayi 6219217c3cfSRaghu Vatsavayi octeon_swap_8B_data((u64 *)ncmd, (OCTNET_CMD_SIZE >> 3)); 6229217c3cfSRaghu Vatsavayi 6239217c3cfSRaghu Vatsavayi sc->iq_no = lio->linfo.txpciq[0].s.q_no; 6249217c3cfSRaghu Vatsavayi 6259217c3cfSRaghu Vatsavayi octeon_prepare_soft_command(oct, sc, OPCODE_NIC, 6269217c3cfSRaghu Vatsavayi OPCODE_NIC_CMD, 0, 0, 0); 6279217c3cfSRaghu Vatsavayi 62864fecd3eSFelix Manlunas init_completion(&sc->complete); 62964fecd3eSFelix Manlunas sc->sc_status = OCTEON_REQUEST_PENDING; 6309217c3cfSRaghu Vatsavayi 6319217c3cfSRaghu Vatsavayi retval = octeon_send_soft_command(oct, sc); 6329217c3cfSRaghu Vatsavayi if (retval == IQ_SEND_FAILED) { 6339217c3cfSRaghu Vatsavayi netif_info(lio, rx_err, lio->netdev, "Failed to send RX Control message\n"); 63464fecd3eSFelix Manlunas octeon_free_soft_command(oct, sc); 6359217c3cfSRaghu Vatsavayi } else { 6369217c3cfSRaghu Vatsavayi /* Sleep on a wait queue till the cond flag indicates that the 6379217c3cfSRaghu Vatsavayi * response arrived or timed-out. 6389217c3cfSRaghu Vatsavayi */ 63964fecd3eSFelix Manlunas retval = wait_for_sc_completion_timeout(oct, sc, 0); 64064fecd3eSFelix Manlunas if (retval) 6419217c3cfSRaghu Vatsavayi return; 6429217c3cfSRaghu Vatsavayi 64364fecd3eSFelix Manlunas oct->props[lio->ifidx].rx_on = start_stop; 64464fecd3eSFelix Manlunas WRITE_ONCE(sc->caller_is_done, true); 64564fecd3eSFelix Manlunas } 6469217c3cfSRaghu Vatsavayi } 6479217c3cfSRaghu Vatsavayi 6489217c3cfSRaghu Vatsavayi /** 649846b4687SRaghu Vatsavayi * \brief Destroy NIC device interface 650846b4687SRaghu Vatsavayi * @param oct octeon device 651846b4687SRaghu Vatsavayi * @param ifidx which interface to destroy 652846b4687SRaghu Vatsavayi * 653846b4687SRaghu Vatsavayi * Cleanup associated with each interface for an Octeon device when NIC 654846b4687SRaghu Vatsavayi * module is being unloaded or if initialization fails during load. 655846b4687SRaghu Vatsavayi */ 656846b4687SRaghu Vatsavayi static void liquidio_destroy_nic_device(struct octeon_device *oct, int ifidx) 657846b4687SRaghu Vatsavayi { 658846b4687SRaghu Vatsavayi struct net_device *netdev = oct->props[ifidx].netdev; 659fe2d22b1SIntiyaz Basha struct octeon_device_priv *oct_priv = 660fe2d22b1SIntiyaz Basha (struct octeon_device_priv *)oct->priv; 6619217c3cfSRaghu Vatsavayi struct napi_struct *napi, *n; 662846b4687SRaghu Vatsavayi struct lio *lio; 663846b4687SRaghu Vatsavayi 664846b4687SRaghu Vatsavayi if (!netdev) { 665846b4687SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "%s No netdevice ptr for index %d\n", 666846b4687SRaghu Vatsavayi __func__, ifidx); 667846b4687SRaghu Vatsavayi return; 668846b4687SRaghu Vatsavayi } 669846b4687SRaghu Vatsavayi 670846b4687SRaghu Vatsavayi lio = GET_LIO(netdev); 671846b4687SRaghu Vatsavayi 672846b4687SRaghu Vatsavayi dev_dbg(&oct->pci_dev->dev, "NIC device cleanup\n"); 673846b4687SRaghu Vatsavayi 674846b4687SRaghu Vatsavayi if (atomic_read(&lio->ifstate) & LIO_IFSTATE_RUNNING) 675846b4687SRaghu Vatsavayi liquidio_stop(netdev); 676846b4687SRaghu Vatsavayi 6779217c3cfSRaghu Vatsavayi if (oct->props[lio->ifidx].napi_enabled == 1) { 6789217c3cfSRaghu Vatsavayi list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list) 6799217c3cfSRaghu Vatsavayi napi_disable(napi); 6809217c3cfSRaghu Vatsavayi 6819217c3cfSRaghu Vatsavayi oct->props[lio->ifidx].napi_enabled = 0; 6829217c3cfSRaghu Vatsavayi 6839217c3cfSRaghu Vatsavayi oct->droq[0]->ops.poll_mode = 0; 6849217c3cfSRaghu Vatsavayi } 6859217c3cfSRaghu Vatsavayi 68642013e90SIntiyaz Basha /* Delete NAPI */ 68742013e90SIntiyaz Basha list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list) 68842013e90SIntiyaz Basha netif_napi_del(napi); 68942013e90SIntiyaz Basha 690fe2d22b1SIntiyaz Basha tasklet_enable(&oct_priv->droq_tasklet); 691fe2d22b1SIntiyaz Basha 692846b4687SRaghu Vatsavayi if (atomic_read(&lio->ifstate) & LIO_IFSTATE_REGISTERED) 693846b4687SRaghu Vatsavayi unregister_netdev(netdev); 694846b4687SRaghu Vatsavayi 695031d4f12SSatanand Burla cleanup_rx_oom_poll_fn(netdev); 696031d4f12SSatanand Burla 6973cd25e48SRaghu Vatsavayi cleanup_link_status_change_wq(netdev); 6983cd25e48SRaghu Vatsavayi 699fd311f1eSIntiyaz Basha lio_delete_glists(lio); 700beea50a5SRaghu Vatsavayi 701846b4687SRaghu Vatsavayi free_netdev(netdev); 702846b4687SRaghu Vatsavayi 703846b4687SRaghu Vatsavayi oct->props[ifidx].gmxport = -1; 704846b4687SRaghu Vatsavayi 705846b4687SRaghu Vatsavayi oct->props[ifidx].netdev = NULL; 706846b4687SRaghu Vatsavayi } 707846b4687SRaghu Vatsavayi 708846b4687SRaghu Vatsavayi /** 709846b4687SRaghu Vatsavayi * \brief Stop complete NIC functionality 710846b4687SRaghu Vatsavayi * @param oct octeon device 711846b4687SRaghu Vatsavayi */ 712846b4687SRaghu Vatsavayi static int liquidio_stop_nic_module(struct octeon_device *oct) 713846b4687SRaghu Vatsavayi { 7149217c3cfSRaghu Vatsavayi struct lio *lio; 7159217c3cfSRaghu Vatsavayi int i, j; 716846b4687SRaghu Vatsavayi 717846b4687SRaghu Vatsavayi dev_dbg(&oct->pci_dev->dev, "Stopping network interfaces\n"); 718846b4687SRaghu Vatsavayi if (!oct->ifcount) { 719846b4687SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Init for Octeon was not completed\n"); 720846b4687SRaghu Vatsavayi return 1; 721846b4687SRaghu Vatsavayi } 722846b4687SRaghu Vatsavayi 7239217c3cfSRaghu Vatsavayi spin_lock_bh(&oct->cmd_resp_wqlock); 7249217c3cfSRaghu Vatsavayi oct->cmd_resp_state = OCT_DRV_OFFLINE; 7259217c3cfSRaghu Vatsavayi spin_unlock_bh(&oct->cmd_resp_wqlock); 7269217c3cfSRaghu Vatsavayi 7279217c3cfSRaghu Vatsavayi for (i = 0; i < oct->ifcount; i++) { 7289217c3cfSRaghu Vatsavayi lio = GET_LIO(oct->props[i].netdev); 729a82457f1SIntiyaz Basha for (j = 0; j < oct->num_oqs; j++) 7309217c3cfSRaghu Vatsavayi octeon_unregister_droq_ops(oct, 7319217c3cfSRaghu Vatsavayi lio->linfo.rxpciq[j].s.q_no); 7329217c3cfSRaghu Vatsavayi } 7339217c3cfSRaghu Vatsavayi 734846b4687SRaghu Vatsavayi for (i = 0; i < oct->ifcount; i++) 735846b4687SRaghu Vatsavayi liquidio_destroy_nic_device(oct, i); 736846b4687SRaghu Vatsavayi 737846b4687SRaghu Vatsavayi dev_dbg(&oct->pci_dev->dev, "Network interfaces stopped\n"); 738846b4687SRaghu Vatsavayi return 0; 739846b4687SRaghu Vatsavayi } 740846b4687SRaghu Vatsavayi 741846b4687SRaghu Vatsavayi /** 742111fc64aSRaghu Vatsavayi * \brief Cleans up resources at unload time 743111fc64aSRaghu Vatsavayi * @param pdev PCI device structure 744111fc64aSRaghu Vatsavayi */ 745111fc64aSRaghu Vatsavayi static void liquidio_vf_remove(struct pci_dev *pdev) 746111fc64aSRaghu Vatsavayi { 747111fc64aSRaghu Vatsavayi struct octeon_device *oct_dev = pci_get_drvdata(pdev); 748111fc64aSRaghu Vatsavayi 749111fc64aSRaghu Vatsavayi dev_dbg(&oct_dev->pci_dev->dev, "Stopping device\n"); 750111fc64aSRaghu Vatsavayi 751846b4687SRaghu Vatsavayi if (oct_dev->app_mode == CVM_DRV_NIC_APP) 752846b4687SRaghu Vatsavayi liquidio_stop_nic_module(oct_dev); 753846b4687SRaghu Vatsavayi 75469c69da3SRaghu Vatsavayi /* Reset the octeon device and cleanup all memory allocated for 75569c69da3SRaghu Vatsavayi * the octeon device by driver. 75669c69da3SRaghu Vatsavayi */ 75769c69da3SRaghu Vatsavayi octeon_destroy_resources(oct_dev); 75869c69da3SRaghu Vatsavayi 75969c69da3SRaghu Vatsavayi dev_info(&oct_dev->pci_dev->dev, "Device removed\n"); 76069c69da3SRaghu Vatsavayi 761111fc64aSRaghu Vatsavayi /* This octeon device has been removed. Update the global 762111fc64aSRaghu Vatsavayi * data structure to reflect this. Free the device structure. 763111fc64aSRaghu Vatsavayi */ 764111fc64aSRaghu Vatsavayi octeon_free_device_mem(oct_dev); 765111fc64aSRaghu Vatsavayi } 766111fc64aSRaghu Vatsavayi 76769c69da3SRaghu Vatsavayi /** 76869c69da3SRaghu Vatsavayi * \brief PCI initialization for each Octeon device. 76969c69da3SRaghu Vatsavayi * @param oct octeon device 77069c69da3SRaghu Vatsavayi */ 77169c69da3SRaghu Vatsavayi static int octeon_pci_os_setup(struct octeon_device *oct) 77269c69da3SRaghu Vatsavayi { 77369c69da3SRaghu Vatsavayi #ifdef CONFIG_PCI_IOV 77469c69da3SRaghu Vatsavayi /* setup PCI stuff first */ 77569c69da3SRaghu Vatsavayi if (!oct->pci_dev->physfn) 77669c69da3SRaghu Vatsavayi octeon_pci_flr(oct); 77769c69da3SRaghu Vatsavayi #endif 77869c69da3SRaghu Vatsavayi 77969c69da3SRaghu Vatsavayi if (pci_enable_device(oct->pci_dev)) { 78069c69da3SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "pci_enable_device failed\n"); 78169c69da3SRaghu Vatsavayi return 1; 78269c69da3SRaghu Vatsavayi } 78369c69da3SRaghu Vatsavayi 78469c69da3SRaghu Vatsavayi if (dma_set_mask_and_coherent(&oct->pci_dev->dev, DMA_BIT_MASK(64))) { 78569c69da3SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Unexpected DMA device capability\n"); 78669c69da3SRaghu Vatsavayi pci_disable_device(oct->pci_dev); 78769c69da3SRaghu Vatsavayi return 1; 78869c69da3SRaghu Vatsavayi } 78969c69da3SRaghu Vatsavayi 79069c69da3SRaghu Vatsavayi /* Enable PCI DMA Master. */ 79169c69da3SRaghu Vatsavayi pci_set_master(oct->pci_dev); 79269c69da3SRaghu Vatsavayi 79369c69da3SRaghu Vatsavayi return 0; 79469c69da3SRaghu Vatsavayi } 79569c69da3SRaghu Vatsavayi 7969bdca5c6SRaghu Vatsavayi /** 7979bdca5c6SRaghu Vatsavayi * \brief Unmap and free network buffer 7989bdca5c6SRaghu Vatsavayi * @param buf buffer 7999bdca5c6SRaghu Vatsavayi */ 8009bdca5c6SRaghu Vatsavayi static void free_netbuf(void *buf) 8019bdca5c6SRaghu Vatsavayi { 8029bdca5c6SRaghu Vatsavayi struct octnet_buf_free_info *finfo; 8039bdca5c6SRaghu Vatsavayi struct sk_buff *skb; 8049bdca5c6SRaghu Vatsavayi struct lio *lio; 8059bdca5c6SRaghu Vatsavayi 8069bdca5c6SRaghu Vatsavayi finfo = (struct octnet_buf_free_info *)buf; 8079bdca5c6SRaghu Vatsavayi skb = finfo->skb; 8089bdca5c6SRaghu Vatsavayi lio = finfo->lio; 8099bdca5c6SRaghu Vatsavayi 8109bdca5c6SRaghu Vatsavayi dma_unmap_single(&lio->oct_dev->pci_dev->dev, finfo->dptr, skb->len, 8119bdca5c6SRaghu Vatsavayi DMA_TO_DEVICE); 8129bdca5c6SRaghu Vatsavayi 8139bdca5c6SRaghu Vatsavayi tx_buffer_free(skb); 8149bdca5c6SRaghu Vatsavayi } 8159bdca5c6SRaghu Vatsavayi 8169bdca5c6SRaghu Vatsavayi /** 8179bdca5c6SRaghu Vatsavayi * \brief Unmap and free gather buffer 8189bdca5c6SRaghu Vatsavayi * @param buf buffer 8199bdca5c6SRaghu Vatsavayi */ 8209bdca5c6SRaghu Vatsavayi static void free_netsgbuf(void *buf) 8219bdca5c6SRaghu Vatsavayi { 8229bdca5c6SRaghu Vatsavayi struct octnet_buf_free_info *finfo; 8239bdca5c6SRaghu Vatsavayi struct octnic_gather *g; 8249bdca5c6SRaghu Vatsavayi struct sk_buff *skb; 8259bdca5c6SRaghu Vatsavayi int i, frags, iq; 8269bdca5c6SRaghu Vatsavayi struct lio *lio; 8279bdca5c6SRaghu Vatsavayi 8289bdca5c6SRaghu Vatsavayi finfo = (struct octnet_buf_free_info *)buf; 8299bdca5c6SRaghu Vatsavayi skb = finfo->skb; 8309bdca5c6SRaghu Vatsavayi lio = finfo->lio; 8319bdca5c6SRaghu Vatsavayi g = finfo->g; 8329bdca5c6SRaghu Vatsavayi frags = skb_shinfo(skb)->nr_frags; 8339bdca5c6SRaghu Vatsavayi 8349bdca5c6SRaghu Vatsavayi dma_unmap_single(&lio->oct_dev->pci_dev->dev, 8359bdca5c6SRaghu Vatsavayi g->sg[0].ptr[0], (skb->len - skb->data_len), 8369bdca5c6SRaghu Vatsavayi DMA_TO_DEVICE); 8379bdca5c6SRaghu Vatsavayi 8389bdca5c6SRaghu Vatsavayi i = 1; 8399bdca5c6SRaghu Vatsavayi while (frags--) { 8409bdca5c6SRaghu Vatsavayi struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; 8419bdca5c6SRaghu Vatsavayi 8429bdca5c6SRaghu Vatsavayi pci_unmap_page((lio->oct_dev)->pci_dev, 8439bdca5c6SRaghu Vatsavayi g->sg[(i >> 2)].ptr[(i & 3)], 8449bdca5c6SRaghu Vatsavayi frag->size, DMA_TO_DEVICE); 8459bdca5c6SRaghu Vatsavayi i++; 8469bdca5c6SRaghu Vatsavayi } 8479bdca5c6SRaghu Vatsavayi 848c33c9973SIntiyaz Basha iq = skb_iq(lio->oct_dev, skb); 8499bdca5c6SRaghu Vatsavayi 8509bdca5c6SRaghu Vatsavayi spin_lock(&lio->glist_lock[iq]); 8519bdca5c6SRaghu Vatsavayi list_add_tail(&g->list, &lio->glist[iq]); 8529bdca5c6SRaghu Vatsavayi spin_unlock(&lio->glist_lock[iq]); 8539bdca5c6SRaghu Vatsavayi 8549bdca5c6SRaghu Vatsavayi tx_buffer_free(skb); 8559bdca5c6SRaghu Vatsavayi } 8569bdca5c6SRaghu Vatsavayi 8579bdca5c6SRaghu Vatsavayi /** 8589bdca5c6SRaghu Vatsavayi * \brief Unmap and free gather buffer with response 8599bdca5c6SRaghu Vatsavayi * @param buf buffer 8609bdca5c6SRaghu Vatsavayi */ 8619bdca5c6SRaghu Vatsavayi static void free_netsgbuf_with_resp(void *buf) 8629bdca5c6SRaghu Vatsavayi { 8639bdca5c6SRaghu Vatsavayi struct octnet_buf_free_info *finfo; 8649bdca5c6SRaghu Vatsavayi struct octeon_soft_command *sc; 8659bdca5c6SRaghu Vatsavayi struct octnic_gather *g; 8669bdca5c6SRaghu Vatsavayi struct sk_buff *skb; 8679bdca5c6SRaghu Vatsavayi int i, frags, iq; 8689bdca5c6SRaghu Vatsavayi struct lio *lio; 8699bdca5c6SRaghu Vatsavayi 8709bdca5c6SRaghu Vatsavayi sc = (struct octeon_soft_command *)buf; 8719bdca5c6SRaghu Vatsavayi skb = (struct sk_buff *)sc->callback_arg; 8729bdca5c6SRaghu Vatsavayi finfo = (struct octnet_buf_free_info *)&skb->cb; 8739bdca5c6SRaghu Vatsavayi 8749bdca5c6SRaghu Vatsavayi lio = finfo->lio; 8759bdca5c6SRaghu Vatsavayi g = finfo->g; 8769bdca5c6SRaghu Vatsavayi frags = skb_shinfo(skb)->nr_frags; 8779bdca5c6SRaghu Vatsavayi 8789bdca5c6SRaghu Vatsavayi dma_unmap_single(&lio->oct_dev->pci_dev->dev, 8799bdca5c6SRaghu Vatsavayi g->sg[0].ptr[0], (skb->len - skb->data_len), 8809bdca5c6SRaghu Vatsavayi DMA_TO_DEVICE); 8819bdca5c6SRaghu Vatsavayi 8829bdca5c6SRaghu Vatsavayi i = 1; 8839bdca5c6SRaghu Vatsavayi while (frags--) { 8849bdca5c6SRaghu Vatsavayi struct skb_frag_struct *frag = &skb_shinfo(skb)->frags[i - 1]; 8859bdca5c6SRaghu Vatsavayi 8869bdca5c6SRaghu Vatsavayi pci_unmap_page((lio->oct_dev)->pci_dev, 8879bdca5c6SRaghu Vatsavayi g->sg[(i >> 2)].ptr[(i & 3)], 8889bdca5c6SRaghu Vatsavayi frag->size, DMA_TO_DEVICE); 8899bdca5c6SRaghu Vatsavayi i++; 8909bdca5c6SRaghu Vatsavayi } 8919bdca5c6SRaghu Vatsavayi 892c33c9973SIntiyaz Basha iq = skb_iq(lio->oct_dev, skb); 8939bdca5c6SRaghu Vatsavayi 8949bdca5c6SRaghu Vatsavayi spin_lock(&lio->glist_lock[iq]); 8959bdca5c6SRaghu Vatsavayi list_add_tail(&g->list, &lio->glist[iq]); 8969bdca5c6SRaghu Vatsavayi spin_unlock(&lio->glist_lock[iq]); 8979bdca5c6SRaghu Vatsavayi 8989bdca5c6SRaghu Vatsavayi /* Don't free the skb yet */ 8999bdca5c6SRaghu Vatsavayi } 9009bdca5c6SRaghu Vatsavayi 90169c69da3SRaghu Vatsavayi /** 9023cd25e48SRaghu Vatsavayi * \brief Net device open for LiquidIO 9033cd25e48SRaghu Vatsavayi * @param netdev network device 9043cd25e48SRaghu Vatsavayi */ 9053cd25e48SRaghu Vatsavayi static int liquidio_open(struct net_device *netdev) 9063cd25e48SRaghu Vatsavayi { 9073cd25e48SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 9083cd25e48SRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 909fe2d22b1SIntiyaz Basha struct octeon_device_priv *oct_priv = 910fe2d22b1SIntiyaz Basha (struct octeon_device_priv *)oct->priv; 9119217c3cfSRaghu Vatsavayi struct napi_struct *napi, *n; 9129217c3cfSRaghu Vatsavayi 9139217c3cfSRaghu Vatsavayi if (!oct->props[lio->ifidx].napi_enabled) { 914fe2d22b1SIntiyaz Basha tasklet_disable(&oct_priv->droq_tasklet); 915fe2d22b1SIntiyaz Basha 9169217c3cfSRaghu Vatsavayi list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list) 9179217c3cfSRaghu Vatsavayi napi_enable(napi); 9189217c3cfSRaghu Vatsavayi 9199217c3cfSRaghu Vatsavayi oct->props[lio->ifidx].napi_enabled = 1; 9209217c3cfSRaghu Vatsavayi 9219217c3cfSRaghu Vatsavayi oct->droq[0]->ops.poll_mode = 1; 9229217c3cfSRaghu Vatsavayi } 9233cd25e48SRaghu Vatsavayi 9243cd25e48SRaghu Vatsavayi ifstate_set(lio, LIO_IFSTATE_RUNNING); 9253cd25e48SRaghu Vatsavayi 9263cd25e48SRaghu Vatsavayi /* Ready for link status updates */ 9273cd25e48SRaghu Vatsavayi lio->intf_open = 1; 9283cd25e48SRaghu Vatsavayi 9293cd25e48SRaghu Vatsavayi netif_info(lio, ifup, lio->netdev, "Interface Open, ready for traffic\n"); 930c9614a16SIntiyaz Basha start_txqs(netdev); 9313cd25e48SRaghu Vatsavayi 93235878618SPradeep Nalla INIT_DELAYED_WORK(&lio->stats_wk.work, lio_fetch_stats); 93335878618SPradeep Nalla lio->stats_wk.ctxptr = lio; 93435878618SPradeep Nalla schedule_delayed_work(&lio->stats_wk.work, msecs_to_jiffies 93535878618SPradeep Nalla (LIQUIDIO_NDEV_STATS_POLL_TIME_MS)); 93635878618SPradeep Nalla 9379217c3cfSRaghu Vatsavayi /* tell Octeon to start forwarding packets to host */ 9389217c3cfSRaghu Vatsavayi send_rx_ctrl_cmd(lio, 1); 9399217c3cfSRaghu Vatsavayi 9403cd25e48SRaghu Vatsavayi dev_info(&oct->pci_dev->dev, "%s interface is opened\n", netdev->name); 9413cd25e48SRaghu Vatsavayi 9423cd25e48SRaghu Vatsavayi return 0; 9433cd25e48SRaghu Vatsavayi } 9443cd25e48SRaghu Vatsavayi 9453cd25e48SRaghu Vatsavayi /** 946846b4687SRaghu Vatsavayi * \brief Net device stop for LiquidIO 947846b4687SRaghu Vatsavayi * @param netdev network device 948846b4687SRaghu Vatsavayi */ 949846b4687SRaghu Vatsavayi static int liquidio_stop(struct net_device *netdev) 950846b4687SRaghu Vatsavayi { 951846b4687SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 952846b4687SRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 953fe2d22b1SIntiyaz Basha struct octeon_device_priv *oct_priv = 954fe2d22b1SIntiyaz Basha (struct octeon_device_priv *)oct->priv; 95542013e90SIntiyaz Basha struct napi_struct *napi, *n; 95642013e90SIntiyaz Basha 957aa28667cSFelix Manlunas /* tell Octeon to stop forwarding packets to host */ 958aa28667cSFelix Manlunas send_rx_ctrl_cmd(lio, 0); 959aa28667cSFelix Manlunas 960846b4687SRaghu Vatsavayi netif_info(lio, ifdown, lio->netdev, "Stopping interface!\n"); 961846b4687SRaghu Vatsavayi /* Inform that netif carrier is down */ 962846b4687SRaghu Vatsavayi lio->intf_open = 0; 963846b4687SRaghu Vatsavayi lio->linfo.link.s.link_up = 0; 964846b4687SRaghu Vatsavayi 965846b4687SRaghu Vatsavayi netif_carrier_off(netdev); 966846b4687SRaghu Vatsavayi lio->link_changes++; 967846b4687SRaghu Vatsavayi 968846b4687SRaghu Vatsavayi ifstate_reset(lio, LIO_IFSTATE_RUNNING); 969846b4687SRaghu Vatsavayi 970736b7ea5SIntiyaz Basha stop_txqs(netdev); 9713cd25e48SRaghu Vatsavayi 972ccdd0b4cSRaghu Vatsavayi /* Wait for any pending Rx descriptors */ 973ccdd0b4cSRaghu Vatsavayi if (lio_wait_for_clean_oq(oct)) 974ccdd0b4cSRaghu Vatsavayi netif_info(lio, rx_err, lio->netdev, 975ccdd0b4cSRaghu Vatsavayi "Proceeding with stop interface after partial RX desc processing\n"); 976ccdd0b4cSRaghu Vatsavayi 977ccdd0b4cSRaghu Vatsavayi if (oct->props[lio->ifidx].napi_enabled == 1) { 978ccdd0b4cSRaghu Vatsavayi list_for_each_entry_safe(napi, n, &netdev->napi_list, dev_list) 979ccdd0b4cSRaghu Vatsavayi napi_disable(napi); 980ccdd0b4cSRaghu Vatsavayi 981ccdd0b4cSRaghu Vatsavayi oct->props[lio->ifidx].napi_enabled = 0; 982ccdd0b4cSRaghu Vatsavayi 983ccdd0b4cSRaghu Vatsavayi oct->droq[0]->ops.poll_mode = 0; 984fe2d22b1SIntiyaz Basha 985fe2d22b1SIntiyaz Basha tasklet_enable(&oct_priv->droq_tasklet); 986ccdd0b4cSRaghu Vatsavayi } 987ccdd0b4cSRaghu Vatsavayi 98835878618SPradeep Nalla cancel_delayed_work_sync(&lio->stats_wk.work); 98935878618SPradeep Nalla 990846b4687SRaghu Vatsavayi dev_info(&oct->pci_dev->dev, "%s interface is stopped\n", netdev->name); 991846b4687SRaghu Vatsavayi 992846b4687SRaghu Vatsavayi return 0; 993846b4687SRaghu Vatsavayi } 994846b4687SRaghu Vatsavayi 99550f7f94bSRaghu Vatsavayi /** 99650f7f94bSRaghu Vatsavayi * \brief Converts a mask based on net device flags 99750f7f94bSRaghu Vatsavayi * @param netdev network device 99850f7f94bSRaghu Vatsavayi * 99950f7f94bSRaghu Vatsavayi * This routine generates a octnet_ifflags mask from the net device flags 100050f7f94bSRaghu Vatsavayi * received from the OS. 100150f7f94bSRaghu Vatsavayi */ 100250f7f94bSRaghu Vatsavayi static enum octnet_ifflags get_new_flags(struct net_device *netdev) 100350f7f94bSRaghu Vatsavayi { 100450f7f94bSRaghu Vatsavayi enum octnet_ifflags f = OCTNET_IFFLAG_UNICAST; 100550f7f94bSRaghu Vatsavayi 100650f7f94bSRaghu Vatsavayi if (netdev->flags & IFF_PROMISC) 100750f7f94bSRaghu Vatsavayi f |= OCTNET_IFFLAG_PROMISC; 100850f7f94bSRaghu Vatsavayi 100950f7f94bSRaghu Vatsavayi if (netdev->flags & IFF_ALLMULTI) 101050f7f94bSRaghu Vatsavayi f |= OCTNET_IFFLAG_ALLMULTI; 101150f7f94bSRaghu Vatsavayi 101250f7f94bSRaghu Vatsavayi if (netdev->flags & IFF_MULTICAST) { 101350f7f94bSRaghu Vatsavayi f |= OCTNET_IFFLAG_MULTICAST; 101450f7f94bSRaghu Vatsavayi 101550f7f94bSRaghu Vatsavayi /* Accept all multicast addresses if there are more than we 101650f7f94bSRaghu Vatsavayi * can handle 101750f7f94bSRaghu Vatsavayi */ 101850f7f94bSRaghu Vatsavayi if (netdev_mc_count(netdev) > MAX_OCTEON_MULTICAST_ADDR) 101950f7f94bSRaghu Vatsavayi f |= OCTNET_IFFLAG_ALLMULTI; 102050f7f94bSRaghu Vatsavayi } 102150f7f94bSRaghu Vatsavayi 102250f7f94bSRaghu Vatsavayi if (netdev->flags & IFF_BROADCAST) 102350f7f94bSRaghu Vatsavayi f |= OCTNET_IFFLAG_BROADCAST; 102450f7f94bSRaghu Vatsavayi 102550f7f94bSRaghu Vatsavayi return f; 102650f7f94bSRaghu Vatsavayi } 102750f7f94bSRaghu Vatsavayi 102850f7f94bSRaghu Vatsavayi static void liquidio_set_uc_list(struct net_device *netdev) 102950f7f94bSRaghu Vatsavayi { 103050f7f94bSRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 103150f7f94bSRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 103250f7f94bSRaghu Vatsavayi struct octnic_ctrl_pkt nctrl; 103350f7f94bSRaghu Vatsavayi struct netdev_hw_addr *ha; 103450f7f94bSRaghu Vatsavayi u64 *mac; 103550f7f94bSRaghu Vatsavayi 103650f7f94bSRaghu Vatsavayi if (lio->netdev_uc_count == netdev_uc_count(netdev)) 103750f7f94bSRaghu Vatsavayi return; 103850f7f94bSRaghu Vatsavayi 103950f7f94bSRaghu Vatsavayi if (netdev_uc_count(netdev) > MAX_NCTRL_UDD) { 104050f7f94bSRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "too many MAC addresses in netdev uc list\n"); 104150f7f94bSRaghu Vatsavayi return; 104250f7f94bSRaghu Vatsavayi } 104350f7f94bSRaghu Vatsavayi 104450f7f94bSRaghu Vatsavayi lio->netdev_uc_count = netdev_uc_count(netdev); 104550f7f94bSRaghu Vatsavayi 104650f7f94bSRaghu Vatsavayi memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); 104750f7f94bSRaghu Vatsavayi nctrl.ncmd.s.cmd = OCTNET_CMD_SET_UC_LIST; 104850f7f94bSRaghu Vatsavayi nctrl.ncmd.s.more = lio->netdev_uc_count; 104950f7f94bSRaghu Vatsavayi nctrl.ncmd.s.param1 = oct->vf_num; 105050f7f94bSRaghu Vatsavayi nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 105150f7f94bSRaghu Vatsavayi nctrl.netpndev = (u64)netdev; 105250f7f94bSRaghu Vatsavayi nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; 105350f7f94bSRaghu Vatsavayi 105450f7f94bSRaghu Vatsavayi /* copy all the addresses into the udd */ 105550f7f94bSRaghu Vatsavayi mac = &nctrl.udd[0]; 105650f7f94bSRaghu Vatsavayi netdev_for_each_uc_addr(ha, netdev) { 105750f7f94bSRaghu Vatsavayi ether_addr_copy(((u8 *)mac) + 2, ha->addr); 105850f7f94bSRaghu Vatsavayi mac++; 105950f7f94bSRaghu Vatsavayi } 106050f7f94bSRaghu Vatsavayi 106150f7f94bSRaghu Vatsavayi octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); 106250f7f94bSRaghu Vatsavayi } 106350f7f94bSRaghu Vatsavayi 106450f7f94bSRaghu Vatsavayi /** 106550f7f94bSRaghu Vatsavayi * \brief Net device set_multicast_list 106650f7f94bSRaghu Vatsavayi * @param netdev network device 106750f7f94bSRaghu Vatsavayi */ 106850f7f94bSRaghu Vatsavayi static void liquidio_set_mcast_list(struct net_device *netdev) 106950f7f94bSRaghu Vatsavayi { 107050f7f94bSRaghu Vatsavayi int mc_count = min(netdev_mc_count(netdev), MAX_OCTEON_MULTICAST_ADDR); 107150f7f94bSRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 107250f7f94bSRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 107350f7f94bSRaghu Vatsavayi struct octnic_ctrl_pkt nctrl; 107450f7f94bSRaghu Vatsavayi struct netdev_hw_addr *ha; 107550f7f94bSRaghu Vatsavayi u64 *mc; 107650f7f94bSRaghu Vatsavayi int ret; 107750f7f94bSRaghu Vatsavayi 107850f7f94bSRaghu Vatsavayi memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); 107950f7f94bSRaghu Vatsavayi 108050f7f94bSRaghu Vatsavayi /* Create a ctrl pkt command to be sent to core app. */ 108150f7f94bSRaghu Vatsavayi nctrl.ncmd.u64 = 0; 108250f7f94bSRaghu Vatsavayi nctrl.ncmd.s.cmd = OCTNET_CMD_SET_MULTI_LIST; 108350f7f94bSRaghu Vatsavayi nctrl.ncmd.s.param1 = get_new_flags(netdev); 108450f7f94bSRaghu Vatsavayi nctrl.ncmd.s.param2 = mc_count; 108550f7f94bSRaghu Vatsavayi nctrl.ncmd.s.more = mc_count; 108650f7f94bSRaghu Vatsavayi nctrl.netpndev = (u64)netdev; 108750f7f94bSRaghu Vatsavayi nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; 108850f7f94bSRaghu Vatsavayi 108950f7f94bSRaghu Vatsavayi /* copy all the addresses into the udd */ 109050f7f94bSRaghu Vatsavayi mc = &nctrl.udd[0]; 109150f7f94bSRaghu Vatsavayi netdev_for_each_mc_addr(ha, netdev) { 109250f7f94bSRaghu Vatsavayi *mc = 0; 109350f7f94bSRaghu Vatsavayi ether_addr_copy(((u8 *)mc) + 2, ha->addr); 109450f7f94bSRaghu Vatsavayi /* no need to swap bytes */ 109550f7f94bSRaghu Vatsavayi if (++mc > &nctrl.udd[mc_count]) 109650f7f94bSRaghu Vatsavayi break; 109750f7f94bSRaghu Vatsavayi } 109850f7f94bSRaghu Vatsavayi 109950f7f94bSRaghu Vatsavayi nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 110050f7f94bSRaghu Vatsavayi 110150f7f94bSRaghu Vatsavayi /* Apparently, any activity in this call from the kernel has to 110250f7f94bSRaghu Vatsavayi * be atomic. So we won't wait for response. 110350f7f94bSRaghu Vatsavayi */ 110450f7f94bSRaghu Vatsavayi 110550f7f94bSRaghu Vatsavayi ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); 1106edd572d7SFelix Manlunas if (ret) { 110750f7f94bSRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "DEVFLAGS change failed in core (ret: 0x%x)\n", 110850f7f94bSRaghu Vatsavayi ret); 110950f7f94bSRaghu Vatsavayi } 111050f7f94bSRaghu Vatsavayi 111150f7f94bSRaghu Vatsavayi liquidio_set_uc_list(netdev); 111250f7f94bSRaghu Vatsavayi } 111350f7f94bSRaghu Vatsavayi 111450f7f94bSRaghu Vatsavayi /** 111550f7f94bSRaghu Vatsavayi * \brief Net device set_mac_address 111650f7f94bSRaghu Vatsavayi * @param netdev network device 111750f7f94bSRaghu Vatsavayi */ 111850f7f94bSRaghu Vatsavayi static int liquidio_set_mac(struct net_device *netdev, void *p) 111950f7f94bSRaghu Vatsavayi { 112050f7f94bSRaghu Vatsavayi struct sockaddr *addr = (struct sockaddr *)p; 112150f7f94bSRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 112250f7f94bSRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 112350f7f94bSRaghu Vatsavayi struct octnic_ctrl_pkt nctrl; 112450f7f94bSRaghu Vatsavayi int ret = 0; 112550f7f94bSRaghu Vatsavayi 112650f7f94bSRaghu Vatsavayi if (!is_valid_ether_addr(addr->sa_data)) 112750f7f94bSRaghu Vatsavayi return -EADDRNOTAVAIL; 112850f7f94bSRaghu Vatsavayi 112950f7f94bSRaghu Vatsavayi if (ether_addr_equal(addr->sa_data, netdev->dev_addr)) 113050f7f94bSRaghu Vatsavayi return 0; 113150f7f94bSRaghu Vatsavayi 113250f7f94bSRaghu Vatsavayi if (lio->linfo.macaddr_is_admin_asgnd) 113350f7f94bSRaghu Vatsavayi return -EPERM; 113450f7f94bSRaghu Vatsavayi 113550f7f94bSRaghu Vatsavayi memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); 113650f7f94bSRaghu Vatsavayi 113750f7f94bSRaghu Vatsavayi nctrl.ncmd.u64 = 0; 113850f7f94bSRaghu Vatsavayi nctrl.ncmd.s.cmd = OCTNET_CMD_CHANGE_MACADDR; 113950f7f94bSRaghu Vatsavayi nctrl.ncmd.s.param1 = 0; 114050f7f94bSRaghu Vatsavayi nctrl.ncmd.s.more = 1; 114150f7f94bSRaghu Vatsavayi nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 114250f7f94bSRaghu Vatsavayi nctrl.netpndev = (u64)netdev; 114350f7f94bSRaghu Vatsavayi 114450f7f94bSRaghu Vatsavayi nctrl.udd[0] = 0; 114550f7f94bSRaghu Vatsavayi /* The MAC Address is presented in network byte order. */ 114650f7f94bSRaghu Vatsavayi ether_addr_copy((u8 *)&nctrl.udd[0] + 2, addr->sa_data); 114750f7f94bSRaghu Vatsavayi 114850f7f94bSRaghu Vatsavayi ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); 114950f7f94bSRaghu Vatsavayi if (ret < 0) { 115050f7f94bSRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "MAC Address change failed\n"); 115150f7f94bSRaghu Vatsavayi return -ENOMEM; 115250f7f94bSRaghu Vatsavayi } 1153edd572d7SFelix Manlunas 115448875222SWeilin Chang if (nctrl.sc_status == 115548875222SWeilin Chang FIRMWARE_STATUS_CODE(OCTEON_REQUEST_NO_PERMISSION)) { 115648875222SWeilin Chang dev_err(&oct->pci_dev->dev, "MAC Address change failed: no permission\n"); 115748875222SWeilin Chang return -EPERM; 115848875222SWeilin Chang } 115948875222SWeilin Chang 116050f7f94bSRaghu Vatsavayi memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); 116150f7f94bSRaghu Vatsavayi ether_addr_copy(((u8 *)&lio->linfo.hw_addr) + 2, addr->sa_data); 116250f7f94bSRaghu Vatsavayi 116350f7f94bSRaghu Vatsavayi return 0; 116450f7f94bSRaghu Vatsavayi } 116550f7f94bSRaghu Vatsavayi 116680002347SPradeep Nalla static void 116780002347SPradeep Nalla liquidio_get_stats64(struct net_device *netdev, 116880002347SPradeep Nalla struct rtnl_link_stats64 *lstats) 1169d8ab848cSRaghu Vatsavayi { 1170d8ab848cSRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 117180002347SPradeep Nalla struct octeon_device *oct; 1172d8ab848cSRaghu Vatsavayi u64 pkts = 0, drop = 0, bytes = 0; 1173d8ab848cSRaghu Vatsavayi struct oct_droq_stats *oq_stats; 1174d8ab848cSRaghu Vatsavayi struct oct_iq_stats *iq_stats; 1175d8ab848cSRaghu Vatsavayi int i, iq_no, oq_no; 1176d8ab848cSRaghu Vatsavayi 1177d8ab848cSRaghu Vatsavayi oct = lio->oct_dev; 1178d8ab848cSRaghu Vatsavayi 1179d18ca7dfSIntiyaz Basha if (ifstate_check(lio, LIO_IFSTATE_RESETTING)) 118080002347SPradeep Nalla return; 1181d18ca7dfSIntiyaz Basha 1182a82457f1SIntiyaz Basha for (i = 0; i < oct->num_iqs; i++) { 1183d8ab848cSRaghu Vatsavayi iq_no = lio->linfo.txpciq[i].s.q_no; 1184d8ab848cSRaghu Vatsavayi iq_stats = &oct->instr_queue[iq_no]->stats; 1185d8ab848cSRaghu Vatsavayi pkts += iq_stats->tx_done; 1186d8ab848cSRaghu Vatsavayi drop += iq_stats->tx_dropped; 1187d8ab848cSRaghu Vatsavayi bytes += iq_stats->tx_tot_bytes; 1188d8ab848cSRaghu Vatsavayi } 1189d8ab848cSRaghu Vatsavayi 119080002347SPradeep Nalla lstats->tx_packets = pkts; 119180002347SPradeep Nalla lstats->tx_bytes = bytes; 119280002347SPradeep Nalla lstats->tx_dropped = drop; 1193d8ab848cSRaghu Vatsavayi 1194d8ab848cSRaghu Vatsavayi pkts = 0; 1195d8ab848cSRaghu Vatsavayi drop = 0; 1196d8ab848cSRaghu Vatsavayi bytes = 0; 1197d8ab848cSRaghu Vatsavayi 1198a82457f1SIntiyaz Basha for (i = 0; i < oct->num_oqs; i++) { 1199d8ab848cSRaghu Vatsavayi oq_no = lio->linfo.rxpciq[i].s.q_no; 1200d8ab848cSRaghu Vatsavayi oq_stats = &oct->droq[oq_no]->stats; 1201d8ab848cSRaghu Vatsavayi pkts += oq_stats->rx_pkts_received; 1202d8ab848cSRaghu Vatsavayi drop += (oq_stats->rx_dropped + 1203d8ab848cSRaghu Vatsavayi oq_stats->dropped_nodispatch + 1204d8ab848cSRaghu Vatsavayi oq_stats->dropped_toomany + 1205d8ab848cSRaghu Vatsavayi oq_stats->dropped_nomem); 1206d8ab848cSRaghu Vatsavayi bytes += oq_stats->rx_bytes_received; 1207d8ab848cSRaghu Vatsavayi } 1208d8ab848cSRaghu Vatsavayi 120980002347SPradeep Nalla lstats->rx_bytes = bytes; 121080002347SPradeep Nalla lstats->rx_packets = pkts; 121180002347SPradeep Nalla lstats->rx_dropped = drop; 1212d8ab848cSRaghu Vatsavayi 121380002347SPradeep Nalla lstats->multicast = oct->link_stats.fromwire.fw_total_mcast; 121480002347SPradeep Nalla 121580002347SPradeep Nalla /* detailed rx_errors: */ 121680002347SPradeep Nalla lstats->rx_length_errors = oct->link_stats.fromwire.l2_err; 121780002347SPradeep Nalla /* recved pkt with crc error */ 121880002347SPradeep Nalla lstats->rx_crc_errors = oct->link_stats.fromwire.fcs_err; 121980002347SPradeep Nalla /* recv'd frame alignment error */ 122080002347SPradeep Nalla lstats->rx_frame_errors = oct->link_stats.fromwire.frame_err; 122180002347SPradeep Nalla 122280002347SPradeep Nalla lstats->rx_errors = lstats->rx_length_errors + lstats->rx_crc_errors + 122380002347SPradeep Nalla lstats->rx_frame_errors; 122480002347SPradeep Nalla 122580002347SPradeep Nalla /* detailed tx_errors */ 122680002347SPradeep Nalla lstats->tx_aborted_errors = oct->link_stats.fromhost.fw_err_pko; 122780002347SPradeep Nalla lstats->tx_carrier_errors = oct->link_stats.fromhost.fw_err_link; 122880002347SPradeep Nalla 122980002347SPradeep Nalla lstats->tx_errors = lstats->tx_aborted_errors + 123080002347SPradeep Nalla lstats->tx_carrier_errors; 1231d8ab848cSRaghu Vatsavayi } 1232d8ab848cSRaghu Vatsavayi 1233d8ab848cSRaghu Vatsavayi /** 1234f625fe62SRaghu Vatsavayi * \brief Handler for SIOCSHWTSTAMP ioctl 1235f625fe62SRaghu Vatsavayi * @param netdev network device 1236f625fe62SRaghu Vatsavayi * @param ifr interface request 1237f625fe62SRaghu Vatsavayi * @param cmd command 1238f625fe62SRaghu Vatsavayi */ 1239f625fe62SRaghu Vatsavayi static int hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) 1240f625fe62SRaghu Vatsavayi { 1241f625fe62SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 1242f625fe62SRaghu Vatsavayi struct hwtstamp_config conf; 1243f625fe62SRaghu Vatsavayi 1244f625fe62SRaghu Vatsavayi if (copy_from_user(&conf, ifr->ifr_data, sizeof(conf))) 1245f625fe62SRaghu Vatsavayi return -EFAULT; 1246f625fe62SRaghu Vatsavayi 1247f625fe62SRaghu Vatsavayi if (conf.flags) 1248f625fe62SRaghu Vatsavayi return -EINVAL; 1249f625fe62SRaghu Vatsavayi 1250f625fe62SRaghu Vatsavayi switch (conf.tx_type) { 1251f625fe62SRaghu Vatsavayi case HWTSTAMP_TX_ON: 1252f625fe62SRaghu Vatsavayi case HWTSTAMP_TX_OFF: 1253f625fe62SRaghu Vatsavayi break; 1254f625fe62SRaghu Vatsavayi default: 1255f625fe62SRaghu Vatsavayi return -ERANGE; 1256f625fe62SRaghu Vatsavayi } 1257f625fe62SRaghu Vatsavayi 1258f625fe62SRaghu Vatsavayi switch (conf.rx_filter) { 1259f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_NONE: 1260f625fe62SRaghu Vatsavayi break; 1261f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_ALL: 1262f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_SOME: 1263f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: 1264f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: 1265f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: 1266f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: 1267f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: 1268f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: 1269f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: 1270f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: 1271f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: 1272f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V2_EVENT: 1273f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V2_SYNC: 1274f625fe62SRaghu Vatsavayi case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: 1275e3412575SMiroslav Lichvar case HWTSTAMP_FILTER_NTP_ALL: 1276f625fe62SRaghu Vatsavayi conf.rx_filter = HWTSTAMP_FILTER_ALL; 1277f625fe62SRaghu Vatsavayi break; 1278f625fe62SRaghu Vatsavayi default: 1279f625fe62SRaghu Vatsavayi return -ERANGE; 1280f625fe62SRaghu Vatsavayi } 1281f625fe62SRaghu Vatsavayi 1282f625fe62SRaghu Vatsavayi if (conf.rx_filter == HWTSTAMP_FILTER_ALL) 1283f625fe62SRaghu Vatsavayi ifstate_set(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED); 1284f625fe62SRaghu Vatsavayi 1285f625fe62SRaghu Vatsavayi else 1286f625fe62SRaghu Vatsavayi ifstate_reset(lio, LIO_IFSTATE_RX_TIMESTAMP_ENABLED); 1287f625fe62SRaghu Vatsavayi 1288f625fe62SRaghu Vatsavayi return copy_to_user(ifr->ifr_data, &conf, sizeof(conf)) ? -EFAULT : 0; 1289f625fe62SRaghu Vatsavayi } 1290f625fe62SRaghu Vatsavayi 1291f625fe62SRaghu Vatsavayi /** 1292f625fe62SRaghu Vatsavayi * \brief ioctl handler 1293f625fe62SRaghu Vatsavayi * @param netdev network device 1294f625fe62SRaghu Vatsavayi * @param ifr interface request 1295f625fe62SRaghu Vatsavayi * @param cmd command 1296f625fe62SRaghu Vatsavayi */ 1297f625fe62SRaghu Vatsavayi static int liquidio_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) 1298f625fe62SRaghu Vatsavayi { 1299f625fe62SRaghu Vatsavayi switch (cmd) { 1300f625fe62SRaghu Vatsavayi case SIOCSHWTSTAMP: 1301f625fe62SRaghu Vatsavayi return hwtstamp_ioctl(netdev, ifr); 1302f625fe62SRaghu Vatsavayi default: 1303f625fe62SRaghu Vatsavayi return -EOPNOTSUPP; 1304f625fe62SRaghu Vatsavayi } 1305f625fe62SRaghu Vatsavayi } 1306f625fe62SRaghu Vatsavayi 1307f625fe62SRaghu Vatsavayi static void handle_timestamp(struct octeon_device *oct, u32 status, void *buf) 1308f625fe62SRaghu Vatsavayi { 1309f625fe62SRaghu Vatsavayi struct sk_buff *skb = (struct sk_buff *)buf; 1310f625fe62SRaghu Vatsavayi struct octnet_buf_free_info *finfo; 1311f625fe62SRaghu Vatsavayi struct oct_timestamp_resp *resp; 1312f625fe62SRaghu Vatsavayi struct octeon_soft_command *sc; 1313f625fe62SRaghu Vatsavayi struct lio *lio; 1314f625fe62SRaghu Vatsavayi 1315f625fe62SRaghu Vatsavayi finfo = (struct octnet_buf_free_info *)skb->cb; 1316f625fe62SRaghu Vatsavayi lio = finfo->lio; 1317f625fe62SRaghu Vatsavayi sc = finfo->sc; 1318f625fe62SRaghu Vatsavayi oct = lio->oct_dev; 1319f625fe62SRaghu Vatsavayi resp = (struct oct_timestamp_resp *)sc->virtrptr; 1320f625fe62SRaghu Vatsavayi 1321f625fe62SRaghu Vatsavayi if (status != OCTEON_REQUEST_DONE) { 1322f625fe62SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Tx timestamp instruction failed. Status: %llx\n", 1323f625fe62SRaghu Vatsavayi CVM_CAST64(status)); 1324f625fe62SRaghu Vatsavayi resp->timestamp = 0; 1325f625fe62SRaghu Vatsavayi } 1326f625fe62SRaghu Vatsavayi 1327f625fe62SRaghu Vatsavayi octeon_swap_8B_data(&resp->timestamp, 1); 1328f625fe62SRaghu Vatsavayi 1329f625fe62SRaghu Vatsavayi if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) { 1330f625fe62SRaghu Vatsavayi struct skb_shared_hwtstamps ts; 1331f625fe62SRaghu Vatsavayi u64 ns = resp->timestamp; 1332f625fe62SRaghu Vatsavayi 1333f625fe62SRaghu Vatsavayi netif_info(lio, tx_done, lio->netdev, 1334f625fe62SRaghu Vatsavayi "Got resulting SKBTX_HW_TSTAMP skb=%p ns=%016llu\n", 1335f625fe62SRaghu Vatsavayi skb, (unsigned long long)ns); 1336f625fe62SRaghu Vatsavayi ts.hwtstamp = ns_to_ktime(ns + lio->ptp_adjust); 1337f625fe62SRaghu Vatsavayi skb_tstamp_tx(skb, &ts); 1338f625fe62SRaghu Vatsavayi } 1339f625fe62SRaghu Vatsavayi 1340f625fe62SRaghu Vatsavayi octeon_free_soft_command(oct, sc); 1341f625fe62SRaghu Vatsavayi tx_buffer_free(skb); 1342f625fe62SRaghu Vatsavayi } 1343f625fe62SRaghu Vatsavayi 1344f625fe62SRaghu Vatsavayi /* \brief Send a data packet that will be timestamped 1345f625fe62SRaghu Vatsavayi * @param oct octeon device 1346f625fe62SRaghu Vatsavayi * @param ndata pointer to network data 1347f625fe62SRaghu Vatsavayi * @param finfo pointer to private network data 1348f625fe62SRaghu Vatsavayi */ 1349f625fe62SRaghu Vatsavayi static int send_nic_timestamp_pkt(struct octeon_device *oct, 1350f625fe62SRaghu Vatsavayi struct octnic_data_pkt *ndata, 1351c859e21aSIntiyaz Basha struct octnet_buf_free_info *finfo, 1352c859e21aSIntiyaz Basha int xmit_more) 1353f625fe62SRaghu Vatsavayi { 1354f625fe62SRaghu Vatsavayi struct octeon_soft_command *sc; 1355f625fe62SRaghu Vatsavayi int ring_doorbell; 1356f625fe62SRaghu Vatsavayi struct lio *lio; 1357f625fe62SRaghu Vatsavayi int retval; 1358f625fe62SRaghu Vatsavayi u32 len; 1359f625fe62SRaghu Vatsavayi 1360f625fe62SRaghu Vatsavayi lio = finfo->lio; 1361f625fe62SRaghu Vatsavayi 1362f625fe62SRaghu Vatsavayi sc = octeon_alloc_soft_command_resp(oct, &ndata->cmd, 1363f625fe62SRaghu Vatsavayi sizeof(struct oct_timestamp_resp)); 1364f625fe62SRaghu Vatsavayi finfo->sc = sc; 1365f625fe62SRaghu Vatsavayi 1366f625fe62SRaghu Vatsavayi if (!sc) { 1367f625fe62SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "No memory for timestamped data packet\n"); 1368f625fe62SRaghu Vatsavayi return IQ_SEND_FAILED; 1369f625fe62SRaghu Vatsavayi } 1370f625fe62SRaghu Vatsavayi 1371f625fe62SRaghu Vatsavayi if (ndata->reqtype == REQTYPE_NORESP_NET) 1372f625fe62SRaghu Vatsavayi ndata->reqtype = REQTYPE_RESP_NET; 1373f625fe62SRaghu Vatsavayi else if (ndata->reqtype == REQTYPE_NORESP_NET_SG) 1374f625fe62SRaghu Vatsavayi ndata->reqtype = REQTYPE_RESP_NET_SG; 1375f625fe62SRaghu Vatsavayi 1376f625fe62SRaghu Vatsavayi sc->callback = handle_timestamp; 1377f625fe62SRaghu Vatsavayi sc->callback_arg = finfo->skb; 1378f625fe62SRaghu Vatsavayi sc->iq_no = ndata->q_no; 1379f625fe62SRaghu Vatsavayi 1380f625fe62SRaghu Vatsavayi len = (u32)((struct octeon_instr_ih3 *)(&sc->cmd.cmd3.ih3))->dlengsz; 1381f625fe62SRaghu Vatsavayi 1382c859e21aSIntiyaz Basha ring_doorbell = !xmit_more; 1383f625fe62SRaghu Vatsavayi 1384f625fe62SRaghu Vatsavayi retval = octeon_send_command(oct, sc->iq_no, ring_doorbell, &sc->cmd, 1385f625fe62SRaghu Vatsavayi sc, len, ndata->reqtype); 1386f625fe62SRaghu Vatsavayi 1387f625fe62SRaghu Vatsavayi if (retval == IQ_SEND_FAILED) { 1388f625fe62SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "timestamp data packet failed status: %x\n", 1389f625fe62SRaghu Vatsavayi retval); 1390f625fe62SRaghu Vatsavayi octeon_free_soft_command(oct, sc); 1391f625fe62SRaghu Vatsavayi } else { 1392f625fe62SRaghu Vatsavayi netif_info(lio, tx_queued, lio->netdev, "Queued timestamp packet\n"); 1393f625fe62SRaghu Vatsavayi } 1394f625fe62SRaghu Vatsavayi 1395f625fe62SRaghu Vatsavayi return retval; 1396f625fe62SRaghu Vatsavayi } 1397f625fe62SRaghu Vatsavayi 13989981328aSRaghu Vatsavayi /** \brief Transmit networks packets to the Octeon interface 13999981328aSRaghu Vatsavayi * @param skbuff skbuff struct to be passed to network layer. 14009981328aSRaghu Vatsavayi * @param netdev pointer to network device 14019981328aSRaghu Vatsavayi * @returns whether the packet was transmitted to the device okay or not 14029981328aSRaghu Vatsavayi * (NETDEV_TX_OK or NETDEV_TX_BUSY) 14039981328aSRaghu Vatsavayi */ 14049981328aSRaghu Vatsavayi static int liquidio_xmit(struct sk_buff *skb, struct net_device *netdev) 14059981328aSRaghu Vatsavayi { 14069981328aSRaghu Vatsavayi struct octnet_buf_free_info *finfo; 14079981328aSRaghu Vatsavayi union octnic_cmd_setup cmdsetup; 14089981328aSRaghu Vatsavayi struct octnic_data_pkt ndata; 14099981328aSRaghu Vatsavayi struct octeon_instr_irh *irh; 14109981328aSRaghu Vatsavayi struct oct_iq_stats *stats; 14119981328aSRaghu Vatsavayi struct octeon_device *oct; 14129981328aSRaghu Vatsavayi int q_idx = 0, iq_no = 0; 14139981328aSRaghu Vatsavayi union tx_info *tx_info; 1414c859e21aSIntiyaz Basha int xmit_more = 0; 14159981328aSRaghu Vatsavayi struct lio *lio; 14169981328aSRaghu Vatsavayi int status = 0; 14179981328aSRaghu Vatsavayi u64 dptr = 0; 14189981328aSRaghu Vatsavayi u32 tag = 0; 14199981328aSRaghu Vatsavayi int j; 14209981328aSRaghu Vatsavayi 14219981328aSRaghu Vatsavayi lio = GET_LIO(netdev); 14229981328aSRaghu Vatsavayi oct = lio->oct_dev; 14239981328aSRaghu Vatsavayi 1424c33c9973SIntiyaz Basha q_idx = skb_iq(lio->oct_dev, skb); 14259981328aSRaghu Vatsavayi tag = q_idx; 14269981328aSRaghu Vatsavayi iq_no = lio->linfo.txpciq[q_idx].s.q_no; 14279981328aSRaghu Vatsavayi 14289981328aSRaghu Vatsavayi stats = &oct->instr_queue[iq_no]->stats; 14299981328aSRaghu Vatsavayi 14309981328aSRaghu Vatsavayi /* Check for all conditions in which the current packet cannot be 14319981328aSRaghu Vatsavayi * transmitted. 14329981328aSRaghu Vatsavayi */ 14339981328aSRaghu Vatsavayi if (!(atomic_read(&lio->ifstate) & LIO_IFSTATE_RUNNING) || 14349981328aSRaghu Vatsavayi (!lio->linfo.link.s.link_up) || (skb->len <= 0)) { 14359981328aSRaghu Vatsavayi netif_info(lio, tx_err, lio->netdev, "Transmit failed link_status : %d\n", 14369981328aSRaghu Vatsavayi lio->linfo.link.s.link_up); 14379981328aSRaghu Vatsavayi goto lio_xmit_failed; 14389981328aSRaghu Vatsavayi } 14399981328aSRaghu Vatsavayi 14409981328aSRaghu Vatsavayi /* Use space in skb->cb to store info used to unmap and 14419981328aSRaghu Vatsavayi * free the buffers. 14429981328aSRaghu Vatsavayi */ 14439981328aSRaghu Vatsavayi finfo = (struct octnet_buf_free_info *)skb->cb; 14449981328aSRaghu Vatsavayi finfo->lio = lio; 14459981328aSRaghu Vatsavayi finfo->skb = skb; 14469981328aSRaghu Vatsavayi finfo->sc = NULL; 14479981328aSRaghu Vatsavayi 14489981328aSRaghu Vatsavayi /* Prepare the attributes for the data to be passed to OSI. */ 14499981328aSRaghu Vatsavayi memset(&ndata, 0, sizeof(struct octnic_data_pkt)); 14509981328aSRaghu Vatsavayi 14519981328aSRaghu Vatsavayi ndata.buf = finfo; 14529981328aSRaghu Vatsavayi 14539981328aSRaghu Vatsavayi ndata.q_no = iq_no; 14549981328aSRaghu Vatsavayi 14559981328aSRaghu Vatsavayi if (octnet_iq_is_full(oct, ndata.q_no)) { 14569981328aSRaghu Vatsavayi /* defer sending if queue is full */ 14579981328aSRaghu Vatsavayi netif_info(lio, tx_err, lio->netdev, "Transmit failed iq:%d full\n", 14589981328aSRaghu Vatsavayi ndata.q_no); 14599981328aSRaghu Vatsavayi stats->tx_iq_busy++; 14609981328aSRaghu Vatsavayi return NETDEV_TX_BUSY; 14619981328aSRaghu Vatsavayi } 14629981328aSRaghu Vatsavayi 14639981328aSRaghu Vatsavayi ndata.datasize = skb->len; 14649981328aSRaghu Vatsavayi 14659981328aSRaghu Vatsavayi cmdsetup.u64 = 0; 14669981328aSRaghu Vatsavayi cmdsetup.s.iq_no = iq_no; 14679981328aSRaghu Vatsavayi 1468c05ebcc8SRaghu Vatsavayi if (skb->ip_summed == CHECKSUM_PARTIAL) { 1469c05ebcc8SRaghu Vatsavayi if (skb->encapsulation) { 1470c05ebcc8SRaghu Vatsavayi cmdsetup.s.tnl_csum = 1; 1471c05ebcc8SRaghu Vatsavayi stats->tx_vxlan++; 1472c05ebcc8SRaghu Vatsavayi } else { 14739981328aSRaghu Vatsavayi cmdsetup.s.transport_csum = 1; 1474c05ebcc8SRaghu Vatsavayi } 1475c05ebcc8SRaghu Vatsavayi } 1476f625fe62SRaghu Vatsavayi if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { 1477f625fe62SRaghu Vatsavayi skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; 1478f625fe62SRaghu Vatsavayi cmdsetup.s.timestamp = 1; 1479f625fe62SRaghu Vatsavayi } 14809981328aSRaghu Vatsavayi 14819981328aSRaghu Vatsavayi if (!skb_shinfo(skb)->nr_frags) { 14829981328aSRaghu Vatsavayi cmdsetup.s.u.datasize = skb->len; 14839981328aSRaghu Vatsavayi octnet_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag); 14849981328aSRaghu Vatsavayi /* Offload checksum calculation for TCP/UDP packets */ 14859981328aSRaghu Vatsavayi dptr = dma_map_single(&oct->pci_dev->dev, 14869981328aSRaghu Vatsavayi skb->data, 14879981328aSRaghu Vatsavayi skb->len, 14889981328aSRaghu Vatsavayi DMA_TO_DEVICE); 14899981328aSRaghu Vatsavayi if (dma_mapping_error(&oct->pci_dev->dev, dptr)) { 14909981328aSRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "%s DMA mapping error 1\n", 14919981328aSRaghu Vatsavayi __func__); 14929981328aSRaghu Vatsavayi return NETDEV_TX_BUSY; 14939981328aSRaghu Vatsavayi } 14949981328aSRaghu Vatsavayi 14959981328aSRaghu Vatsavayi ndata.cmd.cmd3.dptr = dptr; 14969981328aSRaghu Vatsavayi finfo->dptr = dptr; 14979981328aSRaghu Vatsavayi ndata.reqtype = REQTYPE_NORESP_NET; 14989981328aSRaghu Vatsavayi 14999981328aSRaghu Vatsavayi } else { 15009981328aSRaghu Vatsavayi struct skb_frag_struct *frag; 15019981328aSRaghu Vatsavayi struct octnic_gather *g; 15029981328aSRaghu Vatsavayi int i, frags; 15039981328aSRaghu Vatsavayi 15049981328aSRaghu Vatsavayi spin_lock(&lio->glist_lock[q_idx]); 150585a0cd81SIntiyaz Basha g = (struct octnic_gather *) 150685a0cd81SIntiyaz Basha lio_list_delete_head(&lio->glist[q_idx]); 15079981328aSRaghu Vatsavayi spin_unlock(&lio->glist_lock[q_idx]); 15089981328aSRaghu Vatsavayi 15099981328aSRaghu Vatsavayi if (!g) { 15109981328aSRaghu Vatsavayi netif_info(lio, tx_err, lio->netdev, 15119981328aSRaghu Vatsavayi "Transmit scatter gather: glist null!\n"); 15129981328aSRaghu Vatsavayi goto lio_xmit_failed; 15139981328aSRaghu Vatsavayi } 15149981328aSRaghu Vatsavayi 15159981328aSRaghu Vatsavayi cmdsetup.s.gather = 1; 15169981328aSRaghu Vatsavayi cmdsetup.s.u.gatherptrs = (skb_shinfo(skb)->nr_frags + 1); 15179981328aSRaghu Vatsavayi octnet_prepare_pci_cmd(oct, &ndata.cmd, &cmdsetup, tag); 15189981328aSRaghu Vatsavayi 15199981328aSRaghu Vatsavayi memset(g->sg, 0, g->sg_size); 15209981328aSRaghu Vatsavayi 15219981328aSRaghu Vatsavayi g->sg[0].ptr[0] = dma_map_single(&oct->pci_dev->dev, 15229981328aSRaghu Vatsavayi skb->data, 15239981328aSRaghu Vatsavayi (skb->len - skb->data_len), 15249981328aSRaghu Vatsavayi DMA_TO_DEVICE); 15259981328aSRaghu Vatsavayi if (dma_mapping_error(&oct->pci_dev->dev, g->sg[0].ptr[0])) { 15269981328aSRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "%s DMA mapping error 2\n", 15279981328aSRaghu Vatsavayi __func__); 15289981328aSRaghu Vatsavayi return NETDEV_TX_BUSY; 15299981328aSRaghu Vatsavayi } 15309981328aSRaghu Vatsavayi add_sg_size(&g->sg[0], (skb->len - skb->data_len), 0); 15319981328aSRaghu Vatsavayi 15329981328aSRaghu Vatsavayi frags = skb_shinfo(skb)->nr_frags; 15339981328aSRaghu Vatsavayi i = 1; 15349981328aSRaghu Vatsavayi while (frags--) { 15359981328aSRaghu Vatsavayi frag = &skb_shinfo(skb)->frags[i - 1]; 15369981328aSRaghu Vatsavayi 15379981328aSRaghu Vatsavayi g->sg[(i >> 2)].ptr[(i & 3)] = 15389981328aSRaghu Vatsavayi dma_map_page(&oct->pci_dev->dev, 15399981328aSRaghu Vatsavayi frag->page.p, 15409981328aSRaghu Vatsavayi frag->page_offset, 15419981328aSRaghu Vatsavayi frag->size, 15429981328aSRaghu Vatsavayi DMA_TO_DEVICE); 15439981328aSRaghu Vatsavayi if (dma_mapping_error(&oct->pci_dev->dev, 15449981328aSRaghu Vatsavayi g->sg[i >> 2].ptr[i & 3])) { 15459981328aSRaghu Vatsavayi dma_unmap_single(&oct->pci_dev->dev, 15469981328aSRaghu Vatsavayi g->sg[0].ptr[0], 15479981328aSRaghu Vatsavayi skb->len - skb->data_len, 15489981328aSRaghu Vatsavayi DMA_TO_DEVICE); 15499981328aSRaghu Vatsavayi for (j = 1; j < i; j++) { 15509981328aSRaghu Vatsavayi frag = &skb_shinfo(skb)->frags[j - 1]; 15519981328aSRaghu Vatsavayi dma_unmap_page(&oct->pci_dev->dev, 15529981328aSRaghu Vatsavayi g->sg[j >> 2].ptr[j & 3], 15539981328aSRaghu Vatsavayi frag->size, 15549981328aSRaghu Vatsavayi DMA_TO_DEVICE); 15559981328aSRaghu Vatsavayi } 15569981328aSRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "%s DMA mapping error 3\n", 15579981328aSRaghu Vatsavayi __func__); 15589981328aSRaghu Vatsavayi return NETDEV_TX_BUSY; 15599981328aSRaghu Vatsavayi } 15609981328aSRaghu Vatsavayi 15619981328aSRaghu Vatsavayi add_sg_size(&g->sg[(i >> 2)], frag->size, (i & 3)); 15629981328aSRaghu Vatsavayi i++; 15639981328aSRaghu Vatsavayi } 15649981328aSRaghu Vatsavayi 156567e303e0SVSR Burru dptr = g->sg_dma_ptr; 15669981328aSRaghu Vatsavayi 15679981328aSRaghu Vatsavayi ndata.cmd.cmd3.dptr = dptr; 15689981328aSRaghu Vatsavayi finfo->dptr = dptr; 15699981328aSRaghu Vatsavayi finfo->g = g; 15709981328aSRaghu Vatsavayi 15719981328aSRaghu Vatsavayi ndata.reqtype = REQTYPE_NORESP_NET_SG; 15729981328aSRaghu Vatsavayi } 15739981328aSRaghu Vatsavayi 15749981328aSRaghu Vatsavayi irh = (struct octeon_instr_irh *)&ndata.cmd.cmd3.irh; 15759981328aSRaghu Vatsavayi tx_info = (union tx_info *)&ndata.cmd.cmd3.ossp[0]; 15769981328aSRaghu Vatsavayi 15779981328aSRaghu Vatsavayi if (skb_shinfo(skb)->gso_size) { 15789981328aSRaghu Vatsavayi tx_info->s.gso_size = skb_shinfo(skb)->gso_size; 15799981328aSRaghu Vatsavayi tx_info->s.gso_segs = skb_shinfo(skb)->gso_segs; 15809981328aSRaghu Vatsavayi } 15819981328aSRaghu Vatsavayi 15822135f9b1SRaghu Vatsavayi /* HW insert VLAN tag */ 15832135f9b1SRaghu Vatsavayi if (skb_vlan_tag_present(skb)) { 15842135f9b1SRaghu Vatsavayi irh->priority = skb_vlan_tag_get(skb) >> VLAN_PRIO_SHIFT; 15852135f9b1SRaghu Vatsavayi irh->vlan = skb_vlan_tag_get(skb) & VLAN_VID_MASK; 15862135f9b1SRaghu Vatsavayi } 15872135f9b1SRaghu Vatsavayi 1588c859e21aSIntiyaz Basha xmit_more = skb->xmit_more; 1589c859e21aSIntiyaz Basha 1590f625fe62SRaghu Vatsavayi if (unlikely(cmdsetup.s.timestamp)) 1591c859e21aSIntiyaz Basha status = send_nic_timestamp_pkt(oct, &ndata, finfo, xmit_more); 1592f625fe62SRaghu Vatsavayi else 1593c859e21aSIntiyaz Basha status = octnet_send_nic_data_pkt(oct, &ndata, xmit_more); 15949981328aSRaghu Vatsavayi if (status == IQ_SEND_FAILED) 15959981328aSRaghu Vatsavayi goto lio_xmit_failed; 15969981328aSRaghu Vatsavayi 15979981328aSRaghu Vatsavayi netif_info(lio, tx_queued, lio->netdev, "Transmit queued successfully\n"); 15989981328aSRaghu Vatsavayi 15999981328aSRaghu Vatsavayi if (status == IQ_SEND_STOP) { 16009981328aSRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Rcvd IQ_SEND_STOP signal; stopping IQ-%d\n", 16019981328aSRaghu Vatsavayi iq_no); 160278a202f0SIntiyaz Basha netif_stop_subqueue(netdev, q_idx); 16039981328aSRaghu Vatsavayi } 16049981328aSRaghu Vatsavayi 16059981328aSRaghu Vatsavayi netif_trans_update(netdev); 16069981328aSRaghu Vatsavayi 160780c8eae6SSatanand Burla if (tx_info->s.gso_segs) 160880c8eae6SSatanand Burla stats->tx_done += tx_info->s.gso_segs; 16099981328aSRaghu Vatsavayi else 16109981328aSRaghu Vatsavayi stats->tx_done++; 161180c8eae6SSatanand Burla stats->tx_tot_bytes += ndata.datasize; 16129981328aSRaghu Vatsavayi 16139981328aSRaghu Vatsavayi return NETDEV_TX_OK; 16149981328aSRaghu Vatsavayi 16159981328aSRaghu Vatsavayi lio_xmit_failed: 16169981328aSRaghu Vatsavayi stats->tx_dropped++; 16179981328aSRaghu Vatsavayi netif_info(lio, tx_err, lio->netdev, "IQ%d Transmit dropped:%llu\n", 16189981328aSRaghu Vatsavayi iq_no, stats->tx_dropped); 16199981328aSRaghu Vatsavayi if (dptr) 16209981328aSRaghu Vatsavayi dma_unmap_single(&oct->pci_dev->dev, dptr, 16219981328aSRaghu Vatsavayi ndata.datasize, DMA_TO_DEVICE); 1622c859e21aSIntiyaz Basha 1623c859e21aSIntiyaz Basha octeon_ring_doorbell_locked(oct, iq_no); 1624c859e21aSIntiyaz Basha 16259981328aSRaghu Vatsavayi tx_buffer_free(skb); 16269981328aSRaghu Vatsavayi return NETDEV_TX_OK; 16279981328aSRaghu Vatsavayi } 16289981328aSRaghu Vatsavayi 16299981328aSRaghu Vatsavayi /** \brief Network device Tx timeout 16309981328aSRaghu Vatsavayi * @param netdev pointer to network device 16319981328aSRaghu Vatsavayi */ 16329981328aSRaghu Vatsavayi static void liquidio_tx_timeout(struct net_device *netdev) 16339981328aSRaghu Vatsavayi { 16349981328aSRaghu Vatsavayi struct lio *lio; 16359981328aSRaghu Vatsavayi 16369981328aSRaghu Vatsavayi lio = GET_LIO(netdev); 16379981328aSRaghu Vatsavayi 16389981328aSRaghu Vatsavayi netif_info(lio, tx_err, lio->netdev, 16399981328aSRaghu Vatsavayi "Transmit timeout tx_dropped:%ld, waking up queues now!!\n", 16409981328aSRaghu Vatsavayi netdev->stats.tx_dropped); 16419981328aSRaghu Vatsavayi netif_trans_update(netdev); 1642a96d8ad3SIntiyaz Basha wake_txqs(netdev); 16439981328aSRaghu Vatsavayi } 16449981328aSRaghu Vatsavayi 16452135f9b1SRaghu Vatsavayi static int 16462135f9b1SRaghu Vatsavayi liquidio_vlan_rx_add_vid(struct net_device *netdev, 16472135f9b1SRaghu Vatsavayi __be16 proto __attribute__((unused)), u16 vid) 16482135f9b1SRaghu Vatsavayi { 16492135f9b1SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 16502135f9b1SRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 16512135f9b1SRaghu Vatsavayi struct octnic_ctrl_pkt nctrl; 16522135f9b1SRaghu Vatsavayi int ret = 0; 16532135f9b1SRaghu Vatsavayi 16542135f9b1SRaghu Vatsavayi memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); 16552135f9b1SRaghu Vatsavayi 16562135f9b1SRaghu Vatsavayi nctrl.ncmd.u64 = 0; 16572135f9b1SRaghu Vatsavayi nctrl.ncmd.s.cmd = OCTNET_CMD_ADD_VLAN_FILTER; 16582135f9b1SRaghu Vatsavayi nctrl.ncmd.s.param1 = vid; 16592135f9b1SRaghu Vatsavayi nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 16602135f9b1SRaghu Vatsavayi nctrl.netpndev = (u64)netdev; 16612135f9b1SRaghu Vatsavayi nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; 16622135f9b1SRaghu Vatsavayi 16632135f9b1SRaghu Vatsavayi ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); 1664edd572d7SFelix Manlunas if (ret) { 16652135f9b1SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Add VLAN filter failed in core (ret: 0x%x)\n", 16662135f9b1SRaghu Vatsavayi ret); 1667edd572d7SFelix Manlunas return -EPERM; 16682135f9b1SRaghu Vatsavayi } 16692135f9b1SRaghu Vatsavayi 16700c264588SFelix Manlunas return 0; 16712135f9b1SRaghu Vatsavayi } 16722135f9b1SRaghu Vatsavayi 16732135f9b1SRaghu Vatsavayi static int 16742135f9b1SRaghu Vatsavayi liquidio_vlan_rx_kill_vid(struct net_device *netdev, 16752135f9b1SRaghu Vatsavayi __be16 proto __attribute__((unused)), u16 vid) 16762135f9b1SRaghu Vatsavayi { 16772135f9b1SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 16782135f9b1SRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 16792135f9b1SRaghu Vatsavayi struct octnic_ctrl_pkt nctrl; 16802135f9b1SRaghu Vatsavayi int ret = 0; 16812135f9b1SRaghu Vatsavayi 16822135f9b1SRaghu Vatsavayi memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); 16832135f9b1SRaghu Vatsavayi 16842135f9b1SRaghu Vatsavayi nctrl.ncmd.u64 = 0; 16852135f9b1SRaghu Vatsavayi nctrl.ncmd.s.cmd = OCTNET_CMD_DEL_VLAN_FILTER; 16862135f9b1SRaghu Vatsavayi nctrl.ncmd.s.param1 = vid; 16872135f9b1SRaghu Vatsavayi nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 16882135f9b1SRaghu Vatsavayi nctrl.netpndev = (u64)netdev; 16892135f9b1SRaghu Vatsavayi nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; 16902135f9b1SRaghu Vatsavayi 16912135f9b1SRaghu Vatsavayi ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); 1692edd572d7SFelix Manlunas if (ret) { 1693fcaccc82SRick Farrington dev_err(&oct->pci_dev->dev, "Del VLAN filter failed in core (ret: 0x%x)\n", 16942135f9b1SRaghu Vatsavayi ret); 1695edd572d7SFelix Manlunas if (ret > 0) 1696edd572d7SFelix Manlunas ret = -EIO; 16972135f9b1SRaghu Vatsavayi } 16982135f9b1SRaghu Vatsavayi return ret; 16992135f9b1SRaghu Vatsavayi } 17002135f9b1SRaghu Vatsavayi 1701846b4687SRaghu Vatsavayi /** Sending command to enable/disable RX checksum offload 1702846b4687SRaghu Vatsavayi * @param netdev pointer to network device 1703846b4687SRaghu Vatsavayi * @param command OCTNET_CMD_TNL_RX_CSUM_CTL 1704846b4687SRaghu Vatsavayi * @param rx_cmd_bit OCTNET_CMD_RXCSUM_ENABLE/ 1705846b4687SRaghu Vatsavayi * OCTNET_CMD_RXCSUM_DISABLE 1706846b4687SRaghu Vatsavayi * @returns SUCCESS or FAILURE 1707846b4687SRaghu Vatsavayi */ 1708846b4687SRaghu Vatsavayi static int liquidio_set_rxcsum_command(struct net_device *netdev, int command, 1709846b4687SRaghu Vatsavayi u8 rx_cmd) 1710846b4687SRaghu Vatsavayi { 1711846b4687SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 1712846b4687SRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 1713846b4687SRaghu Vatsavayi struct octnic_ctrl_pkt nctrl; 1714846b4687SRaghu Vatsavayi int ret = 0; 1715846b4687SRaghu Vatsavayi 17160c264588SFelix Manlunas memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); 17170c264588SFelix Manlunas 1718846b4687SRaghu Vatsavayi nctrl.ncmd.u64 = 0; 1719846b4687SRaghu Vatsavayi nctrl.ncmd.s.cmd = command; 1720846b4687SRaghu Vatsavayi nctrl.ncmd.s.param1 = rx_cmd; 1721846b4687SRaghu Vatsavayi nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 1722846b4687SRaghu Vatsavayi nctrl.netpndev = (u64)netdev; 1723846b4687SRaghu Vatsavayi nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; 1724846b4687SRaghu Vatsavayi 1725846b4687SRaghu Vatsavayi ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); 1726edd572d7SFelix Manlunas if (ret) { 1727846b4687SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "DEVFLAGS RXCSUM change failed in core (ret:0x%x)\n", 1728846b4687SRaghu Vatsavayi ret); 1729edd572d7SFelix Manlunas if (ret > 0) 1730edd572d7SFelix Manlunas ret = -EIO; 1731846b4687SRaghu Vatsavayi } 1732846b4687SRaghu Vatsavayi return ret; 1733846b4687SRaghu Vatsavayi } 1734846b4687SRaghu Vatsavayi 1735c05ebcc8SRaghu Vatsavayi /** Sending command to add/delete VxLAN UDP port to firmware 1736c05ebcc8SRaghu Vatsavayi * @param netdev pointer to network device 1737c05ebcc8SRaghu Vatsavayi * @param command OCTNET_CMD_VXLAN_PORT_CONFIG 1738c05ebcc8SRaghu Vatsavayi * @param vxlan_port VxLAN port to be added or deleted 1739c05ebcc8SRaghu Vatsavayi * @param vxlan_cmd_bit OCTNET_CMD_VXLAN_PORT_ADD, 1740c05ebcc8SRaghu Vatsavayi * OCTNET_CMD_VXLAN_PORT_DEL 1741c05ebcc8SRaghu Vatsavayi * @returns SUCCESS or FAILURE 1742c05ebcc8SRaghu Vatsavayi */ 1743c05ebcc8SRaghu Vatsavayi static int liquidio_vxlan_port_command(struct net_device *netdev, int command, 1744c05ebcc8SRaghu Vatsavayi u16 vxlan_port, u8 vxlan_cmd_bit) 1745c05ebcc8SRaghu Vatsavayi { 1746c05ebcc8SRaghu Vatsavayi struct lio *lio = GET_LIO(netdev); 1747c05ebcc8SRaghu Vatsavayi struct octeon_device *oct = lio->oct_dev; 1748c05ebcc8SRaghu Vatsavayi struct octnic_ctrl_pkt nctrl; 1749c05ebcc8SRaghu Vatsavayi int ret = 0; 1750c05ebcc8SRaghu Vatsavayi 17510c264588SFelix Manlunas memset(&nctrl, 0, sizeof(struct octnic_ctrl_pkt)); 17520c264588SFelix Manlunas 1753c05ebcc8SRaghu Vatsavayi nctrl.ncmd.u64 = 0; 1754c05ebcc8SRaghu Vatsavayi nctrl.ncmd.s.cmd = command; 1755c05ebcc8SRaghu Vatsavayi nctrl.ncmd.s.more = vxlan_cmd_bit; 1756c05ebcc8SRaghu Vatsavayi nctrl.ncmd.s.param1 = vxlan_port; 1757c05ebcc8SRaghu Vatsavayi nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 1758c05ebcc8SRaghu Vatsavayi nctrl.netpndev = (u64)netdev; 1759c05ebcc8SRaghu Vatsavayi nctrl.cb_fn = liquidio_link_ctrl_cmd_completion; 1760c05ebcc8SRaghu Vatsavayi 1761c05ebcc8SRaghu Vatsavayi ret = octnet_send_nic_ctrl_pkt(lio->oct_dev, &nctrl); 1762edd572d7SFelix Manlunas if (ret) { 1763c05ebcc8SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, 1764c05ebcc8SRaghu Vatsavayi "DEVFLAGS VxLAN port add/delete failed in core (ret : 0x%x)\n", 1765c05ebcc8SRaghu Vatsavayi ret); 1766edd572d7SFelix Manlunas if (ret > 0) 1767edd572d7SFelix Manlunas ret = -EIO; 1768c05ebcc8SRaghu Vatsavayi } 1769c05ebcc8SRaghu Vatsavayi return ret; 1770c05ebcc8SRaghu Vatsavayi } 1771c05ebcc8SRaghu Vatsavayi 1772846b4687SRaghu Vatsavayi /** \brief Net device fix features 1773846b4687SRaghu Vatsavayi * @param netdev pointer to network device 1774846b4687SRaghu Vatsavayi * @param request features requested 1775846b4687SRaghu Vatsavayi * @returns updated features list 1776846b4687SRaghu Vatsavayi */ 1777846b4687SRaghu Vatsavayi static netdev_features_t liquidio_fix_features(struct net_device *netdev, 1778846b4687SRaghu Vatsavayi netdev_features_t request) 1779846b4687SRaghu Vatsavayi { 1780846b4687SRaghu Vatsavayi struct lio *lio = netdev_priv(netdev); 1781846b4687SRaghu Vatsavayi 1782846b4687SRaghu Vatsavayi if ((request & NETIF_F_RXCSUM) && 1783846b4687SRaghu Vatsavayi !(lio->dev_capability & NETIF_F_RXCSUM)) 1784846b4687SRaghu Vatsavayi request &= ~NETIF_F_RXCSUM; 1785846b4687SRaghu Vatsavayi 1786846b4687SRaghu Vatsavayi if ((request & NETIF_F_HW_CSUM) && 1787846b4687SRaghu Vatsavayi !(lio->dev_capability & NETIF_F_HW_CSUM)) 1788846b4687SRaghu Vatsavayi request &= ~NETIF_F_HW_CSUM; 1789846b4687SRaghu Vatsavayi 1790846b4687SRaghu Vatsavayi if ((request & NETIF_F_TSO) && !(lio->dev_capability & NETIF_F_TSO)) 1791846b4687SRaghu Vatsavayi request &= ~NETIF_F_TSO; 1792846b4687SRaghu Vatsavayi 1793846b4687SRaghu Vatsavayi if ((request & NETIF_F_TSO6) && !(lio->dev_capability & NETIF_F_TSO6)) 1794846b4687SRaghu Vatsavayi request &= ~NETIF_F_TSO6; 1795846b4687SRaghu Vatsavayi 1796846b4687SRaghu Vatsavayi if ((request & NETIF_F_LRO) && !(lio->dev_capability & NETIF_F_LRO)) 1797846b4687SRaghu Vatsavayi request &= ~NETIF_F_LRO; 1798846b4687SRaghu Vatsavayi 1799846b4687SRaghu Vatsavayi /* Disable LRO if RXCSUM is off */ 1800846b4687SRaghu Vatsavayi if (!(request & NETIF_F_RXCSUM) && (netdev->features & NETIF_F_LRO) && 1801846b4687SRaghu Vatsavayi (lio->dev_capability & NETIF_F_LRO)) 1802846b4687SRaghu Vatsavayi request &= ~NETIF_F_LRO; 1803846b4687SRaghu Vatsavayi 1804846b4687SRaghu Vatsavayi return request; 1805846b4687SRaghu Vatsavayi } 1806846b4687SRaghu Vatsavayi 1807846b4687SRaghu Vatsavayi /** \brief Net device set features 1808846b4687SRaghu Vatsavayi * @param netdev pointer to network device 1809846b4687SRaghu Vatsavayi * @param features features to enable/disable 1810846b4687SRaghu Vatsavayi */ 1811846b4687SRaghu Vatsavayi static int liquidio_set_features(struct net_device *netdev, 1812846b4687SRaghu Vatsavayi netdev_features_t features) 1813846b4687SRaghu Vatsavayi { 1814846b4687SRaghu Vatsavayi struct lio *lio = netdev_priv(netdev); 1815846b4687SRaghu Vatsavayi 1816846b4687SRaghu Vatsavayi if (!((netdev->features ^ features) & NETIF_F_LRO)) 1817846b4687SRaghu Vatsavayi return 0; 1818846b4687SRaghu Vatsavayi 1819846b4687SRaghu Vatsavayi if ((features & NETIF_F_LRO) && (lio->dev_capability & NETIF_F_LRO)) 1820846b4687SRaghu Vatsavayi liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE, 1821846b4687SRaghu Vatsavayi OCTNIC_LROIPV4 | OCTNIC_LROIPV6); 1822846b4687SRaghu Vatsavayi else if (!(features & NETIF_F_LRO) && 1823846b4687SRaghu Vatsavayi (lio->dev_capability & NETIF_F_LRO)) 1824846b4687SRaghu Vatsavayi liquidio_set_feature(netdev, OCTNET_CMD_LRO_DISABLE, 1825846b4687SRaghu Vatsavayi OCTNIC_LROIPV4 | OCTNIC_LROIPV6); 1826846b4687SRaghu Vatsavayi if (!(netdev->features & NETIF_F_RXCSUM) && 1827846b4687SRaghu Vatsavayi (lio->enc_dev_capability & NETIF_F_RXCSUM) && 1828846b4687SRaghu Vatsavayi (features & NETIF_F_RXCSUM)) 1829846b4687SRaghu Vatsavayi liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL, 1830846b4687SRaghu Vatsavayi OCTNET_CMD_RXCSUM_ENABLE); 1831846b4687SRaghu Vatsavayi else if ((netdev->features & NETIF_F_RXCSUM) && 1832846b4687SRaghu Vatsavayi (lio->enc_dev_capability & NETIF_F_RXCSUM) && 1833846b4687SRaghu Vatsavayi !(features & NETIF_F_RXCSUM)) 1834846b4687SRaghu Vatsavayi liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL, 1835846b4687SRaghu Vatsavayi OCTNET_CMD_RXCSUM_DISABLE); 1836846b4687SRaghu Vatsavayi 1837846b4687SRaghu Vatsavayi return 0; 1838846b4687SRaghu Vatsavayi } 1839846b4687SRaghu Vatsavayi 1840c05ebcc8SRaghu Vatsavayi static void liquidio_add_vxlan_port(struct net_device *netdev, 1841c05ebcc8SRaghu Vatsavayi struct udp_tunnel_info *ti) 1842c05ebcc8SRaghu Vatsavayi { 1843c05ebcc8SRaghu Vatsavayi if (ti->type != UDP_TUNNEL_TYPE_VXLAN) 1844c05ebcc8SRaghu Vatsavayi return; 1845c05ebcc8SRaghu Vatsavayi 1846c05ebcc8SRaghu Vatsavayi liquidio_vxlan_port_command(netdev, 1847c05ebcc8SRaghu Vatsavayi OCTNET_CMD_VXLAN_PORT_CONFIG, 1848c05ebcc8SRaghu Vatsavayi htons(ti->port), 1849c05ebcc8SRaghu Vatsavayi OCTNET_CMD_VXLAN_PORT_ADD); 1850c05ebcc8SRaghu Vatsavayi } 1851c05ebcc8SRaghu Vatsavayi 1852c05ebcc8SRaghu Vatsavayi static void liquidio_del_vxlan_port(struct net_device *netdev, 1853c05ebcc8SRaghu Vatsavayi struct udp_tunnel_info *ti) 1854c05ebcc8SRaghu Vatsavayi { 1855c05ebcc8SRaghu Vatsavayi if (ti->type != UDP_TUNNEL_TYPE_VXLAN) 1856c05ebcc8SRaghu Vatsavayi return; 1857c05ebcc8SRaghu Vatsavayi 1858c05ebcc8SRaghu Vatsavayi liquidio_vxlan_port_command(netdev, 1859c05ebcc8SRaghu Vatsavayi OCTNET_CMD_VXLAN_PORT_CONFIG, 1860c05ebcc8SRaghu Vatsavayi htons(ti->port), 1861c05ebcc8SRaghu Vatsavayi OCTNET_CMD_VXLAN_PORT_DEL); 1862c05ebcc8SRaghu Vatsavayi } 1863c05ebcc8SRaghu Vatsavayi 1864846b4687SRaghu Vatsavayi static const struct net_device_ops lionetdevops = { 18653cd25e48SRaghu Vatsavayi .ndo_open = liquidio_open, 18663cd25e48SRaghu Vatsavayi .ndo_stop = liquidio_stop, 18679981328aSRaghu Vatsavayi .ndo_start_xmit = liquidio_xmit, 186880002347SPradeep Nalla .ndo_get_stats64 = liquidio_get_stats64, 186950f7f94bSRaghu Vatsavayi .ndo_set_mac_address = liquidio_set_mac, 187050f7f94bSRaghu Vatsavayi .ndo_set_rx_mode = liquidio_set_mcast_list, 18719981328aSRaghu Vatsavayi .ndo_tx_timeout = liquidio_tx_timeout, 18722135f9b1SRaghu Vatsavayi .ndo_vlan_rx_add_vid = liquidio_vlan_rx_add_vid, 18732135f9b1SRaghu Vatsavayi .ndo_vlan_rx_kill_vid = liquidio_vlan_rx_kill_vid, 187450f7f94bSRaghu Vatsavayi .ndo_change_mtu = liquidio_change_mtu, 1875f625fe62SRaghu Vatsavayi .ndo_do_ioctl = liquidio_ioctl, 1876846b4687SRaghu Vatsavayi .ndo_fix_features = liquidio_fix_features, 1877846b4687SRaghu Vatsavayi .ndo_set_features = liquidio_set_features, 1878c05ebcc8SRaghu Vatsavayi .ndo_udp_tunnel_add = liquidio_add_vxlan_port, 1879c05ebcc8SRaghu Vatsavayi .ndo_udp_tunnel_del = liquidio_del_vxlan_port, 1880846b4687SRaghu Vatsavayi }; 1881846b4687SRaghu Vatsavayi 18823cd25e48SRaghu Vatsavayi static int lio_nic_info(struct octeon_recv_info *recv_info, void *buf) 18833cd25e48SRaghu Vatsavayi { 18843cd25e48SRaghu Vatsavayi struct octeon_device *oct = (struct octeon_device *)buf; 18853cd25e48SRaghu Vatsavayi struct octeon_recv_pkt *recv_pkt = recv_info->recv_pkt; 18863cd25e48SRaghu Vatsavayi union oct_link_status *ls; 18873cd25e48SRaghu Vatsavayi int gmxport = 0; 18883cd25e48SRaghu Vatsavayi int i; 18893cd25e48SRaghu Vatsavayi 1890c4ee5d81SPrasad Kanneganti if (recv_pkt->buffer_size[0] != (sizeof(*ls) + OCT_DROQ_INFO_SIZE)) { 18913cd25e48SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Malformed NIC_INFO, len=%d, ifidx=%d\n", 18923cd25e48SRaghu Vatsavayi recv_pkt->buffer_size[0], 18933cd25e48SRaghu Vatsavayi recv_pkt->rh.r_nic_info.gmxport); 18943cd25e48SRaghu Vatsavayi goto nic_info_err; 18953cd25e48SRaghu Vatsavayi } 18963cd25e48SRaghu Vatsavayi 18973cd25e48SRaghu Vatsavayi gmxport = recv_pkt->rh.r_nic_info.gmxport; 1898c4ee5d81SPrasad Kanneganti ls = (union oct_link_status *)(get_rbd(recv_pkt->buffer_ptr[0]) + 1899c4ee5d81SPrasad Kanneganti OCT_DROQ_INFO_SIZE); 19003cd25e48SRaghu Vatsavayi 19013cd25e48SRaghu Vatsavayi octeon_swap_8B_data((u64 *)ls, (sizeof(union oct_link_status)) >> 3); 19023cd25e48SRaghu Vatsavayi 19033cd25e48SRaghu Vatsavayi for (i = 0; i < oct->ifcount; i++) { 19043cd25e48SRaghu Vatsavayi if (oct->props[i].gmxport == gmxport) { 19053cd25e48SRaghu Vatsavayi update_link_status(oct->props[i].netdev, ls); 19063cd25e48SRaghu Vatsavayi break; 19073cd25e48SRaghu Vatsavayi } 19083cd25e48SRaghu Vatsavayi } 19093cd25e48SRaghu Vatsavayi 19103cd25e48SRaghu Vatsavayi nic_info_err: 19113cd25e48SRaghu Vatsavayi for (i = 0; i < recv_pkt->buffer_count; i++) 19123cd25e48SRaghu Vatsavayi recv_buffer_free(recv_pkt->buffer_ptr[i]); 19133cd25e48SRaghu Vatsavayi octeon_free_recv_info(recv_info); 19143cd25e48SRaghu Vatsavayi return 0; 19153cd25e48SRaghu Vatsavayi } 19163cd25e48SRaghu Vatsavayi 1917846b4687SRaghu Vatsavayi /** 1918846b4687SRaghu Vatsavayi * \brief Setup network interfaces 1919846b4687SRaghu Vatsavayi * @param octeon_dev octeon device 1920846b4687SRaghu Vatsavayi * 1921846b4687SRaghu Vatsavayi * Called during init time for each device. It assumes the NIC 1922846b4687SRaghu Vatsavayi * is already up and running. The link information for each 1923846b4687SRaghu Vatsavayi * interface is passed in link_info. 1924846b4687SRaghu Vatsavayi */ 1925846b4687SRaghu Vatsavayi static int setup_nic_devices(struct octeon_device *octeon_dev) 1926846b4687SRaghu Vatsavayi { 1927846b4687SRaghu Vatsavayi int retval, num_iqueues, num_oqueues; 192864fecd3eSFelix Manlunas u32 resp_size, data_size; 1929846b4687SRaghu Vatsavayi struct liquidio_if_cfg_resp *resp; 1930846b4687SRaghu Vatsavayi struct octeon_soft_command *sc; 1931846b4687SRaghu Vatsavayi union oct_nic_if_cfg if_cfg; 1932846b4687SRaghu Vatsavayi struct octdev_props *props; 1933846b4687SRaghu Vatsavayi struct net_device *netdev; 1934846b4687SRaghu Vatsavayi struct lio_version *vdata; 1935846b4687SRaghu Vatsavayi struct lio *lio = NULL; 1936846b4687SRaghu Vatsavayi u8 mac[ETH_ALEN], i, j; 1937846b4687SRaghu Vatsavayi u32 ifidx_or_pfnum; 1938846b4687SRaghu Vatsavayi 1939846b4687SRaghu Vatsavayi ifidx_or_pfnum = octeon_dev->pf_num; 1940846b4687SRaghu Vatsavayi 19413cd25e48SRaghu Vatsavayi /* This is to handle link status changes */ 19423cd25e48SRaghu Vatsavayi octeon_register_dispatch_fn(octeon_dev, OPCODE_NIC, OPCODE_NIC_INFO, 19433cd25e48SRaghu Vatsavayi lio_nic_info, octeon_dev); 19443cd25e48SRaghu Vatsavayi 19459bdca5c6SRaghu Vatsavayi /* REQTYPE_RESP_NET and REQTYPE_SOFT_COMMAND do not have free functions. 19469bdca5c6SRaghu Vatsavayi * They are handled directly. 19479bdca5c6SRaghu Vatsavayi */ 19489bdca5c6SRaghu Vatsavayi octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_NORESP_NET, 19499bdca5c6SRaghu Vatsavayi free_netbuf); 19509bdca5c6SRaghu Vatsavayi 19519bdca5c6SRaghu Vatsavayi octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_NORESP_NET_SG, 19529bdca5c6SRaghu Vatsavayi free_netsgbuf); 19539bdca5c6SRaghu Vatsavayi 19549bdca5c6SRaghu Vatsavayi octeon_register_reqtype_free_fn(octeon_dev, REQTYPE_RESP_NET_SG, 19559bdca5c6SRaghu Vatsavayi free_netsgbuf_with_resp); 19569bdca5c6SRaghu Vatsavayi 1957846b4687SRaghu Vatsavayi for (i = 0; i < octeon_dev->ifcount; i++) { 1958846b4687SRaghu Vatsavayi resp_size = sizeof(struct liquidio_if_cfg_resp); 1959846b4687SRaghu Vatsavayi data_size = sizeof(struct lio_version); 1960846b4687SRaghu Vatsavayi sc = (struct octeon_soft_command *) 1961846b4687SRaghu Vatsavayi octeon_alloc_soft_command(octeon_dev, data_size, 196264fecd3eSFelix Manlunas resp_size, 0); 1963846b4687SRaghu Vatsavayi resp = (struct liquidio_if_cfg_resp *)sc->virtrptr; 1964846b4687SRaghu Vatsavayi vdata = (struct lio_version *)sc->virtdptr; 1965846b4687SRaghu Vatsavayi 1966846b4687SRaghu Vatsavayi *((u64 *)vdata) = 0; 1967846b4687SRaghu Vatsavayi vdata->major = cpu_to_be16(LIQUIDIO_BASE_MAJOR_VERSION); 1968846b4687SRaghu Vatsavayi vdata->minor = cpu_to_be16(LIQUIDIO_BASE_MINOR_VERSION); 1969846b4687SRaghu Vatsavayi vdata->micro = cpu_to_be16(LIQUIDIO_BASE_MICRO_VERSION); 1970846b4687SRaghu Vatsavayi 1971846b4687SRaghu Vatsavayi if_cfg.u64 = 0; 1972846b4687SRaghu Vatsavayi 1973846b4687SRaghu Vatsavayi if_cfg.s.num_iqueues = octeon_dev->sriov_info.rings_per_vf; 1974846b4687SRaghu Vatsavayi if_cfg.s.num_oqueues = octeon_dev->sriov_info.rings_per_vf; 1975846b4687SRaghu Vatsavayi if_cfg.s.base_queue = 0; 1976846b4687SRaghu Vatsavayi 1977846b4687SRaghu Vatsavayi sc->iq_no = 0; 1978846b4687SRaghu Vatsavayi 1979846b4687SRaghu Vatsavayi octeon_prepare_soft_command(octeon_dev, sc, OPCODE_NIC, 1980846b4687SRaghu Vatsavayi OPCODE_NIC_IF_CFG, 0, if_cfg.u64, 1981846b4687SRaghu Vatsavayi 0); 1982846b4687SRaghu Vatsavayi 198364fecd3eSFelix Manlunas init_completion(&sc->complete); 198464fecd3eSFelix Manlunas sc->sc_status = OCTEON_REQUEST_PENDING; 1985846b4687SRaghu Vatsavayi 1986846b4687SRaghu Vatsavayi retval = octeon_send_soft_command(octeon_dev, sc); 1987846b4687SRaghu Vatsavayi if (retval == IQ_SEND_FAILED) { 1988846b4687SRaghu Vatsavayi dev_err(&octeon_dev->pci_dev->dev, 1989846b4687SRaghu Vatsavayi "iq/oq config failed status: %x\n", retval); 1990846b4687SRaghu Vatsavayi /* Soft instr is freed by driver in case of failure. */ 199164fecd3eSFelix Manlunas octeon_free_soft_command(octeon_dev, sc); 199264fecd3eSFelix Manlunas return(-EIO); 1993846b4687SRaghu Vatsavayi } 1994846b4687SRaghu Vatsavayi 1995846b4687SRaghu Vatsavayi /* Sleep on a wait queue till the cond flag indicates that the 1996846b4687SRaghu Vatsavayi * response arrived or timed-out. 1997846b4687SRaghu Vatsavayi */ 199864fecd3eSFelix Manlunas retval = wait_for_sc_completion_timeout(octeon_dev, sc, 0); 199964fecd3eSFelix Manlunas if (retval) 200064fecd3eSFelix Manlunas return retval; 2001846b4687SRaghu Vatsavayi 2002846b4687SRaghu Vatsavayi retval = resp->status; 2003846b4687SRaghu Vatsavayi if (retval) { 200464fecd3eSFelix Manlunas dev_err(&octeon_dev->pci_dev->dev, 200564fecd3eSFelix Manlunas "iq/oq config failed, retval = %d\n", retval); 200664fecd3eSFelix Manlunas WRITE_ONCE(sc->caller_is_done, true); 200764fecd3eSFelix Manlunas return -EIO; 2008846b4687SRaghu Vatsavayi } 2009846b4687SRaghu Vatsavayi 201064fecd3eSFelix Manlunas snprintf(octeon_dev->fw_info.liquidio_firmware_version, 201164fecd3eSFelix Manlunas 32, "%s", 201264fecd3eSFelix Manlunas resp->cfg_info.liquidio_firmware_version); 201364fecd3eSFelix Manlunas 2014846b4687SRaghu Vatsavayi octeon_swap_8B_data((u64 *)(&resp->cfg_info), 2015846b4687SRaghu Vatsavayi (sizeof(struct liquidio_if_cfg_info)) >> 3); 2016846b4687SRaghu Vatsavayi 2017846b4687SRaghu Vatsavayi num_iqueues = hweight64(resp->cfg_info.iqmask); 2018846b4687SRaghu Vatsavayi num_oqueues = hweight64(resp->cfg_info.oqmask); 2019846b4687SRaghu Vatsavayi 2020846b4687SRaghu Vatsavayi if (!(num_iqueues) || !(num_oqueues)) { 2021846b4687SRaghu Vatsavayi dev_err(&octeon_dev->pci_dev->dev, 2022846b4687SRaghu Vatsavayi "Got bad iqueues (%016llx) or oqueues (%016llx) from firmware.\n", 2023846b4687SRaghu Vatsavayi resp->cfg_info.iqmask, resp->cfg_info.oqmask); 202464fecd3eSFelix Manlunas WRITE_ONCE(sc->caller_is_done, true); 202564fecd3eSFelix Manlunas goto setup_nic_dev_done; 2026846b4687SRaghu Vatsavayi } 2027846b4687SRaghu Vatsavayi dev_dbg(&octeon_dev->pci_dev->dev, 2028846b4687SRaghu Vatsavayi "interface %d, iqmask %016llx, oqmask %016llx, numiqueues %d, numoqueues %d\n", 2029846b4687SRaghu Vatsavayi i, resp->cfg_info.iqmask, resp->cfg_info.oqmask, 2030846b4687SRaghu Vatsavayi num_iqueues, num_oqueues); 2031846b4687SRaghu Vatsavayi 2032846b4687SRaghu Vatsavayi netdev = alloc_etherdev_mq(LIO_SIZE, num_iqueues); 2033846b4687SRaghu Vatsavayi 2034846b4687SRaghu Vatsavayi if (!netdev) { 2035846b4687SRaghu Vatsavayi dev_err(&octeon_dev->pci_dev->dev, "Device allocation failed\n"); 203664fecd3eSFelix Manlunas WRITE_ONCE(sc->caller_is_done, true); 203764fecd3eSFelix Manlunas goto setup_nic_dev_done; 2038846b4687SRaghu Vatsavayi } 2039846b4687SRaghu Vatsavayi 2040846b4687SRaghu Vatsavayi SET_NETDEV_DEV(netdev, &octeon_dev->pci_dev->dev); 2041846b4687SRaghu Vatsavayi 2042846b4687SRaghu Vatsavayi /* Associate the routines that will handle different 2043846b4687SRaghu Vatsavayi * netdev tasks. 2044846b4687SRaghu Vatsavayi */ 2045846b4687SRaghu Vatsavayi netdev->netdev_ops = &lionetdevops; 2046846b4687SRaghu Vatsavayi 2047846b4687SRaghu Vatsavayi lio = GET_LIO(netdev); 2048846b4687SRaghu Vatsavayi 2049846b4687SRaghu Vatsavayi memset(lio, 0, sizeof(struct lio)); 2050846b4687SRaghu Vatsavayi 2051846b4687SRaghu Vatsavayi lio->ifidx = ifidx_or_pfnum; 2052846b4687SRaghu Vatsavayi 2053846b4687SRaghu Vatsavayi props = &octeon_dev->props[i]; 2054846b4687SRaghu Vatsavayi props->gmxport = resp->cfg_info.linfo.gmxport; 2055846b4687SRaghu Vatsavayi props->netdev = netdev; 2056846b4687SRaghu Vatsavayi 2057846b4687SRaghu Vatsavayi lio->linfo.num_rxpciq = num_oqueues; 2058846b4687SRaghu Vatsavayi lio->linfo.num_txpciq = num_iqueues; 2059846b4687SRaghu Vatsavayi 2060846b4687SRaghu Vatsavayi for (j = 0; j < num_oqueues; j++) { 2061846b4687SRaghu Vatsavayi lio->linfo.rxpciq[j].u64 = 2062846b4687SRaghu Vatsavayi resp->cfg_info.linfo.rxpciq[j].u64; 2063846b4687SRaghu Vatsavayi } 2064846b4687SRaghu Vatsavayi for (j = 0; j < num_iqueues; j++) { 2065846b4687SRaghu Vatsavayi lio->linfo.txpciq[j].u64 = 2066846b4687SRaghu Vatsavayi resp->cfg_info.linfo.txpciq[j].u64; 2067846b4687SRaghu Vatsavayi } 2068846b4687SRaghu Vatsavayi 2069846b4687SRaghu Vatsavayi lio->linfo.hw_addr = resp->cfg_info.linfo.hw_addr; 2070846b4687SRaghu Vatsavayi lio->linfo.gmxport = resp->cfg_info.linfo.gmxport; 2071846b4687SRaghu Vatsavayi lio->linfo.link.u64 = resp->cfg_info.linfo.link.u64; 2072846b4687SRaghu Vatsavayi lio->linfo.macaddr_is_admin_asgnd = 2073846b4687SRaghu Vatsavayi resp->cfg_info.linfo.macaddr_is_admin_asgnd; 207448875222SWeilin Chang lio->linfo.macaddr_spoofchk = 207548875222SWeilin Chang resp->cfg_info.linfo.macaddr_spoofchk; 2076846b4687SRaghu Vatsavayi 2077846b4687SRaghu Vatsavayi lio->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); 2078846b4687SRaghu Vatsavayi 2079846b4687SRaghu Vatsavayi lio->dev_capability = NETIF_F_HIGHDMA 2080846b4687SRaghu Vatsavayi | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM 2081846b4687SRaghu Vatsavayi | NETIF_F_SG | NETIF_F_RXCSUM 2082846b4687SRaghu Vatsavayi | NETIF_F_TSO | NETIF_F_TSO6 2083846b4687SRaghu Vatsavayi | NETIF_F_GRO 2084846b4687SRaghu Vatsavayi | NETIF_F_LRO; 2085846b4687SRaghu Vatsavayi netif_set_gso_max_size(netdev, OCTNIC_GSO_MAX_SIZE); 2086846b4687SRaghu Vatsavayi 2087c05ebcc8SRaghu Vatsavayi /* Copy of transmit encapsulation capabilities: 2088c05ebcc8SRaghu Vatsavayi * TSO, TSO6, Checksums for this device 2089c05ebcc8SRaghu Vatsavayi */ 2090c05ebcc8SRaghu Vatsavayi lio->enc_dev_capability = NETIF_F_IP_CSUM 2091c05ebcc8SRaghu Vatsavayi | NETIF_F_IPV6_CSUM 2092c05ebcc8SRaghu Vatsavayi | NETIF_F_GSO_UDP_TUNNEL 2093c05ebcc8SRaghu Vatsavayi | NETIF_F_HW_CSUM | NETIF_F_SG 2094c05ebcc8SRaghu Vatsavayi | NETIF_F_RXCSUM 2095c05ebcc8SRaghu Vatsavayi | NETIF_F_TSO | NETIF_F_TSO6 2096c05ebcc8SRaghu Vatsavayi | NETIF_F_LRO; 2097c05ebcc8SRaghu Vatsavayi 2098c05ebcc8SRaghu Vatsavayi netdev->hw_enc_features = 2099c05ebcc8SRaghu Vatsavayi (lio->enc_dev_capability & ~NETIF_F_LRO); 21002135f9b1SRaghu Vatsavayi netdev->vlan_features = lio->dev_capability; 21012135f9b1SRaghu Vatsavayi /* Add any unchangeable hw features */ 21022135f9b1SRaghu Vatsavayi lio->dev_capability |= NETIF_F_HW_VLAN_CTAG_FILTER | 21032135f9b1SRaghu Vatsavayi NETIF_F_HW_VLAN_CTAG_RX | 21042135f9b1SRaghu Vatsavayi NETIF_F_HW_VLAN_CTAG_TX; 21052135f9b1SRaghu Vatsavayi 2106846b4687SRaghu Vatsavayi netdev->features = (lio->dev_capability & ~NETIF_F_LRO); 2107846b4687SRaghu Vatsavayi 2108846b4687SRaghu Vatsavayi netdev->hw_features = lio->dev_capability; 2109795d8098SRaghu Vatsavayi netdev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX; 2110846b4687SRaghu Vatsavayi 211150f7f94bSRaghu Vatsavayi /* MTU range: 68 - 16000 */ 211250f7f94bSRaghu Vatsavayi netdev->min_mtu = LIO_MIN_MTU_SIZE; 211350f7f94bSRaghu Vatsavayi netdev->max_mtu = LIO_MAX_MTU_SIZE; 211450f7f94bSRaghu Vatsavayi 211564fecd3eSFelix Manlunas WRITE_ONCE(sc->caller_is_done, true); 211664fecd3eSFelix Manlunas 2117846b4687SRaghu Vatsavayi /* Point to the properties for octeon device to which this 2118846b4687SRaghu Vatsavayi * interface belongs. 2119846b4687SRaghu Vatsavayi */ 2120846b4687SRaghu Vatsavayi lio->oct_dev = octeon_dev; 2121846b4687SRaghu Vatsavayi lio->octprops = props; 2122846b4687SRaghu Vatsavayi lio->netdev = netdev; 2123846b4687SRaghu Vatsavayi 2124846b4687SRaghu Vatsavayi dev_dbg(&octeon_dev->pci_dev->dev, 2125846b4687SRaghu Vatsavayi "if%d gmx: %d hw_addr: 0x%llx\n", i, 2126846b4687SRaghu Vatsavayi lio->linfo.gmxport, CVM_CAST64(lio->linfo.hw_addr)); 2127846b4687SRaghu Vatsavayi 2128846b4687SRaghu Vatsavayi /* 64-bit swap required on LE machines */ 2129846b4687SRaghu Vatsavayi octeon_swap_8B_data(&lio->linfo.hw_addr, 1); 2130846b4687SRaghu Vatsavayi for (j = 0; j < ETH_ALEN; j++) 2131846b4687SRaghu Vatsavayi mac[j] = *((u8 *)(((u8 *)&lio->linfo.hw_addr) + 2 + j)); 2132846b4687SRaghu Vatsavayi 2133846b4687SRaghu Vatsavayi /* Copy MAC Address to OS network device structure */ 2134846b4687SRaghu Vatsavayi ether_addr_copy(netdev->dev_addr, mac); 2135846b4687SRaghu Vatsavayi 2136a82457f1SIntiyaz Basha if (liquidio_setup_io_queues(octeon_dev, i, 2137a82457f1SIntiyaz Basha lio->linfo.num_txpciq, 2138a82457f1SIntiyaz Basha lio->linfo.num_rxpciq)) { 21399981328aSRaghu Vatsavayi dev_err(&octeon_dev->pci_dev->dev, "I/O queues creation failed\n"); 214064fecd3eSFelix Manlunas goto setup_nic_dev_free; 21419981328aSRaghu Vatsavayi } 21429981328aSRaghu Vatsavayi 21439217c3cfSRaghu Vatsavayi ifstate_set(lio, LIO_IFSTATE_DROQ_OPS); 21449217c3cfSRaghu Vatsavayi 21459981328aSRaghu Vatsavayi /* For VFs, enable Octeon device interrupts here, 21469981328aSRaghu Vatsavayi * as this is contingent upon IO queue setup 21479981328aSRaghu Vatsavayi */ 21489981328aSRaghu Vatsavayi octeon_dev->fn_list.enable_interrupt(octeon_dev, 21499981328aSRaghu Vatsavayi OCTEON_ALL_INTR); 21509981328aSRaghu Vatsavayi 21519981328aSRaghu Vatsavayi /* By default all interfaces on a single Octeon uses the same 21529981328aSRaghu Vatsavayi * tx and rx queues 21539981328aSRaghu Vatsavayi */ 21549981328aSRaghu Vatsavayi lio->txq = lio->linfo.txpciq[0].s.q_no; 21559217c3cfSRaghu Vatsavayi lio->rxq = lio->linfo.rxpciq[0].s.q_no; 21569981328aSRaghu Vatsavayi 21579981328aSRaghu Vatsavayi lio->tx_qsize = octeon_get_tx_qsize(octeon_dev, lio->txq); 21589217c3cfSRaghu Vatsavayi lio->rx_qsize = octeon_get_rx_qsize(octeon_dev, lio->rxq); 21599981328aSRaghu Vatsavayi 2160128ea394SIntiyaz Basha if (lio_setup_glists(octeon_dev, lio, num_iqueues)) { 2161beea50a5SRaghu Vatsavayi dev_err(&octeon_dev->pci_dev->dev, 2162beea50a5SRaghu Vatsavayi "Gather list allocation failed\n"); 216364fecd3eSFelix Manlunas goto setup_nic_dev_free; 2164beea50a5SRaghu Vatsavayi } 2165beea50a5SRaghu Vatsavayi 2166d8ab848cSRaghu Vatsavayi /* Register ethtool support */ 2167d8ab848cSRaghu Vatsavayi liquidio_set_ethtool_ops(netdev); 2168d8ab848cSRaghu Vatsavayi if (lio->oct_dev->chip_id == OCTEON_CN23XX_VF_VID) 2169d8ab848cSRaghu Vatsavayi octeon_dev->priv_flags = OCT_PRIV_FLAG_DEFAULT; 2170d8ab848cSRaghu Vatsavayi else 2171d8ab848cSRaghu Vatsavayi octeon_dev->priv_flags = 0x0; 2172d8ab848cSRaghu Vatsavayi 2173846b4687SRaghu Vatsavayi if (netdev->features & NETIF_F_LRO) 2174846b4687SRaghu Vatsavayi liquidio_set_feature(netdev, OCTNET_CMD_LRO_ENABLE, 2175846b4687SRaghu Vatsavayi OCTNIC_LROIPV4 | OCTNIC_LROIPV6); 2176846b4687SRaghu Vatsavayi 21773cd25e48SRaghu Vatsavayi if (setup_link_status_change_wq(netdev)) 217864fecd3eSFelix Manlunas goto setup_nic_dev_free; 21793cd25e48SRaghu Vatsavayi 2180031d4f12SSatanand Burla if (setup_rx_oom_poll_fn(netdev)) 218164fecd3eSFelix Manlunas goto setup_nic_dev_free; 2182031d4f12SSatanand Burla 2183846b4687SRaghu Vatsavayi /* Register the network device with the OS */ 2184846b4687SRaghu Vatsavayi if (register_netdev(netdev)) { 2185846b4687SRaghu Vatsavayi dev_err(&octeon_dev->pci_dev->dev, "Device registration failed\n"); 218664fecd3eSFelix Manlunas goto setup_nic_dev_free; 2187846b4687SRaghu Vatsavayi } 2188846b4687SRaghu Vatsavayi 2189846b4687SRaghu Vatsavayi dev_dbg(&octeon_dev->pci_dev->dev, 2190846b4687SRaghu Vatsavayi "Setup NIC ifidx:%d mac:%02x%02x%02x%02x%02x%02x\n", 2191846b4687SRaghu Vatsavayi i, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 2192846b4687SRaghu Vatsavayi netif_carrier_off(netdev); 2193846b4687SRaghu Vatsavayi lio->link_changes++; 2194846b4687SRaghu Vatsavayi 2195846b4687SRaghu Vatsavayi ifstate_set(lio, LIO_IFSTATE_REGISTERED); 2196846b4687SRaghu Vatsavayi 2197846b4687SRaghu Vatsavayi /* Sending command to firmware to enable Rx checksum offload 2198846b4687SRaghu Vatsavayi * by default at the time of setup of Liquidio driver for 2199846b4687SRaghu Vatsavayi * this device 2200846b4687SRaghu Vatsavayi */ 2201846b4687SRaghu Vatsavayi liquidio_set_rxcsum_command(netdev, OCTNET_CMD_TNL_RX_CSUM_CTL, 2202846b4687SRaghu Vatsavayi OCTNET_CMD_RXCSUM_ENABLE); 2203846b4687SRaghu Vatsavayi liquidio_set_feature(netdev, OCTNET_CMD_TNL_TX_CSUM_CTL, 2204846b4687SRaghu Vatsavayi OCTNET_CMD_TXCSUM_ENABLE); 2205846b4687SRaghu Vatsavayi 2206846b4687SRaghu Vatsavayi dev_dbg(&octeon_dev->pci_dev->dev, 2207846b4687SRaghu Vatsavayi "NIC ifidx:%d Setup successful\n", i); 2208846b4687SRaghu Vatsavayi 220918b338f5SWeilin Chang octeon_dev->no_speed_setting = 1; 2210846b4687SRaghu Vatsavayi } 2211846b4687SRaghu Vatsavayi 2212846b4687SRaghu Vatsavayi return 0; 2213846b4687SRaghu Vatsavayi 221464fecd3eSFelix Manlunas setup_nic_dev_free: 2215846b4687SRaghu Vatsavayi 2216846b4687SRaghu Vatsavayi while (i--) { 2217846b4687SRaghu Vatsavayi dev_err(&octeon_dev->pci_dev->dev, 2218846b4687SRaghu Vatsavayi "NIC ifidx:%d Setup failed\n", i); 2219846b4687SRaghu Vatsavayi liquidio_destroy_nic_device(octeon_dev, i); 2220846b4687SRaghu Vatsavayi } 222164fecd3eSFelix Manlunas 222264fecd3eSFelix Manlunas setup_nic_dev_done: 222364fecd3eSFelix Manlunas 2224846b4687SRaghu Vatsavayi return -ENODEV; 2225846b4687SRaghu Vatsavayi } 2226846b4687SRaghu Vatsavayi 2227846b4687SRaghu Vatsavayi /** 2228846b4687SRaghu Vatsavayi * \brief initialize the NIC 2229846b4687SRaghu Vatsavayi * @param oct octeon device 2230846b4687SRaghu Vatsavayi * 2231846b4687SRaghu Vatsavayi * This initialization routine is called once the Octeon device application is 2232846b4687SRaghu Vatsavayi * up and running 2233846b4687SRaghu Vatsavayi */ 2234846b4687SRaghu Vatsavayi static int liquidio_init_nic_module(struct octeon_device *oct) 2235846b4687SRaghu Vatsavayi { 2236846b4687SRaghu Vatsavayi int num_nic_ports = 1; 2237846b4687SRaghu Vatsavayi int i, retval = 0; 2238846b4687SRaghu Vatsavayi 2239846b4687SRaghu Vatsavayi dev_dbg(&oct->pci_dev->dev, "Initializing network interfaces\n"); 2240846b4687SRaghu Vatsavayi 2241846b4687SRaghu Vatsavayi /* only default iq and oq were initialized 2242846b4687SRaghu Vatsavayi * initialize the rest as well run port_config command for each port 2243846b4687SRaghu Vatsavayi */ 2244846b4687SRaghu Vatsavayi oct->ifcount = num_nic_ports; 2245846b4687SRaghu Vatsavayi memset(oct->props, 0, 2246846b4687SRaghu Vatsavayi sizeof(struct octdev_props) * num_nic_ports); 2247846b4687SRaghu Vatsavayi 2248846b4687SRaghu Vatsavayi for (i = 0; i < MAX_OCTEON_LINKS; i++) 2249846b4687SRaghu Vatsavayi oct->props[i].gmxport = -1; 2250846b4687SRaghu Vatsavayi 2251846b4687SRaghu Vatsavayi retval = setup_nic_devices(oct); 2252846b4687SRaghu Vatsavayi if (retval) { 2253846b4687SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Setup NIC devices failed\n"); 2254846b4687SRaghu Vatsavayi goto octnet_init_failure; 2255846b4687SRaghu Vatsavayi } 2256846b4687SRaghu Vatsavayi 2257d8ab848cSRaghu Vatsavayi dev_dbg(&oct->pci_dev->dev, "Network interfaces ready\n"); 2258d8ab848cSRaghu Vatsavayi 2259d8ab848cSRaghu Vatsavayi return retval; 2260d8ab848cSRaghu Vatsavayi 2261846b4687SRaghu Vatsavayi octnet_init_failure: 2262846b4687SRaghu Vatsavayi 2263846b4687SRaghu Vatsavayi oct->ifcount = 0; 2264846b4687SRaghu Vatsavayi 2265846b4687SRaghu Vatsavayi return retval; 2266846b4687SRaghu Vatsavayi } 2267846b4687SRaghu Vatsavayi 2268846b4687SRaghu Vatsavayi /** 226969c69da3SRaghu Vatsavayi * \brief Device initialization for each Octeon device that is probed 227069c69da3SRaghu Vatsavayi * @param octeon_dev octeon device 227169c69da3SRaghu Vatsavayi */ 227269c69da3SRaghu Vatsavayi static int octeon_device_init(struct octeon_device *oct) 227369c69da3SRaghu Vatsavayi { 227469c69da3SRaghu Vatsavayi u32 rev_id; 2275b3c35973SRaghu Vatsavayi int j; 227669c69da3SRaghu Vatsavayi 227769c69da3SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_BEGIN_STATE); 227869c69da3SRaghu Vatsavayi 227969c69da3SRaghu Vatsavayi /* Enable access to the octeon device and make its DMA capability 228069c69da3SRaghu Vatsavayi * known to the OS. 228169c69da3SRaghu Vatsavayi */ 228269c69da3SRaghu Vatsavayi if (octeon_pci_os_setup(oct)) 228369c69da3SRaghu Vatsavayi return 1; 228469c69da3SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_PCI_ENABLE_DONE); 228569c69da3SRaghu Vatsavayi 228669c69da3SRaghu Vatsavayi oct->chip_id = OCTEON_CN23XX_VF_VID; 228769c69da3SRaghu Vatsavayi pci_read_config_dword(oct->pci_dev, 8, &rev_id); 228869c69da3SRaghu Vatsavayi oct->rev_id = rev_id & 0xff; 228969c69da3SRaghu Vatsavayi 229069c69da3SRaghu Vatsavayi if (cn23xx_setup_octeon_vf_device(oct)) 229169c69da3SRaghu Vatsavayi return 1; 229269c69da3SRaghu Vatsavayi 229369c69da3SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_PCI_MAP_DONE); 229469c69da3SRaghu Vatsavayi 2295846b4687SRaghu Vatsavayi oct->app_mode = CVM_DRV_NIC_APP; 2296846b4687SRaghu Vatsavayi 22979003baf0SRaghu Vatsavayi /* Initialize the dispatch mechanism used to push packets arriving on 22989003baf0SRaghu Vatsavayi * Octeon Output queues. 22999003baf0SRaghu Vatsavayi */ 23009003baf0SRaghu Vatsavayi if (octeon_init_dispatch_list(oct)) 23019003baf0SRaghu Vatsavayi return 1; 23029003baf0SRaghu Vatsavayi 23039003baf0SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_DISPATCH_INIT_DONE); 23049003baf0SRaghu Vatsavayi 2305c865cdf1SRaghu Vatsavayi if (octeon_set_io_queues_off(oct)) { 2306c865cdf1SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "setting io queues off failed\n"); 2307c865cdf1SRaghu Vatsavayi return 1; 2308c865cdf1SRaghu Vatsavayi } 2309c865cdf1SRaghu Vatsavayi 2310da15c78bSRaghu Vatsavayi if (oct->fn_list.setup_device_regs(oct)) { 2311da15c78bSRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "device registers configuration failed\n"); 2312da15c78bSRaghu Vatsavayi return 1; 2313da15c78bSRaghu Vatsavayi } 2314da15c78bSRaghu Vatsavayi 23159003baf0SRaghu Vatsavayi /* Initialize soft command buffer pool */ 23169003baf0SRaghu Vatsavayi if (octeon_setup_sc_buffer_pool(oct)) { 23179003baf0SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "sc buffer pool allocation failed\n"); 23189003baf0SRaghu Vatsavayi return 1; 23199003baf0SRaghu Vatsavayi } 23209003baf0SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_SC_BUFF_POOL_INIT_DONE); 23219003baf0SRaghu Vatsavayi 23229003baf0SRaghu Vatsavayi /* Setup the data structures that manage this Octeon's Input queues. */ 23239003baf0SRaghu Vatsavayi if (octeon_setup_instr_queues(oct)) { 23249003baf0SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "instruction queue initialization failed\n"); 23259003baf0SRaghu Vatsavayi return 1; 23269003baf0SRaghu Vatsavayi } 23279003baf0SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_INSTR_QUEUE_INIT_DONE); 23289003baf0SRaghu Vatsavayi 23299003baf0SRaghu Vatsavayi /* Initialize lists to manage the requests of different types that 23309003baf0SRaghu Vatsavayi * arrive from user & kernel applications for this octeon device. 23319003baf0SRaghu Vatsavayi */ 23329003baf0SRaghu Vatsavayi if (octeon_setup_response_list(oct)) { 23339003baf0SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Response list allocation failed\n"); 23349003baf0SRaghu Vatsavayi return 1; 23359003baf0SRaghu Vatsavayi } 23369003baf0SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_RESP_LIST_INIT_DONE); 23379003baf0SRaghu Vatsavayi 23389003baf0SRaghu Vatsavayi if (octeon_setup_output_queues(oct)) { 23399003baf0SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Output queue initialization failed\n"); 23409003baf0SRaghu Vatsavayi return 1; 23419003baf0SRaghu Vatsavayi } 23429003baf0SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_DROQ_INIT_DONE); 23439003baf0SRaghu Vatsavayi 2344f7cdd64bSRaghu Vatsavayi if (oct->fn_list.setup_mbox(oct)) { 2345f7cdd64bSRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "Mailbox setup failed\n"); 2346f7cdd64bSRaghu Vatsavayi return 1; 2347f7cdd64bSRaghu Vatsavayi } 2348f7cdd64bSRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_MBOX_SETUP_DONE); 2349f7cdd64bSRaghu Vatsavayi 2350c33c9973SIntiyaz Basha if (octeon_allocate_ioq_vector(oct, oct->sriov_info.rings_per_vf)) { 2351cf39faf5SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "ioq vector allocation failed\n"); 2352cf39faf5SRaghu Vatsavayi return 1; 2353cf39faf5SRaghu Vatsavayi } 2354cf39faf5SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_MSIX_ALLOC_VECTOR_DONE); 2355cf39faf5SRaghu Vatsavayi 2356cf39faf5SRaghu Vatsavayi dev_info(&oct->pci_dev->dev, "OCTEON_CN23XX VF Version: %s, %d ioqs\n", 2357cf39faf5SRaghu Vatsavayi LIQUIDIO_VERSION, oct->sriov_info.rings_per_vf); 2358cf39faf5SRaghu Vatsavayi 2359cf39faf5SRaghu Vatsavayi /* Setup the interrupt handler and record the INT SUM register address*/ 2360a82457f1SIntiyaz Basha if (octeon_setup_interrupt(oct, oct->sriov_info.rings_per_vf)) 2361cf39faf5SRaghu Vatsavayi return 1; 2362cf39faf5SRaghu Vatsavayi 23634c1588a2SRick Farrington atomic_set(&oct->status, OCT_DEV_INTR_SET_DONE); 23644c1588a2SRick Farrington 23654c1588a2SRick Farrington /* *************************************************************** 23664c1588a2SRick Farrington * The interrupts need to be enabled for the PF<-->VF handshake. 23674c1588a2SRick Farrington * They are [re]-enabled after the PF<-->VF handshake so that the 23684c1588a2SRick Farrington * correct OQ tick value is used (i.e. the value retrieved from 23694c1588a2SRick Farrington * the PF as part of the handshake). 23704c1588a2SRick Farrington */ 2371cf39faf5SRaghu Vatsavayi 2372cf39faf5SRaghu Vatsavayi /* Enable Octeon device interrupts */ 2373cf39faf5SRaghu Vatsavayi oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR); 2374cf39faf5SRaghu Vatsavayi 23754c1588a2SRick Farrington if (cn23xx_octeon_pfvf_handshake(oct)) 23764c1588a2SRick Farrington return 1; 23774c1588a2SRick Farrington 23784c1588a2SRick Farrington /* Here we [re]-enable the interrupts so that the correct OQ tick value 23794c1588a2SRick Farrington * is used (i.e. the value that was retrieved during the handshake) 23804c1588a2SRick Farrington */ 23814c1588a2SRick Farrington 23824c1588a2SRick Farrington /* Enable Octeon device interrupts */ 23834c1588a2SRick Farrington oct->fn_list.enable_interrupt(oct, OCTEON_ALL_INTR); 23844c1588a2SRick Farrington /* *************************************************************** */ 2385cf39faf5SRaghu Vatsavayi 2386b3c35973SRaghu Vatsavayi /* Enable the input and output queues for this Octeon device */ 2387b3c35973SRaghu Vatsavayi if (oct->fn_list.enable_io_queues(oct)) { 2388b3c35973SRaghu Vatsavayi dev_err(&oct->pci_dev->dev, "enabling io queues failed\n"); 2389b3c35973SRaghu Vatsavayi return 1; 2390b3c35973SRaghu Vatsavayi } 2391b3c35973SRaghu Vatsavayi 2392b3c35973SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_IO_QUEUES_DONE); 2393b3c35973SRaghu Vatsavayi 2394b3c35973SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_HOST_OK); 2395b3c35973SRaghu Vatsavayi 2396b3c35973SRaghu Vatsavayi /* Send Credit for Octeon Output queues. Credits are always sent after 2397b3c35973SRaghu Vatsavayi * the output queue is enabled. 2398b3c35973SRaghu Vatsavayi */ 2399b3c35973SRaghu Vatsavayi for (j = 0; j < oct->num_oqs; j++) 2400b3c35973SRaghu Vatsavayi writel(oct->droq[j]->max_count, oct->droq[j]->pkts_credit_reg); 2401b3c35973SRaghu Vatsavayi 2402b3c35973SRaghu Vatsavayi /* Packets can start arriving on the output queues from this point. */ 2403b3c35973SRaghu Vatsavayi 2404b3c35973SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_CORE_OK); 2405b3c35973SRaghu Vatsavayi 2406b3c35973SRaghu Vatsavayi atomic_set(&oct->status, OCT_DEV_RUNNING); 2407b3c35973SRaghu Vatsavayi 2408846b4687SRaghu Vatsavayi if (liquidio_init_nic_module(oct)) 2409846b4687SRaghu Vatsavayi return 1; 2410846b4687SRaghu Vatsavayi 241169c69da3SRaghu Vatsavayi return 0; 241269c69da3SRaghu Vatsavayi } 241369c69da3SRaghu Vatsavayi 2414111fc64aSRaghu Vatsavayi static int __init liquidio_vf_init(void) 2415111fc64aSRaghu Vatsavayi { 2416111fc64aSRaghu Vatsavayi octeon_init_device_list(0); 2417111fc64aSRaghu Vatsavayi return pci_register_driver(&liquidio_vf_pci_driver); 2418111fc64aSRaghu Vatsavayi } 2419111fc64aSRaghu Vatsavayi 2420111fc64aSRaghu Vatsavayi static void __exit liquidio_vf_exit(void) 2421111fc64aSRaghu Vatsavayi { 2422111fc64aSRaghu Vatsavayi pci_unregister_driver(&liquidio_vf_pci_driver); 2423111fc64aSRaghu Vatsavayi 2424111fc64aSRaghu Vatsavayi pr_info("LiquidIO_VF network module is now unloaded\n"); 2425111fc64aSRaghu Vatsavayi } 2426111fc64aSRaghu Vatsavayi 2427111fc64aSRaghu Vatsavayi module_init(liquidio_vf_init); 2428111fc64aSRaghu Vatsavayi module_exit(liquidio_vf_exit); 2429