mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-23 01:31:30 +03:00
nvethernet: dump HW features through debugfs
cat /sys/kernel/debug/nvethernet-<interface>/hw_features to dump the HW features Bug 200563382 Change-Id: Ifd8eab0564123d1f588241fbadb739e6ef553114 Signed-off-by: Bhadram Varka <vbhadram@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2338196 Reviewed-by: automaticguardword <automaticguardword@nvidia.com> Reviewed-by: Rakesh Goyal <rgoyal@nvidia.com> Reviewed-by: Bitan Biswas <bbiswas@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: Rakesh Goyal <rgoyal@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
committed by
Revanth Kumar Uppala
parent
d7e0d58393
commit
a921c9487b
@@ -4145,8 +4145,8 @@ static void init_filter_values(struct ether_priv_data *pdata)
|
||||
pdata->num_mac_addr_regs = ETHER_ADDR_REG_CNT_128;
|
||||
} else if (pdata->hw_feat.mac_addr32_sel == OSI_ENABLE) {
|
||||
pdata->num_mac_addr_regs = ETHER_ADDR_REG_CNT_64;
|
||||
} else if (pdata->hw_feat.mac_addr16_sel ==
|
||||
EQOS_MAC_HFR0_ADDMACADRSEL_MASK) {
|
||||
} else if (pdata->hw_feat.mac_addr_sel ==
|
||||
(ETHER_ADDR_REG_CNT_32 - 1U)) {
|
||||
pdata->num_mac_addr_regs = ETHER_ADDR_REG_CNT_32;
|
||||
} else {
|
||||
pdata->num_mac_addr_regs = ETHER_ADDR_REG_CNT_1;
|
||||
@@ -4320,19 +4320,20 @@ static int ether_probe(struct platform_device *pdev)
|
||||
ether_tx_usecs_hrtimer;
|
||||
}
|
||||
|
||||
ret = register_netdev(ndev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to register netdev\n");
|
||||
goto err_netdev;
|
||||
}
|
||||
|
||||
/* Register sysfs entry */
|
||||
ret = ether_sysfs_register(pdata->dev);
|
||||
ret = ether_sysfs_register(pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev,
|
||||
"failed to create nvethernet sysfs group\n");
|
||||
goto err_sysfs;
|
||||
}
|
||||
|
||||
ret = register_netdev(ndev);
|
||||
if (ret < 0) {
|
||||
dev_err(&pdev->dev, "failed to register netdev\n");
|
||||
goto err_netdev;
|
||||
}
|
||||
|
||||
spin_lock_init(&pdata->rlock);
|
||||
init_filter_values(pdata);
|
||||
@@ -4351,9 +4352,9 @@ static int ether_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
err_netdev:
|
||||
ether_sysfs_unregister(pdata->dev);
|
||||
err_sysfs:
|
||||
unregister_netdev(ndev);
|
||||
err_netdev:
|
||||
err_napi:
|
||||
mdiobus_unregister(pdata->mii);
|
||||
err_dma_mask:
|
||||
@@ -4388,7 +4389,7 @@ static int ether_remove(struct platform_device *pdev)
|
||||
unregister_netdev(ndev);
|
||||
|
||||
/* remove nvethernet sysfs group under /sys/devices/<ether_device>/ */
|
||||
ether_sysfs_unregister(pdata->dev);
|
||||
ether_sysfs_unregister(pdata);
|
||||
|
||||
if (pdata->mii != NULL) {
|
||||
mdiobus_unregister(pdata->mii);
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/of_mdio.h>
|
||||
#include <linux/if_vlan.h>
|
||||
#include <linux/thermal.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/reset.h>
|
||||
@@ -372,6 +373,12 @@ struct ether_priv_data {
|
||||
#endif
|
||||
/** VM channel info data associated with VM IRQ */
|
||||
struct ether_vm_irq_data *vm_irq_data;
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/** Debug fs directory pointer */
|
||||
struct dentry *dbgfs_dir;
|
||||
/** HW features dump debug fs pointer */
|
||||
struct dentry *dbgfs_hw_feat;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -385,21 +392,21 @@ void ether_set_ethtool_ops(struct net_device *ndev);
|
||||
/**
|
||||
* @brief Creates Ethernet sysfs group
|
||||
*
|
||||
* @param[in] dev: device instance
|
||||
* @param[in] pdata: Ethernet driver private data
|
||||
*
|
||||
* @retval 0 - success,
|
||||
* @retval "negative value" - failure.
|
||||
*/
|
||||
int ether_sysfs_register(struct device *dev);
|
||||
int ether_sysfs_register(struct ether_priv_data *pdata);
|
||||
|
||||
/**
|
||||
* @brief Removes Ethernet sysfs group
|
||||
*
|
||||
* @param[in] dev: device instance
|
||||
* @param[in] pdata: Ethernet driver private data
|
||||
*
|
||||
* @note nvethernet sysfs group need to be registered during probe.
|
||||
*/
|
||||
void ether_sysfs_unregister(struct device *dev);
|
||||
void ether_sysfs_unregister(struct ether_priv_data *pdata);
|
||||
|
||||
/**
|
||||
* @brief Function to register ptp clock driver
|
||||
|
||||
@@ -133,14 +133,456 @@ static struct attribute_group ether_attribute_group = {
|
||||
.attrs = ether_sysfs_attrs,
|
||||
};
|
||||
|
||||
int ether_sysfs_register(struct device *dev)
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
static char *timestamp_system_source(unsigned int source)
|
||||
{
|
||||
switch (source) {
|
||||
case 1:
|
||||
return "Internal";
|
||||
case 2:
|
||||
return "External";
|
||||
case 3:
|
||||
return "Internal and External";
|
||||
case 0:
|
||||
return "Reserved";
|
||||
}
|
||||
|
||||
return "None";
|
||||
}
|
||||
|
||||
static char *active_phy_selected_interface(unsigned int act_phy_sel)
|
||||
{
|
||||
switch (act_phy_sel) {
|
||||
case 0:
|
||||
return "GMII or MII";
|
||||
case 1:
|
||||
return "RGMII";
|
||||
case 2:
|
||||
return "SGMII";
|
||||
case 3:
|
||||
return "TBI";
|
||||
case 4:
|
||||
return "RMII";
|
||||
case 5:
|
||||
return "RTBI";
|
||||
case 6:
|
||||
return "SMII";
|
||||
case 7:
|
||||
return "RevMII";
|
||||
}
|
||||
|
||||
return "None";
|
||||
}
|
||||
|
||||
static char *mtl_fifo_size(unsigned int fifo_size)
|
||||
{
|
||||
switch (fifo_size) {
|
||||
case 0:
|
||||
return "128 Bytes";
|
||||
case 1:
|
||||
return "256 Bytes";
|
||||
case 2:
|
||||
return "512 Bytes";
|
||||
case 3:
|
||||
return "1KB";
|
||||
case 4:
|
||||
return "2KB";
|
||||
case 5:
|
||||
return "4KB";
|
||||
case 6:
|
||||
return "8KB";
|
||||
case 7:
|
||||
return "16KB";
|
||||
case 8:
|
||||
return "32KB";
|
||||
case 9:
|
||||
return "64KB";
|
||||
case 10:
|
||||
return "128KB";
|
||||
case 11:
|
||||
return "256KB";
|
||||
default:
|
||||
return "Reserved";
|
||||
}
|
||||
}
|
||||
|
||||
static char *address_width(unsigned int val)
|
||||
{
|
||||
switch (val) {
|
||||
case 0:
|
||||
return "32";
|
||||
case 1:
|
||||
return "40";
|
||||
case 2:
|
||||
return "48";
|
||||
default:
|
||||
return "Reserved";
|
||||
}
|
||||
}
|
||||
|
||||
static char *hash_table_size(unsigned int size)
|
||||
{
|
||||
switch (size) {
|
||||
case 0:
|
||||
return "No Hash Table";
|
||||
case 1:
|
||||
return "64";
|
||||
case 2:
|
||||
return "128";
|
||||
case 3:
|
||||
return "256";
|
||||
default:
|
||||
return "Invalid size";
|
||||
}
|
||||
}
|
||||
|
||||
static char *num_vlan_filters(unsigned int filters)
|
||||
{
|
||||
switch (filters) {
|
||||
case 0:
|
||||
return "Zero";
|
||||
case 1:
|
||||
return "4";
|
||||
case 2:
|
||||
return "8";
|
||||
case 3:
|
||||
return "16";
|
||||
case 4:
|
||||
return "24";
|
||||
case 5:
|
||||
return "32";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
static char *max_frp_bytes(unsigned int bytes)
|
||||
{
|
||||
switch (bytes) {
|
||||
case 0:
|
||||
return "64 Bytes";
|
||||
case 1:
|
||||
return "128 Bytes";
|
||||
case 2:
|
||||
return "256 Bytes";
|
||||
case 3:
|
||||
return "Reserved";
|
||||
default:
|
||||
return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
static char *max_frp_instructions(unsigned int entries)
|
||||
{
|
||||
switch (entries) {
|
||||
case 0:
|
||||
return "64";
|
||||
case 1:
|
||||
return "128";
|
||||
case 2:
|
||||
return "256";
|
||||
case 3:
|
||||
return "Reserved";
|
||||
default:
|
||||
return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
static char *auto_safety_package(unsigned int pkg)
|
||||
{
|
||||
switch (pkg) {
|
||||
case 0:
|
||||
return "No Safety features selected";
|
||||
case 1:
|
||||
return "Only 'ECC protection for external memory' feature is selected";
|
||||
case 2:
|
||||
return "All the Automotive Safety features are selected without the 'Parity Port Enable for external interface' feature";
|
||||
case 3:
|
||||
return "All the Automotive Safety features are selected with the 'Parity Port Enable for external interface' feature";
|
||||
default:
|
||||
return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
static char *tts_fifo_depth(unsigned int depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 1:
|
||||
return "1";
|
||||
case 2:
|
||||
return "2";
|
||||
case 3:
|
||||
return "4";
|
||||
case 4:
|
||||
return "8";
|
||||
case 5:
|
||||
return "16";
|
||||
default:
|
||||
return "Reserved";
|
||||
}
|
||||
}
|
||||
|
||||
static char *gate_ctl_depth(unsigned int depth)
|
||||
{
|
||||
switch (depth) {
|
||||
case 0:
|
||||
return "No Depth Configured";
|
||||
case 1:
|
||||
return "64";
|
||||
case 2:
|
||||
return "128";
|
||||
case 3:
|
||||
return "256";
|
||||
case 4:
|
||||
return "512";
|
||||
case 5:
|
||||
return "1024";
|
||||
default:
|
||||
return "Reserved";
|
||||
}
|
||||
}
|
||||
|
||||
static char *gate_ctl_width(unsigned int width)
|
||||
{
|
||||
switch (width) {
|
||||
case 0:
|
||||
return "Width not configured";
|
||||
case 1:
|
||||
return "16";
|
||||
case 2:
|
||||
return "20";
|
||||
case 3:
|
||||
return "24";
|
||||
default:
|
||||
return "Invalid";
|
||||
}
|
||||
}
|
||||
|
||||
static int ether_hw_features_read(struct seq_file *seq, void *v)
|
||||
{
|
||||
struct net_device *ndev = seq->private;
|
||||
struct ether_priv_data *pdata = netdev_priv(ndev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
struct osi_hw_features *hw_feat = &pdata->hw_feat;
|
||||
|
||||
if (!netif_running(ndev)) {
|
||||
dev_err(pdata->dev, "Not Allowed. Ether interface is not up\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
seq_printf(seq, "==============================\n");
|
||||
seq_printf(seq, "\tHW features\n");
|
||||
seq_printf(seq, "==============================\n");
|
||||
|
||||
seq_printf(seq, "\t10/100 Mbps: %s\n",
|
||||
(hw_feat->mii_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tRGMII Mode: %s\n",
|
||||
(hw_feat->rgmii_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tRMII Mode: %s\n",
|
||||
(hw_feat->rmii_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\t1000 Mpbs: %s\n",
|
||||
(hw_feat->gmii_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tHalf duplex support: %s\n",
|
||||
(hw_feat->hd_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tTBI/SGMII/RTBI PHY interface: %s\n",
|
||||
(hw_feat->pcs_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tVLAN Hash Filtering: %s\n",
|
||||
(hw_feat->vlan_hash_en) ? "Y" : "N");
|
||||
seq_printf(seq, "\tMDIO interface: %s\n",
|
||||
(hw_feat->sma_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tRemote Wake-Up Packet Detection: %s\n",
|
||||
(hw_feat->rwk_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tMagic Packet Detection: %s\n",
|
||||
(hw_feat->mgk_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tMAC Management Counters (MMC): %s\n",
|
||||
(hw_feat->mmc_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tARP Offload: %s\n",
|
||||
(hw_feat->arp_offld_en) ? "Y" : "N");
|
||||
seq_printf(seq, "\tIEEE 1588 Timestamp Support: %s\n",
|
||||
(hw_feat->ts_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tEnergy Efficient Ethernet (EEE) Support: %s\n",
|
||||
(hw_feat->eee_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tTransmit TCP/IP Checksum Insertion Support: %s\n",
|
||||
(hw_feat->tx_coe_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tReceive TCP/IP Checksum Support: %s\n",
|
||||
(hw_feat->rx_coe_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\t (1 - 31) MAC Address registers: %s\n",
|
||||
(hw_feat->mac_addr_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\t(32 - 63) MAC Address Registers: %s\n",
|
||||
(hw_feat->mac_addr32_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\t(64 - 127) MAC Address Registers: %s\n",
|
||||
(hw_feat->mac_addr64_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tTimestamp System Time Source: %s\n",
|
||||
timestamp_system_source(hw_feat->tsstssel));
|
||||
seq_printf(seq, "\tSource Address or VLAN Insertion Enable: %s\n",
|
||||
(hw_feat->sa_vlan_ins) ? "Y" : "N");
|
||||
seq_printf(seq, "\tActive PHY selected Interface: %s\n",
|
||||
active_phy_selected_interface(hw_feat->sa_vlan_ins));
|
||||
seq_printf(seq, "\tVxLAN/NVGRE Support: %s\n",
|
||||
(hw_feat->vxn) ? "Y" : "N");
|
||||
seq_printf(seq, "\tDifferent Descriptor Cache Support: %s\n",
|
||||
(hw_feat->ediffc) ? "Y" : "N");
|
||||
seq_printf(seq, "\tEnhanced DMA Support: %s\n",
|
||||
(hw_feat->edma) ? "Y" : "N");
|
||||
seq_printf(seq, "\tMTL Receive FIFO Size: %s\n",
|
||||
mtl_fifo_size(hw_feat->rx_fifo_size));
|
||||
seq_printf(seq, "\tMTL Transmit FIFO Size: %s\n",
|
||||
mtl_fifo_size(hw_feat->tx_fifo_size));
|
||||
seq_printf(seq, "\tPFC Enable: %s\n",
|
||||
(hw_feat->pfc_en) ? "Y" : "N");
|
||||
seq_printf(seq, "\tOne-Step Timestamping Support: %s\n",
|
||||
(hw_feat->ost_en) ? "Y" : "N");
|
||||
seq_printf(seq, "\tPTP Offload Enable: %s\n",
|
||||
(hw_feat->pto_en) ? "Y" : "N");
|
||||
seq_printf(seq, "\tIEEE 1588 High Word Register Enable: %s\n",
|
||||
(hw_feat->adv_ts_hword) ? "Y" : "N");
|
||||
seq_printf(seq, "\tAXI Address width: %s\n",
|
||||
address_width(hw_feat->addr_64));
|
||||
seq_printf(seq, "\tDCB Feature Support: %s\n",
|
||||
(hw_feat->dcb_en) ? "Y" : "N");
|
||||
seq_printf(seq, "\tSplit Header Feature Support: %s\n",
|
||||
(hw_feat->sph_en) ? "Y" : "N");
|
||||
seq_printf(seq, "\tTCP Segmentation Offload Support: %s\n",
|
||||
(hw_feat->tso_en) ? "Y" : "N");
|
||||
seq_printf(seq, "\tDMA Debug Registers Enable: %s\n",
|
||||
(hw_feat->dma_debug_gen) ? "Y" : "N");
|
||||
seq_printf(seq, "\tAV Feature Enable: %s\n",
|
||||
(hw_feat->av_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tRx Side Only AV Feature Enable: %s\n",
|
||||
(hw_feat->rav_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tHash Table Size: %s\n",
|
||||
hash_table_size(hw_feat->hash_tbl_sz));
|
||||
seq_printf(seq, "\tTotal number of L3 or L4 Filters: %u\n",
|
||||
hw_feat->l3l4_filter_num);
|
||||
seq_printf(seq, "\tNumber of MTL Receive Queues: %u\n",
|
||||
(hw_feat->rx_q_cnt + 1));
|
||||
seq_printf(seq, "\tNumber of MTL Transmit Queues: %u\n",
|
||||
(hw_feat->tx_q_cnt + 1));
|
||||
seq_printf(seq, "\tNumber of Receive DMA channels: %u\n",
|
||||
(hw_feat->rx_ch_cnt + 1));
|
||||
seq_printf(seq, "\tNumber of Transmit DMA channels: %u\n",
|
||||
(hw_feat->tx_ch_cnt + 1));
|
||||
seq_printf(seq, "\tNumber of PPS outputs: %u\n",
|
||||
hw_feat->pps_out_num);
|
||||
seq_printf(seq, "\tNumber of Auxiliary Snapshot Inputs: %u\n",
|
||||
hw_feat->aux_snap_num);
|
||||
seq_printf(seq, "\tRSS Feature Enabled: %s\n",
|
||||
(hw_feat->rss_en) ? "Y" : "N");
|
||||
seq_printf(seq, "\tNumber of Traffic Classes: %u\n",
|
||||
(hw_feat->num_tc + 1));
|
||||
seq_printf(seq, "\tNumber of VLAN filters: %s\n",
|
||||
num_vlan_filters(hw_feat->num_vlan_filters));
|
||||
seq_printf(seq,
|
||||
"\tQueue/Channel based VLAN tag insert on Tx Enable: %s\n",
|
||||
(hw_feat->cbti_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tOne-Step for PTP over UDP/IP Feature Enable: %s\n",
|
||||
(hw_feat->ost_over_udp) ? "Y" : "N");
|
||||
seq_printf(seq, "\tDouble VLAN processing support: %s\n",
|
||||
(hw_feat->double_vlan_en) ? "Y" : "N");
|
||||
|
||||
if (osi_core->mac_ver > OSI_EQOS_MAC_5_00) {
|
||||
seq_printf(seq, "\tSupported Flexible Receive Parser: %s\n",
|
||||
(hw_feat->frp_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tNumber of FRP Pipes: %u\n",
|
||||
(hw_feat->num_frp_pipes + 1));
|
||||
seq_printf(seq, "\tNumber of FRP Parsable Bytes: %s\n",
|
||||
max_frp_bytes(hw_feat->max_frp_bytes));
|
||||
seq_printf(seq, "\tNumber of FRP Instructions: %s\n",
|
||||
max_frp_instructions(hw_feat->max_frp_entries));
|
||||
seq_printf(seq, "\tAutomotive Safety Package: %s\n",
|
||||
auto_safety_package(hw_feat->auto_safety_pkg));
|
||||
seq_printf(seq, "\tTx Timestamp FIFO Depth: %s\n",
|
||||
tts_fifo_depth(hw_feat->tts_fifo_depth));
|
||||
seq_printf(seq, "\tEnhancements to Scheduling Traffic Support: %s\n",
|
||||
(hw_feat->est_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tDepth of the Gate Control List: %s\n",
|
||||
gate_ctl_depth(hw_feat->gcl_depth));
|
||||
seq_printf(seq, "\tWidth of the Time Interval field in GCL: %s\n",
|
||||
gate_ctl_width(hw_feat->gcl_width));
|
||||
seq_printf(seq, "\tFrame Preemption Enable: %s\n",
|
||||
(hw_feat->fpe_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tTime Based Scheduling Enable: %s\n",
|
||||
(hw_feat->tbs_sel) ? "Y" : "N");
|
||||
seq_printf(seq, "\tNumber of DMA channels enabled for TBS: %u\n",
|
||||
(hw_feat->num_tbs_ch + 1));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ether_hw_feat_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, ether_hw_features_read, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations ether_hw_features_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = ether_hw_feat_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int ether_create_debugfs(struct ether_priv_data *pdata)
|
||||
{
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
|
||||
buf = kasprintf(GFP_KERNEL, "nvethernet-%s", pdata->ndev->name);
|
||||
if (!buf)
|
||||
return -ENOMEM;
|
||||
|
||||
pdata->dbgfs_dir = debugfs_create_dir(buf, NULL);
|
||||
if (!pdata->dbgfs_dir || IS_ERR(pdata->dbgfs_dir)) {
|
||||
netdev_err(pdata->ndev,
|
||||
"failed to create debugfs directory\n");
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
pdata->dbgfs_hw_feat = debugfs_create_file("hw_features", S_IRUGO,
|
||||
pdata->dbgfs_dir, pdata->ndev,
|
||||
ðer_hw_features_fops);
|
||||
if (!pdata->dbgfs_hw_feat) {
|
||||
netdev_err(pdata->ndev,
|
||||
"failed to create HW features debugfs\n");
|
||||
debugfs_remove_recursive(pdata->dbgfs_dir);
|
||||
ret = -ENOMEM;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
kfree(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ether_remove_debugfs(struct ether_priv_data *pdata)
|
||||
{
|
||||
debugfs_remove_recursive(pdata->dbgfs_dir);
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS */
|
||||
|
||||
int ether_sysfs_register(struct ether_priv_data *pdata)
|
||||
{
|
||||
struct device *dev = pdata->dev;
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
ret = ether_create_debugfs(pdata);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
#endif
|
||||
/* Create nvethernet sysfs group under /sys/devices/<ether_device>/ */
|
||||
return sysfs_create_group(&dev->kobj, ðer_attribute_group);
|
||||
}
|
||||
|
||||
void ether_sysfs_unregister(struct device *dev)
|
||||
void ether_sysfs_unregister(struct ether_priv_data *pdata)
|
||||
{
|
||||
struct device *dev = pdata->dev;
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
ether_remove_debugfs(pdata);
|
||||
#endif
|
||||
/* Remove nvethernet sysfs group under /sys/devices/<ether_device>/ */
|
||||
sysfs_remove_group(&dev->kobj, ðer_attribute_group);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user