sfc: add sysfs entry to control MCDI tracing
authorEdward Cree <ecree@solarflare.com>
Wed, 27 May 2015 12:14:01 +0000 (13:14 +0100)
committerDavid S. Miller <davem@davemloft.net>
Wed, 27 May 2015 17:54:51 +0000 (13:54 -0400)
MCDI tracing is enabled per-function with a sysfs file
    /sys/class/net/<NET_DEV>/device/mcdi_logging

Signed-off-by: Edward Cree <ecree@solarflare.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/sfc/Kconfig
drivers/net/ethernet/sfc/efx.c
drivers/net/ethernet/sfc/mcdi.c
drivers/net/ethernet/sfc/mcdi.h

index c4ba42b1923f78c7b25210d04ff1c8dde9ccb5d4..4dd92b7b80f41d2e2c0591f9d3930a24ed6325be 100644 (file)
@@ -43,4 +43,5 @@ config SFC_MCDI_LOGGING
        ---help---
          This enables support for tracing of MCDI (Management-Controller-to-
          Driver-Interface) commands and responses, allowing debugging of
-         driver/firmware interaction.
+         driver/firmware interaction.  The tracing is actually enabled by
+         a sysfs file 'mcdi_logging' under the PCI device.
index 9eafa39d0e7fa1125cb844ac00fe9464eb324e64..2d4853c032c396b834c682757f60f111d8656942 100644 (file)
@@ -2326,6 +2326,28 @@ show_phy_type(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR(phy_type, 0444, show_phy_type, NULL);
 
+#ifdef CONFIG_SFC_MCDI_LOGGING
+static ssize_t show_mcdi_log(struct device *dev, struct device_attribute *attr,
+                            char *buf)
+{
+       struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+       struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", mcdi->logging_enabled);
+}
+static ssize_t set_mcdi_log(struct device *dev, struct device_attribute *attr,
+                           const char *buf, size_t count)
+{
+       struct efx_nic *efx = pci_get_drvdata(to_pci_dev(dev));
+       struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
+       bool enable = count > 0 && *buf != '0';
+
+       mcdi->logging_enabled = enable;
+       return count;
+}
+static DEVICE_ATTR(mcdi_logging, 0644, show_mcdi_log, set_mcdi_log);
+#endif
+
 static int efx_register_netdev(struct efx_nic *efx)
 {
        struct net_device *net_dev = efx->net_dev;
@@ -2383,9 +2405,21 @@ static int efx_register_netdev(struct efx_nic *efx)
                          "failed to init net dev attributes\n");
                goto fail_registered;
        }
+#ifdef CONFIG_SFC_MCDI_LOGGING
+       rc = device_create_file(&efx->pci_dev->dev, &dev_attr_mcdi_logging);
+       if (rc) {
+               netif_err(efx, drv, efx->net_dev,
+                         "failed to init net dev attributes\n");
+               goto fail_attr_mcdi_logging;
+       }
+#endif
 
        return 0;
 
+#ifdef CONFIG_SFC_MCDI_LOGGING
+fail_attr_mcdi_logging:
+       device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+#endif
 fail_registered:
        rtnl_lock();
        efx_dissociate(efx);
@@ -2404,13 +2438,14 @@ static void efx_unregister_netdev(struct efx_nic *efx)
 
        BUG_ON(netdev_priv(efx->net_dev) != efx);
 
-       strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
-       device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
-
-       rtnl_lock();
-       unregister_netdevice(efx->net_dev);
-       efx->state = STATE_UNINIT;
-       rtnl_unlock();
+       if (efx_dev_registered(efx)) {
+               strlcpy(efx->name, pci_name(efx->pci_dev), sizeof(efx->name));
+#ifdef CONFIG_SFC_MCDI_LOGGING
+               device_remove_file(&efx->pci_dev->dev, &dev_attr_mcdi_logging);
+#endif
+               device_remove_file(&efx->pci_dev->dev, &dev_attr_phy_type);
+               unregister_netdev(efx->net_dev);
+       }
 }
 
 /**************************************************************************
index 31eda32559669f512f15f25ed0b539ac3535ec22..dde7f901e16c9a1d75f36839fe6e341025e49c46 100644 (file)
@@ -188,7 +188,7 @@ static void efx_mcdi_send_request(struct efx_nic *efx, unsigned cmd,
        }
 
 #ifdef CONFIG_SFC_MCDI_LOGGING
-       if (!WARN_ON_ONCE(!buf)) {
+       if (mcdi->logging_enabled && !WARN_ON_ONCE(!buf)) {
                int bytes = 0;
                int i;
                /* Lengths should always be a whole number of dwords, so scream
@@ -274,7 +274,7 @@ static void efx_mcdi_read_response_header(struct efx_nic *efx)
        }
 
 #ifdef CONFIG_SFC_MCDI_LOGGING
-       if (!WARN_ON_ONCE(!buf)) {
+       if (mcdi->logging_enabled && !WARN_ON_ONCE(!buf)) {
                size_t hdr_len, data_len;
                int bytes = 0;
                int i;
index b783a2dff80f9825b8998151a4025d69b6bae20e..1838afe2da920c59f7ca43744c7a27a0f4e62a6c 100644 (file)
@@ -59,6 +59,7 @@ enum efx_mcdi_mode {
  * @async_list: Queue of asynchronous requests
  * @async_timer: Timer for asynchronous request timeout
  * @logging_buffer: buffer that may be used to build MCDI tracing messages
+ * @logging_enabled: whether to trace MCDI
  */
 struct efx_mcdi_iface {
        struct efx_nic *efx;
@@ -77,6 +78,7 @@ struct efx_mcdi_iface {
        struct timer_list async_timer;
 #ifdef CONFIG_SFC_MCDI_LOGGING
        char *logging_buffer;
+       bool logging_enabled;
 #endif
 };