1 /* 2 * This file is part of the Chelsio FCoE driver for Linux. 3 * 4 * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved. 5 * 6 * This software is available to you under a choice of one of two 7 * licenses. You may choose to be licensed under the terms of the GNU 8 * General Public License (GPL) Version 2, available from the file 9 * COPYING in the main directory of this source tree, or the 10 * OpenIB.org BSD license below: 11 * 12 * Redistribution and use in source and binary forms, with or 13 * without modification, are permitted provided that the following 14 * conditions are met: 15 * 16 * - Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and the following 18 * disclaimer. 19 * 20 * - Redistributions in binary form must reproduce the above 21 * copyright notice, this list of conditions and the following 22 * disclaimer in the documentation and/or other materials 23 * provided with the distribution. 24 * 25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 * SOFTWARE. 33 */ 34 35 #include <linux/delay.h> 36 #include <linux/jiffies.h> 37 #include <linux/string.h> 38 #include <scsi/scsi_device.h> 39 #include <scsi/scsi_transport_fc.h> 40 41 #include "csio_hw.h" 42 #include "csio_lnode.h" 43 #include "csio_rnode.h" 44 #include "csio_mb.h" 45 #include "csio_wr.h" 46 47 #define csio_mb_is_host_owner(__owner) ((__owner) == CSIO_MBOWNER_PL) 48 49 /* MB Command/Response Helpers */ 50 /* 51 * csio_mb_fw_retval - FW return value from a mailbox response. 52 * @mbp: Mailbox structure 53 * 54 */ 55 enum fw_retval 56 csio_mb_fw_retval(struct csio_mb *mbp) 57 { 58 struct fw_cmd_hdr *hdr; 59 60 hdr = (struct fw_cmd_hdr *)(mbp->mb); 61 62 return FW_CMD_RETVAL_GET(ntohl(hdr->lo)); 63 } 64 65 /* 66 * csio_mb_hello - FW HELLO command helper 67 * @hw: The HW structure 68 * @mbp: Mailbox structure 69 * @m_mbox: Master mailbox number, if any. 70 * @a_mbox: Mailbox number for asycn notifications. 71 * @master: Device mastership. 72 * @cbfn: Callback, if any. 73 * 74 */ 75 void 76 csio_mb_hello(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 77 uint32_t m_mbox, uint32_t a_mbox, enum csio_dev_master master, 78 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 79 { 80 struct fw_hello_cmd *cmdp = (struct fw_hello_cmd *)(mbp->mb); 81 82 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 83 84 cmdp->op_to_write = htonl(FW_CMD_OP(FW_HELLO_CMD) | 85 FW_CMD_REQUEST | FW_CMD_WRITE); 86 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 87 cmdp->err_to_clearinit = htonl( 88 FW_HELLO_CMD_MASTERDIS(master == CSIO_MASTER_CANT) | 89 FW_HELLO_CMD_MASTERFORCE(master == CSIO_MASTER_MUST) | 90 FW_HELLO_CMD_MBMASTER(master == CSIO_MASTER_MUST ? 91 m_mbox : FW_HELLO_CMD_MBMASTER_MASK) | 92 FW_HELLO_CMD_MBASYNCNOT(a_mbox) | 93 FW_HELLO_CMD_STAGE(fw_hello_cmd_stage_os) | 94 FW_HELLO_CMD_CLEARINIT); 95 96 } 97 98 /* 99 * csio_mb_process_hello_rsp - FW HELLO response processing helper 100 * @hw: The HW structure 101 * @mbp: Mailbox structure 102 * @retval: Mailbox return value from Firmware 103 * @state: State that the function is in. 104 * @mpfn: Master pfn 105 * 106 */ 107 void 108 csio_mb_process_hello_rsp(struct csio_hw *hw, struct csio_mb *mbp, 109 enum fw_retval *retval, enum csio_dev_state *state, 110 uint8_t *mpfn) 111 { 112 struct fw_hello_cmd *rsp = (struct fw_hello_cmd *)(mbp->mb); 113 uint32_t value; 114 115 *retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16)); 116 117 if (*retval == FW_SUCCESS) { 118 hw->fwrev = ntohl(rsp->fwrev); 119 120 value = ntohl(rsp->err_to_clearinit); 121 *mpfn = FW_HELLO_CMD_MBMASTER_GET(value); 122 123 if (value & FW_HELLO_CMD_INIT) 124 *state = CSIO_DEV_STATE_INIT; 125 else if (value & FW_HELLO_CMD_ERR) 126 *state = CSIO_DEV_STATE_ERR; 127 else 128 *state = CSIO_DEV_STATE_UNINIT; 129 } 130 } 131 132 /* 133 * csio_mb_bye - FW BYE command helper 134 * @hw: The HW structure 135 * @mbp: Mailbox structure 136 * @cbfn: Callback, if any. 137 * 138 */ 139 void 140 csio_mb_bye(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 141 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 142 { 143 struct fw_bye_cmd *cmdp = (struct fw_bye_cmd *)(mbp->mb); 144 145 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 146 147 cmdp->op_to_write = htonl(FW_CMD_OP(FW_BYE_CMD) | 148 FW_CMD_REQUEST | FW_CMD_WRITE); 149 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 150 151 } 152 153 /* 154 * csio_mb_reset - FW RESET command helper 155 * @hw: The HW structure 156 * @mbp: Mailbox structure 157 * @reset: Type of reset. 158 * @cbfn: Callback, if any. 159 * 160 */ 161 void 162 csio_mb_reset(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 163 int reset, int halt, 164 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 165 { 166 struct fw_reset_cmd *cmdp = (struct fw_reset_cmd *)(mbp->mb); 167 168 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 169 170 cmdp->op_to_write = htonl(FW_CMD_OP(FW_RESET_CMD) | 171 FW_CMD_REQUEST | FW_CMD_WRITE); 172 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 173 cmdp->val = htonl(reset); 174 cmdp->halt_pkd = htonl(halt); 175 176 } 177 178 /* 179 * csio_mb_params - FW PARAMS command helper 180 * @hw: The HW structure 181 * @mbp: Mailbox structure 182 * @tmo: Command timeout. 183 * @pf: PF number. 184 * @vf: VF number. 185 * @nparams: Number of parameters 186 * @params: Parameter mnemonic array. 187 * @val: Parameter value array. 188 * @wr: Write/Read PARAMS. 189 * @cbfn: Callback, if any. 190 * 191 */ 192 void 193 csio_mb_params(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 194 unsigned int pf, unsigned int vf, unsigned int nparams, 195 const u32 *params, u32 *val, bool wr, 196 void (*cbfn)(struct csio_hw *, struct csio_mb *)) 197 { 198 uint32_t i; 199 uint32_t temp_params = 0, temp_val = 0; 200 struct fw_params_cmd *cmdp = (struct fw_params_cmd *)(mbp->mb); 201 __be32 *p = &cmdp->param[0].mnem; 202 203 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 204 205 cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD) | 206 FW_CMD_REQUEST | 207 (wr ? FW_CMD_WRITE : FW_CMD_READ) | 208 FW_PARAMS_CMD_PFN(pf) | 209 FW_PARAMS_CMD_VFN(vf)); 210 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 211 212 /* Write Params */ 213 if (wr) { 214 while (nparams--) { 215 temp_params = *params++; 216 temp_val = *val++; 217 218 *p++ = htonl(temp_params); 219 *p++ = htonl(temp_val); 220 } 221 } else { 222 for (i = 0; i < nparams; i++, p += 2) { 223 temp_params = *params++; 224 *p = htonl(temp_params); 225 } 226 } 227 228 } 229 230 /* 231 * csio_mb_process_read_params_rsp - FW PARAMS response processing helper 232 * @hw: The HW structure 233 * @mbp: Mailbox structure 234 * @retval: Mailbox return value from Firmware 235 * @nparams: Number of parameters 236 * @val: Parameter value array. 237 * 238 */ 239 void 240 csio_mb_process_read_params_rsp(struct csio_hw *hw, struct csio_mb *mbp, 241 enum fw_retval *retval, unsigned int nparams, 242 u32 *val) 243 { 244 struct fw_params_cmd *rsp = (struct fw_params_cmd *)(mbp->mb); 245 uint32_t i; 246 __be32 *p = &rsp->param[0].val; 247 248 *retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16)); 249 250 if (*retval == FW_SUCCESS) 251 for (i = 0; i < nparams; i++, p += 2) 252 *val++ = ntohl(*p); 253 } 254 255 /* 256 * csio_mb_ldst - FW LDST command 257 * @hw: The HW structure 258 * @mbp: Mailbox structure 259 * @tmo: timeout 260 * @reg: register 261 * 262 */ 263 void 264 csio_mb_ldst(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, int reg) 265 { 266 struct fw_ldst_cmd *ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb); 267 CSIO_INIT_MBP(mbp, ldst_cmd, tmo, hw, NULL, 1); 268 269 /* 270 * Construct and send the Firmware LDST Command to retrieve the 271 * specified PCI-E Configuration Space register. 272 */ 273 ldst_cmd->op_to_addrspace = 274 htonl(FW_CMD_OP(FW_LDST_CMD) | 275 FW_CMD_REQUEST | 276 FW_CMD_READ | 277 FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_FUNC_PCIE)); 278 ldst_cmd->cycles_to_len16 = htonl(FW_LEN16(struct fw_ldst_cmd)); 279 ldst_cmd->u.pcie.select_naccess = FW_LDST_CMD_NACCESS(1); 280 ldst_cmd->u.pcie.ctrl_to_fn = 281 (FW_LDST_CMD_LC | FW_LDST_CMD_FN(hw->pfn)); 282 ldst_cmd->u.pcie.r = (uint8_t)reg; 283 } 284 285 /* 286 * 287 * csio_mb_caps_config - FW Read/Write Capabilities command helper 288 * @hw: The HW structure 289 * @mbp: Mailbox structure 290 * @wr: Write if 1, Read if 0 291 * @init: Turn on initiator mode. 292 * @tgt: Turn on target mode. 293 * @cofld: If 1, Control Offload for FCoE 294 * @cbfn: Callback, if any. 295 * 296 * This helper assumes that cmdp has MB payload from a previous CAPS 297 * read command. 298 */ 299 void 300 csio_mb_caps_config(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 301 bool wr, bool init, bool tgt, bool cofld, 302 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 303 { 304 struct fw_caps_config_cmd *cmdp = 305 (struct fw_caps_config_cmd *)(mbp->mb); 306 307 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, wr ? 0 : 1); 308 309 cmdp->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) | 310 FW_CMD_REQUEST | 311 (wr ? FW_CMD_WRITE : FW_CMD_READ)); 312 cmdp->cfvalid_to_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 313 314 /* Read config */ 315 if (!wr) 316 return; 317 318 /* Write config */ 319 cmdp->fcoecaps = 0; 320 321 if (cofld) 322 cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_CTRL_OFLD); 323 if (init) 324 cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_INITIATOR); 325 if (tgt) 326 cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET); 327 } 328 329 void 330 csio_rss_glb_config(struct csio_hw *hw, struct csio_mb *mbp, 331 uint32_t tmo, uint8_t mode, unsigned int flags, 332 void (*cbfn)(struct csio_hw *, struct csio_mb *)) 333 { 334 struct fw_rss_glb_config_cmd *cmdp = 335 (struct fw_rss_glb_config_cmd *)(mbp->mb); 336 337 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 338 339 cmdp->op_to_write = htonl(FW_CMD_OP(FW_RSS_GLB_CONFIG_CMD) | 340 FW_CMD_REQUEST | FW_CMD_WRITE); 341 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 342 343 if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_MANUAL) { 344 cmdp->u.manual.mode_pkd = 345 htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode)); 346 } else if (mode == FW_RSS_GLB_CONFIG_CMD_MODE_BASICVIRTUAL) { 347 cmdp->u.basicvirtual.mode_pkd = 348 htonl(FW_RSS_GLB_CONFIG_CMD_MODE(mode)); 349 cmdp->u.basicvirtual.synmapen_to_hashtoeplitz = htonl(flags); 350 } 351 } 352 353 354 /* 355 * csio_mb_pfvf - FW Write PF/VF capabilities command helper. 356 * @hw: The HW structure 357 * @mbp: Mailbox structure 358 * @pf: 359 * @vf: 360 * @txq: 361 * @txq_eht_ctrl: 362 * @rxqi: 363 * @rxq: 364 * @tc: 365 * @vi: 366 * @pmask: 367 * @rcaps: 368 * @wxcaps: 369 * @cbfn: Callback, if any. 370 * 371 */ 372 void 373 csio_mb_pfvf(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 374 unsigned int pf, unsigned int vf, unsigned int txq, 375 unsigned int txq_eth_ctrl, unsigned int rxqi, 376 unsigned int rxq, unsigned int tc, unsigned int vi, 377 unsigned int cmask, unsigned int pmask, unsigned int nexactf, 378 unsigned int rcaps, unsigned int wxcaps, 379 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 380 { 381 struct fw_pfvf_cmd *cmdp = (struct fw_pfvf_cmd *)(mbp->mb); 382 383 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 384 385 cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_PFVF_CMD) | 386 FW_CMD_REQUEST | 387 FW_CMD_WRITE | 388 FW_PFVF_CMD_PFN(pf) | 389 FW_PFVF_CMD_VFN(vf)); 390 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 391 cmdp->niqflint_niq = htonl(FW_PFVF_CMD_NIQFLINT(rxqi) | 392 FW_PFVF_CMD_NIQ(rxq)); 393 394 cmdp->type_to_neq = htonl(FW_PFVF_CMD_TYPE | 395 FW_PFVF_CMD_CMASK(cmask) | 396 FW_PFVF_CMD_PMASK(pmask) | 397 FW_PFVF_CMD_NEQ(txq)); 398 cmdp->tc_to_nexactf = htonl(FW_PFVF_CMD_TC(tc) | 399 FW_PFVF_CMD_NVI(vi) | 400 FW_PFVF_CMD_NEXACTF(nexactf)); 401 cmdp->r_caps_to_nethctrl = htonl(FW_PFVF_CMD_R_CAPS(rcaps) | 402 FW_PFVF_CMD_WX_CAPS(wxcaps) | 403 FW_PFVF_CMD_NETHCTRL(txq_eth_ctrl)); 404 } 405 406 #define CSIO_ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\ 407 FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_ANEG) 408 409 /* 410 * csio_mb_port- FW PORT command helper 411 * @hw: The HW structure 412 * @mbp: Mailbox structure 413 * @tmo: COmmand timeout 414 * @portid: Port ID to get/set info 415 * @wr: Write/Read PORT information. 416 * @fc: Flow control 417 * @caps: Port capabilites to set. 418 * @cbfn: Callback, if any. 419 * 420 */ 421 void 422 csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 423 uint8_t portid, bool wr, uint32_t fc, uint16_t caps, 424 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 425 { 426 struct fw_port_cmd *cmdp = (struct fw_port_cmd *)(mbp->mb); 427 unsigned int lfc = 0, mdi = FW_PORT_MDI(FW_PORT_MDI_AUTO); 428 429 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 430 431 cmdp->op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) | 432 FW_CMD_REQUEST | 433 (wr ? FW_CMD_EXEC : FW_CMD_READ) | 434 FW_PORT_CMD_PORTID(portid)); 435 if (!wr) { 436 cmdp->action_to_len16 = htonl( 437 FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) | 438 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 439 return; 440 } 441 442 /* Set port */ 443 cmdp->action_to_len16 = htonl( 444 FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) | 445 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 446 447 if (fc & PAUSE_RX) 448 lfc |= FW_PORT_CAP_FC_RX; 449 if (fc & PAUSE_TX) 450 lfc |= FW_PORT_CAP_FC_TX; 451 452 if (!(caps & FW_PORT_CAP_ANEG)) 453 cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | lfc); 454 else 455 cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | 456 lfc | mdi); 457 } 458 459 /* 460 * csio_mb_process_read_port_rsp - FW PORT command response processing helper 461 * @hw: The HW structure 462 * @mbp: Mailbox structure 463 * @retval: Mailbox return value from Firmware 464 * @caps: port capabilities 465 * 466 */ 467 void 468 csio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp, 469 enum fw_retval *retval, uint16_t *caps) 470 { 471 struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb); 472 473 *retval = FW_CMD_RETVAL_GET(ntohl(rsp->action_to_len16)); 474 475 if (*retval == FW_SUCCESS) 476 *caps = ntohs(rsp->u.info.pcap); 477 } 478 479 /* 480 * csio_mb_initialize - FW INITIALIZE command helper 481 * @hw: The HW structure 482 * @mbp: Mailbox structure 483 * @tmo: COmmand timeout 484 * @cbfn: Callback, if any. 485 * 486 */ 487 void 488 csio_mb_initialize(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 489 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 490 { 491 struct fw_initialize_cmd *cmdp = (struct fw_initialize_cmd *)(mbp->mb); 492 493 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 494 495 cmdp->op_to_write = htonl(FW_CMD_OP(FW_INITIALIZE_CMD) | 496 FW_CMD_REQUEST | FW_CMD_WRITE); 497 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 498 499 } 500 501 /* 502 * csio_mb_iq_alloc - Initializes the mailbox to allocate an 503 * Ingress DMA queue in the firmware. 504 * 505 * @hw: The hw structure 506 * @mbp: Mailbox structure to initialize 507 * @priv: Private object 508 * @mb_tmo: Mailbox time-out period (in ms). 509 * @iq_params: Ingress queue params needed for allocation. 510 * @cbfn: The call-back function 511 * 512 * 513 */ 514 static void 515 csio_mb_iq_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 516 uint32_t mb_tmo, struct csio_iq_params *iq_params, 517 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 518 { 519 struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb); 520 521 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 522 523 cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD) | 524 FW_CMD_REQUEST | FW_CMD_EXEC | 525 FW_IQ_CMD_PFN(iq_params->pfn) | 526 FW_IQ_CMD_VFN(iq_params->vfn)); 527 528 cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC | 529 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 530 531 cmdp->type_to_iqandstindex = htonl( 532 FW_IQ_CMD_VIID(iq_params->viid) | 533 FW_IQ_CMD_TYPE(iq_params->type) | 534 FW_IQ_CMD_IQASYNCH(iq_params->iqasynch)); 535 536 cmdp->fl0size = htons(iq_params->fl0size); 537 cmdp->fl0size = htons(iq_params->fl1size); 538 539 } /* csio_mb_iq_alloc */ 540 541 /* 542 * csio_mb_iq_write - Initializes the mailbox for writing into an 543 * Ingress DMA Queue. 544 * 545 * @hw: The HW structure 546 * @mbp: Mailbox structure to initialize 547 * @priv: Private object 548 * @mb_tmo: Mailbox time-out period (in ms). 549 * @cascaded_req: TRUE - if this request is cascased with iq-alloc request. 550 * @iq_params: Ingress queue params needed for writing. 551 * @cbfn: The call-back function 552 * 553 * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating, 554 * because this IQ write request can be cascaded with a previous 555 * IQ alloc request, and we dont want to over-write the bits set by 556 * that request. This logic will work even in a non-cascaded case, since the 557 * cmdp structure is zeroed out by CSIO_INIT_MBP. 558 */ 559 static void 560 csio_mb_iq_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 561 uint32_t mb_tmo, bool cascaded_req, 562 struct csio_iq_params *iq_params, 563 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 564 { 565 struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb); 566 567 uint32_t iq_start_stop = (iq_params->iq_start) ? 568 FW_IQ_CMD_IQSTART(1) : 569 FW_IQ_CMD_IQSTOP(1); 570 571 /* 572 * If this IQ write is cascaded with IQ alloc request, do not 573 * re-initialize with 0's. 574 * 575 */ 576 if (!cascaded_req) 577 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 578 579 cmdp->op_to_vfn |= htonl(FW_CMD_OP(FW_IQ_CMD) | 580 FW_CMD_REQUEST | FW_CMD_WRITE | 581 FW_IQ_CMD_PFN(iq_params->pfn) | 582 FW_IQ_CMD_VFN(iq_params->vfn)); 583 cmdp->alloc_to_len16 |= htonl(iq_start_stop | 584 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 585 cmdp->iqid |= htons(iq_params->iqid); 586 cmdp->fl0id |= htons(iq_params->fl0id); 587 cmdp->fl1id |= htons(iq_params->fl1id); 588 cmdp->type_to_iqandstindex |= htonl( 589 FW_IQ_CMD_IQANDST(iq_params->iqandst) | 590 FW_IQ_CMD_IQANUS(iq_params->iqanus) | 591 FW_IQ_CMD_IQANUD(iq_params->iqanud) | 592 FW_IQ_CMD_IQANDSTINDEX(iq_params->iqandstindex)); 593 cmdp->iqdroprss_to_iqesize |= htons( 594 FW_IQ_CMD_IQPCIECH(iq_params->iqpciech) | 595 FW_IQ_CMD_IQDCAEN(iq_params->iqdcaen) | 596 FW_IQ_CMD_IQDCACPU(iq_params->iqdcacpu) | 597 FW_IQ_CMD_IQINTCNTTHRESH(iq_params->iqintcntthresh) | 598 FW_IQ_CMD_IQCPRIO(iq_params->iqcprio) | 599 FW_IQ_CMD_IQESIZE(iq_params->iqesize)); 600 601 cmdp->iqsize |= htons(iq_params->iqsize); 602 cmdp->iqaddr |= cpu_to_be64(iq_params->iqaddr); 603 604 if (iq_params->type == 0) { 605 cmdp->iqns_to_fl0congen |= htonl( 606 FW_IQ_CMD_IQFLINTIQHSEN(iq_params->iqflintiqhsen)| 607 FW_IQ_CMD_IQFLINTCONGEN(iq_params->iqflintcongen)); 608 } 609 610 if (iq_params->fl0size && iq_params->fl0addr && 611 (iq_params->fl0id != 0xFFFF)) { 612 613 cmdp->iqns_to_fl0congen |= htonl( 614 FW_IQ_CMD_FL0HOSTFCMODE(iq_params->fl0hostfcmode)| 615 FW_IQ_CMD_FL0CPRIO(iq_params->fl0cprio) | 616 FW_IQ_CMD_FL0PADEN(iq_params->fl0paden) | 617 FW_IQ_CMD_FL0PACKEN(iq_params->fl0packen)); 618 cmdp->fl0dcaen_to_fl0cidxfthresh |= htons( 619 FW_IQ_CMD_FL0DCAEN(iq_params->fl0dcaen) | 620 FW_IQ_CMD_FL0DCACPU(iq_params->fl0dcacpu) | 621 FW_IQ_CMD_FL0FBMIN(iq_params->fl0fbmin) | 622 FW_IQ_CMD_FL0FBMAX(iq_params->fl0fbmax) | 623 FW_IQ_CMD_FL0CIDXFTHRESH(iq_params->fl0cidxfthresh)); 624 cmdp->fl0size |= htons(iq_params->fl0size); 625 cmdp->fl0addr |= cpu_to_be64(iq_params->fl0addr); 626 } 627 } /* csio_mb_iq_write */ 628 629 /* 630 * csio_mb_iq_alloc_write - Initializes the mailbox for allocating an 631 * Ingress DMA Queue. 632 * 633 * @hw: The HW structure 634 * @mbp: Mailbox structure to initialize 635 * @priv: Private data. 636 * @mb_tmo: Mailbox time-out period (in ms). 637 * @iq_params: Ingress queue params needed for allocation & writing. 638 * @cbfn: The call-back function 639 * 640 * 641 */ 642 void 643 csio_mb_iq_alloc_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 644 uint32_t mb_tmo, struct csio_iq_params *iq_params, 645 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 646 { 647 csio_mb_iq_alloc(hw, mbp, priv, mb_tmo, iq_params, cbfn); 648 csio_mb_iq_write(hw, mbp, priv, mb_tmo, true, iq_params, cbfn); 649 } /* csio_mb_iq_alloc_write */ 650 651 /* 652 * csio_mb_iq_alloc_write_rsp - Process the allocation & writing 653 * of ingress DMA queue mailbox's response. 654 * 655 * @hw: The HW structure. 656 * @mbp: Mailbox structure to initialize. 657 * @retval: Firmware return value. 658 * @iq_params: Ingress queue parameters, after allocation and write. 659 * 660 */ 661 void 662 csio_mb_iq_alloc_write_rsp(struct csio_hw *hw, struct csio_mb *mbp, 663 enum fw_retval *ret_val, 664 struct csio_iq_params *iq_params) 665 { 666 struct fw_iq_cmd *rsp = (struct fw_iq_cmd *)(mbp->mb); 667 668 *ret_val = FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)); 669 if (*ret_val == FW_SUCCESS) { 670 iq_params->physiqid = ntohs(rsp->physiqid); 671 iq_params->iqid = ntohs(rsp->iqid); 672 iq_params->fl0id = ntohs(rsp->fl0id); 673 iq_params->fl1id = ntohs(rsp->fl1id); 674 } else { 675 iq_params->physiqid = iq_params->iqid = 676 iq_params->fl0id = iq_params->fl1id = 0; 677 } 678 } /* csio_mb_iq_alloc_write_rsp */ 679 680 /* 681 * csio_mb_iq_free - Initializes the mailbox for freeing a 682 * specified Ingress DMA Queue. 683 * 684 * @hw: The HW structure 685 * @mbp: Mailbox structure to initialize 686 * @priv: Private data 687 * @mb_tmo: Mailbox time-out period (in ms). 688 * @iq_params: Parameters of ingress queue, that is to be freed. 689 * @cbfn: The call-back function 690 * 691 * 692 */ 693 void 694 csio_mb_iq_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 695 uint32_t mb_tmo, struct csio_iq_params *iq_params, 696 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 697 { 698 struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb); 699 700 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 701 702 cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_IQ_CMD) | 703 FW_CMD_REQUEST | FW_CMD_EXEC | 704 FW_IQ_CMD_PFN(iq_params->pfn) | 705 FW_IQ_CMD_VFN(iq_params->vfn)); 706 cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_FREE | 707 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 708 cmdp->type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE(iq_params->type)); 709 710 cmdp->iqid = htons(iq_params->iqid); 711 cmdp->fl0id = htons(iq_params->fl0id); 712 cmdp->fl1id = htons(iq_params->fl1id); 713 714 } /* csio_mb_iq_free */ 715 716 /* 717 * csio_mb_eq_ofld_alloc - Initializes the mailbox for allocating 718 * an offload-egress queue. 719 * 720 * @hw: The HW structure 721 * @mbp: Mailbox structure to initialize 722 * @priv: Private data 723 * @mb_tmo: Mailbox time-out period (in ms). 724 * @eq_ofld_params: (Offload) Egress queue parameters. 725 * @cbfn: The call-back function 726 * 727 * 728 */ 729 static void 730 csio_mb_eq_ofld_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 731 uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params, 732 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 733 { 734 struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb); 735 736 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 737 cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD) | 738 FW_CMD_REQUEST | FW_CMD_EXEC | 739 FW_EQ_OFLD_CMD_PFN(eq_ofld_params->pfn) | 740 FW_EQ_OFLD_CMD_VFN(eq_ofld_params->vfn)); 741 cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_ALLOC | 742 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 743 744 } /* csio_mb_eq_ofld_alloc */ 745 746 /* 747 * csio_mb_eq_ofld_write - Initializes the mailbox for writing 748 * an alloacted offload-egress queue. 749 * 750 * @hw: The HW structure 751 * @mbp: Mailbox structure to initialize 752 * @priv: Private data 753 * @mb_tmo: Mailbox time-out period (in ms). 754 * @cascaded_req: TRUE - if this request is cascased with Eq-alloc request. 755 * @eq_ofld_params: (Offload) Egress queue parameters. 756 * @cbfn: The call-back function 757 * 758 * 759 * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating, 760 * because this EQ write request can be cascaded with a previous 761 * EQ alloc request, and we dont want to over-write the bits set by 762 * that request. This logic will work even in a non-cascaded case, since the 763 * cmdp structure is zeroed out by CSIO_INIT_MBP. 764 */ 765 static void 766 csio_mb_eq_ofld_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 767 uint32_t mb_tmo, bool cascaded_req, 768 struct csio_eq_params *eq_ofld_params, 769 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 770 { 771 struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb); 772 773 uint32_t eq_start_stop = (eq_ofld_params->eqstart) ? 774 FW_EQ_OFLD_CMD_EQSTART : FW_EQ_OFLD_CMD_EQSTOP; 775 776 /* 777 * If this EQ write is cascaded with EQ alloc request, do not 778 * re-initialize with 0's. 779 * 780 */ 781 if (!cascaded_req) 782 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 783 784 cmdp->op_to_vfn |= htonl(FW_CMD_OP(FW_EQ_OFLD_CMD) | 785 FW_CMD_REQUEST | FW_CMD_WRITE | 786 FW_EQ_OFLD_CMD_PFN(eq_ofld_params->pfn) | 787 FW_EQ_OFLD_CMD_VFN(eq_ofld_params->vfn)); 788 cmdp->alloc_to_len16 |= htonl(eq_start_stop | 789 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 790 791 cmdp->eqid_pkd |= htonl(FW_EQ_OFLD_CMD_EQID(eq_ofld_params->eqid)); 792 793 cmdp->fetchszm_to_iqid |= htonl( 794 FW_EQ_OFLD_CMD_HOSTFCMODE(eq_ofld_params->hostfcmode) | 795 FW_EQ_OFLD_CMD_CPRIO(eq_ofld_params->cprio) | 796 FW_EQ_OFLD_CMD_PCIECHN(eq_ofld_params->pciechn) | 797 FW_EQ_OFLD_CMD_IQID(eq_ofld_params->iqid)); 798 799 cmdp->dcaen_to_eqsize |= htonl( 800 FW_EQ_OFLD_CMD_DCAEN(eq_ofld_params->dcaen) | 801 FW_EQ_OFLD_CMD_DCACPU(eq_ofld_params->dcacpu) | 802 FW_EQ_OFLD_CMD_FBMIN(eq_ofld_params->fbmin) | 803 FW_EQ_OFLD_CMD_FBMAX(eq_ofld_params->fbmax) | 804 FW_EQ_OFLD_CMD_CIDXFTHRESHO(eq_ofld_params->cidxfthresho) | 805 FW_EQ_OFLD_CMD_CIDXFTHRESH(eq_ofld_params->cidxfthresh) | 806 FW_EQ_OFLD_CMD_EQSIZE(eq_ofld_params->eqsize)); 807 808 cmdp->eqaddr |= cpu_to_be64(eq_ofld_params->eqaddr); 809 810 } /* csio_mb_eq_ofld_write */ 811 812 /* 813 * csio_mb_eq_ofld_alloc_write - Initializes the mailbox for allocation 814 * writing into an Engress DMA Queue. 815 * 816 * @hw: The HW structure 817 * @mbp: Mailbox structure to initialize 818 * @priv: Private data. 819 * @mb_tmo: Mailbox time-out period (in ms). 820 * @eq_ofld_params: (Offload) Egress queue parameters. 821 * @cbfn: The call-back function 822 * 823 * 824 */ 825 void 826 csio_mb_eq_ofld_alloc_write(struct csio_hw *hw, struct csio_mb *mbp, 827 void *priv, uint32_t mb_tmo, 828 struct csio_eq_params *eq_ofld_params, 829 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 830 { 831 csio_mb_eq_ofld_alloc(hw, mbp, priv, mb_tmo, eq_ofld_params, cbfn); 832 csio_mb_eq_ofld_write(hw, mbp, priv, mb_tmo, true, 833 eq_ofld_params, cbfn); 834 } /* csio_mb_eq_ofld_alloc_write */ 835 836 /* 837 * csio_mb_eq_ofld_alloc_write_rsp - Process the allocation 838 * & write egress DMA queue mailbox's response. 839 * 840 * @hw: The HW structure. 841 * @mbp: Mailbox structure to initialize. 842 * @retval: Firmware return value. 843 * @eq_ofld_params: (Offload) Egress queue parameters. 844 * 845 */ 846 void 847 csio_mb_eq_ofld_alloc_write_rsp(struct csio_hw *hw, 848 struct csio_mb *mbp, enum fw_retval *ret_val, 849 struct csio_eq_params *eq_ofld_params) 850 { 851 struct fw_eq_ofld_cmd *rsp = (struct fw_eq_ofld_cmd *)(mbp->mb); 852 853 *ret_val = FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16)); 854 855 if (*ret_val == FW_SUCCESS) { 856 eq_ofld_params->eqid = FW_EQ_OFLD_CMD_EQID_GET( 857 ntohl(rsp->eqid_pkd)); 858 eq_ofld_params->physeqid = FW_EQ_OFLD_CMD_PHYSEQID_GET( 859 ntohl(rsp->physeqid_pkd)); 860 } else 861 eq_ofld_params->eqid = 0; 862 863 } /* csio_mb_eq_ofld_alloc_write_rsp */ 864 865 /* 866 * csio_mb_eq_ofld_free - Initializes the mailbox for freeing a 867 * specified Engress DMA Queue. 868 * 869 * @hw: The HW structure 870 * @mbp: Mailbox structure to initialize 871 * @priv: Private data area. 872 * @mb_tmo: Mailbox time-out period (in ms). 873 * @eq_ofld_params: (Offload) Egress queue parameters, that is to be freed. 874 * @cbfn: The call-back function 875 * 876 * 877 */ 878 void 879 csio_mb_eq_ofld_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 880 uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params, 881 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 882 { 883 struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb); 884 885 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 886 887 cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_EQ_OFLD_CMD) | 888 FW_CMD_REQUEST | FW_CMD_EXEC | 889 FW_EQ_OFLD_CMD_PFN(eq_ofld_params->pfn) | 890 FW_EQ_OFLD_CMD_VFN(eq_ofld_params->vfn)); 891 cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE | 892 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 893 cmdp->eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID(eq_ofld_params->eqid)); 894 895 } /* csio_mb_eq_ofld_free */ 896 897 /* 898 * csio_write_fcoe_link_cond_init_mb - Initialize Mailbox to write FCoE link 899 * condition. 900 * 901 * @ln: The Lnode structure 902 * @mbp: Mailbox structure to initialize 903 * @mb_tmo: Mailbox time-out period (in ms). 904 * @cbfn: The call back function. 905 * 906 * 907 */ 908 void 909 csio_write_fcoe_link_cond_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 910 uint32_t mb_tmo, uint8_t port_id, uint32_t sub_opcode, 911 uint8_t cos, bool link_status, uint32_t fcfi, 912 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 913 { 914 struct fw_fcoe_link_cmd *cmdp = 915 (struct fw_fcoe_link_cmd *)(mbp->mb); 916 917 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 918 919 cmdp->op_to_portid = htonl(( 920 FW_CMD_OP(FW_FCOE_LINK_CMD) | 921 FW_CMD_REQUEST | 922 FW_CMD_WRITE | 923 FW_FCOE_LINK_CMD_PORTID(port_id))); 924 cmdp->sub_opcode_fcfi = htonl( 925 FW_FCOE_LINK_CMD_SUB_OPCODE(sub_opcode) | 926 FW_FCOE_LINK_CMD_FCFI(fcfi)); 927 cmdp->lstatus = link_status; 928 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 929 930 } /* csio_write_fcoe_link_cond_init_mb */ 931 932 /* 933 * csio_fcoe_read_res_info_init_mb - Initializes the mailbox for reading FCoE 934 * resource information(FW_GET_RES_INFO_CMD). 935 * 936 * @hw: The HW structure 937 * @mbp: Mailbox structure to initialize 938 * @mb_tmo: Mailbox time-out period (in ms). 939 * @cbfn: The call-back function 940 * 941 * 942 */ 943 void 944 csio_fcoe_read_res_info_init_mb(struct csio_hw *hw, struct csio_mb *mbp, 945 uint32_t mb_tmo, 946 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 947 { 948 struct fw_fcoe_res_info_cmd *cmdp = 949 (struct fw_fcoe_res_info_cmd *)(mbp->mb); 950 951 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1); 952 953 cmdp->op_to_read = htonl((FW_CMD_OP(FW_FCOE_RES_INFO_CMD) | 954 FW_CMD_REQUEST | 955 FW_CMD_READ)); 956 957 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 958 959 } /* csio_fcoe_read_res_info_init_mb */ 960 961 /* 962 * csio_fcoe_vnp_alloc_init_mb - Initializes the mailbox for allocating VNP 963 * in the firmware (FW_FCOE_VNP_CMD). 964 * 965 * @ln: The Lnode structure. 966 * @mbp: Mailbox structure to initialize. 967 * @mb_tmo: Mailbox time-out period (in ms). 968 * @fcfi: FCF Index. 969 * @vnpi: vnpi 970 * @iqid: iqid 971 * @vnport_wwnn: vnport WWNN 972 * @vnport_wwpn: vnport WWPN 973 * @cbfn: The call-back function. 974 * 975 * 976 */ 977 void 978 csio_fcoe_vnp_alloc_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 979 uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi, uint16_t iqid, 980 uint8_t vnport_wwnn[8], uint8_t vnport_wwpn[8], 981 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 982 { 983 struct fw_fcoe_vnp_cmd *cmdp = 984 (struct fw_fcoe_vnp_cmd *)(mbp->mb); 985 986 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 987 988 cmdp->op_to_fcfi = htonl((FW_CMD_OP(FW_FCOE_VNP_CMD) | 989 FW_CMD_REQUEST | 990 FW_CMD_EXEC | 991 FW_FCOE_VNP_CMD_FCFI(fcfi))); 992 993 cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_ALLOC | 994 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 995 996 cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi)); 997 998 cmdp->iqid = htons(iqid); 999 1000 if (!wwn_to_u64(vnport_wwnn) && !wwn_to_u64(vnport_wwpn)) 1001 cmdp->gen_wwn_to_vnpi |= htonl(FW_FCOE_VNP_CMD_GEN_WWN); 1002 1003 if (vnport_wwnn) 1004 memcpy(cmdp->vnport_wwnn, vnport_wwnn, 8); 1005 if (vnport_wwpn) 1006 memcpy(cmdp->vnport_wwpn, vnport_wwpn, 8); 1007 1008 } /* csio_fcoe_vnp_alloc_init_mb */ 1009 1010 /* 1011 * csio_fcoe_vnp_read_init_mb - Prepares VNP read cmd. 1012 * @ln: The Lnode structure. 1013 * @mbp: Mailbox structure to initialize. 1014 * @mb_tmo: Mailbox time-out period (in ms). 1015 * @fcfi: FCF Index. 1016 * @vnpi: vnpi 1017 * @cbfn: The call-back handler. 1018 */ 1019 void 1020 csio_fcoe_vnp_read_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 1021 uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi, 1022 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 1023 { 1024 struct fw_fcoe_vnp_cmd *cmdp = 1025 (struct fw_fcoe_vnp_cmd *)(mbp->mb); 1026 1027 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 1028 cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_VNP_CMD) | 1029 FW_CMD_REQUEST | 1030 FW_CMD_READ | 1031 FW_FCOE_VNP_CMD_FCFI(fcfi)); 1032 cmdp->alloc_to_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 1033 cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi)); 1034 } 1035 1036 /* 1037 * csio_fcoe_vnp_free_init_mb - Initializes the mailbox for freeing an 1038 * alloacted VNP in the firmware (FW_FCOE_VNP_CMD). 1039 * 1040 * @ln: The Lnode structure. 1041 * @mbp: Mailbox structure to initialize. 1042 * @mb_tmo: Mailbox time-out period (in ms). 1043 * @fcfi: FCF flow id 1044 * @vnpi: VNP flow id 1045 * @cbfn: The call-back function. 1046 * Return: None 1047 */ 1048 void 1049 csio_fcoe_vnp_free_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 1050 uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi, 1051 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 1052 { 1053 struct fw_fcoe_vnp_cmd *cmdp = 1054 (struct fw_fcoe_vnp_cmd *)(mbp->mb); 1055 1056 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 1057 1058 cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_VNP_CMD) | 1059 FW_CMD_REQUEST | 1060 FW_CMD_EXEC | 1061 FW_FCOE_VNP_CMD_FCFI(fcfi)); 1062 cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_FREE | 1063 FW_CMD_LEN16(sizeof(*cmdp) / 16)); 1064 cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi)); 1065 } 1066 1067 /* 1068 * csio_fcoe_read_fcf_init_mb - Initializes the mailbox to read the 1069 * FCF records. 1070 * 1071 * @ln: The Lnode structure 1072 * @mbp: Mailbox structure to initialize 1073 * @mb_tmo: Mailbox time-out period (in ms). 1074 * @fcf_params: FC-Forwarder parameters. 1075 * @cbfn: The call-back function 1076 * 1077 * 1078 */ 1079 void 1080 csio_fcoe_read_fcf_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 1081 uint32_t mb_tmo, uint32_t portid, uint32_t fcfi, 1082 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 1083 { 1084 struct fw_fcoe_fcf_cmd *cmdp = 1085 (struct fw_fcoe_fcf_cmd *)(mbp->mb); 1086 1087 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 1088 1089 cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_FCF_CMD) | 1090 FW_CMD_REQUEST | 1091 FW_CMD_READ | 1092 FW_FCOE_FCF_CMD_FCFI(fcfi)); 1093 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16)); 1094 1095 } /* csio_fcoe_read_fcf_init_mb */ 1096 1097 void 1098 csio_fcoe_read_portparams_init_mb(struct csio_hw *hw, struct csio_mb *mbp, 1099 uint32_t mb_tmo, 1100 struct fw_fcoe_port_cmd_params *portparams, 1101 void (*cbfn)(struct csio_hw *, 1102 struct csio_mb *)) 1103 { 1104 struct fw_fcoe_stats_cmd *cmdp = (struct fw_fcoe_stats_cmd *)(mbp->mb); 1105 1106 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1); 1107 mbp->mb_size = 64; 1108 1109 cmdp->op_to_flowid = htonl(FW_CMD_OP(FW_FCOE_STATS_CMD) | 1110 FW_CMD_REQUEST | FW_CMD_READ); 1111 cmdp->free_to_len16 = htonl(FW_CMD_LEN16(CSIO_MAX_MB_SIZE/16)); 1112 1113 cmdp->u.ctl.nstats_port = FW_FCOE_STATS_CMD_NSTATS(portparams->nstats) | 1114 FW_FCOE_STATS_CMD_PORT(portparams->portid); 1115 1116 cmdp->u.ctl.port_valid_ix = FW_FCOE_STATS_CMD_IX(portparams->idx) | 1117 FW_FCOE_STATS_CMD_PORT_VALID; 1118 1119 } /* csio_fcoe_read_portparams_init_mb */ 1120 1121 void 1122 csio_mb_process_portparams_rsp(struct csio_hw *hw, 1123 struct csio_mb *mbp, 1124 enum fw_retval *retval, 1125 struct fw_fcoe_port_cmd_params *portparams, 1126 struct fw_fcoe_port_stats *portstats) 1127 { 1128 struct fw_fcoe_stats_cmd *rsp = (struct fw_fcoe_stats_cmd *)(mbp->mb); 1129 struct fw_fcoe_port_stats stats; 1130 uint8_t *src; 1131 uint8_t *dst; 1132 1133 *retval = FW_CMD_RETVAL_GET(ntohl(rsp->free_to_len16)); 1134 1135 memset(&stats, 0, sizeof(struct fw_fcoe_port_stats)); 1136 1137 if (*retval == FW_SUCCESS) { 1138 dst = (uint8_t *)(&stats) + ((portparams->idx - 1) * 8); 1139 src = (uint8_t *)rsp + (CSIO_STATS_OFFSET * 8); 1140 memcpy(dst, src, (portparams->nstats * 8)); 1141 if (portparams->idx == 1) { 1142 /* Get the first 6 flits from the Mailbox */ 1143 portstats->tx_bcast_bytes = stats.tx_bcast_bytes; 1144 portstats->tx_bcast_frames = stats.tx_bcast_frames; 1145 portstats->tx_mcast_bytes = stats.tx_mcast_bytes; 1146 portstats->tx_mcast_frames = stats.tx_mcast_frames; 1147 portstats->tx_ucast_bytes = stats.tx_ucast_bytes; 1148 portstats->tx_ucast_frames = stats.tx_ucast_frames; 1149 } 1150 if (portparams->idx == 7) { 1151 /* Get the second 6 flits from the Mailbox */ 1152 portstats->tx_drop_frames = stats.tx_drop_frames; 1153 portstats->tx_offload_bytes = stats.tx_offload_bytes; 1154 portstats->tx_offload_frames = stats.tx_offload_frames; 1155 #if 0 1156 portstats->rx_pf_bytes = stats.rx_pf_bytes; 1157 portstats->rx_pf_frames = stats.rx_pf_frames; 1158 #endif 1159 portstats->rx_bcast_bytes = stats.rx_bcast_bytes; 1160 portstats->rx_bcast_frames = stats.rx_bcast_frames; 1161 portstats->rx_mcast_bytes = stats.rx_mcast_bytes; 1162 } 1163 if (portparams->idx == 13) { 1164 /* Get the last 4 flits from the Mailbox */ 1165 portstats->rx_mcast_frames = stats.rx_mcast_frames; 1166 portstats->rx_ucast_bytes = stats.rx_ucast_bytes; 1167 portstats->rx_ucast_frames = stats.rx_ucast_frames; 1168 portstats->rx_err_frames = stats.rx_err_frames; 1169 } 1170 } 1171 } 1172 1173 /* Entry points/APIs for MB module */ 1174 /* 1175 * csio_mb_intr_enable - Enable Interrupts from mailboxes. 1176 * @hw: The HW structure 1177 * 1178 * Enables CIM interrupt bit in appropriate INT_ENABLE registers. 1179 */ 1180 void 1181 csio_mb_intr_enable(struct csio_hw *hw) 1182 { 1183 csio_wr_reg32(hw, MBMSGRDYINTEN(1), MYPF_REG(CIM_PF_HOST_INT_ENABLE)); 1184 csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE)); 1185 } 1186 1187 /* 1188 * csio_mb_intr_disable - Disable Interrupts from mailboxes. 1189 * @hw: The HW structure 1190 * 1191 * Disable bit in HostInterruptEnable CIM register. 1192 */ 1193 void 1194 csio_mb_intr_disable(struct csio_hw *hw) 1195 { 1196 csio_wr_reg32(hw, MBMSGRDYINTEN(0), MYPF_REG(CIM_PF_HOST_INT_ENABLE)); 1197 csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE)); 1198 } 1199 1200 static void 1201 csio_mb_dump_fw_dbg(struct csio_hw *hw, __be64 *cmd) 1202 { 1203 struct fw_debug_cmd *dbg = (struct fw_debug_cmd *)cmd; 1204 1205 if ((FW_DEBUG_CMD_TYPE_GET(ntohl(dbg->op_type))) == 1) { 1206 csio_info(hw, "FW print message:\n"); 1207 csio_info(hw, "\tdebug->dprtstridx = %d\n", 1208 ntohs(dbg->u.prt.dprtstridx)); 1209 csio_info(hw, "\tdebug->dprtstrparam0 = 0x%x\n", 1210 ntohl(dbg->u.prt.dprtstrparam0)); 1211 csio_info(hw, "\tdebug->dprtstrparam1 = 0x%x\n", 1212 ntohl(dbg->u.prt.dprtstrparam1)); 1213 csio_info(hw, "\tdebug->dprtstrparam2 = 0x%x\n", 1214 ntohl(dbg->u.prt.dprtstrparam2)); 1215 csio_info(hw, "\tdebug->dprtstrparam3 = 0x%x\n", 1216 ntohl(dbg->u.prt.dprtstrparam3)); 1217 } else { 1218 /* This is a FW assertion */ 1219 csio_fatal(hw, "FW assertion at %.16s:%u, val0 %#x, val1 %#x\n", 1220 dbg->u.assert.filename_0_7, 1221 ntohl(dbg->u.assert.line), 1222 ntohl(dbg->u.assert.x), 1223 ntohl(dbg->u.assert.y)); 1224 } 1225 } 1226 1227 static void 1228 csio_mb_debug_cmd_handler(struct csio_hw *hw) 1229 { 1230 int i; 1231 __be64 cmd[CSIO_MB_MAX_REGS]; 1232 uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL); 1233 uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA); 1234 int size = sizeof(struct fw_debug_cmd); 1235 1236 /* Copy mailbox data */ 1237 for (i = 0; i < size; i += 8) 1238 cmd[i / 8] = cpu_to_be64(csio_rd_reg64(hw, data_reg + i)); 1239 1240 csio_mb_dump_fw_dbg(hw, cmd); 1241 1242 /* Notify FW of mailbox by setting owner as UP */ 1243 csio_wr_reg32(hw, MBMSGVALID | MBINTREQ | MBOWNER(CSIO_MBOWNER_FW), 1244 ctl_reg); 1245 1246 csio_rd_reg32(hw, ctl_reg); 1247 wmb(); 1248 } 1249 1250 /* 1251 * csio_mb_issue - generic routine for issuing Mailbox commands. 1252 * @hw: The HW structure 1253 * @mbp: Mailbox command to issue 1254 * 1255 * Caller should hold hw lock across this call. 1256 */ 1257 int 1258 csio_mb_issue(struct csio_hw *hw, struct csio_mb *mbp) 1259 { 1260 uint32_t owner, ctl; 1261 int i; 1262 uint32_t ii; 1263 __be64 *cmd = mbp->mb; 1264 __be64 hdr; 1265 struct csio_mbm *mbm = &hw->mbm; 1266 uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL); 1267 uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA); 1268 int size = mbp->mb_size; 1269 int rv = -EINVAL; 1270 struct fw_cmd_hdr *fw_hdr; 1271 1272 /* Determine mode */ 1273 if (mbp->mb_cbfn == NULL) { 1274 /* Need to issue/get results in the same context */ 1275 if (mbp->tmo < CSIO_MB_POLL_FREQ) { 1276 csio_err(hw, "Invalid tmo: 0x%x\n", mbp->tmo); 1277 goto error_out; 1278 } 1279 } else if (!csio_is_host_intr_enabled(hw) || 1280 !csio_is_hw_intr_enabled(hw)) { 1281 csio_err(hw, "Cannot issue mailbox in interrupt mode 0x%x\n", 1282 *((uint8_t *)mbp->mb)); 1283 goto error_out; 1284 } 1285 1286 if (mbm->mcurrent != NULL) { 1287 /* Queue mbox cmd, if another mbox cmd is active */ 1288 if (mbp->mb_cbfn == NULL) { 1289 rv = -EBUSY; 1290 csio_dbg(hw, "Couldnt own Mailbox %x op:0x%x\n", 1291 hw->pfn, *((uint8_t *)mbp->mb)); 1292 1293 goto error_out; 1294 } else { 1295 list_add_tail(&mbp->list, &mbm->req_q); 1296 CSIO_INC_STATS(mbm, n_activeq); 1297 1298 return 0; 1299 } 1300 } 1301 1302 /* Now get ownership of mailbox */ 1303 owner = MBOWNER_GET(csio_rd_reg32(hw, ctl_reg)); 1304 1305 if (!csio_mb_is_host_owner(owner)) { 1306 1307 for (i = 0; (owner == CSIO_MBOWNER_NONE) && (i < 3); i++) 1308 owner = MBOWNER_GET(csio_rd_reg32(hw, ctl_reg)); 1309 /* 1310 * Mailbox unavailable. In immediate mode, fail the command. 1311 * In other modes, enqueue the request. 1312 */ 1313 if (!csio_mb_is_host_owner(owner)) { 1314 if (mbp->mb_cbfn == NULL) { 1315 rv = owner ? -EBUSY : -ETIMEDOUT; 1316 1317 csio_dbg(hw, 1318 "Couldnt own Mailbox %x op:0x%x " 1319 "owner:%x\n", 1320 hw->pfn, *((uint8_t *)mbp->mb), owner); 1321 goto error_out; 1322 } else { 1323 if (mbm->mcurrent == NULL) { 1324 csio_err(hw, 1325 "Couldnt own Mailbox %x " 1326 "op:0x%x owner:%x\n", 1327 hw->pfn, *((uint8_t *)mbp->mb), 1328 owner); 1329 csio_err(hw, 1330 "No outstanding driver" 1331 " mailbox as well\n"); 1332 goto error_out; 1333 } 1334 } 1335 } 1336 } 1337 1338 /* Mailbox is available, copy mailbox data into it */ 1339 for (i = 0; i < size; i += 8) { 1340 csio_wr_reg64(hw, be64_to_cpu(*cmd), data_reg + i); 1341 cmd++; 1342 } 1343 1344 CSIO_DUMP_MB(hw, hw->pfn, data_reg); 1345 1346 /* Start completion timers in non-immediate modes and notify FW */ 1347 if (mbp->mb_cbfn != NULL) { 1348 mbm->mcurrent = mbp; 1349 mod_timer(&mbm->timer, jiffies + msecs_to_jiffies(mbp->tmo)); 1350 csio_wr_reg32(hw, MBMSGVALID | MBINTREQ | 1351 MBOWNER(CSIO_MBOWNER_FW), ctl_reg); 1352 } else 1353 csio_wr_reg32(hw, MBMSGVALID | MBOWNER(CSIO_MBOWNER_FW), 1354 ctl_reg); 1355 1356 /* Flush posted writes */ 1357 csio_rd_reg32(hw, ctl_reg); 1358 wmb(); 1359 1360 CSIO_INC_STATS(mbm, n_req); 1361 1362 if (mbp->mb_cbfn) 1363 return 0; 1364 1365 /* Poll for completion in immediate mode */ 1366 cmd = mbp->mb; 1367 1368 for (ii = 0; ii < mbp->tmo; ii += CSIO_MB_POLL_FREQ) { 1369 mdelay(CSIO_MB_POLL_FREQ); 1370 1371 /* Check for response */ 1372 ctl = csio_rd_reg32(hw, ctl_reg); 1373 if (csio_mb_is_host_owner(MBOWNER_GET(ctl))) { 1374 1375 if (!(ctl & MBMSGVALID)) { 1376 csio_wr_reg32(hw, 0, ctl_reg); 1377 continue; 1378 } 1379 1380 CSIO_DUMP_MB(hw, hw->pfn, data_reg); 1381 1382 hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg)); 1383 fw_hdr = (struct fw_cmd_hdr *)&hdr; 1384 1385 switch (FW_CMD_OP_GET(ntohl(fw_hdr->hi))) { 1386 case FW_DEBUG_CMD: 1387 csio_mb_debug_cmd_handler(hw); 1388 continue; 1389 } 1390 1391 /* Copy response */ 1392 for (i = 0; i < size; i += 8) 1393 *cmd++ = cpu_to_be64(csio_rd_reg64 1394 (hw, data_reg + i)); 1395 csio_wr_reg32(hw, 0, ctl_reg); 1396 1397 if (csio_mb_fw_retval(mbp) != FW_SUCCESS) 1398 CSIO_INC_STATS(mbm, n_err); 1399 1400 CSIO_INC_STATS(mbm, n_rsp); 1401 return 0; 1402 } 1403 } 1404 1405 CSIO_INC_STATS(mbm, n_tmo); 1406 1407 csio_err(hw, "Mailbox %x op:0x%x timed out!\n", 1408 hw->pfn, *((uint8_t *)cmd)); 1409 1410 return -ETIMEDOUT; 1411 1412 error_out: 1413 CSIO_INC_STATS(mbm, n_err); 1414 return rv; 1415 } 1416 1417 /* 1418 * csio_mb_completions - Completion handler for Mailbox commands 1419 * @hw: The HW structure 1420 * @cbfn_q: Completion queue. 1421 * 1422 */ 1423 void 1424 csio_mb_completions(struct csio_hw *hw, struct list_head *cbfn_q) 1425 { 1426 struct csio_mb *mbp; 1427 struct csio_mbm *mbm = &hw->mbm; 1428 enum fw_retval rv; 1429 1430 while (!list_empty(cbfn_q)) { 1431 mbp = list_first_entry(cbfn_q, struct csio_mb, list); 1432 list_del_init(&mbp->list); 1433 1434 rv = csio_mb_fw_retval(mbp); 1435 if ((rv != FW_SUCCESS) && (rv != FW_HOSTERROR)) 1436 CSIO_INC_STATS(mbm, n_err); 1437 else if (rv != FW_HOSTERROR) 1438 CSIO_INC_STATS(mbm, n_rsp); 1439 1440 if (mbp->mb_cbfn) 1441 mbp->mb_cbfn(hw, mbp); 1442 } 1443 } 1444 1445 static void 1446 csio_mb_portmod_changed(struct csio_hw *hw, uint8_t port_id) 1447 { 1448 static char *mod_str[] = { 1449 NULL, "LR", "SR", "ER", "TWINAX", "active TWINAX", "LRM" 1450 }; 1451 1452 struct csio_pport *port = &hw->pport[port_id]; 1453 1454 if (port->mod_type == FW_PORT_MOD_TYPE_NONE) 1455 csio_info(hw, "Port:%d - port module unplugged\n", port_id); 1456 else if (port->mod_type < ARRAY_SIZE(mod_str)) 1457 csio_info(hw, "Port:%d - %s port module inserted\n", port_id, 1458 mod_str[port->mod_type]); 1459 else if (port->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED) 1460 csio_info(hw, 1461 "Port:%d - unsupported optical port module " 1462 "inserted\n", port_id); 1463 else if (port->mod_type == FW_PORT_MOD_TYPE_UNKNOWN) 1464 csio_info(hw, 1465 "Port:%d - unknown port module inserted, forcing " 1466 "TWINAX\n", port_id); 1467 else if (port->mod_type == FW_PORT_MOD_TYPE_ERROR) 1468 csio_info(hw, "Port:%d - transceiver module error\n", port_id); 1469 else 1470 csio_info(hw, "Port:%d - unknown module type %d inserted\n", 1471 port_id, port->mod_type); 1472 } 1473 1474 int 1475 csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd) 1476 { 1477 uint8_t opcode = *(uint8_t *)cmd; 1478 struct fw_port_cmd *pcmd; 1479 uint8_t port_id; 1480 uint32_t link_status; 1481 uint16_t action; 1482 uint8_t mod_type; 1483 1484 if (opcode == FW_PORT_CMD) { 1485 pcmd = (struct fw_port_cmd *)cmd; 1486 port_id = FW_PORT_CMD_PORTID_GET( 1487 ntohl(pcmd->op_to_portid)); 1488 action = FW_PORT_CMD_ACTION_GET( 1489 ntohl(pcmd->action_to_len16)); 1490 if (action != FW_PORT_ACTION_GET_PORT_INFO) { 1491 csio_err(hw, "Unhandled FW_PORT_CMD action: %u\n", 1492 action); 1493 return -EINVAL; 1494 } 1495 1496 link_status = ntohl(pcmd->u.info.lstatus_to_modtype); 1497 mod_type = FW_PORT_CMD_MODTYPE_GET(link_status); 1498 1499 hw->pport[port_id].link_status = 1500 FW_PORT_CMD_LSTATUS_GET(link_status); 1501 hw->pport[port_id].link_speed = 1502 FW_PORT_CMD_LSPEED_GET(link_status); 1503 1504 csio_info(hw, "Port:%x - LINK %s\n", port_id, 1505 FW_PORT_CMD_LSTATUS_GET(link_status) ? "UP" : "DOWN"); 1506 1507 if (mod_type != hw->pport[port_id].mod_type) { 1508 hw->pport[port_id].mod_type = mod_type; 1509 csio_mb_portmod_changed(hw, port_id); 1510 } 1511 } else if (opcode == FW_DEBUG_CMD) { 1512 csio_mb_dump_fw_dbg(hw, cmd); 1513 } else { 1514 csio_dbg(hw, "Gen MB can't handle op:0x%x on evtq.\n", opcode); 1515 return -EINVAL; 1516 } 1517 1518 return 0; 1519 } 1520 1521 /* 1522 * csio_mb_isr_handler - Handle mailboxes related interrupts. 1523 * @hw: The HW structure 1524 * 1525 * Called from the ISR to handle Mailbox related interrupts. 1526 * HW Lock should be held across this call. 1527 */ 1528 int 1529 csio_mb_isr_handler(struct csio_hw *hw) 1530 { 1531 struct csio_mbm *mbm = &hw->mbm; 1532 struct csio_mb *mbp = mbm->mcurrent; 1533 __be64 *cmd; 1534 uint32_t ctl, cim_cause, pl_cause; 1535 int i; 1536 uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL); 1537 uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA); 1538 int size; 1539 __be64 hdr; 1540 struct fw_cmd_hdr *fw_hdr; 1541 1542 pl_cause = csio_rd_reg32(hw, MYPF_REG(PL_PF_INT_CAUSE)); 1543 cim_cause = csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_CAUSE)); 1544 1545 if (!(pl_cause & PFCIM) || !(cim_cause & MBMSGRDYINT)) { 1546 CSIO_INC_STATS(hw, n_mbint_unexp); 1547 return -EINVAL; 1548 } 1549 1550 /* 1551 * The cause registers below HAVE to be cleared in the SAME 1552 * order as below: The low level cause register followed by 1553 * the upper level cause register. In other words, CIM-cause 1554 * first followed by PL-Cause next. 1555 */ 1556 csio_wr_reg32(hw, MBMSGRDYINT, MYPF_REG(CIM_PF_HOST_INT_CAUSE)); 1557 csio_wr_reg32(hw, PFCIM, MYPF_REG(PL_PF_INT_CAUSE)); 1558 1559 ctl = csio_rd_reg32(hw, ctl_reg); 1560 1561 if (csio_mb_is_host_owner(MBOWNER_GET(ctl))) { 1562 1563 CSIO_DUMP_MB(hw, hw->pfn, data_reg); 1564 1565 if (!(ctl & MBMSGVALID)) { 1566 csio_warn(hw, 1567 "Stray mailbox interrupt recvd," 1568 " mailbox data not valid\n"); 1569 csio_wr_reg32(hw, 0, ctl_reg); 1570 /* Flush */ 1571 csio_rd_reg32(hw, ctl_reg); 1572 return -EINVAL; 1573 } 1574 1575 hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg)); 1576 fw_hdr = (struct fw_cmd_hdr *)&hdr; 1577 1578 switch (FW_CMD_OP_GET(ntohl(fw_hdr->hi))) { 1579 case FW_DEBUG_CMD: 1580 csio_mb_debug_cmd_handler(hw); 1581 return -EINVAL; 1582 #if 0 1583 case FW_ERROR_CMD: 1584 case FW_INITIALIZE_CMD: /* When we are not master */ 1585 #endif 1586 } 1587 1588 CSIO_ASSERT(mbp != NULL); 1589 1590 cmd = mbp->mb; 1591 size = mbp->mb_size; 1592 /* Get response */ 1593 for (i = 0; i < size; i += 8) 1594 *cmd++ = cpu_to_be64(csio_rd_reg64 1595 (hw, data_reg + i)); 1596 1597 csio_wr_reg32(hw, 0, ctl_reg); 1598 /* Flush */ 1599 csio_rd_reg32(hw, ctl_reg); 1600 1601 mbm->mcurrent = NULL; 1602 1603 /* Add completion to tail of cbfn queue */ 1604 list_add_tail(&mbp->list, &mbm->cbfn_q); 1605 CSIO_INC_STATS(mbm, n_cbfnq); 1606 1607 /* 1608 * Enqueue event to EventQ. Events processing happens 1609 * in Event worker thread context 1610 */ 1611 if (csio_enqueue_evt(hw, CSIO_EVT_MBX, mbp, sizeof(mbp))) 1612 CSIO_INC_STATS(hw, n_evt_drop); 1613 1614 return 0; 1615 1616 } else { 1617 /* 1618 * We can get here if mailbox MSIX vector is shared, 1619 * or in INTx case. Or a stray interrupt. 1620 */ 1621 csio_dbg(hw, "Host not owner, no mailbox interrupt\n"); 1622 CSIO_INC_STATS(hw, n_int_stray); 1623 return -EINVAL; 1624 } 1625 } 1626 1627 /* 1628 * csio_mb_tmo_handler - Timeout handler 1629 * @hw: The HW structure 1630 * 1631 */ 1632 struct csio_mb * 1633 csio_mb_tmo_handler(struct csio_hw *hw) 1634 { 1635 struct csio_mbm *mbm = &hw->mbm; 1636 struct csio_mb *mbp = mbm->mcurrent; 1637 struct fw_cmd_hdr *fw_hdr; 1638 1639 /* 1640 * Could be a race b/w the completion handler and the timer 1641 * and the completion handler won that race. 1642 */ 1643 if (mbp == NULL) { 1644 CSIO_DB_ASSERT(0); 1645 return NULL; 1646 } 1647 1648 fw_hdr = (struct fw_cmd_hdr *)(mbp->mb); 1649 1650 csio_dbg(hw, "Mailbox num:%x op:0x%x timed out\n", hw->pfn, 1651 FW_CMD_OP_GET(ntohl(fw_hdr->hi))); 1652 1653 mbm->mcurrent = NULL; 1654 CSIO_INC_STATS(mbm, n_tmo); 1655 fw_hdr->lo = htonl(FW_CMD_RETVAL(FW_ETIMEDOUT)); 1656 1657 return mbp; 1658 } 1659 1660 /* 1661 * csio_mb_cancel_all - Cancel all waiting commands. 1662 * @hw: The HW structure 1663 * @cbfn_q: The callback queue. 1664 * 1665 * Caller should hold hw lock across this call. 1666 */ 1667 void 1668 csio_mb_cancel_all(struct csio_hw *hw, struct list_head *cbfn_q) 1669 { 1670 struct csio_mb *mbp; 1671 struct csio_mbm *mbm = &hw->mbm; 1672 struct fw_cmd_hdr *hdr; 1673 struct list_head *tmp; 1674 1675 if (mbm->mcurrent) { 1676 mbp = mbm->mcurrent; 1677 1678 /* Stop mailbox completion timer */ 1679 del_timer_sync(&mbm->timer); 1680 1681 /* Add completion to tail of cbfn queue */ 1682 list_add_tail(&mbp->list, cbfn_q); 1683 mbm->mcurrent = NULL; 1684 } 1685 1686 if (!list_empty(&mbm->req_q)) { 1687 list_splice_tail_init(&mbm->req_q, cbfn_q); 1688 mbm->stats.n_activeq = 0; 1689 } 1690 1691 if (!list_empty(&mbm->cbfn_q)) { 1692 list_splice_tail_init(&mbm->cbfn_q, cbfn_q); 1693 mbm->stats.n_cbfnq = 0; 1694 } 1695 1696 if (list_empty(cbfn_q)) 1697 return; 1698 1699 list_for_each(tmp, cbfn_q) { 1700 mbp = (struct csio_mb *)tmp; 1701 hdr = (struct fw_cmd_hdr *)(mbp->mb); 1702 1703 csio_dbg(hw, "Cancelling pending mailbox num %x op:%x\n", 1704 hw->pfn, FW_CMD_OP_GET(ntohl(hdr->hi))); 1705 1706 CSIO_INC_STATS(mbm, n_cancel); 1707 hdr->lo = htonl(FW_CMD_RETVAL(FW_HOSTERROR)); 1708 } 1709 } 1710 1711 /* 1712 * csio_mbm_init - Initialize Mailbox module 1713 * @mbm: Mailbox module 1714 * @hw: The HW structure 1715 * @timer: Timing function for interrupting mailboxes 1716 * 1717 * Initialize timer and the request/response queues. 1718 */ 1719 int 1720 csio_mbm_init(struct csio_mbm *mbm, struct csio_hw *hw, 1721 void (*timer_fn)(uintptr_t)) 1722 { 1723 struct timer_list *timer = &mbm->timer; 1724 1725 init_timer(timer); 1726 timer->function = timer_fn; 1727 timer->data = (unsigned long)hw; 1728 1729 INIT_LIST_HEAD(&mbm->req_q); 1730 INIT_LIST_HEAD(&mbm->cbfn_q); 1731 csio_set_mb_intr_idx(mbm, -1); 1732 1733 return 0; 1734 } 1735 1736 /* 1737 * csio_mbm_exit - Uninitialize mailbox module 1738 * @mbm: Mailbox module 1739 * 1740 * Stop timer. 1741 */ 1742 void 1743 csio_mbm_exit(struct csio_mbm *mbm) 1744 { 1745 del_timer_sync(&mbm->timer); 1746 1747 CSIO_DB_ASSERT(mbm->mcurrent == NULL); 1748 CSIO_DB_ASSERT(list_empty(&mbm->req_q)); 1749 CSIO_DB_ASSERT(list_empty(&mbm->cbfn_q)); 1750 } 1751