1f173c2b7SSean Bruno /* 2f173c2b7SSean Bruno * BSD LICENSE 3f173c2b7SSean Bruno * 4f173c2b7SSean Bruno * Copyright(c) 2017 Cavium, Inc.. All rights reserved. 5f173c2b7SSean Bruno * All rights reserved. 6f173c2b7SSean Bruno * 7f173c2b7SSean Bruno * Redistribution and use in source and binary forms, with or without 8f173c2b7SSean Bruno * modification, are permitted provided that the following conditions 9f173c2b7SSean Bruno * are met: 10f173c2b7SSean Bruno * 11f173c2b7SSean Bruno * * Redistributions of source code must retain the above copyright 12f173c2b7SSean Bruno * notice, this list of conditions and the following disclaimer. 13f173c2b7SSean Bruno * * Redistributions in binary form must reproduce the above copyright 14f173c2b7SSean Bruno * notice, this list of conditions and the following disclaimer in 15f173c2b7SSean Bruno * the documentation and/or other materials provided with the 16f173c2b7SSean Bruno * distribution. 17f173c2b7SSean Bruno * * Neither the name of Cavium, Inc. nor the names of its 18f173c2b7SSean Bruno * contributors may be used to endorse or promote products derived 19f173c2b7SSean Bruno * from this software without specific prior written permission. 20f173c2b7SSean Bruno * 21f173c2b7SSean Bruno * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22f173c2b7SSean Bruno * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23f173c2b7SSean Bruno * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24f173c2b7SSean Bruno * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25f173c2b7SSean Bruno * OWNER(S) OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26f173c2b7SSean Bruno * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27f173c2b7SSean Bruno * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28f173c2b7SSean Bruno * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29f173c2b7SSean Bruno * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30f173c2b7SSean Bruno * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31f173c2b7SSean Bruno * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32f173c2b7SSean Bruno */ 33f173c2b7SSean Bruno 34f173c2b7SSean Bruno #include "lio_bsd.h" 35f173c2b7SSean Bruno #include "lio_common.h" 36f173c2b7SSean Bruno 37f173c2b7SSean Bruno #include "lio_droq.h" 38f173c2b7SSean Bruno #include "lio_iq.h" 39f173c2b7SSean Bruno #include "lio_response_manager.h" 40f173c2b7SSean Bruno #include "lio_device.h" 41f173c2b7SSean Bruno #include "lio_ctrl.h" 42f173c2b7SSean Bruno #include "lio_main.h" 43f173c2b7SSean Bruno #include "lio_network.h" 44f173c2b7SSean Bruno #include "cn23xx_pf_device.h" 45f173c2b7SSean Bruno #include "lio_image.h" 46f173c2b7SSean Bruno #include "lio_ioctl.h" 47f173c2b7SSean Bruno #include "lio_rxtx.h" 48f173c2b7SSean Bruno #include "lio_rss.h" 49f173c2b7SSean Bruno 50f173c2b7SSean Bruno /* Number of milliseconds to wait for DDR initialization */ 51f173c2b7SSean Bruno #define LIO_DDR_TIMEOUT 10000 52f173c2b7SSean Bruno #define LIO_MAX_FW_TYPE_LEN 8 53f173c2b7SSean Bruno 54f173c2b7SSean Bruno static char fw_type[LIO_MAX_FW_TYPE_LEN]; 55f173c2b7SSean Bruno TUNABLE_STR("hw.lio.fw_type", fw_type, sizeof(fw_type)); 56f173c2b7SSean Bruno 57f173c2b7SSean Bruno /* 58f173c2b7SSean Bruno * Integers that specify number of queues per PF. 59f173c2b7SSean Bruno * Valid range is 0 to 64. 60f173c2b7SSean Bruno * Use 0 to derive from CPU count. 61f173c2b7SSean Bruno */ 62f173c2b7SSean Bruno static int num_queues_per_pf0; 63f173c2b7SSean Bruno static int num_queues_per_pf1; 64f173c2b7SSean Bruno TUNABLE_INT("hw.lio.num_queues_per_pf0", &num_queues_per_pf0); 65f173c2b7SSean Bruno TUNABLE_INT("hw.lio.num_queues_per_pf1", &num_queues_per_pf1); 66f173c2b7SSean Bruno 67f173c2b7SSean Bruno #ifdef RSS 68f173c2b7SSean Bruno static int lio_rss = 1; 69f173c2b7SSean Bruno TUNABLE_INT("hw.lio.rss", &lio_rss); 70f173c2b7SSean Bruno #endif /* RSS */ 71f173c2b7SSean Bruno 72f173c2b7SSean Bruno /* Hardware LRO */ 73f173c2b7SSean Bruno unsigned int lio_hwlro = 0; 74f173c2b7SSean Bruno TUNABLE_INT("hw.lio.hwlro", &lio_hwlro); 75f173c2b7SSean Bruno 76f173c2b7SSean Bruno /* 77f173c2b7SSean Bruno * Bitmask indicating which consoles have debug 78f173c2b7SSean Bruno * output redirected to syslog. 79f173c2b7SSean Bruno */ 80f173c2b7SSean Bruno static unsigned long console_bitmask; 81f173c2b7SSean Bruno TUNABLE_ULONG("hw.lio.console_bitmask", &console_bitmask); 82f173c2b7SSean Bruno 83f173c2b7SSean Bruno /* 84f173c2b7SSean Bruno * \brief determines if a given console has debug enabled. 85f173c2b7SSean Bruno * @param console console to check 86f173c2b7SSean Bruno * @returns 1 = enabled. 0 otherwise 87f173c2b7SSean Bruno */ 88f173c2b7SSean Bruno int 89f173c2b7SSean Bruno lio_console_debug_enabled(uint32_t console) 90f173c2b7SSean Bruno { 91f173c2b7SSean Bruno 92f173c2b7SSean Bruno return (console_bitmask >> (console)) & 0x1; 93f173c2b7SSean Bruno } 94f173c2b7SSean Bruno 95f173c2b7SSean Bruno static int lio_detach(device_t dev); 96f173c2b7SSean Bruno 97f173c2b7SSean Bruno static int lio_device_init(struct octeon_device *octeon_dev); 98f173c2b7SSean Bruno static int lio_chip_specific_setup(struct octeon_device *oct); 99f173c2b7SSean Bruno static void lio_watchdog(void *param); 100f173c2b7SSean Bruno static int lio_load_firmware(struct octeon_device *oct); 101f173c2b7SSean Bruno static int lio_nic_starter(struct octeon_device *oct); 102f173c2b7SSean Bruno static int lio_init_nic_module(struct octeon_device *oct); 103f173c2b7SSean Bruno static int lio_setup_nic_devices(struct octeon_device *octeon_dev); 104f173c2b7SSean Bruno static int lio_link_info(struct lio_recv_info *recv_info, void *ptr); 105f173c2b7SSean Bruno static void lio_if_cfg_callback(struct octeon_device *oct, uint32_t status, 106f173c2b7SSean Bruno void *buf); 1072c50292dSJustin Hibbits static int lio_set_rxcsum_command(if_t ifp, int command, 108f173c2b7SSean Bruno uint8_t rx_cmd); 109f173c2b7SSean Bruno static int lio_setup_glists(struct octeon_device *oct, struct lio *lio, 110f173c2b7SSean Bruno int num_iqs); 111f173c2b7SSean Bruno static void lio_destroy_nic_device(struct octeon_device *oct, int ifidx); 1122c50292dSJustin Hibbits static inline void lio_update_link_status(if_t ifp, 113f173c2b7SSean Bruno union octeon_link_status *ls); 114f173c2b7SSean Bruno static void lio_send_rx_ctrl_cmd(struct lio *lio, int start_stop); 115f173c2b7SSean Bruno static int lio_stop_nic_module(struct octeon_device *oct); 116f173c2b7SSean Bruno static void lio_destroy_resources(struct octeon_device *oct); 1172c50292dSJustin Hibbits static int lio_setup_rx_oom_poll_fn(if_t ifp); 118f173c2b7SSean Bruno 1192c50292dSJustin Hibbits static void lio_vlan_rx_add_vid(void *arg, if_t ifp, uint16_t vid); 1202c50292dSJustin Hibbits static void lio_vlan_rx_kill_vid(void *arg, if_t ifp, 121f173c2b7SSean Bruno uint16_t vid); 122f173c2b7SSean Bruno static struct octeon_device * 123f173c2b7SSean Bruno lio_get_other_octeon_device(struct octeon_device *oct); 124f173c2b7SSean Bruno 125f173c2b7SSean Bruno static int lio_wait_for_oq_pkts(struct octeon_device *oct); 126f173c2b7SSean Bruno 127f173c2b7SSean Bruno int lio_send_rss_param(struct lio *lio); 128f173c2b7SSean Bruno static int lio_dbg_console_print(struct octeon_device *oct, 129f173c2b7SSean Bruno uint32_t console_num, char *prefix, 130f173c2b7SSean Bruno char *suffix); 131f173c2b7SSean Bruno 132f173c2b7SSean Bruno /* Polling interval for determining when NIC application is alive */ 133f173c2b7SSean Bruno #define LIO_STARTER_POLL_INTERVAL_MS 100 134f173c2b7SSean Bruno 135f173c2b7SSean Bruno /* 136f173c2b7SSean Bruno * vendor_info_array. 137f173c2b7SSean Bruno * This array contains the list of IDs on which the driver should load. 138f173c2b7SSean Bruno */ 139f173c2b7SSean Bruno struct lio_vendor_info { 140f173c2b7SSean Bruno uint16_t vendor_id; 141f173c2b7SSean Bruno uint16_t device_id; 142f173c2b7SSean Bruno uint16_t subdevice_id; 143f173c2b7SSean Bruno uint8_t revision_id; 144f173c2b7SSean Bruno uint8_t index; 145f173c2b7SSean Bruno }; 146f173c2b7SSean Bruno 147f173c2b7SSean Bruno static struct lio_vendor_info lio_pci_tbl[] = { 148f173c2b7SSean Bruno /* CN2350 10G */ 149f173c2b7SSean Bruno {PCI_VENDOR_ID_CAVIUM, LIO_CN23XX_PF_VID, LIO_CN2350_10G_SUBDEVICE, 150f173c2b7SSean Bruno 0x02, 0}, 151f173c2b7SSean Bruno 152f173c2b7SSean Bruno /* CN2350 10G */ 153f173c2b7SSean Bruno {PCI_VENDOR_ID_CAVIUM, LIO_CN23XX_PF_VID, LIO_CN2350_10G_SUBDEVICE1, 154f173c2b7SSean Bruno 0x02, 0}, 155f173c2b7SSean Bruno 156f173c2b7SSean Bruno /* CN2360 10G */ 157f173c2b7SSean Bruno {PCI_VENDOR_ID_CAVIUM, LIO_CN23XX_PF_VID, LIO_CN2360_10G_SUBDEVICE, 158f173c2b7SSean Bruno 0x02, 1}, 159f173c2b7SSean Bruno 160f173c2b7SSean Bruno /* CN2350 25G */ 161f173c2b7SSean Bruno {PCI_VENDOR_ID_CAVIUM, LIO_CN23XX_PF_VID, LIO_CN2350_25G_SUBDEVICE, 162f173c2b7SSean Bruno 0x02, 2}, 163f173c2b7SSean Bruno 164f173c2b7SSean Bruno /* CN2360 25G */ 165f173c2b7SSean Bruno {PCI_VENDOR_ID_CAVIUM, LIO_CN23XX_PF_VID, LIO_CN2360_25G_SUBDEVICE, 166f173c2b7SSean Bruno 0x02, 3}, 167f173c2b7SSean Bruno 168f173c2b7SSean Bruno {0, 0, 0, 0, 0} 169f173c2b7SSean Bruno }; 170f173c2b7SSean Bruno 171f173c2b7SSean Bruno static char *lio_strings[] = { 172f173c2b7SSean Bruno "LiquidIO 2350 10GbE Server Adapter", 173f173c2b7SSean Bruno "LiquidIO 2360 10GbE Server Adapter", 174f173c2b7SSean Bruno "LiquidIO 2350 25GbE Server Adapter", 175f173c2b7SSean Bruno "LiquidIO 2360 25GbE Server Adapter", 176f173c2b7SSean Bruno }; 177f173c2b7SSean Bruno 178f173c2b7SSean Bruno struct lio_if_cfg_resp { 179f173c2b7SSean Bruno uint64_t rh; 180f173c2b7SSean Bruno struct octeon_if_cfg_info cfg_info; 181f173c2b7SSean Bruno uint64_t status; 182f173c2b7SSean Bruno }; 183f173c2b7SSean Bruno 184f173c2b7SSean Bruno struct lio_if_cfg_context { 185f173c2b7SSean Bruno int octeon_id; 186f173c2b7SSean Bruno volatile int cond; 187f173c2b7SSean Bruno }; 188f173c2b7SSean Bruno 189f173c2b7SSean Bruno struct lio_rx_ctl_context { 190f173c2b7SSean Bruno int octeon_id; 191f173c2b7SSean Bruno volatile int cond; 192f173c2b7SSean Bruno }; 193f173c2b7SSean Bruno 194f173c2b7SSean Bruno static int 195f173c2b7SSean Bruno lio_probe(device_t dev) 196f173c2b7SSean Bruno { 197f173c2b7SSean Bruno struct lio_vendor_info *tbl; 198f173c2b7SSean Bruno 199f173c2b7SSean Bruno uint16_t vendor_id; 200f173c2b7SSean Bruno uint16_t device_id; 201f173c2b7SSean Bruno uint16_t subdevice_id; 202f173c2b7SSean Bruno uint8_t revision_id; 203f173c2b7SSean Bruno 204f173c2b7SSean Bruno vendor_id = pci_get_vendor(dev); 205f173c2b7SSean Bruno if (vendor_id != PCI_VENDOR_ID_CAVIUM) 206f173c2b7SSean Bruno return (ENXIO); 207f173c2b7SSean Bruno 208f173c2b7SSean Bruno device_id = pci_get_device(dev); 209f173c2b7SSean Bruno subdevice_id = pci_get_subdevice(dev); 210f173c2b7SSean Bruno revision_id = pci_get_revid(dev); 211f173c2b7SSean Bruno 212f173c2b7SSean Bruno tbl = lio_pci_tbl; 213f173c2b7SSean Bruno while (tbl->vendor_id) { 214f173c2b7SSean Bruno if ((vendor_id == tbl->vendor_id) && 215f173c2b7SSean Bruno (device_id == tbl->device_id) && 216f173c2b7SSean Bruno (subdevice_id == tbl->subdevice_id) && 217f173c2b7SSean Bruno (revision_id == tbl->revision_id)) { 218*1794a0a8SMark Johnston device_set_descf(dev, "%s, Version - %s", 219f173c2b7SSean Bruno lio_strings[tbl->index], LIO_VERSION); 220f173c2b7SSean Bruno return (BUS_PROBE_DEFAULT); 221f173c2b7SSean Bruno } 222f173c2b7SSean Bruno 223f173c2b7SSean Bruno tbl++; 224f173c2b7SSean Bruno } 225f173c2b7SSean Bruno 226f173c2b7SSean Bruno return (ENXIO); 227f173c2b7SSean Bruno } 228f173c2b7SSean Bruno 229f173c2b7SSean Bruno static int 230f173c2b7SSean Bruno lio_attach(device_t device) 231f173c2b7SSean Bruno { 232f173c2b7SSean Bruno struct octeon_device *oct_dev = NULL; 233f173c2b7SSean Bruno uint64_t scratch1; 234f173c2b7SSean Bruno uint32_t error; 235f173c2b7SSean Bruno int timeout, ret = 1; 236f173c2b7SSean Bruno uint8_t bus, dev, function; 237f173c2b7SSean Bruno 238f173c2b7SSean Bruno oct_dev = lio_allocate_device(device); 239f173c2b7SSean Bruno if (oct_dev == NULL) { 240f173c2b7SSean Bruno device_printf(device, "Error: Unable to allocate device\n"); 241f173c2b7SSean Bruno return (-ENOMEM); 242f173c2b7SSean Bruno } 243f173c2b7SSean Bruno 244f173c2b7SSean Bruno oct_dev->tx_budget = LIO_DEFAULT_TX_PKTS_PROCESS_BUDGET; 245f173c2b7SSean Bruno oct_dev->rx_budget = LIO_DEFAULT_RX_PKTS_PROCESS_BUDGET; 246f173c2b7SSean Bruno oct_dev->msix_on = LIO_FLAG_MSIX_ENABLED; 247f173c2b7SSean Bruno 248f173c2b7SSean Bruno oct_dev->device = device; 249f173c2b7SSean Bruno bus = pci_get_bus(device); 250f173c2b7SSean Bruno dev = pci_get_slot(device); 251f173c2b7SSean Bruno function = pci_get_function(device); 252f173c2b7SSean Bruno 253f173c2b7SSean Bruno lio_dev_info(oct_dev, "Initializing device %x:%x %02x:%02x.%01x\n", 254f173c2b7SSean Bruno pci_get_vendor(device), pci_get_device(device), bus, dev, 255f173c2b7SSean Bruno function); 256f173c2b7SSean Bruno 257f173c2b7SSean Bruno if (lio_device_init(oct_dev)) { 258f173c2b7SSean Bruno lio_dev_err(oct_dev, "Failed to init device\n"); 259f173c2b7SSean Bruno lio_detach(device); 260f173c2b7SSean Bruno return (-ENOMEM); 261f173c2b7SSean Bruno } 262f173c2b7SSean Bruno 263f173c2b7SSean Bruno scratch1 = lio_read_csr64(oct_dev, LIO_CN23XX_SLI_SCRATCH1); 264f173c2b7SSean Bruno if (!(scratch1 & 4ULL)) { 265f173c2b7SSean Bruno /* 266f173c2b7SSean Bruno * Bit 2 of SLI_SCRATCH_1 is a flag that indicates that 267f173c2b7SSean Bruno * the lio watchdog kernel thread is running for this 268f173c2b7SSean Bruno * NIC. Each NIC gets one watchdog kernel thread. 269f173c2b7SSean Bruno */ 270f173c2b7SSean Bruno scratch1 |= 4ULL; 271f173c2b7SSean Bruno lio_write_csr64(oct_dev, LIO_CN23XX_SLI_SCRATCH1, scratch1); 272f173c2b7SSean Bruno 273f173c2b7SSean Bruno error = kproc_create(lio_watchdog, oct_dev, 274f173c2b7SSean Bruno &oct_dev->watchdog_task, 0, 0, 275f173c2b7SSean Bruno "liowd/%02hhx:%02hhx.%hhx", bus, 276f173c2b7SSean Bruno dev, function); 277f173c2b7SSean Bruno if (!error) { 278f173c2b7SSean Bruno kproc_resume(oct_dev->watchdog_task); 279f173c2b7SSean Bruno } else { 280f173c2b7SSean Bruno oct_dev->watchdog_task = NULL; 281f173c2b7SSean Bruno lio_dev_err(oct_dev, 282f173c2b7SSean Bruno "failed to create kernel_thread\n"); 283f173c2b7SSean Bruno lio_detach(device); 284f173c2b7SSean Bruno return (-1); 285f173c2b7SSean Bruno } 286f173c2b7SSean Bruno } 287f173c2b7SSean Bruno oct_dev->rx_pause = 1; 288f173c2b7SSean Bruno oct_dev->tx_pause = 1; 289f173c2b7SSean Bruno 290f173c2b7SSean Bruno timeout = 0; 291f173c2b7SSean Bruno while (timeout < LIO_NIC_STARTER_TIMEOUT) { 292f173c2b7SSean Bruno lio_mdelay(LIO_STARTER_POLL_INTERVAL_MS); 293f173c2b7SSean Bruno timeout += LIO_STARTER_POLL_INTERVAL_MS; 294f173c2b7SSean Bruno 295f173c2b7SSean Bruno /* 296f173c2b7SSean Bruno * During the boot process interrupts are not available. 297f173c2b7SSean Bruno * So polling for first control message from FW. 298f173c2b7SSean Bruno */ 299f173c2b7SSean Bruno if (cold) 300f173c2b7SSean Bruno lio_droq_bh(oct_dev->droq[0], 0); 301f173c2b7SSean Bruno 302f173c2b7SSean Bruno if (atomic_load_acq_int(&oct_dev->status) == LIO_DEV_CORE_OK) { 303f173c2b7SSean Bruno ret = lio_nic_starter(oct_dev); 304f173c2b7SSean Bruno break; 305f173c2b7SSean Bruno } 306f173c2b7SSean Bruno } 307f173c2b7SSean Bruno 308f173c2b7SSean Bruno if (ret) { 309f173c2b7SSean Bruno lio_dev_err(oct_dev, "Firmware failed to start\n"); 310f173c2b7SSean Bruno lio_detach(device); 311f173c2b7SSean Bruno return (-EIO); 312f173c2b7SSean Bruno } 313f173c2b7SSean Bruno 314f173c2b7SSean Bruno lio_dev_dbg(oct_dev, "Device is ready\n"); 315f173c2b7SSean Bruno 316f173c2b7SSean Bruno return (0); 317f173c2b7SSean Bruno } 318f173c2b7SSean Bruno 319f173c2b7SSean Bruno static int 320f173c2b7SSean Bruno lio_detach(device_t dev) 321f173c2b7SSean Bruno { 322f173c2b7SSean Bruno struct octeon_device *oct_dev = device_get_softc(dev); 323f173c2b7SSean Bruno 324f173c2b7SSean Bruno lio_dev_dbg(oct_dev, "Stopping device\n"); 325f173c2b7SSean Bruno if (oct_dev->watchdog_task) { 326f173c2b7SSean Bruno uint64_t scratch1; 327f173c2b7SSean Bruno 328f173c2b7SSean Bruno kproc_suspend(oct_dev->watchdog_task, 0); 329f173c2b7SSean Bruno 330f173c2b7SSean Bruno scratch1 = lio_read_csr64(oct_dev, LIO_CN23XX_SLI_SCRATCH1); 331f173c2b7SSean Bruno scratch1 &= ~4ULL; 332f173c2b7SSean Bruno lio_write_csr64(oct_dev, LIO_CN23XX_SLI_SCRATCH1, scratch1); 333f173c2b7SSean Bruno } 334f173c2b7SSean Bruno 335f173c2b7SSean Bruno if (oct_dev->app_mode && (oct_dev->app_mode == LIO_DRV_NIC_APP)) 336f173c2b7SSean Bruno lio_stop_nic_module(oct_dev); 337f173c2b7SSean Bruno 338f173c2b7SSean Bruno /* 339f173c2b7SSean Bruno * Reset the octeon device and cleanup all memory allocated for 340f173c2b7SSean Bruno * the octeon device by driver. 341f173c2b7SSean Bruno */ 342f173c2b7SSean Bruno lio_destroy_resources(oct_dev); 343f173c2b7SSean Bruno 344f173c2b7SSean Bruno lio_dev_info(oct_dev, "Device removed\n"); 345f173c2b7SSean Bruno 346f173c2b7SSean Bruno /* 347f173c2b7SSean Bruno * This octeon device has been removed. Update the global 348f173c2b7SSean Bruno * data structure to reflect this. Free the device structure. 349f173c2b7SSean Bruno */ 350f173c2b7SSean Bruno lio_free_device_mem(oct_dev); 351f173c2b7SSean Bruno return (0); 352f173c2b7SSean Bruno } 353f173c2b7SSean Bruno 354f173c2b7SSean Bruno static int 355f173c2b7SSean Bruno lio_shutdown(device_t dev) 356f173c2b7SSean Bruno { 357f173c2b7SSean Bruno struct octeon_device *oct_dev = device_get_softc(dev); 358f173c2b7SSean Bruno struct lio *lio = if_getsoftc(oct_dev->props.ifp); 359f173c2b7SSean Bruno 360f173c2b7SSean Bruno lio_send_rx_ctrl_cmd(lio, 0); 361f173c2b7SSean Bruno 362f173c2b7SSean Bruno return (0); 363f173c2b7SSean Bruno } 364f173c2b7SSean Bruno 365f173c2b7SSean Bruno static int 366f173c2b7SSean Bruno lio_suspend(device_t dev) 367f173c2b7SSean Bruno { 368f173c2b7SSean Bruno 369f173c2b7SSean Bruno return (ENXIO); 370f173c2b7SSean Bruno } 371f173c2b7SSean Bruno 372f173c2b7SSean Bruno static int 373f173c2b7SSean Bruno lio_resume(device_t dev) 374f173c2b7SSean Bruno { 375f173c2b7SSean Bruno 376f173c2b7SSean Bruno return (ENXIO); 377f173c2b7SSean Bruno } 378f173c2b7SSean Bruno 379f173c2b7SSean Bruno static int 380f173c2b7SSean Bruno lio_event(struct module *mod, int event, void *junk) 381f173c2b7SSean Bruno { 382f173c2b7SSean Bruno 383f173c2b7SSean Bruno switch (event) { 384f173c2b7SSean Bruno case MOD_LOAD: 385f173c2b7SSean Bruno lio_init_device_list(LIO_CFG_TYPE_DEFAULT); 386f173c2b7SSean Bruno break; 387f173c2b7SSean Bruno default: 388f173c2b7SSean Bruno break; 389f173c2b7SSean Bruno } 390f173c2b7SSean Bruno 391f173c2b7SSean Bruno return (0); 392f173c2b7SSean Bruno } 393f173c2b7SSean Bruno 394f173c2b7SSean Bruno /********************************************************************* 395f173c2b7SSean Bruno * FreeBSD Device Interface Entry Points 396f173c2b7SSean Bruno * *******************************************************************/ 397f173c2b7SSean Bruno static device_method_t lio_methods[] = { 398f173c2b7SSean Bruno /* Device interface */ 399f173c2b7SSean Bruno DEVMETHOD(device_probe, lio_probe), 400f173c2b7SSean Bruno DEVMETHOD(device_attach, lio_attach), 401f173c2b7SSean Bruno DEVMETHOD(device_detach, lio_detach), 402f173c2b7SSean Bruno DEVMETHOD(device_shutdown, lio_shutdown), 403f173c2b7SSean Bruno DEVMETHOD(device_suspend, lio_suspend), 404f173c2b7SSean Bruno DEVMETHOD(device_resume, lio_resume), 405f173c2b7SSean Bruno DEVMETHOD_END 406f173c2b7SSean Bruno }; 407f173c2b7SSean Bruno 408f173c2b7SSean Bruno static driver_t lio_driver = { 409f173c2b7SSean Bruno LIO_DRV_NAME, lio_methods, sizeof(struct octeon_device), 410f173c2b7SSean Bruno }; 411f173c2b7SSean Bruno 4121cd1672fSJohn Baldwin DRIVER_MODULE(lio, pci, lio_driver, lio_event, NULL); 413f173c2b7SSean Bruno 414f173c2b7SSean Bruno MODULE_DEPEND(lio, pci, 1, 1, 1); 415f173c2b7SSean Bruno MODULE_DEPEND(lio, ether, 1, 1, 1); 416f173c2b7SSean Bruno MODULE_DEPEND(lio, firmware, 1, 1, 1); 417f173c2b7SSean Bruno 418f173c2b7SSean Bruno static bool 419f173c2b7SSean Bruno fw_type_is_none(void) 420f173c2b7SSean Bruno { 421f173c2b7SSean Bruno return strncmp(fw_type, LIO_FW_NAME_TYPE_NONE, 422f173c2b7SSean Bruno sizeof(LIO_FW_NAME_TYPE_NONE)) == 0; 423f173c2b7SSean Bruno } 424f173c2b7SSean Bruno 425f173c2b7SSean Bruno /* 426f173c2b7SSean Bruno * \brief Device initialization for each Octeon device that is probed 427f173c2b7SSean Bruno * @param octeon_dev octeon device 428f173c2b7SSean Bruno */ 429f173c2b7SSean Bruno static int 430f173c2b7SSean Bruno lio_device_init(struct octeon_device *octeon_dev) 431f173c2b7SSean Bruno { 432f173c2b7SSean Bruno unsigned long ddr_timeout = LIO_DDR_TIMEOUT; 433f173c2b7SSean Bruno char *dbg_enb = NULL; 434f173c2b7SSean Bruno int fw_loaded = 0; 435f173c2b7SSean Bruno int i, j, ret; 436f173c2b7SSean Bruno uint8_t bus, dev, function; 437f173c2b7SSean Bruno char bootcmd[] = "\n"; 438f173c2b7SSean Bruno 439f173c2b7SSean Bruno bus = pci_get_bus(octeon_dev->device); 440f173c2b7SSean Bruno dev = pci_get_slot(octeon_dev->device); 441f173c2b7SSean Bruno function = pci_get_function(octeon_dev->device); 442f173c2b7SSean Bruno 443f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, LIO_DEV_BEGIN_STATE); 444f173c2b7SSean Bruno 445f173c2b7SSean Bruno /* Enable access to the octeon device */ 446f173c2b7SSean Bruno if (pci_enable_busmaster(octeon_dev->device)) { 447f173c2b7SSean Bruno lio_dev_err(octeon_dev, "pci_enable_device failed\n"); 448f173c2b7SSean Bruno return (1); 449f173c2b7SSean Bruno } 450f173c2b7SSean Bruno 451f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, LIO_DEV_PCI_ENABLE_DONE); 452f173c2b7SSean Bruno 453f173c2b7SSean Bruno /* Identify the Octeon type and map the BAR address space. */ 454f173c2b7SSean Bruno if (lio_chip_specific_setup(octeon_dev)) { 455f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Chip specific setup failed\n"); 456f173c2b7SSean Bruno return (1); 457f173c2b7SSean Bruno } 458f173c2b7SSean Bruno 459f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, LIO_DEV_PCI_MAP_DONE); 460f173c2b7SSean Bruno 461f173c2b7SSean Bruno /* 462f173c2b7SSean Bruno * Only add a reference after setting status 'OCT_DEV_PCI_MAP_DONE', 463f173c2b7SSean Bruno * since that is what is required for the reference to be removed 464f173c2b7SSean Bruno * during de-initialization (see 'octeon_destroy_resources'). 465f173c2b7SSean Bruno */ 466f173c2b7SSean Bruno lio_register_device(octeon_dev, bus, dev, function, true); 467f173c2b7SSean Bruno 468f173c2b7SSean Bruno 469f173c2b7SSean Bruno octeon_dev->app_mode = LIO_DRV_INVALID_APP; 470f173c2b7SSean Bruno 471f173c2b7SSean Bruno if (!lio_cn23xx_pf_fw_loaded(octeon_dev) && !fw_type_is_none()) { 472f173c2b7SSean Bruno fw_loaded = 0; 473f173c2b7SSean Bruno /* Do a soft reset of the Octeon device. */ 474f173c2b7SSean Bruno if (octeon_dev->fn_list.soft_reset(octeon_dev)) 475f173c2b7SSean Bruno return (1); 476f173c2b7SSean Bruno 477f173c2b7SSean Bruno /* things might have changed */ 478f173c2b7SSean Bruno if (!lio_cn23xx_pf_fw_loaded(octeon_dev)) 479f173c2b7SSean Bruno fw_loaded = 0; 480f173c2b7SSean Bruno else 481f173c2b7SSean Bruno fw_loaded = 1; 482f173c2b7SSean Bruno } else { 483f173c2b7SSean Bruno fw_loaded = 1; 484f173c2b7SSean Bruno } 485f173c2b7SSean Bruno 486f173c2b7SSean Bruno /* 487f173c2b7SSean Bruno * Initialize the dispatch mechanism used to push packets arriving on 488f173c2b7SSean Bruno * Octeon Output queues. 489f173c2b7SSean Bruno */ 490f173c2b7SSean Bruno if (lio_init_dispatch_list(octeon_dev)) 491f173c2b7SSean Bruno return (1); 492f173c2b7SSean Bruno 493f173c2b7SSean Bruno lio_register_dispatch_fn(octeon_dev, LIO_OPCODE_NIC, 494f173c2b7SSean Bruno LIO_OPCODE_NIC_CORE_DRV_ACTIVE, 495f173c2b7SSean Bruno lio_core_drv_init, octeon_dev); 496f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, LIO_DEV_DISPATCH_INIT_DONE); 497f173c2b7SSean Bruno 498f173c2b7SSean Bruno ret = octeon_dev->fn_list.setup_device_regs(octeon_dev); 499f173c2b7SSean Bruno if (ret) { 500f173c2b7SSean Bruno lio_dev_err(octeon_dev, 501f173c2b7SSean Bruno "Failed to configure device registers\n"); 502f173c2b7SSean Bruno return (ret); 503f173c2b7SSean Bruno } 504f173c2b7SSean Bruno 505f173c2b7SSean Bruno /* Initialize soft command buffer pool */ 506f173c2b7SSean Bruno if (lio_setup_sc_buffer_pool(octeon_dev)) { 507f173c2b7SSean Bruno lio_dev_err(octeon_dev, "sc buffer pool allocation failed\n"); 508f173c2b7SSean Bruno return (1); 509f173c2b7SSean Bruno } 510f173c2b7SSean Bruno 511f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, 512f173c2b7SSean Bruno LIO_DEV_SC_BUFF_POOL_INIT_DONE); 513f173c2b7SSean Bruno 514f173c2b7SSean Bruno if (lio_allocate_ioq_vector(octeon_dev)) { 515f173c2b7SSean Bruno lio_dev_err(octeon_dev, 516f173c2b7SSean Bruno "IOQ vector allocation failed\n"); 517f173c2b7SSean Bruno return (1); 518f173c2b7SSean Bruno } 519f173c2b7SSean Bruno 520f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, 521f173c2b7SSean Bruno LIO_DEV_MSIX_ALLOC_VECTOR_DONE); 522f173c2b7SSean Bruno 523f173c2b7SSean Bruno for (i = 0; i < LIO_MAX_POSSIBLE_INSTR_QUEUES; i++) { 524f173c2b7SSean Bruno octeon_dev->instr_queue[i] = 525f173c2b7SSean Bruno malloc(sizeof(struct lio_instr_queue), 526f173c2b7SSean Bruno M_DEVBUF, M_NOWAIT | M_ZERO); 527f173c2b7SSean Bruno if (octeon_dev->instr_queue[i] == NULL) 528f173c2b7SSean Bruno return (1); 529f173c2b7SSean Bruno } 530f173c2b7SSean Bruno 531f173c2b7SSean Bruno /* Setup the data structures that manage this Octeon's Input queues. */ 532f173c2b7SSean Bruno if (lio_setup_instr_queue0(octeon_dev)) { 533f173c2b7SSean Bruno lio_dev_err(octeon_dev, 534f173c2b7SSean Bruno "Instruction queue initialization failed\n"); 535f173c2b7SSean Bruno return (1); 536f173c2b7SSean Bruno } 537f173c2b7SSean Bruno 538f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, 539f173c2b7SSean Bruno LIO_DEV_INSTR_QUEUE_INIT_DONE); 540f173c2b7SSean Bruno 541f173c2b7SSean Bruno /* 542f173c2b7SSean Bruno * Initialize lists to manage the requests of different types that 543f173c2b7SSean Bruno * arrive from user & kernel applications for this octeon device. 544f173c2b7SSean Bruno */ 545f173c2b7SSean Bruno 546f173c2b7SSean Bruno if (lio_setup_response_list(octeon_dev)) { 547f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Response list allocation failed\n"); 548f173c2b7SSean Bruno return (1); 549f173c2b7SSean Bruno } 550f173c2b7SSean Bruno 551f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, LIO_DEV_RESP_LIST_INIT_DONE); 552f173c2b7SSean Bruno 553f173c2b7SSean Bruno for (i = 0; i < LIO_MAX_POSSIBLE_OUTPUT_QUEUES; i++) { 554f173c2b7SSean Bruno octeon_dev->droq[i] = malloc(sizeof(*octeon_dev->droq[i]), 555f173c2b7SSean Bruno M_DEVBUF, M_NOWAIT | M_ZERO); 556f173c2b7SSean Bruno if (octeon_dev->droq[i] == NULL) 557f173c2b7SSean Bruno return (1); 558f173c2b7SSean Bruno } 559f173c2b7SSean Bruno 560f173c2b7SSean Bruno if (lio_setup_output_queue0(octeon_dev)) { 561f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Output queue initialization failed\n"); 562f173c2b7SSean Bruno return (1); 563f173c2b7SSean Bruno } 564f173c2b7SSean Bruno 565f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, LIO_DEV_DROQ_INIT_DONE); 566f173c2b7SSean Bruno 567f173c2b7SSean Bruno /* 568f173c2b7SSean Bruno * Setup the interrupt handler and record the INT SUM register address 569f173c2b7SSean Bruno */ 570f173c2b7SSean Bruno if (lio_setup_interrupt(octeon_dev, 571f173c2b7SSean Bruno octeon_dev->sriov_info.num_pf_rings)) 572f173c2b7SSean Bruno return (1); 573f173c2b7SSean Bruno 574f173c2b7SSean Bruno /* Enable Octeon device interrupts */ 575f173c2b7SSean Bruno octeon_dev->fn_list.enable_interrupt(octeon_dev, OCTEON_ALL_INTR); 576f173c2b7SSean Bruno 577f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, LIO_DEV_INTR_SET_DONE); 578f173c2b7SSean Bruno 579f173c2b7SSean Bruno /* 580f173c2b7SSean Bruno * Send Credit for Octeon Output queues. Credits are always sent BEFORE 581f173c2b7SSean Bruno * the output queue is enabled. 582f173c2b7SSean Bruno * This ensures that we'll receive the f/w CORE DRV_ACTIVE message in 583f173c2b7SSean Bruno * case we've configured CN23XX_SLI_GBL_CONTROL[NOPTR_D] = 0. 584f173c2b7SSean Bruno * Otherwise, it is possible that the DRV_ACTIVE message will be sent 585f173c2b7SSean Bruno * before any credits have been issued, causing the ring to be reset 586f173c2b7SSean Bruno * (and the f/w appear to never have started). 587f173c2b7SSean Bruno */ 588f173c2b7SSean Bruno for (j = 0; j < octeon_dev->num_oqs; j++) 589f173c2b7SSean Bruno lio_write_csr32(octeon_dev, 590f173c2b7SSean Bruno octeon_dev->droq[j]->pkts_credit_reg, 591f173c2b7SSean Bruno octeon_dev->droq[j]->max_count); 592f173c2b7SSean Bruno 593f173c2b7SSean Bruno /* Enable the input and output queues for this Octeon device */ 594f173c2b7SSean Bruno ret = octeon_dev->fn_list.enable_io_queues(octeon_dev); 595f173c2b7SSean Bruno if (ret) { 596f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Failed to enable input/output queues"); 597f173c2b7SSean Bruno return (ret); 598f173c2b7SSean Bruno } 599f173c2b7SSean Bruno 600f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, LIO_DEV_IO_QUEUES_DONE); 601f173c2b7SSean Bruno 602f173c2b7SSean Bruno if (!fw_loaded) { 603f173c2b7SSean Bruno lio_dev_dbg(octeon_dev, "Waiting for DDR initialization...\n"); 604f173c2b7SSean Bruno if (!ddr_timeout) { 605f173c2b7SSean Bruno lio_dev_info(octeon_dev, 606f173c2b7SSean Bruno "WAITING. Set ddr_timeout to non-zero value to proceed with initialization.\n"); 607f173c2b7SSean Bruno } 608f173c2b7SSean Bruno 609f173c2b7SSean Bruno lio_sleep_timeout(LIO_RESET_MSECS); 610f173c2b7SSean Bruno 611f173c2b7SSean Bruno /* 612f173c2b7SSean Bruno * Wait for the octeon to initialize DDR after the 613f173c2b7SSean Bruno * soft-reset. 614f173c2b7SSean Bruno */ 615f173c2b7SSean Bruno while (!ddr_timeout) { 616f173c2b7SSean Bruno if (pause("-", lio_ms_to_ticks(100))) { 617f173c2b7SSean Bruno /* user probably pressed Control-C */ 618f173c2b7SSean Bruno return (1); 619f173c2b7SSean Bruno } 620f173c2b7SSean Bruno } 621f173c2b7SSean Bruno 622f173c2b7SSean Bruno ret = lio_wait_for_ddr_init(octeon_dev, &ddr_timeout); 623f173c2b7SSean Bruno if (ret) { 624f173c2b7SSean Bruno lio_dev_err(octeon_dev, 625f173c2b7SSean Bruno "DDR not initialized. Please confirm that board is configured to boot from Flash, ret: %d\n", 626f173c2b7SSean Bruno ret); 627f173c2b7SSean Bruno return (1); 628f173c2b7SSean Bruno } 629f173c2b7SSean Bruno 630f173c2b7SSean Bruno if (lio_wait_for_bootloader(octeon_dev, 1100)) { 631f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Board not responding\n"); 632f173c2b7SSean Bruno return (1); 633f173c2b7SSean Bruno } 634f173c2b7SSean Bruno 635f173c2b7SSean Bruno /* Divert uboot to take commands from host instead. */ 636f173c2b7SSean Bruno ret = lio_console_send_cmd(octeon_dev, bootcmd, 50); 637f173c2b7SSean Bruno 638f173c2b7SSean Bruno lio_dev_dbg(octeon_dev, "Initializing consoles\n"); 639f173c2b7SSean Bruno ret = lio_init_consoles(octeon_dev); 640f173c2b7SSean Bruno if (ret) { 641f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Could not access board consoles\n"); 642f173c2b7SSean Bruno return (1); 643f173c2b7SSean Bruno } 644f173c2b7SSean Bruno 645f173c2b7SSean Bruno /* 646f173c2b7SSean Bruno * If console debug enabled, specify empty string to 647f173c2b7SSean Bruno * use default enablement ELSE specify NULL string for 648f173c2b7SSean Bruno * 'disabled'. 649f173c2b7SSean Bruno */ 650f173c2b7SSean Bruno dbg_enb = lio_console_debug_enabled(0) ? "" : NULL; 651f173c2b7SSean Bruno ret = lio_add_console(octeon_dev, 0, dbg_enb); 652f173c2b7SSean Bruno 653f173c2b7SSean Bruno if (ret) { 654f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Could not access board console\n"); 655f173c2b7SSean Bruno return (1); 656f173c2b7SSean Bruno } else if (lio_console_debug_enabled(0)) { 657f173c2b7SSean Bruno /* 658f173c2b7SSean Bruno * If console was added AND we're logging console output 659f173c2b7SSean Bruno * then set our console print function. 660f173c2b7SSean Bruno */ 661f173c2b7SSean Bruno octeon_dev->console[0].print = lio_dbg_console_print; 662f173c2b7SSean Bruno } 663f173c2b7SSean Bruno 664f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, 665f173c2b7SSean Bruno LIO_DEV_CONSOLE_INIT_DONE); 666f173c2b7SSean Bruno 667f173c2b7SSean Bruno lio_dev_dbg(octeon_dev, "Loading firmware\n"); 668f173c2b7SSean Bruno 669f173c2b7SSean Bruno ret = lio_load_firmware(octeon_dev); 670f173c2b7SSean Bruno if (ret) { 671f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Could not load firmware to board\n"); 672f173c2b7SSean Bruno return (1); 673f173c2b7SSean Bruno } 674f173c2b7SSean Bruno } 675f173c2b7SSean Bruno 676f173c2b7SSean Bruno atomic_store_rel_int(&octeon_dev->status, LIO_DEV_HOST_OK); 677f173c2b7SSean Bruno 678f173c2b7SSean Bruno return (0); 679f173c2b7SSean Bruno } 680f173c2b7SSean Bruno 681f173c2b7SSean Bruno /* 682f173c2b7SSean Bruno * \brief PCI FLR for each Octeon device. 683f173c2b7SSean Bruno * @param oct octeon device 684f173c2b7SSean Bruno */ 685f173c2b7SSean Bruno static void 686f173c2b7SSean Bruno lio_pci_flr(struct octeon_device *oct) 687f173c2b7SSean Bruno { 688f173c2b7SSean Bruno uint32_t exppos, status; 689f173c2b7SSean Bruno 690f173c2b7SSean Bruno pci_find_cap(oct->device, PCIY_EXPRESS, &exppos); 691f173c2b7SSean Bruno 692f173c2b7SSean Bruno pci_save_state(oct->device); 693f173c2b7SSean Bruno 694f173c2b7SSean Bruno /* Quiesce the device completely */ 695f173c2b7SSean Bruno pci_write_config(oct->device, PCIR_COMMAND, PCIM_CMD_INTxDIS, 2); 696f173c2b7SSean Bruno 697f173c2b7SSean Bruno /* Wait for Transaction Pending bit clean */ 698f173c2b7SSean Bruno lio_mdelay(100); 699f173c2b7SSean Bruno 700f173c2b7SSean Bruno status = pci_read_config(oct->device, exppos + PCIER_DEVICE_STA, 2); 701f173c2b7SSean Bruno if (status & PCIEM_STA_TRANSACTION_PND) { 702f173c2b7SSean Bruno lio_dev_info(oct, "Function reset incomplete after 100ms, sleeping for 5 seconds\n"); 703f173c2b7SSean Bruno lio_mdelay(5); 704f173c2b7SSean Bruno 705f173c2b7SSean Bruno status = pci_read_config(oct->device, exppos + PCIER_DEVICE_STA, 2); 706f173c2b7SSean Bruno if (status & PCIEM_STA_TRANSACTION_PND) 707f173c2b7SSean Bruno lio_dev_info(oct, "Function reset still incomplete after 5s, reset anyway\n"); 708f173c2b7SSean Bruno } 709f173c2b7SSean Bruno 710f173c2b7SSean Bruno pci_write_config(oct->device, exppos + PCIER_DEVICE_CTL, PCIEM_CTL_INITIATE_FLR, 2); 711f173c2b7SSean Bruno lio_mdelay(100); 712f173c2b7SSean Bruno 713f173c2b7SSean Bruno pci_restore_state(oct->device); 714f173c2b7SSean Bruno } 715f173c2b7SSean Bruno 716f173c2b7SSean Bruno /* 717f173c2b7SSean Bruno * \brief Debug console print function 718f173c2b7SSean Bruno * @param octeon_dev octeon device 719f173c2b7SSean Bruno * @param console_num console number 720f173c2b7SSean Bruno * @param prefix first portion of line to display 721f173c2b7SSean Bruno * @param suffix second portion of line to display 722f173c2b7SSean Bruno * 723f173c2b7SSean Bruno * The OCTEON debug console outputs entire lines (excluding '\n'). 724f173c2b7SSean Bruno * Normally, the line will be passed in the 'prefix' parameter. 725f173c2b7SSean Bruno * However, due to buffering, it is possible for a line to be split into two 726f173c2b7SSean Bruno * parts, in which case they will be passed as the 'prefix' parameter and 727f173c2b7SSean Bruno * 'suffix' parameter. 728f173c2b7SSean Bruno */ 729f173c2b7SSean Bruno static int 730f173c2b7SSean Bruno lio_dbg_console_print(struct octeon_device *oct, uint32_t console_num, 731f173c2b7SSean Bruno char *prefix, char *suffix) 732f173c2b7SSean Bruno { 733f173c2b7SSean Bruno 734f173c2b7SSean Bruno if (prefix != NULL && suffix != NULL) 735f173c2b7SSean Bruno lio_dev_info(oct, "%u: %s%s\n", console_num, prefix, suffix); 736f173c2b7SSean Bruno else if (prefix != NULL) 737f173c2b7SSean Bruno lio_dev_info(oct, "%u: %s\n", console_num, prefix); 738f173c2b7SSean Bruno else if (suffix != NULL) 739f173c2b7SSean Bruno lio_dev_info(oct, "%u: %s\n", console_num, suffix); 740f173c2b7SSean Bruno 741f173c2b7SSean Bruno return (0); 742f173c2b7SSean Bruno } 743f173c2b7SSean Bruno 744f173c2b7SSean Bruno static void 745f173c2b7SSean Bruno lio_watchdog(void *param) 746f173c2b7SSean Bruno { 747f173c2b7SSean Bruno int core_num; 748f173c2b7SSean Bruno uint16_t mask_of_crashed_or_stuck_cores = 0; 749f173c2b7SSean Bruno struct octeon_device *oct = param; 750f173c2b7SSean Bruno bool err_msg_was_printed[12]; 751f173c2b7SSean Bruno 752f173c2b7SSean Bruno bzero(err_msg_was_printed, sizeof(err_msg_was_printed)); 753f173c2b7SSean Bruno 754f173c2b7SSean Bruno while (1) { 755f173c2b7SSean Bruno kproc_suspend_check(oct->watchdog_task); 756f173c2b7SSean Bruno mask_of_crashed_or_stuck_cores = 757f173c2b7SSean Bruno (uint16_t)lio_read_csr64(oct, LIO_CN23XX_SLI_SCRATCH2); 758f173c2b7SSean Bruno 759f173c2b7SSean Bruno if (mask_of_crashed_or_stuck_cores) { 760f173c2b7SSean Bruno struct octeon_device *other_oct; 761f173c2b7SSean Bruno 762f173c2b7SSean Bruno oct->cores_crashed = true; 763f173c2b7SSean Bruno other_oct = lio_get_other_octeon_device(oct); 764f173c2b7SSean Bruno if (other_oct != NULL) 765f173c2b7SSean Bruno other_oct->cores_crashed = true; 766f173c2b7SSean Bruno 767f173c2b7SSean Bruno for (core_num = 0; core_num < LIO_MAX_CORES; 768f173c2b7SSean Bruno core_num++) { 769f173c2b7SSean Bruno bool core_crashed_or_got_stuck; 770f173c2b7SSean Bruno 771f173c2b7SSean Bruno core_crashed_or_got_stuck = 772f173c2b7SSean Bruno (mask_of_crashed_or_stuck_cores >> 773f173c2b7SSean Bruno core_num) & 1; 774f173c2b7SSean Bruno if (core_crashed_or_got_stuck && 775f173c2b7SSean Bruno !err_msg_was_printed[core_num]) { 776f173c2b7SSean Bruno lio_dev_err(oct, 777f173c2b7SSean Bruno "ERROR: Octeon core %d crashed or got stuck! See oct-fwdump for details.\n", 778f173c2b7SSean Bruno core_num); 779f173c2b7SSean Bruno err_msg_was_printed[core_num] = true; 780f173c2b7SSean Bruno } 781f173c2b7SSean Bruno } 782f173c2b7SSean Bruno 783f173c2b7SSean Bruno } 784f173c2b7SSean Bruno 785f173c2b7SSean Bruno /* sleep for two seconds */ 786f173c2b7SSean Bruno pause("-", lio_ms_to_ticks(2000)); 787f173c2b7SSean Bruno } 788f173c2b7SSean Bruno } 789f173c2b7SSean Bruno 790f173c2b7SSean Bruno static int 791f173c2b7SSean Bruno lio_chip_specific_setup(struct octeon_device *oct) 792f173c2b7SSean Bruno { 793f173c2b7SSean Bruno char *s; 7948af24219SJohn Baldwin uint32_t dev_id; 795f173c2b7SSean Bruno int ret = 1; 796f173c2b7SSean Bruno 797f173c2b7SSean Bruno dev_id = lio_read_pci_cfg(oct, 0); 798f173c2b7SSean Bruno oct->subdevice_id = pci_get_subdevice(oct->device); 799f173c2b7SSean Bruno 800f173c2b7SSean Bruno switch (dev_id) { 801f173c2b7SSean Bruno case LIO_CN23XX_PF_PCIID: 802f173c2b7SSean Bruno oct->chip_id = LIO_CN23XX_PF_VID; 803f173c2b7SSean Bruno if (pci_get_function(oct->device) == 0) { 804f173c2b7SSean Bruno if (num_queues_per_pf0 < 0) { 805f173c2b7SSean Bruno lio_dev_info(oct, "Invalid num_queues_per_pf0: %d, Setting it to default\n", 806f173c2b7SSean Bruno num_queues_per_pf0); 807f173c2b7SSean Bruno num_queues_per_pf0 = 0; 808f173c2b7SSean Bruno } 809f173c2b7SSean Bruno 810f173c2b7SSean Bruno oct->sriov_info.num_pf_rings = num_queues_per_pf0; 811f173c2b7SSean Bruno } else { 812f173c2b7SSean Bruno if (num_queues_per_pf1 < 0) { 813f173c2b7SSean Bruno lio_dev_info(oct, "Invalid num_queues_per_pf1: %d, Setting it to default\n", 814f173c2b7SSean Bruno num_queues_per_pf1); 815f173c2b7SSean Bruno num_queues_per_pf1 = 0; 816f173c2b7SSean Bruno } 817f173c2b7SSean Bruno 818f173c2b7SSean Bruno oct->sriov_info.num_pf_rings = num_queues_per_pf1; 819f173c2b7SSean Bruno } 820f173c2b7SSean Bruno 821f173c2b7SSean Bruno ret = lio_cn23xx_pf_setup_device(oct); 822f173c2b7SSean Bruno s = "CN23XX"; 823f173c2b7SSean Bruno break; 824f173c2b7SSean Bruno 825f173c2b7SSean Bruno default: 826f173c2b7SSean Bruno s = "?"; 827f173c2b7SSean Bruno lio_dev_err(oct, "Unknown device found (dev_id: %x)\n", dev_id); 828f173c2b7SSean Bruno } 829f173c2b7SSean Bruno 830f173c2b7SSean Bruno if (!ret) 831f173c2b7SSean Bruno lio_dev_info(oct, "%s PASS%d.%d %s Version: %s\n", s, 832f173c2b7SSean Bruno OCTEON_MAJOR_REV(oct), OCTEON_MINOR_REV(oct), 833f173c2b7SSean Bruno lio_get_conf(oct)->card_name, LIO_VERSION); 834f173c2b7SSean Bruno 835f173c2b7SSean Bruno return (ret); 836f173c2b7SSean Bruno } 837f173c2b7SSean Bruno 838f173c2b7SSean Bruno static struct octeon_device * 839f173c2b7SSean Bruno lio_get_other_octeon_device(struct octeon_device *oct) 840f173c2b7SSean Bruno { 841f173c2b7SSean Bruno struct octeon_device *other_oct; 842f173c2b7SSean Bruno 843f173c2b7SSean Bruno other_oct = lio_get_device(oct->octeon_id + 1); 844f173c2b7SSean Bruno 845f173c2b7SSean Bruno if ((other_oct != NULL) && other_oct->device) { 846f173c2b7SSean Bruno int oct_busnum, other_oct_busnum; 847f173c2b7SSean Bruno 848f173c2b7SSean Bruno oct_busnum = pci_get_bus(oct->device); 849f173c2b7SSean Bruno other_oct_busnum = pci_get_bus(other_oct->device); 850f173c2b7SSean Bruno 851f173c2b7SSean Bruno if (oct_busnum == other_oct_busnum) { 852f173c2b7SSean Bruno int oct_slot, other_oct_slot; 853f173c2b7SSean Bruno 854f173c2b7SSean Bruno oct_slot = pci_get_slot(oct->device); 855f173c2b7SSean Bruno other_oct_slot = pci_get_slot(other_oct->device); 856f173c2b7SSean Bruno 857f173c2b7SSean Bruno if (oct_slot == other_oct_slot) 858f173c2b7SSean Bruno return (other_oct); 859f173c2b7SSean Bruno } 860f173c2b7SSean Bruno } 861f173c2b7SSean Bruno return (NULL); 862f173c2b7SSean Bruno } 863f173c2b7SSean Bruno 864f173c2b7SSean Bruno /* 865f173c2b7SSean Bruno * \brief Load firmware to device 866f173c2b7SSean Bruno * @param oct octeon device 867f173c2b7SSean Bruno * 868f173c2b7SSean Bruno * Maps device to firmware filename, requests firmware, and downloads it 869f173c2b7SSean Bruno */ 870f173c2b7SSean Bruno static int 871f173c2b7SSean Bruno lio_load_firmware(struct octeon_device *oct) 872f173c2b7SSean Bruno { 873f173c2b7SSean Bruno const struct firmware *fw; 874f173c2b7SSean Bruno char *tmp_fw_type = NULL; 875f173c2b7SSean Bruno int ret = 0; 876f173c2b7SSean Bruno char fw_name[LIO_MAX_FW_FILENAME_LEN]; 877f173c2b7SSean Bruno 878f173c2b7SSean Bruno if (fw_type[0] == '\0') 879f173c2b7SSean Bruno tmp_fw_type = LIO_FW_NAME_TYPE_NIC; 880f173c2b7SSean Bruno else 881f173c2b7SSean Bruno tmp_fw_type = fw_type; 882f173c2b7SSean Bruno 883f173c2b7SSean Bruno sprintf(fw_name, "%s%s_%s%s", LIO_FW_BASE_NAME, 884f173c2b7SSean Bruno lio_get_conf(oct)->card_name, tmp_fw_type, LIO_FW_NAME_SUFFIX); 885f173c2b7SSean Bruno 886f173c2b7SSean Bruno fw = firmware_get(fw_name); 887f173c2b7SSean Bruno if (fw == NULL) { 888f173c2b7SSean Bruno lio_dev_err(oct, "Request firmware failed. Could not find file %s.\n", 889f173c2b7SSean Bruno fw_name); 890f173c2b7SSean Bruno return (EINVAL); 891f173c2b7SSean Bruno } 892f173c2b7SSean Bruno 893f173c2b7SSean Bruno ret = lio_download_firmware(oct, fw->data, fw->datasize); 894f173c2b7SSean Bruno 895f173c2b7SSean Bruno firmware_put(fw, FIRMWARE_UNLOAD); 896f173c2b7SSean Bruno 897f173c2b7SSean Bruno return (ret); 898f173c2b7SSean Bruno } 899f173c2b7SSean Bruno 900f173c2b7SSean Bruno static int 901f173c2b7SSean Bruno lio_nic_starter(struct octeon_device *oct) 902f173c2b7SSean Bruno { 903f173c2b7SSean Bruno int ret = 0; 904f173c2b7SSean Bruno 905f173c2b7SSean Bruno atomic_store_rel_int(&oct->status, LIO_DEV_RUNNING); 906f173c2b7SSean Bruno 907f173c2b7SSean Bruno if (oct->app_mode && oct->app_mode == LIO_DRV_NIC_APP) { 908f173c2b7SSean Bruno if (lio_init_nic_module(oct)) { 909f173c2b7SSean Bruno lio_dev_err(oct, "NIC initialization failed\n"); 910f173c2b7SSean Bruno ret = -1; 911f173c2b7SSean Bruno #ifdef CAVIUM_ONiLY_23XX_VF 912f173c2b7SSean Bruno } else { 913f173c2b7SSean Bruno if (octeon_enable_sriov(oct) < 0) 914f173c2b7SSean Bruno ret = -1; 915f173c2b7SSean Bruno #endif 916f173c2b7SSean Bruno } 917f173c2b7SSean Bruno } else { 918f173c2b7SSean Bruno lio_dev_err(oct, 919f173c2b7SSean Bruno "Unexpected application running on NIC (%d). Check firmware.\n", 920f173c2b7SSean Bruno oct->app_mode); 921f173c2b7SSean Bruno ret = -1; 922f173c2b7SSean Bruno } 923f173c2b7SSean Bruno 924f173c2b7SSean Bruno return (ret); 925f173c2b7SSean Bruno } 926f173c2b7SSean Bruno 927f173c2b7SSean Bruno static int 928f173c2b7SSean Bruno lio_init_nic_module(struct octeon_device *oct) 929f173c2b7SSean Bruno { 930f173c2b7SSean Bruno int num_nic_ports = LIO_GET_NUM_NIC_PORTS_CFG(lio_get_conf(oct)); 931f173c2b7SSean Bruno int retval = 0; 932f173c2b7SSean Bruno 933f173c2b7SSean Bruno lio_dev_dbg(oct, "Initializing network interfaces\n"); 934f173c2b7SSean Bruno 935f173c2b7SSean Bruno /* 936f173c2b7SSean Bruno * only default iq and oq were initialized 937f173c2b7SSean Bruno * initialize the rest as well 938f173c2b7SSean Bruno */ 939f173c2b7SSean Bruno 940f173c2b7SSean Bruno /* run port_config command for each port */ 941f173c2b7SSean Bruno oct->ifcount = num_nic_ports; 942f173c2b7SSean Bruno 943f173c2b7SSean Bruno bzero(&oct->props, sizeof(struct lio_if_props)); 944f173c2b7SSean Bruno 945f173c2b7SSean Bruno oct->props.gmxport = -1; 946f173c2b7SSean Bruno 947f173c2b7SSean Bruno retval = lio_setup_nic_devices(oct); 948f173c2b7SSean Bruno if (retval) { 949f173c2b7SSean Bruno lio_dev_err(oct, "Setup NIC devices failed\n"); 950f173c2b7SSean Bruno goto lio_init_failure; 951f173c2b7SSean Bruno } 952f173c2b7SSean Bruno 953f173c2b7SSean Bruno lio_dev_dbg(oct, "Network interfaces ready\n"); 954f173c2b7SSean Bruno 955f173c2b7SSean Bruno return (retval); 956f173c2b7SSean Bruno 957f173c2b7SSean Bruno lio_init_failure: 958f173c2b7SSean Bruno 959f173c2b7SSean Bruno oct->ifcount = 0; 960f173c2b7SSean Bruno 961f173c2b7SSean Bruno return (retval); 962f173c2b7SSean Bruno } 963f173c2b7SSean Bruno 964f173c2b7SSean Bruno static int 9652c50292dSJustin Hibbits lio_ifmedia_update(if_t ifp) 966f173c2b7SSean Bruno { 967f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 968f173c2b7SSean Bruno struct ifmedia *ifm; 969f173c2b7SSean Bruno 970f173c2b7SSean Bruno ifm = &lio->ifmedia; 971f173c2b7SSean Bruno 972f173c2b7SSean Bruno /* We only support Ethernet media type. */ 973f173c2b7SSean Bruno if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER) 974f173c2b7SSean Bruno return (EINVAL); 975f173c2b7SSean Bruno 976f173c2b7SSean Bruno switch (IFM_SUBTYPE(ifm->ifm_media)) { 977f173c2b7SSean Bruno case IFM_AUTO: 978f173c2b7SSean Bruno break; 979f173c2b7SSean Bruno case IFM_10G_CX4: 980f173c2b7SSean Bruno case IFM_10G_SR: 981f173c2b7SSean Bruno case IFM_10G_T: 982f173c2b7SSean Bruno case IFM_10G_TWINAX: 983f173c2b7SSean Bruno default: 984f173c2b7SSean Bruno /* We don't support changing the media type. */ 985f173c2b7SSean Bruno lio_dev_err(lio->oct_dev, "Invalid media type (%d)\n", 986f173c2b7SSean Bruno IFM_SUBTYPE(ifm->ifm_media)); 987f173c2b7SSean Bruno return (EINVAL); 988f173c2b7SSean Bruno } 989f173c2b7SSean Bruno 990f173c2b7SSean Bruno return (0); 991f173c2b7SSean Bruno } 992f173c2b7SSean Bruno 993f173c2b7SSean Bruno static int 994f173c2b7SSean Bruno lio_get_media_subtype(struct octeon_device *oct) 995f173c2b7SSean Bruno { 996f173c2b7SSean Bruno 997f173c2b7SSean Bruno switch(oct->subdevice_id) { 998f173c2b7SSean Bruno case LIO_CN2350_10G_SUBDEVICE: 999f173c2b7SSean Bruno case LIO_CN2350_10G_SUBDEVICE1: 1000f173c2b7SSean Bruno case LIO_CN2360_10G_SUBDEVICE: 1001f173c2b7SSean Bruno return (IFM_10G_SR); 1002f173c2b7SSean Bruno 1003f173c2b7SSean Bruno case LIO_CN2350_25G_SUBDEVICE: 1004f173c2b7SSean Bruno case LIO_CN2360_25G_SUBDEVICE: 1005f173c2b7SSean Bruno return (IFM_25G_SR); 1006f173c2b7SSean Bruno } 1007f173c2b7SSean Bruno 1008f173c2b7SSean Bruno return (IFM_10G_SR); 1009f173c2b7SSean Bruno } 1010f173c2b7SSean Bruno 10113de0952fSSean Bruno static uint64_t 1012f173c2b7SSean Bruno lio_get_baudrate(struct octeon_device *oct) 1013f173c2b7SSean Bruno { 1014f173c2b7SSean Bruno 1015f173c2b7SSean Bruno switch(oct->subdevice_id) { 1016f173c2b7SSean Bruno case LIO_CN2350_10G_SUBDEVICE: 1017f173c2b7SSean Bruno case LIO_CN2350_10G_SUBDEVICE1: 1018f173c2b7SSean Bruno case LIO_CN2360_10G_SUBDEVICE: 1019f173c2b7SSean Bruno return (IF_Gbps(10)); 1020f173c2b7SSean Bruno 1021f173c2b7SSean Bruno case LIO_CN2350_25G_SUBDEVICE: 1022f173c2b7SSean Bruno case LIO_CN2360_25G_SUBDEVICE: 1023f173c2b7SSean Bruno return (IF_Gbps(25)); 1024f173c2b7SSean Bruno } 1025f173c2b7SSean Bruno 1026f173c2b7SSean Bruno return (IF_Gbps(10)); 1027f173c2b7SSean Bruno } 1028f173c2b7SSean Bruno 1029f173c2b7SSean Bruno static void 10302c50292dSJustin Hibbits lio_ifmedia_status(if_t ifp, struct ifmediareq *ifmr) 1031f173c2b7SSean Bruno { 1032f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1033f173c2b7SSean Bruno 1034f173c2b7SSean Bruno /* Report link down if the driver isn't running. */ 1035f173c2b7SSean Bruno if (!lio_ifstate_check(lio, LIO_IFSTATE_RUNNING)) { 1036f173c2b7SSean Bruno ifmr->ifm_active |= IFM_NONE; 1037f173c2b7SSean Bruno return; 1038f173c2b7SSean Bruno } 1039f173c2b7SSean Bruno 1040f173c2b7SSean Bruno /* Setup the default interface info. */ 1041f173c2b7SSean Bruno ifmr->ifm_status = IFM_AVALID; 1042f173c2b7SSean Bruno ifmr->ifm_active = IFM_ETHER; 1043f173c2b7SSean Bruno 1044f173c2b7SSean Bruno if (lio->linfo.link.s.link_up) { 1045f173c2b7SSean Bruno ifmr->ifm_status |= IFM_ACTIVE; 1046f173c2b7SSean Bruno } else { 1047f173c2b7SSean Bruno ifmr->ifm_active |= IFM_NONE; 1048f173c2b7SSean Bruno return; 1049f173c2b7SSean Bruno } 1050f173c2b7SSean Bruno 1051f173c2b7SSean Bruno ifmr->ifm_active |= lio_get_media_subtype(lio->oct_dev); 1052f173c2b7SSean Bruno 1053f173c2b7SSean Bruno if (lio->linfo.link.s.duplex) 1054f173c2b7SSean Bruno ifmr->ifm_active |= IFM_FDX; 1055f173c2b7SSean Bruno else 1056f173c2b7SSean Bruno ifmr->ifm_active |= IFM_HDX; 1057f173c2b7SSean Bruno } 1058f173c2b7SSean Bruno 1059f173c2b7SSean Bruno static uint64_t 1060f173c2b7SSean Bruno lio_get_counter(if_t ifp, ift_counter cnt) 1061f173c2b7SSean Bruno { 1062f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1063f173c2b7SSean Bruno struct octeon_device *oct = lio->oct_dev; 1064f173c2b7SSean Bruno uint64_t counter = 0; 1065f173c2b7SSean Bruno int i, q_no; 1066f173c2b7SSean Bruno 1067f173c2b7SSean Bruno switch (cnt) { 1068f173c2b7SSean Bruno case IFCOUNTER_IPACKETS: 1069f173c2b7SSean Bruno for (i = 0; i < oct->num_oqs; i++) { 1070f173c2b7SSean Bruno q_no = lio->linfo.rxpciq[i].s.q_no; 1071f173c2b7SSean Bruno counter += oct->droq[q_no]->stats.rx_pkts_received; 1072f173c2b7SSean Bruno } 1073f173c2b7SSean Bruno break; 1074f173c2b7SSean Bruno case IFCOUNTER_OPACKETS: 1075f173c2b7SSean Bruno for (i = 0; i < oct->num_iqs; i++) { 1076f173c2b7SSean Bruno q_no = lio->linfo.txpciq[i].s.q_no; 1077f173c2b7SSean Bruno counter += oct->instr_queue[q_no]->stats.tx_done; 1078f173c2b7SSean Bruno } 1079f173c2b7SSean Bruno break; 1080f173c2b7SSean Bruno case IFCOUNTER_IBYTES: 1081f173c2b7SSean Bruno for (i = 0; i < oct->num_oqs; i++) { 1082f173c2b7SSean Bruno q_no = lio->linfo.rxpciq[i].s.q_no; 1083f173c2b7SSean Bruno counter += oct->droq[q_no]->stats.rx_bytes_received; 1084f173c2b7SSean Bruno } 1085f173c2b7SSean Bruno break; 1086f173c2b7SSean Bruno case IFCOUNTER_OBYTES: 1087f173c2b7SSean Bruno for (i = 0; i < oct->num_iqs; i++) { 1088f173c2b7SSean Bruno q_no = lio->linfo.txpciq[i].s.q_no; 1089f173c2b7SSean Bruno counter += oct->instr_queue[q_no]->stats.tx_tot_bytes; 1090f173c2b7SSean Bruno } 1091f173c2b7SSean Bruno break; 1092f173c2b7SSean Bruno case IFCOUNTER_IQDROPS: 1093f173c2b7SSean Bruno for (i = 0; i < oct->num_oqs; i++) { 1094f173c2b7SSean Bruno q_no = lio->linfo.rxpciq[i].s.q_no; 1095f173c2b7SSean Bruno counter += oct->droq[q_no]->stats.rx_dropped; 1096f173c2b7SSean Bruno } 1097f173c2b7SSean Bruno break; 1098f173c2b7SSean Bruno case IFCOUNTER_OQDROPS: 1099f173c2b7SSean Bruno for (i = 0; i < oct->num_iqs; i++) { 1100f173c2b7SSean Bruno q_no = lio->linfo.txpciq[i].s.q_no; 1101f173c2b7SSean Bruno counter += oct->instr_queue[q_no]->stats.tx_dropped; 1102f173c2b7SSean Bruno } 1103f173c2b7SSean Bruno break; 1104f173c2b7SSean Bruno case IFCOUNTER_IMCASTS: 1105f173c2b7SSean Bruno counter = oct->link_stats.fromwire.total_mcst; 1106f173c2b7SSean Bruno break; 1107f173c2b7SSean Bruno case IFCOUNTER_OMCASTS: 1108f173c2b7SSean Bruno counter = oct->link_stats.fromhost.mcast_pkts_sent; 1109f173c2b7SSean Bruno break; 1110f173c2b7SSean Bruno case IFCOUNTER_COLLISIONS: 1111f173c2b7SSean Bruno counter = oct->link_stats.fromhost.total_collisions; 1112f173c2b7SSean Bruno break; 1113f173c2b7SSean Bruno case IFCOUNTER_IERRORS: 1114f173c2b7SSean Bruno counter = oct->link_stats.fromwire.fcs_err + 1115f173c2b7SSean Bruno oct->link_stats.fromwire.l2_err + 1116f173c2b7SSean Bruno oct->link_stats.fromwire.frame_err; 1117f173c2b7SSean Bruno break; 1118f173c2b7SSean Bruno default: 1119f173c2b7SSean Bruno return (if_get_counter_default(ifp, cnt)); 1120f173c2b7SSean Bruno } 1121f173c2b7SSean Bruno 1122f173c2b7SSean Bruno return (counter); 1123f173c2b7SSean Bruno } 1124f173c2b7SSean Bruno 1125f173c2b7SSean Bruno static int 1126f173c2b7SSean Bruno lio_init_ifnet(struct lio *lio) 1127f173c2b7SSean Bruno { 1128f173c2b7SSean Bruno struct octeon_device *oct = lio->oct_dev; 1129f173c2b7SSean Bruno if_t ifp = lio->ifp; 1130f173c2b7SSean Bruno 1131f173c2b7SSean Bruno /* ifconfig entrypoint for media type/status reporting */ 1132f173c2b7SSean Bruno ifmedia_init(&lio->ifmedia, IFM_IMASK, lio_ifmedia_update, 1133f173c2b7SSean Bruno lio_ifmedia_status); 1134f173c2b7SSean Bruno 1135f173c2b7SSean Bruno /* set the default interface values */ 1136f173c2b7SSean Bruno ifmedia_add(&lio->ifmedia, 1137f173c2b7SSean Bruno (IFM_ETHER | IFM_FDX | lio_get_media_subtype(oct)), 1138f173c2b7SSean Bruno 0, NULL); 1139f173c2b7SSean Bruno ifmedia_add(&lio->ifmedia, (IFM_ETHER | IFM_AUTO), 0, NULL); 1140f173c2b7SSean Bruno ifmedia_set(&lio->ifmedia, (IFM_ETHER | IFM_AUTO)); 1141f173c2b7SSean Bruno 1142f173c2b7SSean Bruno lio->ifmedia.ifm_media = lio->ifmedia.ifm_cur->ifm_media; 1143f173c2b7SSean Bruno lio_dev_dbg(oct, "IFMEDIA flags : %x\n", lio->ifmedia.ifm_media); 1144f173c2b7SSean Bruno 1145f173c2b7SSean Bruno if_initname(ifp, device_get_name(oct->device), 1146f173c2b7SSean Bruno device_get_unit(oct->device)); 1147f173c2b7SSean Bruno if_setflags(ifp, (IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST)); 1148f173c2b7SSean Bruno if_setioctlfn(ifp, lio_ioctl); 1149f173c2b7SSean Bruno if_setgetcounterfn(ifp, lio_get_counter); 1150f173c2b7SSean Bruno if_settransmitfn(ifp, lio_mq_start); 1151f173c2b7SSean Bruno if_setqflushfn(ifp, lio_qflush); 1152f173c2b7SSean Bruno if_setinitfn(ifp, lio_open); 1153f173c2b7SSean Bruno if_setmtu(ifp, lio->linfo.link.s.mtu); 1154f173c2b7SSean Bruno lio->mtu = lio->linfo.link.s.mtu; 1155f173c2b7SSean Bruno if_sethwassist(ifp, (CSUM_IP | CSUM_TCP | CSUM_UDP | CSUM_TSO | 1156f173c2b7SSean Bruno CSUM_TCP_IPV6 | CSUM_UDP_IPV6)); 1157f173c2b7SSean Bruno 1158f173c2b7SSean Bruno if_setcapabilitiesbit(ifp, (IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 | 1159f173c2b7SSean Bruno IFCAP_TSO | IFCAP_LRO | 1160f173c2b7SSean Bruno IFCAP_JUMBO_MTU | IFCAP_HWSTATS | 1161f173c2b7SSean Bruno IFCAP_LINKSTATE | IFCAP_VLAN_HWFILTER | 1162f173c2b7SSean Bruno IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTAGGING | 1163f173c2b7SSean Bruno IFCAP_VLAN_HWTSO | IFCAP_VLAN_MTU), 0); 1164f173c2b7SSean Bruno 1165f173c2b7SSean Bruno if_setcapenable(ifp, if_getcapabilities(ifp)); 1166f173c2b7SSean Bruno if_setbaudrate(ifp, lio_get_baudrate(oct)); 1167f173c2b7SSean Bruno 1168f173c2b7SSean Bruno return (0); 1169f173c2b7SSean Bruno } 1170f173c2b7SSean Bruno 1171f173c2b7SSean Bruno static void 11722c50292dSJustin Hibbits lio_tcp_lro_free(struct octeon_device *octeon_dev, if_t ifp) 1173f173c2b7SSean Bruno { 1174f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1175f173c2b7SSean Bruno struct lio_droq *droq; 1176f173c2b7SSean Bruno int q_no; 1177f173c2b7SSean Bruno int i; 1178f173c2b7SSean Bruno 1179f173c2b7SSean Bruno for (i = 0; i < octeon_dev->num_oqs; i++) { 1180f173c2b7SSean Bruno q_no = lio->linfo.rxpciq[i].s.q_no; 1181f173c2b7SSean Bruno droq = octeon_dev->droq[q_no]; 1182f173c2b7SSean Bruno if (droq->lro.ifp) { 1183f173c2b7SSean Bruno tcp_lro_free(&droq->lro); 1184f173c2b7SSean Bruno droq->lro.ifp = NULL; 1185f173c2b7SSean Bruno } 1186f173c2b7SSean Bruno } 1187f173c2b7SSean Bruno } 1188f173c2b7SSean Bruno 1189f173c2b7SSean Bruno static int 11902c50292dSJustin Hibbits lio_tcp_lro_init(struct octeon_device *octeon_dev, if_t ifp) 1191f173c2b7SSean Bruno { 1192f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1193f173c2b7SSean Bruno struct lio_droq *droq; 1194f173c2b7SSean Bruno struct lro_ctrl *lro; 1195f173c2b7SSean Bruno int i, q_no, ret = 0; 1196f173c2b7SSean Bruno 1197f173c2b7SSean Bruno for (i = 0; i < octeon_dev->num_oqs; i++) { 1198f173c2b7SSean Bruno q_no = lio->linfo.rxpciq[i].s.q_no; 1199f173c2b7SSean Bruno droq = octeon_dev->droq[q_no]; 1200f173c2b7SSean Bruno lro = &droq->lro; 1201f173c2b7SSean Bruno ret = tcp_lro_init(lro); 1202f173c2b7SSean Bruno if (ret) { 1203f173c2b7SSean Bruno lio_dev_err(octeon_dev, "LRO Initialization failed ret %d\n", 1204f173c2b7SSean Bruno ret); 1205f173c2b7SSean Bruno goto lro_init_failed; 1206f173c2b7SSean Bruno } 1207f173c2b7SSean Bruno 1208f173c2b7SSean Bruno lro->ifp = ifp; 1209f173c2b7SSean Bruno } 1210f173c2b7SSean Bruno 1211f173c2b7SSean Bruno return (ret); 1212f173c2b7SSean Bruno 1213f173c2b7SSean Bruno lro_init_failed: 1214f173c2b7SSean Bruno lio_tcp_lro_free(octeon_dev, ifp); 1215f173c2b7SSean Bruno 1216f173c2b7SSean Bruno return (ret); 1217f173c2b7SSean Bruno } 1218f173c2b7SSean Bruno 1219f173c2b7SSean Bruno static int 1220f173c2b7SSean Bruno lio_setup_nic_devices(struct octeon_device *octeon_dev) 1221f173c2b7SSean Bruno { 1222f173c2b7SSean Bruno union octeon_if_cfg if_cfg; 1223f173c2b7SSean Bruno struct lio *lio = NULL; 12242c50292dSJustin Hibbits if_t ifp = NULL; 1225f173c2b7SSean Bruno struct lio_version *vdata; 1226f173c2b7SSean Bruno struct lio_soft_command *sc; 1227f173c2b7SSean Bruno struct lio_if_cfg_context *ctx; 1228f173c2b7SSean Bruno struct lio_if_cfg_resp *resp; 1229f173c2b7SSean Bruno struct lio_if_props *props; 1230f173c2b7SSean Bruno int num_iqueues, num_oqueues, retval; 1231f173c2b7SSean Bruno unsigned int base_queue; 1232f173c2b7SSean Bruno unsigned int gmx_port_id; 1233f173c2b7SSean Bruno uint32_t ctx_size, data_size; 1234f173c2b7SSean Bruno uint32_t ifidx_or_pfnum, resp_size; 1235f173c2b7SSean Bruno uint8_t mac[ETHER_HDR_LEN], i, j; 1236f173c2b7SSean Bruno 1237f173c2b7SSean Bruno /* This is to handle link status changes */ 1238f173c2b7SSean Bruno lio_register_dispatch_fn(octeon_dev, LIO_OPCODE_NIC, 1239f173c2b7SSean Bruno LIO_OPCODE_NIC_INFO, 1240f173c2b7SSean Bruno lio_link_info, octeon_dev); 1241f173c2b7SSean Bruno 1242f173c2b7SSean Bruno for (i = 0; i < octeon_dev->ifcount; i++) { 1243f173c2b7SSean Bruno resp_size = sizeof(struct lio_if_cfg_resp); 1244f173c2b7SSean Bruno ctx_size = sizeof(struct lio_if_cfg_context); 1245f173c2b7SSean Bruno data_size = sizeof(struct lio_version); 1246f173c2b7SSean Bruno sc = lio_alloc_soft_command(octeon_dev, data_size, resp_size, 1247f173c2b7SSean Bruno ctx_size); 1248f173c2b7SSean Bruno if (sc == NULL) 1249f173c2b7SSean Bruno return (ENOMEM); 1250f173c2b7SSean Bruno 1251f173c2b7SSean Bruno resp = (struct lio_if_cfg_resp *)sc->virtrptr; 1252f173c2b7SSean Bruno ctx = (struct lio_if_cfg_context *)sc->ctxptr; 1253f173c2b7SSean Bruno vdata = (struct lio_version *)sc->virtdptr; 1254f173c2b7SSean Bruno 1255f173c2b7SSean Bruno *((uint64_t *)vdata) = 0; 1256f173c2b7SSean Bruno vdata->major = htobe16(LIO_BASE_MAJOR_VERSION); 1257f173c2b7SSean Bruno vdata->minor = htobe16(LIO_BASE_MINOR_VERSION); 1258f173c2b7SSean Bruno vdata->micro = htobe16(LIO_BASE_MICRO_VERSION); 1259f173c2b7SSean Bruno 1260f173c2b7SSean Bruno num_iqueues = octeon_dev->sriov_info.num_pf_rings; 1261f173c2b7SSean Bruno num_oqueues = octeon_dev->sriov_info.num_pf_rings; 1262f173c2b7SSean Bruno base_queue = octeon_dev->sriov_info.pf_srn; 1263f173c2b7SSean Bruno 1264f173c2b7SSean Bruno gmx_port_id = octeon_dev->pf_num; 1265f173c2b7SSean Bruno ifidx_or_pfnum = octeon_dev->pf_num; 1266f173c2b7SSean Bruno 1267f173c2b7SSean Bruno lio_dev_dbg(octeon_dev, "requesting config for interface %d, iqs %d, oqs %d\n", 1268f173c2b7SSean Bruno ifidx_or_pfnum, num_iqueues, num_oqueues); 1269f173c2b7SSean Bruno ctx->cond = 0; 1270f173c2b7SSean Bruno ctx->octeon_id = lio_get_device_id(octeon_dev); 1271f173c2b7SSean Bruno 1272f173c2b7SSean Bruno if_cfg.if_cfg64 = 0; 1273f173c2b7SSean Bruno if_cfg.s.num_iqueues = num_iqueues; 1274f173c2b7SSean Bruno if_cfg.s.num_oqueues = num_oqueues; 1275f173c2b7SSean Bruno if_cfg.s.base_queue = base_queue; 1276f173c2b7SSean Bruno if_cfg.s.gmx_port_id = gmx_port_id; 1277f173c2b7SSean Bruno 1278f173c2b7SSean Bruno sc->iq_no = 0; 1279f173c2b7SSean Bruno 1280f173c2b7SSean Bruno lio_prepare_soft_command(octeon_dev, sc, LIO_OPCODE_NIC, 1281f173c2b7SSean Bruno LIO_OPCODE_NIC_IF_CFG, 0, 1282f173c2b7SSean Bruno if_cfg.if_cfg64, 0); 1283f173c2b7SSean Bruno 1284f173c2b7SSean Bruno sc->callback = lio_if_cfg_callback; 1285f173c2b7SSean Bruno sc->callback_arg = sc; 1286f173c2b7SSean Bruno sc->wait_time = 3000; 1287f173c2b7SSean Bruno 1288f173c2b7SSean Bruno retval = lio_send_soft_command(octeon_dev, sc); 1289f173c2b7SSean Bruno if (retval == LIO_IQ_SEND_FAILED) { 1290f173c2b7SSean Bruno lio_dev_err(octeon_dev, "iq/oq config failed status: %x\n", 1291f173c2b7SSean Bruno retval); 1292f173c2b7SSean Bruno /* Soft instr is freed by driver in case of failure. */ 1293f173c2b7SSean Bruno goto setup_nic_dev_fail; 1294f173c2b7SSean Bruno } 1295f173c2b7SSean Bruno 1296f173c2b7SSean Bruno /* 1297f173c2b7SSean Bruno * Sleep on a wait queue till the cond flag indicates that the 1298f173c2b7SSean Bruno * response arrived or timed-out. 1299f173c2b7SSean Bruno */ 1300f173c2b7SSean Bruno lio_sleep_cond(octeon_dev, &ctx->cond); 1301f173c2b7SSean Bruno 1302f173c2b7SSean Bruno retval = resp->status; 1303f173c2b7SSean Bruno if (retval) { 1304f173c2b7SSean Bruno lio_dev_err(octeon_dev, "iq/oq config failed\n"); 1305f173c2b7SSean Bruno goto setup_nic_dev_fail; 1306f173c2b7SSean Bruno } 1307f173c2b7SSean Bruno 1308f173c2b7SSean Bruno lio_swap_8B_data((uint64_t *)(&resp->cfg_info), 1309f173c2b7SSean Bruno (sizeof(struct octeon_if_cfg_info)) >> 3); 1310f173c2b7SSean Bruno 1311f173c2b7SSean Bruno num_iqueues = bitcount64(resp->cfg_info.iqmask); 1312f173c2b7SSean Bruno num_oqueues = bitcount64(resp->cfg_info.oqmask); 1313f173c2b7SSean Bruno 1314f173c2b7SSean Bruno if (!(num_iqueues) || !(num_oqueues)) { 1315f173c2b7SSean Bruno lio_dev_err(octeon_dev, 13163de0952fSSean Bruno "Got bad iqueues (%016llX) or oqueues (%016llX) from firmware.\n", 13173de0952fSSean Bruno LIO_CAST64(resp->cfg_info.iqmask), 13183de0952fSSean Bruno LIO_CAST64(resp->cfg_info.oqmask)); 1319f173c2b7SSean Bruno goto setup_nic_dev_fail; 1320f173c2b7SSean Bruno } 1321f173c2b7SSean Bruno 1322f173c2b7SSean Bruno lio_dev_dbg(octeon_dev, 13233de0952fSSean Bruno "interface %d, iqmask %016llx, oqmask %016llx, numiqueues %d, numoqueues %d\n", 13243de0952fSSean Bruno i, LIO_CAST64(resp->cfg_info.iqmask), 13253de0952fSSean Bruno LIO_CAST64(resp->cfg_info.oqmask), 1326f173c2b7SSean Bruno num_iqueues, num_oqueues); 1327f173c2b7SSean Bruno 1328f173c2b7SSean Bruno ifp = if_alloc(IFT_ETHER); 1329f173c2b7SSean Bruno 1330f173c2b7SSean Bruno lio = malloc(sizeof(struct lio), M_DEVBUF, M_NOWAIT | M_ZERO); 1331f173c2b7SSean Bruno 1332f173c2b7SSean Bruno if (lio == NULL) { 1333f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Lio allocation failed\n"); 1334f173c2b7SSean Bruno goto setup_nic_dev_fail; 1335f173c2b7SSean Bruno } 1336f173c2b7SSean Bruno 1337f173c2b7SSean Bruno if_setsoftc(ifp, lio); 1338f173c2b7SSean Bruno 13392c50292dSJustin Hibbits if_sethwtsomax(ifp, LIO_MAX_FRAME_SIZE); 13402c50292dSJustin Hibbits if_sethwtsomaxsegcount(ifp, LIO_MAX_SG); 13412c50292dSJustin Hibbits if_sethwtsomaxsegsize(ifp, PAGE_SIZE); 1342f173c2b7SSean Bruno 1343f173c2b7SSean Bruno lio->ifidx = ifidx_or_pfnum; 1344f173c2b7SSean Bruno 1345f173c2b7SSean Bruno props = &octeon_dev->props; 1346f173c2b7SSean Bruno props->gmxport = resp->cfg_info.linfo.gmxport; 1347f173c2b7SSean Bruno props->ifp = ifp; 1348f173c2b7SSean Bruno 1349f173c2b7SSean Bruno lio->linfo.num_rxpciq = num_oqueues; 1350f173c2b7SSean Bruno lio->linfo.num_txpciq = num_iqueues; 1351f173c2b7SSean Bruno for (j = 0; j < num_oqueues; j++) { 1352f173c2b7SSean Bruno lio->linfo.rxpciq[j].rxpciq64 = 1353f173c2b7SSean Bruno resp->cfg_info.linfo.rxpciq[j].rxpciq64; 1354f173c2b7SSean Bruno } 1355f173c2b7SSean Bruno 1356f173c2b7SSean Bruno for (j = 0; j < num_iqueues; j++) { 1357f173c2b7SSean Bruno lio->linfo.txpciq[j].txpciq64 = 1358f173c2b7SSean Bruno resp->cfg_info.linfo.txpciq[j].txpciq64; 1359f173c2b7SSean Bruno } 1360f173c2b7SSean Bruno 1361f173c2b7SSean Bruno lio->linfo.hw_addr = resp->cfg_info.linfo.hw_addr; 1362f173c2b7SSean Bruno lio->linfo.gmxport = resp->cfg_info.linfo.gmxport; 1363f173c2b7SSean Bruno lio->linfo.link.link_status64 = 1364f173c2b7SSean Bruno resp->cfg_info.linfo.link.link_status64; 1365f173c2b7SSean Bruno 1366f173c2b7SSean Bruno /* 1367f173c2b7SSean Bruno * Point to the properties for octeon device to which this 1368f173c2b7SSean Bruno * interface belongs. 1369f173c2b7SSean Bruno */ 1370f173c2b7SSean Bruno lio->oct_dev = octeon_dev; 1371f173c2b7SSean Bruno lio->ifp = ifp; 1372f173c2b7SSean Bruno 1373f173c2b7SSean Bruno lio_dev_dbg(octeon_dev, "if%d gmx: %d hw_addr: 0x%llx\n", i, 1374f173c2b7SSean Bruno lio->linfo.gmxport, LIO_CAST64(lio->linfo.hw_addr)); 1375f173c2b7SSean Bruno lio_init_ifnet(lio); 1376f173c2b7SSean Bruno /* 64-bit swap required on LE machines */ 1377f173c2b7SSean Bruno lio_swap_8B_data(&lio->linfo.hw_addr, 1); 1378f173c2b7SSean Bruno for (j = 0; j < 6; j++) 1379f173c2b7SSean Bruno mac[j] = *((uint8_t *)( 1380f173c2b7SSean Bruno ((uint8_t *)&lio->linfo.hw_addr) + 2 + j)); 1381f173c2b7SSean Bruno 1382f173c2b7SSean Bruno ether_ifattach(ifp, mac); 1383f173c2b7SSean Bruno 1384f173c2b7SSean Bruno /* 1385f173c2b7SSean Bruno * By default all interfaces on a single Octeon uses the same 1386f173c2b7SSean Bruno * tx and rx queues 1387f173c2b7SSean Bruno */ 1388f173c2b7SSean Bruno lio->txq = lio->linfo.txpciq[0].s.q_no; 1389f173c2b7SSean Bruno lio->rxq = lio->linfo.rxpciq[0].s.q_no; 1390f173c2b7SSean Bruno if (lio_setup_io_queues(octeon_dev, i, lio->linfo.num_txpciq, 1391f173c2b7SSean Bruno lio->linfo.num_rxpciq)) { 1392f173c2b7SSean Bruno lio_dev_err(octeon_dev, "I/O queues creation failed\n"); 1393f173c2b7SSean Bruno goto setup_nic_dev_fail; 1394f173c2b7SSean Bruno } 1395f173c2b7SSean Bruno 1396f173c2b7SSean Bruno lio_ifstate_set(lio, LIO_IFSTATE_DROQ_OPS); 1397f173c2b7SSean Bruno 1398f173c2b7SSean Bruno lio->tx_qsize = lio_get_tx_qsize(octeon_dev, lio->txq); 1399f173c2b7SSean Bruno lio->rx_qsize = lio_get_rx_qsize(octeon_dev, lio->rxq); 1400f173c2b7SSean Bruno 1401f173c2b7SSean Bruno if (lio_setup_glists(octeon_dev, lio, num_iqueues)) { 1402f173c2b7SSean Bruno lio_dev_err(octeon_dev, "Gather list allocation failed\n"); 1403f173c2b7SSean Bruno goto setup_nic_dev_fail; 1404f173c2b7SSean Bruno } 1405f173c2b7SSean Bruno 1406f173c2b7SSean Bruno if ((lio_hwlro == 0) && lio_tcp_lro_init(octeon_dev, ifp)) 1407f173c2b7SSean Bruno goto setup_nic_dev_fail; 1408f173c2b7SSean Bruno 1409f173c2b7SSean Bruno if (lio_hwlro && 1410f173c2b7SSean Bruno (if_getcapenable(ifp) & IFCAP_LRO) && 1411f173c2b7SSean Bruno (if_getcapenable(ifp) & IFCAP_RXCSUM) && 1412f173c2b7SSean Bruno (if_getcapenable(ifp) & IFCAP_RXCSUM_IPV6)) 1413f173c2b7SSean Bruno lio_set_feature(ifp, LIO_CMD_LRO_ENABLE, 1414f173c2b7SSean Bruno LIO_LROIPV4 | LIO_LROIPV6); 1415f173c2b7SSean Bruno 1416f173c2b7SSean Bruno if ((if_getcapenable(ifp) & IFCAP_VLAN_HWFILTER)) 1417f173c2b7SSean Bruno lio_set_feature(ifp, LIO_CMD_VLAN_FILTER_CTL, 1); 1418f173c2b7SSean Bruno else 1419f173c2b7SSean Bruno lio_set_feature(ifp, LIO_CMD_VLAN_FILTER_CTL, 0); 1420f173c2b7SSean Bruno 1421f173c2b7SSean Bruno if (lio_setup_rx_oom_poll_fn(ifp)) 1422f173c2b7SSean Bruno goto setup_nic_dev_fail; 1423f173c2b7SSean Bruno 1424f173c2b7SSean Bruno lio_dev_dbg(octeon_dev, "Setup NIC ifidx:%d mac:%02x%02x%02x%02x%02x%02x\n", 1425f173c2b7SSean Bruno i, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); 1426f173c2b7SSean Bruno lio->link_changes++; 1427f173c2b7SSean Bruno 1428f173c2b7SSean Bruno lio_ifstate_set(lio, LIO_IFSTATE_REGISTERED); 1429f173c2b7SSean Bruno 1430f173c2b7SSean Bruno /* 1431f173c2b7SSean Bruno * Sending command to firmware to enable Rx checksum offload 1432f173c2b7SSean Bruno * by default at the time of setup of Liquidio driver for 1433f173c2b7SSean Bruno * this device 1434f173c2b7SSean Bruno */ 1435f173c2b7SSean Bruno lio_set_rxcsum_command(ifp, LIO_CMD_TNL_RX_CSUM_CTL, 1436f173c2b7SSean Bruno LIO_CMD_RXCSUM_ENABLE); 1437f173c2b7SSean Bruno lio_set_feature(ifp, LIO_CMD_TNL_TX_CSUM_CTL, 1438f173c2b7SSean Bruno LIO_CMD_TXCSUM_ENABLE); 1439f173c2b7SSean Bruno 1440f173c2b7SSean Bruno #ifdef RSS 1441f173c2b7SSean Bruno if (lio_rss) { 1442f173c2b7SSean Bruno if (lio_send_rss_param(lio)) 1443f173c2b7SSean Bruno goto setup_nic_dev_fail; 1444f173c2b7SSean Bruno } else 1445f173c2b7SSean Bruno #endif /* RSS */ 1446f173c2b7SSean Bruno 1447f173c2b7SSean Bruno lio_set_feature(ifp, LIO_CMD_SET_FNV, 1448f173c2b7SSean Bruno LIO_CMD_FNV_ENABLE); 1449f173c2b7SSean Bruno 1450f173c2b7SSean Bruno lio_dev_dbg(octeon_dev, "NIC ifidx:%d Setup successful\n", i); 1451f173c2b7SSean Bruno 1452f173c2b7SSean Bruno lio_free_soft_command(octeon_dev, sc); 1453f173c2b7SSean Bruno lio->vlan_attach = 1454f173c2b7SSean Bruno EVENTHANDLER_REGISTER(vlan_config, 1455f173c2b7SSean Bruno lio_vlan_rx_add_vid, lio, 1456f173c2b7SSean Bruno EVENTHANDLER_PRI_FIRST); 1457f173c2b7SSean Bruno lio->vlan_detach = 1458f173c2b7SSean Bruno EVENTHANDLER_REGISTER(vlan_unconfig, 1459f173c2b7SSean Bruno lio_vlan_rx_kill_vid, lio, 1460f173c2b7SSean Bruno EVENTHANDLER_PRI_FIRST); 1461f173c2b7SSean Bruno 1462f173c2b7SSean Bruno /* Update stats periodically */ 1463f173c2b7SSean Bruno callout_init(&lio->stats_timer, 0); 1464f173c2b7SSean Bruno lio->stats_interval = LIO_DEFAULT_STATS_INTERVAL; 1465f173c2b7SSean Bruno 1466f173c2b7SSean Bruno lio_add_hw_stats(lio); 1467f173c2b7SSean Bruno } 1468f173c2b7SSean Bruno 1469f173c2b7SSean Bruno return (0); 1470f173c2b7SSean Bruno 1471f173c2b7SSean Bruno setup_nic_dev_fail: 1472f173c2b7SSean Bruno 1473f173c2b7SSean Bruno lio_free_soft_command(octeon_dev, sc); 1474f173c2b7SSean Bruno 1475f173c2b7SSean Bruno while (i--) { 1476f173c2b7SSean Bruno lio_dev_err(octeon_dev, "NIC ifidx:%d Setup failed\n", i); 1477f173c2b7SSean Bruno lio_destroy_nic_device(octeon_dev, i); 1478f173c2b7SSean Bruno } 1479f173c2b7SSean Bruno 1480f173c2b7SSean Bruno return (ENODEV); 1481f173c2b7SSean Bruno } 1482f173c2b7SSean Bruno 1483f173c2b7SSean Bruno static int 1484f173c2b7SSean Bruno lio_link_info(struct lio_recv_info *recv_info, void *ptr) 1485f173c2b7SSean Bruno { 1486f173c2b7SSean Bruno struct octeon_device *oct = (struct octeon_device *)ptr; 1487f173c2b7SSean Bruno struct lio_recv_pkt *recv_pkt = recv_info->recv_pkt; 1488f173c2b7SSean Bruno union octeon_link_status *ls; 1489f173c2b7SSean Bruno int gmxport = 0, i; 1490f173c2b7SSean Bruno 1491f173c2b7SSean Bruno lio_dev_dbg(oct, "%s Called\n", __func__); 1492f173c2b7SSean Bruno if (recv_pkt->buffer_size[0] != (sizeof(*ls) + LIO_DROQ_INFO_SIZE)) { 1493f173c2b7SSean Bruno lio_dev_err(oct, "Malformed NIC_INFO, len=%d, ifidx=%d\n", 1494f173c2b7SSean Bruno recv_pkt->buffer_size[0], 1495f173c2b7SSean Bruno recv_pkt->rh.r_nic_info.gmxport); 1496f173c2b7SSean Bruno goto nic_info_err; 1497f173c2b7SSean Bruno } 1498f173c2b7SSean Bruno gmxport = recv_pkt->rh.r_nic_info.gmxport; 1499f173c2b7SSean Bruno ls = (union octeon_link_status *)(recv_pkt->buffer_ptr[0]->m_data + 1500f173c2b7SSean Bruno LIO_DROQ_INFO_SIZE); 1501f173c2b7SSean Bruno lio_swap_8B_data((uint64_t *)ls, 1502f173c2b7SSean Bruno (sizeof(union octeon_link_status)) >> 3); 1503f173c2b7SSean Bruno 1504f173c2b7SSean Bruno if (oct->props.gmxport == gmxport) 1505f173c2b7SSean Bruno lio_update_link_status(oct->props.ifp, ls); 1506f173c2b7SSean Bruno 1507f173c2b7SSean Bruno nic_info_err: 1508f173c2b7SSean Bruno for (i = 0; i < recv_pkt->buffer_count; i++) 1509f173c2b7SSean Bruno lio_recv_buffer_free(recv_pkt->buffer_ptr[i]); 1510f173c2b7SSean Bruno 1511f173c2b7SSean Bruno lio_free_recv_info(recv_info); 1512f173c2b7SSean Bruno return (0); 1513f173c2b7SSean Bruno } 1514f173c2b7SSean Bruno 1515f173c2b7SSean Bruno void 1516f173c2b7SSean Bruno lio_free_mbuf(struct lio_instr_queue *iq, struct lio_mbuf_free_info *finfo) 1517f173c2b7SSean Bruno { 1518f173c2b7SSean Bruno 1519f173c2b7SSean Bruno bus_dmamap_sync(iq->txtag, finfo->map, BUS_DMASYNC_POSTWRITE); 1520f173c2b7SSean Bruno bus_dmamap_unload(iq->txtag, finfo->map); 1521f173c2b7SSean Bruno m_freem(finfo->mb); 1522f173c2b7SSean Bruno } 1523f173c2b7SSean Bruno 1524f173c2b7SSean Bruno void 1525f173c2b7SSean Bruno lio_free_sgmbuf(struct lio_instr_queue *iq, struct lio_mbuf_free_info *finfo) 1526f173c2b7SSean Bruno { 1527f173c2b7SSean Bruno struct lio_gather *g; 1528f173c2b7SSean Bruno struct octeon_device *oct; 1529f173c2b7SSean Bruno struct lio *lio; 1530f173c2b7SSean Bruno int iq_no; 1531f173c2b7SSean Bruno 1532f173c2b7SSean Bruno g = finfo->g; 1533f173c2b7SSean Bruno iq_no = iq->txpciq.s.q_no; 1534f173c2b7SSean Bruno oct = iq->oct_dev; 1535f173c2b7SSean Bruno lio = if_getsoftc(oct->props.ifp); 1536f173c2b7SSean Bruno 1537f173c2b7SSean Bruno mtx_lock(&lio->glist_lock[iq_no]); 1538f173c2b7SSean Bruno STAILQ_INSERT_TAIL(&lio->ghead[iq_no], &g->node, entries); 1539f173c2b7SSean Bruno mtx_unlock(&lio->glist_lock[iq_no]); 1540f173c2b7SSean Bruno 1541f173c2b7SSean Bruno bus_dmamap_sync(iq->txtag, finfo->map, BUS_DMASYNC_POSTWRITE); 1542f173c2b7SSean Bruno bus_dmamap_unload(iq->txtag, finfo->map); 1543f173c2b7SSean Bruno m_freem(finfo->mb); 1544f173c2b7SSean Bruno } 1545f173c2b7SSean Bruno 1546f173c2b7SSean Bruno static void 1547f173c2b7SSean Bruno lio_if_cfg_callback(struct octeon_device *oct, uint32_t status, void *buf) 1548f173c2b7SSean Bruno { 1549f173c2b7SSean Bruno struct lio_soft_command *sc = (struct lio_soft_command *)buf; 1550f173c2b7SSean Bruno struct lio_if_cfg_resp *resp; 1551f173c2b7SSean Bruno struct lio_if_cfg_context *ctx; 1552f173c2b7SSean Bruno 1553f173c2b7SSean Bruno resp = (struct lio_if_cfg_resp *)sc->virtrptr; 1554f173c2b7SSean Bruno ctx = (struct lio_if_cfg_context *)sc->ctxptr; 1555f173c2b7SSean Bruno 1556f173c2b7SSean Bruno oct = lio_get_device(ctx->octeon_id); 1557f173c2b7SSean Bruno if (resp->status) 1558f173c2b7SSean Bruno lio_dev_err(oct, "nic if cfg instruction failed. Status: %llx (0x%08x)\n", 1559f173c2b7SSean Bruno LIO_CAST64(resp->status), status); 1560f173c2b7SSean Bruno ctx->cond = 1; 1561f173c2b7SSean Bruno 1562f173c2b7SSean Bruno snprintf(oct->fw_info.lio_firmware_version, 32, "%s", 1563f173c2b7SSean Bruno resp->cfg_info.lio_firmware_version); 1564f173c2b7SSean Bruno 1565f173c2b7SSean Bruno /* 1566f173c2b7SSean Bruno * This barrier is required to be sure that the response has been 1567f173c2b7SSean Bruno * written fully before waking up the handler 1568f173c2b7SSean Bruno */ 1569f173c2b7SSean Bruno wmb(); 1570f173c2b7SSean Bruno } 1571f173c2b7SSean Bruno 1572f173c2b7SSean Bruno static int 1573f173c2b7SSean Bruno lio_is_mac_changed(uint8_t *new, uint8_t *old) 1574f173c2b7SSean Bruno { 1575f173c2b7SSean Bruno 1576f173c2b7SSean Bruno return ((new[0] != old[0]) || (new[1] != old[1]) || 1577f173c2b7SSean Bruno (new[2] != old[2]) || (new[3] != old[3]) || 1578f173c2b7SSean Bruno (new[4] != old[4]) || (new[5] != old[5])); 1579f173c2b7SSean Bruno } 1580f173c2b7SSean Bruno 1581f173c2b7SSean Bruno void 1582f173c2b7SSean Bruno lio_open(void *arg) 1583f173c2b7SSean Bruno { 1584f173c2b7SSean Bruno struct lio *lio = arg; 15852c50292dSJustin Hibbits if_t ifp = lio->ifp; 1586f173c2b7SSean Bruno struct octeon_device *oct = lio->oct_dev; 1587f173c2b7SSean Bruno uint8_t *mac_new, mac_old[ETHER_HDR_LEN]; 1588f173c2b7SSean Bruno int ret = 0; 1589f173c2b7SSean Bruno 1590f173c2b7SSean Bruno lio_ifstate_set(lio, LIO_IFSTATE_RUNNING); 1591f173c2b7SSean Bruno 1592f173c2b7SSean Bruno /* Ready for link status updates */ 1593f173c2b7SSean Bruno lio->intf_open = 1; 1594f173c2b7SSean Bruno 1595f173c2b7SSean Bruno lio_dev_info(oct, "Interface Open, ready for traffic\n"); 1596f173c2b7SSean Bruno 1597f173c2b7SSean Bruno /* tell Octeon to start forwarding packets to host */ 1598f173c2b7SSean Bruno lio_send_rx_ctrl_cmd(lio, 1); 1599f173c2b7SSean Bruno 16002c50292dSJustin Hibbits mac_new = if_getlladdr(ifp); 1601f173c2b7SSean Bruno memcpy(mac_old, ((uint8_t *)&lio->linfo.hw_addr) + 2, ETHER_HDR_LEN); 1602f173c2b7SSean Bruno 1603f173c2b7SSean Bruno if (lio_is_mac_changed(mac_new, mac_old)) { 1604f173c2b7SSean Bruno ret = lio_set_mac(ifp, mac_new); 1605f173c2b7SSean Bruno if (ret) 1606f173c2b7SSean Bruno lio_dev_err(oct, "MAC change failed, error: %d\n", ret); 1607f173c2b7SSean Bruno } 1608f173c2b7SSean Bruno 1609f173c2b7SSean Bruno /* Now inform the stack we're ready */ 1610f173c2b7SSean Bruno if_setdrvflagbits(ifp, IFF_DRV_RUNNING, 0); 1611f173c2b7SSean Bruno 1612f173c2b7SSean Bruno lio_dev_info(oct, "Interface is opened\n"); 1613f173c2b7SSean Bruno } 1614f173c2b7SSean Bruno 1615f173c2b7SSean Bruno static int 16162c50292dSJustin Hibbits lio_set_rxcsum_command(if_t ifp, int command, uint8_t rx_cmd) 1617f173c2b7SSean Bruno { 1618f173c2b7SSean Bruno struct lio_ctrl_pkt nctrl; 1619f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1620f173c2b7SSean Bruno struct octeon_device *oct = lio->oct_dev; 1621f173c2b7SSean Bruno int ret = 0; 1622f173c2b7SSean Bruno 1623f173c2b7SSean Bruno nctrl.ncmd.cmd64 = 0; 1624f173c2b7SSean Bruno nctrl.ncmd.s.cmd = command; 1625f173c2b7SSean Bruno nctrl.ncmd.s.param1 = rx_cmd; 1626f173c2b7SSean Bruno nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 1627f173c2b7SSean Bruno nctrl.wait_time = 100; 1628f173c2b7SSean Bruno nctrl.lio = lio; 1629f173c2b7SSean Bruno nctrl.cb_fn = lio_ctrl_cmd_completion; 1630f173c2b7SSean Bruno 1631f173c2b7SSean Bruno ret = lio_send_ctrl_pkt(lio->oct_dev, &nctrl); 1632f173c2b7SSean Bruno if (ret < 0) { 1633f173c2b7SSean Bruno lio_dev_err(oct, "DEVFLAGS RXCSUM change failed in core(ret:0x%x)\n", 1634f173c2b7SSean Bruno ret); 1635f173c2b7SSean Bruno } 1636f173c2b7SSean Bruno 1637f173c2b7SSean Bruno return (ret); 1638f173c2b7SSean Bruno } 1639f173c2b7SSean Bruno 1640f173c2b7SSean Bruno static int 1641f173c2b7SSean Bruno lio_stop_nic_module(struct octeon_device *oct) 1642f173c2b7SSean Bruno { 1643f173c2b7SSean Bruno int i, j; 1644f173c2b7SSean Bruno struct lio *lio; 1645f173c2b7SSean Bruno 1646f173c2b7SSean Bruno lio_dev_dbg(oct, "Stopping network interfaces\n"); 1647f173c2b7SSean Bruno if (!oct->ifcount) { 1648f173c2b7SSean Bruno lio_dev_err(oct, "Init for Octeon was not completed\n"); 1649f173c2b7SSean Bruno return (1); 1650f173c2b7SSean Bruno } 1651f173c2b7SSean Bruno 1652f173c2b7SSean Bruno mtx_lock(&oct->cmd_resp_wqlock); 1653f173c2b7SSean Bruno oct->cmd_resp_state = LIO_DRV_OFFLINE; 1654f173c2b7SSean Bruno mtx_unlock(&oct->cmd_resp_wqlock); 1655f173c2b7SSean Bruno 1656f173c2b7SSean Bruno for (i = 0; i < oct->ifcount; i++) { 1657f173c2b7SSean Bruno lio = if_getsoftc(oct->props.ifp); 1658f173c2b7SSean Bruno for (j = 0; j < oct->num_oqs; j++) 1659f173c2b7SSean Bruno lio_unregister_droq_ops(oct, 1660f173c2b7SSean Bruno lio->linfo.rxpciq[j].s.q_no); 1661f173c2b7SSean Bruno } 1662f173c2b7SSean Bruno 1663f173c2b7SSean Bruno callout_drain(&lio->stats_timer); 1664f173c2b7SSean Bruno 1665f173c2b7SSean Bruno for (i = 0; i < oct->ifcount; i++) 1666f173c2b7SSean Bruno lio_destroy_nic_device(oct, i); 1667f173c2b7SSean Bruno 1668f173c2b7SSean Bruno lio_dev_dbg(oct, "Network interface stopped\n"); 1669f173c2b7SSean Bruno 1670f173c2b7SSean Bruno return (0); 1671f173c2b7SSean Bruno } 1672f173c2b7SSean Bruno 1673f173c2b7SSean Bruno static void 1674f173c2b7SSean Bruno lio_delete_glists(struct octeon_device *oct, struct lio *lio) 1675f173c2b7SSean Bruno { 1676f173c2b7SSean Bruno struct lio_gather *g; 1677f173c2b7SSean Bruno int i; 1678f173c2b7SSean Bruno 1679f173c2b7SSean Bruno if (lio->glist_lock != NULL) { 1680f173c2b7SSean Bruno free((void *)lio->glist_lock, M_DEVBUF); 1681f173c2b7SSean Bruno lio->glist_lock = NULL; 1682f173c2b7SSean Bruno } 1683f173c2b7SSean Bruno 1684f173c2b7SSean Bruno if (lio->ghead == NULL) 1685f173c2b7SSean Bruno return; 1686f173c2b7SSean Bruno 1687f173c2b7SSean Bruno for (i = 0; i < lio->linfo.num_txpciq; i++) { 1688f173c2b7SSean Bruno do { 1689f173c2b7SSean Bruno g = (struct lio_gather *) 1690f173c2b7SSean Bruno lio_delete_first_node(&lio->ghead[i]); 1691f173c2b7SSean Bruno free(g, M_DEVBUF); 1692f173c2b7SSean Bruno } while (g); 1693f173c2b7SSean Bruno 1694f173c2b7SSean Bruno if ((lio->glists_virt_base != NULL) && 1695f173c2b7SSean Bruno (lio->glists_virt_base[i] != NULL)) { 1696f173c2b7SSean Bruno lio_dma_free(lio->glist_entry_size * lio->tx_qsize, 1697f173c2b7SSean Bruno lio->glists_virt_base[i]); 1698f173c2b7SSean Bruno } 1699f173c2b7SSean Bruno } 1700f173c2b7SSean Bruno 1701f173c2b7SSean Bruno free(lio->glists_virt_base, M_DEVBUF); 1702f173c2b7SSean Bruno lio->glists_virt_base = NULL; 1703f173c2b7SSean Bruno 1704f173c2b7SSean Bruno free(lio->glists_dma_base, M_DEVBUF); 1705f173c2b7SSean Bruno lio->glists_dma_base = NULL; 1706f173c2b7SSean Bruno 1707f173c2b7SSean Bruno free(lio->ghead, M_DEVBUF); 1708f173c2b7SSean Bruno lio->ghead = NULL; 1709f173c2b7SSean Bruno } 1710f173c2b7SSean Bruno 1711f173c2b7SSean Bruno static int 1712f173c2b7SSean Bruno lio_setup_glists(struct octeon_device *oct, struct lio *lio, int num_iqs) 1713f173c2b7SSean Bruno { 1714f173c2b7SSean Bruno struct lio_gather *g; 1715f173c2b7SSean Bruno int i, j; 1716f173c2b7SSean Bruno 1717ac2fffa4SPedro F. Giffuni lio->glist_lock = malloc(num_iqs * sizeof(*lio->glist_lock), M_DEVBUF, 1718ac2fffa4SPedro F. Giffuni M_NOWAIT | M_ZERO); 1719f173c2b7SSean Bruno if (lio->glist_lock == NULL) 1720f173c2b7SSean Bruno return (1); 1721f173c2b7SSean Bruno 1722ac2fffa4SPedro F. Giffuni lio->ghead = malloc(num_iqs * sizeof(*lio->ghead), M_DEVBUF, 1723f173c2b7SSean Bruno M_NOWAIT | M_ZERO); 1724f173c2b7SSean Bruno if (lio->ghead == NULL) { 1725f173c2b7SSean Bruno free((void *)lio->glist_lock, M_DEVBUF); 1726f173c2b7SSean Bruno lio->glist_lock = NULL; 1727f173c2b7SSean Bruno return (1); 1728f173c2b7SSean Bruno } 1729f173c2b7SSean Bruno 1730f173c2b7SSean Bruno lio->glist_entry_size = ROUNDUP8((ROUNDUP4(LIO_MAX_SG) >> 2) * 1731f173c2b7SSean Bruno LIO_SG_ENTRY_SIZE); 1732f173c2b7SSean Bruno /* 1733f173c2b7SSean Bruno * allocate memory to store virtual and dma base address of 1734f173c2b7SSean Bruno * per glist consistent memory 1735f173c2b7SSean Bruno */ 1736ac2fffa4SPedro F. Giffuni lio->glists_virt_base = malloc(num_iqs * sizeof(void *), M_DEVBUF, 1737f173c2b7SSean Bruno M_NOWAIT | M_ZERO); 1738ac2fffa4SPedro F. Giffuni lio->glists_dma_base = malloc(num_iqs * sizeof(vm_paddr_t), M_DEVBUF, 1739ac2fffa4SPedro F. Giffuni M_NOWAIT | M_ZERO); 1740f173c2b7SSean Bruno if ((lio->glists_virt_base == NULL) || (lio->glists_dma_base == NULL)) { 1741f173c2b7SSean Bruno lio_delete_glists(oct, lio); 1742f173c2b7SSean Bruno return (1); 1743f173c2b7SSean Bruno } 1744f173c2b7SSean Bruno 1745f173c2b7SSean Bruno for (i = 0; i < num_iqs; i++) { 1746f173c2b7SSean Bruno mtx_init(&lio->glist_lock[i], "glist_lock", NULL, MTX_DEF); 1747f173c2b7SSean Bruno 1748f173c2b7SSean Bruno STAILQ_INIT(&lio->ghead[i]); 1749f173c2b7SSean Bruno 1750f173c2b7SSean Bruno lio->glists_virt_base[i] = 1751f173c2b7SSean Bruno lio_dma_alloc(lio->glist_entry_size * lio->tx_qsize, 1752f173c2b7SSean Bruno (vm_paddr_t *)&lio->glists_dma_base[i]); 1753f173c2b7SSean Bruno if (lio->glists_virt_base[i] == NULL) { 1754f173c2b7SSean Bruno lio_delete_glists(oct, lio); 1755f173c2b7SSean Bruno return (1); 1756f173c2b7SSean Bruno } 1757f173c2b7SSean Bruno 1758f173c2b7SSean Bruno for (j = 0; j < lio->tx_qsize; j++) { 1759f173c2b7SSean Bruno g = malloc(sizeof(*g), M_DEVBUF, M_NOWAIT | M_ZERO); 1760f173c2b7SSean Bruno if (g == NULL) 1761f173c2b7SSean Bruno break; 1762f173c2b7SSean Bruno 17632b6fe1b2SDimitry Andric g->sg = (struct lio_sg_entry *)(uintptr_t) 17642b6fe1b2SDimitry Andric ((uint64_t)(uintptr_t)lio->glists_virt_base[i] + 1765f173c2b7SSean Bruno (j * lio->glist_entry_size)); 1766f173c2b7SSean Bruno g->sg_dma_ptr = (uint64_t)lio->glists_dma_base[i] + 1767f173c2b7SSean Bruno (j * lio->glist_entry_size); 1768f173c2b7SSean Bruno STAILQ_INSERT_TAIL(&lio->ghead[i], &g->node, entries); 1769f173c2b7SSean Bruno } 1770f173c2b7SSean Bruno 1771f173c2b7SSean Bruno if (j != lio->tx_qsize) { 1772f173c2b7SSean Bruno lio_delete_glists(oct, lio); 1773f173c2b7SSean Bruno return (1); 1774f173c2b7SSean Bruno } 1775f173c2b7SSean Bruno } 1776f173c2b7SSean Bruno 1777f173c2b7SSean Bruno return (0); 1778f173c2b7SSean Bruno } 1779f173c2b7SSean Bruno 1780f173c2b7SSean Bruno void 17812c50292dSJustin Hibbits lio_stop(if_t ifp) 1782f173c2b7SSean Bruno { 1783f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1784f173c2b7SSean Bruno struct octeon_device *oct = lio->oct_dev; 1785f173c2b7SSean Bruno 1786f173c2b7SSean Bruno lio_ifstate_reset(lio, LIO_IFSTATE_RUNNING); 1787f173c2b7SSean Bruno if_link_state_change(ifp, LINK_STATE_DOWN); 1788f173c2b7SSean Bruno 1789f173c2b7SSean Bruno lio->intf_open = 0; 1790f173c2b7SSean Bruno lio->linfo.link.s.link_up = 0; 1791f173c2b7SSean Bruno lio->link_changes++; 1792f173c2b7SSean Bruno 1793f173c2b7SSean Bruno lio_send_rx_ctrl_cmd(lio, 0); 1794f173c2b7SSean Bruno 1795f173c2b7SSean Bruno /* Tell the stack that the interface is no longer active */ 1796f173c2b7SSean Bruno if_setdrvflagbits(ifp, 0, IFF_DRV_RUNNING); 1797f173c2b7SSean Bruno 1798f173c2b7SSean Bruno lio_dev_info(oct, "Interface is stopped\n"); 1799f173c2b7SSean Bruno } 1800f173c2b7SSean Bruno 1801f173c2b7SSean Bruno static void 1802f173c2b7SSean Bruno lio_check_rx_oom_status(struct lio *lio) 1803f173c2b7SSean Bruno { 1804f173c2b7SSean Bruno struct lio_droq *droq; 1805f173c2b7SSean Bruno struct octeon_device *oct = lio->oct_dev; 1806f173c2b7SSean Bruno int desc_refilled; 1807f173c2b7SSean Bruno int q, q_no = 0; 1808f173c2b7SSean Bruno 1809f173c2b7SSean Bruno for (q = 0; q < oct->num_oqs; q++) { 1810f173c2b7SSean Bruno q_no = lio->linfo.rxpciq[q].s.q_no; 1811f173c2b7SSean Bruno droq = oct->droq[q_no]; 1812f173c2b7SSean Bruno if (droq == NULL) 1813f173c2b7SSean Bruno continue; 1814f173c2b7SSean Bruno if (lio_read_csr32(oct, droq->pkts_credit_reg) <= 0x40) { 1815f173c2b7SSean Bruno mtx_lock(&droq->lock); 1816f173c2b7SSean Bruno desc_refilled = lio_droq_refill(oct, droq); 1817f173c2b7SSean Bruno /* 1818f173c2b7SSean Bruno * Flush the droq descriptor data to memory to be sure 1819f173c2b7SSean Bruno * that when we update the credits the data in memory 1820f173c2b7SSean Bruno * is accurate. 1821f173c2b7SSean Bruno */ 1822f173c2b7SSean Bruno wmb(); 1823f173c2b7SSean Bruno lio_write_csr32(oct, droq->pkts_credit_reg, 1824f173c2b7SSean Bruno desc_refilled); 1825f173c2b7SSean Bruno /* make sure mmio write completes */ 1826f173c2b7SSean Bruno __compiler_membar(); 1827f173c2b7SSean Bruno mtx_unlock(&droq->lock); 1828f173c2b7SSean Bruno } 1829f173c2b7SSean Bruno } 1830f173c2b7SSean Bruno } 1831f173c2b7SSean Bruno 1832f173c2b7SSean Bruno static void 1833f173c2b7SSean Bruno lio_poll_check_rx_oom_status(void *arg, int pending __unused) 1834f173c2b7SSean Bruno { 1835f173c2b7SSean Bruno struct lio_tq *rx_status_tq = arg; 1836f173c2b7SSean Bruno struct lio *lio = rx_status_tq->ctxptr; 1837f173c2b7SSean Bruno 1838f173c2b7SSean Bruno if (lio_ifstate_check(lio, LIO_IFSTATE_RUNNING)) 1839f173c2b7SSean Bruno lio_check_rx_oom_status(lio); 1840f173c2b7SSean Bruno 1841f173c2b7SSean Bruno taskqueue_enqueue_timeout(rx_status_tq->tq, &rx_status_tq->work, 1842f173c2b7SSean Bruno lio_ms_to_ticks(50)); 1843f173c2b7SSean Bruno } 1844f173c2b7SSean Bruno 1845f173c2b7SSean Bruno static int 18462c50292dSJustin Hibbits lio_setup_rx_oom_poll_fn(if_t ifp) 1847f173c2b7SSean Bruno { 1848f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1849f173c2b7SSean Bruno struct octeon_device *oct = lio->oct_dev; 1850f173c2b7SSean Bruno struct lio_tq *rx_status_tq; 1851f173c2b7SSean Bruno 1852f173c2b7SSean Bruno rx_status_tq = &lio->rx_status_tq; 1853f173c2b7SSean Bruno 1854f173c2b7SSean Bruno rx_status_tq->tq = taskqueue_create("lio_rx_oom_status", M_WAITOK, 1855f173c2b7SSean Bruno taskqueue_thread_enqueue, 1856f173c2b7SSean Bruno &rx_status_tq->tq); 1857f173c2b7SSean Bruno 1858f173c2b7SSean Bruno TIMEOUT_TASK_INIT(rx_status_tq->tq, &rx_status_tq->work, 0, 1859f173c2b7SSean Bruno lio_poll_check_rx_oom_status, (void *)rx_status_tq); 1860f173c2b7SSean Bruno 1861f173c2b7SSean Bruno rx_status_tq->ctxptr = lio; 1862f173c2b7SSean Bruno 1863f173c2b7SSean Bruno taskqueue_start_threads(&rx_status_tq->tq, 1, PI_NET, 1864f173c2b7SSean Bruno "lio%d_rx_oom_status", 1865f173c2b7SSean Bruno oct->octeon_id); 1866f173c2b7SSean Bruno 1867f173c2b7SSean Bruno taskqueue_enqueue_timeout(rx_status_tq->tq, &rx_status_tq->work, 1868f173c2b7SSean Bruno lio_ms_to_ticks(50)); 1869f173c2b7SSean Bruno 1870f173c2b7SSean Bruno return (0); 1871f173c2b7SSean Bruno } 1872f173c2b7SSean Bruno 1873f173c2b7SSean Bruno static void 18742c50292dSJustin Hibbits lio_cleanup_rx_oom_poll_fn(if_t ifp) 1875f173c2b7SSean Bruno { 1876f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1877f173c2b7SSean Bruno 1878f173c2b7SSean Bruno if (lio->rx_status_tq.tq != NULL) { 1879f173c2b7SSean Bruno while (taskqueue_cancel_timeout(lio->rx_status_tq.tq, 1880f173c2b7SSean Bruno &lio->rx_status_tq.work, NULL)) 1881f173c2b7SSean Bruno taskqueue_drain_timeout(lio->rx_status_tq.tq, 1882f173c2b7SSean Bruno &lio->rx_status_tq.work); 1883f173c2b7SSean Bruno 1884f173c2b7SSean Bruno taskqueue_free(lio->rx_status_tq.tq); 1885f173c2b7SSean Bruno 1886f173c2b7SSean Bruno lio->rx_status_tq.tq = NULL; 1887f173c2b7SSean Bruno } 1888f173c2b7SSean Bruno } 1889f173c2b7SSean Bruno 1890f173c2b7SSean Bruno static void 1891f173c2b7SSean Bruno lio_destroy_nic_device(struct octeon_device *oct, int ifidx) 1892f173c2b7SSean Bruno { 18932c50292dSJustin Hibbits if_t ifp = oct->props.ifp; 1894f173c2b7SSean Bruno struct lio *lio; 1895f173c2b7SSean Bruno 1896f173c2b7SSean Bruno if (ifp == NULL) { 1897f173c2b7SSean Bruno lio_dev_err(oct, "%s No ifp ptr for index %d\n", 1898f173c2b7SSean Bruno __func__, ifidx); 1899f173c2b7SSean Bruno return; 1900f173c2b7SSean Bruno } 1901f173c2b7SSean Bruno 1902f173c2b7SSean Bruno lio = if_getsoftc(ifp); 1903f173c2b7SSean Bruno 1904f173c2b7SSean Bruno lio_ifstate_set(lio, LIO_IFSTATE_DETACH); 1905f173c2b7SSean Bruno 1906f173c2b7SSean Bruno lio_dev_dbg(oct, "NIC device cleanup\n"); 1907f173c2b7SSean Bruno 1908f173c2b7SSean Bruno if (atomic_load_acq_int(&lio->ifstate) & LIO_IFSTATE_RUNNING) 1909f173c2b7SSean Bruno lio_stop(ifp); 1910f173c2b7SSean Bruno 1911f173c2b7SSean Bruno if (lio_wait_for_pending_requests(oct)) 1912f173c2b7SSean Bruno lio_dev_err(oct, "There were pending requests\n"); 1913f173c2b7SSean Bruno 1914f173c2b7SSean Bruno if (lio_wait_for_instr_fetch(oct)) 1915f173c2b7SSean Bruno lio_dev_err(oct, "IQ had pending instructions\n"); 1916f173c2b7SSean Bruno 1917f173c2b7SSean Bruno if (lio_wait_for_oq_pkts(oct)) 1918f173c2b7SSean Bruno lio_dev_err(oct, "OQ had pending packets\n"); 1919f173c2b7SSean Bruno 1920f173c2b7SSean Bruno if (atomic_load_acq_int(&lio->ifstate) & LIO_IFSTATE_REGISTERED) 1921f173c2b7SSean Bruno ether_ifdetach(ifp); 1922f173c2b7SSean Bruno 1923f173c2b7SSean Bruno lio_tcp_lro_free(oct, ifp); 1924f173c2b7SSean Bruno 1925f173c2b7SSean Bruno lio_cleanup_rx_oom_poll_fn(ifp); 1926f173c2b7SSean Bruno 1927f173c2b7SSean Bruno lio_delete_glists(oct, lio); 1928f173c2b7SSean Bruno 1929f173c2b7SSean Bruno EVENTHANDLER_DEREGISTER(vlan_config, lio->vlan_attach); 1930f173c2b7SSean Bruno EVENTHANDLER_DEREGISTER(vlan_unconfig, lio->vlan_detach); 1931f173c2b7SSean Bruno 1932f173c2b7SSean Bruno free(lio, M_DEVBUF); 1933f173c2b7SSean Bruno 1934f173c2b7SSean Bruno if_free(ifp); 1935f173c2b7SSean Bruno 1936f173c2b7SSean Bruno oct->props.gmxport = -1; 1937f173c2b7SSean Bruno 1938f173c2b7SSean Bruno oct->props.ifp = NULL; 1939f173c2b7SSean Bruno } 1940f173c2b7SSean Bruno 1941f173c2b7SSean Bruno static void 19422c50292dSJustin Hibbits print_link_info(if_t ifp) 1943f173c2b7SSean Bruno { 1944f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1945f173c2b7SSean Bruno 1946f173c2b7SSean Bruno if (!lio_ifstate_check(lio, LIO_IFSTATE_RESETTING) && 1947f173c2b7SSean Bruno lio_ifstate_check(lio, LIO_IFSTATE_REGISTERED)) { 1948f173c2b7SSean Bruno struct octeon_link_info *linfo = &lio->linfo; 1949f173c2b7SSean Bruno 1950f173c2b7SSean Bruno if (linfo->link.s.link_up) { 1951f173c2b7SSean Bruno lio_dev_info(lio->oct_dev, "%d Mbps %s Duplex UP\n", 1952f173c2b7SSean Bruno linfo->link.s.speed, 1953f173c2b7SSean Bruno (linfo->link.s.duplex) ? "Full" : "Half"); 1954f173c2b7SSean Bruno } else { 1955f173c2b7SSean Bruno lio_dev_info(lio->oct_dev, "Link Down\n"); 1956f173c2b7SSean Bruno } 1957f173c2b7SSean Bruno } 1958f173c2b7SSean Bruno } 1959f173c2b7SSean Bruno 1960f173c2b7SSean Bruno static inline void 19612c50292dSJustin Hibbits lio_update_link_status(if_t ifp, union octeon_link_status *ls) 1962f173c2b7SSean Bruno { 1963f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 1964f173c2b7SSean Bruno int changed = (lio->linfo.link.link_status64 != ls->link_status64); 1965f173c2b7SSean Bruno 1966f173c2b7SSean Bruno lio->linfo.link.link_status64 = ls->link_status64; 1967f173c2b7SSean Bruno 1968f173c2b7SSean Bruno if ((lio->intf_open) && (changed)) { 1969f173c2b7SSean Bruno print_link_info(ifp); 1970f173c2b7SSean Bruno lio->link_changes++; 1971f173c2b7SSean Bruno if (lio->linfo.link.s.link_up) 1972f173c2b7SSean Bruno if_link_state_change(ifp, LINK_STATE_UP); 1973f173c2b7SSean Bruno else 1974f173c2b7SSean Bruno if_link_state_change(ifp, LINK_STATE_DOWN); 1975f173c2b7SSean Bruno } 1976f173c2b7SSean Bruno } 1977f173c2b7SSean Bruno 1978f173c2b7SSean Bruno /* 1979f173c2b7SSean Bruno * \brief Callback for rx ctrl 1980f173c2b7SSean Bruno * @param status status of request 1981f173c2b7SSean Bruno * @param buf pointer to resp structure 1982f173c2b7SSean Bruno */ 1983f173c2b7SSean Bruno static void 1984f173c2b7SSean Bruno lio_rx_ctl_callback(struct octeon_device *oct, uint32_t status, void *buf) 1985f173c2b7SSean Bruno { 1986f173c2b7SSean Bruno struct lio_soft_command *sc = (struct lio_soft_command *)buf; 1987f173c2b7SSean Bruno struct lio_rx_ctl_context *ctx; 1988f173c2b7SSean Bruno 1989f173c2b7SSean Bruno ctx = (struct lio_rx_ctl_context *)sc->ctxptr; 1990f173c2b7SSean Bruno 1991f173c2b7SSean Bruno oct = lio_get_device(ctx->octeon_id); 1992f173c2b7SSean Bruno if (status) 1993f173c2b7SSean Bruno lio_dev_err(oct, "rx ctl instruction failed. Status: %llx\n", 1994f173c2b7SSean Bruno LIO_CAST64(status)); 1995f173c2b7SSean Bruno ctx->cond = 1; 1996f173c2b7SSean Bruno 1997f173c2b7SSean Bruno /* 1998f173c2b7SSean Bruno * This barrier is required to be sure that the response has been 1999f173c2b7SSean Bruno * written fully before waking up the handler 2000f173c2b7SSean Bruno */ 2001f173c2b7SSean Bruno wmb(); 2002f173c2b7SSean Bruno } 2003f173c2b7SSean Bruno 2004f173c2b7SSean Bruno static void 2005f173c2b7SSean Bruno lio_send_rx_ctrl_cmd(struct lio *lio, int start_stop) 2006f173c2b7SSean Bruno { 2007f173c2b7SSean Bruno struct lio_soft_command *sc; 2008f173c2b7SSean Bruno struct lio_rx_ctl_context *ctx; 2009f173c2b7SSean Bruno union octeon_cmd *ncmd; 2010f173c2b7SSean Bruno struct octeon_device *oct = (struct octeon_device *)lio->oct_dev; 2011f173c2b7SSean Bruno int ctx_size = sizeof(struct lio_rx_ctl_context); 2012f173c2b7SSean Bruno int retval; 2013f173c2b7SSean Bruno 2014f173c2b7SSean Bruno if (oct->props.rx_on == start_stop) 2015f173c2b7SSean Bruno return; 2016f173c2b7SSean Bruno 2017f173c2b7SSean Bruno sc = lio_alloc_soft_command(oct, OCTEON_CMD_SIZE, 16, ctx_size); 2018f173c2b7SSean Bruno if (sc == NULL) 2019f173c2b7SSean Bruno return; 2020f173c2b7SSean Bruno 2021f173c2b7SSean Bruno ncmd = (union octeon_cmd *)sc->virtdptr; 2022f173c2b7SSean Bruno ctx = (struct lio_rx_ctl_context *)sc->ctxptr; 2023f173c2b7SSean Bruno 2024f173c2b7SSean Bruno ctx->cond = 0; 2025f173c2b7SSean Bruno ctx->octeon_id = lio_get_device_id(oct); 2026f173c2b7SSean Bruno ncmd->cmd64 = 0; 2027f173c2b7SSean Bruno ncmd->s.cmd = LIO_CMD_RX_CTL; 2028f173c2b7SSean Bruno ncmd->s.param1 = start_stop; 2029f173c2b7SSean Bruno 2030f173c2b7SSean Bruno lio_swap_8B_data((uint64_t *)ncmd, (OCTEON_CMD_SIZE >> 3)); 2031f173c2b7SSean Bruno 2032f173c2b7SSean Bruno sc->iq_no = lio->linfo.txpciq[0].s.q_no; 2033f173c2b7SSean Bruno 2034f173c2b7SSean Bruno lio_prepare_soft_command(oct, sc, LIO_OPCODE_NIC, LIO_OPCODE_NIC_CMD, 0, 2035f173c2b7SSean Bruno 0, 0); 2036f173c2b7SSean Bruno 2037f173c2b7SSean Bruno sc->callback = lio_rx_ctl_callback; 2038f173c2b7SSean Bruno sc->callback_arg = sc; 2039f173c2b7SSean Bruno sc->wait_time = 5000; 2040f173c2b7SSean Bruno 2041f173c2b7SSean Bruno retval = lio_send_soft_command(oct, sc); 2042f173c2b7SSean Bruno if (retval == LIO_IQ_SEND_FAILED) { 2043f173c2b7SSean Bruno lio_dev_err(oct, "Failed to send RX Control message\n"); 2044f173c2b7SSean Bruno } else { 2045f173c2b7SSean Bruno /* 2046f173c2b7SSean Bruno * Sleep on a wait queue till the cond flag indicates that the 2047f173c2b7SSean Bruno * response arrived or timed-out. 2048f173c2b7SSean Bruno */ 2049f173c2b7SSean Bruno lio_sleep_cond(oct, &ctx->cond); 2050f173c2b7SSean Bruno oct->props.rx_on = start_stop; 2051f173c2b7SSean Bruno } 2052f173c2b7SSean Bruno 2053f173c2b7SSean Bruno lio_free_soft_command(oct, sc); 2054f173c2b7SSean Bruno } 2055f173c2b7SSean Bruno 2056f173c2b7SSean Bruno static void 20572c50292dSJustin Hibbits lio_vlan_rx_add_vid(void *arg, if_t ifp, uint16_t vid) 2058f173c2b7SSean Bruno { 2059f173c2b7SSean Bruno struct lio_ctrl_pkt nctrl; 2060f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 2061f173c2b7SSean Bruno struct octeon_device *oct = lio->oct_dev; 2062f173c2b7SSean Bruno int ret = 0; 2063f173c2b7SSean Bruno 2064f173c2b7SSean Bruno if (if_getsoftc(ifp) != arg) /* Not our event */ 2065f173c2b7SSean Bruno return; 2066f173c2b7SSean Bruno 2067f173c2b7SSean Bruno if ((vid == 0) || (vid > 4095)) /* Invalid */ 2068f173c2b7SSean Bruno return; 2069f173c2b7SSean Bruno 2070f173c2b7SSean Bruno bzero(&nctrl, sizeof(struct lio_ctrl_pkt)); 2071f173c2b7SSean Bruno 2072f173c2b7SSean Bruno nctrl.ncmd.cmd64 = 0; 2073f173c2b7SSean Bruno nctrl.ncmd.s.cmd = LIO_CMD_ADD_VLAN_FILTER; 2074f173c2b7SSean Bruno nctrl.ncmd.s.param1 = vid; 2075f173c2b7SSean Bruno nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 2076f173c2b7SSean Bruno nctrl.wait_time = 100; 2077f173c2b7SSean Bruno nctrl.lio = lio; 2078f173c2b7SSean Bruno nctrl.cb_fn = lio_ctrl_cmd_completion; 2079f173c2b7SSean Bruno 2080f173c2b7SSean Bruno ret = lio_send_ctrl_pkt(lio->oct_dev, &nctrl); 2081f173c2b7SSean Bruno if (ret < 0) { 2082f173c2b7SSean Bruno lio_dev_err(oct, "Add VLAN filter failed in core (ret: 0x%x)\n", 2083f173c2b7SSean Bruno ret); 2084f173c2b7SSean Bruno } 2085f173c2b7SSean Bruno } 2086f173c2b7SSean Bruno 2087f173c2b7SSean Bruno static void 20882c50292dSJustin Hibbits lio_vlan_rx_kill_vid(void *arg, if_t ifp, uint16_t vid) 2089f173c2b7SSean Bruno { 2090f173c2b7SSean Bruno struct lio_ctrl_pkt nctrl; 2091f173c2b7SSean Bruno struct lio *lio = if_getsoftc(ifp); 2092f173c2b7SSean Bruno struct octeon_device *oct = lio->oct_dev; 2093f173c2b7SSean Bruno int ret = 0; 2094f173c2b7SSean Bruno 2095f173c2b7SSean Bruno if (if_getsoftc(ifp) != arg) /* Not our event */ 2096f173c2b7SSean Bruno return; 2097f173c2b7SSean Bruno 2098f173c2b7SSean Bruno if ((vid == 0) || (vid > 4095)) /* Invalid */ 2099f173c2b7SSean Bruno return; 2100f173c2b7SSean Bruno 2101f173c2b7SSean Bruno bzero(&nctrl, sizeof(struct lio_ctrl_pkt)); 2102f173c2b7SSean Bruno 2103f173c2b7SSean Bruno nctrl.ncmd.cmd64 = 0; 2104f173c2b7SSean Bruno nctrl.ncmd.s.cmd = LIO_CMD_DEL_VLAN_FILTER; 2105f173c2b7SSean Bruno nctrl.ncmd.s.param1 = vid; 2106f173c2b7SSean Bruno nctrl.iq_no = lio->linfo.txpciq[0].s.q_no; 2107f173c2b7SSean Bruno nctrl.wait_time = 100; 2108f173c2b7SSean Bruno nctrl.lio = lio; 2109f173c2b7SSean Bruno nctrl.cb_fn = lio_ctrl_cmd_completion; 2110f173c2b7SSean Bruno 2111f173c2b7SSean Bruno ret = lio_send_ctrl_pkt(lio->oct_dev, &nctrl); 2112f173c2b7SSean Bruno if (ret < 0) { 2113f173c2b7SSean Bruno lio_dev_err(oct, 2114f173c2b7SSean Bruno "Kill VLAN filter failed in core (ret: 0x%x)\n", 2115f173c2b7SSean Bruno ret); 2116f173c2b7SSean Bruno } 2117f173c2b7SSean Bruno } 2118f173c2b7SSean Bruno 2119f173c2b7SSean Bruno static int 2120f173c2b7SSean Bruno lio_wait_for_oq_pkts(struct octeon_device *oct) 2121f173c2b7SSean Bruno { 2122f173c2b7SSean Bruno int i, pending_pkts, pkt_cnt = 0, retry = 100; 2123f173c2b7SSean Bruno 2124f173c2b7SSean Bruno do { 2125f173c2b7SSean Bruno pending_pkts = 0; 2126f173c2b7SSean Bruno 2127f173c2b7SSean Bruno for (i = 0; i < LIO_MAX_OUTPUT_QUEUES(oct); i++) { 2128f173c2b7SSean Bruno if (!(oct->io_qmask.oq & BIT_ULL(i))) 2129f173c2b7SSean Bruno continue; 2130f173c2b7SSean Bruno 2131f173c2b7SSean Bruno pkt_cnt = lio_droq_check_hw_for_pkts(oct->droq[i]); 2132f173c2b7SSean Bruno if (pkt_cnt > 0) { 2133f173c2b7SSean Bruno pending_pkts += pkt_cnt; 2134f173c2b7SSean Bruno taskqueue_enqueue(oct->droq[i]->droq_taskqueue, 2135f173c2b7SSean Bruno &oct->droq[i]->droq_task); 2136f173c2b7SSean Bruno } 2137f173c2b7SSean Bruno } 2138f173c2b7SSean Bruno 2139f173c2b7SSean Bruno pkt_cnt = 0; 2140f173c2b7SSean Bruno lio_sleep_timeout(1); 2141f173c2b7SSean Bruno } while (retry-- && pending_pkts); 2142f173c2b7SSean Bruno 2143f173c2b7SSean Bruno return (pkt_cnt); 2144f173c2b7SSean Bruno } 2145f173c2b7SSean Bruno 2146f173c2b7SSean Bruno static void 2147f173c2b7SSean Bruno lio_destroy_resources(struct octeon_device *oct) 2148f173c2b7SSean Bruno { 2149f173c2b7SSean Bruno int i, refcount; 2150f173c2b7SSean Bruno 2151f173c2b7SSean Bruno switch (atomic_load_acq_int(&oct->status)) { 2152f173c2b7SSean Bruno case LIO_DEV_RUNNING: 2153f173c2b7SSean Bruno case LIO_DEV_CORE_OK: 2154f173c2b7SSean Bruno /* No more instructions will be forwarded. */ 2155f173c2b7SSean Bruno atomic_store_rel_int(&oct->status, LIO_DEV_IN_RESET); 2156f173c2b7SSean Bruno 2157f173c2b7SSean Bruno oct->app_mode = LIO_DRV_INVALID_APP; 2158f173c2b7SSean Bruno lio_dev_dbg(oct, "Device state is now %s\n", 2159f173c2b7SSean Bruno lio_get_state_string(&oct->status)); 2160f173c2b7SSean Bruno 2161f173c2b7SSean Bruno lio_sleep_timeout(100); 2162f173c2b7SSean Bruno 2163f173c2b7SSean Bruno /* fallthrough */ 2164f173c2b7SSean Bruno case LIO_DEV_HOST_OK: 2165f173c2b7SSean Bruno 2166f173c2b7SSean Bruno /* fallthrough */ 2167f173c2b7SSean Bruno case LIO_DEV_CONSOLE_INIT_DONE: 2168f173c2b7SSean Bruno /* Remove any consoles */ 2169f173c2b7SSean Bruno lio_remove_consoles(oct); 2170f173c2b7SSean Bruno 2171f173c2b7SSean Bruno /* fallthrough */ 2172f173c2b7SSean Bruno case LIO_DEV_IO_QUEUES_DONE: 2173f173c2b7SSean Bruno if (lio_wait_for_pending_requests(oct)) 2174f173c2b7SSean Bruno lio_dev_err(oct, "There were pending requests\n"); 2175f173c2b7SSean Bruno 2176f173c2b7SSean Bruno if (lio_wait_for_instr_fetch(oct)) 2177f173c2b7SSean Bruno lio_dev_err(oct, "IQ had pending instructions\n"); 2178f173c2b7SSean Bruno 2179f173c2b7SSean Bruno /* 2180f173c2b7SSean Bruno * Disable the input and output queues now. No more packets will 2181f173c2b7SSean Bruno * arrive from Octeon, but we should wait for all packet 2182f173c2b7SSean Bruno * processing to finish. 2183f173c2b7SSean Bruno */ 2184f173c2b7SSean Bruno oct->fn_list.disable_io_queues(oct); 2185f173c2b7SSean Bruno 2186f173c2b7SSean Bruno if (lio_wait_for_oq_pkts(oct)) 2187f173c2b7SSean Bruno lio_dev_err(oct, "OQ had pending packets\n"); 2188f173c2b7SSean Bruno 2189f173c2b7SSean Bruno /* fallthrough */ 2190f173c2b7SSean Bruno case LIO_DEV_INTR_SET_DONE: 2191f173c2b7SSean Bruno /* Disable interrupts */ 2192f173c2b7SSean Bruno oct->fn_list.disable_interrupt(oct, OCTEON_ALL_INTR); 2193f173c2b7SSean Bruno 2194f173c2b7SSean Bruno if (oct->msix_on) { 2195f173c2b7SSean Bruno for (i = 0; i < oct->num_msix_irqs - 1; i++) { 2196f173c2b7SSean Bruno if (oct->ioq_vector[i].tag != NULL) { 2197f173c2b7SSean Bruno bus_teardown_intr(oct->device, 2198f173c2b7SSean Bruno oct->ioq_vector[i].msix_res, 2199f173c2b7SSean Bruno oct->ioq_vector[i].tag); 2200f173c2b7SSean Bruno oct->ioq_vector[i].tag = NULL; 2201f173c2b7SSean Bruno } 2202f173c2b7SSean Bruno if (oct->ioq_vector[i].msix_res != NULL) { 2203f173c2b7SSean Bruno bus_release_resource(oct->device, 2204f173c2b7SSean Bruno SYS_RES_IRQ, 2205f173c2b7SSean Bruno oct->ioq_vector[i].vector, 2206f173c2b7SSean Bruno oct->ioq_vector[i].msix_res); 2207f173c2b7SSean Bruno oct->ioq_vector[i].msix_res = NULL; 2208f173c2b7SSean Bruno } 2209f173c2b7SSean Bruno } 2210f173c2b7SSean Bruno /* non-iov vector's argument is oct struct */ 2211f173c2b7SSean Bruno if (oct->tag != NULL) { 2212f173c2b7SSean Bruno bus_teardown_intr(oct->device, oct->msix_res, 2213f173c2b7SSean Bruno oct->tag); 2214f173c2b7SSean Bruno oct->tag = NULL; 2215f173c2b7SSean Bruno } 2216f173c2b7SSean Bruno 2217f173c2b7SSean Bruno if (oct->msix_res != NULL) { 2218f173c2b7SSean Bruno bus_release_resource(oct->device, SYS_RES_IRQ, 2219f173c2b7SSean Bruno oct->aux_vector, 2220f173c2b7SSean Bruno oct->msix_res); 2221f173c2b7SSean Bruno oct->msix_res = NULL; 2222f173c2b7SSean Bruno } 2223f173c2b7SSean Bruno 2224f173c2b7SSean Bruno pci_release_msi(oct->device); 2225f173c2b7SSean Bruno } 2226f173c2b7SSean Bruno /* fallthrough */ 2227f173c2b7SSean Bruno case LIO_DEV_IN_RESET: 2228f173c2b7SSean Bruno case LIO_DEV_DROQ_INIT_DONE: 2229f173c2b7SSean Bruno /* Wait for any pending operations */ 2230f173c2b7SSean Bruno lio_mdelay(100); 2231f173c2b7SSean Bruno for (i = 0; i < LIO_MAX_OUTPUT_QUEUES(oct); i++) { 2232f173c2b7SSean Bruno if (!(oct->io_qmask.oq & BIT_ULL(i))) 2233f173c2b7SSean Bruno continue; 2234f173c2b7SSean Bruno lio_delete_droq(oct, i); 2235f173c2b7SSean Bruno } 2236f173c2b7SSean Bruno 2237f173c2b7SSean Bruno /* fallthrough */ 2238f173c2b7SSean Bruno case LIO_DEV_RESP_LIST_INIT_DONE: 2239f173c2b7SSean Bruno for (i = 0; i < LIO_MAX_POSSIBLE_OUTPUT_QUEUES; i++) { 2240f173c2b7SSean Bruno if (oct->droq[i] != NULL) { 2241f173c2b7SSean Bruno free(oct->droq[i], M_DEVBUF); 2242f173c2b7SSean Bruno oct->droq[i] = NULL; 2243f173c2b7SSean Bruno } 2244f173c2b7SSean Bruno } 2245f173c2b7SSean Bruno lio_delete_response_list(oct); 2246f173c2b7SSean Bruno 2247f173c2b7SSean Bruno /* fallthrough */ 2248f173c2b7SSean Bruno case LIO_DEV_INSTR_QUEUE_INIT_DONE: 2249f173c2b7SSean Bruno for (i = 0; i < LIO_MAX_INSTR_QUEUES(oct); i++) { 2250f173c2b7SSean Bruno if (!(oct->io_qmask.iq & BIT_ULL(i))) 2251f173c2b7SSean Bruno continue; 2252f173c2b7SSean Bruno 2253f173c2b7SSean Bruno lio_delete_instr_queue(oct, i); 2254f173c2b7SSean Bruno } 2255f173c2b7SSean Bruno 2256f173c2b7SSean Bruno /* fallthrough */ 2257f173c2b7SSean Bruno case LIO_DEV_MSIX_ALLOC_VECTOR_DONE: 2258f173c2b7SSean Bruno for (i = 0; i < LIO_MAX_POSSIBLE_INSTR_QUEUES; i++) { 2259f173c2b7SSean Bruno if (oct->instr_queue[i] != NULL) { 2260f173c2b7SSean Bruno free(oct->instr_queue[i], M_DEVBUF); 2261f173c2b7SSean Bruno oct->instr_queue[i] = NULL; 2262f173c2b7SSean Bruno } 2263f173c2b7SSean Bruno } 2264f173c2b7SSean Bruno lio_free_ioq_vector(oct); 2265f173c2b7SSean Bruno 2266f173c2b7SSean Bruno /* fallthrough */ 2267f173c2b7SSean Bruno case LIO_DEV_SC_BUFF_POOL_INIT_DONE: 2268f173c2b7SSean Bruno lio_free_sc_buffer_pool(oct); 2269f173c2b7SSean Bruno 2270f173c2b7SSean Bruno /* fallthrough */ 2271f173c2b7SSean Bruno case LIO_DEV_DISPATCH_INIT_DONE: 2272f173c2b7SSean Bruno lio_delete_dispatch_list(oct); 2273f173c2b7SSean Bruno 2274f173c2b7SSean Bruno /* fallthrough */ 2275f173c2b7SSean Bruno case LIO_DEV_PCI_MAP_DONE: 2276f173c2b7SSean Bruno refcount = lio_deregister_device(oct); 2277f173c2b7SSean Bruno 2278f173c2b7SSean Bruno if (fw_type_is_none()) 2279f173c2b7SSean Bruno lio_pci_flr(oct); 2280f173c2b7SSean Bruno 2281f173c2b7SSean Bruno if (!refcount) 2282f173c2b7SSean Bruno oct->fn_list.soft_reset(oct); 2283f173c2b7SSean Bruno 2284f173c2b7SSean Bruno lio_unmap_pci_barx(oct, 0); 2285f173c2b7SSean Bruno lio_unmap_pci_barx(oct, 1); 2286f173c2b7SSean Bruno 2287f173c2b7SSean Bruno /* fallthrough */ 2288f173c2b7SSean Bruno case LIO_DEV_PCI_ENABLE_DONE: 2289f173c2b7SSean Bruno /* Disable the device, releasing the PCI INT */ 2290f173c2b7SSean Bruno pci_disable_busmaster(oct->device); 2291f173c2b7SSean Bruno 2292f173c2b7SSean Bruno /* fallthrough */ 2293f173c2b7SSean Bruno case LIO_DEV_BEGIN_STATE: 2294f173c2b7SSean Bruno break; 2295f173c2b7SSean Bruno } /* end switch (oct->status) */ 2296f173c2b7SSean Bruno } 2297