Print this page
    
MFV: illumos-joyent@61dc3dec4f82a3e13e94609a0a83d5f66c64e760
OS-6846 want i40e multi-group support
OS-7372 i40e_alloc_ring_mem() unwinds when it shouldn't
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Robert Mustacchi <rm@joyent.com>
Author: Ryan Zezeski <rpz@joyent.com>
MFV: illumos-joyent@9e30beee2f0c127bf41868db46257124206e28d6
OS-5225 Want Fortville TSO support
Reviewed by: Ryan Zezeski <rpz@joyent.com>
Reviewed by: Robert Mustacchi <rm@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
Author: Rob Johnston <rob.johnston@joyent.com>
MFV: illumos-gate@286d309c80aad9eac1fdbcb0388ed194d995d837
9805 i40e should read SFP data when firmware supports it
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Rob Johnston <rob.johnston@joyent.com>
Reviewed by: Dale Ghent <dale.ghent@joyent.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Dan McDonald <danmcd@joyent.com>
Author: Robert Mustacchi <rm@joyent.com>
NEX-13226 xvv710 25Gb NIC panics system under load
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-7822 40Gb Intel XL710 NIC performance data
Reviewed by: Steve Peng <steve.peng@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/i40e/i40e_gld.c
          +++ new/usr/src/uts/common/io/i40e/i40e_gld.c
   1    1  /*
   2    2   * This file and its contents are supplied under the terms of the
   3    3   * Common Development and Distribution License ("CDDL"), version 1.0.
  
    | 
      ↓ open down ↓ | 
    3 lines elided | 
    
      ↑ open up ↑ | 
  
   4    4   * You may only use this file in accordance with the terms of version
   5    5   * 1.0 of the CDDL.
   6    6   *
   7    7   * A full copy of the text of the CDDL should have accompanied this
   8    8   * source.  A copy of the CDDL is also available via the Internet at
   9    9   * http://www.illumos.org/license/CDDL.
  10   10   */
  11   11  
  12   12  /*
  13   13   * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
  14      - * Copyright (c) 2017, Joyent, Inc.
       14 + * Copyright (c) 2018, Joyent, Inc.
  15   15   * Copyright 2017 Tegile Systems, Inc.  All rights reserved.
  16   16   */
  17   17  
  18   18  /*
  19   19   * For more information, please see the big theory statement in i40e_main.c.
  20   20   */
  21   21  
  22   22  #include "i40e_sw.h"
  23   23  
  24   24  #define I40E_PROP_RX_DMA_THRESH "_rx_dma_threshold"
  25   25  #define I40E_PROP_TX_DMA_THRESH "_tx_dma_threshold"
  26   26  #define I40E_PROP_RX_ITR        "_rx_intr_throttle"
  27   27  #define I40E_PROP_TX_ITR        "_tx_intr_throttle"
  28   28  #define I40E_PROP_OTHER_ITR     "_other_intr_throttle"
  29   29  
  30   30  char *i40e_priv_props[] = {
  31   31          I40E_PROP_RX_DMA_THRESH,
  
    | 
      ↓ open down ↓ | 
    7 lines elided | 
    
      ↑ open up ↑ | 
  
  32   32          I40E_PROP_TX_DMA_THRESH,
  33   33          I40E_PROP_RX_ITR,
  34   34          I40E_PROP_TX_ITR,
  35   35          I40E_PROP_OTHER_ITR,
  36   36          NULL
  37   37  };
  38   38  
  39   39  static int
  40   40  i40e_group_remove_mac(void *arg, const uint8_t *mac_addr)
  41   41  {
  42      -        i40e_t *i40e = arg;
       42 +        i40e_rx_group_t *rxg = arg;
       43 +        i40e_t *i40e = rxg->irg_i40e;
  43   44          struct i40e_aqc_remove_macvlan_element_data filt;
  44   45          struct i40e_hw *hw = &i40e->i40e_hw_space;
  45   46          int ret, i, last;
  46   47          i40e_uaddr_t *iua;
  47   48  
  48   49          if (I40E_IS_MULTICAST(mac_addr))
  49   50                  return (EINVAL);
  50   51  
  51   52          mutex_enter(&i40e->i40e_general_lock);
  52   53  
  53   54          if (i40e->i40e_state & I40E_SUSPENDED) {
  54   55                  ret = ECANCELED;
  55   56                  goto done;
  56   57          }
  57   58  
  58   59          for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
  59   60                  if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
  60   61                      ETHERADDRL) == 0)
  61   62                          break;
  62   63          }
  63   64  
  64   65          if (i == i40e->i40e_resources.ifr_nmacfilt_used) {
  65   66                  ret = ENOENT;
  66   67                  goto done;
  67   68          }
  68   69  
  69   70          iua = &i40e->i40e_uaddrs[i];
  70   71          ASSERT(i40e->i40e_resources.ifr_nmacfilt_used > 0);
  71   72  
  72   73          bzero(&filt, sizeof (filt));
  73   74          bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
  74   75          filt.flags = I40E_AQC_MACVLAN_DEL_PERFECT_MATCH |
  75   76              I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
  76   77  
  77   78          if (i40e_aq_remove_macvlan(hw, iua->iua_vsi, &filt, 1, NULL) !=
  78   79              I40E_SUCCESS) {
  79   80                  i40e_error(i40e, "failed to remove mac address "
  80   81                      "%2x:%2x:%2x:%2x:%2x:%2x from unicast filter: %d",
  81   82                      mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
  82   83                      mac_addr[4], mac_addr[5], filt.error_code);
  83   84                  ret = EIO;
  84   85                  goto done;
  85   86          }
  86   87  
  87   88          last = i40e->i40e_resources.ifr_nmacfilt_used - 1;
  88   89          if (i != last) {
  89   90                  i40e_uaddr_t *src = &i40e->i40e_uaddrs[last];
  90   91                  bcopy(src, iua, sizeof (i40e_uaddr_t));
  91   92          }
  92   93  
  93   94          /*
  94   95           * Set the multicast bit in the last one to indicate to ourselves that
  95   96           * it's invalid.
  96   97           */
  97   98          bzero(&i40e->i40e_uaddrs[last], sizeof (i40e_uaddr_t));
  98   99          i40e->i40e_uaddrs[last].iua_mac[0] = 0x01;
  99  100          i40e->i40e_resources.ifr_nmacfilt_used--;
  
    | 
      ↓ open down ↓ | 
    47 lines elided | 
    
      ↑ open up ↑ | 
  
 100  101          ret = 0;
 101  102  done:
 102  103          mutex_exit(&i40e->i40e_general_lock);
 103  104  
 104  105          return (ret);
 105  106  }
 106  107  
 107  108  static int
 108  109  i40e_group_add_mac(void *arg, const uint8_t *mac_addr)
 109  110  {
 110      -        i40e_t *i40e = arg;
 111      -        struct i40e_hw *hw = &i40e->i40e_hw_space;
 112      -        int i, ret;
 113      -        i40e_uaddr_t *iua;
      111 +        i40e_rx_group_t *rxg = arg;
      112 +        i40e_t          *i40e = rxg->irg_i40e;
      113 +        struct i40e_hw  *hw = &i40e->i40e_hw_space;
      114 +        int             i, ret;
      115 +        i40e_uaddr_t    *iua;
 114  116          struct i40e_aqc_add_macvlan_element_data filt;
 115  117  
 116  118          if (I40E_IS_MULTICAST(mac_addr))
 117  119                  return (EINVAL);
 118  120  
 119  121          mutex_enter(&i40e->i40e_general_lock);
 120  122          if (i40e->i40e_state & I40E_SUSPENDED) {
 121  123                  ret = ECANCELED;
 122  124                  goto done;
 123  125          }
 124  126  
 125  127          if (i40e->i40e_resources.ifr_nmacfilt ==
 126  128              i40e->i40e_resources.ifr_nmacfilt_used) {
 127  129                  ret = ENOSPC;
 128  130                  goto done;
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
 129  131          }
 130  132  
 131  133          for (i = 0; i < i40e->i40e_resources.ifr_nmacfilt_used; i++) {
 132  134                  if (bcmp(mac_addr, i40e->i40e_uaddrs[i].iua_mac,
 133  135                      ETHERADDRL) == 0) {
 134  136                          ret = EEXIST;
 135  137                          goto done;
 136  138                  }
 137  139          }
 138  140  
 139      -        /*
 140      -         * Note, the general use of the i40e_vsi_id will have to be refactored
 141      -         * when we have proper group support.
 142      -         */
 143  141          bzero(&filt, sizeof (filt));
 144  142          bcopy(mac_addr, filt.mac_addr, ETHERADDRL);
 145  143          filt.flags = I40E_AQC_MACVLAN_ADD_PERFECT_MATCH |
 146  144              I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
 147  145  
 148      -        if ((ret = i40e_aq_add_macvlan(hw, i40e->i40e_vsi_id, &filt, 1,
      146 +        if ((ret = i40e_aq_add_macvlan(hw, rxg->irg_vsi_seid, &filt, 1,
 149  147              NULL)) != I40E_SUCCESS) {
 150  148                  i40e_error(i40e, "failed to add mac address "
 151  149                      "%2x:%2x:%2x:%2x:%2x:%2x to unicast filter: %d",
 152  150                      mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3],
 153  151                      mac_addr[4], mac_addr[5], ret);
 154  152                  ret = EIO;
 155  153                  goto done;
 156  154          }
 157  155  
 158  156          iua = &i40e->i40e_uaddrs[i40e->i40e_resources.ifr_nmacfilt_used];
 159  157          bcopy(mac_addr, iua->iua_mac, ETHERADDRL);
 160      -        iua->iua_vsi = i40e->i40e_vsi_id;
      158 +        iua->iua_vsi = rxg->irg_vsi_seid;
 161  159          i40e->i40e_resources.ifr_nmacfilt_used++;
 162  160          ASSERT(i40e->i40e_resources.ifr_nmacfilt_used <=
 163  161              i40e->i40e_resources.ifr_nmacfilt);
 164  162          ret = 0;
 165  163  done:
 166  164          mutex_exit(&i40e->i40e_general_lock);
 167  165          return (ret);
 168  166  }
 169  167  
 170  168  static int
 171  169  i40e_m_start(void *arg)
 172  170  {
 173  171          i40e_t *i40e = arg;
 174  172          int rc = 0;
 175  173  
 176  174          mutex_enter(&i40e->i40e_general_lock);
 177  175          if (i40e->i40e_state & I40E_SUSPENDED) {
 178  176                  rc = ECANCELED;
 179  177                  goto done;
 180  178          }
 181  179  
 182  180          if (!i40e_start(i40e, B_TRUE)) {
 183  181                  rc = EIO;
 184  182                  goto done;
 185  183          }
 186  184  
 187  185          atomic_or_32(&i40e->i40e_state, I40E_STARTED);
 188  186  done:
 189  187          mutex_exit(&i40e->i40e_general_lock);
 190  188  
 191  189          return (rc);
 192  190  }
 193  191  
 194  192  static void
 195  193  i40e_m_stop(void *arg)
 196  194  {
 197  195          i40e_t *i40e = arg;
 198  196  
 199  197          mutex_enter(&i40e->i40e_general_lock);
 200  198  
 201  199          if (i40e->i40e_state & I40E_SUSPENDED)
 202  200                  goto done;
 203  201  
 204  202          atomic_and_32(&i40e->i40e_state, ~I40E_STARTED);
 205  203          i40e_stop(i40e, B_TRUE);
 206  204  done:
 207  205          mutex_exit(&i40e->i40e_general_lock);
 208  206  }
 209  207  
 210  208  /*
 211  209   * Enable and disable promiscuous mode as requested. We have to toggle both
 212  210   * unicast and multicast. Note that multicast may already be enabled due to the
 213  211   * i40e_m_multicast may toggle it itself. See i40e_main.c for more information
 214  212   * on this.
 215  213   */
 216  214  static int
 217  215  i40e_m_promisc(void *arg, boolean_t on)
 218  216  {
 219  217          i40e_t *i40e = arg;
  
    | 
      ↓ open down ↓ | 
    49 lines elided | 
    
      ↑ open up ↑ | 
  
 220  218          struct i40e_hw *hw = &i40e->i40e_hw_space;
 221  219          int ret = 0, err = 0;
 222  220  
 223  221          mutex_enter(&i40e->i40e_general_lock);
 224  222          if (i40e->i40e_state & I40E_SUSPENDED) {
 225  223                  ret = ECANCELED;
 226  224                  goto done;
 227  225          }
 228  226  
 229  227  
 230      -        ret = i40e_aq_set_vsi_unicast_promiscuous(hw, i40e->i40e_vsi_id,
      228 +        ret = i40e_aq_set_vsi_unicast_promiscuous(hw, I40E_DEF_VSI_SEID(i40e),
 231  229              on, NULL, B_FALSE);
 232  230          if (ret != I40E_SUCCESS) {
 233  231                  i40e_error(i40e, "failed to %s unicast promiscuity on "
 234  232                      "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
 235  233                      ret);
 236  234                  err = EIO;
 237  235                  goto done;
 238  236          }
 239  237  
 240  238          /*
 241  239           * If we have a non-zero mcast_promisc_count, then it has already been
 242  240           * enabled or we need to leave it that way and not touch it.
 243  241           */
 244  242          if (i40e->i40e_mcast_promisc_count > 0) {
 245  243                  i40e->i40e_promisc_on = on;
 246  244                  goto done;
 247  245          }
 248  246  
 249      -        ret = i40e_aq_set_vsi_multicast_promiscuous(hw, i40e->i40e_vsi_id,
      247 +        ret = i40e_aq_set_vsi_multicast_promiscuous(hw, I40E_DEF_VSI_SEID(i40e),
 250  248              on, NULL);
 251  249          if (ret != I40E_SUCCESS) {
 252  250                  i40e_error(i40e, "failed to %s multicast promiscuity on "
 253  251                      "the default VSI: %d", on == B_TRUE ? "enable" : "disable",
 254  252                      ret);
 255  253  
 256  254                  /*
 257  255                   * Try our best to put us back into a state that MAC expects us
 258  256                   * to be in.
 259  257                   */
 260      -                ret = i40e_aq_set_vsi_unicast_promiscuous(hw, i40e->i40e_vsi_id,
 261      -                    !on, NULL, B_FALSE);
      258 +                ret = i40e_aq_set_vsi_unicast_promiscuous(hw,
      259 +                    I40E_DEF_VSI_SEID(i40e), !on, NULL, B_FALSE);
 262  260                  if (ret != I40E_SUCCESS) {
 263  261                          i40e_error(i40e, "failed to %s unicast promiscuity on "
 264  262                              "the default VSI after toggling multicast failed: "
 265  263                              "%d", on == B_TRUE ? "disable" : "enable", ret);
 266  264                  }
 267  265  
 268  266                  err = EIO;
 269  267                  goto done;
 270  268          } else {
 271  269                  i40e->i40e_promisc_on = on;
 272  270          }
 273  271  
 274  272  done:
 275  273          mutex_exit(&i40e->i40e_general_lock);
 276  274          return (err);
 277  275  }
 278  276  
 279  277  /*
 280  278   * See the big theory statement in i40e_main.c for multicast address management.
 281  279   */
 282  280  static int
 283  281  i40e_multicast_add(i40e_t *i40e, const uint8_t *multicast_address)
 284  282  {
 285  283          struct i40e_hw *hw = &i40e->i40e_hw_space;
 286  284          struct i40e_aqc_add_macvlan_element_data filt;
  
    | 
      ↓ open down ↓ | 
    15 lines elided | 
    
      ↑ open up ↑ | 
  
 287  285          i40e_maddr_t *mc;
 288  286          int ret;
 289  287  
 290  288          ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
 291  289  
 292  290          if (i40e->i40e_resources.ifr_nmcastfilt_used ==
 293  291              i40e->i40e_resources.ifr_nmcastfilt) {
 294  292                  if (i40e->i40e_mcast_promisc_count == 0 &&
 295  293                      i40e->i40e_promisc_on == B_FALSE) {
 296  294                          ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
 297      -                            i40e->i40e_vsi_id, B_TRUE, NULL);
      295 +                            I40E_DEF_VSI_SEID(i40e), B_TRUE, NULL);
 298  296                          if (ret != I40E_SUCCESS) {
 299  297                                  i40e_error(i40e, "failed to enable multicast "
 300  298                                      "promiscuous mode on VSI %d: %d",
 301      -                                    i40e->i40e_vsi_id, ret);
      299 +                                    I40E_DEF_VSI_SEID(i40e), ret);
 302  300                                  return (EIO);
 303  301                          }
 304  302                  }
 305  303                  i40e->i40e_mcast_promisc_count++;
 306  304                  return (0);
 307  305          }
 308  306  
 309  307          mc = &i40e->i40e_maddrs[i40e->i40e_resources.ifr_nmcastfilt_used];
 310  308          bzero(&filt, sizeof (filt));
 311  309          bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
 312  310          filt.flags = I40E_AQC_MACVLAN_ADD_HASH_MATCH |
 313  311              I40E_AQC_MACVLAN_ADD_IGNORE_VLAN;
 314  312  
 315      -        if ((ret = i40e_aq_add_macvlan(hw, i40e->i40e_vsi_id, &filt, 1,
      313 +        if ((ret = i40e_aq_add_macvlan(hw, I40E_DEF_VSI_SEID(i40e), &filt, 1,
 316  314              NULL)) != I40E_SUCCESS) {
 317  315                  i40e_error(i40e, "failed to add mac address "
 318  316                      "%2x:%2x:%2x:%2x:%2x:%2x to multicast filter: %d",
 319  317                      multicast_address[0], multicast_address[1],
 320  318                      multicast_address[2], multicast_address[3],
 321  319                      multicast_address[4], multicast_address[5],
 322  320                      ret);
 323  321                  return (EIO);
 324  322          }
 325  323  
 326  324          bcopy(multicast_address, mc->ima_mac, ETHERADDRL);
 327  325          i40e->i40e_resources.ifr_nmcastfilt_used++;
 328  326          return (0);
 329  327  }
 330  328  
 331  329  /*
 332  330   * See the big theory statement in i40e_main.c for multicast address management.
 333  331   */
 334  332  static int
 335  333  i40e_multicast_remove(i40e_t *i40e, const uint8_t *multicast_address)
 336  334  {
 337  335          int i, ret;
 338  336          struct i40e_hw *hw = &i40e->i40e_hw_space;
 339  337  
 340  338          ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
 341  339  
 342  340          for (i = 0; i < i40e->i40e_resources.ifr_nmcastfilt_used; i++) {
 343  341                  struct i40e_aqc_remove_macvlan_element_data filt;
 344  342                  int last;
 345  343  
  
    | 
      ↓ open down ↓ | 
    20 lines elided | 
    
      ↑ open up ↑ | 
  
 346  344                  if (bcmp(multicast_address, i40e->i40e_maddrs[i].ima_mac,
 347  345                      ETHERADDRL) != 0) {
 348  346                          continue;
 349  347                  }
 350  348  
 351  349                  bzero(&filt, sizeof (filt));
 352  350                  bcopy(multicast_address, filt.mac_addr, ETHERADDRL);
 353  351                  filt.flags = I40E_AQC_MACVLAN_DEL_HASH_MATCH |
 354  352                      I40E_AQC_MACVLAN_DEL_IGNORE_VLAN;
 355  353  
 356      -                if (i40e_aq_remove_macvlan(hw, i40e->i40e_vsi_id,
 357      -                    &filt, 1, NULL) != I40E_SUCCESS) {
      354 +                if (i40e_aq_remove_macvlan(hw, I40E_DEF_VSI_SEID(i40e), &filt,
      355 +                    1, NULL) != I40E_SUCCESS) {
 358  356                          i40e_error(i40e, "failed to remove mac address "
 359  357                              "%2x:%2x:%2x:%2x:%2x:%2x from multicast "
 360  358                              "filter: %d",
 361  359                              multicast_address[0], multicast_address[1],
 362  360                              multicast_address[2], multicast_address[3],
 363  361                              multicast_address[4], multicast_address[5],
 364  362                              filt.error_code);
 365  363                          return (EIO);
 366  364                  }
 367  365  
 368  366                  last = i40e->i40e_resources.ifr_nmcastfilt_used - 1;
 369  367                  if (i != last) {
 370  368                          bcopy(&i40e->i40e_maddrs[last], &i40e->i40e_maddrs[i],
 371  369                              sizeof (i40e_maddr_t));
 372  370                          bzero(&i40e->i40e_maddrs[last], sizeof (i40e_maddr_t));
 373  371                  }
  
    | 
      ↓ open down ↓ | 
    6 lines elided | 
    
      ↑ open up ↑ | 
  
 374  372  
 375  373                  ASSERT(i40e->i40e_resources.ifr_nmcastfilt_used > 0);
 376  374                  i40e->i40e_resources.ifr_nmcastfilt_used--;
 377  375                  return (0);
 378  376          }
 379  377  
 380  378          if (i40e->i40e_mcast_promisc_count > 0) {
 381  379                  if (i40e->i40e_mcast_promisc_count == 1 &&
 382  380                      i40e->i40e_promisc_on == B_FALSE) {
 383  381                          ret = i40e_aq_set_vsi_multicast_promiscuous(hw,
 384      -                            i40e->i40e_vsi_id, B_FALSE, NULL);
      382 +                            I40E_DEF_VSI_SEID(i40e), B_FALSE, NULL);
 385  383                          if (ret != I40E_SUCCESS) {
 386  384                                  i40e_error(i40e, "failed to disable "
 387  385                                      "multicast promiscuous mode on VSI %d: %d",
 388      -                                    i40e->i40e_vsi_id, ret);
      386 +                                    I40E_DEF_VSI_SEID(i40e), ret);
 389  387                                  return (EIO);
 390  388                          }
 391  389                  }
 392  390                  i40e->i40e_mcast_promisc_count--;
 393  391  
 394  392                  return (0);
 395  393          }
 396  394  
 397  395          return (ENOENT);
 398  396  }
 399  397  
 400  398  static int
 401  399  i40e_m_multicast(void *arg, boolean_t add, const uint8_t *multicast_address)
 402  400  {
 403  401          i40e_t *i40e = arg;
 404  402          int rc;
 405  403  
 406  404          mutex_enter(&i40e->i40e_general_lock);
 407  405  
 408  406          if (i40e->i40e_state & I40E_SUSPENDED) {
 409  407                  mutex_exit(&i40e->i40e_general_lock);
 410  408                  return (ECANCELED);
 411  409          }
 412  410  
 413  411          if (add == B_TRUE) {
 414  412                  rc = i40e_multicast_add(i40e, multicast_address);
 415  413          } else {
 416  414                  rc = i40e_multicast_remove(i40e, multicast_address);
 417  415          }
 418  416  
 419  417          mutex_exit(&i40e->i40e_general_lock);
 420  418          return (rc);
 421  419  }
 422  420  
 423  421  /* ARGSUSED */
 424  422  static void
 425  423  i40e_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
 426  424  {
 427  425          /*
 428  426           * At this time, we don't support toggling i40e into loopback mode. It's
 429  427           * questionable how much value this has when there's no clear way to
 430  428           * toggle this behavior from a supported way in userland.
 431  429           */
 432  430          miocnak(q, mp, 0, EINVAL);
 433  431  }
 434  432  
 435  433  static int
 436  434  i40e_ring_start(mac_ring_driver_t rh, uint64_t gen_num)
 437  435  {
 438  436          i40e_trqpair_t *itrq = (i40e_trqpair_t *)rh;
 439  437  
 440  438          /*
 441  439           * GLDv3 requires we keep track of a generation number, as it uses
 442  440           * that number to keep track of whether or not a ring is active.
 443  441           */
 444  442          mutex_enter(&itrq->itrq_rx_lock);
 445  443          itrq->itrq_rxgen = gen_num;
 446  444          mutex_exit(&itrq->itrq_rx_lock);
 447  445          return (0);
 448  446  }
 449  447  
 450  448  /* ARGSUSED */
 451  449  static int
 452  450  i40e_rx_ring_intr_enable(mac_intr_handle_t intrh)
 453  451  {
 454  452          i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
 455  453  
 456  454          mutex_enter(&itrq->itrq_rx_lock);
 457  455          ASSERT(itrq->itrq_intr_poll == B_TRUE);
 458  456          i40e_intr_rx_queue_enable(itrq);
 459  457          itrq->itrq_intr_poll = B_FALSE;
 460  458          mutex_exit(&itrq->itrq_rx_lock);
 461  459  
 462  460          return (0);
 463  461  }
 464  462  
 465  463  /* ARGSUSED */
 466  464  static int
 467  465  i40e_rx_ring_intr_disable(mac_intr_handle_t intrh)
 468  466  {
 469  467          i40e_trqpair_t *itrq = (i40e_trqpair_t *)intrh;
 470  468  
 471  469          mutex_enter(&itrq->itrq_rx_lock);
 472  470          i40e_intr_rx_queue_disable(itrq);
 473  471          itrq->itrq_intr_poll = B_TRUE;
 474  472          mutex_exit(&itrq->itrq_rx_lock);
 475  473  
 476  474          return (0);
 477  475  }
 478  476  
 479  477  /* ARGSUSED */
 480  478  static void
 481  479  i40e_fill_tx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
 482  480      const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
  
    | 
      ↓ open down ↓ | 
    84 lines elided | 
    
      ↑ open up ↑ | 
  
 483  481  {
 484  482          i40e_t *i40e = arg;
 485  483          mac_intr_t *mintr = &infop->mri_intr;
 486  484          i40e_trqpair_t *itrq = &(i40e->i40e_trqpairs[ring_index]);
 487  485  
 488  486          /*
 489  487           * Note the group index here is expected to be -1 due to the fact that
 490  488           * we're not actually grouping things tx-wise at this time.
 491  489           */
 492  490          ASSERT(group_index == -1);
 493      -        ASSERT(ring_index < i40e->i40e_num_trqpairs);
      491 +        ASSERT(ring_index < i40e->i40e_num_trqpairs_per_vsi);
 494  492  
 495  493          itrq->itrq_mactxring = rh;
 496  494          infop->mri_driver = (mac_ring_driver_t)itrq;
 497  495          infop->mri_start = NULL;
 498  496          infop->mri_stop = NULL;
 499  497          infop->mri_tx = i40e_ring_tx;
 500  498          infop->mri_stat = i40e_tx_ring_stat;
 501  499  
 502  500          /*
 503  501           * We only provide the handle in cases where we have MSI-X interrupts,
 504  502           * to indicate that we'd actually support retargetting.
 505  503           */
 506  504          if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
 507  505                  mintr->mi_ddi_handle =
 508  506                      i40e->i40e_intr_handles[itrq->itrq_tx_intrvec];
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
 509  507          }
 510  508  }
 511  509  
 512  510  /* ARGSUSED */
 513  511  static void
 514  512  i40e_fill_rx_ring(void *arg, mac_ring_type_t rtype, const int group_index,
 515  513      const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh)
 516  514  {
 517  515          i40e_t *i40e = arg;
 518  516          mac_intr_t *mintr = &infop->mri_intr;
 519      -        i40e_trqpair_t *itrq = &i40e->i40e_trqpairs[ring_index];
      517 +        uint_t trqpair_index;
      518 +        i40e_trqpair_t *itrq;
 520  519  
 521      -        /*
 522      -         * We assert the group number and ring index to help sanity check
 523      -         * ourselves and mark that we'll need to rework this when we have
 524      -         * multiple groups.
 525      -         */
 526      -        ASSERT3S(group_index, ==, 0);
 527      -        ASSERT3S(ring_index, <, i40e->i40e_num_trqpairs);
      520 +        /* This assumes static groups. */
      521 +        ASSERT3S(group_index, >=, 0);
      522 +        ASSERT3S(ring_index, >=, 0);
      523 +        trqpair_index = (group_index * i40e->i40e_num_trqpairs_per_vsi) +
      524 +            ring_index;
      525 +        ASSERT3U(trqpair_index, <, i40e->i40e_num_trqpairs);
      526 +        itrq = &i40e->i40e_trqpairs[trqpair_index];
 528  527  
 529  528          itrq->itrq_macrxring = rh;
 530  529          infop->mri_driver = (mac_ring_driver_t)itrq;
 531  530          infop->mri_start = i40e_ring_start;
 532  531          infop->mri_stop = NULL;
 533  532          infop->mri_poll = i40e_ring_rx_poll;
 534  533          infop->mri_stat = i40e_rx_ring_stat;
 535  534          mintr->mi_handle = (mac_intr_handle_t)itrq;
 536  535          mintr->mi_enable = i40e_rx_ring_intr_enable;
 537  536          mintr->mi_disable = i40e_rx_ring_intr_disable;
 538  537  
 539  538          /*
 540  539           * We only provide the handle in cases where we have MSI-X interrupts,
 541  540           * to indicate that we'd actually support retargetting.
 542  541           */
 543  542          if (i40e->i40e_intr_type & DDI_INTR_TYPE_MSIX) {
 544  543                  mintr->mi_ddi_handle =
  
    | 
      ↓ open down ↓ | 
    7 lines elided | 
    
      ↑ open up ↑ | 
  
 545  544                      i40e->i40e_intr_handles[itrq->itrq_rx_intrvec];
 546  545          }
 547  546  }
 548  547  
 549  548  /* ARGSUSED */
 550  549  static void
 551  550  i40e_fill_rx_group(void *arg, mac_ring_type_t rtype, const int index,
 552  551      mac_group_info_t *infop, mac_group_handle_t gh)
 553  552  {
 554  553          i40e_t *i40e = arg;
      554 +        i40e_rx_group_t *rxg;
 555  555  
 556  556          if (rtype != MAC_RING_TYPE_RX)
 557  557                  return;
 558  558  
 559      -        /*
 560      -         * Note, this is a simplified view of a group, given that we only have a
 561      -         * single group and a single ring at the moment. We'll want to expand
 562      -         * upon this as we leverage more hardware functionality.
 563      -         */
 564      -        i40e->i40e_rx_group_handle = gh;
 565      -        infop->mgi_driver = (mac_group_driver_t)i40e;
      559 +        rxg = &i40e->i40e_rx_groups[index];
      560 +        rxg->irg_grp_hdl = gh;
      561 +
      562 +        infop->mgi_driver = (mac_group_driver_t)rxg;
 566  563          infop->mgi_start = NULL;
 567  564          infop->mgi_stop = NULL;
 568  565          infop->mgi_addmac = i40e_group_add_mac;
 569  566          infop->mgi_remmac = i40e_group_remove_mac;
 570  567  
 571      -        ASSERT(i40e->i40e_num_rx_groups == I40E_GROUP_MAX);
 572      -        infop->mgi_count = i40e->i40e_num_trqpairs;
      568 +        ASSERT(i40e->i40e_num_rx_groups <= I40E_GROUP_MAX);
      569 +        infop->mgi_count = i40e->i40e_num_trqpairs_per_vsi;
 573  570  }
 574  571  
 575  572  static int
 576  573  i40e_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop)
 577  574  {
 578  575          boolean_t present, usable;
 579  576          i40e_t *i40e = arg;
 580  577  
 581  578          if (id != 0 || infop == NULL)
 582  579                  return (EINVAL);
 583  580  
 584  581          mutex_enter(&i40e->i40e_general_lock);
      582 +        switch (i40e->i40e_hw_space.phy.link_info.module_type[0]) {
      583 +        case I40E_MODULE_TYPE_SFP:
      584 +        case I40E_MODULE_TYPE_QSFP:
      585 +                break;
      586 +        default:
      587 +                mutex_exit(&i40e->i40e_general_lock);
      588 +                return (ENOTSUP);
      589 +        }
      590 +
 585  591          present = !!(i40e->i40e_hw_space.phy.link_info.link_info &
 586  592              I40E_AQ_MEDIA_AVAILABLE);
 587  593          if (present) {
 588  594                  usable = !!(i40e->i40e_hw_space.phy.link_info.an_info &
 589  595                      I40E_AQ_QUALIFIED_MODULE);
 590  596          } else {
 591  597                  usable = B_FALSE;
 592  598          }
 593  599          mutex_exit(&i40e->i40e_general_lock);
 594  600  
 595  601          mac_transceiver_info_set_usable(infop, usable);
 596  602          mac_transceiver_info_set_present(infop, present);
 597  603  
 598  604          return (0);
 599  605  }
 600  606  
 601  607  static int
      608 +i40e_transceiver_read(void *arg, uint_t id, uint_t page, void *buf,
      609 +    size_t nbytes, off_t offset, size_t *nread)
      610 +{
      611 +        i40e_t *i40e = arg;
      612 +        struct i40e_hw *hw = &i40e->i40e_hw_space;
      613 +        uint8_t *buf8 = buf;
      614 +        size_t i;
      615 +
      616 +        if (id != 0 || buf == NULL || nbytes == 0 || nread == NULL ||
      617 +            (page != 0xa0 && page != 0xa2) || offset < 0)
      618 +                return (EINVAL);
      619 +
      620 +        /*
      621 +         * Both supported pages have a length of 256 bytes, ensure nothing asks
      622 +         * us to go beyond that.
      623 +         */
      624 +        if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) {
      625 +                return (EINVAL);
      626 +        }
      627 +
      628 +        mutex_enter(&i40e->i40e_general_lock);
      629 +        switch (i40e->i40e_hw_space.phy.link_info.module_type[0]) {
      630 +        case I40E_MODULE_TYPE_SFP:
      631 +        case I40E_MODULE_TYPE_QSFP:
      632 +                break;
      633 +        default:
      634 +                mutex_exit(&i40e->i40e_general_lock);
      635 +                return (ENOTSUP);
      636 +        }
      637 +
      638 +        /*
      639 +         * Make sure we have a sufficiently new firmware version to run this
      640 +         * command. This was introduced in firmware API 1.7. This is apparently
      641 +         * only supported on the XL710 MAC, not the XL722.
      642 +         */
      643 +        if (hw->mac.type != I40E_MAC_XL710 || hw->aq.api_maj_ver != 1 ||
      644 +            hw->aq.api_min_ver < 7) {
      645 +                mutex_exit(&i40e->i40e_general_lock);
      646 +                return (ENOTSUP);
      647 +        }
      648 +
      649 +        for (i = 0; i < nbytes; i++, offset++) {
      650 +                enum i40e_status_code status;
      651 +                uint32_t val;
      652 +
      653 +                status = i40e_aq_get_phy_register(hw,
      654 +                    I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, page, offset,
      655 +                    &val, NULL);
      656 +                if (status != I40E_SUCCESS) {
      657 +                        mutex_exit(&i40e->i40e_general_lock);
      658 +                        return (EIO);
      659 +                }
      660 +
      661 +                buf8[i] = (uint8_t)val;
      662 +        }
      663 +
      664 +        mutex_exit(&i40e->i40e_general_lock);
      665 +        *nread = nbytes;
      666 +
      667 +        return (0);
      668 +}
      669 +
      670 +static int
 602  671  i40e_gld_led_set(void *arg, mac_led_mode_t mode, uint_t flags)
 603  672  {
 604  673          i40e_t *i40e = arg;
 605  674          struct i40e_hw *hw = &i40e->i40e_hw_space;
 606  675  
 607  676          if (flags != 0)
 608  677                  return (EINVAL);
 609  678  
 610  679          if (mode != MAC_LED_DEFAULT &&
 611  680              mode != MAC_LED_IDENT &&
 612  681              mode != MAC_LED_OFF &&
 613  682              mode != MAC_LED_ON)
 614  683                  return (ENOTSUP);
 615  684  
 616  685          if (mode != MAC_LED_DEFAULT && !i40e->i40e_led_saved) {
 617  686                  i40e->i40e_led_status = i40e_led_get(hw);
 618  687                  i40e->i40e_led_saved = B_TRUE;
 619  688          }
 620  689  
 621  690          switch (mode) {
 622  691          case MAC_LED_DEFAULT:
 623  692                  if (i40e->i40e_led_saved) {
 624  693                          i40e_led_set(hw, i40e->i40e_led_status, B_FALSE);
 625  694                          i40e->i40e_led_status = 0;
 626  695                          i40e->i40e_led_saved = B_FALSE;
 627  696                  }
 628  697                  break;
 629  698          case MAC_LED_IDENT:
 630  699                  i40e_led_set(hw, 0xf, B_TRUE);
 631  700                  break;
 632  701          case MAC_LED_OFF:
 633  702                  i40e_led_set(hw, 0x0, B_FALSE);
 634  703                  break;
 635  704          case MAC_LED_ON:
 636  705                  i40e_led_set(hw, 0xf, B_FALSE);
 637  706                  break;
 638  707          default:
 639  708                  return (ENOTSUP);
 640  709          }
 641  710  
 642  711          return (0);
 643  712  }
 644  713  
 645  714  static boolean_t
 646  715  i40e_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
 647  716  {
 648  717          i40e_t *i40e = arg;
 649  718          mac_capab_rings_t *cap_rings;
 650  719          mac_capab_transceiver_t *mct;
 651  720          mac_capab_led_t *mcl;
 652  721  
  
    | 
      ↓ open down ↓ | 
    41 lines elided | 
    
      ↑ open up ↑ | 
  
 653  722          switch (cap) {
 654  723          case MAC_CAPAB_HCKSUM: {
 655  724                  uint32_t *txflags = cap_data;
 656  725  
 657  726                  *txflags = 0;
 658  727                  if (i40e->i40e_tx_hcksum_enable == B_TRUE)
 659  728                          *txflags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM;
 660  729                  break;
 661  730          }
 662  731  
      732 +        case MAC_CAPAB_LSO: {
      733 +                mac_capab_lso_t *cap_lso = cap_data;
      734 +
      735 +                if (i40e->i40e_tx_lso_enable == B_TRUE) {
      736 +                        cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
      737 +                        cap_lso->lso_basic_tcp_ipv4.lso_max = I40E_LSO_MAXLEN;
      738 +                } else {
      739 +                        return (B_FALSE);
      740 +                }
      741 +                break;
      742 +        }
      743 +
 663  744          case MAC_CAPAB_RINGS:
 664  745                  cap_rings = cap_data;
 665  746                  cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC;
 666  747                  switch (cap_rings->mr_type) {
 667  748                  case MAC_RING_TYPE_TX:
 668  749                          /*
 669      -                         * Note, saying we have no rings, but some number of
 670      -                         * groups indicates to MAC that it should create
 671      -                         * psuedo-groups with one for each TX ring. This may not
 672      -                         * be the long term behavior we want, but it'll work for
 673      -                         * now.
      750 +                         * Note, saying we have no groups, but some
      751 +                         * number of rings indicates to MAC that it
      752 +                         * should create psuedo-groups with one for
      753 +                         * each TX ring. This may not be the long term
      754 +                         * behavior we want, but it'll work for now.
 674  755                           */
 675  756                          cap_rings->mr_gnum = 0;
 676      -                        cap_rings->mr_rnum = i40e->i40e_num_trqpairs;
      757 +                        cap_rings->mr_rnum = i40e->i40e_num_trqpairs_per_vsi;
 677  758                          cap_rings->mr_rget = i40e_fill_tx_ring;
 678  759                          cap_rings->mr_gget = NULL;
 679  760                          cap_rings->mr_gaddring = NULL;
 680  761                          cap_rings->mr_gremring = NULL;
 681  762                          break;
 682  763                  case MAC_RING_TYPE_RX:
 683  764                          cap_rings->mr_rnum = i40e->i40e_num_trqpairs;
 684  765                          cap_rings->mr_rget = i40e_fill_rx_ring;
 685      -                        cap_rings->mr_gnum = I40E_GROUP_MAX;
      766 +                        cap_rings->mr_gnum = i40e->i40e_num_rx_groups;
 686  767                          cap_rings->mr_gget = i40e_fill_rx_group;
 687  768                          cap_rings->mr_gaddring = NULL;
 688  769                          cap_rings->mr_gremring = NULL;
 689  770                          break;
 690  771                  default:
 691  772                          return (B_FALSE);
 692  773                  }
 693  774                  break;
 694  775          case MAC_CAPAB_TRANSCEIVER:
 695  776                  mct = cap_data;
 696  777  
 697  778                  /*
 698  779                   * Firmware doesn't have a great way of telling us in advance
 699  780                   * whether we'd expect a SFF transceiver. As such, we always
 700  781                   * advertise the support for this capability.
 701  782                   */
 702  783                  mct->mct_flags = 0;
 703  784                  mct->mct_ntransceivers = 1;
 704  785                  mct->mct_info = i40e_transceiver_info;
 705      -                mct->mct_read = NULL;
      786 +                mct->mct_read = i40e_transceiver_read;
 706  787  
 707  788                  return (B_TRUE);
 708  789          case MAC_CAPAB_LED:
 709  790                  mcl = cap_data;
 710  791  
 711  792                  mcl->mcl_flags = 0;
 712  793                  mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT | MAC_LED_OFF |
 713  794                      MAC_LED_ON;
 714  795                  mcl->mcl_set = i40e_gld_led_set;
 715  796                  break;
 716  797  
 717  798          default:
 718  799                  return (B_FALSE);
 719  800          }
 720  801  
 721  802          return (B_TRUE);
 722  803  }
 723  804  
 724  805  /* ARGSUSED */
 725  806  static int
 726  807  i40e_m_setprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
 727  808      const void *pr_val)
 728  809  {
 729  810          int ret;
 730  811          long val;
 731  812          char *eptr;
 732  813  
 733  814          ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
 734  815  
 735  816          if ((ret = ddi_strtol(pr_val, &eptr, 10, &val)) != 0 ||
 736  817              *eptr != '\0') {
 737  818                  return (ret);
 738  819          }
 739  820  
 740  821          if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
 741  822                  if (val < I40E_MIN_RX_DMA_THRESH ||
 742  823                      val > I40E_MAX_RX_DMA_THRESH) {
 743  824                          return (EINVAL);
 744  825                  }
 745  826                  i40e->i40e_rx_dma_min = (uint32_t)val;
 746  827                  return (0);
 747  828          }
 748  829  
 749  830          if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
 750  831                  if (val < I40E_MIN_TX_DMA_THRESH ||
 751  832                      val > I40E_MAX_TX_DMA_THRESH) {
 752  833                          return (EINVAL);
 753  834                  }
 754  835                  i40e->i40e_tx_dma_min = (uint32_t)val;
 755  836                  return (0);
 756  837          }
 757  838  
 758  839          if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
 759  840                  if (val < I40E_MIN_ITR ||
 760  841                      val > I40E_MAX_ITR) {
 761  842                          return (EINVAL);
 762  843                  }
 763  844                  i40e->i40e_rx_itr = (uint32_t)val;
 764  845                  i40e_intr_set_itr(i40e, I40E_ITR_INDEX_RX, i40e->i40e_rx_itr);
 765  846                  return (0);
 766  847          }
 767  848  
 768  849          if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
 769  850                  if (val < I40E_MIN_ITR ||
 770  851                      val > I40E_MAX_ITR) {
 771  852                          return (EINVAL);
 772  853                  }
 773  854                  i40e->i40e_tx_itr = (uint32_t)val;
 774  855                  i40e_intr_set_itr(i40e, I40E_ITR_INDEX_TX, i40e->i40e_tx_itr);
 775  856                  return (0);
 776  857          }
 777  858  
 778  859          if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
 779  860                  if (val < I40E_MIN_ITR ||
 780  861                      val > I40E_MAX_ITR) {
 781  862                          return (EINVAL);
 782  863                  }
 783  864                  i40e->i40e_tx_itr = (uint32_t)val;
 784  865                  i40e_intr_set_itr(i40e, I40E_ITR_INDEX_OTHER,
 785  866                      i40e->i40e_other_itr);
 786  867                  return (0);
 787  868          }
 788  869  
 789  870          return (ENOTSUP);
 790  871  }
 791  872  
 792  873  static int
 793  874  i40e_m_getprop_private(i40e_t *i40e, const char *pr_name, uint_t pr_valsize,
 794  875      void *pr_val)
 795  876  {
 796  877          uint32_t val;
 797  878  
 798  879          ASSERT(MUTEX_HELD(&i40e->i40e_general_lock));
 799  880  
 800  881          if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
 801  882                  val = i40e->i40e_rx_dma_min;
 802  883          } else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
 803  884                  val = i40e->i40e_tx_dma_min;
 804  885          } else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
 805  886                  val = i40e->i40e_rx_itr;
 806  887          } else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
 807  888                  val = i40e->i40e_tx_itr;
 808  889          } else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
 809  890                  val = i40e->i40e_other_itr;
 810  891          } else {
 811  892                  return (ENOTSUP);
 812  893          }
 813  894  
 814  895          if (snprintf(pr_val, pr_valsize, "%d", val) >= pr_valsize)
 815  896                  return (ERANGE);
 816  897          return (0);
 817  898  }
 818  899  
 819  900  /*
 820  901   * Annoyingly for private properties MAC seems to ignore default values that
 821  902   * aren't strings. That means that we have to translate all of these into
 822  903   * uint32_t's and instead we size the buffer to be large enough to hold a
 823  904   * uint32_t.
 824  905   */
 825  906  /* ARGSUSED */
 826  907  static void
 827  908  i40e_m_propinfo_private(i40e_t *i40e, const char *pr_name,
 828  909      mac_prop_info_handle_t prh)
 829  910  {
 830  911          char buf[64];
 831  912          uint32_t def;
 832  913  
 833  914          if (strcmp(pr_name, I40E_PROP_RX_DMA_THRESH) == 0) {
 834  915                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
 835  916                  def = I40E_DEF_RX_DMA_THRESH;
 836  917                  mac_prop_info_set_range_uint32(prh,
 837  918                      I40E_MIN_RX_DMA_THRESH,
 838  919                      I40E_MAX_RX_DMA_THRESH);
 839  920          } else if (strcmp(pr_name, I40E_PROP_TX_DMA_THRESH) == 0) {
 840  921                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
 841  922                  def = I40E_DEF_TX_DMA_THRESH;
 842  923                  mac_prop_info_set_range_uint32(prh,
 843  924                      I40E_MIN_TX_DMA_THRESH,
 844  925                      I40E_MAX_TX_DMA_THRESH);
 845  926          } else if (strcmp(pr_name, I40E_PROP_RX_ITR) == 0) {
 846  927                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
 847  928                  def = I40E_DEF_RX_ITR;
 848  929                  mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
 849  930          } else if (strcmp(pr_name, I40E_PROP_TX_ITR) == 0) {
 850  931                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
 851  932                  def = I40E_DEF_TX_ITR;
 852  933                  mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
 853  934          } else if (strcmp(pr_name, I40E_PROP_OTHER_ITR) == 0) {
 854  935                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW);
 855  936                  def = I40E_DEF_OTHER_ITR;
 856  937                  mac_prop_info_set_range_uint32(prh, I40E_MIN_ITR, I40E_MAX_ITR);
 857  938          } else {
 858  939                  return;
 859  940          }
 860  941  
 861  942          (void) snprintf(buf, sizeof (buf), "%d", def);
 862  943          mac_prop_info_set_default_str(prh, buf);
 863  944  }
 864  945  
 865  946  static int
 866  947  i40e_m_setprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
 867  948      uint_t pr_valsize, const void *pr_val)
 868  949  {
 869  950          uint32_t new_mtu;
 870  951          i40e_t *i40e = arg;
 871  952          int ret = 0;
 872  953  
 873  954          mutex_enter(&i40e->i40e_general_lock);
 874  955          if (i40e->i40e_state & I40E_SUSPENDED) {
 875  956                  mutex_exit(&i40e->i40e_general_lock);
 876  957                  return (ECANCELED);
 877  958          }
 878  959  
 879  960          switch (pr_num) {
 880  961          /*
 881  962           * These properties are always read-only across every device.
 882  963           */
 883  964          case MAC_PROP_DUPLEX:
 884  965          case MAC_PROP_SPEED:
 885  966          case MAC_PROP_STATUS:
 886  967          case MAC_PROP_ADV_100FDX_CAP:
 887  968          case MAC_PROP_ADV_1000FDX_CAP:
 888  969          case MAC_PROP_ADV_10GFDX_CAP:
 889  970          case MAC_PROP_ADV_25GFDX_CAP:
 890  971          case MAC_PROP_ADV_40GFDX_CAP:
 891  972                  ret = ENOTSUP;
 892  973                  break;
 893  974          /*
 894  975           * These are read-only at this time as we don't support configuring
 895  976           * auto-negotiation. See the theory statement in i40e_main.c.
 896  977           */
 897  978          case MAC_PROP_EN_100FDX_CAP:
 898  979          case MAC_PROP_EN_1000FDX_CAP:
 899  980          case MAC_PROP_EN_10GFDX_CAP:
 900  981          case MAC_PROP_EN_25GFDX_CAP:
 901  982          case MAC_PROP_EN_40GFDX_CAP:
 902  983          case MAC_PROP_AUTONEG:
 903  984          case MAC_PROP_FLOWCTRL:
 904  985                  ret = ENOTSUP;
 905  986                  break;
 906  987  
 907  988          case MAC_PROP_MTU:
 908  989                  bcopy(pr_val, &new_mtu, sizeof (new_mtu));
 909  990                  if (new_mtu == i40e->i40e_sdu)
 910  991                          break;
 911  992  
 912  993                  if (new_mtu < I40E_MIN_MTU ||
 913  994                      new_mtu > I40E_MAX_MTU) {
 914  995                          ret = EINVAL;
 915  996                          break;
 916  997                  }
 917  998  
 918  999                  if (i40e->i40e_state & I40E_STARTED) {
 919 1000                          ret = EBUSY;
 920 1001                          break;
 921 1002                  }
 922 1003  
 923 1004                  ret = mac_maxsdu_update(i40e->i40e_mac_hdl, new_mtu);
 924 1005                  if (ret == 0) {
 925 1006                          i40e->i40e_sdu = new_mtu;
 926 1007                          i40e_update_mtu(i40e);
 927 1008                  }
 928 1009                  break;
 929 1010  
 930 1011          case MAC_PROP_PRIVATE:
 931 1012                  ret = i40e_m_setprop_private(i40e, pr_name, pr_valsize, pr_val);
 932 1013                  break;
 933 1014          default:
 934 1015                  ret = ENOTSUP;
 935 1016                  break;
 936 1017          }
 937 1018  
 938 1019          mutex_exit(&i40e->i40e_general_lock);
 939 1020          return (ret);
 940 1021  }
 941 1022  
 942 1023  static int
 943 1024  i40e_m_getprop(void *arg, const char *pr_name, mac_prop_id_t pr_num,
 944 1025      uint_t pr_valsize, void *pr_val)
 945 1026  {
 946 1027          i40e_t *i40e = arg;
 947 1028          uint64_t speed;
 948 1029          int ret = 0;
 949 1030          uint8_t *u8;
 950 1031          link_flowctrl_t fctl;
 951 1032  
 952 1033          mutex_enter(&i40e->i40e_general_lock);
 953 1034  
 954 1035          switch (pr_num) {
 955 1036          case MAC_PROP_DUPLEX:
 956 1037                  if (pr_valsize < sizeof (link_duplex_t)) {
 957 1038                          ret = EOVERFLOW;
 958 1039                          break;
 959 1040                  }
 960 1041                  bcopy(&i40e->i40e_link_duplex, pr_val, sizeof (link_duplex_t));
 961 1042                  break;
 962 1043          case MAC_PROP_SPEED:
 963 1044                  if (pr_valsize < sizeof (uint64_t)) {
 964 1045                          ret = EOVERFLOW;
 965 1046                          break;
 966 1047                  }
 967 1048                  speed = i40e->i40e_link_speed * 1000000ULL;
 968 1049                  bcopy(&speed, pr_val, sizeof (speed));
 969 1050                  break;
 970 1051          case MAC_PROP_STATUS:
 971 1052                  if (pr_valsize < sizeof (link_state_t)) {
 972 1053                          ret = EOVERFLOW;
 973 1054                          break;
 974 1055                  }
 975 1056                  bcopy(&i40e->i40e_link_state, pr_val, sizeof (link_state_t));
 976 1057                  break;
 977 1058          case MAC_PROP_AUTONEG:
 978 1059                  if (pr_valsize < sizeof (uint8_t)) {
 979 1060                          ret = EOVERFLOW;
 980 1061                          break;
 981 1062                  }
 982 1063                  u8 = pr_val;
 983 1064                  *u8 = 1;
 984 1065                  break;
 985 1066          case MAC_PROP_FLOWCTRL:
 986 1067                  /*
 987 1068                   * Because we don't currently support hardware flow control, we
 988 1069                   * just hardcode this to be none.
 989 1070                   */
 990 1071                  if (pr_valsize < sizeof (link_flowctrl_t)) {
 991 1072                          ret = EOVERFLOW;
 992 1073                          break;
 993 1074                  }
 994 1075                  fctl = LINK_FLOWCTRL_NONE;
 995 1076                  bcopy(&fctl, pr_val, sizeof (link_flowctrl_t));
 996 1077                  break;
 997 1078          case MAC_PROP_MTU:
 998 1079                  if (pr_valsize < sizeof (uint32_t)) {
 999 1080                          ret = EOVERFLOW;
1000 1081                          break;
1001 1082                  }
1002 1083                  bcopy(&i40e->i40e_sdu, pr_val, sizeof (uint32_t));
1003 1084                  break;
1004 1085  
1005 1086          /*
1006 1087           * Because we don't let users control the speeds we may auto-negotiate
1007 1088           * to, the values of the ADV_ and EN_ will always be the same.
1008 1089           */
1009 1090          case MAC_PROP_ADV_100FDX_CAP:
1010 1091          case MAC_PROP_EN_100FDX_CAP:
1011 1092                  if (pr_valsize < sizeof (uint8_t)) {
1012 1093                          ret = EOVERFLOW;
1013 1094                          break;
1014 1095                  }
1015 1096                  u8 = pr_val;
1016 1097                  *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0;
1017 1098                  break;
1018 1099          case MAC_PROP_ADV_1000FDX_CAP:
1019 1100          case MAC_PROP_EN_1000FDX_CAP:
1020 1101                  if (pr_valsize < sizeof (uint8_t)) {
1021 1102                          ret = EOVERFLOW;
1022 1103                          break;
1023 1104                  }
1024 1105                  u8 = pr_val;
1025 1106                  *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0;
1026 1107                  break;
1027 1108          case MAC_PROP_ADV_10GFDX_CAP:
1028 1109          case MAC_PROP_EN_10GFDX_CAP:
1029 1110                  if (pr_valsize < sizeof (uint8_t)) {
1030 1111                          ret = EOVERFLOW;
1031 1112                          break;
1032 1113                  }
1033 1114                  u8 = pr_val;
1034 1115                  *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0;
1035 1116                  break;
1036 1117          case MAC_PROP_ADV_25GFDX_CAP:
1037 1118          case MAC_PROP_EN_25GFDX_CAP:
1038 1119                  if (pr_valsize < sizeof (uint8_t)) {
1039 1120                          ret = EOVERFLOW;
1040 1121                          break;
1041 1122                  }
1042 1123                  u8 = pr_val;
1043 1124                  *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0;
1044 1125                  break;
1045 1126          case MAC_PROP_ADV_40GFDX_CAP:
1046 1127          case MAC_PROP_EN_40GFDX_CAP:
1047 1128                  if (pr_valsize < sizeof (uint8_t)) {
1048 1129                          ret = EOVERFLOW;
1049 1130                          break;
1050 1131                  }
1051 1132                  u8 = pr_val;
1052 1133                  *u8 = (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0;
1053 1134                  break;
1054 1135          case MAC_PROP_PRIVATE:
1055 1136                  ret = i40e_m_getprop_private(i40e, pr_name, pr_valsize, pr_val);
1056 1137                  break;
1057 1138          default:
1058 1139                  ret = ENOTSUP;
1059 1140                  break;
1060 1141          }
1061 1142  
1062 1143          mutex_exit(&i40e->i40e_general_lock);
1063 1144  
1064 1145          return (ret);
1065 1146  }
1066 1147  
1067 1148  static void
1068 1149  i40e_m_propinfo(void *arg, const char *pr_name, mac_prop_id_t pr_num,
1069 1150      mac_prop_info_handle_t prh)
1070 1151  {
1071 1152          i40e_t *i40e = arg;
1072 1153  
1073 1154          mutex_enter(&i40e->i40e_general_lock);
1074 1155  
1075 1156          switch (pr_num) {
1076 1157          case MAC_PROP_DUPLEX:
1077 1158          case MAC_PROP_SPEED:
1078 1159                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1079 1160                  break;
1080 1161          case MAC_PROP_FLOWCTRL:
1081 1162                  /*
1082 1163                   * At the moment, the driver doesn't support flow control, hence
1083 1164                   * why this is set to read-only and none.
1084 1165                   */
1085 1166                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1086 1167                  mac_prop_info_set_default_link_flowctrl(prh,
1087 1168                      LINK_FLOWCTRL_NONE);
1088 1169                  break;
1089 1170          case MAC_PROP_MTU:
1090 1171                  mac_prop_info_set_range_uint32(prh, I40E_MIN_MTU, I40E_MAX_MTU);
1091 1172                  break;
1092 1173  
1093 1174          /*
1094 1175           * We set the defaults for these based upon the phy's ability to
1095 1176           * support the speeds. Note, auto-negotiation is required for fiber,
1096 1177           * hence it is read-only and always enabled. When we have access to
1097 1178           * copper phys we can revisit this.
1098 1179           */
1099 1180          case MAC_PROP_AUTONEG:
1100 1181                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1101 1182                  mac_prop_info_set_default_uint8(prh, 1);
1102 1183                  break;
1103 1184          case MAC_PROP_ADV_100FDX_CAP:
1104 1185                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1105 1186                  mac_prop_info_set_default_uint8(prh,
1106 1187                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
1107 1188                  break;
1108 1189          case MAC_PROP_EN_100FDX_CAP:
1109 1190                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1110 1191                  mac_prop_info_set_default_uint8(prh,
1111 1192                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_100MB) != 0);
1112 1193                  break;
1113 1194          case MAC_PROP_ADV_1000FDX_CAP:
1114 1195                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1115 1196                  mac_prop_info_set_default_uint8(prh,
1116 1197                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
1117 1198                  break;
1118 1199          case MAC_PROP_EN_1000FDX_CAP:
1119 1200                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1120 1201                  mac_prop_info_set_default_uint8(prh,
1121 1202                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_1GB) != 0);
1122 1203                  break;
1123 1204          case MAC_PROP_ADV_10GFDX_CAP:
1124 1205                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1125 1206                  mac_prop_info_set_default_uint8(prh,
1126 1207                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
1127 1208                  break;
1128 1209          case MAC_PROP_EN_10GFDX_CAP:
1129 1210                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1130 1211                  mac_prop_info_set_default_uint8(prh,
1131 1212                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_10GB) != 0);
1132 1213                  break;
1133 1214          case MAC_PROP_ADV_25GFDX_CAP:
1134 1215                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1135 1216                  mac_prop_info_set_default_uint8(prh,
1136 1217                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
1137 1218                  break;
1138 1219          case MAC_PROP_EN_25GFDX_CAP:
1139 1220                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1140 1221                  mac_prop_info_set_default_uint8(prh,
1141 1222                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_25GB) != 0);
1142 1223                  break;
1143 1224          case MAC_PROP_ADV_40GFDX_CAP:
1144 1225                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1145 1226                  mac_prop_info_set_default_uint8(prh,
1146 1227                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
1147 1228                  break;
1148 1229          case MAC_PROP_EN_40GFDX_CAP:
1149 1230                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
1150 1231                  mac_prop_info_set_default_uint8(prh,
1151 1232                      (i40e->i40e_phy.link_speed & I40E_LINK_SPEED_40GB) != 0);
1152 1233                  break;
1153 1234          case MAC_PROP_PRIVATE:
1154 1235                  i40e_m_propinfo_private(i40e, pr_name, prh);
1155 1236                  break;
1156 1237          default:
1157 1238                  break;
1158 1239          }
1159 1240  
1160 1241          mutex_exit(&i40e->i40e_general_lock);
1161 1242  }
1162 1243  
1163 1244  #define I40E_M_CALLBACK_FLAGS \
1164 1245          (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO)
1165 1246  
1166 1247  static mac_callbacks_t i40e_m_callbacks = {
1167 1248          I40E_M_CALLBACK_FLAGS,
1168 1249          i40e_m_stat,
1169 1250          i40e_m_start,
1170 1251          i40e_m_stop,
1171 1252          i40e_m_promisc,
1172 1253          i40e_m_multicast,
1173 1254          NULL,
1174 1255          NULL,
1175 1256          NULL,
1176 1257          i40e_m_ioctl,
1177 1258          i40e_m_getcapab,
1178 1259          NULL,
1179 1260          NULL,
1180 1261          i40e_m_setprop,
1181 1262          i40e_m_getprop,
1182 1263          i40e_m_propinfo
1183 1264  };
1184 1265  
1185 1266  boolean_t
1186 1267  i40e_register_mac(i40e_t *i40e)
1187 1268  {
1188 1269          struct i40e_hw *hw = &i40e->i40e_hw_space;
1189 1270          int status;
1190 1271          mac_register_t *mac = mac_alloc(MAC_VERSION);
1191 1272  
1192 1273          if (mac == NULL)
1193 1274                  return (B_FALSE);
1194 1275  
1195 1276          mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
1196 1277          mac->m_driver = i40e;
1197 1278          mac->m_dip = i40e->i40e_dip;
1198 1279          mac->m_src_addr = hw->mac.addr;
1199 1280          mac->m_callbacks = &i40e_m_callbacks;
1200 1281          mac->m_min_sdu = 0;
1201 1282          mac->m_max_sdu = i40e->i40e_sdu;
1202 1283          mac->m_margin = VLAN_TAGSZ;
1203 1284          mac->m_priv_props = i40e_priv_props;
1204 1285          mac->m_v12n = MAC_VIRT_LEVEL1;
1205 1286  
1206 1287          status = mac_register(mac, &i40e->i40e_mac_hdl);
1207 1288          if (status != 0)
1208 1289                  i40e_error(i40e, "mac_register() returned %d", status);
1209 1290          mac_free(mac);
1210 1291  
1211 1292          return (status == 0);
1212 1293  }
  
    | 
      ↓ open down ↓ | 
    497 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX