diff options
author | Matt Carlson <mcarlson@broadcom.com> | 2009-11-13 08:03:41 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-11-16 01:14:45 -0500 |
commit | 35f2d7d0d7c222a580da0ed91c8d70c54267620a (patch) | |
tree | ffd6467756d992aeaf431aa732ba4c3fa553916f | |
parent | cbf9ca6cf8304beb640a948709c4672bc1d5a55f (diff) |
tg3: Create tg3_poll_msix() for non-zero MSIX vecs
This patch gives all non-zero MSIX vectors their own NAPI handler. This
will make NAPI handling for those vectors slightly more efficient.
Signed-off-by: Matt Carlson <mcarlson@broadcom.com>
Reviewed-by: Michael Chan <mchan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/tg3.c | 68 |
1 files changed, 60 insertions, 8 deletions
diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 1c1cf68baa94..5e17abb409e9 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c | |||
@@ -4706,18 +4706,17 @@ next_pkt_nopost: | |||
4706 | return received; | 4706 | return received; |
4707 | } | 4707 | } |
4708 | 4708 | ||
4709 | static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) | 4709 | static void tg3_poll_link(struct tg3 *tp) |
4710 | { | 4710 | { |
4711 | struct tg3 *tp = tnapi->tp; | ||
4712 | struct tg3_hw_status *sblk = tnapi->hw_status; | ||
4713 | |||
4714 | /* handle link change and other phy events */ | 4711 | /* handle link change and other phy events */ |
4715 | if (!(tp->tg3_flags & | 4712 | if (!(tp->tg3_flags & |
4716 | (TG3_FLAG_USE_LINKCHG_REG | | 4713 | (TG3_FLAG_USE_LINKCHG_REG | |
4717 | TG3_FLAG_POLL_SERDES))) { | 4714 | TG3_FLAG_POLL_SERDES))) { |
4715 | struct tg3_hw_status *sblk = tp->napi[0].hw_status; | ||
4716 | |||
4718 | if (sblk->status & SD_STATUS_LINK_CHG) { | 4717 | if (sblk->status & SD_STATUS_LINK_CHG) { |
4719 | sblk->status = SD_STATUS_UPDATED | | 4718 | sblk->status = SD_STATUS_UPDATED | |
4720 | (sblk->status & ~SD_STATUS_LINK_CHG); | 4719 | (sblk->status & ~SD_STATUS_LINK_CHG); |
4721 | spin_lock(&tp->lock); | 4720 | spin_lock(&tp->lock); |
4722 | if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { | 4721 | if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB) { |
4723 | tw32_f(MAC_STATUS, | 4722 | tw32_f(MAC_STATUS, |
@@ -4731,6 +4730,11 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) | |||
4731 | spin_unlock(&tp->lock); | 4730 | spin_unlock(&tp->lock); |
4732 | } | 4731 | } |
4733 | } | 4732 | } |
4733 | } | ||
4734 | |||
4735 | static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) | ||
4736 | { | ||
4737 | struct tg3 *tp = tnapi->tp; | ||
4734 | 4738 | ||
4735 | /* run TX completion thread */ | 4739 | /* run TX completion thread */ |
4736 | if (tnapi->hw_status->idx[0].tx_consumer != tnapi->tx_cons) { | 4740 | if (tnapi->hw_status->idx[0].tx_consumer != tnapi->tx_cons) { |
@@ -4749,6 +4753,50 @@ static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) | |||
4749 | return work_done; | 4753 | return work_done; |
4750 | } | 4754 | } |
4751 | 4755 | ||
4756 | static int tg3_poll_msix(struct napi_struct *napi, int budget) | ||
4757 | { | ||
4758 | struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi); | ||
4759 | struct tg3 *tp = tnapi->tp; | ||
4760 | int work_done = 0; | ||
4761 | struct tg3_hw_status *sblk = tnapi->hw_status; | ||
4762 | |||
4763 | while (1) { | ||
4764 | work_done = tg3_poll_work(tnapi, work_done, budget); | ||
4765 | |||
4766 | if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) | ||
4767 | goto tx_recovery; | ||
4768 | |||
4769 | if (unlikely(work_done >= budget)) | ||
4770 | break; | ||
4771 | |||
4772 | /* tp->last_tag is used in tg3_restart_ints() below | ||
4773 | * to tell the hw how much work has been processed, | ||
4774 | * so we must read it before checking for more work. | ||
4775 | */ | ||
4776 | tnapi->last_tag = sblk->status_tag; | ||
4777 | tnapi->last_irq_tag = tnapi->last_tag; | ||
4778 | rmb(); | ||
4779 | |||
4780 | /* check for RX/TX work to do */ | ||
4781 | if (sblk->idx[0].tx_consumer == tnapi->tx_cons && | ||
4782 | *(tnapi->rx_rcb_prod_idx) == tnapi->rx_rcb_ptr) { | ||
4783 | napi_complete(napi); | ||
4784 | /* Reenable interrupts. */ | ||
4785 | tw32_mailbox(tnapi->int_mbox, tnapi->last_tag << 24); | ||
4786 | mmiowb(); | ||
4787 | break; | ||
4788 | } | ||
4789 | } | ||
4790 | |||
4791 | return work_done; | ||
4792 | |||
4793 | tx_recovery: | ||
4794 | /* work_done is guaranteed to be less than budget. */ | ||
4795 | napi_complete(napi); | ||
4796 | schedule_work(&tp->reset_task); | ||
4797 | return work_done; | ||
4798 | } | ||
4799 | |||
4752 | static int tg3_poll(struct napi_struct *napi, int budget) | 4800 | static int tg3_poll(struct napi_struct *napi, int budget) |
4753 | { | 4801 | { |
4754 | struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi); | 4802 | struct tg3_napi *tnapi = container_of(napi, struct tg3_napi, napi); |
@@ -4757,6 +4805,8 @@ static int tg3_poll(struct napi_struct *napi, int budget) | |||
4757 | struct tg3_hw_status *sblk = tnapi->hw_status; | 4805 | struct tg3_hw_status *sblk = tnapi->hw_status; |
4758 | 4806 | ||
4759 | while (1) { | 4807 | while (1) { |
4808 | tg3_poll_link(tp); | ||
4809 | |||
4760 | work_done = tg3_poll_work(tnapi, work_done, budget); | 4810 | work_done = tg3_poll_work(tnapi, work_done, budget); |
4761 | 4811 | ||
4762 | if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) | 4812 | if (unlikely(tp->tg3_flags & TG3_FLAG_TX_RECOVERY_PENDING)) |
@@ -14057,10 +14107,13 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
14057 | tnapi->consmbox = rcvmbx; | 14107 | tnapi->consmbox = rcvmbx; |
14058 | tnapi->prodmbox = sndmbx; | 14108 | tnapi->prodmbox = sndmbx; |
14059 | 14109 | ||
14060 | if (i) | 14110 | if (i) { |
14061 | tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1); | 14111 | tnapi->coal_now = HOSTCC_MODE_COAL_VEC1_NOW << (i - 1); |
14062 | else | 14112 | netif_napi_add(dev, &tnapi->napi, tg3_poll_msix, 64); |
14113 | } else { | ||
14063 | tnapi->coal_now = HOSTCC_MODE_NOW; | 14114 | tnapi->coal_now = HOSTCC_MODE_NOW; |
14115 | netif_napi_add(dev, &tnapi->napi, tg3_poll, 64); | ||
14116 | } | ||
14064 | 14117 | ||
14065 | if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX)) | 14118 | if (!(tp->tg3_flags & TG3_FLAG_SUPPORT_MSIX)) |
14066 | break; | 14119 | break; |
@@ -14083,7 +14136,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, | |||
14083 | sndmbx += 0xc; | 14136 | sndmbx += 0xc; |
14084 | } | 14137 | } |
14085 | 14138 | ||
14086 | netif_napi_add(dev, &tp->napi[0].napi, tg3_poll, 64); | ||
14087 | dev->ethtool_ops = &tg3_ethtool_ops; | 14139 | dev->ethtool_ops = &tg3_ethtool_ops; |
14088 | dev->watchdog_timeo = TG3_TX_TIMEOUT; | 14140 | dev->watchdog_timeo = TG3_TX_TIMEOUT; |
14089 | dev->irq = pdev->irq; | 14141 | dev->irq = pdev->irq; |