|
@@ -1672,6 +1672,82 @@ nfp_net_vec_write_ring_data(struct nfp_net *nn, struct nfp_net_r_vector *r_vec,
|
|
nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), r_vec->irq_idx);
|
|
nn_writeb(nn, NFP_NET_CFG_TXR_VEC(idx), r_vec->irq_idx);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static int __nfp_net_set_config_and_enable(struct nfp_net *nn)
|
|
|
|
+{
|
|
|
|
+ u32 new_ctrl, update = 0;
|
|
|
|
+ unsigned int r;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ new_ctrl = nn->ctrl;
|
|
|
|
+
|
|
|
|
+ if (nn->cap & NFP_NET_CFG_CTRL_RSS) {
|
|
|
|
+ nfp_net_rss_write_key(nn);
|
|
|
|
+ nfp_net_rss_write_itbl(nn);
|
|
|
|
+ nn_writel(nn, NFP_NET_CFG_RSS_CTRL, nn->rss_cfg);
|
|
|
|
+ update |= NFP_NET_CFG_UPDATE_RSS;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (nn->cap & NFP_NET_CFG_CTRL_IRQMOD) {
|
|
|
|
+ nfp_net_coalesce_write_cfg(nn);
|
|
|
|
+
|
|
|
|
+ new_ctrl |= NFP_NET_CFG_CTRL_IRQMOD;
|
|
|
|
+ update |= NFP_NET_CFG_UPDATE_IRQMOD;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ for (r = 0; r < nn->num_r_vecs; r++)
|
|
|
|
+ nfp_net_vec_write_ring_data(nn, &nn->r_vecs[r], r);
|
|
|
|
+
|
|
|
|
+ nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, nn->num_tx_rings == 64 ?
|
|
|
|
+ 0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1);
|
|
|
|
+
|
|
|
|
+ nn_writeq(nn, NFP_NET_CFG_RXRS_ENABLE, nn->num_rx_rings == 64 ?
|
|
|
|
+ 0xffffffffffffffffULL : ((u64)1 << nn->num_rx_rings) - 1);
|
|
|
|
+
|
|
|
|
+ nfp_net_write_mac_addr(nn, nn->netdev->dev_addr);
|
|
|
|
+
|
|
|
|
+ nn_writel(nn, NFP_NET_CFG_MTU, nn->netdev->mtu);
|
|
|
|
+ nn_writel(nn, NFP_NET_CFG_FLBUFSZ, nn->fl_bufsz);
|
|
|
|
+
|
|
|
|
+ /* Enable device */
|
|
|
|
+ new_ctrl |= NFP_NET_CFG_CTRL_ENABLE;
|
|
|
|
+ update |= NFP_NET_CFG_UPDATE_GEN;
|
|
|
|
+ update |= NFP_NET_CFG_UPDATE_MSIX;
|
|
|
|
+ update |= NFP_NET_CFG_UPDATE_RING;
|
|
|
|
+ if (nn->cap & NFP_NET_CFG_CTRL_RINGCFG)
|
|
|
|
+ new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG;
|
|
|
|
+
|
|
|
|
+ nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl);
|
|
|
|
+ err = nfp_net_reconfig(nn, update);
|
|
|
|
+
|
|
|
|
+ nn->ctrl = new_ctrl;
|
|
|
|
+
|
|
|
|
+ /* Since reconfiguration requests while NFP is down are ignored we
|
|
|
|
+ * have to wipe the entire VXLAN configuration and reinitialize it.
|
|
|
|
+ */
|
|
|
|
+ if (nn->ctrl & NFP_NET_CFG_CTRL_VXLAN) {
|
|
|
|
+ memset(&nn->vxlan_ports, 0, sizeof(nn->vxlan_ports));
|
|
|
|
+ memset(&nn->vxlan_usecnt, 0, sizeof(nn->vxlan_usecnt));
|
|
|
|
+ vxlan_get_rx_port(nn->netdev);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * nfp_net_set_config_and_enable() - Write control BAR and enable NFP
|
|
|
|
+ * @nn: NFP Net device to reconfigure
|
|
|
|
+ */
|
|
|
|
+static int nfp_net_set_config_and_enable(struct nfp_net *nn)
|
|
|
|
+{
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ err = __nfp_net_set_config_and_enable(nn);
|
|
|
|
+ if (err)
|
|
|
|
+ nfp_net_clear_config_and_disable(nn);
|
|
|
|
+
|
|
|
|
+ return err;
|
|
|
|
+}
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* nfp_net_start_vec() - Start ring vector
|
|
* nfp_net_start_vec() - Start ring vector
|
|
* @nn: NFP Net device structure
|
|
* @nn: NFP Net device structure
|
|
@@ -1692,20 +1768,33 @@ nfp_net_start_vec(struct nfp_net *nn, struct nfp_net_r_vector *r_vec)
|
|
enable_irq(irq_vec);
|
|
enable_irq(irq_vec);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/**
|
|
|
|
+ * nfp_net_open_stack() - Start the device from stack's perspective
|
|
|
|
+ * @nn: NFP Net device to reconfigure
|
|
|
|
+ */
|
|
|
|
+static void nfp_net_open_stack(struct nfp_net *nn)
|
|
|
|
+{
|
|
|
|
+ unsigned int r;
|
|
|
|
+
|
|
|
|
+ for (r = 0; r < nn->num_r_vecs; r++)
|
|
|
|
+ nfp_net_start_vec(nn, &nn->r_vecs[r]);
|
|
|
|
+
|
|
|
|
+ netif_tx_wake_all_queues(nn->netdev);
|
|
|
|
+
|
|
|
|
+ enable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector);
|
|
|
|
+ nfp_net_read_link_status(nn);
|
|
|
|
+}
|
|
|
|
+
|
|
static int nfp_net_netdev_open(struct net_device *netdev)
|
|
static int nfp_net_netdev_open(struct net_device *netdev)
|
|
{
|
|
{
|
|
struct nfp_net *nn = netdev_priv(netdev);
|
|
struct nfp_net *nn = netdev_priv(netdev);
|
|
int err, r;
|
|
int err, r;
|
|
- u32 update = 0;
|
|
|
|
- u32 new_ctrl;
|
|
|
|
|
|
|
|
if (nn->ctrl & NFP_NET_CFG_CTRL_ENABLE) {
|
|
if (nn->ctrl & NFP_NET_CFG_CTRL_ENABLE) {
|
|
nn_err(nn, "Dev is already enabled: 0x%08x\n", nn->ctrl);
|
|
nn_err(nn, "Dev is already enabled: 0x%08x\n", nn->ctrl);
|
|
return -EBUSY;
|
|
return -EBUSY;
|
|
}
|
|
}
|
|
|
|
|
|
- new_ctrl = nn->ctrl;
|
|
|
|
-
|
|
|
|
/* Step 1: Allocate resources for rings and the like
|
|
/* Step 1: Allocate resources for rings and the like
|
|
* - Request interrupts
|
|
* - Request interrupts
|
|
* - Allocate RX and TX ring resources
|
|
* - Allocate RX and TX ring resources
|
|
@@ -1758,20 +1847,6 @@ static int nfp_net_netdev_open(struct net_device *netdev)
|
|
if (err)
|
|
if (err)
|
|
goto err_free_rings;
|
|
goto err_free_rings;
|
|
|
|
|
|
- if (nn->cap & NFP_NET_CFG_CTRL_RSS) {
|
|
|
|
- nfp_net_rss_write_key(nn);
|
|
|
|
- nfp_net_rss_write_itbl(nn);
|
|
|
|
- nn_writel(nn, NFP_NET_CFG_RSS_CTRL, nn->rss_cfg);
|
|
|
|
- update |= NFP_NET_CFG_UPDATE_RSS;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (nn->cap & NFP_NET_CFG_CTRL_IRQMOD) {
|
|
|
|
- nfp_net_coalesce_write_cfg(nn);
|
|
|
|
-
|
|
|
|
- new_ctrl |= NFP_NET_CFG_CTRL_IRQMOD;
|
|
|
|
- update |= NFP_NET_CFG_UPDATE_IRQMOD;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
/* Step 2: Configure the NFP
|
|
/* Step 2: Configure the NFP
|
|
* - Enable rings from 0 to tx_rings/rx_rings - 1.
|
|
* - Enable rings from 0 to tx_rings/rx_rings - 1.
|
|
* - Write MAC address (in case it changed)
|
|
* - Write MAC address (in case it changed)
|
|
@@ -1779,43 +1854,9 @@ static int nfp_net_netdev_open(struct net_device *netdev)
|
|
* - Set the Freelist buffer size
|
|
* - Set the Freelist buffer size
|
|
* - Enable the FW
|
|
* - Enable the FW
|
|
*/
|
|
*/
|
|
- for (r = 0; r < nn->num_r_vecs; r++)
|
|
|
|
- nfp_net_vec_write_ring_data(nn, &nn->r_vecs[r], r);
|
|
|
|
-
|
|
|
|
- nn_writeq(nn, NFP_NET_CFG_TXRS_ENABLE, nn->num_tx_rings == 64 ?
|
|
|
|
- 0xffffffffffffffffULL : ((u64)1 << nn->num_tx_rings) - 1);
|
|
|
|
-
|
|
|
|
- nn_writeq(nn, NFP_NET_CFG_RXRS_ENABLE, nn->num_rx_rings == 64 ?
|
|
|
|
- 0xffffffffffffffffULL : ((u64)1 << nn->num_rx_rings) - 1);
|
|
|
|
-
|
|
|
|
- nfp_net_write_mac_addr(nn, netdev->dev_addr);
|
|
|
|
-
|
|
|
|
- nn_writel(nn, NFP_NET_CFG_MTU, netdev->mtu);
|
|
|
|
- nn_writel(nn, NFP_NET_CFG_FLBUFSZ, nn->fl_bufsz);
|
|
|
|
-
|
|
|
|
- /* Enable device */
|
|
|
|
- new_ctrl |= NFP_NET_CFG_CTRL_ENABLE;
|
|
|
|
- update |= NFP_NET_CFG_UPDATE_GEN;
|
|
|
|
- update |= NFP_NET_CFG_UPDATE_MSIX;
|
|
|
|
- update |= NFP_NET_CFG_UPDATE_RING;
|
|
|
|
- if (nn->cap & NFP_NET_CFG_CTRL_RINGCFG)
|
|
|
|
- new_ctrl |= NFP_NET_CFG_CTRL_RINGCFG;
|
|
|
|
-
|
|
|
|
- nn_writel(nn, NFP_NET_CFG_CTRL, new_ctrl);
|
|
|
|
- err = nfp_net_reconfig(nn, update);
|
|
|
|
|
|
+ err = nfp_net_set_config_and_enable(nn);
|
|
if (err)
|
|
if (err)
|
|
- goto err_clear_config;
|
|
|
|
-
|
|
|
|
- nn->ctrl = new_ctrl;
|
|
|
|
-
|
|
|
|
- /* Since reconfiguration requests while NFP is down are ignored we
|
|
|
|
- * have to wipe the entire VXLAN configuration and reinitialize it.
|
|
|
|
- */
|
|
|
|
- if (nn->ctrl & NFP_NET_CFG_CTRL_VXLAN) {
|
|
|
|
- memset(&nn->vxlan_ports, 0, sizeof(nn->vxlan_ports));
|
|
|
|
- memset(&nn->vxlan_usecnt, 0, sizeof(nn->vxlan_usecnt));
|
|
|
|
- vxlan_get_rx_port(netdev);
|
|
|
|
- }
|
|
|
|
|
|
+ goto err_free_rings;
|
|
|
|
|
|
/* Step 3: Enable for kernel
|
|
/* Step 3: Enable for kernel
|
|
* - put some freelist descriptors on each RX ring
|
|
* - put some freelist descriptors on each RX ring
|
|
@@ -1823,18 +1864,10 @@ static int nfp_net_netdev_open(struct net_device *netdev)
|
|
* - enable all TX queues
|
|
* - enable all TX queues
|
|
* - set link state
|
|
* - set link state
|
|
*/
|
|
*/
|
|
- for (r = 0; r < nn->num_r_vecs; r++)
|
|
|
|
- nfp_net_start_vec(nn, &nn->r_vecs[r]);
|
|
|
|
-
|
|
|
|
- netif_tx_wake_all_queues(netdev);
|
|
|
|
-
|
|
|
|
- enable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector);
|
|
|
|
- nfp_net_read_link_status(nn);
|
|
|
|
|
|
+ nfp_net_open_stack(nn);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
-err_clear_config:
|
|
|
|
- nfp_net_clear_config_and_disable(nn);
|
|
|
|
err_free_rings:
|
|
err_free_rings:
|
|
r = nn->num_r_vecs;
|
|
r = nn->num_r_vecs;
|
|
err_free_prev_vecs:
|
|
err_free_prev_vecs:
|
|
@@ -1858,36 +1891,31 @@ err_free_exn:
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * nfp_net_netdev_close() - Called when the device is downed
|
|
|
|
- * @netdev: netdev structure
|
|
|
|
|
|
+ * nfp_net_close_stack() - Quiescent the stack (part of close)
|
|
|
|
+ * @nn: NFP Net device to reconfigure
|
|
*/
|
|
*/
|
|
-static int nfp_net_netdev_close(struct net_device *netdev)
|
|
|
|
|
|
+static void nfp_net_close_stack(struct nfp_net *nn)
|
|
{
|
|
{
|
|
- struct nfp_net *nn = netdev_priv(netdev);
|
|
|
|
- int r;
|
|
|
|
-
|
|
|
|
- if (!(nn->ctrl & NFP_NET_CFG_CTRL_ENABLE)) {
|
|
|
|
- nn_err(nn, "Dev is not up: 0x%08x\n", nn->ctrl);
|
|
|
|
- return 0;
|
|
|
|
- }
|
|
|
|
|
|
+ unsigned int r;
|
|
|
|
|
|
- /* Step 1: Disable RX and TX rings from the Linux kernel perspective
|
|
|
|
- */
|
|
|
|
disable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector);
|
|
disable_irq(nn->irq_entries[NFP_NET_CFG_LSC].vector);
|
|
- netif_carrier_off(netdev);
|
|
|
|
|
|
+ netif_carrier_off(nn->netdev);
|
|
nn->link_up = false;
|
|
nn->link_up = false;
|
|
|
|
|
|
for (r = 0; r < nn->num_r_vecs; r++)
|
|
for (r = 0; r < nn->num_r_vecs; r++)
|
|
napi_disable(&nn->r_vecs[r].napi);
|
|
napi_disable(&nn->r_vecs[r].napi);
|
|
|
|
|
|
- netif_tx_disable(netdev);
|
|
|
|
|
|
+ netif_tx_disable(nn->netdev);
|
|
|
|
+}
|
|
|
|
|
|
- /* Step 2: Tell NFP
|
|
|
|
- */
|
|
|
|
- nfp_net_clear_config_and_disable(nn);
|
|
|
|
|
|
+/**
|
|
|
|
+ * nfp_net_close_free_all() - Free all runtime resources
|
|
|
|
+ * @nn: NFP Net device to reconfigure
|
|
|
|
+ */
|
|
|
|
+static void nfp_net_close_free_all(struct nfp_net *nn)
|
|
|
|
+{
|
|
|
|
+ unsigned int r;
|
|
|
|
|
|
- /* Step 3: Free resources
|
|
|
|
- */
|
|
|
|
for (r = 0; r < nn->num_r_vecs; r++) {
|
|
for (r = 0; r < nn->num_r_vecs; r++) {
|
|
nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring);
|
|
nfp_net_rx_ring_reset(nn->r_vecs[r].rx_ring);
|
|
nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring);
|
|
nfp_net_rx_ring_bufs_free(nn, nn->r_vecs[r].rx_ring);
|
|
@@ -1902,6 +1930,32 @@ static int nfp_net_netdev_close(struct net_device *netdev)
|
|
|
|
|
|
nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
|
|
nfp_net_aux_irq_free(nn, NFP_NET_CFG_LSC, NFP_NET_IRQ_LSC_IDX);
|
|
nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX);
|
|
nfp_net_aux_irq_free(nn, NFP_NET_CFG_EXN, NFP_NET_IRQ_EXN_IDX);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * nfp_net_netdev_close() - Called when the device is downed
|
|
|
|
+ * @netdev: netdev structure
|
|
|
|
+ */
|
|
|
|
+static int nfp_net_netdev_close(struct net_device *netdev)
|
|
|
|
+{
|
|
|
|
+ struct nfp_net *nn = netdev_priv(netdev);
|
|
|
|
+
|
|
|
|
+ if (!(nn->ctrl & NFP_NET_CFG_CTRL_ENABLE)) {
|
|
|
|
+ nn_err(nn, "Dev is not up: 0x%08x\n", nn->ctrl);
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Step 1: Disable RX and TX rings from the Linux kernel perspective
|
|
|
|
+ */
|
|
|
|
+ nfp_net_close_stack(nn);
|
|
|
|
+
|
|
|
|
+ /* Step 2: Tell NFP
|
|
|
|
+ */
|
|
|
|
+ nfp_net_clear_config_and_disable(nn);
|
|
|
|
+
|
|
|
|
+ /* Step 3: Free resources
|
|
|
|
+ */
|
|
|
|
+ nfp_net_close_free_all(nn);
|
|
|
|
|
|
nn_dbg(nn, "%s down", netdev->name);
|
|
nn_dbg(nn, "%s down", netdev->name);
|
|
return 0;
|
|
return 0;
|