0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "cxgb4.h"
0010
0011
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
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
0054
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
0068 app.priority = 0;
0069
0070 for (i = 0; i < CXGB4_MAX_DCBX_APP_SUPPORTED; i++) {
0071
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
0097
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
0106
0107
0108
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
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
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
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
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
0176
0177
0178
0179
0180
0181 cxgb4_dcb_update_support(dcb);
0182 }
0183 switch (transition_to) {
0184 case CXGB4_DCB_INPUT_FW_ENABLED: {
0185
0186 break;
0187 }
0188
0189 case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
0190
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
0211 break;
0212 }
0213
0214 case CXGB4_DCB_INPUT_FW_INCOMPLETE: {
0215
0216
0217
0218
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
0229
0230
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
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
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
0285
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
0318
0319
0320
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
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
0372
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
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
0406
0407
0408
0409
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
0419
0420 static u8 cxgb4_setstate(struct net_device *dev, u8 enabled)
0421 {
0422 struct port_info *pi = netdev2pinfo(dev);
0423
0424
0425 if (pi->dcb.state == CXGB4_DCB_STATE_HOST) {
0426 pi->dcb.enabled = enabled;
0427 return 0;
0428 }
0429
0430
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
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
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
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
0630
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
0645
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
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
0698 *caps = 0x80;
0699 break;
0700
0701 case DCB_CAP_ATTR_PFC_TCS:
0702
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
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
0752
0753
0754 static int cxgb4_setnumtcs(struct net_device *dev, int tcs_id, u8 num)
0755 {
0756
0757
0758 return -ENOSYS;
0759 }
0760
0761
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
0773 static void cxgb4_setpfcstate(struct net_device *dev, u8 state)
0774 {
0775
0776
0777
0778 }
0779
0780
0781
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
0816 if (!pcmd.u.dcb.app_priority.protocolid)
0817 break;
0818 }
0819
0820 return -EEXIST;
0821 }
0822
0823
0824
0825
0826 static int cxgb4_getapp(struct net_device *dev, u8 app_idtype, u16 app_id)
0827 {
0828
0829 return __cxgb4_getapp(dev, app_idtype == DCB_APP_IDTYPE_ETHTYPE ?
0830 app_idtype : 3, app_id, 0);
0831 }
0832
0833
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
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
0864 pcmd.u.dcb.app_priority.protocolid = 0;
0865 break;
0866 }
0867
0868 if (!pcmd.u.dcb.app_priority.protocolid)
0869 break;
0870 }
0871
0872 if (i == CXGB4_MAX_DCBX_APP_SUPPORTED) {
0873
0874 dev_err(adap->pdev_dev, "DCB app table full\n");
0875 return -EBUSY;
0876 }
0877
0878
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
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
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
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
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
1023
1024
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
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
1046
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
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
1071
1072 static u8 cxgb4_getdcbx(struct net_device *dev)
1073 {
1074 struct port_info *pi = netdev2pinfo(dev);
1075
1076
1077 return pi->dcb.supported;
1078 }
1079
1080
1081
1082 static u8 cxgb4_setdcbx(struct net_device *dev, u8 dcb_request)
1083 {
1084 struct port_info *pi = netdev2pinfo(dev);
1085
1086
1087
1088 if ((dcb_request & (CXGB4_DCBX_FW_SUPPORT | CXGB4_DCBX_HOST_SUPPORT))
1089 != dcb_request)
1090 return 1;
1091
1092
1093
1094 if (!cxgb4_dcb_state_synced(pi->dcb.state))
1095 return 1;
1096
1097
1098
1099
1100
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
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
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
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
1190
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
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
1232
1233
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
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
1271 .getdcbx = cxgb4_getdcbx,
1272 .setdcbx = cxgb4_setdcbx,
1273
1274
1275 .peer_getappinfo = cxgb4_getpeer_app,
1276 .peer_getapptable = cxgb4_getpeerapp_tbl,
1277
1278
1279 .cee_peer_getpg = cxgb4_cee_peer_getpg,
1280 .cee_peer_getpfc = cxgb4_cee_peer_getpfc,
1281 };