Commit 62c1c2e6 authored by Dmitry Bogdanov's avatar Dmitry Bogdanov Committed by David S. Miller
Browse files

net: atlantic: MACSec offload skeleton



This patch adds basic functionality for MACSec offloading for Atlantic
NICs.

MACSec offloading functionality is enabled if network card has
appropriate FW that has MACSec offloading enabled in config.

Actual functionality (ingress, egress, etc) will be added in follow-up
patches.

Signed-off-by: default avatarDmitry Bogdanov <dbogdanov@marvell.com>
Signed-off-by: default avatarMark Starovoytov <mstarovoitov@marvell.com>
Signed-off-by: default avatarIgor Russkikh <irusskikh@marvell.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c850240b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ config AQTION
	tristate "aQuantia AQtion(tm) Support"
	depends on PCI
	depends on X86_64 || ARM64 || COMPILE_TEST
	depends on MACSEC || MACSEC=n
	---help---
	  This enables the support for the aQuantia AQtion(tm) Ethernet card.

+4 −0
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@

obj-$(CONFIG_AQTION) += atlantic.o

ccflags-y += -I$(src)

atlantic-objs := aq_main.o \
	aq_nic.o \
	aq_pci_func.o \
@@ -24,4 +26,6 @@ atlantic-objs := aq_main.o \
	hw_atl/hw_atl_utils_fw2x.o \
	hw_atl/hw_atl_llh.o

atlantic-$(CONFIG_MACSEC) += aq_macsec.o

atlantic-$(CONFIG_PTP_1588_CLOCK) += aq_ptp.o
 No newline at end of file
+6 −0
Original line number Diff line number Diff line
@@ -343,6 +343,12 @@ struct aq_fw_ops {

	int (*get_eee_rate)(struct aq_hw_s *self, u32 *rate,
			    u32 *supported_rates);

	u32 (*get_link_capabilities)(struct aq_hw_s *self);

	int (*send_macsec_req)(struct aq_hw_s *self,
			       struct macsec_msg_fw_request *msg,
			       struct macsec_msg_fw_response *resp);
};

#endif /* AQ_HW_H */
+174 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Atlantic Network Driver
 * Copyright (C) 2020 Marvell International Ltd.
 */

#include "aq_macsec.h"
#include "aq_nic.h"
#include <linux/rtnetlink.h>

static int aq_mdo_dev_open(struct macsec_context *ctx)
{
	return 0;
}

static int aq_mdo_dev_stop(struct macsec_context *ctx)
{
	return 0;
}

static int aq_mdo_add_secy(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_upd_secy(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_del_secy(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_add_txsa(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_upd_txsa(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_del_txsa(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_add_rxsc(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_upd_rxsc(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_del_rxsc(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_add_rxsa(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_upd_rxsa(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static int aq_mdo_del_rxsa(struct macsec_context *ctx)
{
	return -EOPNOTSUPP;
}

static void aq_check_txsa_expiration(struct aq_nic_s *nic)
{
}

const struct macsec_ops aq_macsec_ops = {
	.mdo_dev_open = aq_mdo_dev_open,
	.mdo_dev_stop = aq_mdo_dev_stop,
	.mdo_add_secy = aq_mdo_add_secy,
	.mdo_upd_secy = aq_mdo_upd_secy,
	.mdo_del_secy = aq_mdo_del_secy,
	.mdo_add_rxsc = aq_mdo_add_rxsc,
	.mdo_upd_rxsc = aq_mdo_upd_rxsc,
	.mdo_del_rxsc = aq_mdo_del_rxsc,
	.mdo_add_rxsa = aq_mdo_add_rxsa,
	.mdo_upd_rxsa = aq_mdo_upd_rxsa,
	.mdo_del_rxsa = aq_mdo_del_rxsa,
	.mdo_add_txsa = aq_mdo_add_txsa,
	.mdo_upd_txsa = aq_mdo_upd_txsa,
	.mdo_del_txsa = aq_mdo_del_txsa,
};

int aq_macsec_init(struct aq_nic_s *nic)
{
	struct aq_macsec_cfg *cfg;
	u32 caps_lo;

	if (!nic->aq_fw_ops->get_link_capabilities)
		return 0;

	caps_lo = nic->aq_fw_ops->get_link_capabilities(nic->aq_hw);

	if (!(caps_lo & BIT(CAPS_LO_MACSEC)))
		return 0;

	nic->macsec_cfg = kzalloc(sizeof(*cfg), GFP_KERNEL);
	if (!nic->macsec_cfg)
		return -ENOMEM;

	nic->ndev->features |= NETIF_F_HW_MACSEC;
	nic->ndev->macsec_ops = &aq_macsec_ops;

	return 0;
}

void aq_macsec_free(struct aq_nic_s *nic)
{
	kfree(nic->macsec_cfg);
	nic->macsec_cfg = NULL;
}

int aq_macsec_enable(struct aq_nic_s *nic)
{
	struct macsec_msg_fw_response resp = { 0 };
	struct macsec_msg_fw_request msg = { 0 };
	struct aq_hw_s *hw = nic->aq_hw;
	int ret = 0;

	if (!nic->macsec_cfg)
		return 0;

	rtnl_lock();

	if (nic->aq_fw_ops->send_macsec_req) {
		struct macsec_cfg_request cfg = { 0 };

		cfg.enabled = 1;
		cfg.egress_threshold = 0xffffffff;
		cfg.ingress_threshold = 0xffffffff;
		cfg.interrupts_enabled = 1;

		msg.msg_type = macsec_cfg_msg;
		msg.cfg = cfg;

		ret = nic->aq_fw_ops->send_macsec_req(hw, &msg, &resp);
		if (ret)
			goto unlock;
	}

unlock:
	rtnl_unlock();
	return ret;
}

void aq_macsec_work(struct aq_nic_s *nic)
{
	if (!nic->macsec_cfg)
		return;

	if (!netif_carrier_ok(nic->ndev))
		return;

	rtnl_lock();
	aq_check_txsa_expiration(nic);
	rtnl_unlock();
}
+51 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/* Atlantic Network Driver
 * Copyright (C) 2020 Marvell International Ltd.
 */

#ifndef AQ_MACSEC_H
#define AQ_MACSEC_H

#include <linux/netdevice.h>
#if IS_ENABLED(CONFIG_MACSEC)

#include "net/macsec.h"

struct aq_nic_s;

#define AQ_MACSEC_MAX_SC 32
#define AQ_MACSEC_MAX_SA 32

enum aq_macsec_sc_sa {
	aq_macsec_sa_sc_4sa_8sc,
	aq_macsec_sa_sc_not_used,
	aq_macsec_sa_sc_2sa_16sc,
	aq_macsec_sa_sc_1sa_32sc,
};

struct aq_macsec_txsc {
};

struct aq_macsec_rxsc {
};

struct aq_macsec_cfg {
	enum aq_macsec_sc_sa sc_sa;
	/* Egress channel configuration */
	unsigned long txsc_idx_busy;
	struct aq_macsec_txsc aq_txsc[AQ_MACSEC_MAX_SC];
	/* Ingress channel configuration */
	unsigned long rxsc_idx_busy;
	struct aq_macsec_rxsc aq_rxsc[AQ_MACSEC_MAX_SC];
};

extern const struct macsec_ops aq_macsec_ops;

int aq_macsec_init(struct aq_nic_s *nic);
void aq_macsec_free(struct aq_nic_s *nic);
int aq_macsec_enable(struct aq_nic_s *nic);
void aq_macsec_work(struct aq_nic_s *nic);

#endif

#endif /* AQ_MACSEC_H */
Loading