Skip to content

Commit

Permalink
tg3: Add support code around kernel interrupt API
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Matt Carlson authored and David S. Miller committed Sep 2, 2009
1 parent 2d31eca commit 4f125f4
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 18 deletions.
73 changes: 55 additions & 18 deletions drivers/net/tg3.c
Original file line number Diff line number Diff line change
Expand Up @@ -4729,12 +4729,15 @@ static int tg3_poll(struct napi_struct *napi, int budget)

static void tg3_irq_quiesce(struct tg3 *tp)
{
int i;

BUG_ON(tp->irq_sync);

tp->irq_sync = 1;
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)
Expand Down Expand Up @@ -4947,9 +4950,11 @@ static int tg3_restart_hw(struct tg3 *tp, int reset_phy)
#ifdef CONFIG_NET_POLL_CONTROLLER
static void tg3_poll_controller(struct net_device *dev)
{
int i;
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

Expand Down Expand Up @@ -6244,7 +6249,7 @@ static int tg3_chip_reset(struct tg3 *tp)
{
u32 val;
void (*write_op)(struct tg3 *, u32, u32);
int err;
int i, err;

tg3_nvram_lock(tp);

Expand Down Expand Up @@ -6291,7 +6296,9 @@ static int tg3_chip_reset(struct tg3 *tp)
tp->napi[0].last_tag = 0;
tp->napi[0].last_irq_tag = 0;
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) {
val = tr32(TG3_PCIE_LNKCTL) & ~TG3_PCIE_LNKCTL_L1_PLL_PD_EN;
Expand Down Expand Up @@ -7745,11 +7752,20 @@ static void tg3_timer(unsigned long __opaque)
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;
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) {
fn = tg3_msi;
Expand All @@ -7762,7 +7778,8 @@ static int tg3_request_irq(struct tg3 *tp)
fn = tg3_interrupt_tagged;
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)
Expand All @@ -7776,9 +7793,9 @@ static int tg3_test_interrupt(struct tg3 *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);
if (err)
return err;
Expand Down Expand Up @@ -7806,9 +7823,9 @@ static int tg3_test_interrupt(struct tg3 *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)
return err;
Expand Down Expand Up @@ -7854,13 +7871,13 @@ static int tg3_test_msi(struct tg3 *tp)
"the PCI maintainer and include system chipset information.\n",
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);

tp->tg3_flags2 &= ~TG3_FLG2_USING_MSI;

err = tg3_request_irq(tp);
err = tg3_request_irq(tp, 0);
if (err)
return err;

Expand All @@ -7875,7 +7892,7 @@ static int tg3_test_msi(struct tg3 *tp)
tg3_full_unlock(tp);

if (err)
free_irq(tp->pdev->irq, &tp->napi[0]);
free_irq(tp->napi[0].irq_vec, &tp->napi[0]);

return err;
}
Expand Down Expand Up @@ -7928,6 +7945,9 @@ static void tg3_ints_init(struct tg3 *tp)
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)
Expand All @@ -7941,7 +7961,7 @@ static void tg3_ints_fini(struct tg3 *tp)
static int tg3_open(struct net_device *dev)
{
struct tg3 *tp = netdev_priv(dev);
int err;
int i, err;

if (tp->fw_needed) {
err = tg3_request_firmware(tp);
Expand Down Expand Up @@ -7983,7 +8003,15 @@ static int tg3_open(struct net_device *dev)

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)
goto err_out1;
Expand Down Expand Up @@ -8054,7 +8082,10 @@ static int tg3_open(struct net_device *dev)
return 0;

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:
napi_disable(&tp->napi[0].napi);
Expand Down Expand Up @@ -8298,6 +8329,7 @@ static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *);

static int tg3_close(struct net_device *dev)
{
int i;
struct tg3 *tp = netdev_priv(dev);

napi_disable(&tp->napi[0].napi);
Expand All @@ -8320,7 +8352,10 @@ static int tg3_close(struct net_device *dev)

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);

Expand Down Expand Up @@ -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) ||
(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))
tp->tg3_flags |= TG3_FLAG_JUMBO_CAPABLE;
Expand Down
6 changes: 6 additions & 0 deletions drivers/net/tg3.h
Original file line number Diff line number Diff line change
Expand Up @@ -2514,6 +2514,9 @@ struct tg3_napi {
dma_addr_t status_mapping;
dma_addr_t rx_rcb_mapping;
dma_addr_t tx_desc_mapping;

char irq_lbl[IFNAMSIZ];
unsigned int irq_vec;
};

struct tg3 {
Expand Down Expand Up @@ -2829,6 +2832,9 @@ struct tg3 {

#define SST_25VF0X0_PAGE_SIZE 4098

unsigned int irq_max;
unsigned int irq_cnt;

struct ethtool_coalesce coal;

/* firmware info */
Expand Down

0 comments on commit 4f125f4

Please sign in to comment.