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

mc5.c (12494B)


      1/*
      2 * Copyright (c) 2003-2008 Chelsio, Inc. All rights reserved.
      3 *
      4 * This software is available to you under a choice of one of two
      5 * licenses.  You may choose to be licensed under the terms of the GNU
      6 * General Public License (GPL) Version 2, available from the file
      7 * COPYING in the main directory of this source tree, or the
      8 * OpenIB.org BSD license below:
      9 *
     10 *     Redistribution and use in source and binary forms, with or
     11 *     without modification, are permitted provided that the following
     12 *     conditions are met:
     13 *
     14 *      - Redistributions of source code must retain the above
     15 *        copyright notice, this list of conditions and the following
     16 *        disclaimer.
     17 *
     18 *      - Redistributions in binary form must reproduce the above
     19 *        copyright notice, this list of conditions and the following
     20 *        disclaimer in the documentation and/or other materials
     21 *        provided with the distribution.
     22 *
     23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     30 * SOFTWARE.
     31 */
     32#include "common.h"
     33#include "regs.h"
     34
     35enum {
     36	IDT75P52100 = 4,
     37	IDT75N43102 = 5
     38};
     39
     40/* DBGI command mode */
     41enum {
     42	DBGI_MODE_MBUS = 0,
     43	DBGI_MODE_IDT52100 = 5
     44};
     45
     46/* IDT 75P52100 commands */
     47#define IDT_CMD_READ   0
     48#define IDT_CMD_WRITE  1
     49#define IDT_CMD_SEARCH 2
     50#define IDT_CMD_LEARN  3
     51
     52/* IDT LAR register address and value for 144-bit mode (low 32 bits) */
     53#define IDT_LAR_ADR0   	0x180006
     54#define IDT_LAR_MODE144	0xffff0000
     55
     56/* IDT SCR and SSR addresses (low 32 bits) */
     57#define IDT_SCR_ADR0  0x180000
     58#define IDT_SSR0_ADR0 0x180002
     59#define IDT_SSR1_ADR0 0x180004
     60
     61/* IDT GMR base address (low 32 bits) */
     62#define IDT_GMR_BASE_ADR0 0x180020
     63
     64/* IDT data and mask array base addresses (low 32 bits) */
     65#define IDT_DATARY_BASE_ADR0 0
     66#define IDT_MSKARY_BASE_ADR0 0x80000
     67
     68/* IDT 75N43102 commands */
     69#define IDT4_CMD_SEARCH144 3
     70#define IDT4_CMD_WRITE     4
     71#define IDT4_CMD_READ      5
     72
     73/* IDT 75N43102 SCR address (low 32 bits) */
     74#define IDT4_SCR_ADR0  0x3
     75
     76/* IDT 75N43102 GMR base addresses (low 32 bits) */
     77#define IDT4_GMR_BASE0 0x10
     78#define IDT4_GMR_BASE1 0x20
     79#define IDT4_GMR_BASE2 0x30
     80
     81/* IDT 75N43102 data and mask array base addresses (low 32 bits) */
     82#define IDT4_DATARY_BASE_ADR0 0x1000000
     83#define IDT4_MSKARY_BASE_ADR0 0x2000000
     84
     85#define MAX_WRITE_ATTEMPTS 5
     86
     87#define MAX_ROUTES 2048
     88
     89/*
     90 * Issue a command to the TCAM and wait for its completion.  The address and
     91 * any data required by the command must have been setup by the caller.
     92 */
     93static int mc5_cmd_write(struct adapter *adapter, u32 cmd)
     94{
     95	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_CMD, cmd);
     96	return t3_wait_op_done(adapter, A_MC5_DB_DBGI_RSP_STATUS,
     97			       F_DBGIRSPVALID, 1, MAX_WRITE_ATTEMPTS, 1);
     98}
     99
    100static inline void dbgi_wr_data3(struct adapter *adapter, u32 v1, u32 v2,
    101				 u32 v3)
    102{
    103	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA0, v1);
    104	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA1, v2);
    105	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_DATA2, v3);
    106}
    107
    108/*
    109 * Write data to the TCAM register at address (0, 0, addr_lo) using the TCAM
    110 * command cmd.  The data to be written must have been set up by the caller.
    111 * Returns -1 on failure, 0 on success.
    112 */
    113static int mc5_write(struct adapter *adapter, u32 addr_lo, u32 cmd)
    114{
    115	t3_write_reg(adapter, A_MC5_DB_DBGI_REQ_ADDR0, addr_lo);
    116	if (mc5_cmd_write(adapter, cmd) == 0)
    117		return 0;
    118	CH_ERR(adapter, "MC5 timeout writing to TCAM address 0x%x\n",
    119	       addr_lo);
    120	return -1;
    121}
    122
    123static int init_mask_data_array(struct mc5 *mc5, u32 mask_array_base,
    124				u32 data_array_base, u32 write_cmd,
    125				int addr_shift)
    126{
    127	unsigned int i;
    128	struct adapter *adap = mc5->adapter;
    129
    130	/*
    131	 * We need the size of the TCAM data and mask arrays in terms of
    132	 * 72-bit entries.
    133	 */
    134	unsigned int size72 = mc5->tcam_size;
    135	unsigned int server_base = t3_read_reg(adap, A_MC5_DB_SERVER_INDEX);
    136
    137	if (mc5->mode == MC5_MODE_144_BIT) {
    138		size72 *= 2;	/* 1 144-bit entry is 2 72-bit entries */
    139		server_base *= 2;
    140	}
    141
    142	/* Clear the data array */
    143	dbgi_wr_data3(adap, 0, 0, 0);
    144	for (i = 0; i < size72; i++)
    145		if (mc5_write(adap, data_array_base + (i << addr_shift),
    146			      write_cmd))
    147			return -1;
    148
    149	/* Initialize the mask array. */
    150	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
    151	for (i = 0; i < size72; i++) {
    152		if (i == server_base)	/* entering server or routing region */
    153			t3_write_reg(adap, A_MC5_DB_DBGI_REQ_DATA0,
    154				     mc5->mode == MC5_MODE_144_BIT ?
    155				     0xfffffff9 : 0xfffffffd);
    156		if (mc5_write(adap, mask_array_base + (i << addr_shift),
    157			      write_cmd))
    158			return -1;
    159	}
    160	return 0;
    161}
    162
    163static int init_idt52100(struct mc5 *mc5)
    164{
    165	int i;
    166	struct adapter *adap = mc5->adapter;
    167
    168	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
    169		     V_RDLAT(0x15) | V_LRNLAT(0x15) | V_SRCHLAT(0x15));
    170	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 2);
    171
    172	/*
    173	 * Use GMRs 14-15 for ELOOKUP, GMRs 12-13 for SYN lookups, and
    174	 * GMRs 8-9 for ACK- and AOPEN searches.
    175	 */
    176	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT_CMD_WRITE);
    177	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT_CMD_WRITE);
    178	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD, IDT_CMD_SEARCH);
    179	t3_write_reg(adap, A_MC5_DB_AOPEN_LRN_CMD, IDT_CMD_LEARN);
    180	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT_CMD_SEARCH | 0x6000);
    181	t3_write_reg(adap, A_MC5_DB_SYN_LRN_CMD, IDT_CMD_LEARN);
    182	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT_CMD_SEARCH);
    183	t3_write_reg(adap, A_MC5_DB_ACK_LRN_CMD, IDT_CMD_LEARN);
    184	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT_CMD_SEARCH);
    185	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT_CMD_SEARCH | 0x7000);
    186	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT_CMD_WRITE);
    187	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT_CMD_READ);
    188
    189	/* Set DBGI command mode for IDT TCAM. */
    190	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
    191
    192	/* Set up LAR */
    193	dbgi_wr_data3(adap, IDT_LAR_MODE144, 0, 0);
    194	if (mc5_write(adap, IDT_LAR_ADR0, IDT_CMD_WRITE))
    195		goto err;
    196
    197	/* Set up SSRs */
    198	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0);
    199	if (mc5_write(adap, IDT_SSR0_ADR0, IDT_CMD_WRITE) ||
    200	    mc5_write(adap, IDT_SSR1_ADR0, IDT_CMD_WRITE))
    201		goto err;
    202
    203	/* Set up GMRs */
    204	for (i = 0; i < 32; ++i) {
    205		if (i >= 12 && i < 15)
    206			dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
    207		else if (i == 15)
    208			dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
    209		else
    210			dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
    211
    212		if (mc5_write(adap, IDT_GMR_BASE_ADR0 + i, IDT_CMD_WRITE))
    213			goto err;
    214	}
    215
    216	/* Set up SCR */
    217	dbgi_wr_data3(adap, 1, 0, 0);
    218	if (mc5_write(adap, IDT_SCR_ADR0, IDT_CMD_WRITE))
    219		goto err;
    220
    221	return init_mask_data_array(mc5, IDT_MSKARY_BASE_ADR0,
    222				    IDT_DATARY_BASE_ADR0, IDT_CMD_WRITE, 0);
    223err:
    224	return -EIO;
    225}
    226
    227static int init_idt43102(struct mc5 *mc5)
    228{
    229	int i;
    230	struct adapter *adap = mc5->adapter;
    231
    232	t3_write_reg(adap, A_MC5_DB_RSP_LATENCY,
    233		     adap->params.rev == 0 ? V_RDLAT(0xd) | V_SRCHLAT(0x11) :
    234		     V_RDLAT(0xd) | V_SRCHLAT(0x12));
    235
    236	/*
    237	 * Use GMRs 24-25 for ELOOKUP, GMRs 20-21 for SYN lookups, and no mask
    238	 * for ACK- and AOPEN searches.
    239	 */
    240	t3_write_reg(adap, A_MC5_DB_POPEN_DATA_WR_CMD, IDT4_CMD_WRITE);
    241	t3_write_reg(adap, A_MC5_DB_POPEN_MASK_WR_CMD, IDT4_CMD_WRITE);
    242	t3_write_reg(adap, A_MC5_DB_AOPEN_SRCH_CMD,
    243		     IDT4_CMD_SEARCH144 | 0x3800);
    244	t3_write_reg(adap, A_MC5_DB_SYN_SRCH_CMD, IDT4_CMD_SEARCH144);
    245	t3_write_reg(adap, A_MC5_DB_ACK_SRCH_CMD, IDT4_CMD_SEARCH144 | 0x3800);
    246	t3_write_reg(adap, A_MC5_DB_ILOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x3800);
    247	t3_write_reg(adap, A_MC5_DB_ELOOKUP_CMD, IDT4_CMD_SEARCH144 | 0x800);
    248	t3_write_reg(adap, A_MC5_DB_DATA_WRITE_CMD, IDT4_CMD_WRITE);
    249	t3_write_reg(adap, A_MC5_DB_DATA_READ_CMD, IDT4_CMD_READ);
    250
    251	t3_write_reg(adap, A_MC5_DB_PART_ID_INDEX, 3);
    252
    253	/* Set DBGI command mode for IDT TCAM. */
    254	t3_write_reg(adap, A_MC5_DB_DBGI_CONFIG, DBGI_MODE_IDT52100);
    255
    256	/* Set up GMRs */
    257	dbgi_wr_data3(adap, 0xffffffff, 0xffffffff, 0xff);
    258	for (i = 0; i < 7; ++i)
    259		if (mc5_write(adap, IDT4_GMR_BASE0 + i, IDT4_CMD_WRITE))
    260			goto err;
    261
    262	for (i = 0; i < 4; ++i)
    263		if (mc5_write(adap, IDT4_GMR_BASE2 + i, IDT4_CMD_WRITE))
    264			goto err;
    265
    266	dbgi_wr_data3(adap, 0xfffffff9, 0xffffffff, 0xff);
    267	if (mc5_write(adap, IDT4_GMR_BASE1, IDT4_CMD_WRITE) ||
    268	    mc5_write(adap, IDT4_GMR_BASE1 + 1, IDT4_CMD_WRITE) ||
    269	    mc5_write(adap, IDT4_GMR_BASE1 + 4, IDT4_CMD_WRITE))
    270		goto err;
    271
    272	dbgi_wr_data3(adap, 0xfffffff9, 0xffff8007, 0xff);
    273	if (mc5_write(adap, IDT4_GMR_BASE1 + 5, IDT4_CMD_WRITE))
    274		goto err;
    275
    276	/* Set up SCR */
    277	dbgi_wr_data3(adap, 0xf0000000, 0, 0);
    278	if (mc5_write(adap, IDT4_SCR_ADR0, IDT4_CMD_WRITE))
    279		goto err;
    280
    281	return init_mask_data_array(mc5, IDT4_MSKARY_BASE_ADR0,
    282				    IDT4_DATARY_BASE_ADR0, IDT4_CMD_WRITE, 1);
    283err:
    284	return -EIO;
    285}
    286
    287/* Put MC5 in DBGI mode. */
    288static inline void mc5_dbgi_mode_enable(const struct mc5 *mc5)
    289{
    290	t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
    291		     V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_DBGIEN);
    292}
    293
    294/* Put MC5 in M-Bus mode. */
    295static void mc5_dbgi_mode_disable(const struct mc5 *mc5)
    296{
    297	t3_write_reg(mc5->adapter, A_MC5_DB_CONFIG,
    298		     V_TMMODE(mc5->mode == MC5_MODE_72_BIT) |
    299		     V_COMPEN(mc5->mode == MC5_MODE_72_BIT) |
    300		     V_PRTYEN(mc5->parity_enabled) | F_MBUSEN);
    301}
    302
    303/*
    304 * Initialization that requires the OS and protocol layers to already
    305 * be initialized goes here.
    306 */
    307int t3_mc5_init(struct mc5 *mc5, unsigned int nservers, unsigned int nfilters,
    308		unsigned int nroutes)
    309{
    310	u32 cfg;
    311	int err;
    312	unsigned int tcam_size = mc5->tcam_size;
    313	struct adapter *adap = mc5->adapter;
    314
    315	if (!tcam_size)
    316		return 0;
    317
    318	if (nroutes > MAX_ROUTES || nroutes + nservers + nfilters > tcam_size)
    319		return -EINVAL;
    320
    321	/* Reset the TCAM */
    322	cfg = t3_read_reg(adap, A_MC5_DB_CONFIG) & ~F_TMMODE;
    323	cfg |= V_TMMODE(mc5->mode == MC5_MODE_72_BIT) | F_TMRST;
    324	t3_write_reg(adap, A_MC5_DB_CONFIG, cfg);
    325	if (t3_wait_op_done(adap, A_MC5_DB_CONFIG, F_TMRDY, 1, 500, 0)) {
    326		CH_ERR(adap, "TCAM reset timed out\n");
    327		return -1;
    328	}
    329
    330	t3_write_reg(adap, A_MC5_DB_ROUTING_TABLE_INDEX, tcam_size - nroutes);
    331	t3_write_reg(adap, A_MC5_DB_FILTER_TABLE,
    332		     tcam_size - nroutes - nfilters);
    333	t3_write_reg(adap, A_MC5_DB_SERVER_INDEX,
    334		     tcam_size - nroutes - nfilters - nservers);
    335
    336	mc5->parity_enabled = 1;
    337
    338	/* All the TCAM addresses we access have only the low 32 bits non 0 */
    339	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR1, 0);
    340	t3_write_reg(adap, A_MC5_DB_DBGI_REQ_ADDR2, 0);
    341
    342	mc5_dbgi_mode_enable(mc5);
    343
    344	switch (mc5->part_type) {
    345	case IDT75P52100:
    346		err = init_idt52100(mc5);
    347		break;
    348	case IDT75N43102:
    349		err = init_idt43102(mc5);
    350		break;
    351	default:
    352		CH_ERR(adap, "Unsupported TCAM type %d\n", mc5->part_type);
    353		err = -EINVAL;
    354		break;
    355	}
    356
    357	mc5_dbgi_mode_disable(mc5);
    358	return err;
    359}
    360
    361
    362#define MC5_INT_FATAL (F_PARITYERR | F_REQQPARERR | F_DISPQPARERR)
    363
    364/*
    365 * MC5 interrupt handler
    366 */
    367void t3_mc5_intr_handler(struct mc5 *mc5)
    368{
    369	struct adapter *adap = mc5->adapter;
    370	u32 cause = t3_read_reg(adap, A_MC5_DB_INT_CAUSE);
    371
    372	if ((cause & F_PARITYERR) && mc5->parity_enabled) {
    373		CH_ALERT(adap, "MC5 parity error\n");
    374		mc5->stats.parity_err++;
    375	}
    376
    377	if (cause & F_REQQPARERR) {
    378		CH_ALERT(adap, "MC5 request queue parity error\n");
    379		mc5->stats.reqq_parity_err++;
    380	}
    381
    382	if (cause & F_DISPQPARERR) {
    383		CH_ALERT(adap, "MC5 dispatch queue parity error\n");
    384		mc5->stats.dispq_parity_err++;
    385	}
    386
    387	if (cause & F_ACTRGNFULL)
    388		mc5->stats.active_rgn_full++;
    389	if (cause & F_NFASRCHFAIL)
    390		mc5->stats.nfa_srch_err++;
    391	if (cause & F_UNKNOWNCMD)
    392		mc5->stats.unknown_cmd++;
    393	if (cause & F_DELACTEMPTY)
    394		mc5->stats.del_act_empty++;
    395	if (cause & MC5_INT_FATAL)
    396		t3_fatal_err(adap);
    397
    398	t3_write_reg(adap, A_MC5_DB_INT_CAUSE, cause);
    399}
    400
    401void t3_mc5_prep(struct adapter *adapter, struct mc5 *mc5, int mode)
    402{
    403#define K * 1024
    404
    405	static unsigned int tcam_part_size[] = {	/* in K 72-bit entries */
    406		64 K, 128 K, 256 K, 32 K
    407	};
    408
    409#undef K
    410
    411	u32 cfg = t3_read_reg(adapter, A_MC5_DB_CONFIG);
    412
    413	mc5->adapter = adapter;
    414	mc5->mode = (unsigned char)mode;
    415	mc5->part_type = (unsigned char)G_TMTYPE(cfg);
    416	if (cfg & F_TMTYPEHI)
    417		mc5->part_type |= 4;
    418
    419	mc5->tcam_size = tcam_part_size[G_TMPARTSIZE(cfg)];
    420	if (mode == MC5_MODE_144_BIT)
    421		mc5->tcam_size /= 2;
    422}