aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/tile/tilegx.c
diff options
context:
space:
mode:
authorChris Metcalf <cmetcalf@tilera.com>2012-07-01 14:43:47 -0400
committerChris Metcalf <cmetcalf@tilera.com>2012-07-18 15:02:59 -0400
commit9b4c341b1e3c207f57de3bf5f3c65845592dee89 (patch)
treea13eb745a704951d28dc0282f118f04290e3879b /drivers/net/ethernet/tile/tilegx.c
parentddbe503203855939946430e39bae58de11b70b69 (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.c23
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. */
125struct tile_net_tx_wake { 125struct 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
576static void tile_net_schedule_tx_wake_timer(struct net_device *dev) 577static 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 */
1293static s64 tile_net_equeue_try_reserve(struct net_device *dev, 1297static 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;