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

Commit bd0362dd authored by Jeb Cramer's avatar Jeb Cramer Committed by Jeff Garzik
Browse files

ixgbe: Add optional DCA infrastructure



82598 cards and up support DCA, which enables the chipset to warm
up the caches for upcoming payload data. This code makes the
driver plug into the CONFIG_DCA infrastructure that was merged
earlier.

Signed-off-by: default avatarJeb Cramer <cramerj@intel.com>
Signed-off-by: default avatarAuke Kok <auke-jan.h.kok@intel.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent f494e8fa
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,9 @@
#include "ixgbe_type.h"
#include "ixgbe_type.h"
#include "ixgbe_common.h"
#include "ixgbe_common.h"


#ifdef CONFIG_DCA
#include <linux/dca.h>
#endif


#define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args)
#define IXGBE_ERR(args...) printk(KERN_ERR "ixgbe: " args)


@@ -142,6 +145,11 @@ struct ixgbe_ring {
	u16 reg_idx; /* holds the special value that gets the hardware register
	u16 reg_idx; /* holds the special value that gets the hardware register
		      * offset associated with this ring, which is different
		      * offset associated with this ring, which is different
		      * for DCE and RSS modes */
		      * for DCE and RSS modes */

#ifdef CONFIG_DCA
	/* cpu for tx queue */
	int cpu;
#endif
	struct ixgbe_queue_stats stats;
	struct ixgbe_queue_stats stats;
	u8 v_idx; /* maps directly to the index for this ring in the hardware
	u8 v_idx; /* maps directly to the index for this ring in the hardware
		   * vector array, can also be used for finding the bit in EICR
		   * vector array, can also be used for finding the bit in EICR
@@ -261,6 +269,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG_IMIR_ENABLED                 (u32)(1 << 5)
#define IXGBE_FLAG_IMIR_ENABLED                 (u32)(1 << 5)
#define IXGBE_FLAG_RSS_ENABLED                  (u32)(1 << 6)
#define IXGBE_FLAG_RSS_ENABLED                  (u32)(1 << 6)
#define IXGBE_FLAG_VMDQ_ENABLED                 (u32)(1 << 7)
#define IXGBE_FLAG_VMDQ_ENABLED                 (u32)(1 << 7)
#define IXGBE_FLAG_DCA_ENABLED                  (u32)(1 << 8)


	/* OS defined structs */
	/* OS defined structs */
	struct net_device *netdev;
	struct net_device *netdev;
+148 −0
Original line number Original line Diff line number Diff line
@@ -80,6 +80,16 @@ static struct pci_device_id ixgbe_pci_tbl[] = {
};
};
MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);
MODULE_DEVICE_TABLE(pci, ixgbe_pci_tbl);


#ifdef CONFIG_DCA
static int ixgbe_notify_dca(struct notifier_block *, unsigned long event,
			    void *p);
static struct notifier_block dca_notifier = {
	.notifier_call = ixgbe_notify_dca,
	.next          = NULL,
	.priority      = 0
};
#endif

MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_AUTHOR("Intel Corporation, <linux.nics@intel.com>");
MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
MODULE_DESCRIPTION("Intel(R) 10 Gigabit PCI Express Network Driver");
MODULE_LICENSE("GPL");
MODULE_LICENSE("GPL");
@@ -290,6 +300,91 @@ static bool ixgbe_clean_tx_irq(struct ixgbe_adapter *adapter,
	return cleaned;
	return cleaned;
}
}


#ifdef CONFIG_DCA
static void ixgbe_update_rx_dca(struct ixgbe_adapter *adapter,
				struct ixgbe_ring *rxr)
{
	u32 rxctrl;
	int cpu = get_cpu();
	int q = rxr - adapter->rx_ring;

	if (rxr->cpu != cpu) {
		rxctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q));
		rxctrl &= ~IXGBE_DCA_RXCTRL_CPUID_MASK;
		rxctrl |= dca_get_tag(cpu);
		rxctrl |= IXGBE_DCA_RXCTRL_DESC_DCA_EN;
		rxctrl |= IXGBE_DCA_RXCTRL_HEAD_DCA_EN;
		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_RXCTRL(q), rxctrl);
		rxr->cpu = cpu;
	}
	put_cpu();
}

static void ixgbe_update_tx_dca(struct ixgbe_adapter *adapter,
				struct ixgbe_ring *txr)
{
	u32 txctrl;
	int cpu = get_cpu();
	int q = txr - adapter->tx_ring;

	if (txr->cpu != cpu) {
		txctrl = IXGBE_READ_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q));
		txctrl &= ~IXGBE_DCA_TXCTRL_CPUID_MASK;
		txctrl |= dca_get_tag(cpu);
		txctrl |= IXGBE_DCA_TXCTRL_DESC_DCA_EN;
		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_TXCTRL(q), txctrl);
		txr->cpu = cpu;
	}
	put_cpu();
}

static void ixgbe_setup_dca(struct ixgbe_adapter *adapter)
{
	int i;

	if (!(adapter->flags & IXGBE_FLAG_DCA_ENABLED))
		return;

	for (i = 0; i < adapter->num_tx_queues; i++) {
		adapter->tx_ring[i].cpu = -1;
		ixgbe_update_tx_dca(adapter, &adapter->tx_ring[i]);
	}
	for (i = 0; i < adapter->num_rx_queues; i++) {
		adapter->rx_ring[i].cpu = -1;
		ixgbe_update_rx_dca(adapter, &adapter->rx_ring[i]);
	}
}

static int __ixgbe_notify_dca(struct device *dev, void *data)
{
	struct net_device *netdev = dev_get_drvdata(dev);
	struct ixgbe_adapter *adapter = netdev_priv(netdev);
	unsigned long event = *(unsigned long *)data;

	switch (event) {
	case DCA_PROVIDER_ADD:
		adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
		/* Always use CB2 mode, difference is masked
		 * in the CB driver. */
		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 2);
		if (dca_add_requester(dev) == IXGBE_SUCCESS) {
			ixgbe_setup_dca(adapter);
			break;
		}
		/* Fall Through since DCA is disabled. */
	case DCA_PROVIDER_REMOVE:
		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
			dca_remove_requester(dev);
			adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
			IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
		}
		break;
	}

	return IXGBE_SUCCESS;
}

#endif /* CONFIG_DCA */
/**
/**
 * ixgbe_receive_skb - Send a completed packet up the stack
 * ixgbe_receive_skb - Send a completed packet up the stack
 * @adapter: board private structure
 * @adapter: board private structure
@@ -811,6 +906,10 @@ static irqreturn_t ixgbe_msix_clean_tx(int irq, void *data)
	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
	r_idx = find_first_bit(q_vector->txr_idx, adapter->num_tx_queues);
	for (i = 0; i < q_vector->txr_count; i++) {
	for (i = 0; i < q_vector->txr_count; i++) {
		txr = &(adapter->tx_ring[r_idx]);
		txr = &(adapter->tx_ring[r_idx]);
#ifdef CONFIG_DCA
		if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
			ixgbe_update_tx_dca(adapter, txr);
#endif
		txr->total_bytes = 0;
		txr->total_bytes = 0;
		txr->total_packets = 0;
		txr->total_packets = 0;
		ixgbe_clean_tx_irq(adapter, txr);
		ixgbe_clean_tx_irq(adapter, txr);
@@ -872,6 +971,10 @@ static int ixgbe_clean_rxonly(struct napi_struct *napi, int budget)


	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
	r_idx = find_first_bit(q_vector->rxr_idx, adapter->num_rx_queues);
	rxr = &(adapter->rx_ring[r_idx]);
	rxr = &(adapter->rx_ring[r_idx]);
#ifdef CONFIG_DCA
	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED)
		ixgbe_update_rx_dca(adapter, rxr);
#endif


	ixgbe_clean_rx_irq(adapter, rxr, &work_done, budget);
	ixgbe_clean_rx_irq(adapter, rxr, &work_done, budget);


@@ -1924,6 +2027,13 @@ static int ixgbe_poll(struct napi_struct *napi, int budget)
	struct ixgbe_adapter *adapter = q_vector->adapter;
	struct ixgbe_adapter *adapter = q_vector->adapter;
	int tx_cleaned = 0, work_done = 0;
	int tx_cleaned = 0, work_done = 0;


#ifdef CONFIG_DCA
	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
		ixgbe_update_tx_dca(adapter, adapter->tx_ring);
		ixgbe_update_rx_dca(adapter, adapter->rx_ring);
	}
#endif

	tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring);
	tx_cleaned = ixgbe_clean_tx_irq(adapter, adapter->tx_ring);
	ixgbe_clean_rx_irq(adapter, adapter->rx_ring, &work_done, budget);
	ixgbe_clean_rx_irq(adapter, adapter->rx_ring, &work_done, budget);


@@ -3494,6 +3604,15 @@ static int __devinit ixgbe_probe(struct pci_dev *pdev,
	if (err)
	if (err)
		goto err_register;
		goto err_register;


#ifdef CONFIG_DCA
	if (dca_add_requester(&pdev->dev) == IXGBE_SUCCESS) {
		adapter->flags |= IXGBE_FLAG_DCA_ENABLED;
		/* always use CB2 mode, difference is masked
		 * in the CB driver */
		IXGBE_WRITE_REG(hw, IXGBE_DCA_CTRL, 2);
		ixgbe_setup_dca(adapter);
	}
#endif


	dev_info(&pdev->dev, "Intel(R) 10 Gigabit Network Connection\n");
	dev_info(&pdev->dev, "Intel(R) 10 Gigabit Network Connection\n");
	cards_found++;
	cards_found++;
@@ -3535,6 +3654,14 @@ static void __devexit ixgbe_remove(struct pci_dev *pdev)


	flush_scheduled_work();
	flush_scheduled_work();


#ifdef CONFIG_DCA
	if (adapter->flags & IXGBE_FLAG_DCA_ENABLED) {
		adapter->flags &= ~IXGBE_FLAG_DCA_ENABLED;
		dca_remove_requester(&pdev->dev);
		IXGBE_WRITE_REG(&adapter->hw, IXGBE_DCA_CTRL, 1);
	}

#endif
	unregister_netdev(netdev);
	unregister_netdev(netdev);


	ixgbe_reset_interrupt_capability(adapter);
	ixgbe_reset_interrupt_capability(adapter);
@@ -3659,6 +3786,10 @@ static int __init ixgbe_init_module(void)


	printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright);
	printk(KERN_INFO "%s: %s\n", ixgbe_driver_name, ixgbe_copyright);


#ifdef CONFIG_DCA
	dca_register_notify(&dca_notifier);

#endif
	ret = pci_register_driver(&ixgbe_driver);
	ret = pci_register_driver(&ixgbe_driver);
	return ret;
	return ret;
}
}
@@ -3672,8 +3803,25 @@ module_init(ixgbe_init_module);
 **/
 **/
static void __exit ixgbe_exit_module(void)
static void __exit ixgbe_exit_module(void)
{
{
#ifdef CONFIG_DCA
	dca_unregister_notify(&dca_notifier);
#endif
	pci_unregister_driver(&ixgbe_driver);
	pci_unregister_driver(&ixgbe_driver);
}
}

#ifdef CONFIG_DCA
static int ixgbe_notify_dca(struct notifier_block *nb, unsigned long event,
			    void *p)
{
	int ret_val;

	ret_val = driver_for_each_device(&ixgbe_driver.driver, NULL, &event,
					 __ixgbe_notify_dca);

	return ret_val ? NOTIFY_BAD : NOTIFY_DONE;
}
#endif /* CONFIG_DCA */

module_exit(ixgbe_exit_module);
module_exit(ixgbe_exit_module);


/* ixgbe_main.c */
/* ixgbe_main.c */