mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
net: stmmac: introduce MSI Interrupt routines for mac, safety, RX & TX
Now we introduce MSI interrupt service routines and hook these routines up if stmmac_open() sees valid irq line being requested:- stmmac_mac_interrupt() :- MAC (dev->irq), WOL (wol_irq), LPI (lpi_irq) stmmac_safety_interrupt() :- Safety Feat Correctible Error (sfty_ce_irq) & Uncorrectible Error (sfty_ue_irq) stmmac_msi_intr_rx() :- For all RX MSI irq (rx_irq) stmmac_msi_intr_tx() :- For all TX MSI irq (tx_irq) Each of IRQs will have its unique name so that we can differentiate them easily under /proc/interrupts. Signed-off-by: Ong Boon Leong <boon.leong.ong@intel.com> Signed-off-by: Voon Weifeng <weifeng.voon@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
29e6573c61
commit
8532f613bc
4 changed files with 431 additions and 45 deletions
|
@ -259,6 +259,9 @@ struct stmmac_safety_stats {
|
|||
#define DMA_HW_FEAT_ACTPHYIF 0x70000000 /* Active/selected PHY iface */
|
||||
#define DEFAULT_DMA_PBL 8
|
||||
|
||||
/* MSI defines */
|
||||
#define STMMAC_MSI_VEC_MAX 32
|
||||
|
||||
/* PCS status and mask defines */
|
||||
#define PCS_ANE_IRQ BIT(2) /* PCS Auto-Negotiation */
|
||||
#define PCS_LINK_IRQ BIT(1) /* PCS Link */
|
||||
|
@ -315,6 +318,18 @@ enum dma_irq_dir {
|
|||
DMA_DIR_RXTX = 0x3,
|
||||
};
|
||||
|
||||
enum request_irq_err {
|
||||
REQ_IRQ_ERR_ALL,
|
||||
REQ_IRQ_ERR_TX,
|
||||
REQ_IRQ_ERR_RX,
|
||||
REQ_IRQ_ERR_SFTY_UE,
|
||||
REQ_IRQ_ERR_SFTY_CE,
|
||||
REQ_IRQ_ERR_LPI,
|
||||
REQ_IRQ_ERR_WOL,
|
||||
REQ_IRQ_ERR_MAC,
|
||||
REQ_IRQ_ERR_NO,
|
||||
};
|
||||
|
||||
/* EEE and LPI defines */
|
||||
#define CORE_IRQ_TX_PATH_IN_LPI_MODE (1 << 0)
|
||||
#define CORE_IRQ_TX_PATH_EXIT_LPI_MODE (1 << 1)
|
||||
|
|
|
@ -30,6 +30,10 @@ struct stmmac_resources {
|
|||
int wol_irq;
|
||||
int lpi_irq;
|
||||
int irq;
|
||||
int sfty_ce_irq;
|
||||
int sfty_ue_irq;
|
||||
int rx_irq[MTL_MAX_RX_QUEUES];
|
||||
int tx_irq[MTL_MAX_TX_QUEUES];
|
||||
};
|
||||
|
||||
struct stmmac_tx_info {
|
||||
|
@ -225,6 +229,18 @@ struct stmmac_priv {
|
|||
void __iomem *mmcaddr;
|
||||
void __iomem *ptpaddr;
|
||||
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
|
||||
int sfty_ce_irq;
|
||||
int sfty_ue_irq;
|
||||
int rx_irq[MTL_MAX_RX_QUEUES];
|
||||
int tx_irq[MTL_MAX_TX_QUEUES];
|
||||
/*irq name */
|
||||
char int_name_mac[IFNAMSIZ + 9];
|
||||
char int_name_wol[IFNAMSIZ + 9];
|
||||
char int_name_lpi[IFNAMSIZ + 9];
|
||||
char int_name_sfty_ce[IFNAMSIZ + 10];
|
||||
char int_name_sfty_ue[IFNAMSIZ + 10];
|
||||
char int_name_rx_irq[MTL_MAX_TX_QUEUES][IFNAMSIZ + 14];
|
||||
char int_name_tx_irq[MTL_MAX_TX_QUEUES][IFNAMSIZ + 18];
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct dentry *dbgfs_dir;
|
||||
|
|
|
@ -105,6 +105,11 @@ module_param(chain_mode, int, 0444);
|
|||
MODULE_PARM_DESC(chain_mode, "To use chain instead of ring mode");
|
||||
|
||||
static irqreturn_t stmmac_interrupt(int irq, void *dev_id);
|
||||
/* For MSI interrupts handling */
|
||||
static irqreturn_t stmmac_mac_interrupt(int irq, void *dev_id);
|
||||
static irqreturn_t stmmac_safety_interrupt(int irq, void *dev_id);
|
||||
static irqreturn_t stmmac_msi_intr_tx(int irq, void *data);
|
||||
static irqreturn_t stmmac_msi_intr_rx(int irq, void *data);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static const struct net_device_ops stmmac_netdev_ops;
|
||||
|
@ -2986,6 +2991,260 @@ static void stmmac_hw_teardown(struct net_device *dev)
|
|||
clk_disable_unprepare(priv->plat->clk_ptp_ref);
|
||||
}
|
||||
|
||||
static void stmmac_free_irq(struct net_device *dev,
|
||||
enum request_irq_err irq_err, int irq_idx)
|
||||
{
|
||||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
int j;
|
||||
|
||||
switch (irq_err) {
|
||||
case REQ_IRQ_ERR_ALL:
|
||||
irq_idx = priv->plat->tx_queues_to_use;
|
||||
fallthrough;
|
||||
case REQ_IRQ_ERR_TX:
|
||||
for (j = irq_idx - 1; j >= 0; j--) {
|
||||
if (priv->tx_irq[j] > 0)
|
||||
free_irq(priv->tx_irq[j], &priv->tx_queue[j]);
|
||||
}
|
||||
irq_idx = priv->plat->rx_queues_to_use;
|
||||
fallthrough;
|
||||
case REQ_IRQ_ERR_RX:
|
||||
for (j = irq_idx - 1; j >= 0; j--) {
|
||||
if (priv->rx_irq[j] > 0)
|
||||
free_irq(priv->rx_irq[j], &priv->rx_queue[j]);
|
||||
}
|
||||
|
||||
if (priv->sfty_ue_irq > 0 && priv->sfty_ue_irq != dev->irq)
|
||||
free_irq(priv->sfty_ue_irq, dev);
|
||||
fallthrough;
|
||||
case REQ_IRQ_ERR_SFTY_UE:
|
||||
if (priv->sfty_ce_irq > 0 && priv->sfty_ce_irq != dev->irq)
|
||||
free_irq(priv->sfty_ce_irq, dev);
|
||||
fallthrough;
|
||||
case REQ_IRQ_ERR_SFTY_CE:
|
||||
if (priv->lpi_irq > 0 && priv->lpi_irq != dev->irq)
|
||||
free_irq(priv->lpi_irq, dev);
|
||||
fallthrough;
|
||||
case REQ_IRQ_ERR_LPI:
|
||||
if (priv->wol_irq > 0 && priv->wol_irq != dev->irq)
|
||||
free_irq(priv->wol_irq, dev);
|
||||
fallthrough;
|
||||
case REQ_IRQ_ERR_WOL:
|
||||
free_irq(dev->irq, dev);
|
||||
fallthrough;
|
||||
case REQ_IRQ_ERR_MAC:
|
||||
case REQ_IRQ_ERR_NO:
|
||||
/* If MAC IRQ request error, no more IRQ to free */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int stmmac_request_irq_multi_msi(struct net_device *dev)
|
||||
{
|
||||
enum request_irq_err irq_err = REQ_IRQ_ERR_NO;
|
||||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
int irq_idx = 0;
|
||||
char *int_name;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* For common interrupt */
|
||||
int_name = priv->int_name_mac;
|
||||
sprintf(int_name, "%s:%s", dev->name, "mac");
|
||||
ret = request_irq(dev->irq, stmmac_mac_interrupt,
|
||||
0, int_name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: alloc mac MSI %d (error: %d)\n",
|
||||
__func__, dev->irq, ret);
|
||||
irq_err = REQ_IRQ_ERR_MAC;
|
||||
goto irq_error;
|
||||
}
|
||||
|
||||
/* Request the Wake IRQ in case of another line
|
||||
* is used for WoL
|
||||
*/
|
||||
if (priv->wol_irq > 0 && priv->wol_irq != dev->irq) {
|
||||
int_name = priv->int_name_wol;
|
||||
sprintf(int_name, "%s:%s", dev->name, "wol");
|
||||
ret = request_irq(priv->wol_irq,
|
||||
stmmac_mac_interrupt,
|
||||
0, int_name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: alloc wol MSI %d (error: %d)\n",
|
||||
__func__, priv->wol_irq, ret);
|
||||
irq_err = REQ_IRQ_ERR_WOL;
|
||||
goto irq_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request the LPI IRQ in case of another line
|
||||
* is used for LPI
|
||||
*/
|
||||
if (priv->lpi_irq > 0 && priv->lpi_irq != dev->irq) {
|
||||
int_name = priv->int_name_lpi;
|
||||
sprintf(int_name, "%s:%s", dev->name, "lpi");
|
||||
ret = request_irq(priv->lpi_irq,
|
||||
stmmac_mac_interrupt,
|
||||
0, int_name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: alloc lpi MSI %d (error: %d)\n",
|
||||
__func__, priv->lpi_irq, ret);
|
||||
irq_err = REQ_IRQ_ERR_LPI;
|
||||
goto irq_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request the Safety Feature Correctible Error line in
|
||||
* case of another line is used
|
||||
*/
|
||||
if (priv->sfty_ce_irq > 0 && priv->sfty_ce_irq != dev->irq) {
|
||||
int_name = priv->int_name_sfty_ce;
|
||||
sprintf(int_name, "%s:%s", dev->name, "safety-ce");
|
||||
ret = request_irq(priv->sfty_ce_irq,
|
||||
stmmac_safety_interrupt,
|
||||
0, int_name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: alloc sfty ce MSI %d (error: %d)\n",
|
||||
__func__, priv->sfty_ce_irq, ret);
|
||||
irq_err = REQ_IRQ_ERR_SFTY_CE;
|
||||
goto irq_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request the Safety Feature Uncorrectible Error line in
|
||||
* case of another line is used
|
||||
*/
|
||||
if (priv->sfty_ue_irq > 0 && priv->sfty_ue_irq != dev->irq) {
|
||||
int_name = priv->int_name_sfty_ue;
|
||||
sprintf(int_name, "%s:%s", dev->name, "safety-ue");
|
||||
ret = request_irq(priv->sfty_ue_irq,
|
||||
stmmac_safety_interrupt,
|
||||
0, int_name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: alloc sfty ue MSI %d (error: %d)\n",
|
||||
__func__, priv->sfty_ue_irq, ret);
|
||||
irq_err = REQ_IRQ_ERR_SFTY_UE;
|
||||
goto irq_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request Rx MSI irq */
|
||||
for (i = 0; i < priv->plat->rx_queues_to_use; i++) {
|
||||
if (priv->rx_irq[i] == 0)
|
||||
continue;
|
||||
|
||||
int_name = priv->int_name_rx_irq[i];
|
||||
sprintf(int_name, "%s:%s-%d", dev->name, "rx", i);
|
||||
ret = request_irq(priv->rx_irq[i],
|
||||
stmmac_msi_intr_rx,
|
||||
0, int_name, &priv->rx_queue[i]);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: alloc rx-%d MSI %d (error: %d)\n",
|
||||
__func__, i, priv->rx_irq[i], ret);
|
||||
irq_err = REQ_IRQ_ERR_RX;
|
||||
irq_idx = i;
|
||||
goto irq_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request Tx MSI irq */
|
||||
for (i = 0; i < priv->plat->tx_queues_to_use; i++) {
|
||||
if (priv->tx_irq[i] == 0)
|
||||
continue;
|
||||
|
||||
int_name = priv->int_name_tx_irq[i];
|
||||
sprintf(int_name, "%s:%s-%d", dev->name, "tx", i);
|
||||
ret = request_irq(priv->tx_irq[i],
|
||||
stmmac_msi_intr_tx,
|
||||
0, int_name, &priv->tx_queue[i]);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: alloc tx-%d MSI %d (error: %d)\n",
|
||||
__func__, i, priv->tx_irq[i], ret);
|
||||
irq_err = REQ_IRQ_ERR_TX;
|
||||
irq_idx = i;
|
||||
goto irq_error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
irq_error:
|
||||
stmmac_free_irq(dev, irq_err, irq_idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stmmac_request_irq_single(struct net_device *dev)
|
||||
{
|
||||
enum request_irq_err irq_err = REQ_IRQ_ERR_NO;
|
||||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
ret = request_irq(dev->irq, stmmac_interrupt,
|
||||
IRQF_SHARED, dev->name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: ERROR: allocating the IRQ %d (error: %d)\n",
|
||||
__func__, dev->irq, ret);
|
||||
irq_err = REQ_IRQ_ERR_MAC;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Request the Wake IRQ in case of another line
|
||||
* is used for WoL
|
||||
*/
|
||||
if (priv->wol_irq > 0 && priv->wol_irq != dev->irq) {
|
||||
ret = request_irq(priv->wol_irq, stmmac_interrupt,
|
||||
IRQF_SHARED, dev->name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: ERROR: allocating the WoL IRQ %d (%d)\n",
|
||||
__func__, priv->wol_irq, ret);
|
||||
irq_err = REQ_IRQ_ERR_WOL;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request the IRQ lines */
|
||||
if (priv->lpi_irq > 0 && priv->lpi_irq != dev->irq) {
|
||||
ret = request_irq(priv->lpi_irq, stmmac_interrupt,
|
||||
IRQF_SHARED, dev->name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: ERROR: allocating the LPI IRQ %d (%d)\n",
|
||||
__func__, priv->lpi_irq, ret);
|
||||
irq_err = REQ_IRQ_ERR_LPI;
|
||||
goto irq_error;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
irq_error:
|
||||
stmmac_free_irq(dev, irq_err, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stmmac_request_irq(struct net_device *dev)
|
||||
{
|
||||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
/* Request the IRQ lines */
|
||||
if (priv->plat->multi_msi_en)
|
||||
ret = stmmac_request_irq_multi_msi(dev);
|
||||
else
|
||||
ret = stmmac_request_irq_single(dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_open - open entry point of the driver
|
||||
* @dev : pointer to the device structure.
|
||||
|
@ -3077,50 +3336,15 @@ static int stmmac_open(struct net_device *dev)
|
|||
/* We may have called phylink_speed_down before */
|
||||
phylink_speed_up(priv->phylink);
|
||||
|
||||
/* Request the IRQ lines */
|
||||
ret = request_irq(dev->irq, stmmac_interrupt,
|
||||
IRQF_SHARED, dev->name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: ERROR: allocating the IRQ %d (error: %d)\n",
|
||||
__func__, dev->irq, ret);
|
||||
ret = stmmac_request_irq(dev);
|
||||
if (ret)
|
||||
goto irq_error;
|
||||
}
|
||||
|
||||
/* Request the Wake IRQ in case of another line is used for WoL */
|
||||
if (priv->wol_irq != dev->irq) {
|
||||
ret = request_irq(priv->wol_irq, stmmac_interrupt,
|
||||
IRQF_SHARED, dev->name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: ERROR: allocating the WoL IRQ %d (%d)\n",
|
||||
__func__, priv->wol_irq, ret);
|
||||
goto wolirq_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Request the IRQ lines */
|
||||
if (priv->lpi_irq > 0) {
|
||||
ret = request_irq(priv->lpi_irq, stmmac_interrupt, IRQF_SHARED,
|
||||
dev->name, dev);
|
||||
if (unlikely(ret < 0)) {
|
||||
netdev_err(priv->dev,
|
||||
"%s: ERROR: allocating the LPI IRQ %d (%d)\n",
|
||||
__func__, priv->lpi_irq, ret);
|
||||
goto lpiirq_error;
|
||||
}
|
||||
}
|
||||
|
||||
stmmac_enable_all_queues(priv);
|
||||
netif_tx_start_all_queues(priv->dev);
|
||||
|
||||
return 0;
|
||||
|
||||
lpiirq_error:
|
||||
if (priv->wol_irq != dev->irq)
|
||||
free_irq(priv->wol_irq, dev);
|
||||
wolirq_error:
|
||||
free_irq(dev->irq, dev);
|
||||
irq_error:
|
||||
phylink_stop(priv->phylink);
|
||||
|
||||
|
@ -3170,11 +3394,7 @@ static int stmmac_release(struct net_device *dev)
|
|||
hrtimer_cancel(&priv->tx_queue[chan].txtimer);
|
||||
|
||||
/* Free the IRQ lines */
|
||||
free_irq(dev->irq, dev);
|
||||
if (priv->wol_irq != dev->irq)
|
||||
free_irq(priv->wol_irq, dev);
|
||||
if (priv->lpi_irq > 0)
|
||||
free_irq(priv->lpi_irq, dev);
|
||||
stmmac_free_irq(dev, REQ_IRQ_ERR_ALL, 0);
|
||||
|
||||
if (priv->eee_enabled) {
|
||||
priv->tx_path_in_lpi_mode = false;
|
||||
|
@ -4477,15 +4697,136 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
|
|||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stmmac_mac_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)dev_id;
|
||||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
|
||||
if (unlikely(!dev)) {
|
||||
netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* Check if adapter is up */
|
||||
if (test_bit(STMMAC_DOWN, &priv->state))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/* To handle Common interrupts */
|
||||
stmmac_common_interrupt(priv);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stmmac_safety_interrupt(int irq, void *dev_id)
|
||||
{
|
||||
struct net_device *dev = (struct net_device *)dev_id;
|
||||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
|
||||
if (unlikely(!dev)) {
|
||||
netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* Check if adapter is up */
|
||||
if (test_bit(STMMAC_DOWN, &priv->state))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
/* Check if a fatal error happened */
|
||||
stmmac_safety_feat_interrupt(priv);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stmmac_msi_intr_tx(int irq, void *data)
|
||||
{
|
||||
struct stmmac_tx_queue *tx_q = (struct stmmac_tx_queue *)data;
|
||||
int chan = tx_q->queue_index;
|
||||
struct stmmac_priv *priv;
|
||||
int status;
|
||||
|
||||
priv = container_of(tx_q, struct stmmac_priv, tx_queue[chan]);
|
||||
|
||||
if (unlikely(!data)) {
|
||||
netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* Check if adapter is up */
|
||||
if (test_bit(STMMAC_DOWN, &priv->state))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
status = stmmac_napi_check(priv, chan, DMA_DIR_TX);
|
||||
|
||||
if (unlikely(status & tx_hard_error_bump_tc)) {
|
||||
/* Try to bump up the dma threshold on this failure */
|
||||
if (unlikely(priv->xstats.threshold != SF_DMA_MODE) &&
|
||||
tc <= 256) {
|
||||
tc += 64;
|
||||
if (priv->plat->force_thresh_dma_mode)
|
||||
stmmac_set_dma_operation_mode(priv,
|
||||
tc,
|
||||
tc,
|
||||
chan);
|
||||
else
|
||||
stmmac_set_dma_operation_mode(priv,
|
||||
tc,
|
||||
SF_DMA_MODE,
|
||||
chan);
|
||||
priv->xstats.threshold = tc;
|
||||
}
|
||||
} else if (unlikely(status == tx_hard_error)) {
|
||||
stmmac_tx_err(priv, chan);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t stmmac_msi_intr_rx(int irq, void *data)
|
||||
{
|
||||
struct stmmac_rx_queue *rx_q = (struct stmmac_rx_queue *)data;
|
||||
int chan = rx_q->queue_index;
|
||||
struct stmmac_priv *priv;
|
||||
|
||||
priv = container_of(rx_q, struct stmmac_priv, rx_queue[chan]);
|
||||
|
||||
if (unlikely(!data)) {
|
||||
netdev_err(priv->dev, "%s: invalid dev pointer\n", __func__);
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/* Check if adapter is up */
|
||||
if (test_bit(STMMAC_DOWN, &priv->state))
|
||||
return IRQ_HANDLED;
|
||||
|
||||
stmmac_napi_check(priv, chan, DMA_DIR_RX);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||
/* Polling receive - used by NETCONSOLE and other diagnostic tools
|
||||
* to allow network I/O with interrupts disabled.
|
||||
*/
|
||||
static void stmmac_poll_controller(struct net_device *dev)
|
||||
{
|
||||
disable_irq(dev->irq);
|
||||
stmmac_interrupt(dev->irq, dev);
|
||||
enable_irq(dev->irq);
|
||||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
int i;
|
||||
|
||||
/* If adapter is down, do nothing */
|
||||
if (test_bit(STMMAC_DOWN, &priv->state))
|
||||
return;
|
||||
|
||||
if (priv->plat->multi_msi_en) {
|
||||
for (i = 0; i < priv->plat->rx_queues_to_use; i++)
|
||||
stmmac_msi_intr_rx(0, &priv->rx_queue[i]);
|
||||
|
||||
for (i = 0; i < priv->plat->tx_queues_to_use; i++)
|
||||
stmmac_msi_intr_tx(0, &priv->tx_queue[i]);
|
||||
} else {
|
||||
disable_irq(dev->irq);
|
||||
stmmac_interrupt(dev->irq, dev);
|
||||
enable_irq(dev->irq);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -5283,6 +5624,12 @@ int stmmac_dvr_probe(struct device *device,
|
|||
priv->dev->irq = res->irq;
|
||||
priv->wol_irq = res->wol_irq;
|
||||
priv->lpi_irq = res->lpi_irq;
|
||||
priv->sfty_ce_irq = res->sfty_ce_irq;
|
||||
priv->sfty_ue_irq = res->sfty_ue_irq;
|
||||
for (i = 0; i < MTL_MAX_RX_QUEUES; i++)
|
||||
priv->rx_irq[i] = res->rx_irq[i];
|
||||
for (i = 0; i < MTL_MAX_TX_QUEUES; i++)
|
||||
priv->tx_irq[i] = res->tx_irq[i];
|
||||
|
||||
if (!IS_ERR_OR_NULL(res->mac))
|
||||
memcpy(priv->dev->dev_addr, res->mac, ETH_ALEN);
|
||||
|
|
|
@ -237,5 +237,13 @@ struct plat_stmmacenet_data {
|
|||
struct pci_dev *pdev;
|
||||
bool has_crossts;
|
||||
int int_snapshot_num;
|
||||
bool multi_msi_en;
|
||||
int msi_mac_vec;
|
||||
int msi_wol_vec;
|
||||
int msi_lpi_vec;
|
||||
int msi_sfty_ce_vec;
|
||||
int msi_sfty_ue_vec;
|
||||
int msi_rx_base_vec;
|
||||
int msi_tx_base_vec;
|
||||
};
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue