cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

global1_vtu.c (14629B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Marvell 88E6xxx VLAN [Spanning Tree] Translation Unit (VTU [STU]) support
      4 *
      5 * Copyright (c) 2008 Marvell Semiconductor
      6 * Copyright (c) 2015 CMC Electronics, Inc.
      7 * Copyright (c) 2017 Savoir-faire Linux, Inc.
      8 */
      9
     10#include <linux/bitfield.h>
     11#include <linux/interrupt.h>
     12#include <linux/irqdomain.h>
     13
     14#include "chip.h"
     15#include "global1.h"
     16
     17/* Offset 0x02: VTU FID Register */
     18
     19static int mv88e6xxx_g1_vtu_fid_read(struct mv88e6xxx_chip *chip,
     20				     struct mv88e6xxx_vtu_entry *entry)
     21{
     22	u16 val;
     23	int err;
     24
     25	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_FID, &val);
     26	if (err)
     27		return err;
     28
     29	entry->fid = val & MV88E6352_G1_VTU_FID_MASK;
     30	entry->policy = !!(val & MV88E6352_G1_VTU_FID_VID_POLICY);
     31	return 0;
     32}
     33
     34static int mv88e6xxx_g1_vtu_fid_write(struct mv88e6xxx_chip *chip,
     35				      struct mv88e6xxx_vtu_entry *entry)
     36{
     37	u16 val = entry->fid & MV88E6352_G1_VTU_FID_MASK;
     38
     39	if (entry->policy)
     40		val |= MV88E6352_G1_VTU_FID_VID_POLICY;
     41
     42	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_FID, val);
     43}
     44
     45/* Offset 0x03: VTU SID Register */
     46
     47static int mv88e6xxx_g1_vtu_sid_read(struct mv88e6xxx_chip *chip, u8 *sid)
     48{
     49	u16 val;
     50	int err;
     51
     52	err = mv88e6xxx_g1_read(chip, MV88E6352_G1_VTU_SID, &val);
     53	if (err)
     54		return err;
     55
     56	*sid = val & MV88E6352_G1_VTU_SID_MASK;
     57
     58	return 0;
     59}
     60
     61static int mv88e6xxx_g1_vtu_sid_write(struct mv88e6xxx_chip *chip, u8 sid)
     62{
     63	u16 val = sid & MV88E6352_G1_VTU_SID_MASK;
     64
     65	return mv88e6xxx_g1_write(chip, MV88E6352_G1_VTU_SID, val);
     66}
     67
     68/* Offset 0x05: VTU Operation Register */
     69
     70static int mv88e6xxx_g1_vtu_op_wait(struct mv88e6xxx_chip *chip)
     71{
     72	int bit = __bf_shf(MV88E6XXX_G1_VTU_OP_BUSY);
     73
     74	return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_VTU_OP, bit, 0);
     75}
     76
     77static int mv88e6xxx_g1_vtu_op(struct mv88e6xxx_chip *chip, u16 op)
     78{
     79	int err;
     80
     81	err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_OP,
     82				 MV88E6XXX_G1_VTU_OP_BUSY | op);
     83	if (err)
     84		return err;
     85
     86	return mv88e6xxx_g1_vtu_op_wait(chip);
     87}
     88
     89/* Offset 0x06: VTU VID Register */
     90
     91static int mv88e6xxx_g1_vtu_vid_read(struct mv88e6xxx_chip *chip,
     92				     bool *valid, u16 *vid)
     93{
     94	u16 val;
     95	int err;
     96
     97	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_VID, &val);
     98	if (err)
     99		return err;
    100
    101	if (vid) {
    102		*vid = val & 0xfff;
    103
    104		if (val & MV88E6390_G1_VTU_VID_PAGE)
    105			*vid |= 0x1000;
    106	}
    107
    108	if (valid)
    109		*valid = !!(val & MV88E6XXX_G1_VTU_VID_VALID);
    110
    111	return 0;
    112}
    113
    114static int mv88e6xxx_g1_vtu_vid_write(struct mv88e6xxx_chip *chip,
    115				      bool valid, u16 vid)
    116{
    117	u16 val = vid & 0xfff;
    118
    119	if (vid & 0x1000)
    120		val |= MV88E6390_G1_VTU_VID_PAGE;
    121
    122	if (valid)
    123		val |= MV88E6XXX_G1_VTU_VID_VALID;
    124
    125	return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_VID, val);
    126}
    127
    128/* Offset 0x07: VTU/STU Data Register 1
    129 * Offset 0x08: VTU/STU Data Register 2
    130 * Offset 0x09: VTU/STU Data Register 3
    131 */
    132static int mv88e6185_g1_vtu_stu_data_read(struct mv88e6xxx_chip *chip,
    133					  u16 *regs)
    134{
    135	int i;
    136
    137	/* Read all 3 VTU/STU Data registers */
    138	for (i = 0; i < 3; ++i) {
    139		u16 *reg = &regs[i];
    140		int err;
    141
    142		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
    143		if (err)
    144			return err;
    145	}
    146
    147	return 0;
    148}
    149
    150static int mv88e6185_g1_vtu_data_read(struct mv88e6xxx_chip *chip,
    151				      u8 *member, u8 *state)
    152{
    153	u16 regs[3];
    154	int err;
    155	int i;
    156
    157	err = mv88e6185_g1_vtu_stu_data_read(chip, regs);
    158	if (err)
    159		return err;
    160
    161	/* Extract MemberTag data */
    162	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
    163		unsigned int member_offset = (i % 4) * 4;
    164		unsigned int state_offset = member_offset + 2;
    165
    166		if (member)
    167			member[i] = (regs[i / 4] >> member_offset) & 0x3;
    168
    169		if (state)
    170			state[i] = (regs[i / 4] >> state_offset) & 0x3;
    171	}
    172
    173	return 0;
    174}
    175
    176static int mv88e6185_g1_vtu_data_write(struct mv88e6xxx_chip *chip,
    177				       u8 *member, u8 *state)
    178{
    179	u16 regs[3] = { 0 };
    180	int i;
    181
    182	/* Insert MemberTag and PortState data */
    183	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
    184		unsigned int member_offset = (i % 4) * 4;
    185		unsigned int state_offset = member_offset + 2;
    186
    187		if (member)
    188			regs[i / 4] |= (member[i] & 0x3) << member_offset;
    189
    190		if (state)
    191			regs[i / 4] |= (state[i] & 0x3) << state_offset;
    192	}
    193
    194	/* Write all 3 VTU/STU Data registers */
    195	for (i = 0; i < 3; ++i) {
    196		u16 reg = regs[i];
    197		int err;
    198
    199		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
    200		if (err)
    201			return err;
    202	}
    203
    204	return 0;
    205}
    206
    207static int mv88e6390_g1_vtu_data_read(struct mv88e6xxx_chip *chip, u8 *data)
    208{
    209	u16 regs[2];
    210	int i;
    211
    212	/* Read the 2 VTU/STU Data registers */
    213	for (i = 0; i < 2; ++i) {
    214		u16 *reg = &regs[i];
    215		int err;
    216
    217		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
    218		if (err)
    219			return err;
    220	}
    221
    222	/* Extract data */
    223	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
    224		unsigned int offset = (i % 8) * 2;
    225
    226		data[i] = (regs[i / 8] >> offset) & 0x3;
    227	}
    228
    229	return 0;
    230}
    231
    232static int mv88e6390_g1_vtu_data_write(struct mv88e6xxx_chip *chip, u8 *data)
    233{
    234	u16 regs[2] = { 0 };
    235	int i;
    236
    237	/* Insert data */
    238	for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) {
    239		unsigned int offset = (i % 8) * 2;
    240
    241		regs[i / 8] |= (data[i] & 0x3) << offset;
    242	}
    243
    244	/* Write the 2 VTU/STU Data registers */
    245	for (i = 0; i < 2; ++i) {
    246		u16 reg = regs[i];
    247		int err;
    248
    249		err = mv88e6xxx_g1_write(chip, MV88E6XXX_G1_VTU_DATA1 + i, reg);
    250		if (err)
    251			return err;
    252	}
    253
    254	return 0;
    255}
    256
    257/* VLAN Translation Unit Operations */
    258
    259int mv88e6xxx_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
    260			     struct mv88e6xxx_vtu_entry *entry)
    261{
    262	int err;
    263
    264	err = mv88e6xxx_g1_vtu_op_wait(chip);
    265	if (err)
    266		return err;
    267
    268	/* To get the next higher active VID, the VTU GetNext operation can be
    269	 * started again without setting the VID registers since it already
    270	 * contains the last VID.
    271	 *
    272	 * To save a few hardware accesses and abstract this to the caller,
    273	 * write the VID only once, when the entry is given as invalid.
    274	 */
    275	if (!entry->valid) {
    276		err = mv88e6xxx_g1_vtu_vid_write(chip, false, entry->vid);
    277		if (err)
    278			return err;
    279	}
    280
    281	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_GET_NEXT);
    282	if (err)
    283		return err;
    284
    285	return mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, &entry->vid);
    286}
    287
    288int mv88e6185_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
    289			     struct mv88e6xxx_vtu_entry *entry)
    290{
    291	u16 val;
    292	int err;
    293
    294	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
    295	if (err)
    296		return err;
    297
    298	if (entry->valid) {
    299		err = mv88e6185_g1_vtu_data_read(chip, entry->member, entry->state);
    300		if (err)
    301			return err;
    302
    303		/* VTU DBNum[3:0] are located in VTU Operation 3:0
    304		 * VTU DBNum[7:4] ([5:4] for 6250) are located in VTU Operation 11:8 (9:8)
    305		 */
    306		err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
    307		if (err)
    308			return err;
    309
    310		entry->fid = val & 0x000f;
    311		entry->fid |= (val & 0x0f00) >> 4;
    312		entry->fid &= mv88e6xxx_num_databases(chip) - 1;
    313	}
    314
    315	return 0;
    316}
    317
    318int mv88e6352_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
    319			     struct mv88e6xxx_vtu_entry *entry)
    320{
    321	int err;
    322
    323	/* Fetch VLAN MemberTag data from the VTU */
    324	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
    325	if (err)
    326		return err;
    327
    328	if (entry->valid) {
    329		err = mv88e6185_g1_vtu_data_read(chip, entry->member, NULL);
    330		if (err)
    331			return err;
    332
    333		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
    334		if (err)
    335			return err;
    336
    337		err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
    338		if (err)
    339			return err;
    340	}
    341
    342	return 0;
    343}
    344
    345int mv88e6390_g1_vtu_getnext(struct mv88e6xxx_chip *chip,
    346			     struct mv88e6xxx_vtu_entry *entry)
    347{
    348	int err;
    349
    350	/* Fetch VLAN MemberTag data from the VTU */
    351	err = mv88e6xxx_g1_vtu_getnext(chip, entry);
    352	if (err)
    353		return err;
    354
    355	if (entry->valid) {
    356		err = mv88e6390_g1_vtu_data_read(chip, entry->member);
    357		if (err)
    358			return err;
    359
    360		err = mv88e6xxx_g1_vtu_fid_read(chip, entry);
    361		if (err)
    362			return err;
    363
    364		err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
    365		if (err)
    366			return err;
    367	}
    368
    369	return 0;
    370}
    371
    372int mv88e6185_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
    373			       struct mv88e6xxx_vtu_entry *entry)
    374{
    375	u16 op = MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE;
    376	int err;
    377
    378	err = mv88e6xxx_g1_vtu_op_wait(chip);
    379	if (err)
    380		return err;
    381
    382	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
    383	if (err)
    384		return err;
    385
    386	if (entry->valid) {
    387		err = mv88e6185_g1_vtu_data_write(chip, entry->member, entry->state);
    388		if (err)
    389			return err;
    390
    391		/* VTU DBNum[3:0] are located in VTU Operation 3:0
    392		 * VTU DBNum[7:4] are located in VTU Operation 11:8
    393		 *
    394		 * For the 6250/6220, the latter are really [5:4] and
    395		 * 9:8, but in those cases bits 7:6 of entry->fid are
    396		 * 0 since they have num_databases = 64.
    397		 */
    398		op |= entry->fid & 0x000f;
    399		op |= (entry->fid & 0x00f0) << 4;
    400	}
    401
    402	return mv88e6xxx_g1_vtu_op(chip, op);
    403}
    404
    405int mv88e6352_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
    406			       struct mv88e6xxx_vtu_entry *entry)
    407{
    408	int err;
    409
    410	err = mv88e6xxx_g1_vtu_op_wait(chip);
    411	if (err)
    412		return err;
    413
    414	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
    415	if (err)
    416		return err;
    417
    418	if (entry->valid) {
    419		/* Write MemberTag data */
    420		err = mv88e6185_g1_vtu_data_write(chip, entry->member, NULL);
    421		if (err)
    422			return err;
    423
    424		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
    425		if (err)
    426			return err;
    427
    428		err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
    429		if (err)
    430			return err;
    431	}
    432
    433	/* Load/Purge VTU entry */
    434	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
    435}
    436
    437int mv88e6390_g1_vtu_loadpurge(struct mv88e6xxx_chip *chip,
    438			       struct mv88e6xxx_vtu_entry *entry)
    439{
    440	int err;
    441
    442	err = mv88e6xxx_g1_vtu_op_wait(chip);
    443	if (err)
    444		return err;
    445
    446	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, entry->vid);
    447	if (err)
    448		return err;
    449
    450	if (entry->valid) {
    451		/* Write MemberTag data */
    452		err = mv88e6390_g1_vtu_data_write(chip, entry->member);
    453		if (err)
    454			return err;
    455
    456		err = mv88e6xxx_g1_vtu_fid_write(chip, entry);
    457		if (err)
    458			return err;
    459
    460		err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
    461		if (err)
    462			return err;
    463	}
    464
    465	/* Load/Purge VTU entry */
    466	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_VTU_LOAD_PURGE);
    467}
    468
    469int mv88e6xxx_g1_vtu_flush(struct mv88e6xxx_chip *chip)
    470{
    471	int err;
    472
    473	err = mv88e6xxx_g1_vtu_op_wait(chip);
    474	if (err)
    475		return err;
    476
    477	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_FLUSH_ALL);
    478}
    479
    480/* Spanning Tree Unit Operations */
    481
    482int mv88e6xxx_g1_stu_getnext(struct mv88e6xxx_chip *chip,
    483			     struct mv88e6xxx_stu_entry *entry)
    484{
    485	int err;
    486
    487	err = mv88e6xxx_g1_vtu_op_wait(chip);
    488	if (err)
    489		return err;
    490
    491	/* To get the next higher active SID, the STU GetNext operation can be
    492	 * started again without setting the SID registers since it already
    493	 * contains the last SID.
    494	 *
    495	 * To save a few hardware accesses and abstract this to the caller,
    496	 * write the SID only once, when the entry is given as invalid.
    497	 */
    498	if (!entry->valid) {
    499		err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
    500		if (err)
    501			return err;
    502	}
    503
    504	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_GET_NEXT);
    505	if (err)
    506		return err;
    507
    508	err = mv88e6xxx_g1_vtu_vid_read(chip, &entry->valid, NULL);
    509	if (err)
    510		return err;
    511
    512	if (entry->valid) {
    513		err = mv88e6xxx_g1_vtu_sid_read(chip, &entry->sid);
    514		if (err)
    515			return err;
    516	}
    517
    518	return 0;
    519}
    520
    521int mv88e6352_g1_stu_getnext(struct mv88e6xxx_chip *chip,
    522			     struct mv88e6xxx_stu_entry *entry)
    523{
    524	int err;
    525
    526	err = mv88e6xxx_g1_stu_getnext(chip, entry);
    527	if (err)
    528		return err;
    529
    530	if (!entry->valid)
    531		return 0;
    532
    533	return mv88e6185_g1_vtu_data_read(chip, NULL, entry->state);
    534}
    535
    536int mv88e6390_g1_stu_getnext(struct mv88e6xxx_chip *chip,
    537			     struct mv88e6xxx_stu_entry *entry)
    538{
    539	int err;
    540
    541	err = mv88e6xxx_g1_stu_getnext(chip, entry);
    542	if (err)
    543		return err;
    544
    545	if (!entry->valid)
    546		return 0;
    547
    548	return mv88e6390_g1_vtu_data_read(chip, entry->state);
    549}
    550
    551int mv88e6352_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
    552			       struct mv88e6xxx_stu_entry *entry)
    553{
    554	int err;
    555
    556	err = mv88e6xxx_g1_vtu_op_wait(chip);
    557	if (err)
    558		return err;
    559
    560	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
    561	if (err)
    562		return err;
    563
    564	err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
    565	if (err)
    566		return err;
    567
    568	if (entry->valid) {
    569		err = mv88e6185_g1_vtu_data_write(chip, NULL, entry->state);
    570		if (err)
    571			return err;
    572	}
    573
    574	/* Load/Purge STU entry */
    575	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
    576}
    577
    578int mv88e6390_g1_stu_loadpurge(struct mv88e6xxx_chip *chip,
    579			       struct mv88e6xxx_stu_entry *entry)
    580{
    581	int err;
    582
    583	err = mv88e6xxx_g1_vtu_op_wait(chip);
    584	if (err)
    585		return err;
    586
    587	err = mv88e6xxx_g1_vtu_vid_write(chip, entry->valid, 0);
    588	if (err)
    589		return err;
    590
    591	err = mv88e6xxx_g1_vtu_sid_write(chip, entry->sid);
    592	if (err)
    593		return err;
    594
    595	if (entry->valid) {
    596		err = mv88e6390_g1_vtu_data_write(chip, entry->state);
    597		if (err)
    598			return err;
    599	}
    600
    601	/* Load/Purge STU entry */
    602	return mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_STU_LOAD_PURGE);
    603}
    604
    605/* VTU Violation Management */
    606
    607static irqreturn_t mv88e6xxx_g1_vtu_prob_irq_thread_fn(int irq, void *dev_id)
    608{
    609	struct mv88e6xxx_chip *chip = dev_id;
    610	u16 val, vid;
    611	int spid;
    612	int err;
    613
    614	mv88e6xxx_reg_lock(chip);
    615
    616	err = mv88e6xxx_g1_vtu_op(chip, MV88E6XXX_G1_VTU_OP_GET_CLR_VIOLATION);
    617	if (err)
    618		goto out;
    619
    620	err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_VTU_OP, &val);
    621	if (err)
    622		goto out;
    623
    624	err = mv88e6xxx_g1_vtu_vid_read(chip, NULL, &vid);
    625	if (err)
    626		goto out;
    627
    628	spid = val & MV88E6XXX_G1_VTU_OP_SPID_MASK;
    629
    630	if (val & MV88E6XXX_G1_VTU_OP_MEMBER_VIOLATION) {
    631		dev_err_ratelimited(chip->dev, "VTU member violation for vid %d, source port %d\n",
    632				    vid, spid);
    633		chip->ports[spid].vtu_member_violation++;
    634	}
    635
    636	if (val & MV88E6XXX_G1_VTU_OP_MISS_VIOLATION) {
    637		dev_dbg_ratelimited(chip->dev, "VTU miss violation for vid %d, source port %d\n",
    638				    vid, spid);
    639		chip->ports[spid].vtu_miss_violation++;
    640	}
    641
    642	mv88e6xxx_reg_unlock(chip);
    643
    644	return IRQ_HANDLED;
    645
    646out:
    647	mv88e6xxx_reg_unlock(chip);
    648
    649	dev_err(chip->dev, "VTU problem: error %d while handling interrupt\n",
    650		err);
    651
    652	return IRQ_HANDLED;
    653}
    654
    655int mv88e6xxx_g1_vtu_prob_irq_setup(struct mv88e6xxx_chip *chip)
    656{
    657	int err;
    658
    659	chip->vtu_prob_irq = irq_find_mapping(chip->g1_irq.domain,
    660					      MV88E6XXX_G1_STS_IRQ_VTU_PROB);
    661	if (chip->vtu_prob_irq < 0)
    662		return chip->vtu_prob_irq;
    663
    664	snprintf(chip->vtu_prob_irq_name, sizeof(chip->vtu_prob_irq_name),
    665		 "mv88e6xxx-%s-g1-vtu-prob", dev_name(chip->dev));
    666
    667	err = request_threaded_irq(chip->vtu_prob_irq, NULL,
    668				   mv88e6xxx_g1_vtu_prob_irq_thread_fn,
    669				   IRQF_ONESHOT, chip->vtu_prob_irq_name,
    670				   chip);
    671	if (err)
    672		irq_dispose_mapping(chip->vtu_prob_irq);
    673
    674	return err;
    675}
    676
    677void mv88e6xxx_g1_vtu_prob_irq_free(struct mv88e6xxx_chip *chip)
    678{
    679	free_irq(chip->vtu_prob_irq, chip);
    680	irq_dispose_mapping(chip->vtu_prob_irq);
    681}