Making use of VNICs in the sfc driver
Subsystems (2)
RFC PATCH 1/2 Making use of VNICs in the sfc driver
--- drivers/net/sfc/Makefile | 4 +- drivers/net/sfc/driverlink.c | 525 ++++++++++++++++++++++++++++++++ drivers/net/sfc/driverlink.h | 76 +++++ drivers/net/sfc/driverlink_api.h | 614 ++++++++++++++++++++++++++++++++++++++ drivers/net/sfc/efx.c | 47 +++- drivers/net/sfc/falcon.c | 88 ++++++- drivers/net/sfc/net_driver.h | 15 + 7 files changed, 1365 insertions(+), 4 deletions(-) create mode 100644 drivers/net/sfc/driverlink.c create mode 100644 drivers/net/sfc/driverlink.h create mode 100644 drivers/net/sfc/driverlink_api.h
drivers/net/sfc/Makefile +2 -2
@@ -1,5 +1,5 @@ sfc-y += efx.o falcon.o tx.o rx.o falcon_xmac.o \ selftest.o ethtool.o xfp_phy.o \ - mdio_10g.o tenxpress.o boards.o sfe4001.o - + mdio_10g.o tenxpress.o boards.o sfe4001.o \ + driverlink.o obj-$(CONFIG_SFC) += sfc.o
drivers/net/sfc/driverlink.c new file +525 -0
525 lines not on this page · raw message
drivers/net/sfc/driverlink.h new file +76 -0
76 lines not on this page · raw message
drivers/net/sfc/driverlink_api.h new file +614 -0
614 lines not on this page · raw message
drivers/net/sfc/efx.c +33 -1
@@ -544,6 +544,9 @@ static void efx_link_status_changed(struct efx_nic *efx)netif_carrier_off (efx->net_dev); } +/* Inform driverlink client */ +EFX_DL_CALLBACK (efx, link_change, efx->link_up); +/* Status message for kernel log */ if (efx->link_up) {struct mii_if_info *gmii = &efx->mii;
@@ -1410,6 +1413,8 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)efx_stop_all (efx); +/* Ask driverlink client if we can change MTU */ + rc =EFX_DL_CALLBACK (efx, request_mtu, new_mtu);EFX_LOG (efx,"changing MTU to %d\n" , new_mtu);efx_fini_channels (efx);
@@ -1418,6 +1423,9 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)if (rc) goto fail; +/* Notify driverlink client of new MTU */ +EFX_DL_CALLBACK (efx, mtu_changed, new_mtu); +efx_start_all (efx);return rc;
@@ -1570,6 +1578,23 @@ static void efx_unregister_netdev(struct efx_nic *efx)* Device reset and suspend * **************************************************************************/ +/* Serialise access to the driverlink callbacks, by quiescing event processing +* (without flushing the descriptor queues), and acquiring the rtnl_lock */ +void efx_suspend (struct efx_nic *efx) +{ +EFX_LOG (efx,"suspending operations\n" ); + +rtnl_lock (); +efx_stop_all (efx); +} + +void efx_resume (struct efx_nic *efx) +{ +EFX_LOG (efx,"resuming operations\n" ); + +efx_start_all (efx); +rtnl_unlock (); +}/* The final hardware and software finalisation before reset. */ static int efx_reset_down (struct efx_nic *efx,struct ethtool_cmd *ecmd)
@@ -1632,6 +1657,10 @@ static int efx_reset(struct efx_nic *efx)enum reset_type method = efx->reset_pending;int rc; +/* Notify driverlink clients of imminent reset. */ +efx_dl_reset_lock (); +efx_dl_reset_suspend (efx); +/* Serialise with kernel interfaces */ rtnl_lock ();
@@ -1701,8 +1730,9 @@ static int efx_reset(struct efx_nic *efx) unlock_rtnl:rtnl_unlock (); +efx_dl_reset_resume (efx,1 ); +efx_dl_reset_unlock ();return 0 ; - fail5: fail4: fail3:
@@ -1715,6 +1745,8 @@ static int efx_reset(struct efx_nic *efx)rtnl_unlock ();efx_unregister_netdev (efx);efx_fini_port (efx); +efx_dl_reset_resume (efx,0 ); +efx_dl_reset_unlock ();return rc; }
@@ -1854,6 +1886,9 @@ static int efx_init_struct(struct efx_nic *efx, struct
efx_nic_type *type,
mutex_init(&efx->mac_lock);
efx->phy_op = &efx_dummy_phy_operations; efx->mii.dev = net_dev;
+ INIT_LIST_HEAD(&efx->dl_node);
+ INIT_LIST_HEAD(&efx->dl_device_list);
+ efx->dl_cb = efx_default_callbacks;
INIT_WORK(&efx->reconfigure_work, efx_reconfigure_work); atomic_set(&efx->netif_stop_count, 1);
@@ -1960,6 +1995,9 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
if (!efx)
return;
+ /* Unregister driver from driverlink layer */
+ efx_dl_unregister_nic(efx);
+
/* Mark the NIC as fini, then stop the interface */ rtnl_lock();
efx->state = STATE_FINI;
@@ -2126,8 +2164,15 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
EFX_LOG(efx, "initialisation successful\n");
+ /* Register with driverlink layer */
+ rc = efx_dl_register_nic(efx);
+ if (rc)
+ goto fail6;
+
return 0;
+ fail6:
+ efx_unregister_netdev(efx);
fail5:
efx_pci_remove_main(efx);
fail4:
drivers/net/sfc/falcon.c +9 -0
@@ -36,14 +36,23 @@/** * struct falcon_nic_data - Falcon NIC state +* @tx_dc_entries: Number of entries in each TX queue descriptor cache +* @rx_dc_entries: Number of entries in each RX queue descriptor cache +* @tx_dc_base: Base address in SRAM of TX queue descriptor caches +* @rx_dc_base: Base address in SRAM of RX queue descriptor caches * @next_buffer_table: First available buffer table id * @pci_dev2: The secondary PCI device if present * @i2c_data: Operations and state for I2C bit-bashing algorithm */ struct falcon_nic_data { +unsigned tx_dc_entries; +unsigned rx_dc_entries; +unsigned tx_dc_base; +unsigned rx_dc_base;unsigned next_buffer_table;struct pci_dev *pci_dev2;struct i2c_algo_bit_data i2c_data; +struct efx_dl_falcon_resources resources; };/**************************************************************************
@@ -1120,10 +1129,12 @@ static void falcon_handle_driver_event(struct efx_channel
*channel,
case TX_DESCQ_FLS_DONE_EV_DECODE:
EFX_TRACE(efx, "channel %d TXQ %d flushed\n",
channel->channel, ev_sub_data);
+ EFX_DL_CALLBACK(efx, event, event);
break;
case RX_DESCQ_FLS_DONE_EV_DECODE:
EFX_TRACE(efx, "channel %d RXQ %d flushed\n",
channel->channel, ev_sub_data);
+ EFX_DL_CALLBACK(efx, event, event);
break;
case EVQ_INIT_DONE_EV_DECODE:
EFX_LOG(efx, "channel %d EVQ %d initialised\n",
@@ -1132,14 +1143,17 @@ static void falcon_handle_driver_event(struct efx_channel *channel,
case SRM_UPD_DONE_EV_DECODE:
EFX_TRACE(efx, "channel %d SRAM update done\n",
channel->channel);
+ EFX_DL_CALLBACK(efx, event, event);
break;
case WAKE_UP_EV_DECODE:
EFX_TRACE(efx, "channel %d RXQ %d wakeup event\n",
channel->channel, ev_sub_data);
+ EFX_DL_CALLBACK(efx, event, event);
break;
case TIMER_EV_DECODE:
EFX_TRACE(efx, "channel %d RX queue %d timer expired\n",
channel->channel, ev_sub_data);
+ EFX_DL_CALLBACK(efx, event, event);
break;
case RX_RECOVERY_EV_DECODE:
EFX_ERR(efx, "channel %d seen DRIVER RX_RESET event. "
@@ -1164,6 +1178,7 @@ static void falcon_handle_driver_event(struct efx_channel *channel,
EFX_TRACE(efx, "channel %d unknown driver event code %d "
"data %04x\n", channel->channel, ev_sub_code, ev_sub_data);
+ EFX_DL_CALLBACK(efx, event, event);
break;
}
}
@@ -2376,6 +2391,70 @@ static int falcon_probe_nvconfig(struct efx_nic *efx)
return rc;
}
+/* Looks at available SRAM resources and silicon revision, and works out
+ * how many queues we can support, and where things like descriptor caches
+ * should live. */
+static int falcon_dimension_resources(struct efx_nic *efx)
+{
+ unsigned buffer_entry_bytes, internal_dcs_entries;
+ struct falcon_nic_data *nic_data = efx->nic_data;
+ struct efx_dl_falcon_resources *res = &nic_data->resources;
+
+ /* Fill out the driverlink resource list */
+ res->hdr.type = EFX_DL_FALCON_RESOURCES;
+ res->biu_lock = &efx->biu_lock;
+ efx->dl_info = &res->hdr;
+ nic_data->tx_dc_entries = 16;
+
+ /* Set the RX descriptor cache size. Values 16, 32 and 64 are
+ * supported (8 won't work). Bigger is better, especially on B
+ * silicon.
+ */
+ nic_data->rx_dc_entries = 64;
+
+ /* NB. The minimum values get increased as this driver initialises
+ * its resources, so this should prevent any overlap.
+ */
+ switch (falcon_rev(efx)) {
+ case FALCON_REV_A1:
+ res->rxq_min = 16;
+ res->txq_min = 16;
+ res->evq_int_min = 4;
+ res->evq_int_lim = 5;
+ res->evq_timer_min = 5;
+ res->evq_timer_lim = 4096;
+ internal_dcs_entries = 8192;
+ break;
+ case FALCON_REV_B0:
+ default:
+ res->rxq_min = 0;
+ res->txq_min = 0;
+ res->evq_int_min = 0;
+ res->evq_int_lim = 64;
+ res->evq_timer_min = 64;
+ res->evq_timer_lim = 4096;
+ internal_dcs_entries = 4096;
+ break;
+ }
+
+ buffer_entry_bytes = 8;
+
+ res->rxq_lim = internal_dcs_entries / nic_data->rx_dc_entries;
+ res->txq_lim = internal_dcs_entries / nic_data->tx_dc_entries;
+ /* Internal SRAM only for now */
+ res->buffer_table_lim = 8192;
+ nic_data->tx_dc_base = 0x130000;
+ nic_data->rx_dc_base = 0x100000;
+
+ if (FALCON_IS_DUAL_FUNC(efx))
+ res->flags |= EFX_DL_FALCON_DUAL_FUNC;
+
+ if (EFX_INT_MODE_USE_MSI(efx))
+ res->flags |= EFX_DL_FALCON_USE_MSI;
+
+ return 0;
+}
+
/* Probe the NIC variant (revision, ASIC vs FPGA, function count, port
* count, port speed). Set workaround and feature flags accordingly. */
@@ -2477,6 +2556,10 @@ int falcon_probe_nic(struct efx_nic *efx)
if (rc)
goto fail5;
+ rc = falcon_dimension_resources(efx);
+ if (rc)
+ goto fail6;
+
/* Initialise I2C adapter */ efx->i2c_adap.owner = THIS_MODULE; efx->i2c_adap.class = I2C_CLASS_HWMON;
@@ -2487,10 +2570,12 @@ int falcon_probe_nic(struct efx_nic *efx)
strcpy(efx->i2c_adap.name, "SFC4000 GPIO");
rc = i2c_bit_add_bus(&efx->i2c_adap);
if (rc)
- goto fail5;
+ goto fail6;
return 0;
+ fail6:
+ efx->dl_info = NULL;
fail5:
falcon_free_buffer(efx, &efx->irq_status);
fail4:
@@ -2681,6 +2766,7 @@ void falcon_remove_nic(struct efx_nic *efx)
/* Tear down the private nic state */ kfree(efx->nic_data);
efx->nic_data = NULL;
+ efx->dl_info = NULL;
}
void falcon_update_nic_stats(struct efx_nic *efx)
drivers/net/sfc/net_driver.h +15 -0
@@ -30,6 +30,8 @@#include "enum.h" #include "bitfield.h" +#include "driverlink_api.h" +#include "driverlink.h" #define EFX_MAX_LRO_DESCRIPTORS 8#define EFX_MAX_LRO_AGGR MAX_SKB_FRAGS
@@ -674,6 +676,12 @@ union efx_multicast_hash {* @loopback_mode: Loopback status * @loopback_modes: Supported loopback mode bitmask * @loopback_selftest: Offline self-test private state +* @silicon_rev: Silicon revision description for driverlink +* @dl_info: Linked list of hardware parameters exposed through driverlink +* @dl_node: Driverlink port list +* @dl_device_list: Driverlink device list +* @dl_cb: Driverlink callbacks table +* @dl_cb_dev: Driverlink callback owner devices * * The @priv field of the corresponding &struct net_device points to * this.
@@ -749,6 +757,13 @@ struct efx_nic {unsigned int loopback_modes;void *loopback_selftest; + +const char *silicon_rev; +struct efx_dl_device_info *dl_info; +struct list_head dl_node; +struct list_head dl_device_list; +struct efx_dl_callbacks dl_cb; +struct efx_dl_cb_devices dl_cb_dev; };static inline int efx_dev_registered (struct efx_nic *efx)
Signature · 1 line
1.5.3.7