static int cvm_oct_remove(struct platform_device *pdev) { int port; /* Disable POW interrupt */ if (OCTEON_IS_MODEL(OCTEON_CN68XX)) cvmx_write_csr(CVMX_SSO_WQ_INT_THRX(pow_receive_group), 0); else cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0); cvmx_ipd_disable(); /* Free the interrupt handler */ free_irq(OCTEON_IRQ_WORKQ0 + pow_receive_group, cvm_oct_device); atomic_inc_return(&cvm_oct_poll_queue_stopping); cancel_delayed_work_sync(&cvm_oct_rx_refill_work); cvm_oct_rx_shutdown(); cvm_oct_tx_shutdown(); cvmx_pko_disable(); /* Free the ethernet devices */ for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { if (cvm_oct_device[port]) { struct net_device *dev = cvm_oct_device[port]; struct octeon_ethernet *priv = netdev_priv(dev); cancel_delayed_work_sync(&priv->port_periodic_work); cvm_oct_tx_shutdown_dev(dev); unregister_netdev(dev); free_netdev(dev); cvm_oct_device[port] = NULL; } } cvmx_pko_shutdown(); cvmx_ipd_free_ptr(); /* Free the HW pools */ cvm_oct_mem_empty_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, num_packet_buffers); cvm_oct_mem_empty_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, num_packet_buffers); if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); return 0; }
static int cvm_oct_remove(struct platform_device *pdev) { int port; cvmx_ipd_disable(); atomic_inc_return(&cvm_oct_poll_queue_stopping); cancel_delayed_work_sync(&cvm_oct_rx_refill_work); cvm_oct_rx_shutdown(); cvm_oct_tx_shutdown(); cvmx_pko_disable(); /* Free the ethernet devices */ for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { if (cvm_oct_device[port]) { struct net_device *dev = cvm_oct_device[port]; struct octeon_ethernet *priv = netdev_priv(dev); cancel_delayed_work_sync(&priv->port_periodic_work); cvm_oct_tx_shutdown_dev(dev); unregister_netdev(dev); free_netdev(dev); cvm_oct_device[port] = NULL; } } cvmx_pko_shutdown(); cvmx_ipd_free_ptr(); /* Free the HW pools */ cvm_oct_mem_empty_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, num_packet_buffers); cvm_oct_mem_empty_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, num_packet_buffers); if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, 128); return 0; }
/** * Module / driver shutdown * * @return Zero on success */ void cvm_oct_cleanup_module(device_t bus) { int port; struct octebus_softc *sc = device_get_softc(bus); /* Disable POW interrupt */ cvmx_write_csr(CVMX_POW_WQ_INT_THRX(pow_receive_group), 0); /* Free the interrupt handler */ bus_teardown_intr(bus, sc->sc_rx_irq, sc->sc_rx_intr_cookie); callout_stop(&cvm_oct_poll_timer); cvm_oct_rx_shutdown(); cvmx_helper_shutdown_packet_io_global(); /* Free the ethernet devices */ for (port = 0; port < TOTAL_NUMBER_OF_PORTS; port++) { if (cvm_oct_device[port]) { cvm_oct_tx_shutdown(cvm_oct_device[port]); #if 0 unregister_netdev(cvm_oct_device[port]); kfree(cvm_oct_device[port]); #else panic("%s: need to detach and free interface.", __func__); #endif cvm_oct_device[port] = NULL; } } /* Free the HW pools */ cvm_oct_mem_empty_fpa(CVMX_FPA_PACKET_POOL, CVMX_FPA_PACKET_POOL_SIZE, num_packet_buffers); cvm_oct_mem_empty_fpa(CVMX_FPA_WQE_POOL, CVMX_FPA_WQE_POOL_SIZE, num_packet_buffers); if (CVMX_FPA_OUTPUT_BUFFER_POOL != CVMX_FPA_PACKET_POOL) cvm_oct_mem_empty_fpa(CVMX_FPA_OUTPUT_BUFFER_POOL, CVMX_FPA_OUTPUT_BUFFER_POOL_SIZE, cvm_oct_num_output_buffers); /* Disable FPA, all buffers are free, not done by helper shutdown. */ cvmx_fpa_disable(); }