* DPDK callback to close the device. * * Destroy all queues and objects, free memory. * * @param dev * Pointer to Ethernet device structure. */
| 384 | * Pointer to Ethernet device structure. |
| 385 | */ |
| 386 | static int |
| 387 | mlx4_dev_close(struct rte_eth_dev *dev) |
| 388 | { |
| 389 | struct mlx4_priv *priv = dev->data->dev_private; |
| 390 | unsigned int i; |
| 391 | |
| 392 | if (rte_eal_process_type() == RTE_PROC_SECONDARY) { |
| 393 | rte_eth_dev_release_port(dev); |
| 394 | return 0; |
| 395 | } |
| 396 | DEBUG("%p: closing device \"%s\"", |
| 397 | (void *)dev, |
| 398 | ((priv->ctx != NULL) ? priv->ctx->device->name : "")); |
| 399 | dev->rx_pkt_burst = rte_eth_pkt_burst_dummy; |
| 400 | dev->tx_pkt_burst = rte_eth_pkt_burst_dummy; |
| 401 | rte_wmb(); |
| 402 | /* Disable datapath on secondary process. */ |
| 403 | mlx4_mp_req_stop_rxtx(dev); |
| 404 | mlx4_flow_clean(priv); |
| 405 | mlx4_rss_deinit(priv); |
| 406 | for (i = 0; i != dev->data->nb_rx_queues; ++i) |
| 407 | mlx4_rx_queue_release(dev, i); |
| 408 | for (i = 0; i != dev->data->nb_tx_queues; ++i) |
| 409 | mlx4_tx_queue_release(dev, i); |
| 410 | mlx4_proc_priv_uninit(dev); |
| 411 | mlx4_mr_release(dev); |
| 412 | if (priv->pd != NULL) { |
| 413 | MLX4_ASSERT(priv->ctx != NULL); |
| 414 | claim_zero(mlx4_glue->dealloc_pd(priv->pd)); |
| 415 | claim_zero(mlx4_glue->close_device(priv->ctx)); |
| 416 | } else |
| 417 | MLX4_ASSERT(priv->ctx == NULL); |
| 418 | mlx4_intr_uninstall(priv); |
| 419 | memset(priv, 0, sizeof(*priv)); |
| 420 | /* mac_addrs must not be freed because part of dev_private */ |
| 421 | dev->data->mac_addrs = NULL; |
| 422 | return 0; |
| 423 | } |
| 424 | |
| 425 | static const struct eth_dev_ops mlx4_dev_ops = { |
| 426 | .dev_configure = mlx4_dev_configure, |
no test coverage detected