aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Kicinski <jakub.kicinski@netronome.com>2016-04-07 14:39:48 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-08 15:26:06 -0400
commitcc7c033330fd67dd9d66a1ccb8c9d42381107bcd (patch)
treee14ca89f097521bfbf0ecd1a967f4834a38344bb
parenta98cb2581211023539887a11f8391dd615409ab8 (diff)
nfp: allow ring size reconfiguration at runtime
Since much of the required changes have already been made for changing MTU at runtime let's use it for ring size changes as well. Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net.h1
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c126
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c30
3 files changed, 136 insertions, 21 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net.h b/drivers/net/ethernet/netronome/nfp/nfp_net.h
index 9ab8e3967dc9..3d53fcf323eb 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net.h
@@ -724,6 +724,7 @@ void nfp_net_rss_write_key(struct nfp_net *nn);
724void nfp_net_coalesce_write_cfg(struct nfp_net *nn); 724void nfp_net_coalesce_write_cfg(struct nfp_net *nn);
725int nfp_net_irqs_alloc(struct nfp_net *nn); 725int nfp_net_irqs_alloc(struct nfp_net *nn);
726void nfp_net_irqs_disable(struct nfp_net *nn); 726void nfp_net_irqs_disable(struct nfp_net *nn);
727int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt);
727 728
728#ifdef CONFIG_NFP_NET_DEBUG 729#ifdef CONFIG_NFP_NET_DEBUG
729void nfp_net_debugfs_create(void); 730void nfp_net_debugfs_create(void);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index c4f0c70e77ce..0bdff390c958 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -1444,6 +1444,59 @@ err_alloc:
1444 return -ENOMEM; 1444 return -ENOMEM;
1445} 1445}
1446 1446
1447static struct nfp_net_tx_ring *
1448nfp_net_shadow_tx_rings_prepare(struct nfp_net *nn, u32 buf_cnt)
1449{
1450 struct nfp_net_tx_ring *rings;
1451 unsigned int r;
1452
1453 rings = kcalloc(nn->num_tx_rings, sizeof(*rings), GFP_KERNEL);
1454 if (!rings)
1455 return NULL;
1456
1457 for (r = 0; r < nn->num_tx_rings; r++) {
1458 nfp_net_tx_ring_init(&rings[r], nn->tx_rings[r].r_vec, r);
1459
1460 if (nfp_net_tx_ring_alloc(&rings[r], buf_cnt))
1461 goto err_free_prev;
1462 }
1463
1464 return rings;
1465
1466err_free_prev:
1467 while (r--)
1468 nfp_net_tx_ring_free(&rings[r]);
1469 kfree(rings);
1470 return NULL;
1471}
1472
1473static struct nfp_net_tx_ring *
1474nfp_net_shadow_tx_rings_swap(struct nfp_net *nn, struct nfp_net_tx_ring *rings)
1475{
1476 struct nfp_net_tx_ring *old = nn->tx_rings;
1477 unsigned int r;
1478
1479 for (r = 0; r < nn->num_tx_rings; r++)
1480 old[r].r_vec->tx_ring = &rings[r];
1481
1482 nn->tx_rings = rings;
1483 return old;
1484}
1485
1486static void
1487nfp_net_shadow_tx_rings_free(struct nfp_net *nn, struct nfp_net_tx_ring *rings)
1488{
1489 unsigned int r;
1490
1491 if (!rings)
1492 return;
1493
1494 for (r = 0; r < nn->num_tx_rings; r++)
1495 nfp_net_tx_ring_free(&rings[r]);
1496
1497 kfree(rings);
1498}
1499
1447/** 1500/**
1448 * nfp_net_rx_ring_free() - Free resources allocated to a RX ring 1501 * nfp_net_rx_ring_free() - Free resources allocated to a RX ring
1449 * @rx_ring: RX ring to free 1502 * @rx_ring: RX ring to free
@@ -1560,6 +1613,9 @@ nfp_net_shadow_rx_rings_free(struct nfp_net *nn, struct nfp_net_rx_ring *rings)
1560{ 1613{
1561 unsigned int r; 1614 unsigned int r;
1562 1615
1616 if (!rings)
1617 return;
1618
1563 for (r = 0; r < nn->num_r_vecs; r++) { 1619 for (r = 0; r < nn->num_r_vecs; r++) {
1564 nfp_net_rx_ring_bufs_free(nn, &rings[r]); 1620 nfp_net_rx_ring_bufs_free(nn, &rings[r]);
1565 nfp_net_rx_ring_free(&rings[r]); 1621 nfp_net_rx_ring_free(&rings[r]);
@@ -2104,6 +2160,76 @@ static int nfp_net_change_mtu(struct net_device *netdev, int new_mtu)
2104 return err; 2160 return err;
2105} 2161}
2106 2162
2163int nfp_net_set_ring_size(struct nfp_net *nn, u32 rxd_cnt, u32 txd_cnt)
2164{
2165 struct nfp_net_tx_ring *tx_rings = NULL;
2166 struct nfp_net_rx_ring *rx_rings = NULL;
2167 u32 old_rxd_cnt, old_txd_cnt;
2168 int err;
2169
2170 if (!netif_running(nn->netdev)) {
2171 nn->rxd_cnt = rxd_cnt;
2172 nn->txd_cnt = txd_cnt;
2173 return 0;
2174 }
2175
2176 old_rxd_cnt = nn->rxd_cnt;
2177 old_txd_cnt = nn->txd_cnt;
2178
2179 /* Prepare new rings */
2180 if (nn->rxd_cnt != rxd_cnt) {
2181 rx_rings = nfp_net_shadow_rx_rings_prepare(nn, nn->fl_bufsz,
2182 rxd_cnt);
2183 if (!rx_rings)
2184 return -ENOMEM;
2185 }
2186 if (nn->txd_cnt != txd_cnt) {
2187 tx_rings = nfp_net_shadow_tx_rings_prepare(nn, txd_cnt);
2188 if (!tx_rings) {
2189 nfp_net_shadow_rx_rings_free(nn, rx_rings);
2190 return -ENOMEM;
2191 }
2192 }
2193
2194 /* Stop device, swap in new rings, try to start the firmware */
2195 nfp_net_close_stack(nn);
2196 nfp_net_clear_config_and_disable(nn);
2197
2198 if (rx_rings)
2199 rx_rings = nfp_net_shadow_rx_rings_swap(nn, rx_rings);
2200 if (tx_rings)
2201 tx_rings = nfp_net_shadow_tx_rings_swap(nn, tx_rings);
2202
2203 nn->rxd_cnt = rxd_cnt;
2204 nn->txd_cnt = txd_cnt;
2205
2206 err = nfp_net_set_config_and_enable(nn);
2207 if (err) {
2208 const int err_new = err;
2209
2210 /* Try with old configuration and old rings */
2211 if (rx_rings)
2212 rx_rings = nfp_net_shadow_rx_rings_swap(nn, rx_rings);
2213 if (tx_rings)
2214 tx_rings = nfp_net_shadow_tx_rings_swap(nn, tx_rings);
2215
2216 nn->rxd_cnt = old_rxd_cnt;
2217 nn->txd_cnt = old_txd_cnt;
2218
2219 err = __nfp_net_set_config_and_enable(nn);
2220 if (err)
2221 nn_err(nn, "Can't restore ring config - FW communication failed (%d,%d)\n",
2222 err_new, err);
2223 }
2224
2225 nfp_net_shadow_rx_rings_free(nn, rx_rings);
2226 nfp_net_shadow_tx_rings_free(nn, tx_rings);
2227
2228 nfp_net_open_stack(nn);
2229
2230 return err;
2231}
2232
2107static struct rtnl_link_stats64 *nfp_net_stat64(struct net_device *netdev, 2233static struct rtnl_link_stats64 *nfp_net_stat64(struct net_device *netdev,
2108 struct rtnl_link_stats64 *stats) 2234 struct rtnl_link_stats64 *stats)
2109{ 2235{
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
index 9a4084a68db5..ccfef1f17627 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c
@@ -153,37 +153,25 @@ static int nfp_net_set_ringparam(struct net_device *netdev,
153 struct nfp_net *nn = netdev_priv(netdev); 153 struct nfp_net *nn = netdev_priv(netdev);
154 u32 rxd_cnt, txd_cnt; 154 u32 rxd_cnt, txd_cnt;
155 155
156 if (netif_running(netdev)) {
157 /* Some NIC drivers allow reconfiguration on the fly,
158 * some down the interface, change and then up it
159 * again. For now we don't allow changes when the
160 * device is up.
161 */
162 nn_warn(nn, "Can't change rings while device is up\n");
163 return -EBUSY;
164 }
165
166 /* We don't have separate queues/rings for small/large frames. */ 156 /* We don't have separate queues/rings for small/large frames. */
167 if (ring->rx_mini_pending || ring->rx_jumbo_pending) 157 if (ring->rx_mini_pending || ring->rx_jumbo_pending)
168 return -EINVAL; 158 return -EINVAL;
169 159
170 /* Round up to supported values */ 160 /* Round up to supported values */
171 rxd_cnt = roundup_pow_of_two(ring->rx_pending); 161 rxd_cnt = roundup_pow_of_two(ring->rx_pending);
172 rxd_cnt = max_t(u32, rxd_cnt, NFP_NET_MIN_RX_DESCS);
173 rxd_cnt = min_t(u32, rxd_cnt, NFP_NET_MAX_RX_DESCS);
174
175 txd_cnt = roundup_pow_of_two(ring->tx_pending); 162 txd_cnt = roundup_pow_of_two(ring->tx_pending);
176 txd_cnt = max_t(u32, txd_cnt, NFP_NET_MIN_TX_DESCS);
177 txd_cnt = min_t(u32, txd_cnt, NFP_NET_MAX_TX_DESCS);
178 163
179 if (nn->rxd_cnt != rxd_cnt || nn->txd_cnt != txd_cnt) 164 if (rxd_cnt < NFP_NET_MIN_RX_DESCS || rxd_cnt > NFP_NET_MAX_RX_DESCS ||
180 nn_dbg(nn, "Change ring size: RxQ %u->%u, TxQ %u->%u\n", 165 txd_cnt < NFP_NET_MIN_TX_DESCS || txd_cnt > NFP_NET_MAX_TX_DESCS)
181 nn->rxd_cnt, rxd_cnt, nn->txd_cnt, txd_cnt); 166 return -EINVAL;
182 167
183 nn->rxd_cnt = rxd_cnt; 168 if (nn->rxd_cnt == rxd_cnt && nn->txd_cnt == txd_cnt)
184 nn->txd_cnt = txd_cnt; 169 return 0;
185 170
186 return 0; 171 nn_dbg(nn, "Change ring size: RxQ %u->%u, TxQ %u->%u\n",
172 nn->rxd_cnt, rxd_cnt, nn->txd_cnt, txd_cnt);
173
174 return nfp_net_set_ring_size(nn, rxd_cnt, txd_cnt);
187} 175}
188 176
189static void nfp_net_get_strings(struct net_device *netdev, 177static void nfp_net_get_strings(struct net_device *netdev,