aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/tg3.c
diff options
context:
space:
mode:
authorMatt Carlson <mcarlson@broadcom.com>2009-11-13 08:03:41 -0500
committerDavid S. Miller <davem@davemloft.net>2009-11-16 01:14:45 -0500
commit35f2d7d0d7c222a580da0ed91c8d70c54267620a (patch)
treeffd6467756d992aeaf431aa732ba4c3fa553916f /drivers/net/tg3.c
parentcbf9ca6cf8304beb640a948709c4672bc1d5a55f (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>
Diffstat (limited to 'drivers/net/tg3.c')
-rw-r--r--drivers/net/tg3.c68
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
4709static int tg3_poll_work(struct tg3_napi *tnapi, int work_done, int budget) 4709static 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
4735static 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
4756static 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
4793tx_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
4752static int tg3_poll(struct napi_struct *napi, int budget) 4800static 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;