diff --git a/drivers/crypto/qat/rte_qat_cryptodev.c b/drivers/crypto/qat/rte_qat_cryptodev.c
index 6853aee..ded5d60 100644
--- a/drivers/crypto/qat/rte_qat_cryptodev.c
+++ b/drivers/crypto/qat/rte_qat_cryptodev.c
@@ -124,17 +124,10 @@ static struct rte_cryptodev_driver rte_qat_pmd = {
 	.dev_private_size = sizeof(struct qat_pmd_private),
 };
 
-static int
-rte_qat_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_qat_pmd_init(void)
 {
 	PMD_INIT_FUNC_TRACE();
 	rte_eal_pci_register(&rte_qat_pmd.pci_drv);
-	return 0;
 }
-
-static struct rte_driver pmd_qat_drv = {
-	.type = PMD_PDEV,
-	.init = rte_qat_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(pmd_qat_drv);
diff --git a/drivers/net/bnx2x/bnx2x_ethdev.c b/drivers/net/bnx2x/bnx2x_ethdev.c
index 916b9da..a4b1599 100644
--- a/drivers/net/bnx2x/bnx2x_ethdev.c
+++ b/drivers/net/bnx2x/bnx2x_ethdev.c
@@ -523,31 +523,11 @@ static struct eth_driver rte_bnx2xvf_pmd = {
 	.dev_private_size = sizeof(struct bnx2x_softc),
 };
 
-static int rte_bnx2x_pmd_init(const char *name __rte_unused,
-			      const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_bnx2x_pmd_init(void)
 {
 	PMD_INIT_FUNC_TRACE();
 	rte_eal_pci_register(&rte_bnx2x_pmd.pci_drv);
-	return 0;
-}
-
-static int rte_bnx2xvf_pmd_init(const char *name __rte_unused,
-				const char *params __rte_unused)
-{
-	PMD_INIT_FUNC_TRACE();
 	rte_eal_pci_register(&rte_bnx2xvf_pmd.pci_drv);
-	return 0;
 }
-
-static struct rte_driver rte_bnx2x_driver = {
-	.type = PMD_PDEV,
-	.init = rte_bnx2x_pmd_init,
-};
-
-static struct rte_driver rte_bnx2xvf_driver = {
-	.type = PMD_PDEV,
-	.init = rte_bnx2xvf_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_bnx2x_driver);
-PMD_REGISTER_DRIVER(rte_bnx2xvf_driver);
diff --git a/drivers/net/cxgbe/cxgbe_ethdev.c b/drivers/net/cxgbe/cxgbe_ethdev.c
index e425ef2..9654ced 100644
--- a/drivers/net/cxgbe/cxgbe_ethdev.c
+++ b/drivers/net/cxgbe/cxgbe_ethdev.c
@@ -858,23 +858,10 @@ static struct eth_driver rte_cxgbe_pmd = {
 	.dev_private_size = sizeof(struct port_info),
 };
 
-/*
- * Driver initialization routine.
- * Invoked once at EAL init time.
- * Register itself as the [Poll Mode] Driver of PCI CXGBE devices.
- */
-static int rte_cxgbe_pmd_init(const char *name __rte_unused,
-			      const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_cxgbe_pmd_init(void)
 {
 	CXGBE_FUNC_TRACE();
 	rte_eal_pci_register(&rte_cxgbe_pmd.pci_drv);
-	return 0;
 }
-
-static struct rte_driver rte_cxgbe_driver = {
-	.name = "cxgbe_driver",
-	.type = PMD_PDEV,
-	.init = rte_cxgbe_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_cxgbe_driver);
diff --git a/drivers/net/e1000/em_ethdev.c b/drivers/net/e1000/em_ethdev.c
index 973ec97..19b2645 100644
--- a/drivers/net/e1000/em_ethdev.c
+++ b/drivers/net/e1000/em_ethdev.c
@@ -348,11 +348,11 @@ static struct eth_driver rte_em_pmd = {
 	.dev_private_size = sizeof(struct e1000_adapter),
 };
 
-static int
-rte_em_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_em_pmd_init(void)
 {
 	rte_eal_pci_register(&rte_em_pmd.pci_drv);
-	return 0;
 }
 
 static int
@@ -1738,10 +1738,3 @@ eth_em_set_mc_addr_list(struct rte_eth_dev *dev,
 	e1000_update_mc_addr_list(hw, (u8 *)mc_addr_set, nb_mc_addr);
 	return 0;
 }
-
-struct rte_driver em_pmd_drv = {
-	.type = PMD_PDEV,
-	.init = rte_em_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(em_pmd_drv);
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index a8d94a4..da63365 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -985,11 +985,12 @@ static struct eth_driver rte_igbvf_pmd = {
 	.dev_private_size = sizeof(struct e1000_adapter),
 };
 
-static int
-rte_igb_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_igb_pmd_init(void)
 {
 	rte_eal_pci_register(&rte_igb_pmd.pci_drv);
-	return 0;
+	rte_eal_pci_register(&rte_igbvf_pmd.pci_drv);
 }
 
 static void
@@ -1003,20 +1004,6 @@ igb_vmdq_vlan_hw_filter_enable(struct rte_eth_dev *dev)
 	E1000_WRITE_REG(hw, E1000_RCTL, rctl);
 }
 
-/*
- * VF Driver initialization routine.
- * Invoked one at EAL init time.
- * Register itself as the [Virtual Poll Mode] Driver of PCI IGB devices.
- */
-static int
-rte_igbvf_pmd_init(const char *name __rte_unused,
-		   const char *params __rte_unused)
-{
-	PMD_INIT_FUNC_TRACE();
-	rte_eal_pci_register(&rte_igbvf_pmd.pci_drv);
-	return 0;
-}
-
 static int
 igb_check_mq_mode(struct rte_eth_dev *dev)
 {
@@ -4696,16 +4683,6 @@ eth_igb_set_eeprom(struct rte_eth_dev *dev,
 	return nvm->ops.write(hw,  first, length, data);
 }
 
-static struct rte_driver pmd_igb_drv = {
-	.type = PMD_PDEV,
-	.init = rte_igb_pmd_init,
-};
-
-static struct rte_driver pmd_igbvf_drv = {
-	.type = PMD_PDEV,
-	.init = rte_igbvf_pmd_init,
-};
-
 static int
 eth_igb_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id)
 {
@@ -4866,6 +4843,3 @@ eth_igb_configure_msix_intr(struct rte_eth_dev *dev)
 
 	E1000_WRITE_FLUSH(hw);
 }
-
-PMD_REGISTER_DRIVER(pmd_igb_drv);
-PMD_REGISTER_DRIVER(pmd_igbvf_drv);
diff --git a/drivers/net/enic/enic_ethdev.c b/drivers/net/enic/enic_ethdev.c
index 7678c0a..9f997b1 100644
--- a/drivers/net/enic/enic_ethdev.c
+++ b/drivers/net/enic/enic_ethdev.c
@@ -632,22 +632,10 @@ static struct eth_driver rte_enic_pmd = {
 	.dev_private_size = sizeof(struct enic),
 };
 
-/* Driver initialization routine.
- * Invoked once at EAL init time.
- * Register as the [Poll Mode] Driver of Cisco ENIC device.
- */
-static int
-rte_enic_pmd_init(const char *name __rte_unused,
-	const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_enic_pmd_init(void)
 {
 	ENICPMD_FUNC_TRACE();
 	rte_eal_pci_register(&rte_enic_pmd.pci_drv);
-	return 0;
 }
-
-static struct rte_driver rte_enic_driver = {
-	.type = PMD_PDEV,
-	.init = rte_enic_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_enic_driver);
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 75537e0..b69fc22 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -2760,23 +2760,10 @@ static struct eth_driver rte_pmd_fm10k = {
 	.dev_private_size = sizeof(struct fm10k_adapter),
 };
 
-/*
- * Driver initialization routine.
- * Invoked once at EAL init time.
- * Register itself as the [Poll Mode] Driver of PCI FM10K devices.
- */
-static int
-rte_pmd_fm10k_init(__rte_unused const char *name,
-	__rte_unused const char *params)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_pmd_fm10k_init(void)
 {
 	PMD_INIT_FUNC_TRACE();
 	rte_eal_pci_register(&rte_pmd_fm10k.pci_drv);
-	return 0;
 }
-
-static struct rte_driver rte_fm10k_driver = {
-	.type = PMD_PDEV,
-	.init = rte_pmd_fm10k_init,
-};
-
-PMD_REGISTER_DRIVER(rte_fm10k_driver);
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index ab24115..f47bb4b 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -639,27 +639,14 @@ rte_i40e_dev_atomic_write_link_status(struct rte_eth_dev *dev,
 	return 0;
 }
 
-/*
- * Driver initialization routine.
- * Invoked once at EAL init time.
- * Register itself as the [Poll Mode] Driver of PCI IXGBE devices.
- */
-static int
-rte_i40e_pmd_init(const char *name __rte_unused,
-		  const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_i40e_pmd_init(void)
 {
 	PMD_INIT_FUNC_TRACE();
 	rte_eal_pci_register(&rte_i40e_pmd.pci_drv);
-	return 0;
 }
 
-static struct rte_driver rte_i40e_driver = {
-	.type = PMD_PDEV,
-	.init = rte_i40e_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_i40e_driver);
-
 /*
  * Initialize registers for flexible payload, which should be set by NVM.
  * This should be removed from code once it is fixed in NVM.
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 050d7ea..2e11ff9 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1374,27 +1374,14 @@ static struct eth_driver rte_i40evf_pmd = {
 	.dev_private_size = sizeof(struct i40e_adapter),
 };
 
-/*
- * VF Driver initialization routine.
- * Invoked one at EAL init time.
- * Register itself as the [Virtual Poll Mode] Driver of PCI Fortville devices.
- */
-static int
-rte_i40evf_pmd_init(const char *name __rte_unused,
-		    const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_i40evf_pmd_init(void)
 {
 	PMD_INIT_FUNC_TRACE();
 	rte_eal_pci_register(&rte_i40evf_pmd.pci_drv);
-	return 0;
 }
 
-static struct rte_driver rte_i40evf_driver = {
-	.type = PMD_PDEV,
-	.init = rte_i40evf_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_i40evf_driver);
-
 static int
 i40evf_dev_configure(struct rte_eth_dev *dev)
 {
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 970528e..9f29525 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -1457,30 +1457,13 @@ static struct eth_driver rte_ixgbevf_pmd = {
 	.dev_private_size = sizeof(struct ixgbe_adapter),
 };
 
-/*
- * Driver initialization routine.
- * Invoked once at EAL init time.
- * Register itself as the [Poll Mode] Driver of PCI IXGBE devices.
- */
-static int
-rte_ixgbe_pmd_init(const char *name __rte_unused, const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_ixgbe_pmd_init(void)
 {
 	PMD_INIT_FUNC_TRACE();
 	rte_eal_pci_register(&rte_ixgbe_pmd.pci_drv);
-	return 0;
-}
-
-/*
- * VF Driver initialization routine.
- * Invoked one at EAL init time.
- * Register itself as the [Virtual Poll Mode] Driver of PCI niantic devices.
- */
-static int
-rte_ixgbevf_pmd_init(const char *name __rte_unused, const char *param __rte_unused)
-{
-	PMD_INIT_FUNC_TRACE();
 	rte_eal_pci_register(&rte_ixgbevf_pmd.pci_drv);
-	return (0);
 }
 
 static int
@@ -6192,16 +6175,3 @@ ixgbe_dev_get_dcb_info(struct rte_eth_dev *dev,
 	}
 	return 0;
 }
-
-static struct rte_driver rte_ixgbe_driver = {
-	.type = PMD_PDEV,
-	.init = rte_ixgbe_pmd_init,
-};
-
-static struct rte_driver rte_ixgbevf_driver = {
-	.type = PMD_PDEV,
-	.init = rte_ixgbevf_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_ixgbe_driver);
-PMD_REGISTER_DRIVER(rte_ixgbevf_driver);
diff --git a/drivers/net/mlx4/mlx4.c b/drivers/net/mlx4/mlx4.c
index 207bfe2..bd223c0 100644
--- a/drivers/net/mlx4/mlx4.c
+++ b/drivers/net/mlx4/mlx4.c
@@ -5677,14 +5677,10 @@ static struct eth_driver mlx4_driver = {
 	.dev_private_size = sizeof(struct priv)
 };
 
-/**
- * Driver initialization routine.
- */
-static int
-rte_mlx4_pmd_init(const char *name, const char *args)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_mlx4_pmd_init(void)
 {
-	(void)name;
-	(void)args;
 	/*
 	 * RDMAV_HUGEPAGES_SAFE tells ibv_fork_init() we intend to use
 	 * huge pages. Calling ibv_fork_init() during init allows
@@ -5694,13 +5690,4 @@ rte_mlx4_pmd_init(const char *name, const char *args)
 	setenv("RDMAV_HUGEPAGES_SAFE", "1", 1);
 	ibv_fork_init();
 	rte_eal_pci_register(&mlx4_driver.pci_drv);
-	return 0;
 }
-
-static struct rte_driver rte_mlx4_driver = {
-	.type = PMD_PDEV,
-	.name = MLX4_DRIVER_NAME,
-	.init = rte_mlx4_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_mlx4_driver)
diff --git a/drivers/net/mlx5/mlx5.c b/drivers/net/mlx5/mlx5.c
index 821ee0f..8d23068 100644
--- a/drivers/net/mlx5/mlx5.c
+++ b/drivers/net/mlx5/mlx5.c
@@ -542,14 +542,10 @@ static struct eth_driver mlx5_driver = {
 	.dev_private_size = sizeof(struct priv)
 };
 
-/**
- * Driver initialization routine.
- */
-static int
-rte_mlx5_pmd_init(const char *name, const char *args)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_mlx5_pmd_init(void)
 {
-	(void)name;
-	(void)args;
 	/*
 	 * RDMAV_HUGEPAGES_SAFE tells ibv_fork_init() we intend to use
 	 * huge pages. Calling ibv_fork_init() during init allows
@@ -559,13 +555,4 @@ rte_mlx5_pmd_init(const char *name, const char *args)
 	setenv("RDMAV_HUGEPAGES_SAFE", "1", 1);
 	ibv_fork_init();
 	rte_eal_pci_register(&mlx5_driver.pci_drv);
-	return 0;
 }
-
-static struct rte_driver rte_mlx5_driver = {
-	.type = PMD_PDEV,
-	.name = MLX5_DRIVER_NAME,
-	.init = rte_mlx5_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_mlx5_driver)
diff --git a/drivers/net/nfp/nfp_net.c b/drivers/net/nfp/nfp_net.c
index 89ba703..6e4bc16 100644
--- a/drivers/net/nfp/nfp_net.c
+++ b/drivers/net/nfp/nfp_net.c
@@ -2474,24 +2474,16 @@ static struct eth_driver rte_nfp_net_pmd = {
 	.dev_private_size = sizeof(struct nfp_net_adapter),
 };
 
-static int
-nfp_net_pmd_init(const char *name __rte_unused,
-		 const char *params __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+nfp_net_pmd_init(void)
 {
 	PMD_INIT_FUNC_TRACE();
 	PMD_INIT_LOG(INFO, "librte_pmd_nfp_net version %s\n",
 		     NFP_NET_PMD_VERSION);
 	rte_eal_pci_register(&rte_nfp_net_pmd.pci_drv);
-	return 0;
 }
 
-static struct rte_driver rte_nfp_net_driver = {
-	.type = PMD_PDEV,
-	.init = nfp_net_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_nfp_net_driver);
-
 /*
  * Local variables:
  * c-file-style: "Linux"
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 08f386a..e44411e 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1447,23 +1447,16 @@ static struct eth_driver rte_virtio_pmd = {
 	.dev_private_size = sizeof(struct virtio_hw),
 };
 
-/*
- * Driver initialization routine.
- * Invoked once at EAL init time.
- * Register itself as the [Poll Mode] Driver of PCI virtio devices.
- * Returns 0 on success.
- */
-static int
-rte_virtio_pmd_init(const char *name __rte_unused,
-		    const char *param __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_virtio_pmd_init(void)
 {
 	if (rte_eal_iopl_init() != 0) {
 		PMD_INIT_LOG(ERR, "IOPL call failed - cannot use virtio PMD");
-		return -1;
+		return;
 	}
 
 	rte_eal_pci_register(&rte_virtio_pmd.pci_drv);
-	return 0;
 }
 
 /*
@@ -1684,10 +1677,3 @@ __rte_unused uint8_t is_rx)
 {
 	return 0;
 }
-
-static struct rte_driver rte_virtio_driver = {
-	.type = PMD_PDEV,
-	.init = rte_virtio_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_virtio_driver);
diff --git a/drivers/net/vmxnet3/vmxnet3_ethdev.c b/drivers/net/vmxnet3/vmxnet3_ethdev.c
index 1a3bc66..a065610 100644
--- a/drivers/net/vmxnet3/vmxnet3_ethdev.c
+++ b/drivers/net/vmxnet3/vmxnet3_ethdev.c
@@ -333,17 +333,12 @@ static struct eth_driver rte_vmxnet3_pmd = {
 	.dev_private_size = sizeof(struct vmxnet3_hw),
 };
 
-/*
- * Driver initialization routine.
- * Invoked once at EAL init time.
- * Register itself as the [Poll Mode] Driver of Virtual PCI VMXNET3 devices.
- */
-static int
-rte_vmxnet3_pmd_init(const char *name __rte_unused, const char *param __rte_unused)
+/* Driver registration */
+static void __attribute__((constructor, used))
+rte_vmxnet3_pmd_init(void)
 {
 	PMD_INIT_FUNC_TRACE();
 	rte_eal_pci_register(&rte_vmxnet3_pmd.pci_drv);
-	return 0;
 }
 
 static int
@@ -922,10 +917,3 @@ vmxnet3_process_events(struct vmxnet3_hw *hw)
 
 }
 #endif
-
-static struct rte_driver rte_vmxnet3_driver = {
-	.type = PMD_PDEV,
-	.init = rte_vmxnet3_pmd_init,
-};
-
-PMD_REGISTER_DRIVER(rte_vmxnet3_driver);
