Exemplo n.º 1
0
static void fm10k_get_reg_vsi(struct fm10k_hw *hw, u32 *buff, int i)
{
	int idx = 0, j;

	buff[idx++] = fm10k_read_reg(hw, FM10K_MRQC(i));
	for (j = 0; j < 10; j++)
		buff[idx++] = fm10k_read_reg(hw, FM10K_RSSRK(i, j));
	for (j = 0; j < 32; j++)
		buff[idx++] = fm10k_read_reg(hw, FM10K_RETA(i, j));

	BUG_ON(idx != FM10K_REGS_LEN_VSI);
}
Exemplo n.º 2
0
/**
 *  fm10k_disable_queues_generic - Stop Tx/Rx queues
 *  @hw: pointer to hardware structure
 *  @q_cnt: number of queues to be disabled
 *
 **/
s32 fm10k_disable_queues_generic(struct fm10k_hw *hw, u16 q_cnt)
{
	u32 reg;
	u16 i, time;

	/* clear tx_ready to prevent any false hits for reset */
	hw->mac.tx_ready = false;

	if (FM10K_REMOVED(hw->hw_addr))
		return 0;

	/* clear the enable bit for all rings */
	for (i = 0; i < q_cnt; i++) {
		reg = fm10k_read_reg(hw, FM10K_TXDCTL(i));
		fm10k_write_reg(hw, FM10K_TXDCTL(i),
				reg & ~FM10K_TXDCTL_ENABLE);
		reg = fm10k_read_reg(hw, FM10K_RXQCTL(i));
		fm10k_write_reg(hw, FM10K_RXQCTL(i),
				reg & ~FM10K_RXQCTL_ENABLE);
	}

	fm10k_write_flush(hw);
	udelay(1);

	/* loop through all queues to verify that they are all disabled */
	for (i = 0, time = FM10K_QUEUE_DISABLE_TIMEOUT; time;) {
		/* if we are at end of rings all rings are disabled */
		if (i == q_cnt)
			return 0;

		/* if queue enables cleared, then move to next ring pair */
		reg = fm10k_read_reg(hw, FM10K_TXDCTL(i));
		if (!~reg || !(reg & FM10K_TXDCTL_ENABLE)) {
			reg = fm10k_read_reg(hw, FM10K_RXQCTL(i));
			if (!~reg || !(reg & FM10K_RXQCTL_ENABLE)) {
				i++;
				continue;
			}
		}

		/* decrement time and wait 1 usec */
		time--;
		if (time)
			udelay(1);
	}

	return FM10K_ERR_REQUESTS_PENDING;
}
Exemplo n.º 3
0
/**
 *  fm10k_update_hw_stats_rx_q - Updates RX queue statistics counters
 *  @hw: pointer to the hardware structure
 *  @q: pointer to the ring of hardware statistics queue
 *  @idx: index pointing to the start of the ring iteration
 *
 *  Function updates the RX queue statistics counters that are related to the
 *  hardware.
 **/
static void fm10k_update_hw_stats_rx_q(struct fm10k_hw *hw,
				       struct fm10k_hw_stats_q *q,
				       u32 idx)
{
	u32 id_rx, id_rx_prev, rx_packets, rx_drops;
	u64 rx_bytes = 0;

	/* Retrieve RX Owner Data */
	id_rx = fm10k_read_reg(hw, FM10K_RXQCTL(idx));

	/* Process RX Ring */
	do {
		rx_drops = fm10k_read_hw_stats_32b(hw, FM10K_QPRDC(idx),
						   &q->rx_drops);

		rx_packets = fm10k_read_hw_stats_32b(hw, FM10K_QPRC(idx),
						     &q->rx_packets);

		if (rx_packets)
			rx_bytes = fm10k_read_hw_stats_48b(hw,
							   FM10K_QBRC_L(idx),
							   &q->rx_bytes);

		/* Re-Check Owner Data */
		id_rx_prev = id_rx;
		id_rx = fm10k_read_reg(hw, FM10K_RXQCTL(idx));
	} while ((id_rx ^ id_rx_prev) & FM10K_RXQCTL_ID_MASK);

	/* drop non-ID bits and set VALID ID bit */
	id_rx &= FM10K_RXQCTL_ID_MASK;
	id_rx |= FM10K_STAT_VALID;

	/* update packet counts */
	if (q->rx_stats_idx == id_rx) {
		q->rx_drops.count += rx_drops;
		q->rx_packets.count += rx_packets;
		q->rx_bytes.count += rx_bytes;
	}

	/* update bases and record ID */
	fm10k_update_hw_base_32b(&q->rx_drops, rx_drops);
	fm10k_update_hw_base_32b(&q->rx_packets, rx_packets);
	fm10k_update_hw_base_48b(&q->rx_bytes, rx_bytes);

	q->rx_stats_idx = id_rx;
}
Exemplo n.º 4
0
/**
 *  fm10k_read_hw_stats_32b - Reads value of 32-bit registers
 *  @hw: pointer to the hardware structure
 *  @addr: address of register containing a 32-bit value
 *  @stat: pointer to structure holding hw stat information
 *
 *  Function reads the content of the register and returns the delta
 *  between the base and the current value.
 *  **/
u32 fm10k_read_hw_stats_32b(struct fm10k_hw *hw, u32 addr,
			    struct fm10k_hw_stat *stat)
{
	u32 delta = fm10k_read_reg(hw, addr) - stat->base_l;

	if (FM10K_REMOVED(hw->hw_addr))
		stat->base_h = 0;

	return delta;
}
Exemplo n.º 5
0
/**
 *  fm10k_update_hw_stats_tx_q - Updates TX queue statistics counters
 *  @hw: pointer to the hardware structure
 *  @q: pointer to the ring of hardware statistics queue
 *  @idx: index pointing to the start of the ring iteration
 *
 *  Function updates the TX queue statistics counters that are related to the
 *  hardware.
 **/
static void fm10k_update_hw_stats_tx_q(struct fm10k_hw *hw,
				       struct fm10k_hw_stats_q *q,
				       u32 idx)
{
	u32 id_tx, id_tx_prev, tx_packets;
	u64 tx_bytes = 0;

	/* Retrieve TX Owner Data */
	id_tx = fm10k_read_reg(hw, FM10K_TXQCTL(idx));

	/* Process TX Ring */
	do {
		tx_packets = fm10k_read_hw_stats_32b(hw, FM10K_QPTC(idx),
						     &q->tx_packets);

		if (tx_packets)
			tx_bytes = fm10k_read_hw_stats_48b(hw,
							   FM10K_QBTC_L(idx),
							   &q->tx_bytes);

		/* Re-Check Owner Data */
		id_tx_prev = id_tx;
		id_tx = fm10k_read_reg(hw, FM10K_TXQCTL(idx));
	} while ((id_tx ^ id_tx_prev) & FM10K_TXQCTL_ID_MASK);

	/* drop non-ID bits and set VALID ID bit */
	id_tx &= FM10K_TXQCTL_ID_MASK;
	id_tx |= FM10K_STAT_VALID;

	/* update packet counts */
	if (q->tx_stats_idx == id_tx) {
		q->tx_packets.count += tx_packets;
		q->tx_bytes.count += tx_bytes;
	}

	/* update bases and record ID */
	fm10k_update_hw_base_32b(&q->tx_packets, tx_packets);
	fm10k_update_hw_base_48b(&q->tx_bytes, tx_bytes);

	q->tx_stats_idx = id_tx;
}
Exemplo n.º 6
0
/**
 *  fm10k_read_hw_stats_48b - Reads value of 48-bit registers
 *  @hw: pointer to the hardware structure
 *  @addr: address of register containing the lower 32-bit value
 *  @stat: pointer to structure holding hw stat information
 *
 *  Function reads the content of 2 registers, combined to represent a 48-bit
 *  statistical value. Extra processing is required to handle overflowing.
 *  Finally, a delta value is returned representing the difference between the
 *  values stored in registers and values stored in the statistic counters.
 *  **/
static u64 fm10k_read_hw_stats_48b(struct fm10k_hw *hw, u32 addr,
				   struct fm10k_hw_stat *stat)
{
	u32 count_l;
	u32 count_h;
	u32 count_tmp;
	u64 delta;

	count_h = fm10k_read_reg(hw, addr + 1);

	/* Check for overflow */
	do {
		count_tmp = count_h;
		count_l = fm10k_read_reg(hw, addr);
		count_h = fm10k_read_reg(hw, addr + 1);
	} while (count_h != count_tmp);

	delta = ((u64)(count_h - stat->base_h) << 32) + count_l;
	delta -= stat->base_l;

	return delta & FM10K_48_BIT_MASK;
}
Exemplo n.º 7
0
/**
 *  fm10k_get_host_state_generic - Returns the state of the host
 *  @hw: pointer to hardware structure
 *  @host_ready: pointer to boolean value that will record host state
 *
 *  This function will check the health of the mailbox and Tx queue 0
 *  in order to determine if we should report that the link is up or not.
 **/
s32 fm10k_get_host_state_generic(struct fm10k_hw *hw, bool *host_ready)
{
	struct fm10k_mbx_info *mbx = &hw->mbx;
	struct fm10k_mac_info *mac = &hw->mac;
	s32 ret_val = 0;
	u32 txdctl = fm10k_read_reg(hw, FM10K_TXDCTL(0));

	/* process upstream mailbox in case interrupts were disabled */
	mbx->ops.process(hw, mbx);

	/* If Tx is no longer enabled link should come down */
	if (!(~txdctl) || !(txdctl & FM10K_TXDCTL_ENABLE))
		mac->get_host_state = true;

	/* exit if not checking for link, or link cannot be changed */
	if (!mac->get_host_state || !(~txdctl))
		goto out;

	/* if we somehow dropped the Tx enable we should reset */
	if (mac->tx_ready && !(txdctl & FM10K_TXDCTL_ENABLE)) {
		ret_val = FM10K_ERR_RESET_REQUESTED;
		goto out;
	}

	/* if Mailbox timed out we should request reset */
	if (!mbx->timeout) {
		ret_val = FM10K_ERR_RESET_REQUESTED;
		goto out;
	}

	/* verify Mailbox is still open */
	if (mbx->state != FM10K_STATE_OPEN)
		goto out;

	/* interface cannot receive traffic without logical ports */
	if (mac->dglort_map == FM10K_DGLORTMAP_NONE) {
		if (mac->ops.request_lport_map)
			ret_val = mac->ops.request_lport_map(hw);

		goto out;
	}

	/* if we passed all the tests above then the switch is ready and we no
	 * longer need to check for link
	 */
	mac->get_host_state = false;

out:
	*host_ready = !mac->get_host_state;
	return ret_val;
}
Exemplo n.º 8
0
static void fm10k_get_regs(struct net_device *netdev,
			   struct ethtool_regs *regs, void *p)
{
	struct fm10k_intfc *interface = netdev_priv(netdev);
	struct fm10k_hw *hw = &interface->hw;
	u32 *buff = p;
	u16 i;

	regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id;

	switch (hw->mac.type) {
	case fm10k_mac_pf:
		/* General PF Registers */
		*(buff++) = fm10k_read_reg(hw, FM10K_CTRL);
		*(buff++) = fm10k_read_reg(hw, FM10K_CTRL_EXT);
		*(buff++) = fm10k_read_reg(hw, FM10K_GCR);
		*(buff++) = fm10k_read_reg(hw, FM10K_GCR_EXT);

		for (i = 0; i < 8; i++) {
			*(buff++) = fm10k_read_reg(hw, FM10K_DGLORTMAP(i));
			*(buff++) = fm10k_read_reg(hw, FM10K_DGLORTDEC(i));
		}

		for (i = 0; i < 65; i++) {
			fm10k_get_reg_vsi(hw, buff, i);
			buff += FM10K_REGS_LEN_VSI;
		}

		*(buff++) = fm10k_read_reg(hw, FM10K_DMA_CTRL);
		*(buff++) = fm10k_read_reg(hw, FM10K_DMA_CTRL2);

		for (i = 0; i < FM10K_MAX_QUEUES_PF; i++) {
			fm10k_get_reg_q(hw, buff, i);
			buff += FM10K_REGS_LEN_Q;
		}

		*(buff++) = fm10k_read_reg(hw, FM10K_TPH_CTRL);

		for (i = 0; i < 8; i++)
			*(buff++) = fm10k_read_reg(hw, FM10K_INT_MAP(i));

		/* Interrupt Throttling Registers */
		for (i = 0; i < 130; i++)
			*(buff++) = fm10k_read_reg(hw, FM10K_ITR(i));

		break;
	case fm10k_mac_vf:
		/* General VF registers */
		*(buff++) = fm10k_read_reg(hw, FM10K_VFCTRL);
		*(buff++) = fm10k_read_reg(hw, FM10K_VFINT_MAP);
		*(buff++) = fm10k_read_reg(hw, FM10K_VFSYSTIME);

		/* Interrupt Throttling Registers */
		for (i = 0; i < 8; i++)
			*(buff++) = fm10k_read_reg(hw, FM10K_VFITR(i));

		fm10k_get_reg_vsi(hw, buff, 0);
		buff += FM10K_REGS_LEN_VSI;

		for (i = 0; i < FM10K_MAX_QUEUES_POOL; i++) {
			if (i < hw->mac.max_queues)
				fm10k_get_reg_q(hw, buff, i);
			else
				memset(buff, 0, sizeof(u32) * FM10K_REGS_LEN_Q);
			buff += FM10K_REGS_LEN_Q;
		}

		break;
	default:
		return;
	}
}
Exemplo n.º 9
0
static void fm10k_get_reg_q(struct fm10k_hw *hw, u32 *buff, int i)
{
	int idx = 0;

	buff[idx++] = fm10k_read_reg(hw, FM10K_RDBAL(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_RDBAH(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_RDLEN(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TPH_RXCTRL(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_RDH(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_RDT(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_RXQCTL(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_RXDCTL(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_RXINT(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_SRRCTL(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_QPRC(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_QPRDC(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_QBRC_L(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_QBRC_H(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TDBAL(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TDBAH(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TDLEN(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TPH_TXCTRL(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TDH(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TDT(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TXDCTL(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TXQCTL(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TXINT(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_QPTC(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_QBTC_L(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_QBTC_H(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TQDLOC(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_TX_SGLORT(i));
	buff[idx++] = fm10k_read_reg(hw, FM10K_PFVTCTL(i));

	BUG_ON(idx != FM10K_REGS_LEN_Q);
}