[dpdk-dev] [PATCH v4 1/2] ethdev: remove get_reg_length callback
From: Zyta Szpak Version 4 of fixing the assumption of that device registers are always 32 bits long. rte_eth_dev_get_reg_length and rte_eth_dev_get_reg_info callbacks did not provide register size to the app in any way. It is needed to allocate proper number of bytes before retrieving registers content with rte_eth_dev_get_reg. This commit remove rte_eth_dev_get_reg_length callback and adds width parameter to reg_info struct which makes it possible to call rte_eth_dev_get_reg_info to get attributes first. The drivers using this callback fill width and length when call to function made with data=NULL. Signed-off-by: Zyta Szpak --- drivers/net/e1000/igb_ethdev.c | 14 -- drivers/net/i40e/i40e_ethdev.c | 15 ++- drivers/net/ixgbe/ixgbe_ethdev.c | 14 -- lib/librte_ether/rte_dev_info.h| 1 + lib/librte_ether/rte_ethdev.c | 12 lib/librte_ether/rte_ethdev.h | 20 +--- lib/librte_ether/rte_ether_version.map | 1 - 7 files changed, 32 insertions(+), 45 deletions(-) diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c index b822992..312a2f4 100644 --- a/drivers/net/e1000/igb_ethdev.c +++ b/drivers/net/e1000/igb_ethdev.c @@ -366,7 +366,6 @@ static const struct eth_dev_ops eth_igb_ops = { .timesync_disable = igb_timesync_disable, .timesync_read_rx_timestamp = igb_timesync_read_rx_timestamp, .timesync_read_tx_timestamp = igb_timesync_read_tx_timestamp, - .get_reg_length = eth_igb_get_reg_length, .get_reg = eth_igb_get_regs, .get_eeprom_length= eth_igb_get_eeprom_length, .get_eeprom = eth_igb_get_eeprom, @@ -406,7 +405,6 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = { .rxq_info_get = igb_rxq_info_get, .txq_info_get = igb_txq_info_get, .mac_addr_set = igbvf_default_mac_addr_set, - .get_reg_length = igbvf_get_reg_length, .get_reg = igbvf_get_regs, }; @@ -4750,6 +4748,12 @@ eth_igb_get_regs(struct rte_eth_dev *dev, int count = 0; const struct reg_info *reg_group; + if (data == NULL) { + regs->length = eth_igb_get_reg_length(dev); + regs->width = sizeof(uint32_t); + return 0; + } + /* Support only full register dump */ if ((regs->length == 0) || (regs->length == (uint32_t)eth_igb_get_reg_length(dev))) { @@ -4774,6 +4778,12 @@ igbvf_get_regs(struct rte_eth_dev *dev, int count = 0; const struct reg_info *reg_group; + if (data == NULL) { + regs->length = igbvf_get_reg_length(dev); + regs->width = sizeof(uint32_t); + return 0; + } + /* Support only full register dump */ if ((regs->length == 0) || (regs->length == (uint32_t)igbvf_get_reg_length(dev))) { diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index f94ad87..9173e24 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -437,8 +437,6 @@ static int i40e_dev_rx_queue_intr_enable(struct rte_eth_dev *dev, static int i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id); -static int i40e_get_reg_length(struct rte_eth_dev *dev); - static int i40e_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs); @@ -519,7 +517,6 @@ static const struct eth_dev_ops i40e_eth_dev_ops = { .timesync_adjust_time = i40e_timesync_adjust_time, .timesync_read_time = i40e_timesync_read_time, .timesync_write_time = i40e_timesync_write_time, - .get_reg_length = i40e_get_reg_length, .get_reg = i40e_get_regs, .get_eeprom_length= i40e_get_eeprom_length, .get_eeprom = i40e_get_eeprom, @@ -9059,12 +9056,6 @@ i40e_dev_rx_queue_intr_disable(struct rte_eth_dev *dev, uint16_t queue_id) return 0; } -static int i40e_get_reg_length(__rte_unused struct rte_eth_dev *dev) -{ - /* Highest base addr + 32-bit word */ - return I40E_GLGEN_STAT_CLEAR + 4; -} - static int i40e_get_regs(struct rte_eth_dev *dev, struct rte_dev_reg_info *regs) { @@ -9073,6 +9064,12 @@ static int i40e_get_regs(struct rte_eth_dev *dev, uint32_t reg_idx, arr_idx, arr_idx2, reg_offset; const struct i40e_reg_info *reg_info; + if (ptr_data == NULL) { + regs->length = I40E_GLGEN_STAT_CLEAR + 4; + regs->width = sizeof(uint32_t); + return 0; + } + /* The first few registers have to be read using AQ operations */ reg_idx = 0; while (i40e_regs_adminq[reg_idx].name) { diff --git a/drivers/net/
[dpdk-dev] [PATCH v4 2/2] examples/ethtool: use rte_eth_dev_get_reg_info for reg params
From: Zyta Szpak Version 4 of fixing the fixed register width assumption. The app was allocating too little space for 64-bit registers which resulted in memory corruption. This commit resolves this by getting the number of registers and size of register by rte_eth_dev_get_reg_info function called first time with data=NULL. Signed-off-by: Zyta Szpak --- examples/ethtool/lib/rte_ethtool.c | 19 +-- 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c index 54391f2..a1f91d4 100644 --- a/examples/ethtool/lib/rte_ethtool.c +++ b/examples/ethtool/lib/rte_ethtool.c @@ -46,6 +46,7 @@ int rte_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo) { struct rte_eth_dev_info dev_info; + struct rte_dev_reg_info reg_info; int n; if (drvinfo == NULL) @@ -65,7 +66,9 @@ rte_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo) dev_info.pci_dev->addr.domain, dev_info.pci_dev->addr.bus, dev_info.pci_dev->addr.devid, dev_info.pci_dev->addr.function); - n = rte_eth_dev_get_reg_length(port_id); + memset(®_info, 0, sizeof(reg_info)); + rte_eth_dev_get_reg_info(port_id, ®_info); + n = reg_info.length; if (n > 0) drvinfo->regdump_len = n; else @@ -86,12 +89,16 @@ rte_ethtool_get_drvinfo(uint8_t port_id, struct ethtool_drvinfo *drvinfo) int rte_ethtool_get_regs_len(uint8_t port_id) { - int count_regs; + struct rte_dev_reg_info reg_info; + int ret; + + memset(®_info, 0, sizeof(reg_info)); + + ret = rte_eth_dev_get_reg_info(port_id, ®_info); + if (ret) + return ret; - count_regs = rte_eth_dev_get_reg_length(port_id); - if (count_regs > 0) - return count_regs * sizeof(uint32_t); - return count_regs; + return reg_info.length * reg_info.width; } int -- 1.9.1
[dpdk-dev] [PATCH v3 1/2] ethdev: add callback to get register size in bytes
From: Zyta Szpak Version 2 of fixing the fixed register width assumption. rte_eth_dev_get_reg_length and rte_eth_dev_get_reg callbacks do not provide register size to the app in any way. It is needed to allocate proper number of bytes before retrieving registers content with rte_eth_dev_get_reg. Signed-off-by: Zyta Szpak --- lib/librte_ether/rte_ethdev.c | 12 lib/librte_ether/rte_ethdev.h | 18 ++ lib/librte_ether/rte_ether_version.map | 7 +++ 3 files changed, 37 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index a31018e..e0765f8 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -3231,6 +3231,18 @@ rte_eth_dev_get_reg_length(uint8_t port_id) } int +rte_eth_dev_get_reg_width(uint8_t port_id) +{ + struct rte_eth_dev *dev; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + + dev = &rte_eth_devices[port_id]; + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_reg_width, -ENOTSUP); + return (*dev->dev_ops->get_reg_width)(dev); +} + +int rte_eth_dev_get_reg_info(uint8_t port_id, struct rte_dev_reg_info *info) { struct rte_eth_dev *dev; diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 2757510..552eaed 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1292,6 +1292,9 @@ typedef int (*eth_timesync_write_time)(struct rte_eth_dev *dev, typedef int (*eth_get_reg_length_t)(struct rte_eth_dev *dev); /**< @internal Retrieve device register count */ +typedef int (*eth_get_reg_width_t)(struct rte_eth_dev *dev); +/**< @internal Retrieve device register byte number */ + typedef int (*eth_get_reg_t)(struct rte_eth_dev *dev, struct rte_dev_reg_info *info); /**< @internal Retrieve registers */ @@ -1455,6 +1458,8 @@ struct eth_dev_ops { eth_get_reg_length_t get_reg_length; /**< Get # of registers */ + eth_get_reg_width_t get_reg_width; + /**< Get # of bytes in register */ eth_get_reg_t get_reg; /**< Get registers */ eth_get_eeprom_length_t get_eeprom_length; @@ -3971,6 +3976,19 @@ int rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id, */ int rte_eth_dev_get_reg_length(uint8_t port_id); +/* + * Retrieve the number of bytes in register for a specific device + * + * @param port_id + * The port identifier of the Ethernet device. + * @return + * - (>=0) number of registers if successful. + * - (-ENOTSUP) if hardware doesn't support. + * - (-ENODEV) if *port_id* invalid. + * - others depends on the specific operations implementation. + */ +int rte_eth_dev_get_reg_width(uint8_t port_id); + /** * Retrieve device registers and register attributes * diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map index 214ecc7..568509c 100644 --- a/lib/librte_ether/rte_ether_version.map +++ b/lib/librte_ether/rte_ether_version.map @@ -132,3 +132,10 @@ DPDK_16.04 { rte_eth_tx_buffer_set_err_callback; } DPDK_2.2; + +DPDK_16.07 { + global: + + rte_eth_dev_get_reg_width; + +} DPDK_16.04; \ No newline at end of file -- 1.9.1
[dpdk-dev] [PATCH v3 2/2] examples/ethtool: get reg width to allocate memory
From: Zyta Szpak Version 2 of fixing the fixed register width assumption. Not every device uses 32-bit wide register. The app was allocating too little space for 64-bit registers which resulted in memory corruption. This commit resolves this by getting the size of register in bytes for a specific device. If the device does not implement this function, it fallsback to sizeof(uint32_t) Signed-off-by: Zyta Szpak --- examples/ethtool/lib/rte_ethtool.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c index 42e05f1..59191ca 100644 --- a/examples/ethtool/lib/rte_ethtool.c +++ b/examples/ethtool/lib/rte_ethtool.c @@ -88,10 +88,14 @@ int rte_ethtool_get_regs_len(uint8_t port_id) { int count_regs; + int reg_width; count_regs = rte_eth_dev_get_reg_length(port_id); + reg_width = rte_eth_dev_get_reg_width(port_id); + if (reg_width < 0) + reg_width = sizeof(uint32_t); if (count_regs > 0) - return count_regs * sizeof(uint32_t); + return count_regs * reg_width; return count_regs; } -- 1.9.1
[dpdk-dev] [PATCH] examples/ethtool: include case for 64-bit registers
From: Zyta Szpak rte_eth_dev_get_reg_length and rte_eth_dev_get_reg callbacks do not provide register size to the app in any way. Example assuming they are 32-bit wide always allocates not enough memory if the registers are 64-bit wide. It results in memory corruption. This commit is a quick fix to make enough room for 64-bit register values when this returned value is given to malloc. Signed-off-by: Zyta Szpak --- examples/ethtool/lib/rte_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c index 42e05f1..bf0a6ac 100644 --- a/examples/ethtool/lib/rte_ethtool.c +++ b/examples/ethtool/lib/rte_ethtool.c @@ -91,7 +91,7 @@ rte_ethtool_get_regs_len(uint8_t port_id) count_regs = rte_eth_dev_get_reg_length(port_id); if (count_regs > 0) - return count_regs * sizeof(uint32_t); + return count_regs * sizeof(uint64_t); return count_regs; } -- 1.9.1
[dpdk-dev] [PATCH 1/2] ethdev: add callback to get register size in bytes
From: Zyta Szpak Version 2 of fixing the fixed register width assumption. rte_eth_dev_get_reg_length and rte_eth_dev_get_reg callbacks do not provide register size to the app in any way. It is needed to allocate proper number of bytes before retrieving registers content with rte_eth_dev_get_reg. Signed-off-by: Zyta Szpak --- lib/librte_ether/rte_ethdev.c | 12 lib/librte_ether/rte_ethdev.h | 18 ++ 2 files changed, 30 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index a31018e..e0765f8 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -3231,6 +3231,18 @@ rte_eth_dev_get_reg_length(uint8_t port_id) } int +rte_eth_dev_get_reg_width(uint8_t port_id) +{ + struct rte_eth_dev *dev; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + + dev = &rte_eth_devices[port_id]; + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_reg_width, -ENOTSUP); + return (*dev->dev_ops->get_reg_width)(dev); +} + +int rte_eth_dev_get_reg_info(uint8_t port_id, struct rte_dev_reg_info *info) { struct rte_eth_dev *dev; diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 2757510..552eaed 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1292,6 +1292,9 @@ typedef int (*eth_timesync_write_time)(struct rte_eth_dev *dev, typedef int (*eth_get_reg_length_t)(struct rte_eth_dev *dev); /**< @internal Retrieve device register count */ +typedef int (*eth_get_reg_width_t)(struct rte_eth_dev *dev); +/**< @internal Retrieve device register byte number */ + typedef int (*eth_get_reg_t)(struct rte_eth_dev *dev, struct rte_dev_reg_info *info); /**< @internal Retrieve registers */ @@ -1455,6 +1458,8 @@ struct eth_dev_ops { eth_get_reg_length_t get_reg_length; /**< Get # of registers */ + eth_get_reg_width_t get_reg_width; + /**< Get # of bytes in register */ eth_get_reg_t get_reg; /**< Get registers */ eth_get_eeprom_length_t get_eeprom_length; @@ -3971,6 +3976,19 @@ int rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id, */ int rte_eth_dev_get_reg_length(uint8_t port_id); +/* + * Retrieve the number of bytes in register for a specific device + * + * @param port_id + * The port identifier of the Ethernet device. + * @return + * - (>=0) number of registers if successful. + * - (-ENOTSUP) if hardware doesn't support. + * - (-ENODEV) if *port_id* invalid. + * - others depends on the specific operations implementation. + */ +int rte_eth_dev_get_reg_width(uint8_t port_id); + /** * Retrieve device registers and register attributes * -- 1.9.1
[dpdk-dev] [PATCH 2/2] examples/ethtool: get reg width to allocate memory
From: Zyta Szpak Version 2 of fixing the fixed register width assumption. Not every device uses 32-bit wide register. The app was allocating too little space for 64-bit registers which resulted in memory corruption. This commit resolves this by getting the size of register in bytes for a specific device. If the device does not implement this function, it fallsback to sizeof(uint32_t) Signed-off-by: Zyta Szpak --- examples/ethtool/lib/rte_ethtool.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c index 42e05f1..59191ca 100644 --- a/examples/ethtool/lib/rte_ethtool.c +++ b/examples/ethtool/lib/rte_ethtool.c @@ -88,10 +88,14 @@ int rte_ethtool_get_regs_len(uint8_t port_id) { int count_regs; + int reg_width; count_regs = rte_eth_dev_get_reg_length(port_id); + reg_width = rte_eth_dev_get_reg_width(port_id); + if (reg_width < 0) + reg_width = sizeof(uint32_t); if (count_regs > 0) - return count_regs * sizeof(uint32_t); + return count_regs * reg_width; return count_regs; } -- 1.9.1
[dpdk-dev] [PATCH v2 1/2] ethdev: add callback to get register size in bytes
From: Zyta Szpak Version 2 of fixing the fixed register width assumption. rte_eth_dev_get_reg_length and rte_eth_dev_get_reg callbacks do not provide register size to the app in any way. It is needed to allocate proper number of bytes before retrieving registers content with rte_eth_dev_get_reg. Signed-off-by: Zyta Szpak --- lib/librte_ether/rte_ethdev.c | 12 lib/librte_ether/rte_ethdev.h | 18 ++ lib/librte_ether/rte_ether_version.map | 1 + 3 files changed, 31 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index a31018e..e0765f8 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -3231,6 +3231,18 @@ rte_eth_dev_get_reg_length(uint8_t port_id) } int +rte_eth_dev_get_reg_width(uint8_t port_id) +{ + struct rte_eth_dev *dev; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + + dev = &rte_eth_devices[port_id]; + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_reg_width, -ENOTSUP); + return (*dev->dev_ops->get_reg_width)(dev); +} + +int rte_eth_dev_get_reg_info(uint8_t port_id, struct rte_dev_reg_info *info) { struct rte_eth_dev *dev; diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 2757510..552eaed 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1292,6 +1292,9 @@ typedef int (*eth_timesync_write_time)(struct rte_eth_dev *dev, typedef int (*eth_get_reg_length_t)(struct rte_eth_dev *dev); /**< @internal Retrieve device register count */ +typedef int (*eth_get_reg_width_t)(struct rte_eth_dev *dev); +/**< @internal Retrieve device register byte number */ + typedef int (*eth_get_reg_t)(struct rte_eth_dev *dev, struct rte_dev_reg_info *info); /**< @internal Retrieve registers */ @@ -1455,6 +1458,8 @@ struct eth_dev_ops { eth_get_reg_length_t get_reg_length; /**< Get # of registers */ + eth_get_reg_width_t get_reg_width; + /**< Get # of bytes in register */ eth_get_reg_t get_reg; /**< Get registers */ eth_get_eeprom_length_t get_eeprom_length; @@ -3971,6 +3976,19 @@ int rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id, */ int rte_eth_dev_get_reg_length(uint8_t port_id); +/* + * Retrieve the number of bytes in register for a specific device + * + * @param port_id + * The port identifier of the Ethernet device. + * @return + * - (>=0) number of registers if successful. + * - (-ENOTSUP) if hardware doesn't support. + * - (-ENODEV) if *port_id* invalid. + * - others depends on the specific operations implementation. + */ +int rte_eth_dev_get_reg_width(uint8_t port_id); + /** * Retrieve device registers and register attributes * diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map index 214ecc7..288bc63 100644 --- a/lib/librte_ether/rte_ether_version.map +++ b/lib/librte_ether/rte_ether_version.map @@ -130,5 +130,6 @@ DPDK_16.04 { rte_eth_tx_buffer_drop_callback; rte_eth_tx_buffer_init; rte_eth_tx_buffer_set_err_callback; + rte_eth_dev_get_reg_width; } DPDK_2.2; -- 1.9.1
[dpdk-dev] [PATCH v2 1/2] ethdev: add callback to get register size in bytes
From: Zyta Szpak Version 2 of fixing the fixed register width assumption. rte_eth_dev_get_reg_length and rte_eth_dev_get_reg callbacks do not provide register size to the app in any way. It is needed to allocate proper number of bytes before retrieving registers content with rte_eth_dev_get_reg. Signed-off-by: Zyta Szpak --- lib/librte_ether/rte_ethdev.c | 12 lib/librte_ether/rte_ethdev.h | 18 ++ lib/librte_ether/rte_ether_version.map | 1 + 3 files changed, 31 insertions(+) diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index a31018e..e0765f8 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -3231,6 +3231,18 @@ rte_eth_dev_get_reg_length(uint8_t port_id) } int +rte_eth_dev_get_reg_width(uint8_t port_id) +{ + struct rte_eth_dev *dev; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -ENODEV); + + dev = &rte_eth_devices[port_id]; + RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->get_reg_width, -ENOTSUP); + return (*dev->dev_ops->get_reg_width)(dev); +} + +int rte_eth_dev_get_reg_info(uint8_t port_id, struct rte_dev_reg_info *info) { struct rte_eth_dev *dev; diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index 2757510..552eaed 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1292,6 +1292,9 @@ typedef int (*eth_timesync_write_time)(struct rte_eth_dev *dev, typedef int (*eth_get_reg_length_t)(struct rte_eth_dev *dev); /**< @internal Retrieve device register count */ +typedef int (*eth_get_reg_width_t)(struct rte_eth_dev *dev); +/**< @internal Retrieve device register byte number */ + typedef int (*eth_get_reg_t)(struct rte_eth_dev *dev, struct rte_dev_reg_info *info); /**< @internal Retrieve registers */ @@ -1455,6 +1458,8 @@ struct eth_dev_ops { eth_get_reg_length_t get_reg_length; /**< Get # of registers */ + eth_get_reg_width_t get_reg_width; + /**< Get # of bytes in register */ eth_get_reg_t get_reg; /**< Get registers */ eth_get_eeprom_length_t get_eeprom_length; @@ -3971,6 +3976,19 @@ int rte_eth_tx_queue_info_get(uint8_t port_id, uint16_t queue_id, */ int rte_eth_dev_get_reg_length(uint8_t port_id); +/* + * Retrieve the number of bytes in register for a specific device + * + * @param port_id + * The port identifier of the Ethernet device. + * @return + * - (>=0) number of registers if successful. + * - (-ENOTSUP) if hardware doesn't support. + * - (-ENODEV) if *port_id* invalid. + * - others depends on the specific operations implementation. + */ +int rte_eth_dev_get_reg_width(uint8_t port_id); + /** * Retrieve device registers and register attributes * diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map index 214ecc7..288bc63 100644 --- a/lib/librte_ether/rte_ether_version.map +++ b/lib/librte_ether/rte_ether_version.map @@ -130,5 +130,6 @@ DPDK_16.04 { rte_eth_tx_buffer_drop_callback; rte_eth_tx_buffer_init; rte_eth_tx_buffer_set_err_callback; + rte_eth_dev_get_reg_width; } DPDK_2.2; -- 1.9.1
[dpdk-dev] [PATCH v2 2/2] examples/ethtool: get reg width to allocate memory
From: Zyta Szpak Version 2 of fixing the fixed register width assumption. Not every device uses 32-bit wide register. The app was allocating too little space for 64-bit registers which resulted in memory corruption. This commit resolves this by getting the size of register in bytes for a specific device. If the device does not implement this function, it fallsback to sizeof(uint32_t) Signed-off-by: Zyta Szpak --- examples/ethtool/lib/rte_ethtool.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/ethtool/lib/rte_ethtool.c b/examples/ethtool/lib/rte_ethtool.c index 42e05f1..59191ca 100644 --- a/examples/ethtool/lib/rte_ethtool.c +++ b/examples/ethtool/lib/rte_ethtool.c @@ -88,10 +88,14 @@ int rte_ethtool_get_regs_len(uint8_t port_id) { int count_regs; + int reg_width; count_regs = rte_eth_dev_get_reg_length(port_id); + reg_width = rte_eth_dev_get_reg_width(port_id); + if (reg_width < 0) + reg_width = sizeof(uint32_t); if (count_regs > 0) - return count_regs * sizeof(uint32_t); + return count_regs * reg_width; return count_regs; } -- 1.9.1