[PATCH 07/15] habanalabs/gaudi: allow user to get MAC addresses in INFO IOCTL

Oded Gabbay
2020-09-10T16:21:20Z

From: Omer Shpigelman <oshpigelman@habana.ai>

The user needs this information when working in a distributed environment
with master/slave configuration. All the slaves get their MAC addresses
from the driver and send them to the master.

Signed-off-by: Omer Shpigelman <oshpigelman@habana.ai>
Reviewed-by: Oded Gabbay <oded.gabbay@gmail.com>
Signed-off-by: Oded Gabbay <oded.gabbay@gmail.com>
---
drivers/misc/habanalabs/common/habanalabs.h | 5 +++
.../misc/habanalabs/common/habanalabs_ioctl.c | 31 +++++++++++++++++++
drivers/misc/habanalabs/gaudi/gaudi.c | 1 +
drivers/misc/habanalabs/gaudi/gaudiP.h | 2 ++
drivers/misc/habanalabs/gaudi/gaudi_nic.c | 27 ++++++++++++++++
drivers/misc/habanalabs/goya/goya.c | 9 ++++++
include/uapi/misc/habanalabs.h | 20 +++++++++++-
7 files changed, 94 insertions(+), 1 deletion(-)

diff --git a/drivers/misc/habanalabs/common/habanalabs.h b/drivers/misc/habanalabs/common/habanalabs.h
index f99db3483ba4..6bfef3da6e61 100644
--- a/drivers/misc/habanalabs/common/habanalabs.h
+++ b/drivers/misc/habanalabs/common/habanalabs.h
@@ -602,6 +602,8 @@ enum div_select_defs {
DIV_SEL_DIVIDED_PLL = 3,
};

+struct hl_info_mac_addr;
+
/**
* struct hl_asic_funcs - ASIC specific functions that are can be called from
* common code.
@@ -679,6 +681,7 @@ enum div_select_defs {
* @get_hw_state: retrieve the H/W state
* @pci_bars_map: Map PCI BARs.
* @init_iatu: Initialize the iATU unit inside the PCI controller.
+ * @get_mac_addr: Get list of MAC addresses.
* @rreg: Read a register. Needed for simulator support.
* @wreg: Write a register. Needed for simulator support.
* @halt_coresight: stop the ETF and ETR traces.
@@ -782,6 +785,8 @@ struct hl_asic_funcs {
enum hl_device_hw_state (*get_hw_state)(struct hl_device *hdev);
int (*pci_bars_map)(struct hl_device *hdev);
int (*init_iatu)(struct hl_device *hdev);
+ int (*get_mac_addr)(struct hl_device *hdev,
+ struct hl_info_mac_addr *mac_addr);
u32 (*rreg)(struct hl_device *hdev, u32 reg);
void (*wreg)(struct hl_device *hdev, u32 reg, u32 val);
void (*halt_coresight)(struct hl_device *hdev);
diff --git a/drivers/misc/habanalabs/common/habanalabs_ioctl.c b/drivers/misc/habanalabs/common/habanalabs_ioctl.c
index 07317ea49129..01425b821828 100644
--- a/drivers/misc/habanalabs/common/habanalabs_ioctl.c
+++ b/drivers/misc/habanalabs/common/habanalabs_ioctl.c
@@ -203,6 +203,33 @@ static int debug_coresight(struct hl_device *hdev, struct hl_debug_args *args)
return rc;
}

+static int mac_addr_info(struct hl_device *hdev, struct hl_info_args *args)
+{
+ struct hl_info_mac_addr *mac_addr;
+ u32 max_size = args->return_size;
+ void __user *out = (void __user *) (uintptr_t) args->return_pointer;
+ int rc;
+
+ if (!max_size || !out)
+ return -EINVAL;
+
+ mac_addr = kzalloc(sizeof(struct hl_info_mac_addr), GFP_KERNEL);
+ if (!mac_addr)
+ return -ENOMEM;
+
+ rc = hdev->asic_funcs->get_mac_addr(hdev, mac_addr);
+ if (rc)
+ goto out;
+
+ rc = copy_to_user(out, mac_addr,
+ min((size_t) max_size, sizeof(struct hl_info_mac_addr))) ?
+ -EFAULT : 0;
+
+out:
+ kfree(mac_addr);
+ return rc;
+}
+
static int device_utilization(struct hl_device *hdev, struct hl_info_args *args)
{
struct hl_info_device_utilization device_util = {0};
@@ -423,6 +450,10 @@ static int _hl_info_ioctl(struct hl_fpriv *hpriv, void *data,
rc = hw_idle(hdev, args);
break;

+ case HL_INFO_MAC_ADDR:
+ rc = mac_addr_info(hdev, args);
+ break;
+
case HL_INFO_DEVICE_UTILIZATION:
rc = device_utilization(hdev, args);
break;
diff --git a/drivers/misc/habanalabs/gaudi/gaudi.c b/drivers/misc/habanalabs/gaudi/gaudi.c
index d350519a9e31..8ce20e0f8c59 100644
--- a/drivers/misc/habanalabs/gaudi/gaudi.c
+++ b/drivers/misc/habanalabs/gaudi/gaudi.c
@@ -7470,6 +7470,7 @@ static const struct hl_asic_funcs gaudi_funcs = {
.get_hw_state = gaudi_get_hw_state,
.pci_bars_map = gaudi_pci_bars_map,
.init_iatu = gaudi_init_iatu,
+ .get_mac_addr = gaudi_nic_get_mac_addr,
.rreg = hl_rreg,
.wreg = hl_wreg,
.halt_coresight = gaudi_halt_coresight,
diff --git a/drivers/misc/habanalabs/gaudi/gaudiP.h b/drivers/misc/habanalabs/gaudi/gaudiP.h
index bf3a215e0f8e..17560510a05f 100644
--- a/drivers/misc/habanalabs/gaudi/gaudiP.h
+++ b/drivers/misc/habanalabs/gaudi/gaudiP.h
@@ -566,6 +566,8 @@ void gaudi_nic_ports_fini(struct hl_device *hdev);
int gaudi_nic_hard_reset_prepare(struct hl_device *hdev);
void gaudi_nic_stop(struct hl_device *hdev);
void gaudi_nic_ports_reopen(struct hl_device *hdev);
+int gaudi_nic_get_mac_addr(struct hl_device *hdev,
+ struct hl_info_mac_addr *mac_addr);
void gaudi_nic_ctx_fini(struct hl_ctx *ctx);
irqreturn_t gaudi_nic_rx_irq_handler(int irq, void *arg);
irqreturn_t gaudi_nic_cq_irq_handler(int irq, void *arg);
diff --git a/drivers/misc/habanalabs/gaudi/gaudi_nic.c b/drivers/misc/habanalabs/gaudi/gaudi_nic.c
index ff08cfc81e69..491f426ab0bb 100644
--- a/drivers/misc/habanalabs/gaudi/gaudi_nic.c
+++ b/drivers/misc/habanalabs/gaudi/gaudi_nic.c
@@ -2743,6 +2743,33 @@ void gaudi_nic_ports_reopen(struct hl_device *hdev)
gaudi->hw_cap_initialized |= HW_CAP_NIC_DRV;
}

+int gaudi_nic_get_mac_addr(struct hl_device *hdev,
+ struct hl_info_mac_addr *mac_addr)
+{
+ struct gaudi_device *gaudi = hdev->asic_specific;
+ struct net_device *ndev;
+ int i, number_of_ports;
+
+ if (!(gaudi->hw_cap_initialized & HW_CAP_NIC_DRV))
+ goto out;
+
+ number_of_ports = min_t(int, NIC_NUMBER_OF_PORTS,
+ HL_INFO_MAC_ADDR_MAX_NUM);
+
+ for (i = 0 ; i < number_of_ports ; i++) {
+ if (!(hdev->nic_ports_mask & BIT(i)))
+ continue;
+
+ ndev = gaudi->nic_devices[i].ndev;
+ if (!ndev)
+ continue;
+
+ ether_addr_copy(mac_addr->array[i].addr, ndev->dev_addr);
+ mac_addr->mask[i / 64] |= BIT_ULL(i % 64);
+ }
+out:
+ return 0;
+}
void gaudi_nic_ctx_fini(struct hl_ctx *ctx)
{
}
diff --git a/drivers/misc/habanalabs/goya/goya.c b/drivers/misc/habanalabs/goya/goya.c
index 8e15d9f85af8..e49ee24cde50 100644
--- a/drivers/misc/habanalabs/goya/goya.c
+++ b/drivers/misc/habanalabs/goya/goya.c
@@ -5265,6 +5265,14 @@ static enum hl_device_hw_state goya_get_hw_state(struct hl_device *hdev)
return RREG32(mmHW_STATE);
}

+static int goya_get_mac_addr(struct hl_device *hdev,
+ struct hl_info_mac_addr *mac_addr)
+{
+ dev_err_ratelimited(hdev->dev,
+ "No MAC addresses are assigned to Goya\n");
+ return -ENXIO;
+}
+
static int goya_ctx_init(struct hl_ctx *ctx)
{
return 0;
@@ -5384,6 +5392,7 @@ static const struct hl_asic_funcs goya_funcs = {
.get_hw_state = goya_get_hw_state,
.pci_bars_map = goya_pci_bars_map,
.init_iatu = goya_init_iatu,
+ .get_mac_addr = goya_get_mac_addr,
.rreg = hl_rreg,
.wreg = hl_wreg,
.halt_coresight = goya_halt_coresight,
diff --git a/include/uapi/misc/habanalabs.h b/include/uapi/misc/habanalabs.h
index e8a5b62b95dd..cd600a52f40a 100644
--- a/include/uapi/misc/habanalabs.h
+++ b/include/uapi/misc/habanalabs.h
@@ -10,6 +10,7 @@

#include <linux/types.h>
#include <linux/ioctl.h>
+#include <linux/if_ether.h>

/*
* Defines that are asic-specific but constitutes as ABI between kernel driver
@@ -248,6 +249,8 @@ enum hl_device_status {
* internal engine.
* HL_INFO_DEVICE_STATUS - Retrieve the device's status. This opcode doesn't
* require an open context.
+ * HL_INFO_MAC_ADDR - Retrieve the list of MAC addresses of the device's
+ * network ports, if the device has network ports.
* HL_INFO_DEVICE_UTILIZATION - Retrieve the total utilization of the device
* over the last period specified by the user.
* The period can be between 100ms to 1s, in
@@ -274,6 +277,7 @@ enum hl_device_status {
#define HL_INFO_DRAM_USAGE 2
#define HL_INFO_HW_IDLE 3
#define HL_INFO_DEVICE_STATUS 4
+#define HL_INFO_MAC_ADDR 5
#define HL_INFO_DEVICE_UTILIZATION 6
#define HL_INFO_HW_EVENTS_AGGREGATE 7
#define HL_INFO_CLK_RATE 8
@@ -285,9 +289,11 @@ enum hl_device_status {
#define HL_INFO_SYNC_MANAGER 14
#define HL_INFO_TOTAL_ENERGY 15

-#define HL_INFO_VERSION_MAX_LEN 128
+#define HL_INFO_VERSION_MAX_LEN 128
#define HL_INFO_CARD_NAME_MAX_LEN 16

+#define HL_INFO_MAC_ADDR_MAX_NUM 128
+
struct hl_info_hw_ip_info {
__u64 sram_base_address;
__u64 dram_base_address;
@@ -334,6 +340,18 @@ struct hl_info_device_status {
__u32 pad;
};

+struct hl_mac_addr {
+ __u8 addr[ETH_ALEN];
+ __u8 pad[2];
+};
+
+struct hl_info_mac_addr {
+ /* MAC address at index N is of the corresponding PORT ID */
+ struct hl_mac_addr array[HL_INFO_MAC_ADDR_MAX_NUM];
+ /* Mask of valid entries at the MAC addresses array */
+ __u64 mask[2];
+};
+
struct hl_info_device_utilization {
__u32 utilization;
__u32 pad;
--
2.17.1