linux/drivers/net/ethernet/qlogic/qlcnic/qlcnic_83xx_vnic.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * QLogic qlcnic NIC Driver
   4 * Copyright (c) 2009-2013 QLogic Corporation
   5 */
   6
   7#include "qlcnic.h"
   8#include "qlcnic_hw.h"
   9
  10static int qlcnic_83xx_enable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
  11{
  12        if (lock) {
  13                if (qlcnic_83xx_lock_driver(adapter))
  14                        return -EBUSY;
  15        }
  16        QLCWRX(adapter->ahw, QLC_83XX_VNIC_STATE, QLCNIC_DEV_NPAR_OPER);
  17        if (lock)
  18                qlcnic_83xx_unlock_driver(adapter);
  19
  20        return 0;
  21}
  22
  23int qlcnic_83xx_disable_vnic_mode(struct qlcnic_adapter *adapter, int lock)
  24{
  25        struct qlcnic_hardware_context *ahw = adapter->ahw;
  26
  27        if (lock) {
  28                if (qlcnic_83xx_lock_driver(adapter))
  29                        return -EBUSY;
  30        }
  31
  32        QLCWRX(adapter->ahw, QLC_83XX_VNIC_STATE, QLCNIC_DEV_NPAR_NON_OPER);
  33        ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
  34
  35        if (lock)
  36                qlcnic_83xx_unlock_driver(adapter);
  37
  38        return 0;
  39}
  40
  41int qlcnic_83xx_set_vnic_opmode(struct qlcnic_adapter *adapter)
  42{
  43        u8 id;
  44        int ret = -EBUSY;
  45        u32 data = QLCNIC_MGMT_FUNC;
  46        struct qlcnic_hardware_context *ahw = adapter->ahw;
  47
  48        if (qlcnic_83xx_lock_driver(adapter))
  49                return ret;
  50
  51        id = ahw->pci_func;
  52        data = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
  53        data = (data & ~QLC_83XX_SET_FUNC_OPMODE(0x3, id)) |
  54               QLC_83XX_SET_FUNC_OPMODE(QLCNIC_MGMT_FUNC, id);
  55
  56        QLCWRX(adapter->ahw, QLC_83XX_DRV_OP_MODE, data);
  57
  58        qlcnic_83xx_unlock_driver(adapter);
  59
  60        return 0;
  61}
  62
  63static void
  64qlcnic_83xx_config_vnic_buff_descriptors(struct qlcnic_adapter *adapter)
  65{
  66        struct qlcnic_hardware_context *ahw = adapter->ahw;
  67
  68        if (ahw->port_type == QLCNIC_XGBE) {
  69                adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_VF;
  70                adapter->max_rxd = MAX_RCV_DESCRIPTORS_VF;
  71                adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
  72                adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_10G;
  73
  74        } else if (ahw->port_type == QLCNIC_GBE) {
  75                adapter->num_rxd = DEFAULT_RCV_DESCRIPTORS_1G;
  76                adapter->num_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
  77                adapter->max_jumbo_rxd = MAX_JUMBO_RCV_DESCRIPTORS_1G;
  78                adapter->max_rxd = MAX_RCV_DESCRIPTORS_1G;
  79        }
  80        adapter->num_txd = MAX_CMD_DESCRIPTORS;
  81        adapter->max_rds_rings = MAX_RDS_RINGS;
  82}
  83
  84
  85/**
  86 * qlcnic_83xx_init_mgmt_vnic
  87 *
  88 * @adapter: adapter structure
  89 * Management virtual NIC sets the operational mode of other vNIC's and
  90 * configures embedded switch (ESWITCH).
  91 * Returns: Success(0) or error code.
  92 *
  93 **/
  94static int qlcnic_83xx_init_mgmt_vnic(struct qlcnic_adapter *adapter)
  95{
  96        struct qlcnic_hardware_context *ahw = adapter->ahw;
  97        struct device *dev = &adapter->pdev->dev;
  98        struct qlcnic_npar_info *npar;
  99        int i, err = -EIO;
 100
 101        qlcnic_83xx_get_minidump_template(adapter);
 102
 103        if (!(adapter->flags & QLCNIC_ADAPTER_INITIALIZED)) {
 104                if (qlcnic_init_pci_info(adapter))
 105                        return err;
 106
 107                npar = adapter->npars;
 108
 109                for (i = 0; i < ahw->total_nic_func; i++, npar++) {
 110                        dev_info(dev, "id:%d active:%d type:%d port:%d min_bw:%d max_bw:%d mac_addr:%pM\n",
 111                                 npar->pci_func, npar->active, npar->type,
 112                                 npar->phy_port, npar->min_bw, npar->max_bw,
 113                                 npar->mac);
 114                }
 115
 116                dev_info(dev, "Max functions = %d, active functions = %d\n",
 117                         ahw->max_pci_func, ahw->total_nic_func);
 118
 119                if (qlcnic_83xx_set_vnic_opmode(adapter))
 120                        return err;
 121
 122                if (qlcnic_set_default_offload_settings(adapter))
 123                        return err;
 124        } else {
 125                if (qlcnic_reset_npar_config(adapter))
 126                        return err;
 127        }
 128
 129        if (qlcnic_83xx_get_port_info(adapter))
 130                return err;
 131
 132        qlcnic_83xx_config_vnic_buff_descriptors(adapter);
 133        ahw->msix_supported = qlcnic_use_msi_x ? 1 : 0;
 134        adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
 135        qlcnic_83xx_enable_vnic_mode(adapter, 1);
 136
 137        dev_info(dev, "HAL Version: %d, Management function\n",
 138                 ahw->fw_hal_version);
 139
 140        return 0;
 141}
 142
 143static int qlcnic_83xx_init_privileged_vnic(struct qlcnic_adapter *adapter)
 144{
 145        int err = -EIO;
 146
 147        qlcnic_83xx_get_minidump_template(adapter);
 148        if (qlcnic_83xx_get_port_info(adapter))
 149                return err;
 150
 151        qlcnic_83xx_config_vnic_buff_descriptors(adapter);
 152        adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
 153        adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
 154
 155        dev_info(&adapter->pdev->dev,
 156                 "HAL Version: %d, Privileged function\n",
 157                 adapter->ahw->fw_hal_version);
 158        return 0;
 159}
 160
 161static int qlcnic_83xx_init_non_privileged_vnic(struct qlcnic_adapter *adapter)
 162{
 163        int err = -EIO;
 164
 165        qlcnic_83xx_get_fw_version(adapter);
 166        if (qlcnic_set_eswitch_port_config(adapter))
 167                return err;
 168
 169        if (qlcnic_83xx_get_port_info(adapter))
 170                return err;
 171
 172        qlcnic_83xx_config_vnic_buff_descriptors(adapter);
 173        adapter->ahw->msix_supported = !!qlcnic_use_msi_x;
 174        adapter->flags |= QLCNIC_ADAPTER_INITIALIZED;
 175
 176        dev_info(&adapter->pdev->dev, "HAL Version: %d, Virtual function\n",
 177                 adapter->ahw->fw_hal_version);
 178
 179        return 0;
 180}
 181
 182/**
 183 * qlcnic_83xx_config_vnic_opmode
 184 *
 185 * @adapter: adapter structure
 186 * Identify virtual NIC operational modes.
 187 *
 188 * Returns: Success(0) or error code.
 189 *
 190 **/
 191int qlcnic_83xx_config_vnic_opmode(struct qlcnic_adapter *adapter)
 192{
 193        u32 op_mode, priv_level;
 194        struct qlcnic_hardware_context *ahw = adapter->ahw;
 195        struct qlcnic_nic_template *nic_ops = adapter->nic_ops;
 196
 197        qlcnic_get_func_no(adapter);
 198        op_mode = QLCRDX(adapter->ahw, QLC_83XX_DRV_OP_MODE);
 199
 200        if (op_mode == QLC_83XX_DEFAULT_OPMODE)
 201                priv_level = QLCNIC_MGMT_FUNC;
 202        else
 203                priv_level = QLC_83XX_GET_FUNC_PRIVILEGE(op_mode,
 204                                                         ahw->pci_func);
 205        switch (priv_level) {
 206        case QLCNIC_NON_PRIV_FUNC:
 207                ahw->op_mode = QLCNIC_NON_PRIV_FUNC;
 208                ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
 209                nic_ops->init_driver = qlcnic_83xx_init_non_privileged_vnic;
 210                break;
 211        case QLCNIC_PRIV_FUNC:
 212                ahw->op_mode = QLCNIC_PRIV_FUNC;
 213                ahw->idc.state_entry = qlcnic_83xx_idc_vnic_pf_entry;
 214                nic_ops->init_driver = qlcnic_83xx_init_privileged_vnic;
 215                break;
 216        case QLCNIC_MGMT_FUNC:
 217                ahw->op_mode = QLCNIC_MGMT_FUNC;
 218                ahw->idc.state_entry = qlcnic_83xx_idc_ready_state_entry;
 219                nic_ops->init_driver = qlcnic_83xx_init_mgmt_vnic;
 220                break;
 221        default:
 222                dev_err(&adapter->pdev->dev, "Invalid Virtual NIC opmode\n");
 223                return -EIO;
 224        }
 225
 226        if (ahw->capabilities & QLC_83XX_ESWITCH_CAPABILITY) {
 227                adapter->flags |= QLCNIC_ESWITCH_ENABLED;
 228                if (adapter->drv_mac_learn)
 229                        adapter->rx_mac_learn = true;
 230        } else {
 231                adapter->flags &= ~QLCNIC_ESWITCH_ENABLED;
 232                adapter->rx_mac_learn = false;
 233        }
 234
 235        ahw->idc.vnic_state = QLCNIC_DEV_NPAR_NON_OPER;
 236        ahw->idc.vnic_wait_limit = QLCNIC_DEV_NPAR_OPER_TIMEO;
 237
 238        return 0;
 239}
 240
 241int qlcnic_83xx_check_vnic_state(struct qlcnic_adapter *adapter)
 242{
 243        struct qlcnic_hardware_context *ahw = adapter->ahw;
 244        struct qlc_83xx_idc *idc = &ahw->idc;
 245        u32 state;
 246
 247        state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
 248        while (state != QLCNIC_DEV_NPAR_OPER && idc->vnic_wait_limit) {
 249                idc->vnic_wait_limit--;
 250                msleep(1000);
 251                state = QLCRDX(ahw, QLC_83XX_VNIC_STATE);
 252        }
 253
 254        if (state != QLCNIC_DEV_NPAR_OPER) {
 255                dev_err(&adapter->pdev->dev,
 256                        "vNIC mode not operational, state check timed out.\n");
 257                return -EIO;
 258        }
 259
 260        return 0;
 261}
 262
 263int qlcnic_83xx_set_port_eswitch_status(struct qlcnic_adapter *adapter,
 264                                        int func, int *port_id)
 265{
 266        struct qlcnic_info nic_info;
 267        int err = 0;
 268
 269        memset(&nic_info, 0, sizeof(struct qlcnic_info));
 270
 271        err = qlcnic_get_nic_info(adapter, &nic_info, func);
 272        if (err)
 273                return err;
 274
 275        if (nic_info.capabilities & QLC_83XX_ESWITCH_CAPABILITY)
 276                *port_id = nic_info.phys_port;
 277        else
 278                err = -EIO;
 279
 280        if (!err)
 281                adapter->eswitch[*port_id].flags |= QLCNIC_SWITCH_ENABLE;
 282
 283        return err;
 284}
 285