drivers/net/ethernet/aquantia/atlantic/macsec/macsec_api.c

Source file repositories/reference/linux-study-clean/drivers/net/ethernet/aquantia/atlantic/macsec/macsec_api.c

File Facts

System
Linux kernel
Corpus path
drivers/net/ethernet/aquantia/atlantic/macsec/macsec_api.c
Extension
.c
Size
67407 bytes
Lines
2478
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0-only
/* Atlantic Network Driver
 * Copyright (C) 2020 Marvell International Ltd.
 */

#include "macsec_api.h"
#include <linux/mdio.h>
#include "MSS_Ingress_registers.h"
#include "MSS_Egress_registers.h"
#include "aq_phy.h"

#define AQ_API_CALL_SAFE(func, ...)                                            \
({                                                                             \
	int ret;                                                               \
	do {                                                                   \
		ret = aq_mss_mdio_sem_get(hw);                                 \
		if (unlikely(ret))                                             \
			break;                                                 \
									       \
		ret = func(__VA_ARGS__);                                       \
									       \
		aq_mss_mdio_sem_put(hw);                                       \
	} while (0);                                                           \
	ret;                                                                   \
})

/*******************************************************************************
 *                               MDIO wrappers
 ******************************************************************************/
static int aq_mss_mdio_sem_get(struct aq_hw_s *hw)
{
	u32 val;

	return readx_poll_timeout_atomic(hw_atl_sem_mdio_get, hw, val,
					 val == 1U, 10U, 100000U);
}

static void aq_mss_mdio_sem_put(struct aq_hw_s *hw)
{
	hw_atl_reg_glb_cpu_sem_set(hw, 1U, HW_ATL_FW_SM_MDIO);
}

static int aq_mss_mdio_read(struct aq_hw_s *hw, u16 mmd, u16 addr, u16 *data)
{
	*data = aq_mdio_read_word(hw, mmd, addr);
	return (*data != 0xffff) ? 0 : -ETIME;
}

static int aq_mss_mdio_write(struct aq_hw_s *hw, u16 mmd, u16 addr, u16 data)
{
	aq_mdio_write_word(hw, mmd, addr, data);
	return 0;
}

/*******************************************************************************
 *                          MACSEC config and status
 ******************************************************************************/

static int set_raw_ingress_record(struct aq_hw_s *hw, u16 *packed_record,
				  u8 num_words, u8 table_id,
				  u16 table_index)
{
	struct mss_ingress_lut_addr_ctl_register lut_sel_reg;
	struct mss_ingress_lut_ctl_register lut_op_reg;

	unsigned int i;

	/* NOTE: MSS registers must always be read/written as adjacent pairs.
	 * For instance, to write either or both 1E.80A0 and 80A1, we have to:
	 * 1. Write 1E.80A0 first
	 * 2. Then write 1E.80A1
	 *
	 * For HHD devices: These writes need to be performed consecutively, and
	 * to ensure this we use the PIF mailbox to delegate the reads/writes to
	 * the FW.
	 *
	 * For EUR devices: Not need to use the PIF mailbox; it is safe to
	 * write to the registers directly.
	 */

	/* Write the packed record words to the data buffer registers. */
	for (i = 0; i < num_words; i += 2) {
		aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
				  MSS_INGRESS_LUT_DATA_CTL_REGISTER_ADDR + i,
				  packed_record[i]);
		aq_mss_mdio_write(hw, MDIO_MMD_VEND1,
				  MSS_INGRESS_LUT_DATA_CTL_REGISTER_ADDR + i +
					  1,
				  packed_record[i + 1]);
	}

Annotation

Implementation Notes