Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  *  linux/drivers/net/ethernet/ibm/ehea/ehea_ethtool.c
0004  *
0005  *  eHEA ethernet device driver for IBM eServer System p
0006  *
0007  *  (C) Copyright IBM Corp. 2006
0008  *
0009  *  Authors:
0010  *       Christoph Raisch <raisch@de.ibm.com>
0011  *       Jan-Bernd Themann <themann@de.ibm.com>
0012  *       Thomas Klein <tklein@de.ibm.com>
0013  */
0014 
0015 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0016 
0017 #include "ehea.h"
0018 #include "ehea_phyp.h"
0019 
0020 static int ehea_get_link_ksettings(struct net_device *dev,
0021                    struct ethtool_link_ksettings *cmd)
0022 {
0023     struct ehea_port *port = netdev_priv(dev);
0024     u32 supported, advertising;
0025     u32 speed;
0026     int ret;
0027 
0028     ret = ehea_sense_port_attr(port);
0029 
0030     if (ret)
0031         return ret;
0032 
0033     if (netif_carrier_ok(dev)) {
0034         switch (port->port_speed) {
0035         case EHEA_SPEED_10M:
0036             speed = SPEED_10;
0037             break;
0038         case EHEA_SPEED_100M:
0039             speed = SPEED_100;
0040             break;
0041         case EHEA_SPEED_1G:
0042             speed = SPEED_1000;
0043             break;
0044         case EHEA_SPEED_10G:
0045             speed = SPEED_10000;
0046             break;
0047         default:
0048             speed = -1;
0049             break; /* BUG */
0050         }
0051         cmd->base.duplex = port->full_duplex == 1 ?
0052                              DUPLEX_FULL : DUPLEX_HALF;
0053     } else {
0054         speed = SPEED_UNKNOWN;
0055         cmd->base.duplex = DUPLEX_UNKNOWN;
0056     }
0057     cmd->base.speed = speed;
0058 
0059     if (cmd->base.speed == SPEED_10000) {
0060         supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
0061         advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
0062         cmd->base.port = PORT_FIBRE;
0063     } else {
0064         supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full
0065                    | SUPPORTED_100baseT_Half | SUPPORTED_10baseT_Full
0066                    | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg
0067                    | SUPPORTED_TP);
0068         advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg
0069                  | ADVERTISED_TP);
0070         cmd->base.port = PORT_TP;
0071     }
0072 
0073     cmd->base.autoneg = port->autoneg == 1 ?
0074         AUTONEG_ENABLE : AUTONEG_DISABLE;
0075 
0076     ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
0077                         supported);
0078     ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
0079                         advertising);
0080 
0081     return 0;
0082 }
0083 
0084 static int ehea_set_link_ksettings(struct net_device *dev,
0085                    const struct ethtool_link_ksettings *cmd)
0086 {
0087     struct ehea_port *port = netdev_priv(dev);
0088     int ret = 0;
0089     u32 sp;
0090 
0091     if (cmd->base.autoneg == AUTONEG_ENABLE) {
0092         sp = EHEA_SPEED_AUTONEG;
0093         goto doit;
0094     }
0095 
0096     switch (cmd->base.speed) {
0097     case SPEED_10:
0098         if (cmd->base.duplex == DUPLEX_FULL)
0099             sp = H_SPEED_10M_F;
0100         else
0101             sp = H_SPEED_10M_H;
0102         break;
0103 
0104     case SPEED_100:
0105         if (cmd->base.duplex == DUPLEX_FULL)
0106             sp = H_SPEED_100M_F;
0107         else
0108             sp = H_SPEED_100M_H;
0109         break;
0110 
0111     case SPEED_1000:
0112         if (cmd->base.duplex == DUPLEX_FULL)
0113             sp = H_SPEED_1G_F;
0114         else
0115             ret = -EINVAL;
0116         break;
0117 
0118     case SPEED_10000:
0119         if (cmd->base.duplex == DUPLEX_FULL)
0120             sp = H_SPEED_10G_F;
0121         else
0122             ret = -EINVAL;
0123         break;
0124 
0125     default:
0126             ret = -EINVAL;
0127         break;
0128     }
0129 
0130     if (ret)
0131         goto out;
0132 doit:
0133     ret = ehea_set_portspeed(port, sp);
0134 
0135     if (!ret)
0136         netdev_info(dev,
0137                 "Port speed successfully set: %dMbps %s Duplex\n",
0138                 port->port_speed,
0139                 port->full_duplex == 1 ? "Full" : "Half");
0140 out:
0141     return ret;
0142 }
0143 
0144 static int ehea_nway_reset(struct net_device *dev)
0145 {
0146     struct ehea_port *port = netdev_priv(dev);
0147     int ret;
0148 
0149     ret = ehea_set_portspeed(port, EHEA_SPEED_AUTONEG);
0150 
0151     if (!ret)
0152         netdev_info(port->netdev,
0153                 "Port speed successfully set: %dMbps %s Duplex\n",
0154                 port->port_speed,
0155                 port->full_duplex == 1 ? "Full" : "Half");
0156     return ret;
0157 }
0158 
0159 static void ehea_get_drvinfo(struct net_device *dev,
0160                    struct ethtool_drvinfo *info)
0161 {
0162     strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
0163     strlcpy(info->version, DRV_VERSION, sizeof(info->version));
0164 }
0165 
0166 static u32 ehea_get_msglevel(struct net_device *dev)
0167 {
0168     struct ehea_port *port = netdev_priv(dev);
0169     return port->msg_enable;
0170 }
0171 
0172 static void ehea_set_msglevel(struct net_device *dev, u32 value)
0173 {
0174     struct ehea_port *port = netdev_priv(dev);
0175     port->msg_enable = value;
0176 }
0177 
0178 static const char ehea_ethtool_stats_keys[][ETH_GSTRING_LEN] = {
0179     {"sig_comp_iv"},
0180     {"swqe_refill_th"},
0181     {"port resets"},
0182     {"Receive errors"},
0183     {"TCP cksum errors"},
0184     {"IP cksum errors"},
0185     {"Frame cksum errors"},
0186     {"num SQ stopped"},
0187     {"PR0 free_swqes"},
0188     {"PR1 free_swqes"},
0189     {"PR2 free_swqes"},
0190     {"PR3 free_swqes"},
0191     {"PR4 free_swqes"},
0192     {"PR5 free_swqes"},
0193     {"PR6 free_swqes"},
0194     {"PR7 free_swqes"},
0195     {"PR8 free_swqes"},
0196     {"PR9 free_swqes"},
0197     {"PR10 free_swqes"},
0198     {"PR11 free_swqes"},
0199     {"PR12 free_swqes"},
0200     {"PR13 free_swqes"},
0201     {"PR14 free_swqes"},
0202     {"PR15 free_swqes"},
0203 };
0204 
0205 static void ehea_get_strings(struct net_device *dev, u32 stringset, u8 *data)
0206 {
0207     if (stringset == ETH_SS_STATS) {
0208         memcpy(data, &ehea_ethtool_stats_keys,
0209                sizeof(ehea_ethtool_stats_keys));
0210     }
0211 }
0212 
0213 static int ehea_get_sset_count(struct net_device *dev, int sset)
0214 {
0215     switch (sset) {
0216     case ETH_SS_STATS:
0217         return ARRAY_SIZE(ehea_ethtool_stats_keys);
0218     default:
0219         return -EOPNOTSUPP;
0220     }
0221 }
0222 
0223 static void ehea_get_ethtool_stats(struct net_device *dev,
0224                      struct ethtool_stats *stats, u64 *data)
0225 {
0226     int i, k, tmp;
0227     struct ehea_port *port = netdev_priv(dev);
0228 
0229     for (i = 0; i < ehea_get_sset_count(dev, ETH_SS_STATS); i++)
0230         data[i] = 0;
0231     i = 0;
0232 
0233     data[i++] = port->sig_comp_iv;
0234     data[i++] = port->port_res[0].swqe_refill_th;
0235     data[i++] = port->resets;
0236 
0237     for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
0238         tmp += port->port_res[k].p_stats.poll_receive_errors;
0239     data[i++] = tmp;
0240 
0241     for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
0242         tmp += port->port_res[k].p_stats.err_tcp_cksum;
0243     data[i++] = tmp;
0244 
0245     for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
0246         tmp += port->port_res[k].p_stats.err_ip_cksum;
0247     data[i++] = tmp;
0248 
0249     for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
0250         tmp += port->port_res[k].p_stats.err_frame_crc;
0251     data[i++] = tmp;
0252 
0253     for (k = 0, tmp = 0; k < EHEA_MAX_PORT_RES; k++)
0254         tmp += port->port_res[k].p_stats.queue_stopped;
0255     data[i++] = tmp;
0256 
0257     for (k = 0; k < 16; k++)
0258         data[i++] = atomic_read(&port->port_res[k].swqe_avail);
0259 }
0260 
0261 static const struct ethtool_ops ehea_ethtool_ops = {
0262     .get_drvinfo = ehea_get_drvinfo,
0263     .get_msglevel = ehea_get_msglevel,
0264     .set_msglevel = ehea_set_msglevel,
0265     .get_link = ethtool_op_get_link,
0266     .get_strings = ehea_get_strings,
0267     .get_sset_count = ehea_get_sset_count,
0268     .get_ethtool_stats = ehea_get_ethtool_stats,
0269     .nway_reset = ehea_nway_reset,      /* Restart autonegotiation */
0270     .get_link_ksettings = ehea_get_link_ksettings,
0271     .set_link_ksettings = ehea_set_link_ksettings,
0272 };
0273 
0274 void ehea_set_ethtool_ops(struct net_device *netdev)
0275 {
0276     netdev->ethtool_ops = &ehea_ethtool_ops;
0277 }