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

fm10k_common.c (14348B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Copyright(c) 2013 - 2018 Intel Corporation. */
      3
      4#include "fm10k_common.h"
      5
      6/**
      7 *  fm10k_get_bus_info_generic - Generic set PCI bus info
      8 *  @hw: pointer to hardware structure
      9 *
     10 *  Gets the PCI bus info (speed, width, type) then calls helper function to
     11 *  store this data within the fm10k_hw structure.
     12 **/
     13s32 fm10k_get_bus_info_generic(struct fm10k_hw *hw)
     14{
     15	u16 link_cap, link_status, device_cap, device_control;
     16
     17	/* Get the maximum link width and speed from PCIe config space */
     18	link_cap = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_LINK_CAP);
     19
     20	switch (link_cap & FM10K_PCIE_LINK_WIDTH) {
     21	case FM10K_PCIE_LINK_WIDTH_1:
     22		hw->bus_caps.width = fm10k_bus_width_pcie_x1;
     23		break;
     24	case FM10K_PCIE_LINK_WIDTH_2:
     25		hw->bus_caps.width = fm10k_bus_width_pcie_x2;
     26		break;
     27	case FM10K_PCIE_LINK_WIDTH_4:
     28		hw->bus_caps.width = fm10k_bus_width_pcie_x4;
     29		break;
     30	case FM10K_PCIE_LINK_WIDTH_8:
     31		hw->bus_caps.width = fm10k_bus_width_pcie_x8;
     32		break;
     33	default:
     34		hw->bus_caps.width = fm10k_bus_width_unknown;
     35		break;
     36	}
     37
     38	switch (link_cap & FM10K_PCIE_LINK_SPEED) {
     39	case FM10K_PCIE_LINK_SPEED_2500:
     40		hw->bus_caps.speed = fm10k_bus_speed_2500;
     41		break;
     42	case FM10K_PCIE_LINK_SPEED_5000:
     43		hw->bus_caps.speed = fm10k_bus_speed_5000;
     44		break;
     45	case FM10K_PCIE_LINK_SPEED_8000:
     46		hw->bus_caps.speed = fm10k_bus_speed_8000;
     47		break;
     48	default:
     49		hw->bus_caps.speed = fm10k_bus_speed_unknown;
     50		break;
     51	}
     52
     53	/* Get the PCIe maximum payload size for the PCIe function */
     54	device_cap = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_DEV_CAP);
     55
     56	switch (device_cap & FM10K_PCIE_DEV_CAP_PAYLOAD) {
     57	case FM10K_PCIE_DEV_CAP_PAYLOAD_128:
     58		hw->bus_caps.payload = fm10k_bus_payload_128;
     59		break;
     60	case FM10K_PCIE_DEV_CAP_PAYLOAD_256:
     61		hw->bus_caps.payload = fm10k_bus_payload_256;
     62		break;
     63	case FM10K_PCIE_DEV_CAP_PAYLOAD_512:
     64		hw->bus_caps.payload = fm10k_bus_payload_512;
     65		break;
     66	default:
     67		hw->bus_caps.payload = fm10k_bus_payload_unknown;
     68		break;
     69	}
     70
     71	/* Get the negotiated link width and speed from PCIe config space */
     72	link_status = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_LINK_STATUS);
     73
     74	switch (link_status & FM10K_PCIE_LINK_WIDTH) {
     75	case FM10K_PCIE_LINK_WIDTH_1:
     76		hw->bus.width = fm10k_bus_width_pcie_x1;
     77		break;
     78	case FM10K_PCIE_LINK_WIDTH_2:
     79		hw->bus.width = fm10k_bus_width_pcie_x2;
     80		break;
     81	case FM10K_PCIE_LINK_WIDTH_4:
     82		hw->bus.width = fm10k_bus_width_pcie_x4;
     83		break;
     84	case FM10K_PCIE_LINK_WIDTH_8:
     85		hw->bus.width = fm10k_bus_width_pcie_x8;
     86		break;
     87	default:
     88		hw->bus.width = fm10k_bus_width_unknown;
     89		break;
     90	}
     91
     92	switch (link_status & FM10K_PCIE_LINK_SPEED) {
     93	case FM10K_PCIE_LINK_SPEED_2500:
     94		hw->bus.speed = fm10k_bus_speed_2500;
     95		break;
     96	case FM10K_PCIE_LINK_SPEED_5000:
     97		hw->bus.speed = fm10k_bus_speed_5000;
     98		break;
     99	case FM10K_PCIE_LINK_SPEED_8000:
    100		hw->bus.speed = fm10k_bus_speed_8000;
    101		break;
    102	default:
    103		hw->bus.speed = fm10k_bus_speed_unknown;
    104		break;
    105	}
    106
    107	/* Get the negotiated PCIe maximum payload size for the PCIe function */
    108	device_control = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_DEV_CTRL);
    109
    110	switch (device_control & FM10K_PCIE_DEV_CTRL_PAYLOAD) {
    111	case FM10K_PCIE_DEV_CTRL_PAYLOAD_128:
    112		hw->bus.payload = fm10k_bus_payload_128;
    113		break;
    114	case FM10K_PCIE_DEV_CTRL_PAYLOAD_256:
    115		hw->bus.payload = fm10k_bus_payload_256;
    116		break;
    117	case FM10K_PCIE_DEV_CTRL_PAYLOAD_512:
    118		hw->bus.payload = fm10k_bus_payload_512;
    119		break;
    120	default:
    121		hw->bus.payload = fm10k_bus_payload_unknown;
    122		break;
    123	}
    124
    125	return 0;
    126}
    127
    128static u16 fm10k_get_pcie_msix_count_generic(struct fm10k_hw *hw)
    129{
    130	u16 msix_count;
    131
    132	/* read in value from MSI-X capability register */
    133	msix_count = fm10k_read_pci_cfg_word(hw, FM10K_PCI_MSIX_MSG_CTRL);
    134	msix_count &= FM10K_PCI_MSIX_MSG_CTRL_TBL_SZ_MASK;
    135
    136	/* MSI-X count is zero-based in HW */
    137	msix_count++;
    138
    139	if (msix_count > FM10K_MAX_MSIX_VECTORS)
    140		msix_count = FM10K_MAX_MSIX_VECTORS;
    141
    142	return msix_count;
    143}
    144
    145/**
    146 *  fm10k_get_invariants_generic - Inits constant values
    147 *  @hw: pointer to the hardware structure
    148 *
    149 *  Initialize the common invariants for the device.
    150 **/
    151s32 fm10k_get_invariants_generic(struct fm10k_hw *hw)
    152{
    153	struct fm10k_mac_info *mac = &hw->mac;
    154
    155	/* initialize GLORT state to avoid any false hits */
    156	mac->dglort_map = FM10K_DGLORTMAP_NONE;
    157
    158	/* record maximum number of MSI-X vectors */
    159	mac->max_msix_vectors = fm10k_get_pcie_msix_count_generic(hw);
    160
    161	return 0;
    162}
    163
    164/**
    165 *  fm10k_start_hw_generic - Prepare hardware for Tx/Rx
    166 *  @hw: pointer to hardware structure
    167 *
    168 *  This function sets the Tx ready flag to indicate that the Tx path has
    169 *  been initialized.
    170 **/
    171s32 fm10k_start_hw_generic(struct fm10k_hw *hw)
    172{
    173	/* set flag indicating we are beginning Tx */
    174	hw->mac.tx_ready = true;
    175
    176	return 0;
    177}
    178
    179/**
    180 *  fm10k_disable_queues_generic - Stop Tx/Rx queues
    181 *  @hw: pointer to hardware structure
    182 *  @q_cnt: number of queues to be disabled
    183 *
    184 **/
    185s32 fm10k_disable_queues_generic(struct fm10k_hw *hw, u16 q_cnt)
    186{
    187	u32 reg;
    188	u16 i, time;
    189
    190	/* clear tx_ready to prevent any false hits for reset */
    191	hw->mac.tx_ready = false;
    192
    193	if (FM10K_REMOVED(hw->hw_addr))
    194		return 0;
    195
    196	/* clear the enable bit for all rings */
    197	for (i = 0; i < q_cnt; i++) {
    198		reg = fm10k_read_reg(hw, FM10K_TXDCTL(i));
    199		fm10k_write_reg(hw, FM10K_TXDCTL(i),
    200				reg & ~FM10K_TXDCTL_ENABLE);
    201		reg = fm10k_read_reg(hw, FM10K_RXQCTL(i));
    202		fm10k_write_reg(hw, FM10K_RXQCTL(i),
    203				reg & ~FM10K_RXQCTL_ENABLE);
    204	}
    205
    206	fm10k_write_flush(hw);
    207	udelay(1);
    208
    209	/* loop through all queues to verify that they are all disabled */
    210	for (i = 0, time = FM10K_QUEUE_DISABLE_TIMEOUT; time;) {
    211		/* if we are at end of rings all rings are disabled */
    212		if (i == q_cnt)
    213			return 0;
    214
    215		/* if queue enables cleared, then move to next ring pair */
    216		reg = fm10k_read_reg(hw, FM10K_TXDCTL(i));
    217		if (!~reg || !(reg & FM10K_TXDCTL_ENABLE)) {
    218			reg = fm10k_read_reg(hw, FM10K_RXQCTL(i));
    219			if (!~reg || !(reg & FM10K_RXQCTL_ENABLE)) {
    220				i++;
    221				continue;
    222			}
    223		}
    224
    225		/* decrement time and wait 1 usec */
    226		time--;
    227		if (time)
    228			udelay(1);
    229	}
    230
    231	return FM10K_ERR_REQUESTS_PENDING;
    232}
    233
    234/**
    235 *  fm10k_stop_hw_generic - Stop Tx/Rx units
    236 *  @hw: pointer to hardware structure
    237 *
    238 **/
    239s32 fm10k_stop_hw_generic(struct fm10k_hw *hw)
    240{
    241	return fm10k_disable_queues_generic(hw, hw->mac.max_queues);
    242}
    243
    244/**
    245 *  fm10k_read_hw_stats_32b - Reads value of 32-bit registers
    246 *  @hw: pointer to the hardware structure
    247 *  @addr: address of register containing a 32-bit value
    248 *  @stat: pointer to structure holding hw stat information
    249 *
    250 *  Function reads the content of the register and returns the delta
    251 *  between the base and the current value.
    252 *  **/
    253u32 fm10k_read_hw_stats_32b(struct fm10k_hw *hw, u32 addr,
    254			    struct fm10k_hw_stat *stat)
    255{
    256	u32 delta = fm10k_read_reg(hw, addr) - stat->base_l;
    257
    258	if (FM10K_REMOVED(hw->hw_addr))
    259		stat->base_h = 0;
    260
    261	return delta;
    262}
    263
    264/**
    265 *  fm10k_read_hw_stats_48b - Reads value of 48-bit registers
    266 *  @hw: pointer to the hardware structure
    267 *  @addr: address of register containing the lower 32-bit value
    268 *  @stat: pointer to structure holding hw stat information
    269 *
    270 *  Function reads the content of 2 registers, combined to represent a 48-bit
    271 *  statistical value. Extra processing is required to handle overflowing.
    272 *  Finally, a delta value is returned representing the difference between the
    273 *  values stored in registers and values stored in the statistic counters.
    274 *  **/
    275static u64 fm10k_read_hw_stats_48b(struct fm10k_hw *hw, u32 addr,
    276				   struct fm10k_hw_stat *stat)
    277{
    278	u32 count_l;
    279	u32 count_h;
    280	u32 count_tmp;
    281	u64 delta;
    282
    283	count_h = fm10k_read_reg(hw, addr + 1);
    284
    285	/* Check for overflow */
    286	do {
    287		count_tmp = count_h;
    288		count_l = fm10k_read_reg(hw, addr);
    289		count_h = fm10k_read_reg(hw, addr + 1);
    290	} while (count_h != count_tmp);
    291
    292	delta = ((u64)(count_h - stat->base_h) << 32) + count_l;
    293	delta -= stat->base_l;
    294
    295	return delta & FM10K_48_BIT_MASK;
    296}
    297
    298/**
    299 *  fm10k_update_hw_base_48b - Updates 48-bit statistic base value
    300 *  @stat: pointer to the hardware statistic structure
    301 *  @delta: value to be updated into the hardware statistic structure
    302 *
    303 *  Function receives a value and determines if an update is required based on
    304 *  a delta calculation. Only the base value will be updated.
    305 **/
    306static void fm10k_update_hw_base_48b(struct fm10k_hw_stat *stat, u64 delta)
    307{
    308	if (!delta)
    309		return;
    310
    311	/* update lower 32 bits */
    312	delta += stat->base_l;
    313	stat->base_l = (u32)delta;
    314
    315	/* update upper 32 bits */
    316	stat->base_h += (u32)(delta >> 32);
    317}
    318
    319/**
    320 *  fm10k_update_hw_stats_tx_q - Updates TX queue statistics counters
    321 *  @hw: pointer to the hardware structure
    322 *  @q: pointer to the ring of hardware statistics queue
    323 *  @idx: index pointing to the start of the ring iteration
    324 *
    325 *  Function updates the TX queue statistics counters that are related to the
    326 *  hardware.
    327 **/
    328static void fm10k_update_hw_stats_tx_q(struct fm10k_hw *hw,
    329				       struct fm10k_hw_stats_q *q,
    330				       u32 idx)
    331{
    332	u32 id_tx, id_tx_prev, tx_packets;
    333	u64 tx_bytes = 0;
    334
    335	/* Retrieve TX Owner Data */
    336	id_tx = fm10k_read_reg(hw, FM10K_TXQCTL(idx));
    337
    338	/* Process TX Ring */
    339	do {
    340		tx_packets = fm10k_read_hw_stats_32b(hw, FM10K_QPTC(idx),
    341						     &q->tx_packets);
    342
    343		if (tx_packets)
    344			tx_bytes = fm10k_read_hw_stats_48b(hw,
    345							   FM10K_QBTC_L(idx),
    346							   &q->tx_bytes);
    347
    348		/* Re-Check Owner Data */
    349		id_tx_prev = id_tx;
    350		id_tx = fm10k_read_reg(hw, FM10K_TXQCTL(idx));
    351	} while ((id_tx ^ id_tx_prev) & FM10K_TXQCTL_ID_MASK);
    352
    353	/* drop non-ID bits and set VALID ID bit */
    354	id_tx &= FM10K_TXQCTL_ID_MASK;
    355	id_tx |= FM10K_STAT_VALID;
    356
    357	/* update packet counts */
    358	if (q->tx_stats_idx == id_tx) {
    359		q->tx_packets.count += tx_packets;
    360		q->tx_bytes.count += tx_bytes;
    361	}
    362
    363	/* update bases and record ID */
    364	fm10k_update_hw_base_32b(&q->tx_packets, tx_packets);
    365	fm10k_update_hw_base_48b(&q->tx_bytes, tx_bytes);
    366
    367	q->tx_stats_idx = id_tx;
    368}
    369
    370/**
    371 *  fm10k_update_hw_stats_rx_q - Updates RX queue statistics counters
    372 *  @hw: pointer to the hardware structure
    373 *  @q: pointer to the ring of hardware statistics queue
    374 *  @idx: index pointing to the start of the ring iteration
    375 *
    376 *  Function updates the RX queue statistics counters that are related to the
    377 *  hardware.
    378 **/
    379static void fm10k_update_hw_stats_rx_q(struct fm10k_hw *hw,
    380				       struct fm10k_hw_stats_q *q,
    381				       u32 idx)
    382{
    383	u32 id_rx, id_rx_prev, rx_packets, rx_drops;
    384	u64 rx_bytes = 0;
    385
    386	/* Retrieve RX Owner Data */
    387	id_rx = fm10k_read_reg(hw, FM10K_RXQCTL(idx));
    388
    389	/* Process RX Ring */
    390	do {
    391		rx_drops = fm10k_read_hw_stats_32b(hw, FM10K_QPRDC(idx),
    392						   &q->rx_drops);
    393
    394		rx_packets = fm10k_read_hw_stats_32b(hw, FM10K_QPRC(idx),
    395						     &q->rx_packets);
    396
    397		if (rx_packets)
    398			rx_bytes = fm10k_read_hw_stats_48b(hw,
    399							   FM10K_QBRC_L(idx),
    400							   &q->rx_bytes);
    401
    402		/* Re-Check Owner Data */
    403		id_rx_prev = id_rx;
    404		id_rx = fm10k_read_reg(hw, FM10K_RXQCTL(idx));
    405	} while ((id_rx ^ id_rx_prev) & FM10K_RXQCTL_ID_MASK);
    406
    407	/* drop non-ID bits and set VALID ID bit */
    408	id_rx &= FM10K_RXQCTL_ID_MASK;
    409	id_rx |= FM10K_STAT_VALID;
    410
    411	/* update packet counts */
    412	if (q->rx_stats_idx == id_rx) {
    413		q->rx_drops.count += rx_drops;
    414		q->rx_packets.count += rx_packets;
    415		q->rx_bytes.count += rx_bytes;
    416	}
    417
    418	/* update bases and record ID */
    419	fm10k_update_hw_base_32b(&q->rx_drops, rx_drops);
    420	fm10k_update_hw_base_32b(&q->rx_packets, rx_packets);
    421	fm10k_update_hw_base_48b(&q->rx_bytes, rx_bytes);
    422
    423	q->rx_stats_idx = id_rx;
    424}
    425
    426/**
    427 *  fm10k_update_hw_stats_q - Updates queue statistics counters
    428 *  @hw: pointer to the hardware structure
    429 *  @q: pointer to the ring of hardware statistics queue
    430 *  @idx: index pointing to the start of the ring iteration
    431 *  @count: number of queues to iterate over
    432 *
    433 *  Function updates the queue statistics counters that are related to the
    434 *  hardware.
    435 **/
    436void fm10k_update_hw_stats_q(struct fm10k_hw *hw, struct fm10k_hw_stats_q *q,
    437			     u32 idx, u32 count)
    438{
    439	u32 i;
    440
    441	for (i = 0; i < count; i++, idx++, q++) {
    442		fm10k_update_hw_stats_tx_q(hw, q, idx);
    443		fm10k_update_hw_stats_rx_q(hw, q, idx);
    444	}
    445}
    446
    447/**
    448 *  fm10k_unbind_hw_stats_q - Unbind the queue counters from their queues
    449 *  @q: pointer to the ring of hardware statistics queue
    450 *  @idx: index pointing to the start of the ring iteration
    451 *  @count: number of queues to iterate over
    452 *
    453 *  Function invalidates the index values for the queues so any updates that
    454 *  may have happened are ignored and the base for the queue stats is reset.
    455 **/
    456void fm10k_unbind_hw_stats_q(struct fm10k_hw_stats_q *q, u32 idx, u32 count)
    457{
    458	u32 i;
    459
    460	for (i = 0; i < count; i++, idx++, q++) {
    461		q->rx_stats_idx = 0;
    462		q->tx_stats_idx = 0;
    463	}
    464}
    465
    466/**
    467 *  fm10k_get_host_state_generic - Returns the state of the host
    468 *  @hw: pointer to hardware structure
    469 *  @host_ready: pointer to boolean value that will record host state
    470 *
    471 *  This function will check the health of the mailbox and Tx queue 0
    472 *  in order to determine if we should report that the link is up or not.
    473 **/
    474s32 fm10k_get_host_state_generic(struct fm10k_hw *hw, bool *host_ready)
    475{
    476	struct fm10k_mbx_info *mbx = &hw->mbx;
    477	struct fm10k_mac_info *mac = &hw->mac;
    478	s32 ret_val = 0;
    479	u32 txdctl = fm10k_read_reg(hw, FM10K_TXDCTL(0));
    480
    481	/* process upstream mailbox in case interrupts were disabled */
    482	mbx->ops.process(hw, mbx);
    483
    484	/* If Tx is no longer enabled link should come down */
    485	if (!(~txdctl) || !(txdctl & FM10K_TXDCTL_ENABLE))
    486		mac->get_host_state = true;
    487
    488	/* exit if not checking for link, or link cannot be changed */
    489	if (!mac->get_host_state || !(~txdctl))
    490		goto out;
    491
    492	/* if we somehow dropped the Tx enable we should reset */
    493	if (mac->tx_ready && !(txdctl & FM10K_TXDCTL_ENABLE)) {
    494		ret_val = FM10K_ERR_RESET_REQUESTED;
    495		goto out;
    496	}
    497
    498	/* if Mailbox timed out we should request reset */
    499	if (!mbx->timeout) {
    500		ret_val = FM10K_ERR_RESET_REQUESTED;
    501		goto out;
    502	}
    503
    504	/* verify Mailbox is still open */
    505	if (mbx->state != FM10K_STATE_OPEN)
    506		goto out;
    507
    508	/* interface cannot receive traffic without logical ports */
    509	if (mac->dglort_map == FM10K_DGLORTMAP_NONE) {
    510		if (mac->ops.request_lport_map)
    511			ret_val = mac->ops.request_lport_map(hw);
    512
    513		goto out;
    514	}
    515
    516	/* if we passed all the tests above then the switch is ready and we no
    517	 * longer need to check for link
    518	 */
    519	mac->get_host_state = false;
    520
    521out:
    522	*host_ready = !mac->get_host_state;
    523	return ret_val;
    524}