Print this page
    
NEX-1890 update oce from source provided by Emulex
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/io/fibre-channel/fca/oce/oce_gld.c
          +++ new/usr/src/uts/common/io/fibre-channel/fca/oce/oce_gld.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  
    | 
      ↓ open down ↓ | 
    11 lines elided | 
    
      ↑ open up ↑ | 
  
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22      -/* Copyright © 2003-2011 Emulex. All rights reserved.  */
       22 +/*
       23 + * Copyright (c) 2009-2012 Emulex. All rights reserved.
       24 + * Use is subject to license terms.
       25 + */
  23   26  
       27 +
       28 +
  24   29  /*
  25   30   * Source file containing the implementation of the driver entry points
  26   31   * and related helper functions
  27   32   */
  28   33  
  29   34  #include <oce_impl.h>
  30   35  #include <oce_ioctl.h>
  31   36  
  32      -/* array of properties supported by this driver */
  33      -char *oce_priv_props[] = {
  34      -        "_tx_ring_size",
  35      -        "_tx_bcopy_limit",
  36      -        "_rx_ring_size",
  37      -        "_rx_bcopy_limit",
  38      -        NULL
  39      -};
  40      -
  41      -extern int pow10[];
  42      -
  43   37  /* ---[ static function declarations ]----------------------------------- */
  44   38  static int oce_set_priv_prop(struct oce_dev *dev, const char *name,
  45   39      uint_t size, const void *val);
  46   40  
  47   41  static int oce_get_priv_prop(struct oce_dev *dev, const char *name,
  48   42      uint_t size, void *val);
  49   43  
  50   44  /* ---[ GLD entry points ]----------------------------------------------- */
  51   45  int
  52   46  oce_m_start(void *arg)
  53   47  {
  54   48          struct oce_dev *dev = arg;
  55      -        int ret;
       49 +        int i;
  56   50  
  57   51          mutex_enter(&dev->dev_lock);
  58   52  
  59   53          if (dev->state & STATE_MAC_STARTED) {
  60   54                  mutex_exit(&dev->dev_lock);
  61   55                  return (0);
  62   56          }
  63   57  
  64   58          if (dev->suspended) {
  65   59                  mutex_exit(&dev->dev_lock);
  66   60                  return (EIO);
  67   61          }
  68      -        ret = oce_start(dev);
  69      -        if (ret != DDI_SUCCESS) {
       62 +
       63 +        /* allocate Tx buffers */
       64 +        if (oce_init_tx(dev) != DDI_SUCCESS) {
  70   65                  mutex_exit(&dev->dev_lock);
  71      -                return (EIO);
       66 +                oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
       67 +                    "Failed to init rings");
       68 +                return (DDI_FAILURE);
  72   69          }
  73   70  
       71 +        if (oce_start(dev) != DDI_SUCCESS) {
       72 +                oce_fini_tx(dev);
       73 +                mutex_exit(&dev->dev_lock);
       74 +                return (EIO);
       75 +        }
  74   76          dev->state |= STATE_MAC_STARTED;
  75      -        mutex_exit(&dev->dev_lock);
  76   77  
       78 +        /* initialise the group locks */
       79 +        for (i = 0; i < dev->num_rx_groups; i++) {
       80 +                mutex_init(&dev->rx_group[i].grp_lock, NULL, MUTEX_DRIVER,
       81 +                    DDI_INTR_PRI(dev->intr_pri));
       82 +        }
  77   83  
       84 +        mutex_exit(&dev->dev_lock);
       85 +        oce_enable_wd_timer(dev);
  78   86          return (DDI_SUCCESS);
  79   87  }
  80   88  
       89 +void
       90 +oce_start_eqs(struct oce_dev *dev)
       91 +{
       92 +        int qidx = 0;
       93 +
       94 +        for (qidx = 0; qidx < dev->neqs; qidx++) {
       95 +                mutex_enter(&dev->eq[qidx].lock);
       96 +                oce_arm_eq(dev, dev->eq[qidx].eq_id, 0, B_TRUE, B_FALSE);
       97 +                dev->eq[qidx].qstate = QSTARTED;
       98 +                mutex_exit(&dev->eq[qidx].lock);
       99 +        }
      100 +}
      101 +
      102 +void
      103 +oce_stop_eqs(struct oce_dev *dev)
      104 +{
      105 +        int qidx = 0;
      106 +
      107 +        for (qidx = 0; qidx < dev->neqs; qidx++) {
      108 +                mutex_enter(&dev->eq[qidx].lock);
      109 +                oce_arm_eq(dev, dev->eq[qidx].eq_id, 0, B_FALSE, B_FALSE);
      110 +                dev->eq[qidx].qstate = QSTOPPED;
      111 +                mutex_exit(&dev->eq[qidx].lock);
      112 +        }
      113 +}
  81  114  int
  82  115  oce_start(struct oce_dev *dev)
  83  116  {
  84  117          int qidx = 0;
  85      -        struct link_status link = {0};
  86  118  
  87      -        /* get link status */
  88      -        (void) oce_get_link_status(dev, &link);
      119 +        /* disable the interrupts */
      120 +        if (!LANCER_CHIP(dev))
      121 +                oce_chip_di(dev);
  89  122  
  90      -        dev->link_status  = (link.logical_link_status == NTWK_LOGICAL_LINK_UP) ?
  91      -            LINK_STATE_UP : LINK_STATE_DOWN;
      123 +        /* set default flow control */
      124 +        (void) oce_set_flow_control(dev, dev->flow_control, MBX_BOOTSTRAP);
      125 +        (void) oce_set_promiscuous(dev, dev->promisc, MBX_BOOTSTRAP);
  92  126  
  93      -        dev->link_speed = link.qos_link_speed ? link.qos_link_speed * 10 :
  94      -            pow10[link.mac_speed];
      127 +        if (oce_ei(dev) != DDI_SUCCESS) {
      128 +                return (DDI_FAILURE);
      129 +        }
  95  130  
  96      -        mac_link_update(dev->mac_handle, dev->link_status);
      131 +        if (oce_create_queues(dev) != DDI_SUCCESS) {
      132 +                goto cleanup_handler;
      133 +        }
  97  134  
  98      -        for (qidx = 0; qidx < dev->nwqs; qidx++) {
  99      -                (void) oce_start_wq(dev->wq[qidx]);
      135 +        for (qidx = 0; qidx < dev->tx_rings; qidx++) {
      136 +                mac_ring_intr_set(dev->default_tx_rings[qidx].tx->handle,
      137 +                    dev->htable[dev->default_tx_rings[qidx].tx->cq->eq->idx]);
      138 +                (void) oce_start_wq(dev->default_tx_rings[qidx].tx);
 100  139          }
 101      -        for (qidx = 0; qidx < dev->nrqs; qidx++) {
 102      -                (void) oce_start_rq(dev->rq[qidx]);
      140 +
      141 +        if (oce_create_mcc_queue(dev) != DDI_SUCCESS) {
      142 +                goto delete_queues;
 103  143          }
 104  144          (void) oce_start_mq(dev->mq);
 105      -        /* enable interrupts */
 106      -        oce_ei(dev);
      145 +
      146 +        dev->state |= STATE_INTR_ENABLED;
      147 +
      148 +        if (!LANCER_CHIP(dev))
      149 +                oce_chip_ei(dev);
      150 +
 107  151          /* arm the eqs */
 108      -        for (qidx = 0; qidx < dev->neqs; qidx++) {
 109      -                oce_arm_eq(dev, dev->eq[qidx]->eq_id, 0, B_TRUE, B_FALSE);
      152 +        oce_start_eqs(dev);
      153 +
      154 +        /* get link status */
      155 +        if (oce_get_link_status(dev, &dev->link_status, &dev->link_speed,
      156 +            (uint8_t *)&dev->link_duplex, 1, MBX_ASYNC_MQ) != DDI_SUCCESS) {
      157 +                (void) oce_get_link_status(dev, &dev->link_status,
      158 +                    &dev->link_speed, (uint8_t *)&dev->link_duplex,
      159 +                    0, MBX_ASYNC_MQ);
 110  160          }
 111      -        /* TODO update state */
      161 +        oce_log(dev, CE_NOTE, MOD_CONFIG, "link speed %d "
      162 +            "link status %d", dev->link_speed, dev->link_status);
      163 +
      164 +        mac_link_update(dev->mac_handle, dev->link_status);
 112  165          return (DDI_SUCCESS);
      166 +
      167 +delete_queues:
      168 +        oce_delete_queues(dev);
      169 +cleanup_handler:
      170 +        (void) oce_di(dev);
      171 +        return (DDI_FAILURE);
 113  172  } /* oce_start */
 114  173  
 115  174  
 116  175  void
 117  176  oce_m_stop(void *arg)
 118  177  {
 119  178          struct oce_dev *dev = arg;
      179 +        int i;
 120  180  
 121      -        /* disable interrupts */
 122      -
 123  181          mutex_enter(&dev->dev_lock);
 124  182          if (dev->suspended) {
 125  183                  mutex_exit(&dev->dev_lock);
 126  184                  return;
 127  185          }
 128      -        dev->state |= STATE_MAC_STOPPING;
      186 +
      187 +        dev->state &= ~STATE_MAC_STARTED;
 129  188          oce_stop(dev);
 130      -        dev->state &= ~(STATE_MAC_STOPPING | STATE_MAC_STARTED);
      189 +
      190 +        /* free Tx buffers */
      191 +        oce_fini_tx(dev);
      192 +
      193 +        for (i = 0; i < dev->rx_rings; i++) {
      194 +                while (dev->rq[i].pending > 0) {
      195 +                        oce_log(dev, CE_NOTE, MOD_CONFIG,
      196 +                            "%d pending buffers on rq %p\n",
      197 +                            dev->rq[i].pending, (void *)&dev->rq[i]);
      198 +                        drv_usecwait(10 * 1000);
      199 +                }
      200 +        }
      201 +
      202 +        /* destroy group locks */
      203 +        for (i = 0; i < dev->num_rx_groups; i++) {
      204 +                mutex_destroy(&dev->rx_group[i].grp_lock);
      205 +        }
      206 +
 131  207          mutex_exit(&dev->dev_lock);
      208 +        oce_disable_wd_timer(dev);
 132  209  }
      210 +
      211 +
 133  212  /* called with Tx/Rx comp locks held */
 134  213  void
 135  214  oce_stop(struct oce_dev *dev)
 136  215  {
 137  216          int qidx;
      217 +
      218 +        dev->state |= STATE_MAC_STOPPING;
      219 +
 138  220          /* disable interrupts */
 139      -        oce_di(dev);
      221 +        (void) oce_di(dev);
      222 +        oce_stop_eqs(dev);
      223 +        dev->state &= (~STATE_INTR_ENABLED);
      224 +
 140  225          for (qidx = 0; qidx < dev->nwqs; qidx++) {
 141      -                mutex_enter(&dev->wq[qidx]->tx_lock);
      226 +                mac_ring_intr_set(dev->default_tx_rings[qidx].tx->handle, NULL);
      227 +                mutex_enter(&dev->wq[qidx].tx_lock);
 142  228          }
 143  229          mutex_enter(&dev->mq->lock);
 144      -        /* complete the pending Tx */
 145      -        for (qidx = 0; qidx < dev->nwqs; qidx++)
 146      -                oce_clean_wq(dev->wq[qidx]);
      230 +
      231 +        for (qidx = 0; qidx < dev->tx_rings; qidx++) {
      232 +                /* stop and flush the Tx */
      233 +                (void) oce_clean_wq(dev->default_tx_rings[qidx].tx);
      234 +        }
      235 +
      236 +        /* Free the pending commands */
      237 +        oce_clean_mq(dev->mq);
      238 +
 147  239          /* Release all the locks */
 148  240          mutex_exit(&dev->mq->lock);
 149  241          for (qidx = 0; qidx < dev->nwqs; qidx++)
 150      -                mutex_exit(&dev->wq[qidx]->tx_lock);
      242 +                mutex_exit(&dev->wq[qidx].tx_lock);
      243 +
 151  244          if (dev->link_status == LINK_STATE_UP) {
 152  245                  dev->link_status = LINK_STATE_UNKNOWN;
 153  246                  mac_link_update(dev->mac_handle, dev->link_status);
 154  247          }
 155  248  
      249 +        oce_delete_mcc_queue(dev);
      250 +        oce_delete_queues(dev);
      251 +
      252 +        dev->state &= ~STATE_MAC_STOPPING;
 156  253  } /* oce_stop */
 157  254  
      255 +
 158  256  int
 159  257  oce_m_multicast(void *arg, boolean_t add, const uint8_t *mca)
 160  258  {
 161  259          struct oce_dev *dev = (struct oce_dev *)arg;
 162  260          struct ether_addr  *mca_drv_list;
 163  261          struct ether_addr  mca_hw_list[OCE_MAX_MCA];
 164  262          uint16_t new_mcnt = dev->num_mca;
 165  263          int ret;
 166  264          int i;
 167  265  
 168      -        /* check the address */
 169      -        if ((mca[0] & 0x1) == 0) {
 170      -                return (EINVAL);
 171      -        }
 172  266          /* Allocate the local array for holding the addresses temporarily */
 173  267          bzero(&mca_hw_list, sizeof (&mca_hw_list));
 174  268          mca_drv_list = &dev->multi_cast[0];
 175  269  
 176  270          DEV_LOCK(dev);
 177  271          if (add) {
 178  272                  /* check if we exceeded hw max  supported */
 179  273                  if (new_mcnt < OCE_MAX_MCA) {
 180  274                          /* copy entire dev mca to the mbx */
 181  275                          bcopy((void*)mca_drv_list,
 182  276                              (void*)mca_hw_list,
 183  277                              (dev->num_mca * sizeof (struct ether_addr)));
 184  278                          /* Append the new one to local list */
 185  279                          bcopy(mca, &mca_hw_list[dev->num_mca],
 186  280                              sizeof (struct ether_addr));
  
    | 
      ↓ open down ↓ | 
    5 lines elided | 
    
      ↑ open up ↑ | 
  
 187  281                  }
 188  282                  new_mcnt++;
 189  283          } else {
 190  284                  struct ether_addr *hwlistp = &mca_hw_list[0];
 191  285                  for (i = 0; i < dev->num_mca; i++) {
 192  286                          /* copy only if it does not match */
 193  287                          if (bcmp((mca_drv_list + i), mca, ETHERADDRL)) {
 194  288                                  bcopy(mca_drv_list + i, hwlistp,
 195  289                                      ETHERADDRL);
 196  290                                  hwlistp++;
 197      -                        } else {
 198      -                                new_mcnt--;
 199  291                          }
 200  292                  }
      293 +                /* Decrement the count */
      294 +                new_mcnt--;
 201  295          }
 202  296  
 203  297          if (dev->suspended) {
 204  298                  goto finish;
 205  299          }
 206  300          if (new_mcnt > OCE_MAX_MCA) {
 207  301                  ret = oce_set_multicast_table(dev, dev->if_id, &mca_hw_list[0],
 208      -                    OCE_MAX_MCA, B_TRUE);
      302 +                    OCE_MAX_MCA, B_TRUE, MBX_BOOTSTRAP);
 209  303          } else {
 210  304                  ret = oce_set_multicast_table(dev, dev->if_id,
 211      -                    &mca_hw_list[0], new_mcnt, B_FALSE);
      305 +                    &mca_hw_list[0], new_mcnt, B_FALSE, MBX_BOOTSTRAP);
 212  306          }
 213      -                if (ret != 0) {
      307 +        if (ret != 0) {
 214  308                  oce_log(dev, CE_WARN, MOD_CONFIG,
 215      -                    "mcast %s fails", add ? "ADD" : "DEL");
      309 +                    "mcast %s failed 0x%x", add ? "ADD" : "DEL", ret);
 216  310                  DEV_UNLOCK(dev);
 217  311                  return (EIO);
 218  312          }
 219  313          /*
 220  314           *  Copy the local structure to dev structure
 221  315           */
 222  316  finish:
 223  317          if (new_mcnt && new_mcnt <= OCE_MAX_MCA) {
 224  318                  bcopy(mca_hw_list, mca_drv_list,
 225  319                      new_mcnt * sizeof (struct ether_addr));
 226  320  
 227  321                  dev->num_mca = (uint16_t)new_mcnt;
  
    | 
      ↓ open down ↓ | 
    2 lines elided | 
    
      ↑ open up ↑ | 
  
 228  322          }
 229  323          DEV_UNLOCK(dev);
 230  324          oce_log(dev, CE_NOTE, MOD_CONFIG,
 231  325              "mcast %s, addr=%02x:%02x:%02x:%02x:%02x:%02x, num_mca=%d",
 232  326              add ? "ADD" : "DEL",
 233  327              mca[0], mca[1], mca[2], mca[3], mca[4], mca[5],
 234  328              dev->num_mca);
 235  329          return (0);
 236  330  } /* oce_m_multicast */
 237  331  
 238      -int
 239      -oce_m_unicast(void *arg, const uint8_t *uca)
 240      -{
 241      -        struct oce_dev *dev = arg;
 242      -        int ret;
 243  332  
 244      -        DEV_LOCK(dev);
 245      -        if (dev->suspended) {
 246      -                bcopy(uca, dev->unicast_addr, ETHERADDRL);
 247      -                dev->num_smac = 0;
 248      -                DEV_UNLOCK(dev);
 249      -                return (DDI_SUCCESS);
 250      -        }
 251      -
 252      -        /* Delete previous one and add new one */
 253      -        ret = oce_del_mac(dev, dev->if_id, &dev->pmac_id);
 254      -        if (ret != DDI_SUCCESS) {
 255      -                DEV_UNLOCK(dev);
 256      -                return (EIO);
 257      -        }
 258      -        dev->num_smac = 0;
 259      -        bzero(dev->unicast_addr, ETHERADDRL);
 260      -
 261      -        /* Set the New MAC addr earlier is no longer valid */
 262      -        ret = oce_add_mac(dev, dev->if_id, uca, &dev->pmac_id);
 263      -        if (ret != DDI_SUCCESS) {
 264      -                DEV_UNLOCK(dev);
 265      -                return (EIO);
 266      -        }
 267      -        bcopy(uca, dev->unicast_addr, ETHERADDRL);
 268      -        dev->num_smac = 1;
 269      -        DEV_UNLOCK(dev);
 270      -        return (ret);
 271      -} /* oce_m_unicast */
 272      -
 273      -/*
 274      - * Hashing policy for load balancing over the set of TX rings
 275      - * available to the driver.
 276      - */
 277      -mblk_t *
 278      -oce_m_send(void *arg, mblk_t *mp)
 279      -{
 280      -        struct oce_dev *dev = arg;
 281      -        mblk_t *nxt_pkt;
 282      -        mblk_t *rmp = NULL;
 283      -        struct oce_wq *wq;
 284      -
 285      -        DEV_LOCK(dev);
 286      -        if (dev->suspended || !(dev->state & STATE_MAC_STARTED)) {
 287      -                DEV_UNLOCK(dev);
 288      -                freemsg(mp);
 289      -                return (NULL);
 290      -        }
 291      -        DEV_UNLOCK(dev);
 292      -        /*
 293      -         * Hash to pick a wq
 294      -         */
 295      -        wq = oce_get_wq(dev, mp);
 296      -
 297      -        while (mp != NULL) {
 298      -                /* Save the Pointer since mp will be freed in case of copy */
 299      -                nxt_pkt = mp->b_next;
 300      -                mp->b_next = NULL;
 301      -                /* Hardcode wq since we have only one */
 302      -                rmp = oce_send_packet(wq, mp);
 303      -                if (rmp != NULL) {
 304      -                        /* reschedule Tx */
 305      -                        wq->resched = B_TRUE;
 306      -                        oce_arm_cq(dev, wq->cq->cq_id, 0, B_TRUE);
 307      -                        /* restore the chain */
 308      -                        rmp->b_next = nxt_pkt;
 309      -                        break;
 310      -                }
 311      -                mp  = nxt_pkt;
 312      -        }
 313      -        return (rmp);
 314      -} /* oce_send */
 315      -
 316  333  boolean_t
 317  334  oce_m_getcap(void *arg, mac_capab_t cap, void *data)
 318  335  {
 319  336          struct oce_dev *dev = arg;
 320  337          boolean_t ret = B_TRUE;
 321  338          switch (cap) {
 322  339  
 323  340          case MAC_CAPAB_HCKSUM: {
 324  341                  uint32_t *csum_flags = u32ptr(data);
 325  342                  *csum_flags = HCKSUM_ENABLE |
 326  343                      HCKSUM_INET_FULL_V4 |
 327  344                      HCKSUM_IPHDRCKSUM;
 328  345                  break;
 329  346          }
  
    | 
      ↓ open down ↓ | 
    4 lines elided | 
    
      ↑ open up ↑ | 
  
 330  347          case MAC_CAPAB_LSO: {
 331  348                  mac_capab_lso_t *mcap_lso = (mac_capab_lso_t *)data;
 332  349                  if (dev->lso_capable) {
 333  350                          mcap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
 334  351                          mcap_lso->lso_basic_tcp_ipv4.lso_max = OCE_LSO_MAX_SIZE;
 335  352                  } else {
 336  353                          ret = B_FALSE;
 337  354                  }
 338  355                  break;
 339  356          }
      357 +        case MAC_CAPAB_RINGS:
      358 +
      359 +                ret = oce_fill_rings_capab(dev, (mac_capab_rings_t *)data);
      360 +                break;
      361 +
 340  362          default:
 341  363                  ret = B_FALSE;
 342  364                  break;
 343  365          }
 344  366          return (ret);
 345  367  } /* oce_m_getcap */
 346  368  
 347  369  int
 348  370  oce_m_setprop(void *arg, const char *name, mac_prop_id_t id,
 349  371      uint_t size, const void *val)
 350  372  {
 351  373          struct oce_dev *dev = arg;
 352  374          int ret = 0;
 353  375  
 354  376          DEV_LOCK(dev);
 355  377          switch (id) {
 356  378          case MAC_PROP_MTU: {
 357  379                  uint32_t mtu;
 358  380  
 359  381                  bcopy(val, &mtu, sizeof (uint32_t));
 360  382  
  
    | 
      ↓ open down ↓ | 
    11 lines elided | 
    
      ↑ open up ↑ | 
  
 361  383                  if (dev->mtu == mtu) {
 362  384                          ret = 0;
 363  385                          break;
 364  386                  }
 365  387  
 366  388                  if (mtu != OCE_MIN_MTU && mtu != OCE_MAX_MTU) {
 367  389                          ret = EINVAL;
 368  390                          break;
 369  391                  }
 370  392  
      393 +                if (dev->state & STATE_MAC_STARTED) {
      394 +                        ret =  EBUSY;
      395 +                        break;
      396 +                }
      397 +
 371  398                  ret = mac_maxsdu_update(dev->mac_handle, mtu);
 372  399                  if (0 == ret) {
 373  400                          dev->mtu = mtu;
 374  401                          break;
 375  402                  }
 376  403                  break;
 377  404          }
 378  405  
 379  406          case MAC_PROP_FLOWCTRL: {
 380  407                  link_flowctrl_t flowctrl;
 381  408                  uint32_t fc = 0;
 382  409  
 383  410                  bcopy(val, &flowctrl, sizeof (link_flowctrl_t));
 384  411  
 385  412                  switch (flowctrl) {
 386  413                  case LINK_FLOWCTRL_NONE:
 387  414                          fc = 0;
 388  415                          break;
 389  416  
 390  417                  case LINK_FLOWCTRL_RX:
 391  418                          fc = OCE_FC_RX;
 392  419                          break;
 393  420  
 394  421                  case LINK_FLOWCTRL_TX:
 395  422                          fc = OCE_FC_TX;
 396  423                          break;
 397  424  
 398  425                  case LINK_FLOWCTRL_BI:
 399  426                          fc = OCE_FC_RX | OCE_FC_TX;
 400  427                          break;
 401  428                  default:
 402  429                          ret = EINVAL;
 403  430                          break;
 404  431                  } /* switch flowctrl */
 405  432  
 406  433                  if (ret)
  
    | 
      ↓ open down ↓ | 
    26 lines elided | 
    
      ↑ open up ↑ | 
  
 407  434                          break;
 408  435  
 409  436                  if (fc == dev->flow_control)
 410  437                          break;
 411  438  
 412  439                  if (dev->suspended) {
 413  440                          dev->flow_control = fc;
 414  441                          break;
 415  442                  }
 416  443                  /* call to set flow control */
 417      -                ret = oce_set_flow_control(dev, fc);
      444 +                ret = oce_set_flow_control(dev, fc, MBX_ASYNC_MQ);
 418  445                  /* store the new fc setting on success */
 419  446                  if (ret == 0) {
 420      -                dev->flow_control = fc;
      447 +                        dev->flow_control = fc;
 421  448                  }
 422  449                  break;
 423  450          }
 424  451  
 425  452          case MAC_PROP_PRIVATE:
 426  453                  ret = oce_set_priv_prop(dev, name, size, val);
 427  454                  break;
 428  455  
 429  456          default:
 430  457                  ret = ENOTSUP;
 431  458                  break;
 432  459          } /* switch id */
 433  460  
 434  461          DEV_UNLOCK(dev);
 435  462          return (ret);
 436  463  } /* oce_m_setprop */
 437  464  
 438  465  int
 439  466  oce_m_getprop(void *arg, const char *name, mac_prop_id_t id,
 440  467      uint_t size, void *val)
 441  468  {
 442  469          struct oce_dev *dev = arg;
 443  470          uint32_t ret = 0;
 444  471  
 445  472          switch (id) {
 446  473          case MAC_PROP_ADV_10GFDX_CAP:
 447  474          case MAC_PROP_EN_10GFDX_CAP:
 448  475                  *(uint8_t *)val = 0x01;
 449  476                  break;
 450  477  
 451  478          case MAC_PROP_DUPLEX: {
 452  479                  uint32_t *mode = (uint32_t *)val;
  
    | 
      ↓ open down ↓ | 
    22 lines elided | 
    
      ↑ open up ↑ | 
  
 453  480  
 454  481                  ASSERT(size >= sizeof (link_duplex_t));
 455  482                  if (dev->state & STATE_MAC_STARTED)
 456  483                          *mode = LINK_DUPLEX_FULL;
 457  484                  else
 458  485                          *mode = LINK_DUPLEX_UNKNOWN;
 459  486                  break;
 460  487          }
 461  488  
 462  489          case MAC_PROP_SPEED: {
 463      -                uint64_t *speed = (uint64_t *)val;
 464      -                struct link_status link = {0};
 465      -
 466      -                ASSERT(size >= sizeof (uint64_t));
 467      -                *speed = 0;
 468      -
 469      -                if (dev->state & STATE_MAC_STARTED) {
 470      -                        if (dev->link_speed < 0) {
 471      -                                (void) oce_get_link_status(dev, &link);
 472      -                                dev->link_speed = link.qos_link_speed ?
 473      -                                    link.qos_link_speed * 10 :
 474      -                                    pow10[link.mac_speed];
 475      -                        }
 476      -
 477      -                        *speed = dev->link_speed * 1000000ull;
 478      -                }
      490 +                uint64_t speed;
      491 +                speed = dev->link_speed * 1000000ull;
      492 +                bcopy(&speed, val, sizeof (speed));
 479  493                  break;
 480  494          }
 481  495  
 482  496          case MAC_PROP_FLOWCTRL: {
 483  497                  link_flowctrl_t *fc = (link_flowctrl_t *)val;
 484  498  
 485  499                  ASSERT(size >= sizeof (link_flowctrl_t));
 486  500                  if (dev->flow_control & OCE_FC_TX &&
 487  501                      dev->flow_control & OCE_FC_RX)
 488  502                          *fc = LINK_FLOWCTRL_BI;
 489  503                  else if (dev->flow_control == OCE_FC_TX)
 490  504                          *fc = LINK_FLOWCTRL_TX;
 491  505                  else if (dev->flow_control == OCE_FC_RX)
 492  506                          *fc = LINK_FLOWCTRL_RX;
 493  507                  else if (dev->flow_control == 0)
 494  508                          *fc = LINK_FLOWCTRL_NONE;
 495  509                  else
 496  510                          ret = EINVAL;
 497  511                  break;
 498  512          }
 499  513  
 500  514          case MAC_PROP_PRIVATE:
 501  515                  ret = oce_get_priv_prop(dev, name, size, val);
 502  516                  break;
 503  517  
 504  518          default:
 505  519                  ret = ENOTSUP;
 506  520                  break;
 507  521          } /* switch id */
 508  522          return (ret);
 509  523  } /* oce_m_getprop */
 510  524  
 511  525  void
 512  526  oce_m_propinfo(void *arg, const char *name, mac_prop_id_t pr_num,
 513  527      mac_prop_info_handle_t prh)
 514  528  {
 515  529          _NOTE(ARGUNUSED(arg));
 516  530  
 517  531          switch (pr_num) {
 518  532          case MAC_PROP_AUTONEG:
 519  533          case MAC_PROP_EN_AUTONEG:
 520  534          case MAC_PROP_ADV_1000FDX_CAP:
 521  535          case MAC_PROP_EN_1000FDX_CAP:
 522  536          case MAC_PROP_ADV_1000HDX_CAP:
 523  537          case MAC_PROP_EN_1000HDX_CAP:
 524  538          case MAC_PROP_ADV_100FDX_CAP:
 525  539          case MAC_PROP_EN_100FDX_CAP:
 526  540          case MAC_PROP_ADV_100HDX_CAP:
 527  541          case MAC_PROP_EN_100HDX_CAP:
 528  542          case MAC_PROP_ADV_10FDX_CAP:
 529  543          case MAC_PROP_EN_10FDX_CAP:
 530  544          case MAC_PROP_ADV_10HDX_CAP:
 531  545          case MAC_PROP_EN_10HDX_CAP:
 532  546          case MAC_PROP_ADV_100T4_CAP:
 533  547          case MAC_PROP_EN_100T4_CAP:
 534  548          case MAC_PROP_ADV_10GFDX_CAP:
 535  549          case MAC_PROP_EN_10GFDX_CAP:
 536  550          case MAC_PROP_SPEED:
 537  551          case MAC_PROP_DUPLEX:
  
    | 
      ↓ open down ↓ | 
    49 lines elided | 
    
      ↑ open up ↑ | 
  
 538  552                  mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
 539  553                  break;
 540  554  
 541  555          case MAC_PROP_MTU:
 542  556                  mac_prop_info_set_range_uint32(prh, OCE_MIN_MTU, OCE_MAX_MTU);
 543  557                  break;
 544  558  
 545  559          case MAC_PROP_PRIVATE: {
 546  560                  char valstr[64];
 547  561                  int value;
      562 +                uint_t perm = MAC_PROP_PERM_READ;
 548  563  
 549      -                if (strcmp(name, "_tx_ring_size") == 0) {
      564 +                bzero(valstr, sizeof (valstr));
      565 +                if (strcmp(name, "_tx_rings") == 0) {
      566 +                        value = OCE_DEFAULT_WQS;
      567 +                } else if (strcmp(name, "_tx_ring_size") == 0) {
 550  568                          value = OCE_DEFAULT_TX_RING_SIZE;
      569 +                        perm = MAC_PROP_PERM_RW;
      570 +                } else if (strcmp(name, "_tx_bcopy_limit") == 0) {
      571 +                        value = OCE_DEFAULT_TX_BCOPY_LIMIT;
      572 +                        perm = MAC_PROP_PERM_RW;
      573 +                } else if (strcmp(name, "_tx_reclaim_threshold") == 0) {
      574 +                        value = OCE_DEFAULT_TX_RECLAIM_THRESHOLD;
      575 +                        perm = MAC_PROP_PERM_RW;
      576 +                } else if (strcmp(name, "_rx_rings") == 0) {
      577 +                        value = OCE_DEFAULT_RQS;
      578 +                } else if (strcmp(name, "_rx_rings_per_group") == 0) {
      579 +                        value = OCE_DEF_RING_PER_GROUP;
 551  580                  } else if (strcmp(name, "_rx_ring_size") == 0) {
 552  581                          value = OCE_DEFAULT_RX_RING_SIZE;
 553      -                } else {
      582 +                } else if (strcmp(name, "_rx_bcopy_limit") == 0) {
      583 +                        value = OCE_DEFAULT_RX_BCOPY_LIMIT;
      584 +                        perm = MAC_PROP_PERM_RW;
      585 +                } else if (strcmp(name, "_rx_pkts_per_intr") == 0) {
      586 +                        value = OCE_DEFAULT_RX_PKTS_PER_INTR;
      587 +                        perm = MAC_PROP_PERM_RW;
      588 +                } else if (strcmp(name, "_log_level") == 0) {
      589 +                        value = OCE_DEFAULT_LOG_SETTINGS;
      590 +                        perm = MAC_PROP_PERM_RW;
      591 +                } else
 554  592                          return;
 555      -                }
 556  593  
 557  594                  (void) snprintf(valstr, sizeof (valstr), "%d", value);
 558  595                  mac_prop_info_set_default_str(prh, valstr);
 559      -                mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
      596 +                mac_prop_info_set_perm(prh, perm);
 560  597                  break;
 561  598          }
 562  599          }
 563  600  } /* oce_m_propinfo */
 564  601  
 565  602  /*
 566  603   * function to handle dlpi streams message from GLDv3 mac layer
 567  604   */
 568  605  void
 569  606  oce_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
 570  607  {
 571  608          struct oce_dev *dev = arg;
 572  609          struct  iocblk *iocp;
 573  610          int cmd;
 574  611          uint32_t payload_length;
 575  612          int ret;
 576  613  
 577  614          iocp = (struct iocblk *)voidptr(mp->b_rptr);
 578  615          iocp->ioc_error = 0;
 579  616          cmd = iocp->ioc_cmd;
 580  617  
 581  618          DEV_LOCK(dev);
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
 582  619          if (dev->suspended) {
 583  620                  miocnak(wq, mp, 0, EINVAL);
 584  621                  DEV_UNLOCK(dev);
 585  622                  return;
 586  623          }
 587  624          DEV_UNLOCK(dev);
 588  625  
 589  626          switch (cmd) {
 590  627  
 591  628          case OCE_ISSUE_MBOX: {
 592      -                ret = oce_issue_mbox(dev, wq, mp, &payload_length);
      629 +                ret = oce_issue_mbox_passthru(dev, wq, mp, &payload_length);
 593  630                  miocack(wq, mp, payload_length, ret);
 594  631                  break;
 595  632          }
 596  633          case OCE_QUERY_DRIVER_DATA: {
 597  634                  struct oce_driver_query *drv_query =
 598  635                      (struct oce_driver_query *)(void *)mp->b_cont->b_rptr;
 599  636  
 600  637                  /* if the driver version does not match bail */
 601  638                  if (drv_query->version != OCN_VERSION_SUPPORTED) {
 602  639                          oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
 603  640                              "One Connect version mismatch");
 604  641                          miocnak(wq, mp, 0, ENOTSUP);
 605  642                          break;
 606  643                  }
 607  644  
 608  645                  /* fill the return values */
 609  646                  bcopy(OCE_MOD_NAME, drv_query->driver_name,
 610  647                      (sizeof (OCE_MOD_NAME) > 32) ?
 611  648                      31 : sizeof (OCE_MOD_NAME));
 612  649                  drv_query->driver_name[31] = '\0';
 613  650  
 614  651                  bcopy(OCE_VERSION, drv_query->driver_version,
 615  652                      (sizeof (OCE_VERSION) > 32) ? 31 :
 616  653                      sizeof (OCE_VERSION));
 617  654                  drv_query->driver_version[31] = '\0';
 618  655  
 619  656                  if (dev->num_smac == 0) {
 620  657                          drv_query->num_smac = 1;
 621  658                          bcopy(dev->mac_addr, drv_query->smac_addr[0],
 622  659                              ETHERADDRL);
 623  660                  } else {
 624  661                          drv_query->num_smac = dev->num_smac;
 625  662                          bcopy(dev->unicast_addr, drv_query->smac_addr[0],
 626  663                              ETHERADDRL);
 627  664                  }
 628  665  
 629  666                  bcopy(dev->mac_addr, drv_query->pmac_addr, ETHERADDRL);
 630  667  
 631  668                  payload_length = sizeof (struct oce_driver_query);
 632  669                  miocack(wq, mp, payload_length, 0);
 633  670                  break;
 634  671          }
 635  672  
 636  673          default:
 637  674                  miocnak(wq, mp, 0, ENOTSUP);
 638  675                  break;
 639  676          }
 640  677  } /* oce_m_ioctl */
 641  678  
 642  679  int
 643  680  oce_m_promiscuous(void *arg, boolean_t enable)
 644  681  {
 645  682          struct oce_dev *dev = arg;
 646  683          int ret = 0;
 647  684  
 648  685          DEV_LOCK(dev);
 649  686  
 650  687          if (dev->promisc == enable) {
 651  688                  DEV_UNLOCK(dev);
  
    | 
      ↓ open down ↓ | 
    49 lines elided | 
    
      ↑ open up ↑ | 
  
 652  689                  return (ret);
 653  690          }
 654  691  
 655  692          if (dev->suspended) {
 656  693                  /* remember the setting */
 657  694                  dev->promisc = enable;
 658  695                  DEV_UNLOCK(dev);
 659  696                  return (ret);
 660  697          }
 661  698  
 662      -        ret = oce_set_promiscuous(dev, enable);
 663      -        if (ret == DDI_SUCCESS)
      699 +        ret = oce_set_promiscuous(dev, enable, MBX_ASYNC_MQ);
      700 +        if (ret == DDI_SUCCESS) {
 664  701                  dev->promisc = enable;
      702 +                if (!(enable)) {
      703 +                        struct ether_addr  *mca_drv_list;
      704 +                        mca_drv_list = &dev->multi_cast[0];
      705 +                        if (dev->num_mca > OCE_MAX_MCA) {
      706 +                                ret = oce_set_multicast_table(dev, dev->if_id,
      707 +                                    &mca_drv_list[0], OCE_MAX_MCA, B_TRUE,
      708 +                                    MBX_ASYNC_MQ);
      709 +                        } else {
      710 +                                ret = oce_set_multicast_table(dev, dev->if_id,
      711 +                                    &mca_drv_list[0], dev->num_mca, B_FALSE,
      712 +                                    MBX_ASYNC_MQ);
      713 +                        }
      714 +                }
      715 +        }
 665  716          DEV_UNLOCK(dev);
 666  717          return (ret);
 667  718  } /* oce_m_promiscuous */
 668  719  
 669  720  /*
 670  721   * function to set a private property.
 671  722   * Called from the set_prop GLD entry point
 672  723   *
 673  724   * dev - sofware handle to the device
 674  725   * name - string containing the property name
 675  726   * size - length of the string in name
 676  727   * val - pointer to a location where the value to set is stored
 677  728   *
 678  729   * return EINVAL => invalid value in val 0 => success
 679  730   */
 680  731  static int
 681  732  oce_set_priv_prop(struct oce_dev *dev, const char *name,
 682  733      uint_t size, const void *val)
 683  734  {
 684      -        int ret = ENOTSUP;
      735 +        int ret = EINVAL;
 685  736          long result;
 686  737  
 687  738          _NOTE(ARGUNUSED(size));
 688  739  
 689  740          if (NULL == val) {
 690      -                ret = EINVAL;
 691      -                return (ret);
      741 +                return (EINVAL);
 692  742          }
 693      -
 694      -        if (strcmp(name, "_tx_bcopy_limit") == 0) {
 695      -                (void) ddi_strtol(val, (char **)NULL, 0, &result);
 696      -                if (result <= OCE_WQ_BUF_SIZE) {
      743 +        (void) ddi_strtol(val, (char **)NULL, 0, &result);
      744 +        if (strcmp(name, "_tx_ring_size") == 0) {
      745 +                if (result <= SIZE_2K) {
      746 +                        if (dev->tx_ring_size != result) {
      747 +                                dev->tx_ring_size = (uint32_t)result;
      748 +                        }
      749 +                        ret = 0;
      750 +                }
      751 +        } else if (strcmp(name, "_tx_bcopy_limit") == 0) {
      752 +                if (result <= SIZE_2K) {
 697  753                          if (result != dev->tx_bcopy_limit)
 698  754                                  dev->tx_bcopy_limit = (uint32_t)result;
 699  755                          ret = 0;
 700      -                } else {
 701      -                        ret = EINVAL;
 702  756                  }
 703      -        }
 704      -        if (strcmp(name, "_rx_bcopy_limit") == 0) {
 705      -                (void) ddi_strtol(val, (char **)NULL, 0, &result);
 706      -                if (result <= OCE_RQ_BUF_SIZE) {
 707      -                        if (result != dev->rx_bcopy_limit)
      757 +        } else if (strcmp(name, "_tx_reclaim_threshold") == 0) {
      758 +                if (result <= dev->tx_ring_size) {
      759 +                        if (dev->tx_reclaim_threshold != result) {
      760 +                                dev->tx_reclaim_threshold = (uint32_t)result;
      761 +                        }
      762 +                        ret = 0;
      763 +                }
      764 +        } else if (strcmp(name, "_rx_bcopy_limit") == 0) {
      765 +                if (result <= dev->mtu) {
      766 +                        if (dev->rx_bcopy_limit != result) {
 708  767                                  dev->rx_bcopy_limit = (uint32_t)result;
      768 +                        }
 709  769                          ret = 0;
 710      -                } else {
 711      -                        ret = EINVAL;
 712  770                  }
      771 +        } else if (strcmp(name, "_rx_pkts_per_intr") == 0) {
      772 +                if (result <= dev->rx_ring_size) {
      773 +                        if (dev->rx_pkt_per_intr != result) {
      774 +                                dev->rx_pkt_per_intr = (uint32_t)result;
      775 +                        }
      776 +                        ret = 0;
      777 +                }
      778 +        } else if (strcmp(name, "_log_level") == 0) {
      779 +                if (result <= OCE_MAX_LOG_SETTINGS) {
      780 +                        /* derive from the loglevel */
      781 +                        dev->severity = (uint16_t)(result & 0xffff);
      782 +                        dev->mod_mask = (uint16_t)(result >> 16);
      783 +                }
      784 +                ret = 0;
 713  785          }
 714  786  
 715  787          return (ret);
 716  788  } /* oce_set_priv_prop */
 717  789  
 718  790  /*
 719  791   * function to get the value of a private property. Called from get_prop
 720  792   *
 721  793   * dev - software handle to the device
 722  794   * name - string containing the property name
 723  795   * size - length of the string contained name
  
    | 
      ↓ open down ↓ | 
    1 lines elided | 
    
      ↑ open up ↑ | 
  
 724  796   * val - [OUT] pointer to the location where the result is returned
 725  797   *
 726  798   * return EINVAL => invalid request 0 => success
 727  799   */
 728  800  static int
 729  801  oce_get_priv_prop(struct oce_dev *dev, const char *name,
 730  802      uint_t size, void *val)
 731  803  {
 732  804          int value;
 733  805  
 734      -        if (strcmp(name, "_tx_ring_size") == 0) {
      806 +        if (strcmp(name, "_tx_rings") == 0) {
      807 +                value = dev->tx_rings;
      808 +        } else if (strcmp(name, "_tx_ring_size") == 0) {
 735  809                  value = dev->tx_ring_size;
 736  810          } else if (strcmp(name, "_tx_bcopy_limit") == 0) {
 737  811                  value = dev->tx_bcopy_limit;
      812 +        } else if (strcmp(name, "_tx_reclaim_threshold") == 0) {
      813 +                value = dev->tx_reclaim_threshold;
      814 +        } else if (strcmp(name, "_rx_rings") == 0) {
      815 +                        value = dev->rx_rings;
      816 +        } else if (strcmp(name, "_rx_rings_per_group") == 0) {
      817 +                        value = dev->rx_rings_per_group;
 738  818          } else if (strcmp(name, "_rx_ring_size") == 0) {
 739  819                  value = dev->rx_ring_size;
 740  820          } else if (strcmp(name, "_rx_bcopy_limit") == 0) {
 741  821                  value = dev->rx_bcopy_limit;
      822 +        } else if (strcmp(name, "_rx_pkts_per_intr") == 0) {
      823 +                value = dev->rx_pkt_per_intr;
      824 +        } else if (strcmp(name, "_log_level") == 0) {
      825 +                value = (dev->mod_mask << 16UL) | dev->severity;
 742  826          } else {
 743  827                  return (ENOTSUP);
 744  828          }
 745  829  
 746  830          (void) snprintf(val, size, "%d", value);
 747  831          return (0);
 748  832  } /* oce_get_priv_prop */
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX