Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  Copyright (C) 2013-2014 Chelsio Communications.  All rights reserved.
0004  *
0005  *  Written by Anish Bhatt (anish@chelsio.com)
0006  *         Casey Leedom (leedom@chelsio.com)
0007  */
0008 
0009 #include "cxgb4.h"
0010 
0011 /* DCBx version control
0012  */
0013 const char * const dcb_ver_array[] = {
0014     "Unknown",
0015     "DCBx-CIN",
0016     "DCBx-CEE 1.01",
0017     "DCBx-IEEE",
0018     "", "", "",
0019     "Auto Negotiated"
0020 };
0021 
0022 static inline bool cxgb4_dcb_state_synced(enum cxgb4_dcb_state state)
0023 {
0024     if (state == CXGB4_DCB_STATE_FW_ALLSYNCED ||
0025         state == CXGB4_DCB_STATE_HOST)
0026         return true;
0027     else
0028         return false;
0029 }
0030 
0031 /* Initialize a port's Data Center Bridging state.
0032  */
0033 void cxgb4_dcb_state_init(struct net_device *dev)
0034 {
0035     struct port_info *pi = netdev2pinfo(dev);
0036     struct port_dcb_info *dcb = &pi->dcb;
0037     int version_temp = dcb->dcb_version;
0038 
0039     memset(dcb, 0, sizeof(struct port_dcb_info));
0040     dcb->state = CXGB4_DCB_STATE_START;
0041     if (version_temp)
0042         dcb->dcb_version = version_temp;
0043 
0044     netdev_dbg(dev, "%s: Initializing DCB state for port[%d]\n",
0045             __func__, pi->port_id);
0046 }
0047 
0048 void cxgb4_dcb_version_init(struct net_device *dev)
0049 {
0050     struct port_info *pi = netdev2pinfo(dev);
0051     struct port_dcb_info *dcb = &pi->dcb;
0052 
0053     /* Any writes here are only done on kernels that exlicitly need
0054      * a specific version, say < 2.6.38 which only support CEE
0055      */
0056     dcb->dcb_version = FW_PORT_DCB_VER_AUTO;
0057 }
0058 
0059 static void cxgb4_dcb_cleanup_apps(struct net_device *dev)
0060 {
0061     struct port_info *pi = netdev2pinfo(dev);
0062     struct adapter *adap = pi->adapter;
0063     struct port_dcb_info *dcb = &pi->dcb;
0064     struct dcb_app app;
0065     int i, err;
0066 
0067     /* zero priority implies remove */
0068     app.priority = 0;
0069 
0070     for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
0071         /* Check if app list is exhausted */
0072         if (!dcb->app_priority[i].protocolid)
0073             break;
0074 
0075         app.protocol = dcb->app_priority[i].protocolid;
0076 
0077         if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
0078             app.priority = dcb->app_priority[i].user_prio_map;
0079             app.selector = dcb->app_priority[i].sel_field + 1;
0080             err = dcb_ieee_delapp(dev, &app);
0081         } else {
0082             app.selector = !!(dcb->app_priority[i].sel_field);
0083             err = dcb_setapp(dev, &app);
0084         }
0085 
0086         if (err) {
0087             dev_err(adap->pdev_dev,
0088                 "Failed DCB Clear %s Application Priority: sel=%d, prot=%d, err=%d\n",
0089                 dcb_ver_array[dcb->dcb_version], app.selector,
0090                 app.protocol, -err);
0091             break;
0092         }
0093     }
0094 }
0095 
0096 /* Reset a port's Data Center Bridging state.  Typically used after a
0097  * Link Down event.
0098  */
0099 void cxgb4_dcb_reset(struct net_device *dev)
0100 {
0101     cxgb4_dcb_cleanup_apps(dev);
0102     cxgb4_dcb_state_init(dev);
0103 }
0104 
0105 /* update the dcb port support, if version is IEEE then set it to
0106  * FW_PORT_DCB_VER_IEEE and if DCB_CAP_DCBX_VER_CEE is already set then
0107  * clear that. and if it is set to CEE then set dcb supported to
0108  * DCB_CAP_DCBX_VER_CEE & if DCB_CAP_DCBX_VER_IEEE is set, clear it
0109  */
0110 static inline void cxgb4_dcb_update_support(struct port_dcb_info *dcb)
0111 {
0112     if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
0113         if (dcb->supported & DCB_CAP_DCBX_VER_CEE)
0114             dcb->supported &= ~DCB_CAP_DCBX_VER_CEE;
0115         dcb->supported |= DCB_CAP_DCBX_VER_IEEE;
0116     } else if (dcb->dcb_version == FW_PORT_DCB_VER_CEE1D01) {
0117         if (dcb->supported & DCB_CAP_DCBX_VER_IEEE)
0118             dcb->supported &= ~DCB_CAP_DCBX_VER_IEEE;
0119         dcb->supported |= DCB_CAP_DCBX_VER_CEE;
0120     }
0121 }
0122 
0123 /* Finite State machine for Data Center Bridging.
0124  */
0125 void cxgb4_dcb_state_fsm(struct net_device *dev,
0126              enum cxgb4_dcb_state_input transition_to)
0127 {
0128     struct port_info *pi = netdev2pinfo(dev);
0129     struct port_dcb_info *dcb = &pi->dcb;
0130     struct adapter *adap = pi->adapter;
0131     enum cxgb4_dcb_state current_state = dcb->state;
0132 
0133     netdev_dbg(dev, "%s: State change from %d to %d for %s\n",
0134             __func__, dcb->state, transition_to, dev->name);
0135 
0136     switch (current_state) {
0137     case CXGB4_DCB_STATE_START: {
0138         switch (transition_to) {
0139         case CXGB4_DCB_INPUT_FW_DISABLED: {
0140             /* we're going to use Host DCB */
0141             dcb->state = CXGB4_DCB_STATE_HOST;
0142             dcb->supported = CXGB4_DCBX_HOST_SUPPORT;
0143             break;
0144         }
0145 
0146         case CXGB4_DCB_INPUT_FW_ENABLED: {
0147             /* we're going to use Firmware DCB */
0148             dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
0149             dcb->supported = DCB_CAP_DCBX_LLD_MANAGED;
0150             if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE)
0151                 dcb->supported |= DCB_CAP_DCBX_VER_IEEE;
0152             else
0153                 dcb->supported |= DCB_CAP_DCBX_VER_CEE;
0154             break;
0155         }
0156 
0157         case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
0158             /* expected transition */
0159             break;
0160         }
0161 
0162         case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
0163             dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
0164             break;
0165         }
0166 
0167         default:
0168             goto bad_state_input;
0169         }
0170         break;
0171     }
0172 
0173     case CXGB4_DCB_STATE_FW_INCOMPLETE: {
0174         if (transition_to != CXGB4_DCB_INPUT_FW_DISABLED) {
0175             /* during this CXGB4_DCB_STATE_FW_INCOMPLETE state,
0176              * check if the dcb version is changed (there can be
0177              * mismatch in default config & the negotiated switch
0178              * configuration at FW, so update the dcb support
0179              * accordingly.
0180              */
0181             cxgb4_dcb_update_support(dcb);
0182         }
0183         switch (transition_to) {
0184         case CXGB4_DCB_INPUT_FW_ENABLED: {
0185             /* we're alreaady in firmware DCB mode */
0186             break;
0187         }
0188 
0189         case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
0190             /* we're already incomplete */
0191             break;
0192         }
0193 
0194         case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
0195             dcb->state = CXGB4_DCB_STATE_FW_ALLSYNCED;
0196             dcb->enabled = 1;
0197             linkwatch_fire_event(dev);
0198             break;
0199         }
0200 
0201         default:
0202             goto bad_state_input;
0203         }
0204         break;
0205     }
0206 
0207     case CXGB4_DCB_STATE_FW_ALLSYNCED: {
0208         switch (transition_to) {
0209         case CXGB4_DCB_INPUT_FW_ENABLED: {
0210             /* we're alreaady in firmware DCB mode */
0211             break;
0212         }
0213 
0214         case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
0215             /* We were successfully running with firmware DCB but
0216              * now it's telling us that it's in an "incomplete
0217              * state.  We need to reset back to a ground state
0218              * of incomplete.
0219              */
0220             cxgb4_dcb_reset(dev);
0221             dcb->state = CXGB4_DCB_STATE_FW_INCOMPLETE;
0222             dcb->supported = CXGB4_DCBX_FW_SUPPORT;
0223             linkwatch_fire_event(dev);
0224             break;
0225         }
0226 
0227         case CXGB4_DCB_INPUT_FW_ALLSYNCED: {
0228             /* we're already all sync'ed
0229              * this is only applicable for IEEE or
0230              * when another VI already completed negotiaton
0231              */
0232             dcb->enabled = 1;
0233             linkwatch_fire_event(dev);
0234             break;
0235         }
0236 
0237         default:
0238             goto bad_state_input;
0239         }
0240         break;
0241     }
0242 
0243     case CXGB4_DCB_STATE_HOST: {
0244         switch (transition_to) {
0245         case CXGB4_DCB_INPUT_FW_DISABLED: {
0246             /* we're alreaady in Host DCB mode */
0247             break;
0248         }
0249 
0250         default:
0251             goto bad_state_input;
0252         }
0253         break;
0254     }
0255 
0256     default:
0257         goto bad_state_transition;
0258     }
0259     return;
0260 
0261 bad_state_input:
0262     dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: illegal input symbol %d\n",
0263         transition_to);
0264     return;
0265 
0266 bad_state_transition:
0267     dev_err(adap->pdev_dev, "cxgb4_dcb_state_fsm: bad state transition, state = %d, input = %d\n",
0268         current_state, transition_to);
0269 }
0270 
0271 /* Handle a DCB/DCBX update message from the firmware.
0272  */
0273 void cxgb4_dcb_handle_fw_update(struct adapter *adap,
0274                 const struct fw_port_cmd *pcmd)
0275 {
0276     const union fw_port_dcb *fwdcb = &pcmd->u.dcb;
0277     int port = FW_PORT_CMD_PORTID_G(be32_to_cpu(pcmd->op_to_portid));
0278     struct net_device *dev = adap->port[adap->chan_map[port]];
0279     struct port_info *pi = netdev_priv(dev);
0280     struct port_dcb_info *dcb = &pi->dcb;
0281     int dcb_type = pcmd->u.dcb.pgid.type;
0282     int dcb_running_version;
0283 
0284     /* Handle Firmware DCB Control messages separately since they drive
0285      * our state machine.
0286      */
0287     if (dcb_type == FW_PORT_DCB_TYPE_CONTROL) {
0288         enum cxgb4_dcb_state_input input =
0289             ((pcmd->u.dcb.control.all_syncd_pkd &
0290               FW_PORT_CMD_ALL_SYNCD_F)
0291              ? CXGB4_DCB_INPUT_FW_ALLSYNCED
0292              : CXGB4_DCB_INPUT_FW_INCOMPLETE);
0293 
0294         if (dcb->dcb_version != FW_PORT_DCB_VER_UNKNOWN) {
0295             dcb_running_version = FW_PORT_CMD_DCB_VERSION_G(
0296                 be16_to_cpu(
0297                 pcmd->u.dcb.control.dcb_version_to_app_state));
0298             if (dcb_running_version == FW_PORT_DCB_VER_CEE1D01 ||
0299                 dcb_running_version == FW_PORT_DCB_VER_IEEE) {
0300                 dcb->dcb_version = dcb_running_version;
0301                 dev_warn(adap->pdev_dev, "Interface %s is running %s\n",
0302                      dev->name,
0303                      dcb_ver_array[dcb->dcb_version]);
0304             } else {
0305                 dev_warn(adap->pdev_dev,
0306                      "Something screwed up, requested firmware for %s, but firmware returned %s instead\n",
0307                      dcb_ver_array[dcb->dcb_version],
0308                      dcb_ver_array[dcb_running_version]);
0309                 dcb->dcb_version = FW_PORT_DCB_VER_UNKNOWN;
0310             }
0311         }
0312 
0313         cxgb4_dcb_state_fsm(dev, input);
0314         return;
0315     }
0316 
0317     /* It's weird, and almost certainly an error, to get Firmware DCB
0318      * messages when we either haven't been told whether we're going to be
0319      * doing Host or Firmware DCB; and even worse when we've been told
0320      * that we're doing Host DCB!
0321      */
0322     if (dcb->state == CXGB4_DCB_STATE_START ||
0323         dcb->state == CXGB4_DCB_STATE_HOST) {
0324         dev_err(adap->pdev_dev, "Receiving Firmware DCB messages in State %d\n",
0325             dcb->state);
0326         return;
0327     }
0328 
0329     /* Now handle the general Firmware DCB update messages ...
0330      */
0331     switch (dcb_type) {
0332     case FW_PORT_DCB_TYPE_PGID:
0333         dcb->pgid = be32_to_cpu(fwdcb->pgid.pgid);
0334         dcb->msgs |= CXGB4_DCB_FW_PGID;
0335         break;
0336 
0337     case FW_PORT_DCB_TYPE_PGRATE:
0338         dcb->pg_num_tcs_supported = fwdcb->pgrate.num_tcs_supported;
0339         memcpy(dcb->pgrate, &fwdcb->pgrate.pgrate,
0340                sizeof(dcb->pgrate));
0341         memcpy(dcb->tsa, &fwdcb->pgrate.tsa,
0342                sizeof(dcb->tsa));
0343         dcb->msgs |= CXGB4_DCB_FW_PGRATE;
0344         if (dcb->msgs & CXGB4_DCB_FW_PGID)
0345             IEEE_FAUX_SYNC(dev, dcb);
0346         break;
0347 
0348     case FW_PORT_DCB_TYPE_PRIORATE:
0349         memcpy(dcb->priorate, &fwdcb->priorate.strict_priorate,
0350                sizeof(dcb->priorate));
0351         dcb->msgs |= CXGB4_DCB_FW_PRIORATE;
0352         break;
0353 
0354     case FW_PORT_DCB_TYPE_PFC:
0355         dcb->pfcen = fwdcb->pfc.pfcen;
0356         dcb->pfc_num_tcs_supported = fwdcb->pfc.max_pfc_tcs;
0357         dcb->msgs |= CXGB4_DCB_FW_PFC;
0358         IEEE_FAUX_SYNC(dev, dcb);
0359         break;
0360 
0361     case FW_PORT_DCB_TYPE_APP_ID: {
0362         const struct fw_port_app_priority *fwap = &fwdcb->app_priority;
0363         int idx = fwap->idx;
0364         struct app_priority *ap = &dcb->app_priority[idx];
0365 
0366         struct dcb_app app = {
0367             .protocol = be16_to_cpu(fwap->protocolid),
0368         };
0369         int err;
0370 
0371         /* Convert from firmware format to relevant format
0372          * when using app selector
0373          */
0374         if (dcb->dcb_version == FW_PORT_DCB_VER_IEEE) {
0375             app.selector = (fwap->sel_field + 1);
0376             app.priority = ffs(fwap->user_prio_map) - 1;
0377             err = dcb_ieee_setapp(dev, &app);
0378             IEEE_FAUX_SYNC(dev, dcb);
0379         } else {
0380             /* Default is CEE */
0381             app.selector = !!(fwap->sel_field);
0382             app.priority = fwap->user_prio_map;
0383             err = dcb_setapp(dev, &app);
0384         }
0385 
0386         if (err)
0387             dev_err(adap->pdev_dev,
0388                 "Failed DCB Set Application Priority: sel=%d, prot=%d, prio=%d, err=%d\n",
0389                 app.selector, app.protocol, app.priority, -err);
0390 
0391         ap->user_prio_map = fwap->user_prio_map;
0392         ap->sel_field = fwap->sel_field;
0393         ap->protocolid = be16_to_cpu(fwap->protocolid);
0394         dcb->msgs |= CXGB4_DCB_FW_APP_ID;
0395         break;
0396     }
0397 
0398     default:
0399         dev_err(adap->pdev_dev, "Unknown DCB update type received %x\n",
0400             dcb_type);
0401         break;
0402     }
0403 }
0404 
0405 /* Data Center Bridging netlink operations.
0406  */
0407 
0408 
0409 /* Get current DCB enabled/disabled state.
0410  */
0411 static u8 cxgb4_getstate(struct net_device *dev)
0412 {
0413     struct port_info *pi = netdev2pinfo(dev);
0414 
0415     return pi->dcb.enabled;
0416 }
0417 
0418 /* Set DCB enabled/disabled.
0419  */
0420 static u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
0421 {
0422     struct port_info *pi = netdev2pinfo(dev);
0423 
0424     /* If DCBx is host-managed, dcb is enabled by outside lldp agents */
0425     if (pi->dcb.state == CXGB4_DCB_STATE_HOST) {
0426         pi->dcb.enabled = enabled;
0427         return 0;
0428     }
0429 
0430     /* Firmware doesn't provide any mechanism to control the DCB state.
0431      */
0432     if (enabled != (pi->dcb.state == CXGB4_DCB_STATE_FW_ALLSYNCED))
0433         return 1;
0434 
0435     return 0;
0436 }
0437 
0438 static void cxgb4_getpgtccfg(struct net_device *dev, int tc,
0439                  u8 *prio_type, u8 *pgid, u8 *bw_per,
0440                  u8 *up_tc_map, int local)
0441 {
0442     struct fw_port_cmd pcmd;
0443     struct port_info *pi = netdev2pinfo(dev);
0444     struct adapter *adap = pi->adapter;
0445     int err;
0446 
0447     *prio_type = *pgid = *bw_per = *up_tc_map = 0;
0448 
0449     if (local)
0450         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0451     else
0452         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
0453 
0454     pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
0455     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0456     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0457         dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
0458         return;
0459     }
0460     *pgid = (be32_to_cpu(pcmd.u.dcb.pgid.pgid) >> (tc * 4)) & 0xf;
0461 
0462     if (local)
0463         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0464     else
0465         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
0466     pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
0467     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0468     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0469         dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
0470             -err);
0471         return;
0472     }
0473 
0474     *bw_per = pcmd.u.dcb.pgrate.pgrate[*pgid];
0475     *up_tc_map = (1 << tc);
0476 
0477     /* prio_type is link strict */
0478     if (*pgid != 0xF)
0479         *prio_type = 0x2;
0480 }
0481 
0482 static void cxgb4_getpgtccfg_tx(struct net_device *dev, int tc,
0483                 u8 *prio_type, u8 *pgid, u8 *bw_per,
0484                 u8 *up_tc_map)
0485 {
0486     /* tc 0 is written at MSB position */
0487     return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per,
0488                 up_tc_map, 1);
0489 }
0490 
0491 
0492 static void cxgb4_getpgtccfg_rx(struct net_device *dev, int tc,
0493                 u8 *prio_type, u8 *pgid, u8 *bw_per,
0494                 u8 *up_tc_map)
0495 {
0496     /* tc 0 is written at MSB position */
0497     return cxgb4_getpgtccfg(dev, (7 - tc), prio_type, pgid, bw_per,
0498                 up_tc_map, 0);
0499 }
0500 
0501 static void cxgb4_setpgtccfg_tx(struct net_device *dev, int tc,
0502                 u8 prio_type, u8 pgid, u8 bw_per,
0503                 u8 up_tc_map)
0504 {
0505     struct fw_port_cmd pcmd;
0506     struct port_info *pi = netdev2pinfo(dev);
0507     struct adapter *adap = pi->adapter;
0508     int fw_tc = 7 - tc;
0509     u32 _pgid;
0510     int err;
0511 
0512     if (pgid == DCB_ATTR_VALUE_UNDEFINED)
0513         return;
0514     if (bw_per == DCB_ATTR_VALUE_UNDEFINED)
0515         return;
0516 
0517     INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0518     pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
0519 
0520     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0521     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0522         dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
0523         return;
0524     }
0525 
0526     _pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
0527     _pgid &= ~(0xF << (fw_tc * 4));
0528     _pgid |= pgid << (fw_tc * 4);
0529     pcmd.u.dcb.pgid.pgid = cpu_to_be32(_pgid);
0530 
0531     INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
0532 
0533     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0534     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0535         dev_err(adap->pdev_dev, "DCB write PGID failed with %d\n",
0536             -err);
0537         return;
0538     }
0539 
0540     memset(&pcmd, 0, sizeof(struct fw_port_cmd));
0541 
0542     INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0543     pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
0544 
0545     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0546     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0547         dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
0548             -err);
0549         return;
0550     }
0551 
0552     pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
0553 
0554     INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
0555     if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
0556         pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
0557 
0558     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0559     if (err != FW_PORT_DCB_CFG_SUCCESS)
0560         dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
0561             -err);
0562 }
0563 
0564 static void cxgb4_getpgbwgcfg(struct net_device *dev, int pgid, u8 *bw_per,
0565                   int local)
0566 {
0567     struct fw_port_cmd pcmd;
0568     struct port_info *pi = netdev2pinfo(dev);
0569     struct adapter *adap = pi->adapter;
0570     int err;
0571 
0572     if (local)
0573         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0574     else
0575         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
0576 
0577     pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
0578     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0579     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0580         dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
0581             -err);
0582         return;
0583     }
0584 
0585     *bw_per = pcmd.u.dcb.pgrate.pgrate[pgid];
0586 }
0587 
0588 static void cxgb4_getpgbwgcfg_tx(struct net_device *dev, int pgid, u8 *bw_per)
0589 {
0590     return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 1);
0591 }
0592 
0593 static void cxgb4_getpgbwgcfg_rx(struct net_device *dev, int pgid, u8 *bw_per)
0594 {
0595     return cxgb4_getpgbwgcfg(dev, pgid, bw_per, 0);
0596 }
0597 
0598 static void cxgb4_setpgbwgcfg_tx(struct net_device *dev, int pgid,
0599                  u8 bw_per)
0600 {
0601     struct fw_port_cmd pcmd;
0602     struct port_info *pi = netdev2pinfo(dev);
0603     struct adapter *adap = pi->adapter;
0604     int err;
0605 
0606     INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0607     pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
0608 
0609     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0610     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0611         dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
0612             -err);
0613         return;
0614     }
0615 
0616     pcmd.u.dcb.pgrate.pgrate[pgid] = bw_per;
0617 
0618     INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
0619     if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
0620         pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
0621 
0622     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0623 
0624     if (err != FW_PORT_DCB_CFG_SUCCESS)
0625         dev_err(adap->pdev_dev, "DCB write PGRATE failed with %d\n",
0626             -err);
0627 }
0628 
0629 /* Return whether the specified Traffic Class Priority has Priority Pause
0630  * Frames enabled.
0631  */
0632 static void cxgb4_getpfccfg(struct net_device *dev, int priority, u8 *pfccfg)
0633 {
0634     struct port_info *pi = netdev2pinfo(dev);
0635     struct port_dcb_info *dcb = &pi->dcb;
0636 
0637     if (!cxgb4_dcb_state_synced(dcb->state) ||
0638         priority >= CXGB4_MAX_PRIORITY)
0639         *pfccfg = 0;
0640     else
0641         *pfccfg = (pi->dcb.pfcen >> (7 - priority)) & 1;
0642 }
0643 
0644 /* Enable/disable Priority Pause Frames for the specified Traffic Class
0645  * Priority.
0646  */
0647 static void cxgb4_setpfccfg(struct net_device *dev, int priority, u8 pfccfg)
0648 {
0649     struct fw_port_cmd pcmd;
0650     struct port_info *pi = netdev2pinfo(dev);
0651     struct adapter *adap = pi->adapter;
0652     int err;
0653 
0654     if (!cxgb4_dcb_state_synced(pi->dcb.state) ||
0655         priority >= CXGB4_MAX_PRIORITY)
0656         return;
0657 
0658     INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
0659     if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
0660         pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
0661 
0662     pcmd.u.dcb.pfc.type = FW_PORT_DCB_TYPE_PFC;
0663     pcmd.u.dcb.pfc.pfcen = pi->dcb.pfcen;
0664 
0665     if (pfccfg)
0666         pcmd.u.dcb.pfc.pfcen |= (1 << (7 - priority));
0667     else
0668         pcmd.u.dcb.pfc.pfcen &= (~(1 << (7 - priority)));
0669 
0670     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0671     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0672         dev_err(adap->pdev_dev, "DCB PFC write failed with %d\n", -err);
0673         return;
0674     }
0675 
0676     pi->dcb.pfcen = pcmd.u.dcb.pfc.pfcen;
0677 }
0678 
0679 static u8 cxgb4_setall(struct net_device *dev)
0680 {
0681     return 0;
0682 }
0683 
0684 /* Return DCB capabilities.
0685  */
0686 static u8 cxgb4_getcap(struct net_device *dev, int cap_id, u8 *caps)
0687 {
0688     struct port_info *pi = netdev2pinfo(dev);
0689 
0690     switch (cap_id) {
0691     case DCB_CAP_ATTR_PG:
0692     case DCB_CAP_ATTR_PFC:
0693         *caps = true;
0694         break;
0695 
0696     case DCB_CAP_ATTR_PG_TCS:
0697         /* 8 priorities for PG represented by bitmap */
0698         *caps = 0x80;
0699         break;
0700 
0701     case DCB_CAP_ATTR_PFC_TCS:
0702         /* 8 priorities for PFC represented by bitmap */
0703         *caps = 0x80;
0704         break;
0705 
0706     case DCB_CAP_ATTR_GSP:
0707         *caps = true;
0708         break;
0709 
0710     case DCB_CAP_ATTR_UP2TC:
0711     case DCB_CAP_ATTR_BCN:
0712         *caps = false;
0713         break;
0714 
0715     case DCB_CAP_ATTR_DCBX:
0716         *caps = pi->dcb.supported;
0717         break;
0718 
0719     default:
0720         *caps = false;
0721     }
0722 
0723     return 0;
0724 }
0725 
0726 /* Return the number of Traffic Classes for the indicated Traffic Class ID.
0727  */
0728 static int cxgb4_getnumtcs(struct net_device *dev, int tcs_id, u8 *num)
0729 {
0730     struct port_info *pi = netdev2pinfo(dev);
0731 
0732     switch (tcs_id) {
0733     case DCB_NUMTCS_ATTR_PG:
0734         if (pi->dcb.msgs & CXGB4_DCB_FW_PGRATE)
0735             *num = pi->dcb.pg_num_tcs_supported;
0736         else
0737             *num = 0x8;
0738         break;
0739 
0740     case DCB_NUMTCS_ATTR_PFC:
0741         *num = 0x8;
0742         break;
0743 
0744     default:
0745         return -EINVAL;
0746     }
0747 
0748     return 0;
0749 }
0750 
0751 /* Set the number of Traffic Classes supported for the indicated Traffic Class
0752  * ID.
0753  */
0754 static int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num)
0755 {
0756     /* Setting the number of Traffic Classes isn't supported.
0757      */
0758     return -ENOSYS;
0759 }
0760 
0761 /* Return whether Priority Flow Control is enabled.  */
0762 static u8 cxgb4_getpfcstate(struct net_device *dev)
0763 {
0764     struct port_info *pi = netdev2pinfo(dev);
0765 
0766     if (!cxgb4_dcb_state_synced(pi->dcb.state))
0767         return false;
0768 
0769     return pi->dcb.pfcen != 0;
0770 }
0771 
0772 /* Enable/disable Priority Flow Control. */
0773 static void cxgb4_setpfcstate(struct net_device *dev, u8 state)
0774 {
0775     /* We can't enable/disable Priority Flow Control but we also can't
0776      * return an error ...
0777      */
0778 }
0779 
0780 /* Return the Application User Priority Map associated with the specified
0781  * Application ID.
0782  */
0783 static int __cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id,
0784               int peer)
0785 {
0786     struct port_info *pi = netdev2pinfo(dev);
0787     struct adapter *adap = pi->adapter;
0788     int i;
0789 
0790     if (!cxgb4_dcb_state_synced(pi->dcb.state))
0791         return 0;
0792 
0793     for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
0794         struct fw_port_cmd pcmd;
0795         int err;
0796 
0797         if (peer)
0798             INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
0799         else
0800             INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0801 
0802         pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
0803         pcmd.u.dcb.app_priority.idx = i;
0804 
0805         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0806         if (err != FW_PORT_DCB_CFG_SUCCESS) {
0807             dev_err(adap->pdev_dev, "DCB APP read failed with %d\n",
0808                 -err);
0809             return err;
0810         }
0811         if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id)
0812             if (pcmd.u.dcb.app_priority.sel_field == app_idtype)
0813                 return pcmd.u.dcb.app_priority.user_prio_map;
0814 
0815         /* exhausted app list */
0816         if (!pcmd.u.dcb.app_priority.protocolid)
0817             break;
0818     }
0819 
0820     return -EEXIST;
0821 }
0822 
0823 /* Return the Application User Priority Map associated with the specified
0824  * Application ID.
0825  */
0826 static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
0827 {
0828     /* Convert app_idtype to firmware format before querying */
0829     return __cxgb4_getapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
0830                   app_idtype : 3, app_id, 0);
0831 }
0832 
0833 /* Write a new Application User Priority Map for the specified Application ID
0834  */
0835 static int __cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
0836               u8 app_prio)
0837 {
0838     struct fw_port_cmd pcmd;
0839     struct port_info *pi = netdev2pinfo(dev);
0840     struct adapter *adap = pi->adapter;
0841     int i, err;
0842 
0843 
0844     if (!cxgb4_dcb_state_synced(pi->dcb.state))
0845         return -EINVAL;
0846 
0847     /* DCB info gets thrown away on link up */
0848     if (!netif_carrier_ok(dev))
0849         return -ENOLINK;
0850 
0851     for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
0852         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0853         pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
0854         pcmd.u.dcb.app_priority.idx = i;
0855         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0856 
0857         if (err != FW_PORT_DCB_CFG_SUCCESS) {
0858             dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
0859                 -err);
0860             return err;
0861         }
0862         if (be16_to_cpu(pcmd.u.dcb.app_priority.protocolid) == app_id) {
0863             /* overwrite existing app table */
0864             pcmd.u.dcb.app_priority.protocolid = 0;
0865             break;
0866         }
0867         /* find first empty slot */
0868         if (!pcmd.u.dcb.app_priority.protocolid)
0869             break;
0870     }
0871 
0872     if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) {
0873         /* no empty slots available */
0874         dev_err(adap->pdev_dev, "DCB app table full\n");
0875         return -EBUSY;
0876     }
0877 
0878     /* write out new app table entry */
0879     INIT_PORT_DCB_WRITE_CMD(pcmd, pi->port_id);
0880     if (pi->dcb.state == CXGB4_DCB_STATE_HOST)
0881         pcmd.op_to_portid |= cpu_to_be32(FW_PORT_CMD_APPLY_F);
0882 
0883     pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
0884     pcmd.u.dcb.app_priority.protocolid = cpu_to_be16(app_id);
0885     pcmd.u.dcb.app_priority.sel_field = app_idtype;
0886     pcmd.u.dcb.app_priority.user_prio_map = app_prio;
0887     pcmd.u.dcb.app_priority.idx = i;
0888 
0889     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0890     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0891         dev_err(adap->pdev_dev, "DCB app table write failed with %d\n",
0892             -err);
0893         return err;
0894     }
0895 
0896     return 0;
0897 }
0898 
0899 /* Priority for CEE inside dcb_app is bitmask, with 0 being an invalid value */
0900 static int cxgb4_setapp(struct net_device *dev, u8 app_idtype, u16 app_id,
0901             u8 app_prio)
0902 {
0903     int ret;
0904     struct dcb_app app = {
0905         .selector = app_idtype,
0906         .protocol = app_id,
0907         .priority = app_prio,
0908     };
0909 
0910     if (app_idtype != DCB_APP_IDTYPE_ETHTYPE &&
0911         app_idtype != DCB_APP_IDTYPE_PORTNUM)
0912         return -EINVAL;
0913 
0914     /* Convert app_idtype to a format that firmware understands */
0915     ret = __cxgb4_setapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
0916                   app_idtype : 3, app_id, app_prio);
0917     if (ret)
0918         return ret;
0919 
0920     return dcb_setapp(dev, &app);
0921 }
0922 
0923 /* Return whether IEEE Data Center Bridging has been negotiated.
0924  */
0925 static inline int
0926 cxgb4_ieee_negotiation_complete(struct net_device *dev,
0927                 enum cxgb4_dcb_fw_msgs dcb_subtype)
0928 {
0929     struct port_info *pi = netdev2pinfo(dev);
0930     struct port_dcb_info *dcb = &pi->dcb;
0931 
0932     if (dcb->state == CXGB4_DCB_STATE_FW_ALLSYNCED)
0933         if (dcb_subtype && !(dcb->msgs & dcb_subtype))
0934             return 0;
0935 
0936     return (cxgb4_dcb_state_synced(dcb->state) &&
0937         (dcb->supported & DCB_CAP_DCBX_VER_IEEE));
0938 }
0939 
0940 static int cxgb4_ieee_read_ets(struct net_device *dev, struct ieee_ets *ets,
0941                    int local)
0942 {
0943     struct port_info *pi = netdev2pinfo(dev);
0944     struct port_dcb_info *dcb = &pi->dcb;
0945     struct adapter *adap = pi->adapter;
0946     uint32_t tc_info;
0947     struct fw_port_cmd pcmd;
0948     int i, bwg, err;
0949 
0950     if (!(dcb->msgs & (CXGB4_DCB_FW_PGID | CXGB4_DCB_FW_PGRATE)))
0951         return 0;
0952 
0953     ets->ets_cap =  dcb->pg_num_tcs_supported;
0954 
0955     if (local) {
0956         ets->willing = 1;
0957         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0958     } else {
0959         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
0960     }
0961 
0962     pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
0963     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0964     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0965         dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
0966         return err;
0967     }
0968 
0969     tc_info = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
0970 
0971     if (local)
0972         INIT_PORT_DCB_READ_LOCAL_CMD(pcmd, pi->port_id);
0973     else
0974         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
0975 
0976     pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
0977     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
0978     if (err != FW_PORT_DCB_CFG_SUCCESS) {
0979         dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
0980             -err);
0981         return err;
0982     }
0983 
0984     for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
0985         bwg = (tc_info >> ((7 - i) * 4)) & 0xF;
0986         ets->prio_tc[i] = bwg;
0987         ets->tc_tx_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
0988         ets->tc_rx_bw[i] = ets->tc_tx_bw[i];
0989         ets->tc_tsa[i] = pcmd.u.dcb.pgrate.tsa[i];
0990     }
0991 
0992     return 0;
0993 }
0994 
0995 static int cxgb4_ieee_get_ets(struct net_device *dev, struct ieee_ets *ets)
0996 {
0997     return cxgb4_ieee_read_ets(dev, ets, 1);
0998 }
0999 
1000 /* We reuse this for peer PFC as well, as we can't have it enabled one way */
1001 static int cxgb4_ieee_get_pfc(struct net_device *dev, struct ieee_pfc *pfc)
1002 {
1003     struct port_info *pi = netdev2pinfo(dev);
1004     struct port_dcb_info *dcb = &pi->dcb;
1005 
1006     memset(pfc, 0, sizeof(struct ieee_pfc));
1007 
1008     if (!(dcb->msgs & CXGB4_DCB_FW_PFC))
1009         return 0;
1010 
1011     pfc->pfc_cap = dcb->pfc_num_tcs_supported;
1012     pfc->pfc_en = bitswap_1(dcb->pfcen);
1013 
1014     return 0;
1015 }
1016 
1017 static int cxgb4_ieee_peer_ets(struct net_device *dev, struct ieee_ets *ets)
1018 {
1019     return cxgb4_ieee_read_ets(dev, ets, 0);
1020 }
1021 
1022 /* Fill in the Application User Priority Map associated with the
1023  * specified Application.
1024  * Priority for IEEE dcb_app is an integer, with 0 being a valid value
1025  */
1026 static int cxgb4_ieee_getapp(struct net_device *dev, struct dcb_app *app)
1027 {
1028     int prio;
1029 
1030     if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
1031         return -EINVAL;
1032     if (!(app->selector && app->protocol))
1033         return -EINVAL;
1034 
1035     /* Try querying firmware first, use firmware format */
1036     prio = __cxgb4_getapp(dev, app->selector - 1, app->protocol, 0);
1037 
1038     if (prio < 0)
1039         prio = dcb_ieee_getapp_mask(dev, app);
1040 
1041     app->priority = ffs(prio) - 1;
1042     return 0;
1043 }
1044 
1045 /* Write a new Application User Priority Map for the specified Application ID.
1046  * Priority for IEEE dcb_app is an integer, with 0 being a valid value
1047  */
1048 static int cxgb4_ieee_setapp(struct net_device *dev, struct dcb_app *app)
1049 {
1050     int ret;
1051 
1052     if (!cxgb4_ieee_negotiation_complete(dev, CXGB4_DCB_FW_APP_ID))
1053         return -EINVAL;
1054     if (!(app->selector && app->protocol))
1055         return -EINVAL;
1056 
1057     if (!(app->selector > IEEE_8021QAZ_APP_SEL_ETHERTYPE  &&
1058           app->selector < IEEE_8021QAZ_APP_SEL_ANY))
1059         return -EINVAL;
1060 
1061     /* change selector to a format that firmware understands */
1062     ret = __cxgb4_setapp(dev, app->selector - 1, app->protocol,
1063                  (1 << app->priority));
1064     if (ret)
1065         return ret;
1066 
1067     return dcb_ieee_setapp(dev, app);
1068 }
1069 
1070 /* Return our DCBX parameters.
1071  */
1072 static u8 cxgb4_getdcbx(struct net_device *dev)
1073 {
1074     struct port_info *pi = netdev2pinfo(dev);
1075 
1076     /* This is already set by cxgb4_set_dcb_caps, so just return it */
1077     return pi->dcb.supported;
1078 }
1079 
1080 /* Set our DCBX parameters.
1081  */
1082 static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
1083 {
1084     struct port_info *pi = netdev2pinfo(dev);
1085 
1086     /* Filter out requests which exceed our capabilities.
1087      */
1088     if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT))
1089         != dcb_request)
1090         return 1;
1091 
1092     /* Can't enable DCB if we haven't successfully negotiated it.
1093      */
1094     if (!cxgb4_dcb_state_synced(pi->dcb.state))
1095         return 1;
1096 
1097     /* There's currently no mechanism to allow for the firmware DCBX
1098      * negotiation to be changed from the Host Driver.  If the caller
1099      * requests exactly the same parameters that we already have then
1100      * we'll allow them to be successfully "set" ...
1101      */
1102     if (dcb_request != pi->dcb.supported)
1103         return 1;
1104 
1105     pi->dcb.supported = dcb_request;
1106     return 0;
1107 }
1108 
1109 static int cxgb4_getpeer_app(struct net_device *dev,
1110                  struct dcb_peer_app_info *info, u16 *app_count)
1111 {
1112     struct fw_port_cmd pcmd;
1113     struct port_info *pi = netdev2pinfo(dev);
1114     struct adapter *adap = pi->adapter;
1115     int i, err = 0;
1116 
1117     if (!cxgb4_dcb_state_synced(pi->dcb.state))
1118         return 1;
1119 
1120     info->willing = 0;
1121     info->error = 0;
1122 
1123     *app_count = 0;
1124     for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
1125         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1126         pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
1127         pcmd.u.dcb.app_priority.idx = *app_count;
1128         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1129 
1130         if (err != FW_PORT_DCB_CFG_SUCCESS) {
1131             dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
1132                 -err);
1133             return err;
1134         }
1135 
1136         /* find first empty slot */
1137         if (!pcmd.u.dcb.app_priority.protocolid)
1138             break;
1139     }
1140     *app_count = i;
1141     return err;
1142 }
1143 
1144 static int cxgb4_getpeerapp_tbl(struct net_device *dev, struct dcb_app *table)
1145 {
1146     struct fw_port_cmd pcmd;
1147     struct port_info *pi = netdev2pinfo(dev);
1148     struct adapter *adap = pi->adapter;
1149     int i, err = 0;
1150 
1151     if (!cxgb4_dcb_state_synced(pi->dcb.state))
1152         return 1;
1153 
1154     for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
1155         INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1156         pcmd.u.dcb.app_priority.type = FW_PORT_DCB_TYPE_APP_ID;
1157         pcmd.u.dcb.app_priority.idx = i;
1158         err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1159 
1160         if (err != FW_PORT_DCB_CFG_SUCCESS) {
1161             dev_err(adap->pdev_dev, "DCB app table read failed with %d\n",
1162                 -err);
1163             return err;
1164         }
1165 
1166         /* find first empty slot */
1167         if (!pcmd.u.dcb.app_priority.protocolid)
1168             break;
1169 
1170         table[i].selector = (pcmd.u.dcb.app_priority.sel_field + 1);
1171         table[i].protocol =
1172             be16_to_cpu(pcmd.u.dcb.app_priority.protocolid);
1173         table[i].priority =
1174             ffs(pcmd.u.dcb.app_priority.user_prio_map) - 1;
1175     }
1176     return err;
1177 }
1178 
1179 /* Return Priority Group information.
1180  */
1181 static int cxgb4_cee_peer_getpg(struct net_device *dev, struct cee_pg *pg)
1182 {
1183     struct fw_port_cmd pcmd;
1184     struct port_info *pi = netdev2pinfo(dev);
1185     struct adapter *adap = pi->adapter;
1186     u32 pgid;
1187     int i, err;
1188 
1189     /* We're always "willing" -- the Switch Fabric always dictates the
1190      * DCBX parameters to us.
1191      */
1192     pg->willing = true;
1193 
1194     INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1195     pcmd.u.dcb.pgid.type = FW_PORT_DCB_TYPE_PGID;
1196     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1197     if (err != FW_PORT_DCB_CFG_SUCCESS) {
1198         dev_err(adap->pdev_dev, "DCB read PGID failed with %d\n", -err);
1199         return err;
1200     }
1201     pgid = be32_to_cpu(pcmd.u.dcb.pgid.pgid);
1202 
1203     for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
1204         pg->prio_pg[7 - i] = (pgid >> (i * 4)) & 0xF;
1205 
1206     INIT_PORT_DCB_READ_PEER_CMD(pcmd, pi->port_id);
1207     pcmd.u.dcb.pgrate.type = FW_PORT_DCB_TYPE_PGRATE;
1208     err = t4_wr_mbox(adap, adap->mbox, &pcmd, sizeof(pcmd), &pcmd);
1209     if (err != FW_PORT_DCB_CFG_SUCCESS) {
1210         dev_err(adap->pdev_dev, "DCB read PGRATE failed with %d\n",
1211             -err);
1212         return err;
1213     }
1214 
1215     for (i = 0; i < CXGB4_MAX_PRIORITY; i++)
1216         pg->pg_bw[i] = pcmd.u.dcb.pgrate.pgrate[i];
1217 
1218     pg->tcs_supported = pcmd.u.dcb.pgrate.num_tcs_supported;
1219 
1220     return 0;
1221 }
1222 
1223 /* Return Priority Flow Control information.
1224  */
1225 static int cxgb4_cee_peer_getpfc(struct net_device *dev, struct cee_pfc *pfc)
1226 {
1227     struct port_info *pi = netdev2pinfo(dev);
1228 
1229     cxgb4_getnumtcs(dev, DCB_NUMTCS_ATTR_PFC, &(pfc->tcs_supported));
1230 
1231     /* Firmware sends this to us in a formwat that is a bit flipped version
1232      * of spec, correct it before we send it to host. This is taken care of
1233      * by bit shifting in other uses of pfcen
1234      */
1235     pfc->pfc_en = bitswap_1(pi->dcb.pfcen);
1236 
1237     pfc->tcs_supported = pi->dcb.pfc_num_tcs_supported;
1238 
1239     return 0;
1240 }
1241 
1242 const struct dcbnl_rtnl_ops cxgb4_dcb_ops = {
1243     .ieee_getets        = cxgb4_ieee_get_ets,
1244     .ieee_getpfc        = cxgb4_ieee_get_pfc,
1245     .ieee_getapp        = cxgb4_ieee_getapp,
1246     .ieee_setapp        = cxgb4_ieee_setapp,
1247     .ieee_peer_getets   = cxgb4_ieee_peer_ets,
1248     .ieee_peer_getpfc   = cxgb4_ieee_get_pfc,
1249 
1250     /* CEE std */
1251     .getstate       = cxgb4_getstate,
1252     .setstate       = cxgb4_setstate,
1253     .getpgtccfgtx       = cxgb4_getpgtccfg_tx,
1254     .getpgbwgcfgtx      = cxgb4_getpgbwgcfg_tx,
1255     .getpgtccfgrx       = cxgb4_getpgtccfg_rx,
1256     .getpgbwgcfgrx      = cxgb4_getpgbwgcfg_rx,
1257     .setpgtccfgtx       = cxgb4_setpgtccfg_tx,
1258     .setpgbwgcfgtx      = cxgb4_setpgbwgcfg_tx,
1259     .setpfccfg      = cxgb4_setpfccfg,
1260     .getpfccfg      = cxgb4_getpfccfg,
1261     .setall         = cxgb4_setall,
1262     .getcap         = cxgb4_getcap,
1263     .getnumtcs      = cxgb4_getnumtcs,
1264     .setnumtcs      = cxgb4_setnumtcs,
1265     .getpfcstate        = cxgb4_getpfcstate,
1266     .setpfcstate        = cxgb4_setpfcstate,
1267     .getapp         = cxgb4_getapp,
1268     .setapp         = cxgb4_setapp,
1269 
1270     /* DCBX configuration */
1271     .getdcbx        = cxgb4_getdcbx,
1272     .setdcbx        = cxgb4_setdcbx,
1273 
1274     /* peer apps */
1275     .peer_getappinfo    = cxgb4_getpeer_app,
1276     .peer_getapptable   = cxgb4_getpeerapp_tbl,
1277 
1278     /* CEE peer */
1279     .cee_peer_getpg     = cxgb4_cee_peer_getpg,
1280     .cee_peer_getpfc    = cxgb4_cee_peer_getpfc,
1281 };