Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f77a6a8e authored by Matt Carlson's avatar Matt Carlson Committed by David S. Miller
Browse files

tg3: Add tx and rx ring resource tracking



This patch adds code to assign status block, tx producer ring and rx
return ring resources needed for the other interrupt vectors.

Signed-off-by: default avatarMatt Carlson <mcarlson@broadcom.com>
Reviewed-by: default avatarBenjamin Li <benli@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 646c9edd
Loading
Loading
Loading
Loading
+158 −84
Original line number Diff line number Diff line
@@ -5722,8 +5722,10 @@ static int tg3_rx_prodring_init(struct tg3 *tp,
 */
static void tg3_free_rings(struct tg3 *tp)
{
	struct tg3_napi *tnapi = &tp->napi[0];
	int i;
	int i, j;

	for (j = 0; j < tp->irq_cnt; j++) {
		struct tg3_napi *tnapi = &tp->napi[j];

		for (i = 0; i < TG3_TX_RING_SIZE; ) {
			struct tx_ring_info *txp;
@@ -5745,6 +5747,7 @@ static void tg3_free_rings(struct tg3 *tp)

			dev_kfree_skb_any(skb);
		}
	}

	tg3_rx_prodring_free(tp, &tp->prodring[0]);
}
@@ -5758,16 +5761,27 @@ static void tg3_free_rings(struct tg3 *tp)
 */
static int tg3_init_rings(struct tg3 *tp)
{
	struct tg3_napi *tnapi = &tp->napi[0];
	int i;

	/* Free up all the SKBs. */
	tg3_free_rings(tp);

	/* Zero out all descriptors. */
	for (i = 0; i < tp->irq_cnt; i++) {
		struct tg3_napi *tnapi = &tp->napi[i];

		tnapi->last_tag = 0;
		tnapi->last_irq_tag = 0;
		tnapi->hw_status->status = 0;
		tnapi->hw_status->status_tag = 0;
		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);

		tnapi->tx_prod = 0;
		tnapi->tx_cons = 0;
		memset(tnapi->tx_ring, 0, TG3_TX_RING_BYTES);

		tnapi->rx_rcb_ptr = 0;
		memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
	}

	return tg3_rx_prodring_alloc(tp, &tp->prodring[0]);
}
@@ -5778,31 +5792,41 @@ static int tg3_init_rings(struct tg3 *tp)
 */
static void tg3_free_consistent(struct tg3 *tp)
{
	struct tg3_napi *tnapi = &tp->napi[0];
	int i;

	for (i = 0; i < tp->irq_cnt; i++) {
		struct tg3_napi *tnapi = &tp->napi[i];

	kfree(tnapi->tx_buffers);
	tnapi->tx_buffers = NULL;
		if (tnapi->tx_ring) {
			pci_free_consistent(tp->pdev, TG3_TX_RING_BYTES,
				tnapi->tx_ring, tnapi->tx_desc_mapping);
			tnapi->tx_ring = NULL;
		}

		kfree(tnapi->tx_buffers);
		tnapi->tx_buffers = NULL;

		if (tnapi->rx_rcb) {
			pci_free_consistent(tp->pdev, TG3_RX_RCB_RING_BYTES(tp),
				    tnapi->rx_rcb, tnapi->rx_rcb_mapping);
					    tnapi->rx_rcb,
					    tnapi->rx_rcb_mapping);
			tnapi->rx_rcb = NULL;
		}

		if (tnapi->hw_status) {
			pci_free_consistent(tp->pdev, TG3_HW_STATUS_SIZE,
					    tnapi->hw_status,
					    tnapi->status_mapping);
			tnapi->hw_status = NULL;
		}
	}

	if (tp->hw_stats) {
		pci_free_consistent(tp->pdev, sizeof(struct tg3_hw_stats),
				    tp->hw_stats, tp->stats_mapping);
		tp->hw_stats = NULL;
	}

	tg3_rx_prodring_fini(tp, &tp->prodring[0]);
}

@@ -5812,20 +5836,21 @@ static void tg3_free_consistent(struct tg3 *tp)
 */
static int tg3_alloc_consistent(struct tg3 *tp)
{
	struct tg3_napi *tnapi = &tp->napi[0];
	int i;

	if (tg3_rx_prodring_init(tp, &tp->prodring[0]))
		return -ENOMEM;

	tnapi->tx_buffers = kzalloc(sizeof(struct tx_ring_info) *
				    TG3_TX_RING_SIZE, GFP_KERNEL);
	if (!tnapi->tx_buffers)
	tp->hw_stats = pci_alloc_consistent(tp->pdev,
					    sizeof(struct tg3_hw_stats),
					    &tp->stats_mapping);
	if (!tp->hw_stats)
		goto err_out;

	tnapi->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
					      &tnapi->tx_desc_mapping);
	if (!tnapi->tx_ring)
		goto err_out;
	memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));

	for (i = 0; i < tp->irq_cnt; i++) {
		struct tg3_napi *tnapi = &tp->napi[i];

		tnapi->hw_status = pci_alloc_consistent(tp->pdev,
							TG3_HW_STATUS_SIZE,
@@ -5843,13 +5868,17 @@ static int tg3_alloc_consistent(struct tg3 *tp)

		memset(tnapi->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));

	tp->hw_stats = pci_alloc_consistent(tp->pdev,
					    sizeof(struct tg3_hw_stats),
					    &tp->stats_mapping);
	if (!tp->hw_stats)
		tnapi->tx_buffers = kzalloc(sizeof(struct tx_ring_info) *
					    TG3_TX_RING_SIZE, GFP_KERNEL);
		if (!tnapi->tx_buffers)
			goto err_out;

	memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));
		tnapi->tx_ring = pci_alloc_consistent(tp->pdev,
						      TG3_TX_RING_BYTES,
						      &tnapi->tx_desc_mapping);
		if (!tnapi->tx_ring)
			goto err_out;
	}

	return 0;

@@ -5910,7 +5939,6 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, int
static int tg3_abort_hw(struct tg3 *tp, int silent)
{
	int i, err;
	struct tg3_napi *tnapi = &tp->napi[0];

	tg3_disable_ints(tp);

@@ -5962,8 +5990,11 @@ static int tg3_abort_hw(struct tg3 *tp, int silent)
	err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE, silent);
	err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE, silent);

	for (i = 0; i < tp->irq_cnt; i++) {
		struct tg3_napi *tnapi = &tp->napi[i];
		if (tnapi->hw_status)
			memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);
	}
	if (tp->hw_stats)
		memset(tp->hw_stats, 0, sizeof(struct tg3_hw_stats));

@@ -6290,12 +6321,15 @@ static int tg3_chip_reset(struct tg3 *tp)
	 * sharing or irqpoll.
	 */
	tp->tg3_flags |= TG3_FLAG_CHIP_RESETTING;
	if (tp->napi[0].hw_status) {
		tp->napi[0].hw_status->status = 0;
		tp->napi[0].hw_status->status_tag = 0;
	for (i = 0; i < tp->irq_cnt; i++) {
		struct tg3_napi *tnapi = &tp->napi[i];
		if (tnapi->hw_status) {
			tnapi->hw_status->status = 0;
			tnapi->hw_status->status_tag = 0;
		}
		tnapi->last_tag = 0;
		tnapi->last_irq_tag = 0;
	}
	tp->napi[0].last_tag = 0;
	tp->napi[0].last_irq_tag = 0;
	smp_mb();

	for (i = 0; i < tp->irq_cnt; i++)
@@ -6829,7 +6863,7 @@ static void __tg3_set_coalesce(struct tg3 *tp, struct ethtool_coalesce *ec)
static void tg3_rings_reset(struct tg3 *tp)
{
	int i;
	u32 txrcb, rxrcb, limit;
	u32 stblk, txrcb, rxrcb, limit;
	struct tg3_napi *tnapi = &tp->napi[0];

	/* Disable all transmit rings but the first. */
@@ -6861,10 +6895,20 @@ static void tg3_rings_reset(struct tg3 *tp)
	tw32_mailbox_f(tp->napi[0].int_mbox, 1);

	/* Zero mailbox registers. */
	if (tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX) {
		for (i = 1; i < TG3_IRQ_MAX_VECS; i++) {
			tp->napi[i].tx_prod = 0;
			tp->napi[i].tx_cons = 0;
			tw32_mailbox(tp->napi[i].prodmbox, 0);
			tw32_rx_mbox(tp->napi[i].consmbox, 0);
			tw32_mailbox_f(tp->napi[i].int_mbox, 1);
		}
	} else {
		tp->napi[0].tx_prod = 0;
		tp->napi[0].tx_cons = 0;
		tw32_mailbox(tp->napi[0].prodmbox, 0);
		tw32_rx_mbox(tp->napi[0].consmbox, 0);
	}

	/* Make sure the NIC-based send BD rings are disabled. */
	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS)) {
@@ -6885,14 +6929,44 @@ static void tg3_rings_reset(struct tg3 *tp)
	tw32(HOSTCC_STATUS_BLK_HOST_ADDR + TG3_64BIT_REG_LOW,
	     ((u64) tnapi->status_mapping & 0xffffffff));

	if (tnapi->tx_ring) {
		tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
			       (TG3_TX_RING_SIZE <<
				BDINFO_FLAGS_MAXLEN_SHIFT),
			       NIC_SRAM_TX_BUFFER_DESC);
		txrcb += TG3_BDINFO_SIZE;
	}

	if (tnapi->rx_rcb) {
		tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
			       (TG3_RX_RCB_RING_SIZE(tp) <<
				BDINFO_FLAGS_MAXLEN_SHIFT), 0);
		rxrcb += TG3_BDINFO_SIZE;
	}

	stblk = HOSTCC_STATBLCK_RING1;

	for (i = 1, tnapi++; i < tp->irq_cnt; i++, tnapi++) {
		u64 mapping = (u64)tnapi->status_mapping;
		tw32(stblk + TG3_64BIT_REG_HIGH, mapping >> 32);
		tw32(stblk + TG3_64BIT_REG_LOW, mapping & 0xffffffff);

		/* Clear status block in ram. */
		memset(tnapi->hw_status, 0, TG3_HW_STATUS_SIZE);

		tg3_set_bdinfo(tp, txrcb, tnapi->tx_desc_mapping,
			       (TG3_TX_RING_SIZE <<
				BDINFO_FLAGS_MAXLEN_SHIFT),
			       NIC_SRAM_TX_BUFFER_DESC);

		tg3_set_bdinfo(tp, rxrcb, tnapi->rx_rcb_mapping,
			       (TG3_RX_RCB_RING_SIZE(tp) <<
				BDINFO_FLAGS_MAXLEN_SHIFT), 0);

		stblk += 8;
		txrcb += TG3_BDINFO_SIZE;
		rxrcb += TG3_BDINFO_SIZE;
	}
}

/* tp->lock is held. */
+2 −1
Original line number Diff line number Diff line
@@ -1117,7 +1117,8 @@
#define HOSTCC_SND_CON_IDX_13		0x00003cf4
#define HOSTCC_SND_CON_IDX_14		0x00003cf8
#define HOSTCC_SND_CON_IDX_15		0x00003cfc
/* 0x3d00 --> 0x4000 unused */
#define HOSTCC_STATBLCK_RING1		0x00003d00
/* 0x3d04 --> 0x4000 unused */

/* Memory arbiter control registers */
#define MEMARB_MODE			0x00004000