mirror of
https://github.com/adulau/aha.git
synced 2025-01-01 13:46:24 +00:00
tg3: Add support code around kernel interrupt API
This patch adds code to support multiple interrupt vectors around the kernel's interrupt API. Signed-off-by: Matt Carlson <mcarlson@broadcom.com> Reviewed-by: Benjamin Li <benli@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2d31ecaf10
commit
4f125f42dd
2 changed files with 61 additions and 18 deletions
|
@ -4729,12 +4729,15 @@ tx_recovery:
|
||||||
|
|
||||||
static void tg3_irq_quiesce(struct tg3 *tp)
|
static void tg3_irq_quiesce(struct tg3 *tp)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
BUG_ON(tp->irq_sync);
|
BUG_ON(tp->irq_sync);
|
||||||
|
|
||||||
tp->irq_sync = 1;
|
tp->irq_sync = 1;
|
||||||
smp_mb();
|
smp_mb();
|
||||||
|
|
||||||
synchronize_irq(tp->pdev->irq);
|
for (i = 0; i < tp->irq_cnt; i++)
|
||||||
|
synchronize_irq(tp->napi[i].irq_vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int tg3_irq_sync(struct tg3 *tp)
|
static inline int tg3_irq_sync(struct tg3 *tp)
|
||||||
|
@ -4947,9 +4950,11 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
|
||||||
#ifdef CONFIG_NET_POLL_CONTROLLER
|
#ifdef CONFIG_NET_POLL_CONTROLLER
|
||||||
static void tg3_poll_controller(struct net_device *dev)
|
static void tg3_poll_controller(struct net_device *dev)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
struct tg3 *tp = netdev_priv(dev);
|
struct tg3 *tp = netdev_priv(dev);
|
||||||
|
|
||||||
tg3_interrupt(tp->pdev->irq, dev);
|
for (i = 0; i < tp->irq_cnt; i++)
|
||||||
|
tg3_interrupt(tp->napi[i].irq_vec, dev);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -6244,7 +6249,7 @@ static int tg3_chip_reset(struct tg3 *tp)
|
||||||
{
|
{
|
||||||
u32 val;
|
u32 val;
|
||||||
void (*write_op)(struct tg3 *, u32, u32);
|
void (*write_op)(struct tg3 *, u32, u32);
|
||||||
int err;
|
int i, err;
|
||||||
|
|
||||||
tg3_nvram_lock(tp);
|
tg3_nvram_lock(tp);
|
||||||
|
|
||||||
|
@ -6291,7 +6296,9 @@ static int tg3_chip_reset(struct tg3 *tp)
|
||||||
tp->napi[0].last_tag = 0;
|
tp->napi[0].last_tag = 0;
|
||||||
tp->napi[0].last_irq_tag = 0;
|
tp->napi[0].last_irq_tag = 0;
|
||||||
smp_mb();
|
smp_mb();
|
||||||
synchronize_irq(tp->pdev->irq);
|
|
||||||
|
for (i = 0; i < tp->irq_cnt; i++)
|
||||||
|
synchronize_irq(tp->napi[i].irq_vec);
|
||||||
|
|
||||||
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
|
if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57780) {
|
||||||
val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
|
val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
|
||||||
|
@ -7745,11 +7752,20 @@ restart_timer:
|
||||||
add_timer(&tp->timer);
|
add_timer(&tp->timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tg3_request_irq(struct tg3 *tp)
|
static int tg3_request_irq(struct tg3 *tp, int irq_num)
|
||||||
{
|
{
|
||||||
irq_handler_t fn;
|
irq_handler_t fn;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
char *name = tp->dev->name;
|
char *name;
|
||||||
|
struct tg3_napi *tnapi = &tp->napi[irq_num];
|
||||||
|
|
||||||
|
if (tp->irq_cnt == 1)
|
||||||
|
name = tp->dev->name;
|
||||||
|
else {
|
||||||
|
name = &tnapi->irq_lbl[0];
|
||||||
|
snprintf(name, IFNAMSIZ, "%s-%d", tp->dev->name, irq_num);
|
||||||
|
name[IFNAMSIZ-1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
|
if (tp->tg3_flags2 & TG3_FLG2_USING_MSI) {
|
||||||
fn = tg3_msi;
|
fn = tg3_msi;
|
||||||
|
@ -7762,7 +7778,8 @@ static int tg3_request_irq(struct tg3 *tp)
|
||||||
fn = tg3_interrupt_tagged;
|
fn = tg3_interrupt_tagged;
|
||||||
flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
|
flags = IRQF_SHARED | IRQF_SAMPLE_RANDOM;
|
||||||
}
|
}
|
||||||
return request_irq(tp->pdev->irq, fn, flags, name, &tp->napi[0]);
|
|
||||||
|
return request_irq(tnapi->irq_vec, fn, flags, name, tnapi);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tg3_test_interrupt(struct tg3 *tp)
|
static int tg3_test_interrupt(struct tg3 *tp)
|
||||||
|
@ -7776,9 +7793,9 @@ static int tg3_test_interrupt(struct tg3 *tp)
|
||||||
|
|
||||||
tg3_disable_ints(tp);
|
tg3_disable_ints(tp);
|
||||||
|
|
||||||
free_irq(tp->pdev->irq, tnapi);
|
free_irq(tnapi->irq_vec, tnapi);
|
||||||
|
|
||||||
err = request_irq(tp->pdev->irq, tg3_test_isr,
|
err = request_irq(tnapi->irq_vec, tg3_test_isr,
|
||||||
IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
|
IRQF_SHARED | IRQF_SAMPLE_RANDOM, dev->name, tnapi);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -7806,9 +7823,9 @@ static int tg3_test_interrupt(struct tg3 *tp)
|
||||||
|
|
||||||
tg3_disable_ints(tp);
|
tg3_disable_ints(tp);
|
||||||
|
|
||||||
free_irq(tp->pdev->irq, tnapi);
|
free_irq(tnapi->irq_vec, tnapi);
|
||||||
|
|
||||||
err = tg3_request_irq(tp);
|
err = tg3_request_irq(tp, 0);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
@ -7854,13 +7871,13 @@ static int tg3_test_msi(struct tg3 *tp)
|
||||||
"the PCI maintainer and include system chipset information.\n",
|
"the PCI maintainer and include system chipset information.\n",
|
||||||
tp->dev->name);
|
tp->dev->name);
|
||||||
|
|
||||||
free_irq(tp->pdev->irq, &tp->napi[0]);
|
free_irq(tp->napi[0].irq_vec, &tp->napi[0]);
|
||||||
|
|
||||||
pci_disable_msi(tp->pdev);
|
pci_disable_msi(tp->pdev);
|
||||||
|
|
||||||
tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
|
tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;
|
||||||
|
|
||||||
err = tg3_request_irq(tp);
|
err = tg3_request_irq(tp, 0);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
@ -7875,7 +7892,7 @@ static int tg3_test_msi(struct tg3 *tp)
|
||||||
tg3_full_unlock(tp);
|
tg3_full_unlock(tp);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
free_irq(tp->pdev->irq, &tp->napi[0]);
|
free_irq(tp->napi[0].irq_vec, &tp->napi[0]);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -7928,6 +7945,9 @@ static void tg3_ints_init(struct tg3 *tp)
|
||||||
tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
|
tp->tg3_flags2 |= TG3_FLG2_USING_MSI;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tp->irq_cnt = 1;
|
||||||
|
tp->napi[0].irq_vec = tp->pdev->irq;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tg3_ints_fini(struct tg3 *tp)
|
static void tg3_ints_fini(struct tg3 *tp)
|
||||||
|
@ -7941,7 +7961,7 @@ static void tg3_ints_fini(struct tg3 *tp)
|
||||||
static int tg3_open(struct net_device *dev)
|
static int tg3_open(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct tg3 *tp = netdev_priv(dev);
|
struct tg3 *tp = netdev_priv(dev);
|
||||||
int err;
|
int i, err;
|
||||||
|
|
||||||
if (tp->fw_needed) {
|
if (tp->fw_needed) {
|
||||||
err = tg3_request_firmware(tp);
|
err = tg3_request_firmware(tp);
|
||||||
|
@ -7983,7 +8003,15 @@ static int tg3_open(struct net_device *dev)
|
||||||
|
|
||||||
napi_enable(&tp->napi[0].napi);
|
napi_enable(&tp->napi[0].napi);
|
||||||
|
|
||||||
err = tg3_request_irq(tp);
|
for (i = 0; i < tp->irq_cnt; i++) {
|
||||||
|
struct tg3_napi *tnapi = &tp->napi[i];
|
||||||
|
err = tg3_request_irq(tp, i);
|
||||||
|
if (err) {
|
||||||
|
for (i--; i >= 0; i--)
|
||||||
|
free_irq(tnapi->irq_vec, tnapi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
goto err_out1;
|
goto err_out1;
|
||||||
|
@ -8054,7 +8082,10 @@ static int tg3_open(struct net_device *dev)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err_out2:
|
err_out2:
|
||||||
free_irq(tp->pdev->irq, &tp->napi[0]);
|
for (i = tp->irq_cnt - 1; i >= 0; i--) {
|
||||||
|
struct tg3_napi *tnapi = &tp->napi[i];
|
||||||
|
free_irq(tnapi->irq_vec, tnapi);
|
||||||
|
}
|
||||||
|
|
||||||
err_out1:
|
err_out1:
|
||||||
napi_disable(&tp->napi[0].napi);
|
napi_disable(&tp->napi[0].napi);
|
||||||
|
@ -8298,6 +8329,7 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *);
|
||||||
|
|
||||||
static int tg3_close(struct net_device *dev)
|
static int tg3_close(struct net_device *dev)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
struct tg3 *tp = netdev_priv(dev);
|
struct tg3 *tp = netdev_priv(dev);
|
||||||
|
|
||||||
napi_disable(&tp->napi[0].napi);
|
napi_disable(&tp->napi[0].napi);
|
||||||
|
@ -8320,7 +8352,10 @@ static int tg3_close(struct net_device *dev)
|
||||||
|
|
||||||
tg3_full_unlock(tp);
|
tg3_full_unlock(tp);
|
||||||
|
|
||||||
free_irq(tp->pdev->irq, &tp->napi[0]);
|
for (i = tp->irq_cnt - 1; i >= 0; i--) {
|
||||||
|
struct tg3_napi *tnapi = &tp->napi[i];
|
||||||
|
free_irq(tnapi->irq_vec, tnapi);
|
||||||
|
}
|
||||||
|
|
||||||
tg3_ints_fini(tp);
|
tg3_ints_fini(tp);
|
||||||
|
|
||||||
|
@ -12151,6 +12186,8 @@ static int __devinit tg3_get_invariants(struct tg3 *tp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tp->irq_max = 1;
|
||||||
|
|
||||||
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
|
if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
|
||||||
(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
|
(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
|
||||||
tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE;
|
tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE;
|
||||||
|
|
|
@ -2514,6 +2514,9 @@ struct tg3_napi {
|
||||||
dma_addr_t status_mapping;
|
dma_addr_t status_mapping;
|
||||||
dma_addr_t rx_rcb_mapping;
|
dma_addr_t rx_rcb_mapping;
|
||||||
dma_addr_t tx_desc_mapping;
|
dma_addr_t tx_desc_mapping;
|
||||||
|
|
||||||
|
char irq_lbl[IFNAMSIZ];
|
||||||
|
unsigned int irq_vec;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tg3 {
|
struct tg3 {
|
||||||
|
@ -2829,6 +2832,9 @@ struct tg3 {
|
||||||
|
|
||||||
#define SST_25VF0X0_PAGE_SIZE 4098
|
#define SST_25VF0X0_PAGE_SIZE 4098
|
||||||
|
|
||||||
|
unsigned int irq_max;
|
||||||
|
unsigned int irq_cnt;
|
||||||
|
|
||||||
struct ethtool_coalesce coal;
|
struct ethtool_coalesce coal;
|
||||||
|
|
||||||
/* firmware info */
|
/* firmware info */
|
||||||
|
|
Loading…
Reference in a new issue