root/drivers/s390/net/qeth_ethtool.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. qeth_add_stat_data
  2. qeth_add_stat_strings
  3. qeth_get_sset_count
  4. qeth_get_ethtool_stats
  5. qeth_get_ringparam
  6. qeth_get_strings
  7. qeth_get_drvinfo
  8. qeth_get_channels
  9. qeth_set_cmd_adv_sup
  10. qeth_get_link_ksettings

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Copyright IBM Corp. 2018
   4  */
   5 
   6 #define KMSG_COMPONENT "qeth"
   7 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
   8 
   9 #include <linux/ethtool.h>
  10 #include "qeth_core.h"
  11 
  12 
  13 #define QETH_TXQ_STAT(_name, _stat) { \
  14         .name = _name, \
  15         .offset = offsetof(struct qeth_out_q_stats, _stat) \
  16 }
  17 
  18 #define QETH_CARD_STAT(_name, _stat) { \
  19         .name = _name, \
  20         .offset = offsetof(struct qeth_card_stats, _stat) \
  21 }
  22 
  23 struct qeth_stats {
  24         char name[ETH_GSTRING_LEN];
  25         unsigned int offset;
  26 };
  27 
  28 static const struct qeth_stats txq_stats[] = {
  29         QETH_TXQ_STAT("IO buffers", bufs),
  30         QETH_TXQ_STAT("IO buffer elements", buf_elements),
  31         QETH_TXQ_STAT("packed IO buffers", bufs_pack),
  32         QETH_TXQ_STAT("skbs", tx_packets),
  33         QETH_TXQ_STAT("packed skbs", skbs_pack),
  34         QETH_TXQ_STAT("SG skbs", skbs_sg),
  35         QETH_TXQ_STAT("HW csum skbs", skbs_csum),
  36         QETH_TXQ_STAT("TSO skbs", skbs_tso),
  37         QETH_TXQ_STAT("linearized skbs", skbs_linearized),
  38         QETH_TXQ_STAT("linearized+error skbs", skbs_linearized_fail),
  39         QETH_TXQ_STAT("TSO bytes", tso_bytes),
  40         QETH_TXQ_STAT("Packing mode switches", packing_mode_switch),
  41         QETH_TXQ_STAT("Queue stopped", stopped),
  42         QETH_TXQ_STAT("Completion yield", completion_yield),
  43         QETH_TXQ_STAT("Completion timer", completion_timer),
  44 };
  45 
  46 static const struct qeth_stats card_stats[] = {
  47         QETH_CARD_STAT("rx0 IO buffers", rx_bufs),
  48         QETH_CARD_STAT("rx0 HW csum skbs", rx_skb_csum),
  49         QETH_CARD_STAT("rx0 SG skbs", rx_sg_skbs),
  50         QETH_CARD_STAT("rx0 SG page frags", rx_sg_frags),
  51         QETH_CARD_STAT("rx0 SG page allocs", rx_sg_alloc_page),
  52 };
  53 
  54 #define TXQ_STATS_LEN   ARRAY_SIZE(txq_stats)
  55 #define CARD_STATS_LEN  ARRAY_SIZE(card_stats)
  56 
  57 static void qeth_add_stat_data(u64 **dst, void *src,
  58                                const struct qeth_stats stats[],
  59                                unsigned int size)
  60 {
  61         unsigned int i;
  62         char *stat;
  63 
  64         for (i = 0; i < size; i++) {
  65                 stat = (char *)src + stats[i].offset;
  66                 **dst = *(u64 *)stat;
  67                 (*dst)++;
  68         }
  69 }
  70 
  71 static void qeth_add_stat_strings(u8 **data, const char *prefix,
  72                                   const struct qeth_stats stats[],
  73                                   unsigned int size)
  74 {
  75         unsigned int i;
  76 
  77         for (i = 0; i < size; i++) {
  78                 snprintf(*data, ETH_GSTRING_LEN, "%s%s", prefix, stats[i].name);
  79                 *data += ETH_GSTRING_LEN;
  80         }
  81 }
  82 
  83 static int qeth_get_sset_count(struct net_device *dev, int stringset)
  84 {
  85         struct qeth_card *card = dev->ml_priv;
  86 
  87         switch (stringset) {
  88         case ETH_SS_STATS:
  89                 return CARD_STATS_LEN +
  90                        card->qdio.no_out_queues * TXQ_STATS_LEN;
  91         default:
  92                 return -EINVAL;
  93         }
  94 }
  95 
  96 static void qeth_get_ethtool_stats(struct net_device *dev,
  97                                    struct ethtool_stats *stats, u64 *data)
  98 {
  99         struct qeth_card *card = dev->ml_priv;
 100         unsigned int i;
 101 
 102         qeth_add_stat_data(&data, &card->stats, card_stats, CARD_STATS_LEN);
 103         for (i = 0; i < card->qdio.no_out_queues; i++)
 104                 qeth_add_stat_data(&data, &card->qdio.out_qs[i]->stats,
 105                                    txq_stats, TXQ_STATS_LEN);
 106 }
 107 
 108 static void qeth_get_ringparam(struct net_device *dev,
 109                                struct ethtool_ringparam *param)
 110 {
 111         struct qeth_card *card = dev->ml_priv;
 112 
 113         param->rx_max_pending = QDIO_MAX_BUFFERS_PER_Q;
 114         param->rx_mini_max_pending = 0;
 115         param->rx_jumbo_max_pending = 0;
 116         param->tx_max_pending = QDIO_MAX_BUFFERS_PER_Q;
 117 
 118         param->rx_pending = card->qdio.in_buf_pool.buf_count;
 119         param->rx_mini_pending = 0;
 120         param->rx_jumbo_pending = 0;
 121         param->tx_pending = QDIO_MAX_BUFFERS_PER_Q;
 122 }
 123 
 124 static void qeth_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 125 {
 126         struct qeth_card *card = dev->ml_priv;
 127         char prefix[ETH_GSTRING_LEN] = "";
 128         unsigned int i;
 129 
 130         switch (stringset) {
 131         case ETH_SS_STATS:
 132                 qeth_add_stat_strings(&data, prefix, card_stats,
 133                                       CARD_STATS_LEN);
 134                 for (i = 0; i < card->qdio.no_out_queues; i++) {
 135                         snprintf(prefix, ETH_GSTRING_LEN, "tx%u ", i);
 136                         qeth_add_stat_strings(&data, prefix, txq_stats,
 137                                               TXQ_STATS_LEN);
 138                 }
 139                 break;
 140         default:
 141                 WARN_ON(1);
 142                 break;
 143         }
 144 }
 145 
 146 static void qeth_get_drvinfo(struct net_device *dev,
 147                              struct ethtool_drvinfo *info)
 148 {
 149         struct qeth_card *card = dev->ml_priv;
 150 
 151         strlcpy(info->driver, IS_LAYER2(card) ? "qeth_l2" : "qeth_l3",
 152                 sizeof(info->driver));
 153         strlcpy(info->version, "1.0", sizeof(info->version));
 154         strlcpy(info->fw_version, card->info.mcl_level,
 155                 sizeof(info->fw_version));
 156         snprintf(info->bus_info, sizeof(info->bus_info), "%s/%s/%s",
 157                  CARD_RDEV_ID(card), CARD_WDEV_ID(card), CARD_DDEV_ID(card));
 158 }
 159 
 160 static void qeth_get_channels(struct net_device *dev,
 161                               struct ethtool_channels *channels)
 162 {
 163         struct qeth_card *card = dev->ml_priv;
 164 
 165         channels->max_rx = dev->num_rx_queues;
 166         channels->max_tx = card->qdio.no_out_queues;
 167         channels->max_other = 0;
 168         channels->max_combined = 0;
 169         channels->rx_count = dev->real_num_rx_queues;
 170         channels->tx_count = dev->real_num_tx_queues;
 171         channels->other_count = 0;
 172         channels->combined_count = 0;
 173 }
 174 
 175 /* Helper function to fill 'advertising' and 'supported' which are the same. */
 176 /* Autoneg and full-duplex are supported and advertised unconditionally.     */
 177 /* Always advertise and support all speeds up to specified, and only one     */
 178 /* specified port type.                                                      */
 179 static void qeth_set_cmd_adv_sup(struct ethtool_link_ksettings *cmd,
 180                                 int maxspeed, int porttype)
 181 {
 182         ethtool_link_ksettings_zero_link_mode(cmd, supported);
 183         ethtool_link_ksettings_zero_link_mode(cmd, advertising);
 184         ethtool_link_ksettings_zero_link_mode(cmd, lp_advertising);
 185 
 186         ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
 187         ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
 188 
 189         switch (porttype) {
 190         case PORT_TP:
 191                 ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
 192                 ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
 193                 break;
 194         case PORT_FIBRE:
 195                 ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
 196                 ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
 197                 break;
 198         default:
 199                 ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
 200                 ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
 201                 WARN_ON_ONCE(1);
 202         }
 203 
 204         /* partially does fall through, to also select lower speeds */
 205         switch (maxspeed) {
 206         case SPEED_25000:
 207                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 208                                                      25000baseSR_Full);
 209                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 210                                                      25000baseSR_Full);
 211                 break;
 212         case SPEED_10000:
 213                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 214                                                      10000baseT_Full);
 215                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 216                                                      10000baseT_Full);
 217                 /* fall through */
 218         case SPEED_1000:
 219                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 220                                                      1000baseT_Full);
 221                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 222                                                      1000baseT_Full);
 223                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 224                                                      1000baseT_Half);
 225                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 226                                                      1000baseT_Half);
 227                 /* fall through */
 228         case SPEED_100:
 229                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 230                                                      100baseT_Full);
 231                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 232                                                      100baseT_Full);
 233                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 234                                                      100baseT_Half);
 235                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 236                                                      100baseT_Half);
 237                 /* fall through */
 238         case SPEED_10:
 239                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 240                                                      10baseT_Full);
 241                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 242                                                      10baseT_Full);
 243                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 244                                                      10baseT_Half);
 245                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 246                                                      10baseT_Half);
 247                 break;
 248         default:
 249                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 250                                                      10baseT_Full);
 251                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 252                                                      10baseT_Full);
 253                 ethtool_link_ksettings_add_link_mode(cmd, supported,
 254                                                      10baseT_Half);
 255                 ethtool_link_ksettings_add_link_mode(cmd, advertising,
 256                                                      10baseT_Half);
 257                 WARN_ON_ONCE(1);
 258         }
 259 }
 260 
 261 
 262 static int qeth_get_link_ksettings(struct net_device *netdev,
 263                                    struct ethtool_link_ksettings *cmd)
 264 {
 265         struct qeth_card *card = netdev->ml_priv;
 266         enum qeth_link_types link_type;
 267         struct carrier_info carrier_info;
 268         int rc;
 269 
 270         if (IS_IQD(card) || IS_VM_NIC(card))
 271                 link_type = QETH_LINK_TYPE_10GBIT_ETH;
 272         else
 273                 link_type = card->info.link_type;
 274 
 275         cmd->base.duplex = DUPLEX_FULL;
 276         cmd->base.autoneg = AUTONEG_ENABLE;
 277         cmd->base.phy_address = 0;
 278         cmd->base.mdio_support = 0;
 279         cmd->base.eth_tp_mdix = ETH_TP_MDI_INVALID;
 280         cmd->base.eth_tp_mdix_ctrl = ETH_TP_MDI_INVALID;
 281 
 282         switch (link_type) {
 283         case QETH_LINK_TYPE_FAST_ETH:
 284         case QETH_LINK_TYPE_LANE_ETH100:
 285                 cmd->base.speed = SPEED_100;
 286                 cmd->base.port = PORT_TP;
 287                 break;
 288         case QETH_LINK_TYPE_GBIT_ETH:
 289         case QETH_LINK_TYPE_LANE_ETH1000:
 290                 cmd->base.speed = SPEED_1000;
 291                 cmd->base.port = PORT_FIBRE;
 292                 break;
 293         case QETH_LINK_TYPE_10GBIT_ETH:
 294                 cmd->base.speed = SPEED_10000;
 295                 cmd->base.port = PORT_FIBRE;
 296                 break;
 297         case QETH_LINK_TYPE_25GBIT_ETH:
 298                 cmd->base.speed = SPEED_25000;
 299                 cmd->base.port = PORT_FIBRE;
 300                 break;
 301         default:
 302                 cmd->base.speed = SPEED_10;
 303                 cmd->base.port = PORT_TP;
 304         }
 305         qeth_set_cmd_adv_sup(cmd, cmd->base.speed, cmd->base.port);
 306 
 307         /* Check if we can obtain more accurate information.     */
 308         /* If QUERY_CARD_INFO command is not supported or fails, */
 309         /* just return the heuristics that was filled above.     */
 310         rc = qeth_query_card_info(card, &carrier_info);
 311         if (rc == -EOPNOTSUPP) /* for old hardware, return heuristic */
 312                 return 0;
 313         if (rc) /* report error from the hardware operation */
 314                 return rc;
 315         /* on success, fill in the information got from the hardware */
 316 
 317         netdev_dbg(netdev,
 318         "card info: card_type=0x%02x, port_mode=0x%04x, port_speed=0x%08x\n",
 319                         carrier_info.card_type,
 320                         carrier_info.port_mode,
 321                         carrier_info.port_speed);
 322 
 323         /* Update attributes for which we've obtained more authoritative */
 324         /* information, leave the rest the way they where filled above.  */
 325         switch (carrier_info.card_type) {
 326         case CARD_INFO_TYPE_1G_COPPER_A:
 327         case CARD_INFO_TYPE_1G_COPPER_B:
 328                 cmd->base.port = PORT_TP;
 329                 qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
 330                 break;
 331         case CARD_INFO_TYPE_1G_FIBRE_A:
 332         case CARD_INFO_TYPE_1G_FIBRE_B:
 333                 cmd->base.port = PORT_FIBRE;
 334                 qeth_set_cmd_adv_sup(cmd, SPEED_1000, cmd->base.port);
 335                 break;
 336         case CARD_INFO_TYPE_10G_FIBRE_A:
 337         case CARD_INFO_TYPE_10G_FIBRE_B:
 338                 cmd->base.port = PORT_FIBRE;
 339                 qeth_set_cmd_adv_sup(cmd, SPEED_10000, cmd->base.port);
 340                 break;
 341         }
 342 
 343         switch (carrier_info.port_mode) {
 344         case CARD_INFO_PORTM_FULLDUPLEX:
 345                 cmd->base.duplex = DUPLEX_FULL;
 346                 break;
 347         case CARD_INFO_PORTM_HALFDUPLEX:
 348                 cmd->base.duplex = DUPLEX_HALF;
 349                 break;
 350         }
 351 
 352         switch (carrier_info.port_speed) {
 353         case CARD_INFO_PORTS_10M:
 354                 cmd->base.speed = SPEED_10;
 355                 break;
 356         case CARD_INFO_PORTS_100M:
 357                 cmd->base.speed = SPEED_100;
 358                 break;
 359         case CARD_INFO_PORTS_1G:
 360                 cmd->base.speed = SPEED_1000;
 361                 break;
 362         case CARD_INFO_PORTS_10G:
 363                 cmd->base.speed = SPEED_10000;
 364                 break;
 365         case CARD_INFO_PORTS_25G:
 366                 cmd->base.speed = SPEED_25000;
 367                 break;
 368         }
 369 
 370         return 0;
 371 }
 372 
 373 const struct ethtool_ops qeth_ethtool_ops = {
 374         .get_link = ethtool_op_get_link,
 375         .get_ringparam = qeth_get_ringparam,
 376         .get_strings = qeth_get_strings,
 377         .get_ethtool_stats = qeth_get_ethtool_stats,
 378         .get_sset_count = qeth_get_sset_count,
 379         .get_drvinfo = qeth_get_drvinfo,
 380         .get_channels = qeth_get_channels,
 381         .get_link_ksettings = qeth_get_link_ksettings,
 382 };
 383 
 384 const struct ethtool_ops qeth_osn_ethtool_ops = {
 385         .get_strings = qeth_get_strings,
 386         .get_ethtool_stats = qeth_get_ethtool_stats,
 387         .get_sset_count = qeth_get_sset_count,
 388         .get_drvinfo = qeth_get_drvinfo,
 389 };

/* [<][>][^][v][top][bottom][index][help] */