0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
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;
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,
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 }