From patchwork Tue Oct 12 01:07:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sui Chen X-Patchwork-Id: 1539551 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20210112 header.b=JaZ79AYY; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4HSyGM6NcNz9ssD for ; Tue, 12 Oct 2021 12:08:27 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232086AbhJLBK1 (ORCPT ); Mon, 11 Oct 2021 21:10:27 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47836 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230074AbhJLBK1 (ORCPT ); Mon, 11 Oct 2021 21:10:27 -0400 Received: from mail-lf1-x129.google.com (mail-lf1-x129.google.com [IPv6:2a00:1450:4864:20::129]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B2003C06161C for ; Mon, 11 Oct 2021 18:08:24 -0700 (PDT) Received: by mail-lf1-x129.google.com with SMTP id j5so80777703lfg.8 for ; Mon, 11 Oct 2021 18:08:23 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=mime-version:from:date:message-id:subject:to; bh=TwOeLnfWWv7fat9oyQdft7/MoLdXXciyS6TClTMDJ9w=; b=JaZ79AYYL7b6mmQgx31ARu0GMTLokVxT6kbH8SBj2AxS/eu52gsFrxPxDaFEZUZFmr dyD0OvIJNvITCLVns/8upeu9onJdgKAFEBomfL+YYpnJcEUqOAjv5XlT84piop7ilzuv GKFeQOKbuBBiOWQ18Imk2/6Uh/1oooX1jZ8n3j8jc63H0r3h0aD5x6DVVudFp6a0lSM0 ameAhEZm1XIpnBmf42SOCKkVqbUaClBtqI2hqQ1NNdbhqa5C+s2hOcH4dBhqDmlBzl6i 97rle4qNRn9gwcTvBSWLOXW63maNScylaDRcUkscmxcA+JHom8DGzOgkYEfuJUFydw23 LRPg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=TwOeLnfWWv7fat9oyQdft7/MoLdXXciyS6TClTMDJ9w=; b=EXNyWZZ9Li7wXAI9mic8xNScnxNvTLMaDHgVPzMrUW5bFF9nTJc29QsqW8ef8pKv12 Xl6nVeHOG0seguloM0G6QiNp3AOvUGQKf1dJDkkIGPMXHKKfqP/u4pe3KBVnuuaSMGvq zebb6LAMr/xDisch45nkz/er28Vspkil517ut7Ln/YSoIJrSMNMExOBuPLs7IrDh2J7Z OYew0fKGmkLIxwub0gQy4F0qKbvk3nBt83XBh6b4AIgyJ/gqQKFIewSc45vsr5CmXKkK sEhxoOajOb64+LGgvM4MZZyfnJCpJ8BP/VC+OMYZW391Uh5xfdjXmM6vM6kSaNGfEzTQ 8W1A== X-Gm-Message-State: AOAM531vhZKDGRLFTzopKjftlDYzXkz7EwBMptyviCfAaJjsh7OKeNGY TIerE0dgqD64zlQaVGCUHAct7hwzSZoexIDZPsf8kpC8W2c9/A== X-Google-Smtp-Source: ABdhPJzTqv/qZ777zf0gw//q5BDpSAbcPtykoNv8BSKvuAp8hJ5OevDHkgRwsOipASnguHWN7TeHgSEz/u0c3T/6tDE= X-Received: by 2002:a05:6512:ea1:: with SMTP id bi33mr12669706lfb.287.1634000888784; Mon, 11 Oct 2021 18:08:08 -0700 (PDT) MIME-Version: 1.0 From: Sui Chen Date: Mon, 11 Oct 2021 18:07:56 -0700 Message-ID: Subject: [RFC Patch 1/2] i2c debug counters as sysfs attributes To: linux-i2c@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org This change adds a few example I2C debug counters as sysfs attributes: - ber_cnt (bus error count) - nack_cnt (NACK count) - rec_fail_cnt, rec_succ_cnt (recovery failure/success count) - timeout_cnt (timeout count) - i2c_speed (bus frequency) The function i2c_adapter_create_stats_folder creates a stats directory in the device's sysfs directory to hold the debug counters. The platform drivers will instantiate the counters in the stats directory if available. Signed-off-by: Sui Chen --- drivers/i2c/i2c-core-base.c | 3 ++ drivers/i2c/i2c-dev.c | 99 +++++++++++++++++++++++++++++++++++++ include/linux/i2c.h | 21 ++++++++ 3 files changed, 123 insertions(+) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 84f12bf90644a..ca4ef4d8b1799 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -1610,6 +1610,9 @@ static int i2c_register_adapter(struct i2c_adapter *adap) bus_for_each_drv(&i2c_bus_type, NULL, adap, __process_new_adapter); mutex_unlock(&core_lock); + /* Create a statistics folder for this i2c-adapter */ + i2c_adapter_create_stats_folder(adap); + return 0; out_reg: diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 77f576e516522..1f29beb7b8eab 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c @@ -767,6 +767,105 @@ static void __exit i2c_dev_exit(void) unregister_chrdev_region(MKDEV(I2C_MAJOR, 0), I2C_MINORS); } + +static struct i2c_adapter* kobj_to_adapter(struct device* pdev) { + struct kobject* dev_kobj = ((struct kobject*)pdev)->parent; + struct device* dev = container_of(dev_kobj, struct device, kobj); + return to_i2c_adapter(dev); +} + +static ssize_t ber_cnt_show(struct device* pdev, + struct device_attribute* attr, char* buf) { + u64* ber_cnt = kobj_to_adapter(pdev)->stats->ber_cnt; + if (ber_cnt == NULL) return 0; + ssize_t ret = sprintf(buf, "%llu\n", *ber_cnt); + return ret; +} +DEVICE_ATTR_RO(ber_cnt); + +ssize_t nack_cnt_show(struct device* pdev, + struct device_attribute* attr, char* buf) { + u64* nack_cnt = kobj_to_adapter(pdev)->stats->nack_cnt; + if (nack_cnt == NULL) return 0; + ssize_t ret = sprintf(buf, "%llu\n", *nack_cnt); + return ret; +} +DEVICE_ATTR_RO(nack_cnt); + +ssize_t rec_succ_cnt_show(struct device* pdev, + struct device_attribute* attr, char* buf) { + u64* rec_succ_cnt = kobj_to_adapter(pdev)->stats->rec_succ_cnt; + if (rec_succ_cnt == NULL) return 0; + ssize_t ret = sprintf(buf, "%llu\n", *rec_succ_cnt); + return ret; +} +DEVICE_ATTR_RO(rec_succ_cnt); + +ssize_t rec_fail_cnt_show(struct device* pdev, + struct device_attribute* attr, char* buf) { + u64* rec_fail_cnt = kobj_to_adapter(pdev)->stats->rec_fail_cnt; + if (rec_fail_cnt == NULL) return 0; + ssize_t ret = sprintf(buf, "%llu\n", *rec_fail_cnt); + return ret; +} +DEVICE_ATTR_RO(rec_fail_cnt); + +ssize_t timeout_cnt_show(struct device* pdev, + struct device_attribute* attr, char* buf) { + u64* timeout_cnt = kobj_to_adapter(pdev)->stats->timeout_cnt; + if (timeout_cnt == NULL) return 0; + ssize_t ret = sprintf(buf, "%llu\n", *timeout_cnt); + return ret; +} +DEVICE_ATTR_RO(timeout_cnt); + +ssize_t i2c_speed_show(struct device* pdev, + struct device_attribute* attr, char* buf) { + u64* i2c_speed = kobj_to_adapter(pdev)->stats->i2c_speed; + if (i2c_speed == NULL) return 0; + ssize_t ret = sprintf(buf, "%llu\n", *i2c_speed); + return ret; +} +DEVICE_ATTR_RO(i2c_speed); + +void i2c_adapter_create_stats_folder(struct i2c_adapter* adapter) { + adapter->stats = kzalloc(sizeof(struct i2c_adapter_stats), GFP_KERNEL); + adapter->stats->kobj = kobject_create_and_add("stats", &adapter->dev.kobj);; +} + +void i2c_adapter_stats_register_counter(struct i2c_adapter* adapter, + const char* counter_name, void* data_source) { + int ret; + if (adapter->stats == NULL) { + i2c_adapter_create_stats_folder(adapter); + } + + if (!strcmp(counter_name, "ber_cnt")) { + adapter->stats->ber_cnt = data_source; + ret = sysfs_create_file(adapter->stats->kobj, &dev_attr_ber_cnt.attr); + } else if (!strcmp(counter_name, "nack_cnt")) { + adapter->stats->nack_cnt = data_source; + ret = sysfs_create_file(adapter->stats->kobj, &dev_attr_nack_cnt.attr); + } else if (!strcmp(counter_name, "rec_succ_cnt")) { + adapter->stats->rec_succ_cnt = data_source; + ret = sysfs_create_file(adapter->stats->kobj, &dev_attr_rec_succ_cnt.attr); + } else if (!strcmp(counter_name, "rec_fail_cnt")) { + adapter->stats->rec_fail_cnt = data_source; + ret = sysfs_create_file(adapter->stats->kobj, &dev_attr_rec_fail_cnt.attr); + } else if (!strcmp(counter_name, "timeout_cnt")) { + adapter->stats->timeout_cnt = data_source; + ret = sysfs_create_file(adapter->stats->kobj, &dev_attr_timeout_cnt.attr); + } else if (!strcmp(counter_name, "i2c_speed")) { + adapter->stats->i2c_speed = data_source; + ret = sysfs_create_file(adapter->stats->kobj, &dev_attr_i2c_speed.attr); + } + + if (ret) { + printk("Failed to create sysfs file for %s", counter_name); + } +} + + MODULE_AUTHOR("Frodo Looijaard "); MODULE_AUTHOR("Simon G. Vogl "); MODULE_DESCRIPTION("I2C /dev entries driver"); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 3eb60a2e9e618..4267541660074 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -21,6 +21,7 @@ #include /* for struct device_node */ #include /* for swab16 */ #include +#include /* for kzalloc */ extern struct bus_type i2c_bus_type; extern struct device_type i2c_adapter_type; @@ -684,6 +685,21 @@ struct i2c_adapter_quirks { u16 max_comb_2nd_msg_len; }; +/** + * I2C statistics + * The list of statistics are currently copied from npcm7xx. + * Perhaps a more universal set of statistics can be used. + */ +struct i2c_adapter_stats { + struct kobject* kobj; + u64* ber_cnt; + u64* nack_cnt; + u64* rec_succ_cnt; + u64* rec_fail_cnt; + u64* timeout_cnt; + u64* i2c_speed; +}; + /* enforce max_num_msgs = 2 and use max_comb_*_len for length checks */ #define I2C_AQ_COMB BIT(0) /* first combined message must be write */ @@ -735,12 +751,17 @@ struct i2c_adapter { struct i2c_bus_recovery_info *bus_recovery_info; const struct i2c_adapter_quirks *quirks; + struct i2c_adapter_stats* stats; struct irq_domain *host_notify_domain; struct regulator *bus_regulator; }; #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) +void i2c_adapter_create_stats_folder(struct i2c_adapter* adapter); +void i2c_adapter_stats_register_counter(struct i2c_adapter* adapter, + const char* counter_name, void* data_source); + static inline void *i2c_get_adapdata(const struct i2c_adapter *adap) { return dev_get_drvdata(&adap->dev); From patchwork Tue Oct 12 01:08:16 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sui Chen X-Patchwork-Id: 1539553 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.a=rsa-sha256 header.s=20210112 header.b=BHyOda20; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org (client-ip=23.128.96.18; helo=vger.kernel.org; envelope-from=linux-i2c-owner@vger.kernel.org; receiver=) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by bilbo.ozlabs.org (Postfix) with ESMTP id 4HSyGv3s6Rz9ssD for ; Tue, 12 Oct 2021 12:08:55 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231199AbhJLBKz (ORCPT ); Mon, 11 Oct 2021 21:10:55 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47942 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230074AbhJLBKz (ORCPT ); Mon, 11 Oct 2021 21:10:55 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id AD2FBC061570 for ; Mon, 11 Oct 2021 18:08:53 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id u18so80393560lfd.12 for ; Mon, 11 Oct 2021 18:08:53 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20210112; h=mime-version:from:date:message-id:subject:to; bh=9HcOVr8JD61cbEk0dQbFXubvFww54VrmGyyOpCRyVXc=; b=BHyOda20zyDEXOXBUvqbHt94HRTkDaOhU190MxEcDj0RslE6dILpEnR7ie/2pSSz50 4sK4ADM15RsiyJF95Hi4CKVBzKpQbvCCgGlcIPt4LUwvR5M8YyjmYJgHVBYTylm9wbWw NpSWKi9dMeIpV9O+88tqxLAoTWV/ZAtVZWWkCuWrttShreqh25qc4KX3g4OxGhiJAC8Q jCDdPz1pEECZTmJoKU/AjzkGneSqokOzIHEq+nZwLdkmRssEGoi/eHUPsAoD4jzUk+HN 4Vt+rxOgxA66HWDSQi6QZVGK5vH3qIwOMlEQHBcS6L1YTP4J7F2/1knXFl+0w9LgWYCM KIcw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=9HcOVr8JD61cbEk0dQbFXubvFww54VrmGyyOpCRyVXc=; b=y0s2awQDs8IkXqoLNLMDk7R6ZyL527gWR7dlYxA7DMbp+Y6pZ8MYWzOYV1j3+o8/ae EgyhYhuDJH7M/SQ9PIm6LaN5vocgGp4ndCMlIJWMYm8TcHGrYqn9Kp5H/USKk0jIcxxT F0bRFWyicAYAGcfdfbq/f0TyQLtACsgGAwZ0AVBRuKWxGu0vGLv0tnY2bMMhFAY+TFUP CND0FrHd7ZXr2FaEHTuz/PR4Tm8m4gNFOx9Lo2t/TMGAKoauBdyR1HBZKUmhY/32CQRT zvHjv+pS5ABKK2vbuddBVQIVV9WRppc9P4gVAa8qZJOSfYVhb+rzlVaanijziuSWZk0z 9A8Q== X-Gm-Message-State: AOAM532L8SGAYXQDiUzNKsOWerYz93JJvLYN8HSTJreoW69peAz2XiiX pl6cb1qLsjLl5BNc7sVy7PQG0MQJLsOubMnKir+6MrtWiKqeWg== X-Google-Smtp-Source: ABdhPJxd8UZalePXNSvl8KsyBg9KAYSGURryVOZlt1PmIvCf/h9Bpd+QH4q9VxNbY3k9ouXcOePE+cDFVTwNZB+OQSQ= X-Received: by 2002:a2e:6e0d:: with SMTP id j13mr27598350ljc.91.1634000908167; Mon, 11 Oct 2021 18:08:28 -0700 (PDT) MIME-Version: 1.0 From: Sui Chen Date: Mon, 11 Oct 2021 18:08:16 -0700 Message-ID: Subject: [RFC Patch 2/2] add npcm7xx debug counters as sysfs attributes To: linux-i2c@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org This change adds npcm7xx debug counters as sysfs attributes using the i2c_adapter_stats_register_counter function. Signed-off-by: Sui Chen Reviewed-by: Tali Perry --- drivers/i2c/busses/i2c-npcm7xx.c | 8 ++++++++ 1 file changed, 8 insertions(+) + bus->debugfs = d; } diff --git a/drivers/i2c/busses/i2c-npcm7xx.c b/drivers/i2c/busses/i2c-npcm7xx.c index 2ad166355ec9b..def044207cae2 100644 --- a/drivers/i2c/busses/i2c-npcm7xx.c +++ b/drivers/i2c/busses/i2c-npcm7xx.c @@ -2224,6 +2224,14 @@ static void npcm_i2c_init_debugfs(struct platform_device *pdev, debugfs_create_u64("rec_fail_cnt", 0444, d, &bus->rec_fail_cnt); debugfs_create_u64("timeout_cnt", 0444, d, &bus->timeout_cnt); + /* register debug counters in sysfs */ + i2c_adapter_stats_register_counter(&bus->adap, "ber_cnt", &bus->ber_cnt); + i2c_adapter_stats_register_counter(&bus->adap, "nack_cnt", &bus->nack_cnt); + i2c_adapter_stats_register_counter(&bus->adap, "rec_succ_cnt", &bus->rec_succ_cnt); + i2c_adapter_stats_register_counter(&bus->adap, "rec_fail_cnt", &bus->rec_fail_cnt); + i2c_adapter_stats_register_counter(&bus->adap, "timeout_cnt", &bus->timeout_cnt); + i2c_adapter_stats_register_counter(&bus->adap, "i2c_speed", &bus->bus_freq);