diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index b92af3735dd4..3d8b8e0f2438 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -11,6 +11,7 @@ #define __QETH_CORE_H__ #include +#include #include #include #include @@ -797,6 +798,7 @@ struct qeth_card { struct qeth_channel data; struct net_device *dev; + struct dentry *debugfs; struct qeth_card_stats stats; struct qeth_card_info info; struct qeth_token token; diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 6b5d42a4501c..771282cb7aef 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -61,6 +61,7 @@ EXPORT_SYMBOL_GPL(qeth_core_header_cache); static struct kmem_cache *qeth_qdio_outbuf_cache; static struct device *qeth_core_root_dev; +static struct dentry *qeth_debugfs_root; static struct lock_class_key qdio_out_skb_queue_key; static void qeth_issue_next_read_cb(struct qeth_card *card, @@ -805,6 +806,24 @@ static void qeth_del_local_addrs6(struct qeth_card *card, spin_unlock(&card->local_addrs6_lock); } +static int qeth_debugfs_local_addr_show(struct seq_file *m, void *v) +{ + struct qeth_card *card = m->private; + struct qeth_local_addr *tmp; + unsigned int i; + + rcu_read_lock(); + hash_for_each_rcu(card->local_addrs4, i, tmp, hnode) + seq_printf(m, "%pI4\n", &tmp->addr.s6_addr32[3]); + hash_for_each_rcu(card->local_addrs6, i, tmp, hnode) + seq_printf(m, "%pI6c\n", &tmp->addr); + rcu_read_unlock(); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(qeth_debugfs_local_addr); + static void qeth_issue_ipa_msg(struct qeth_ipa_cmd *cmd, int rc, struct qeth_card *card) { @@ -1608,6 +1627,11 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev) if (!card->read_cmd) goto out_read_cmd; + card->debugfs = debugfs_create_dir(dev_name(&gdev->dev), + qeth_debugfs_root); + debugfs_create_file("local_addrs", 0400, card->debugfs, card, + &qeth_debugfs_local_addr_fops); + card->qeth_service_level.seq_print = qeth_core_sl_print; register_service_level(&card->qeth_service_level); return card; @@ -5085,9 +5109,11 @@ out_free_nothing: static void qeth_core_free_card(struct qeth_card *card) { QETH_CARD_TEXT(card, 2, "freecrd"); + + unregister_service_level(&card->qeth_service_level); + debugfs_remove_recursive(card->debugfs); qeth_put_cmd(card->read_cmd); destroy_workqueue(card->event_wq); - unregister_service_level(&card->qeth_service_level); dev_set_drvdata(&card->gdev->dev, NULL); kfree(card); } @@ -6967,6 +6993,8 @@ static int __init qeth_core_init(void) pr_info("loading core functions\n"); + qeth_debugfs_root = debugfs_create_dir("qeth", NULL); + rc = qeth_register_dbf_views(); if (rc) goto dbf_err; @@ -7008,6 +7036,7 @@ slab_err: register_err: qeth_unregister_dbf_views(); dbf_err: + debugfs_remove_recursive(qeth_debugfs_root); pr_err("Initializing the qeth device driver failed\n"); return rc; } @@ -7021,6 +7050,7 @@ static void __exit qeth_core_exit(void) kmem_cache_destroy(qeth_core_header_cache); root_device_unregister(qeth_core_root_dev); qeth_unregister_dbf_views(); + debugfs_remove_recursive(qeth_debugfs_root); pr_info("core functions removed\n"); }