diff options
author | Chris Metcalf <cmetcalf@tilera.com> | 2012-07-01 14:43:47 -0400 |
---|---|---|
committer | Chris Metcalf <cmetcalf@tilera.com> | 2012-07-18 15:02:59 -0400 |
commit | 9b4c341b1e3c207f57de3bf5f3c65845592dee89 (patch) | |
tree | a13eb745a704951d28dc0282f118f04290e3879b /drivers/net/ethernet/tile/tilegx.c | |
parent | ddbe503203855939946430e39bae58de11b70b69 (diff) |
net: tilegx driver bugfix (be explicit about percpu queue number)
Avoid packets belonging to queue/cpu A trying to transmit on cpu B.
Signed-off-by: Chris Metcalf <cmetcalf@tilera.com>
Diffstat (limited to 'drivers/net/ethernet/tile/tilegx.c')
-rw-r--r-- | drivers/net/ethernet/tile/tilegx.c | 23 |
1 files changed, 15 insertions, 8 deletions
diff --git a/drivers/net/ethernet/tile/tilegx.c b/drivers/net/ethernet/tile/tilegx.c index 7f500288f6b3..a1c414f55114 100644 --- a/drivers/net/ethernet/tile/tilegx.c +++ b/drivers/net/ethernet/tile/tilegx.c | |||
@@ -123,6 +123,7 @@ struct tile_net_comps { | |||
123 | 123 | ||
124 | /* The transmit wake timer for a given cpu and echannel. */ | 124 | /* The transmit wake timer for a given cpu and echannel. */ |
125 | struct tile_net_tx_wake { | 125 | struct tile_net_tx_wake { |
126 | int tx_queue_idx; | ||
126 | struct hrtimer timer; | 127 | struct hrtimer timer; |
127 | struct net_device *dev; | 128 | struct net_device *dev; |
128 | }; | 129 | }; |
@@ -573,12 +574,14 @@ static void add_comp(gxio_mpipe_equeue_t *equeue, | |||
573 | comps->comp_next++; | 574 | comps->comp_next++; |
574 | } | 575 | } |
575 | 576 | ||
576 | static void tile_net_schedule_tx_wake_timer(struct net_device *dev) | 577 | static void tile_net_schedule_tx_wake_timer(struct net_device *dev, |
578 | int tx_queue_idx) | ||
577 | { | 579 | { |
578 | struct tile_net_info *info = &__get_cpu_var(per_cpu_info); | 580 | struct tile_net_info *info = &per_cpu(per_cpu_info, tx_queue_idx); |
579 | struct tile_net_priv *priv = netdev_priv(dev); | 581 | struct tile_net_priv *priv = netdev_priv(dev); |
582 | struct tile_net_tx_wake *tx_wake = &info->tx_wake[priv->echannel]; | ||
580 | 583 | ||
581 | hrtimer_start(&info->tx_wake[priv->echannel].timer, | 584 | hrtimer_start(&tx_wake->timer, |
582 | ktime_set(0, TX_TIMER_DELAY_USEC * 1000UL), | 585 | ktime_set(0, TX_TIMER_DELAY_USEC * 1000UL), |
583 | HRTIMER_MODE_REL_PINNED); | 586 | HRTIMER_MODE_REL_PINNED); |
584 | } | 587 | } |
@@ -587,7 +590,7 @@ static enum hrtimer_restart tile_net_handle_tx_wake_timer(struct hrtimer *t) | |||
587 | { | 590 | { |
588 | struct tile_net_tx_wake *tx_wake = | 591 | struct tile_net_tx_wake *tx_wake = |
589 | container_of(t, struct tile_net_tx_wake, timer); | 592 | container_of(t, struct tile_net_tx_wake, timer); |
590 | netif_wake_subqueue(tx_wake->dev, smp_processor_id()); | 593 | netif_wake_subqueue(tx_wake->dev, tx_wake->tx_queue_idx); |
591 | return HRTIMER_NORESTART; | 594 | return HRTIMER_NORESTART; |
592 | } | 595 | } |
593 | 596 | ||
@@ -1218,6 +1221,7 @@ static int tile_net_open(struct net_device *dev) | |||
1218 | 1221 | ||
1219 | hrtimer_init(&tx_wake->timer, CLOCK_MONOTONIC, | 1222 | hrtimer_init(&tx_wake->timer, CLOCK_MONOTONIC, |
1220 | HRTIMER_MODE_REL); | 1223 | HRTIMER_MODE_REL); |
1224 | tx_wake->tx_queue_idx = cpu; | ||
1221 | tx_wake->timer.function = tile_net_handle_tx_wake_timer; | 1225 | tx_wake->timer.function = tile_net_handle_tx_wake_timer; |
1222 | tx_wake->dev = dev; | 1226 | tx_wake->dev = dev; |
1223 | } | 1227 | } |
@@ -1291,6 +1295,7 @@ static inline void *tile_net_frag_buf(skb_frag_t *f) | |||
1291 | * stop the queue and schedule the tx_wake timer. | 1295 | * stop the queue and schedule the tx_wake timer. |
1292 | */ | 1296 | */ |
1293 | static s64 tile_net_equeue_try_reserve(struct net_device *dev, | 1297 | static s64 tile_net_equeue_try_reserve(struct net_device *dev, |
1298 | int tx_queue_idx, | ||
1294 | struct tile_net_comps *comps, | 1299 | struct tile_net_comps *comps, |
1295 | gxio_mpipe_equeue_t *equeue, | 1300 | gxio_mpipe_equeue_t *equeue, |
1296 | int num_edescs) | 1301 | int num_edescs) |
@@ -1313,8 +1318,8 @@ static s64 tile_net_equeue_try_reserve(struct net_device *dev, | |||
1313 | } | 1318 | } |
1314 | 1319 | ||
1315 | /* Still nothing; give up and stop the queue for a short while. */ | 1320 | /* Still nothing; give up and stop the queue for a short while. */ |
1316 | netif_stop_subqueue(dev, smp_processor_id()); | 1321 | netif_stop_subqueue(dev, tx_queue_idx); |
1317 | tile_net_schedule_tx_wake_timer(dev); | 1322 | tile_net_schedule_tx_wake_timer(dev, tx_queue_idx); |
1318 | return -1; | 1323 | return -1; |
1319 | } | 1324 | } |
1320 | 1325 | ||
@@ -1580,7 +1585,8 @@ static int tile_net_tx_tso(struct sk_buff *skb, struct net_device *dev) | |||
1580 | local_irq_save(irqflags); | 1585 | local_irq_save(irqflags); |
1581 | 1586 | ||
1582 | /* Try to acquire a completion entry and an egress slot. */ | 1587 | /* Try to acquire a completion entry and an egress slot. */ |
1583 | slot = tile_net_equeue_try_reserve(dev, comps, equeue, num_edescs); | 1588 | slot = tile_net_equeue_try_reserve(dev, skb->queue_mapping, comps, |
1589 | equeue, num_edescs); | ||
1584 | if (slot < 0) { | 1590 | if (slot < 0) { |
1585 | local_irq_restore(irqflags); | 1591 | local_irq_restore(irqflags); |
1586 | return NETDEV_TX_BUSY; | 1592 | return NETDEV_TX_BUSY; |
@@ -1674,7 +1680,8 @@ static int tile_net_tx(struct sk_buff *skb, struct net_device *dev) | |||
1674 | local_irq_save(irqflags); | 1680 | local_irq_save(irqflags); |
1675 | 1681 | ||
1676 | /* Try to acquire a completion entry and an egress slot. */ | 1682 | /* Try to acquire a completion entry and an egress slot. */ |
1677 | slot = tile_net_equeue_try_reserve(dev, comps, equeue, num_edescs); | 1683 | slot = tile_net_equeue_try_reserve(dev, skb->queue_mapping, comps, |
1684 | equeue, num_edescs); | ||
1678 | if (slot < 0) { | 1685 | if (slot < 0) { |
1679 | local_irq_restore(irqflags); | 1686 | local_irq_restore(irqflags); |
1680 | return NETDEV_TX_BUSY; | 1687 | return NETDEV_TX_BUSY; |