aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/qlnx/qlnxe/qlnx_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/qlnx/qlnxe/qlnx_ioctl.c')
-rw-r--r--sys/dev/qlnx/qlnxe/qlnx_ioctl.c238
1 files changed, 237 insertions, 1 deletions
diff --git a/sys/dev/qlnx/qlnxe/qlnx_ioctl.c b/sys/dev/qlnx/qlnxe/qlnx_ioctl.c
index c5572c78a8cb..7442ca9b69fa 100644
--- a/sys/dev/qlnx/qlnxe/qlnx_ioctl.c
+++ b/sys/dev/qlnx/qlnxe/qlnx_ioctl.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include "nvm_cfg.h"
#include "ecore_dev_api.h"
#include "ecore_dbg_fw_funcs.h"
+#include "ecore_dcbx_api.h"
#include "qlnx_ioctl.h"
#include "qlnx_def.h"
@@ -574,7 +575,7 @@ qlnx_dev_settings(qlnx_host_t *ha, qlnx_dev_setting_t *dev_info)
p_hwfn = &ha->cdev.hwfns[0];
- qlnx_fill_link(p_hwfn, &if_link);
+ qlnx_fill_link(ha, p_hwfn, &if_link);
dev_info->supported = if_link.supported_caps;
dev_info->advertising = if_link.advertised_caps;
@@ -771,6 +772,235 @@ qlnx_storm_stats(qlnx_host_t *ha, qlnx_storm_stats_dump_t *s_stats)
return;
}
+#ifdef QLNX_USER_LLDP
+
+static int
+qlnx_lldp_configure(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn,
+ struct ecore_ptt *p_ptt, uint32_t enable)
+{
+ int ret = 0;
+ uint8_t lldp_mac[6] = {0};
+ struct ecore_lldp_config_params lldp_params;
+ struct ecore_lldp_sys_tlvs tlv_params;
+
+ ret = ecore_mcp_get_lldp_mac(p_hwfn, p_ptt, lldp_mac);
+
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: ecore_mcp_get_lldp_mac failed\n", __func__);
+ return (-1);
+ }
+
+ bzero(&lldp_params, sizeof(struct ecore_lldp_config_params));
+ bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs));
+
+ lldp_params.agent = ECORE_LLDP_NEAREST_BRIDGE;
+ lldp_params.tx_interval = 30; //Default value used as suggested by MFW
+ lldp_params.tx_hold = 4; //Default value used as suggested by MFW
+ lldp_params.tx_credit = 5; //Default value used as suggested by MFW
+ lldp_params.rx_enable = enable ? 1 : 0;
+ lldp_params.tx_enable = enable ? 1 : 0;
+
+ lldp_params.chassis_id_tlv[0] = 0;
+ lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_TYPE_CHASSIS_ID << 1);
+ lldp_params.chassis_id_tlv[0] |=
+ ((QLNX_LLDP_CHASSIS_ID_SUBTYPE_OCTETS +
+ QLNX_LLDP_CHASSIS_ID_MAC_ADDR_LEN) << 8);
+ lldp_params.chassis_id_tlv[0] |= (QLNX_LLDP_CHASSIS_ID_SUBTYPE_MAC << 16);
+ lldp_params.chassis_id_tlv[0] |= lldp_mac[0] << 24;
+ lldp_params.chassis_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) |
+ (lldp_mac[3] << 16) | (lldp_mac[4] << 24);
+ lldp_params.chassis_id_tlv[2] = lldp_mac[5];
+
+
+ lldp_params.port_id_tlv[0] = 0;
+ lldp_params.port_id_tlv[0] |= (QLNX_LLDP_TYPE_PORT_ID << 1);
+ lldp_params.port_id_tlv[0] |=
+ ((QLNX_LLDP_PORT_ID_SUBTYPE_OCTETS +
+ QLNX_LLDP_PORT_ID_MAC_ADDR_LEN) << 8);
+ lldp_params.port_id_tlv[0] |= (QLNX_LLDP_PORT_ID_SUBTYPE_MAC << 16);
+ lldp_params.port_id_tlv[0] |= lldp_mac[0] << 24;
+ lldp_params.port_id_tlv[1] = lldp_mac[1] | (lldp_mac[2] << 8) |
+ (lldp_mac[3] << 16) | (lldp_mac[4] << 24);
+ lldp_params.port_id_tlv[2] = lldp_mac[5];
+
+ ret = ecore_lldp_set_params(p_hwfn, p_ptt, &lldp_params);
+
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: ecore_lldp_set_params failed\n", __func__);
+ return (-1);
+ }
+
+ //If LLDP is disable then disable discard_mandatory_tlv flag
+ if (!enable) {
+ tlv_params.discard_mandatory_tlv = false;
+ tlv_params.buf_size = 0;
+ ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params);
+ }
+
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: ecore_lldp_set_system_tlvs failed\n", __func__);
+ }
+
+ return (ret);
+}
+
+static int
+qlnx_register_default_lldp_tlvs(qlnx_host_t *ha, struct ecore_hwfn *p_hwfn,
+ struct ecore_ptt *p_ptt)
+{
+ int ret = 0;
+
+ ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
+ ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_CHASSIS_ID);
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: QLNX_LLDP_TYPE_CHASSIS_ID failed\n", __func__);
+ goto qlnx_register_default_lldp_tlvs_exit;
+ }
+
+ //register Port ID TLV
+ ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
+ ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_ID);
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: QLNX_LLDP_TYPE_PORT_ID failed\n", __func__);
+ goto qlnx_register_default_lldp_tlvs_exit;
+ }
+
+ //register TTL TLV
+ ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
+ ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_TTL);
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: QLNX_LLDP_TYPE_TTL failed\n", __func__);
+ goto qlnx_register_default_lldp_tlvs_exit;
+ }
+
+ //register Port Description TLV
+ ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
+ ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_PORT_DESC);
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: QLNX_LLDP_TYPE_PORT_DESC failed\n", __func__);
+ goto qlnx_register_default_lldp_tlvs_exit;
+ }
+
+ //register System Name TLV
+ ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
+ ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_NAME);
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: QLNX_LLDP_TYPE_SYS_NAME failed\n", __func__);
+ goto qlnx_register_default_lldp_tlvs_exit;
+ }
+
+ //register System Description TLV
+ ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
+ ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_DESC);
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: QLNX_LLDP_TYPE_SYS_DESC failed\n", __func__);
+ goto qlnx_register_default_lldp_tlvs_exit;
+ }
+
+ //register System Capabilities TLV
+ ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
+ ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_SYS_CAPS);
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: QLNX_LLDP_TYPE_SYS_CAPS failed\n", __func__);
+ goto qlnx_register_default_lldp_tlvs_exit;
+ }
+
+ //register Management Address TLV
+ ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
+ ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_MGMT_ADDR);
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: QLNX_LLDP_TYPE_MGMT_ADDR failed\n", __func__);
+ goto qlnx_register_default_lldp_tlvs_exit;
+ }
+
+ //register Organizationally Specific TLVs
+ ret = ecore_lldp_register_tlv(p_hwfn, p_ptt,
+ ECORE_LLDP_NEAREST_BRIDGE, QLNX_LLDP_TYPE_ORG_SPECIFIC);
+ if (ret != ECORE_SUCCESS) {
+ device_printf(ha->pci_dev,
+ "%s: QLNX_LLDP_TYPE_ORG_SPECIFIC failed\n", __func__);
+ }
+
+qlnx_register_default_lldp_tlvs_exit:
+ return (ret);
+}
+
+int
+qlnx_set_lldp_tlvx(qlnx_host_t *ha, qlnx_lldp_sys_tlvs_t *lldp_tlvs)
+{
+ int ret = 0;
+ struct ecore_hwfn *p_hwfn;
+ struct ecore_ptt *p_ptt;
+ struct ecore_lldp_sys_tlvs tlv_params;
+
+ p_hwfn = &ha->cdev.hwfns[0];
+ p_ptt = ecore_ptt_acquire(p_hwfn);
+
+ if (!p_ptt) {
+ device_printf(ha->pci_dev,
+ "%s: ecore_ptt_acquire failed\n", __func__);
+ return (ENXIO);
+ }
+
+ ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 0);
+
+ if (ret) {
+ device_printf(ha->pci_dev,
+ "%s: qlnx_lldp_configure disable failed\n", __func__);
+ goto qlnx_set_lldp_tlvx_exit;
+ }
+
+ ret = qlnx_register_default_lldp_tlvs(ha, p_hwfn, p_ptt);
+
+ if (ret) {
+ device_printf(ha->pci_dev,
+ "%s: qlnx_register_default_lldp_tlvs failed\n",
+ __func__);
+ goto qlnx_set_lldp_tlvx_exit;
+ }
+
+ ret = qlnx_lldp_configure(ha, p_hwfn, p_ptt, 1);
+
+ if (ret) {
+ device_printf(ha->pci_dev,
+ "%s: qlnx_lldp_configure enable failed\n", __func__);
+ goto qlnx_set_lldp_tlvx_exit;
+ }
+
+ if (lldp_tlvs != NULL) {
+ bzero(&tlv_params, sizeof(struct ecore_lldp_sys_tlvs));
+
+ tlv_params.discard_mandatory_tlv =
+ (lldp_tlvs->discard_mandatory_tlv ? true: false);
+ tlv_params.buf_size = lldp_tlvs->buf_size;
+ memcpy(tlv_params.buf, lldp_tlvs->buf, lldp_tlvs->buf_size);
+
+ ret = ecore_lldp_set_system_tlvs(p_hwfn, p_ptt, &tlv_params);
+
+ if (ret) {
+ device_printf(ha->pci_dev,
+ "%s: ecore_lldp_set_system_tlvs failed\n",
+ __func__);
+ }
+ }
+qlnx_set_lldp_tlvx_exit:
+
+ ecore_ptt_release(p_hwfn, p_ptt);
+ return (ret);
+}
+
+#endif /* #ifdef QLNX_USER_LLDP */
static int
qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
@@ -854,6 +1084,12 @@ qlnx_eioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
}
break;
+#ifdef QLNX_USER_LLDP
+ case QLNX_SET_LLDP_TLVS:
+ rval = qlnx_set_lldp_tlvx(ha, (qlnx_lldp_sys_tlvs_t *)data);
+ break;
+#endif /* #ifdef QLNX_USER_LLDP */
+
default:
rval = EINVAL;
break;