Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/net/ethtool/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 7 kB image not shown  

Quelle  plca.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only

#include <linux/phy.h>
#include <linux/ethtool_netlink.h>

#include "netlink.h"
#include "common.h"

struct plca_req_info {
 struct ethnl_req_info  base;
};

struct plca_reply_data {
 struct ethnl_reply_data  base;
 struct phy_plca_cfg  plca_cfg;
 struct phy_plca_status  plca_st;
};

// Helpers ------------------------------------------------------------------ //

#define PLCA_REPDATA(__reply_base) \
 container_of(__reply_base, struct plca_reply_data, base)

// PLCA get configuration message ------------------------------------------- //

const struct nla_policy ethnl_plca_get_cfg_policy[] = {
 [ETHTOOL_A_PLCA_HEADER]  =
  NLA_POLICY_NESTED(ethnl_header_policy_phy),
};

static void plca_update_sint(int *dst, struct nlattr **tb, u32 attrid,
        bool *mod)
{
 const struct nlattr *attr = tb[attrid];

 if (!attr ||
     WARN_ON_ONCE(attrid >= ARRAY_SIZE(ethnl_plca_set_cfg_policy)))
  return;

 switch (ethnl_plca_set_cfg_policy[attrid].type) {
 case NLA_U8:
  *dst = nla_get_u8(attr);
  break;
 case NLA_U32:
  *dst = nla_get_u32(attr);
  break;
 default:
  WARN_ON_ONCE(1);
 }

 *mod = true;
}

static int plca_get_cfg_prepare_data(const struct ethnl_req_info *req_base,
         struct ethnl_reply_data *reply_base,
         const struct genl_info *info)
{
 struct plca_reply_data *data = PLCA_REPDATA(reply_base);
 struct net_device *dev = reply_base->dev;
 const struct ethtool_phy_ops *ops;
 struct nlattr **tb = info->attrs;
 struct phy_device *phydev;
 int ret;

 phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PLCA_HEADER,
          info->extack);
 // check that the PHY device is available and connected
 if (IS_ERR_OR_NULL(phydev)) {
  ret = -EOPNOTSUPP;
  goto out;
 }

 // note: rtnl_lock is held already by ethnl_default_doit
 ops = ethtool_phy_ops;
 if (!ops || !ops->get_plca_cfg) {
  ret = -EOPNOTSUPP;
  goto out;
 }

 ret = ethnl_ops_begin(dev);
 if (ret < 0)
  goto out;

 memset(&data->plca_cfg, 0xff,
        sizeof_field(struct plca_reply_data, plca_cfg));

 ret = ops->get_plca_cfg(phydev, &data->plca_cfg);
 ethnl_ops_complete(dev);

out:
 return ret;
}

static int plca_get_cfg_reply_size(const struct ethnl_req_info *req_base,
       const struct ethnl_reply_data *reply_base)
{
 return nla_total_size(sizeof(u16)) + /* _VERSION */
        nla_total_size(sizeof(u8)) + /* _ENABLED */
        nla_total_size(sizeof(u32)) + /* _NODE_CNT */
        nla_total_size(sizeof(u32)) + /* _NODE_ID */
        nla_total_size(sizeof(u32)) + /* _TO_TIMER */
        nla_total_size(sizeof(u32)) + /* _BURST_COUNT */
        nla_total_size(sizeof(u32)); /* _BURST_TIMER */
}

static int plca_get_cfg_fill_reply(struct sk_buff *skb,
       const struct ethnl_req_info *req_base,
       const struct ethnl_reply_data *reply_base)
{
 const struct plca_reply_data *data = PLCA_REPDATA(reply_base);
 const struct phy_plca_cfg *plca = &data->plca_cfg;

 if ((plca->version >= 0 &&
      nla_put_u16(skb, ETHTOOL_A_PLCA_VERSION, plca->version)) ||
     (plca->enabled >= 0 &&
      nla_put_u8(skb, ETHTOOL_A_PLCA_ENABLED, !!plca->enabled)) ||
     (plca->node_id >= 0 &&
      nla_put_u32(skb, ETHTOOL_A_PLCA_NODE_ID, plca->node_id)) ||
     (plca->node_cnt >= 0 &&
      nla_put_u32(skb, ETHTOOL_A_PLCA_NODE_CNT, plca->node_cnt)) ||
     (plca->to_tmr >= 0 &&
      nla_put_u32(skb, ETHTOOL_A_PLCA_TO_TMR, plca->to_tmr)) ||
     (plca->burst_cnt >= 0 &&
      nla_put_u32(skb, ETHTOOL_A_PLCA_BURST_CNT, plca->burst_cnt)) ||
     (plca->burst_tmr >= 0 &&
      nla_put_u32(skb, ETHTOOL_A_PLCA_BURST_TMR, plca->burst_tmr)))
  return -EMSGSIZE;

 return 0;
};

// PLCA set configuration message ------------------------------------------- //

const struct nla_policy ethnl_plca_set_cfg_policy[] = {
 [ETHTOOL_A_PLCA_HEADER]  =
  NLA_POLICY_NESTED(ethnl_header_policy_phy),
 [ETHTOOL_A_PLCA_ENABLED] = NLA_POLICY_MAX(NLA_U8, 1),
 [ETHTOOL_A_PLCA_NODE_ID] = NLA_POLICY_MAX(NLA_U32, 255),
 [ETHTOOL_A_PLCA_NODE_CNT] = NLA_POLICY_RANGE(NLA_U32, 1, 255),
 [ETHTOOL_A_PLCA_TO_TMR]  = NLA_POLICY_MAX(NLA_U32, 255),
 [ETHTOOL_A_PLCA_BURST_CNT] = NLA_POLICY_MAX(NLA_U32, 255),
 [ETHTOOL_A_PLCA_BURST_TMR] = NLA_POLICY_MAX(NLA_U32, 255),
};

static int
ethnl_set_plca(struct ethnl_req_info *req_info, struct genl_info *info)
{
 const struct ethtool_phy_ops *ops;
 struct nlattr **tb = info->attrs;
 struct phy_plca_cfg plca_cfg;
 struct phy_device *phydev;
 bool mod = false;
 int ret;

 phydev = ethnl_req_get_phydev(req_info, tb, ETHTOOL_A_PLCA_HEADER,
          info->extack);
 // check that the PHY device is available and connected
 if (IS_ERR_OR_NULL(phydev))
  return -EOPNOTSUPP;

 ops = ethtool_phy_ops;
 if (!ops || !ops->set_plca_cfg)
  return -EOPNOTSUPP;

 memset(&plca_cfg, 0xff, sizeof(plca_cfg));
 plca_update_sint(&plca_cfg.enabled, tb, ETHTOOL_A_PLCA_ENABLED, &mod);
 plca_update_sint(&plca_cfg.node_id, tb, ETHTOOL_A_PLCA_NODE_ID, &mod);
 plca_update_sint(&plca_cfg.node_cnt, tb, ETHTOOL_A_PLCA_NODE_CNT, &mod);
 plca_update_sint(&plca_cfg.to_tmr, tb, ETHTOOL_A_PLCA_TO_TMR, &mod);
 plca_update_sint(&plca_cfg.burst_cnt, tb, ETHTOOL_A_PLCA_BURST_CNT,
    &mod);
 plca_update_sint(&plca_cfg.burst_tmr, tb, ETHTOOL_A_PLCA_BURST_TMR,
    &mod);
 if (!mod)
  return 0;

 ret = ops->set_plca_cfg(phydev, &plca_cfg, info->extack);
 return ret < 0 ? ret : 1;
}

const struct ethnl_request_ops ethnl_plca_cfg_request_ops = {
 .request_cmd  = ETHTOOL_MSG_PLCA_GET_CFG,
 .reply_cmd  = ETHTOOL_MSG_PLCA_GET_CFG_REPLY,
 .hdr_attr  = ETHTOOL_A_PLCA_HEADER,
 .req_info_size  = sizeof(struct plca_req_info),
 .reply_data_size = sizeof(struct plca_reply_data),

 .prepare_data  = plca_get_cfg_prepare_data,
 .reply_size  = plca_get_cfg_reply_size,
 .fill_reply  = plca_get_cfg_fill_reply,

 .set   = ethnl_set_plca,
 .set_ntf_cmd  = ETHTOOL_MSG_PLCA_NTF,
};

// PLCA get status message -------------------------------------------------- //

const struct nla_policy ethnl_plca_get_status_policy[] = {
 [ETHTOOL_A_PLCA_HEADER]  =
  NLA_POLICY_NESTED(ethnl_header_policy_phy),
};

static int plca_get_status_prepare_data(const struct ethnl_req_info *req_base,
     struct ethnl_reply_data *reply_base,
     const struct genl_info *info)
{
 struct plca_reply_data *data = PLCA_REPDATA(reply_base);
 struct net_device *dev = reply_base->dev;
 const struct ethtool_phy_ops *ops;
 struct nlattr **tb = info->attrs;
 struct phy_device *phydev;
 int ret;

 phydev = ethnl_req_get_phydev(req_base, tb, ETHTOOL_A_PLCA_HEADER,
          info->extack);
 // check that the PHY device is available and connected
 if (IS_ERR_OR_NULL(phydev)) {
  ret = -EOPNOTSUPP;
  goto out;
 }

 // note: rtnl_lock is held already by ethnl_default_doit
 ops = ethtool_phy_ops;
 if (!ops || !ops->get_plca_status) {
  ret = -EOPNOTSUPP;
  goto out;
 }

 ret = ethnl_ops_begin(dev);
 if (ret < 0)
  goto out;

 memset(&data->plca_st, 0xff,
        sizeof_field(struct plca_reply_data, plca_st));

 ret = ops->get_plca_status(phydev, &data->plca_st);
 ethnl_ops_complete(dev);
out:
 return ret;
}

static int plca_get_status_reply_size(const struct ethnl_req_info *req_base,
          const struct ethnl_reply_data *reply_base)
{
 return nla_total_size(sizeof(u8)); /* _STATUS */
}

static int plca_get_status_fill_reply(struct sk_buff *skb,
          const struct ethnl_req_info *req_base,
          const struct ethnl_reply_data *reply_base)
{
 const struct plca_reply_data *data = PLCA_REPDATA(reply_base);
 const u8 status = data->plca_st.pst;

 if (nla_put_u8(skb, ETHTOOL_A_PLCA_STATUS, !!status))
  return -EMSGSIZE;

 return 0;
};

const struct ethnl_request_ops ethnl_plca_status_request_ops = {
 .request_cmd  = ETHTOOL_MSG_PLCA_GET_STATUS,
 .reply_cmd  = ETHTOOL_MSG_PLCA_GET_STATUS_REPLY,
 .hdr_attr  = ETHTOOL_A_PLCA_HEADER,
 .req_info_size  = sizeof(struct plca_req_info),
 .reply_data_size = sizeof(struct plca_reply_data),

 .prepare_data  = plca_get_status_prepare_data,
 .reply_size  = plca_get_status_reply_size,
 .fill_reply  = plca_get_status_fill_reply,
};

Messung V0.5
C=94 H=93 G=93

¤ Dauer der Verarbeitung: 0.4 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.