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_G(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_V(FW_HELLO_CMD) | 85 FW_CMD_REQUEST_F | FW_CMD_WRITE_F); 86 cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 87 cmdp->err_to_clearinit = htonl( 88 FW_HELLO_CMD_MASTERDIS_V(master == CSIO_MASTER_CANT) | 89 FW_HELLO_CMD_MASTERFORCE_V(master == CSIO_MASTER_MUST) | 90 FW_HELLO_CMD_MBMASTER_V(master == CSIO_MASTER_MUST ? 91 m_mbox : FW_HELLO_CMD_MBMASTER_M) | 92 FW_HELLO_CMD_MBASYNCNOT_V(a_mbox) | 93 FW_HELLO_CMD_STAGE_V(fw_hello_cmd_stage_os) | 94 FW_HELLO_CMD_CLEARINIT_F); 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_G(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_G(value); 122 123 if (value & FW_HELLO_CMD_INIT_F) 124 *state = CSIO_DEV_STATE_INIT; 125 else if (value & FW_HELLO_CMD_ERR_F) 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_V(FW_BYE_CMD) | 148 FW_CMD_REQUEST_F | FW_CMD_WRITE_F); 149 cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(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_V(FW_RESET_CMD) | 171 FW_CMD_REQUEST_F | FW_CMD_WRITE_F); 172 cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(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_V(FW_PARAMS_CMD) | 206 FW_CMD_REQUEST_F | 207 (wr ? FW_CMD_WRITE_F : FW_CMD_READ_F) | 208 FW_PARAMS_CMD_PFN_V(pf) | 209 FW_PARAMS_CMD_VFN_V(vf)); 210 cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(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_G(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_V(FW_LDST_CMD) | 275 FW_CMD_REQUEST_F | 276 FW_CMD_READ_F | 277 FW_LDST_CMD_ADDRSPACE_V(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_V(1); 280 ldst_cmd->u.pcie.ctrl_to_fn = 281 (FW_LDST_CMD_LC_F | FW_LDST_CMD_FN_V(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_V(FW_CAPS_CONFIG_CMD) | 310 FW_CMD_REQUEST_F | 311 (wr ? FW_CMD_WRITE_F : FW_CMD_READ_F)); 312 cmdp->cfvalid_to_len16 = htonl(FW_CMD_LEN16_V(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 #define CSIO_ADVERT_MASK (FW_PORT_CAP_SPEED_100M | FW_PORT_CAP_SPEED_1G |\ 330 FW_PORT_CAP_SPEED_10G | FW_PORT_CAP_SPEED_40G |\ 331 FW_PORT_CAP_ANEG) 332 333 /* 334 * csio_mb_port- FW PORT command helper 335 * @hw: The HW structure 336 * @mbp: Mailbox structure 337 * @tmo: COmmand timeout 338 * @portid: Port ID to get/set info 339 * @wr: Write/Read PORT information. 340 * @fc: Flow control 341 * @caps: Port capabilites to set. 342 * @cbfn: Callback, if any. 343 * 344 */ 345 void 346 csio_mb_port(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 347 uint8_t portid, bool wr, uint32_t fc, uint16_t caps, 348 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 349 { 350 struct fw_port_cmd *cmdp = (struct fw_port_cmd *)(mbp->mb); 351 unsigned int lfc = 0, mdi = FW_PORT_CAP_MDI_V(FW_PORT_CAP_MDI_AUTO); 352 353 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 354 355 cmdp->op_to_portid = htonl(FW_CMD_OP_V(FW_PORT_CMD) | 356 FW_CMD_REQUEST_F | 357 (wr ? FW_CMD_EXEC_F : FW_CMD_READ_F) | 358 FW_PORT_CMD_PORTID_V(portid)); 359 if (!wr) { 360 cmdp->action_to_len16 = htonl( 361 FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_GET_PORT_INFO) | 362 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 363 return; 364 } 365 366 /* Set port */ 367 cmdp->action_to_len16 = htonl( 368 FW_PORT_CMD_ACTION_V(FW_PORT_ACTION_L1_CFG) | 369 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 370 371 if (fc & PAUSE_RX) 372 lfc |= FW_PORT_CAP_FC_RX; 373 if (fc & PAUSE_TX) 374 lfc |= FW_PORT_CAP_FC_TX; 375 376 if (!(caps & FW_PORT_CAP_ANEG)) 377 cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | lfc); 378 else 379 cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | 380 lfc | mdi); 381 } 382 383 /* 384 * csio_mb_process_read_port_rsp - FW PORT command response processing helper 385 * @hw: The HW structure 386 * @mbp: Mailbox structure 387 * @retval: Mailbox return value from Firmware 388 * @caps: port capabilities 389 * 390 */ 391 void 392 csio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp, 393 enum fw_retval *retval, uint16_t *caps) 394 { 395 struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb); 396 397 *retval = FW_CMD_RETVAL_G(ntohl(rsp->action_to_len16)); 398 399 if (*retval == FW_SUCCESS) 400 *caps = ntohs(rsp->u.info.pcap); 401 } 402 403 /* 404 * csio_mb_initialize - FW INITIALIZE command helper 405 * @hw: The HW structure 406 * @mbp: Mailbox structure 407 * @tmo: COmmand timeout 408 * @cbfn: Callback, if any. 409 * 410 */ 411 void 412 csio_mb_initialize(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, 413 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 414 { 415 struct fw_initialize_cmd *cmdp = (struct fw_initialize_cmd *)(mbp->mb); 416 417 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1); 418 419 cmdp->op_to_write = htonl(FW_CMD_OP_V(FW_INITIALIZE_CMD) | 420 FW_CMD_REQUEST_F | FW_CMD_WRITE_F); 421 cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 422 423 } 424 425 /* 426 * csio_mb_iq_alloc - Initializes the mailbox to allocate an 427 * Ingress DMA queue in the firmware. 428 * 429 * @hw: The hw structure 430 * @mbp: Mailbox structure to initialize 431 * @priv: Private object 432 * @mb_tmo: Mailbox time-out period (in ms). 433 * @iq_params: Ingress queue params needed for allocation. 434 * @cbfn: The call-back function 435 * 436 * 437 */ 438 static void 439 csio_mb_iq_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 440 uint32_t mb_tmo, struct csio_iq_params *iq_params, 441 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 442 { 443 struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb); 444 445 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 446 447 cmdp->op_to_vfn = htonl(FW_CMD_OP_V(FW_IQ_CMD) | 448 FW_CMD_REQUEST_F | FW_CMD_EXEC_F | 449 FW_IQ_CMD_PFN_V(iq_params->pfn) | 450 FW_IQ_CMD_VFN_V(iq_params->vfn)); 451 452 cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC_F | 453 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 454 455 cmdp->type_to_iqandstindex = htonl( 456 FW_IQ_CMD_VIID_V(iq_params->viid) | 457 FW_IQ_CMD_TYPE_V(iq_params->type) | 458 FW_IQ_CMD_IQASYNCH_V(iq_params->iqasynch)); 459 460 cmdp->fl0size = htons(iq_params->fl0size); 461 cmdp->fl0size = htons(iq_params->fl1size); 462 463 } /* csio_mb_iq_alloc */ 464 465 /* 466 * csio_mb_iq_write - Initializes the mailbox for writing into an 467 * Ingress DMA Queue. 468 * 469 * @hw: The HW structure 470 * @mbp: Mailbox structure to initialize 471 * @priv: Private object 472 * @mb_tmo: Mailbox time-out period (in ms). 473 * @cascaded_req: TRUE - if this request is cascased with iq-alloc request. 474 * @iq_params: Ingress queue params needed for writing. 475 * @cbfn: The call-back function 476 * 477 * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating, 478 * because this IQ write request can be cascaded with a previous 479 * IQ alloc request, and we dont want to over-write the bits set by 480 * that request. This logic will work even in a non-cascaded case, since the 481 * cmdp structure is zeroed out by CSIO_INIT_MBP. 482 */ 483 static void 484 csio_mb_iq_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 485 uint32_t mb_tmo, bool cascaded_req, 486 struct csio_iq_params *iq_params, 487 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 488 { 489 struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb); 490 491 uint32_t iq_start_stop = (iq_params->iq_start) ? 492 FW_IQ_CMD_IQSTART_F : 493 FW_IQ_CMD_IQSTOP_F; 494 int relaxed = !(hw->flags & CSIO_HWF_ROOT_NO_RELAXED_ORDERING); 495 496 /* 497 * If this IQ write is cascaded with IQ alloc request, do not 498 * re-initialize with 0's. 499 * 500 */ 501 if (!cascaded_req) 502 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 503 504 cmdp->op_to_vfn |= htonl(FW_CMD_OP_V(FW_IQ_CMD) | 505 FW_CMD_REQUEST_F | FW_CMD_WRITE_F | 506 FW_IQ_CMD_PFN_V(iq_params->pfn) | 507 FW_IQ_CMD_VFN_V(iq_params->vfn)); 508 cmdp->alloc_to_len16 |= htonl(iq_start_stop | 509 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 510 cmdp->iqid |= htons(iq_params->iqid); 511 cmdp->fl0id |= htons(iq_params->fl0id); 512 cmdp->fl1id |= htons(iq_params->fl1id); 513 cmdp->type_to_iqandstindex |= htonl( 514 FW_IQ_CMD_IQANDST_V(iq_params->iqandst) | 515 FW_IQ_CMD_IQANUS_V(iq_params->iqanus) | 516 FW_IQ_CMD_IQANUD_V(iq_params->iqanud) | 517 FW_IQ_CMD_IQANDSTINDEX_V(iq_params->iqandstindex)); 518 cmdp->iqdroprss_to_iqesize |= htons( 519 FW_IQ_CMD_IQPCIECH_V(iq_params->iqpciech) | 520 FW_IQ_CMD_IQDCAEN_V(iq_params->iqdcaen) | 521 FW_IQ_CMD_IQDCACPU_V(iq_params->iqdcacpu) | 522 FW_IQ_CMD_IQINTCNTTHRESH_V(iq_params->iqintcntthresh) | 523 FW_IQ_CMD_IQCPRIO_V(iq_params->iqcprio) | 524 FW_IQ_CMD_IQESIZE_V(iq_params->iqesize)); 525 526 cmdp->iqsize |= htons(iq_params->iqsize); 527 cmdp->iqaddr |= cpu_to_be64(iq_params->iqaddr); 528 529 if (iq_params->type == 0) { 530 cmdp->iqns_to_fl0congen |= htonl( 531 FW_IQ_CMD_IQFLINTIQHSEN_V(iq_params->iqflintiqhsen)| 532 FW_IQ_CMD_IQFLINTCONGEN_V(iq_params->iqflintcongen)); 533 } 534 535 if (iq_params->fl0size && iq_params->fl0addr && 536 (iq_params->fl0id != 0xFFFF)) { 537 538 cmdp->iqns_to_fl0congen |= htonl( 539 FW_IQ_CMD_FL0HOSTFCMODE_V(iq_params->fl0hostfcmode)| 540 FW_IQ_CMD_FL0CPRIO_V(iq_params->fl0cprio) | 541 FW_IQ_CMD_FL0FETCHRO_V(relaxed) | 542 FW_IQ_CMD_FL0DATARO_V(relaxed) | 543 FW_IQ_CMD_FL0PADEN_V(iq_params->fl0paden) | 544 FW_IQ_CMD_FL0PACKEN_V(iq_params->fl0packen)); 545 cmdp->fl0dcaen_to_fl0cidxfthresh |= htons( 546 FW_IQ_CMD_FL0DCAEN_V(iq_params->fl0dcaen) | 547 FW_IQ_CMD_FL0DCACPU_V(iq_params->fl0dcacpu) | 548 FW_IQ_CMD_FL0FBMIN_V(iq_params->fl0fbmin) | 549 FW_IQ_CMD_FL0FBMAX_V(iq_params->fl0fbmax) | 550 FW_IQ_CMD_FL0CIDXFTHRESH_V(iq_params->fl0cidxfthresh)); 551 cmdp->fl0size |= htons(iq_params->fl0size); 552 cmdp->fl0addr |= cpu_to_be64(iq_params->fl0addr); 553 } 554 } /* csio_mb_iq_write */ 555 556 /* 557 * csio_mb_iq_alloc_write - Initializes the mailbox for allocating an 558 * Ingress DMA Queue. 559 * 560 * @hw: The HW structure 561 * @mbp: Mailbox structure to initialize 562 * @priv: Private data. 563 * @mb_tmo: Mailbox time-out period (in ms). 564 * @iq_params: Ingress queue params needed for allocation & writing. 565 * @cbfn: The call-back function 566 * 567 * 568 */ 569 void 570 csio_mb_iq_alloc_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 571 uint32_t mb_tmo, struct csio_iq_params *iq_params, 572 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 573 { 574 csio_mb_iq_alloc(hw, mbp, priv, mb_tmo, iq_params, cbfn); 575 csio_mb_iq_write(hw, mbp, priv, mb_tmo, true, iq_params, cbfn); 576 } /* csio_mb_iq_alloc_write */ 577 578 /* 579 * csio_mb_iq_alloc_write_rsp - Process the allocation & writing 580 * of ingress DMA queue mailbox's response. 581 * 582 * @hw: The HW structure. 583 * @mbp: Mailbox structure to initialize. 584 * @retval: Firmware return value. 585 * @iq_params: Ingress queue parameters, after allocation and write. 586 * 587 */ 588 void 589 csio_mb_iq_alloc_write_rsp(struct csio_hw *hw, struct csio_mb *mbp, 590 enum fw_retval *ret_val, 591 struct csio_iq_params *iq_params) 592 { 593 struct fw_iq_cmd *rsp = (struct fw_iq_cmd *)(mbp->mb); 594 595 *ret_val = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)); 596 if (*ret_val == FW_SUCCESS) { 597 iq_params->physiqid = ntohs(rsp->physiqid); 598 iq_params->iqid = ntohs(rsp->iqid); 599 iq_params->fl0id = ntohs(rsp->fl0id); 600 iq_params->fl1id = ntohs(rsp->fl1id); 601 } else { 602 iq_params->physiqid = iq_params->iqid = 603 iq_params->fl0id = iq_params->fl1id = 0; 604 } 605 } /* csio_mb_iq_alloc_write_rsp */ 606 607 /* 608 * csio_mb_iq_free - Initializes the mailbox for freeing a 609 * specified Ingress DMA Queue. 610 * 611 * @hw: The HW structure 612 * @mbp: Mailbox structure to initialize 613 * @priv: Private data 614 * @mb_tmo: Mailbox time-out period (in ms). 615 * @iq_params: Parameters of ingress queue, that is to be freed. 616 * @cbfn: The call-back function 617 * 618 * 619 */ 620 void 621 csio_mb_iq_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 622 uint32_t mb_tmo, struct csio_iq_params *iq_params, 623 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 624 { 625 struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb); 626 627 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 628 629 cmdp->op_to_vfn = htonl(FW_CMD_OP_V(FW_IQ_CMD) | 630 FW_CMD_REQUEST_F | FW_CMD_EXEC_F | 631 FW_IQ_CMD_PFN_V(iq_params->pfn) | 632 FW_IQ_CMD_VFN_V(iq_params->vfn)); 633 cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_FREE_F | 634 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 635 cmdp->type_to_iqandstindex = htonl(FW_IQ_CMD_TYPE_V(iq_params->type)); 636 637 cmdp->iqid = htons(iq_params->iqid); 638 cmdp->fl0id = htons(iq_params->fl0id); 639 cmdp->fl1id = htons(iq_params->fl1id); 640 641 } /* csio_mb_iq_free */ 642 643 /* 644 * csio_mb_eq_ofld_alloc - Initializes the mailbox for allocating 645 * an offload-egress queue. 646 * 647 * @hw: The HW structure 648 * @mbp: Mailbox structure to initialize 649 * @priv: Private data 650 * @mb_tmo: Mailbox time-out period (in ms). 651 * @eq_ofld_params: (Offload) Egress queue parameters. 652 * @cbfn: The call-back function 653 * 654 * 655 */ 656 static void 657 csio_mb_eq_ofld_alloc(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 658 uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params, 659 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 660 { 661 struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb); 662 663 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 664 cmdp->op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | 665 FW_CMD_REQUEST_F | FW_CMD_EXEC_F | 666 FW_EQ_OFLD_CMD_PFN_V(eq_ofld_params->pfn) | 667 FW_EQ_OFLD_CMD_VFN_V(eq_ofld_params->vfn)); 668 cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_ALLOC_F | 669 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 670 671 } /* csio_mb_eq_ofld_alloc */ 672 673 /* 674 * csio_mb_eq_ofld_write - Initializes the mailbox for writing 675 * an alloacted offload-egress queue. 676 * 677 * @hw: The HW structure 678 * @mbp: Mailbox structure to initialize 679 * @priv: Private data 680 * @mb_tmo: Mailbox time-out period (in ms). 681 * @cascaded_req: TRUE - if this request is cascased with Eq-alloc request. 682 * @eq_ofld_params: (Offload) Egress queue parameters. 683 * @cbfn: The call-back function 684 * 685 * 686 * NOTE: We OR relevant bits with cmdp->XXX, instead of just equating, 687 * because this EQ write request can be cascaded with a previous 688 * EQ alloc request, and we dont want to over-write the bits set by 689 * that request. This logic will work even in a non-cascaded case, since the 690 * cmdp structure is zeroed out by CSIO_INIT_MBP. 691 */ 692 static void 693 csio_mb_eq_ofld_write(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 694 uint32_t mb_tmo, bool cascaded_req, 695 struct csio_eq_params *eq_ofld_params, 696 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 697 { 698 struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb); 699 700 uint32_t eq_start_stop = (eq_ofld_params->eqstart) ? 701 FW_EQ_OFLD_CMD_EQSTART_F : 702 FW_EQ_OFLD_CMD_EQSTOP_F; 703 704 /* 705 * If this EQ write is cascaded with EQ alloc request, do not 706 * re-initialize with 0's. 707 * 708 */ 709 if (!cascaded_req) 710 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 711 712 cmdp->op_to_vfn |= htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | 713 FW_CMD_REQUEST_F | FW_CMD_WRITE_F | 714 FW_EQ_OFLD_CMD_PFN_V(eq_ofld_params->pfn) | 715 FW_EQ_OFLD_CMD_VFN_V(eq_ofld_params->vfn)); 716 cmdp->alloc_to_len16 |= htonl(eq_start_stop | 717 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 718 719 cmdp->eqid_pkd |= htonl(FW_EQ_OFLD_CMD_EQID_V(eq_ofld_params->eqid)); 720 721 cmdp->fetchszm_to_iqid |= htonl( 722 FW_EQ_OFLD_CMD_HOSTFCMODE_V(eq_ofld_params->hostfcmode) | 723 FW_EQ_OFLD_CMD_CPRIO_V(eq_ofld_params->cprio) | 724 FW_EQ_OFLD_CMD_PCIECHN_V(eq_ofld_params->pciechn) | 725 FW_EQ_OFLD_CMD_IQID_V(eq_ofld_params->iqid)); 726 727 cmdp->dcaen_to_eqsize |= htonl( 728 FW_EQ_OFLD_CMD_DCAEN_V(eq_ofld_params->dcaen) | 729 FW_EQ_OFLD_CMD_DCACPU_V(eq_ofld_params->dcacpu) | 730 FW_EQ_OFLD_CMD_FBMIN_V(eq_ofld_params->fbmin) | 731 FW_EQ_OFLD_CMD_FBMAX_V(eq_ofld_params->fbmax) | 732 FW_EQ_OFLD_CMD_CIDXFTHRESHO_V(eq_ofld_params->cidxfthresho) | 733 FW_EQ_OFLD_CMD_CIDXFTHRESH_V(eq_ofld_params->cidxfthresh) | 734 FW_EQ_OFLD_CMD_EQSIZE_V(eq_ofld_params->eqsize)); 735 736 cmdp->eqaddr |= cpu_to_be64(eq_ofld_params->eqaddr); 737 738 } /* csio_mb_eq_ofld_write */ 739 740 /* 741 * csio_mb_eq_ofld_alloc_write - Initializes the mailbox for allocation 742 * writing into an Engress DMA Queue. 743 * 744 * @hw: The HW structure 745 * @mbp: Mailbox structure to initialize 746 * @priv: Private data. 747 * @mb_tmo: Mailbox time-out period (in ms). 748 * @eq_ofld_params: (Offload) Egress queue parameters. 749 * @cbfn: The call-back function 750 * 751 * 752 */ 753 void 754 csio_mb_eq_ofld_alloc_write(struct csio_hw *hw, struct csio_mb *mbp, 755 void *priv, uint32_t mb_tmo, 756 struct csio_eq_params *eq_ofld_params, 757 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 758 { 759 csio_mb_eq_ofld_alloc(hw, mbp, priv, mb_tmo, eq_ofld_params, cbfn); 760 csio_mb_eq_ofld_write(hw, mbp, priv, mb_tmo, true, 761 eq_ofld_params, cbfn); 762 } /* csio_mb_eq_ofld_alloc_write */ 763 764 /* 765 * csio_mb_eq_ofld_alloc_write_rsp - Process the allocation 766 * & write egress DMA queue mailbox's response. 767 * 768 * @hw: The HW structure. 769 * @mbp: Mailbox structure to initialize. 770 * @retval: Firmware return value. 771 * @eq_ofld_params: (Offload) Egress queue parameters. 772 * 773 */ 774 void 775 csio_mb_eq_ofld_alloc_write_rsp(struct csio_hw *hw, 776 struct csio_mb *mbp, enum fw_retval *ret_val, 777 struct csio_eq_params *eq_ofld_params) 778 { 779 struct fw_eq_ofld_cmd *rsp = (struct fw_eq_ofld_cmd *)(mbp->mb); 780 781 *ret_val = FW_CMD_RETVAL_G(ntohl(rsp->alloc_to_len16)); 782 783 if (*ret_val == FW_SUCCESS) { 784 eq_ofld_params->eqid = FW_EQ_OFLD_CMD_EQID_G( 785 ntohl(rsp->eqid_pkd)); 786 eq_ofld_params->physeqid = FW_EQ_OFLD_CMD_PHYSEQID_G( 787 ntohl(rsp->physeqid_pkd)); 788 } else 789 eq_ofld_params->eqid = 0; 790 791 } /* csio_mb_eq_ofld_alloc_write_rsp */ 792 793 /* 794 * csio_mb_eq_ofld_free - Initializes the mailbox for freeing a 795 * specified Engress DMA Queue. 796 * 797 * @hw: The HW structure 798 * @mbp: Mailbox structure to initialize 799 * @priv: Private data area. 800 * @mb_tmo: Mailbox time-out period (in ms). 801 * @eq_ofld_params: (Offload) Egress queue parameters, that is to be freed. 802 * @cbfn: The call-back function 803 * 804 * 805 */ 806 void 807 csio_mb_eq_ofld_free(struct csio_hw *hw, struct csio_mb *mbp, void *priv, 808 uint32_t mb_tmo, struct csio_eq_params *eq_ofld_params, 809 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 810 { 811 struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb); 812 813 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1); 814 815 cmdp->op_to_vfn = htonl(FW_CMD_OP_V(FW_EQ_OFLD_CMD) | 816 FW_CMD_REQUEST_F | FW_CMD_EXEC_F | 817 FW_EQ_OFLD_CMD_PFN_V(eq_ofld_params->pfn) | 818 FW_EQ_OFLD_CMD_VFN_V(eq_ofld_params->vfn)); 819 cmdp->alloc_to_len16 = htonl(FW_EQ_OFLD_CMD_FREE_F | 820 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 821 cmdp->eqid_pkd = htonl(FW_EQ_OFLD_CMD_EQID_V(eq_ofld_params->eqid)); 822 823 } /* csio_mb_eq_ofld_free */ 824 825 /* 826 * csio_write_fcoe_link_cond_init_mb - Initialize Mailbox to write FCoE link 827 * condition. 828 * 829 * @ln: The Lnode structure 830 * @mbp: Mailbox structure to initialize 831 * @mb_tmo: Mailbox time-out period (in ms). 832 * @cbfn: The call back function. 833 * 834 * 835 */ 836 void 837 csio_write_fcoe_link_cond_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 838 uint32_t mb_tmo, uint8_t port_id, uint32_t sub_opcode, 839 uint8_t cos, bool link_status, uint32_t fcfi, 840 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 841 { 842 struct fw_fcoe_link_cmd *cmdp = 843 (struct fw_fcoe_link_cmd *)(mbp->mb); 844 845 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 846 847 cmdp->op_to_portid = htonl(( 848 FW_CMD_OP_V(FW_FCOE_LINK_CMD) | 849 FW_CMD_REQUEST_F | 850 FW_CMD_WRITE_F | 851 FW_FCOE_LINK_CMD_PORTID(port_id))); 852 cmdp->sub_opcode_fcfi = htonl( 853 FW_FCOE_LINK_CMD_SUB_OPCODE(sub_opcode) | 854 FW_FCOE_LINK_CMD_FCFI(fcfi)); 855 cmdp->lstatus = link_status; 856 cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 857 858 } /* csio_write_fcoe_link_cond_init_mb */ 859 860 /* 861 * csio_fcoe_read_res_info_init_mb - Initializes the mailbox for reading FCoE 862 * resource information(FW_GET_RES_INFO_CMD). 863 * 864 * @hw: The HW structure 865 * @mbp: Mailbox structure to initialize 866 * @mb_tmo: Mailbox time-out period (in ms). 867 * @cbfn: The call-back function 868 * 869 * 870 */ 871 void 872 csio_fcoe_read_res_info_init_mb(struct csio_hw *hw, struct csio_mb *mbp, 873 uint32_t mb_tmo, 874 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 875 { 876 struct fw_fcoe_res_info_cmd *cmdp = 877 (struct fw_fcoe_res_info_cmd *)(mbp->mb); 878 879 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1); 880 881 cmdp->op_to_read = htonl((FW_CMD_OP_V(FW_FCOE_RES_INFO_CMD) | 882 FW_CMD_REQUEST_F | 883 FW_CMD_READ_F)); 884 885 cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 886 887 } /* csio_fcoe_read_res_info_init_mb */ 888 889 /* 890 * csio_fcoe_vnp_alloc_init_mb - Initializes the mailbox for allocating VNP 891 * in the firmware (FW_FCOE_VNP_CMD). 892 * 893 * @ln: The Lnode structure. 894 * @mbp: Mailbox structure to initialize. 895 * @mb_tmo: Mailbox time-out period (in ms). 896 * @fcfi: FCF Index. 897 * @vnpi: vnpi 898 * @iqid: iqid 899 * @vnport_wwnn: vnport WWNN 900 * @vnport_wwpn: vnport WWPN 901 * @cbfn: The call-back function. 902 * 903 * 904 */ 905 void 906 csio_fcoe_vnp_alloc_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 907 uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi, uint16_t iqid, 908 uint8_t vnport_wwnn[8], uint8_t vnport_wwpn[8], 909 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 910 { 911 struct fw_fcoe_vnp_cmd *cmdp = 912 (struct fw_fcoe_vnp_cmd *)(mbp->mb); 913 914 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 915 916 cmdp->op_to_fcfi = htonl((FW_CMD_OP_V(FW_FCOE_VNP_CMD) | 917 FW_CMD_REQUEST_F | 918 FW_CMD_EXEC_F | 919 FW_FCOE_VNP_CMD_FCFI(fcfi))); 920 921 cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_ALLOC | 922 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 923 924 cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi)); 925 926 cmdp->iqid = htons(iqid); 927 928 if (!wwn_to_u64(vnport_wwnn) && !wwn_to_u64(vnport_wwpn)) 929 cmdp->gen_wwn_to_vnpi |= htonl(FW_FCOE_VNP_CMD_GEN_WWN); 930 931 if (vnport_wwnn) 932 memcpy(cmdp->vnport_wwnn, vnport_wwnn, 8); 933 if (vnport_wwpn) 934 memcpy(cmdp->vnport_wwpn, vnport_wwpn, 8); 935 936 } /* csio_fcoe_vnp_alloc_init_mb */ 937 938 /* 939 * csio_fcoe_vnp_read_init_mb - Prepares VNP read cmd. 940 * @ln: The Lnode structure. 941 * @mbp: Mailbox structure to initialize. 942 * @mb_tmo: Mailbox time-out period (in ms). 943 * @fcfi: FCF Index. 944 * @vnpi: vnpi 945 * @cbfn: The call-back handler. 946 */ 947 void 948 csio_fcoe_vnp_read_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 949 uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi, 950 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 951 { 952 struct fw_fcoe_vnp_cmd *cmdp = 953 (struct fw_fcoe_vnp_cmd *)(mbp->mb); 954 955 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 956 cmdp->op_to_fcfi = htonl(FW_CMD_OP_V(FW_FCOE_VNP_CMD) | 957 FW_CMD_REQUEST_F | 958 FW_CMD_READ_F | 959 FW_FCOE_VNP_CMD_FCFI(fcfi)); 960 cmdp->alloc_to_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 961 cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi)); 962 } 963 964 /* 965 * csio_fcoe_vnp_free_init_mb - Initializes the mailbox for freeing an 966 * alloacted VNP in the firmware (FW_FCOE_VNP_CMD). 967 * 968 * @ln: The Lnode structure. 969 * @mbp: Mailbox structure to initialize. 970 * @mb_tmo: Mailbox time-out period (in ms). 971 * @fcfi: FCF flow id 972 * @vnpi: VNP flow id 973 * @cbfn: The call-back function. 974 * Return: None 975 */ 976 void 977 csio_fcoe_vnp_free_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 978 uint32_t mb_tmo, uint32_t fcfi, uint32_t vnpi, 979 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 980 { 981 struct fw_fcoe_vnp_cmd *cmdp = 982 (struct fw_fcoe_vnp_cmd *)(mbp->mb); 983 984 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 985 986 cmdp->op_to_fcfi = htonl(FW_CMD_OP_V(FW_FCOE_VNP_CMD) | 987 FW_CMD_REQUEST_F | 988 FW_CMD_EXEC_F | 989 FW_FCOE_VNP_CMD_FCFI(fcfi)); 990 cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_FREE | 991 FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 992 cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi)); 993 } 994 995 /* 996 * csio_fcoe_read_fcf_init_mb - Initializes the mailbox to read the 997 * FCF records. 998 * 999 * @ln: The Lnode structure 1000 * @mbp: Mailbox structure to initialize 1001 * @mb_tmo: Mailbox time-out period (in ms). 1002 * @fcf_params: FC-Forwarder parameters. 1003 * @cbfn: The call-back function 1004 * 1005 * 1006 */ 1007 void 1008 csio_fcoe_read_fcf_init_mb(struct csio_lnode *ln, struct csio_mb *mbp, 1009 uint32_t mb_tmo, uint32_t portid, uint32_t fcfi, 1010 void (*cbfn) (struct csio_hw *, struct csio_mb *)) 1011 { 1012 struct fw_fcoe_fcf_cmd *cmdp = 1013 (struct fw_fcoe_fcf_cmd *)(mbp->mb); 1014 1015 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1); 1016 1017 cmdp->op_to_fcfi = htonl(FW_CMD_OP_V(FW_FCOE_FCF_CMD) | 1018 FW_CMD_REQUEST_F | 1019 FW_CMD_READ_F | 1020 FW_FCOE_FCF_CMD_FCFI(fcfi)); 1021 cmdp->retval_len16 = htonl(FW_CMD_LEN16_V(sizeof(*cmdp) / 16)); 1022 1023 } /* csio_fcoe_read_fcf_init_mb */ 1024 1025 void 1026 csio_fcoe_read_portparams_init_mb(struct csio_hw *hw, struct csio_mb *mbp, 1027 uint32_t mb_tmo, 1028 struct fw_fcoe_port_cmd_params *portparams, 1029 void (*cbfn)(struct csio_hw *, 1030 struct csio_mb *)) 1031 { 1032 struct fw_fcoe_stats_cmd *cmdp = (struct fw_fcoe_stats_cmd *)(mbp->mb); 1033 1034 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1); 1035 mbp->mb_size = 64; 1036 1037 cmdp->op_to_flowid = htonl(FW_CMD_OP_V(FW_FCOE_STATS_CMD) | 1038 FW_CMD_REQUEST_F | FW_CMD_READ_F); 1039 cmdp->free_to_len16 = htonl(FW_CMD_LEN16_V(CSIO_MAX_MB_SIZE/16)); 1040 1041 cmdp->u.ctl.nstats_port = FW_FCOE_STATS_CMD_NSTATS(portparams->nstats) | 1042 FW_FCOE_STATS_CMD_PORT(portparams->portid); 1043 1044 cmdp->u.ctl.port_valid_ix = FW_FCOE_STATS_CMD_IX(portparams->idx) | 1045 FW_FCOE_STATS_CMD_PORT_VALID; 1046 1047 } /* csio_fcoe_read_portparams_init_mb */ 1048 1049 void 1050 csio_mb_process_portparams_rsp(struct csio_hw *hw, 1051 struct csio_mb *mbp, 1052 enum fw_retval *retval, 1053 struct fw_fcoe_port_cmd_params *portparams, 1054 struct fw_fcoe_port_stats *portstats) 1055 { 1056 struct fw_fcoe_stats_cmd *rsp = (struct fw_fcoe_stats_cmd *)(mbp->mb); 1057 struct fw_fcoe_port_stats stats; 1058 uint8_t *src; 1059 uint8_t *dst; 1060 1061 *retval = FW_CMD_RETVAL_G(ntohl(rsp->free_to_len16)); 1062 1063 memset(&stats, 0, sizeof(struct fw_fcoe_port_stats)); 1064 1065 if (*retval == FW_SUCCESS) { 1066 dst = (uint8_t *)(&stats) + ((portparams->idx - 1) * 8); 1067 src = (uint8_t *)rsp + (CSIO_STATS_OFFSET * 8); 1068 memcpy(dst, src, (portparams->nstats * 8)); 1069 if (portparams->idx == 1) { 1070 /* Get the first 6 flits from the Mailbox */ 1071 portstats->tx_bcast_bytes = stats.tx_bcast_bytes; 1072 portstats->tx_bcast_frames = stats.tx_bcast_frames; 1073 portstats->tx_mcast_bytes = stats.tx_mcast_bytes; 1074 portstats->tx_mcast_frames = stats.tx_mcast_frames; 1075 portstats->tx_ucast_bytes = stats.tx_ucast_bytes; 1076 portstats->tx_ucast_frames = stats.tx_ucast_frames; 1077 } 1078 if (portparams->idx == 7) { 1079 /* Get the second 6 flits from the Mailbox */ 1080 portstats->tx_drop_frames = stats.tx_drop_frames; 1081 portstats->tx_offload_bytes = stats.tx_offload_bytes; 1082 portstats->tx_offload_frames = stats.tx_offload_frames; 1083 #if 0 1084 portstats->rx_pf_bytes = stats.rx_pf_bytes; 1085 portstats->rx_pf_frames = stats.rx_pf_frames; 1086 #endif 1087 portstats->rx_bcast_bytes = stats.rx_bcast_bytes; 1088 portstats->rx_bcast_frames = stats.rx_bcast_frames; 1089 portstats->rx_mcast_bytes = stats.rx_mcast_bytes; 1090 } 1091 if (portparams->idx == 13) { 1092 /* Get the last 4 flits from the Mailbox */ 1093 portstats->rx_mcast_frames = stats.rx_mcast_frames; 1094 portstats->rx_ucast_bytes = stats.rx_ucast_bytes; 1095 portstats->rx_ucast_frames = stats.rx_ucast_frames; 1096 portstats->rx_err_frames = stats.rx_err_frames; 1097 } 1098 } 1099 } 1100 1101 /* Entry points/APIs for MB module */ 1102 /* 1103 * csio_mb_intr_enable - Enable Interrupts from mailboxes. 1104 * @hw: The HW structure 1105 * 1106 * Enables CIM interrupt bit in appropriate INT_ENABLE registers. 1107 */ 1108 void 1109 csio_mb_intr_enable(struct csio_hw *hw) 1110 { 1111 csio_wr_reg32(hw, MBMSGRDYINTEN_F, MYPF_REG(CIM_PF_HOST_INT_ENABLE_A)); 1112 csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE_A)); 1113 } 1114 1115 /* 1116 * csio_mb_intr_disable - Disable Interrupts from mailboxes. 1117 * @hw: The HW structure 1118 * 1119 * Disable bit in HostInterruptEnable CIM register. 1120 */ 1121 void 1122 csio_mb_intr_disable(struct csio_hw *hw) 1123 { 1124 csio_wr_reg32(hw, MBMSGRDYINTEN_V(0), 1125 MYPF_REG(CIM_PF_HOST_INT_ENABLE_A)); 1126 csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_ENABLE_A)); 1127 } 1128 1129 static void 1130 csio_mb_dump_fw_dbg(struct csio_hw *hw, __be64 *cmd) 1131 { 1132 struct fw_debug_cmd *dbg = (struct fw_debug_cmd *)cmd; 1133 1134 if ((FW_DEBUG_CMD_TYPE_G(ntohl(dbg->op_type))) == 1) { 1135 csio_info(hw, "FW print message:\n"); 1136 csio_info(hw, "\tdebug->dprtstridx = %d\n", 1137 ntohs(dbg->u.prt.dprtstridx)); 1138 csio_info(hw, "\tdebug->dprtstrparam0 = 0x%x\n", 1139 ntohl(dbg->u.prt.dprtstrparam0)); 1140 csio_info(hw, "\tdebug->dprtstrparam1 = 0x%x\n", 1141 ntohl(dbg->u.prt.dprtstrparam1)); 1142 csio_info(hw, "\tdebug->dprtstrparam2 = 0x%x\n", 1143 ntohl(dbg->u.prt.dprtstrparam2)); 1144 csio_info(hw, "\tdebug->dprtstrparam3 = 0x%x\n", 1145 ntohl(dbg->u.prt.dprtstrparam3)); 1146 } else { 1147 /* This is a FW assertion */ 1148 csio_fatal(hw, "FW assertion at %.16s:%u, val0 %#x, val1 %#x\n", 1149 dbg->u.assert.filename_0_7, 1150 ntohl(dbg->u.assert.line), 1151 ntohl(dbg->u.assert.x), 1152 ntohl(dbg->u.assert.y)); 1153 } 1154 } 1155 1156 static void 1157 csio_mb_debug_cmd_handler(struct csio_hw *hw) 1158 { 1159 int i; 1160 __be64 cmd[CSIO_MB_MAX_REGS]; 1161 uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL_A); 1162 uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA_A); 1163 int size = sizeof(struct fw_debug_cmd); 1164 1165 /* Copy mailbox data */ 1166 for (i = 0; i < size; i += 8) 1167 cmd[i / 8] = cpu_to_be64(csio_rd_reg64(hw, data_reg + i)); 1168 1169 csio_mb_dump_fw_dbg(hw, cmd); 1170 1171 /* Notify FW of mailbox by setting owner as UP */ 1172 csio_wr_reg32(hw, MBMSGVALID_F | MBINTREQ_F | 1173 MBOWNER_V(CSIO_MBOWNER_FW), ctl_reg); 1174 1175 csio_rd_reg32(hw, ctl_reg); 1176 wmb(); 1177 } 1178 1179 /* 1180 * csio_mb_issue - generic routine for issuing Mailbox commands. 1181 * @hw: The HW structure 1182 * @mbp: Mailbox command to issue 1183 * 1184 * Caller should hold hw lock across this call. 1185 */ 1186 int 1187 csio_mb_issue(struct csio_hw *hw, struct csio_mb *mbp) 1188 { 1189 uint32_t owner, ctl; 1190 int i; 1191 uint32_t ii; 1192 __be64 *cmd = mbp->mb; 1193 __be64 hdr; 1194 struct csio_mbm *mbm = &hw->mbm; 1195 uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL_A); 1196 uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA_A); 1197 int size = mbp->mb_size; 1198 int rv = -EINVAL; 1199 struct fw_cmd_hdr *fw_hdr; 1200 1201 /* Determine mode */ 1202 if (mbp->mb_cbfn == NULL) { 1203 /* Need to issue/get results in the same context */ 1204 if (mbp->tmo < CSIO_MB_POLL_FREQ) { 1205 csio_err(hw, "Invalid tmo: 0x%x\n", mbp->tmo); 1206 goto error_out; 1207 } 1208 } else if (!csio_is_host_intr_enabled(hw) || 1209 !csio_is_hw_intr_enabled(hw)) { 1210 csio_err(hw, "Cannot issue mailbox in interrupt mode 0x%x\n", 1211 *((uint8_t *)mbp->mb)); 1212 goto error_out; 1213 } 1214 1215 if (mbm->mcurrent != NULL) { 1216 /* Queue mbox cmd, if another mbox cmd is active */ 1217 if (mbp->mb_cbfn == NULL) { 1218 rv = -EBUSY; 1219 csio_dbg(hw, "Couldnt own Mailbox %x op:0x%x\n", 1220 hw->pfn, *((uint8_t *)mbp->mb)); 1221 1222 goto error_out; 1223 } else { 1224 list_add_tail(&mbp->list, &mbm->req_q); 1225 CSIO_INC_STATS(mbm, n_activeq); 1226 1227 return 0; 1228 } 1229 } 1230 1231 /* Now get ownership of mailbox */ 1232 owner = MBOWNER_G(csio_rd_reg32(hw, ctl_reg)); 1233 1234 if (!csio_mb_is_host_owner(owner)) { 1235 1236 for (i = 0; (owner == CSIO_MBOWNER_NONE) && (i < 3); i++) 1237 owner = MBOWNER_G(csio_rd_reg32(hw, ctl_reg)); 1238 /* 1239 * Mailbox unavailable. In immediate mode, fail the command. 1240 * In other modes, enqueue the request. 1241 */ 1242 if (!csio_mb_is_host_owner(owner)) { 1243 if (mbp->mb_cbfn == NULL) { 1244 rv = owner ? -EBUSY : -ETIMEDOUT; 1245 1246 csio_dbg(hw, 1247 "Couldnt own Mailbox %x op:0x%x " 1248 "owner:%x\n", 1249 hw->pfn, *((uint8_t *)mbp->mb), owner); 1250 goto error_out; 1251 } else { 1252 if (mbm->mcurrent == NULL) { 1253 csio_err(hw, 1254 "Couldnt own Mailbox %x " 1255 "op:0x%x owner:%x\n", 1256 hw->pfn, *((uint8_t *)mbp->mb), 1257 owner); 1258 csio_err(hw, 1259 "No outstanding driver" 1260 " mailbox as well\n"); 1261 goto error_out; 1262 } 1263 } 1264 } 1265 } 1266 1267 /* Mailbox is available, copy mailbox data into it */ 1268 for (i = 0; i < size; i += 8) { 1269 csio_wr_reg64(hw, be64_to_cpu(*cmd), data_reg + i); 1270 cmd++; 1271 } 1272 1273 CSIO_DUMP_MB(hw, hw->pfn, data_reg); 1274 1275 /* Start completion timers in non-immediate modes and notify FW */ 1276 if (mbp->mb_cbfn != NULL) { 1277 mbm->mcurrent = mbp; 1278 mod_timer(&mbm->timer, jiffies + msecs_to_jiffies(mbp->tmo)); 1279 csio_wr_reg32(hw, MBMSGVALID_F | MBINTREQ_F | 1280 MBOWNER_V(CSIO_MBOWNER_FW), ctl_reg); 1281 } else 1282 csio_wr_reg32(hw, MBMSGVALID_F | MBOWNER_V(CSIO_MBOWNER_FW), 1283 ctl_reg); 1284 1285 /* Flush posted writes */ 1286 csio_rd_reg32(hw, ctl_reg); 1287 wmb(); 1288 1289 CSIO_INC_STATS(mbm, n_req); 1290 1291 if (mbp->mb_cbfn) 1292 return 0; 1293 1294 /* Poll for completion in immediate mode */ 1295 cmd = mbp->mb; 1296 1297 for (ii = 0; ii < mbp->tmo; ii += CSIO_MB_POLL_FREQ) { 1298 mdelay(CSIO_MB_POLL_FREQ); 1299 1300 /* Check for response */ 1301 ctl = csio_rd_reg32(hw, ctl_reg); 1302 if (csio_mb_is_host_owner(MBOWNER_G(ctl))) { 1303 1304 if (!(ctl & MBMSGVALID_F)) { 1305 csio_wr_reg32(hw, 0, ctl_reg); 1306 continue; 1307 } 1308 1309 CSIO_DUMP_MB(hw, hw->pfn, data_reg); 1310 1311 hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg)); 1312 fw_hdr = (struct fw_cmd_hdr *)&hdr; 1313 1314 switch (FW_CMD_OP_G(ntohl(fw_hdr->hi))) { 1315 case FW_DEBUG_CMD: 1316 csio_mb_debug_cmd_handler(hw); 1317 continue; 1318 } 1319 1320 /* Copy response */ 1321 for (i = 0; i < size; i += 8) 1322 *cmd++ = cpu_to_be64(csio_rd_reg64 1323 (hw, data_reg + i)); 1324 csio_wr_reg32(hw, 0, ctl_reg); 1325 1326 if (csio_mb_fw_retval(mbp) != FW_SUCCESS) 1327 CSIO_INC_STATS(mbm, n_err); 1328 1329 CSIO_INC_STATS(mbm, n_rsp); 1330 return 0; 1331 } 1332 } 1333 1334 CSIO_INC_STATS(mbm, n_tmo); 1335 1336 csio_err(hw, "Mailbox %x op:0x%x timed out!\n", 1337 hw->pfn, *((uint8_t *)cmd)); 1338 1339 return -ETIMEDOUT; 1340 1341 error_out: 1342 CSIO_INC_STATS(mbm, n_err); 1343 return rv; 1344 } 1345 1346 /* 1347 * csio_mb_completions - Completion handler for Mailbox commands 1348 * @hw: The HW structure 1349 * @cbfn_q: Completion queue. 1350 * 1351 */ 1352 void 1353 csio_mb_completions(struct csio_hw *hw, struct list_head *cbfn_q) 1354 { 1355 struct csio_mb *mbp; 1356 struct csio_mbm *mbm = &hw->mbm; 1357 enum fw_retval rv; 1358 1359 while (!list_empty(cbfn_q)) { 1360 mbp = list_first_entry(cbfn_q, struct csio_mb, list); 1361 list_del_init(&mbp->list); 1362 1363 rv = csio_mb_fw_retval(mbp); 1364 if ((rv != FW_SUCCESS) && (rv != FW_HOSTERROR)) 1365 CSIO_INC_STATS(mbm, n_err); 1366 else if (rv != FW_HOSTERROR) 1367 CSIO_INC_STATS(mbm, n_rsp); 1368 1369 if (mbp->mb_cbfn) 1370 mbp->mb_cbfn(hw, mbp); 1371 } 1372 } 1373 1374 static void 1375 csio_mb_portmod_changed(struct csio_hw *hw, uint8_t port_id) 1376 { 1377 static char *mod_str[] = { 1378 NULL, "LR", "SR", "ER", "TWINAX", "active TWINAX", "LRM" 1379 }; 1380 1381 struct csio_pport *port = &hw->pport[port_id]; 1382 1383 if (port->mod_type == FW_PORT_MOD_TYPE_NONE) 1384 csio_info(hw, "Port:%d - port module unplugged\n", port_id); 1385 else if (port->mod_type < ARRAY_SIZE(mod_str)) 1386 csio_info(hw, "Port:%d - %s port module inserted\n", port_id, 1387 mod_str[port->mod_type]); 1388 else if (port->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED) 1389 csio_info(hw, 1390 "Port:%d - unsupported optical port module " 1391 "inserted\n", port_id); 1392 else if (port->mod_type == FW_PORT_MOD_TYPE_UNKNOWN) 1393 csio_info(hw, 1394 "Port:%d - unknown port module inserted, forcing " 1395 "TWINAX\n", port_id); 1396 else if (port->mod_type == FW_PORT_MOD_TYPE_ERROR) 1397 csio_info(hw, "Port:%d - transceiver module error\n", port_id); 1398 else 1399 csio_info(hw, "Port:%d - unknown module type %d inserted\n", 1400 port_id, port->mod_type); 1401 } 1402 1403 int 1404 csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd) 1405 { 1406 uint8_t opcode = *(uint8_t *)cmd; 1407 struct fw_port_cmd *pcmd; 1408 uint8_t port_id; 1409 uint32_t link_status; 1410 uint16_t action; 1411 uint8_t mod_type; 1412 1413 if (opcode == FW_PORT_CMD) { 1414 pcmd = (struct fw_port_cmd *)cmd; 1415 port_id = FW_PORT_CMD_PORTID_G( 1416 ntohl(pcmd->op_to_portid)); 1417 action = FW_PORT_CMD_ACTION_G( 1418 ntohl(pcmd->action_to_len16)); 1419 if (action != FW_PORT_ACTION_GET_PORT_INFO) { 1420 csio_err(hw, "Unhandled FW_PORT_CMD action: %u\n", 1421 action); 1422 return -EINVAL; 1423 } 1424 1425 link_status = ntohl(pcmd->u.info.lstatus_to_modtype); 1426 mod_type = FW_PORT_CMD_MODTYPE_G(link_status); 1427 1428 hw->pport[port_id].link_status = 1429 FW_PORT_CMD_LSTATUS_G(link_status); 1430 hw->pport[port_id].link_speed = 1431 FW_PORT_CMD_LSPEED_G(link_status); 1432 1433 csio_info(hw, "Port:%x - LINK %s\n", port_id, 1434 FW_PORT_CMD_LSTATUS_G(link_status) ? "UP" : "DOWN"); 1435 1436 if (mod_type != hw->pport[port_id].mod_type) { 1437 hw->pport[port_id].mod_type = mod_type; 1438 csio_mb_portmod_changed(hw, port_id); 1439 } 1440 } else if (opcode == FW_DEBUG_CMD) { 1441 csio_mb_dump_fw_dbg(hw, cmd); 1442 } else { 1443 csio_dbg(hw, "Gen MB can't handle op:0x%x on evtq.\n", opcode); 1444 return -EINVAL; 1445 } 1446 1447 return 0; 1448 } 1449 1450 /* 1451 * csio_mb_isr_handler - Handle mailboxes related interrupts. 1452 * @hw: The HW structure 1453 * 1454 * Called from the ISR to handle Mailbox related interrupts. 1455 * HW Lock should be held across this call. 1456 */ 1457 int 1458 csio_mb_isr_handler(struct csio_hw *hw) 1459 { 1460 struct csio_mbm *mbm = &hw->mbm; 1461 struct csio_mb *mbp = mbm->mcurrent; 1462 __be64 *cmd; 1463 uint32_t ctl, cim_cause, pl_cause; 1464 int i; 1465 uint32_t ctl_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_CTRL_A); 1466 uint32_t data_reg = PF_REG(hw->pfn, CIM_PF_MAILBOX_DATA_A); 1467 int size; 1468 __be64 hdr; 1469 struct fw_cmd_hdr *fw_hdr; 1470 1471 pl_cause = csio_rd_reg32(hw, MYPF_REG(PL_PF_INT_CAUSE_A)); 1472 cim_cause = csio_rd_reg32(hw, MYPF_REG(CIM_PF_HOST_INT_CAUSE_A)); 1473 1474 if (!(pl_cause & PFCIM_F) || !(cim_cause & MBMSGRDYINT_F)) { 1475 CSIO_INC_STATS(hw, n_mbint_unexp); 1476 return -EINVAL; 1477 } 1478 1479 /* 1480 * The cause registers below HAVE to be cleared in the SAME 1481 * order as below: The low level cause register followed by 1482 * the upper level cause register. In other words, CIM-cause 1483 * first followed by PL-Cause next. 1484 */ 1485 csio_wr_reg32(hw, MBMSGRDYINT_F, MYPF_REG(CIM_PF_HOST_INT_CAUSE_A)); 1486 csio_wr_reg32(hw, PFCIM_F, MYPF_REG(PL_PF_INT_CAUSE_A)); 1487 1488 ctl = csio_rd_reg32(hw, ctl_reg); 1489 1490 if (csio_mb_is_host_owner(MBOWNER_G(ctl))) { 1491 1492 CSIO_DUMP_MB(hw, hw->pfn, data_reg); 1493 1494 if (!(ctl & MBMSGVALID_F)) { 1495 csio_warn(hw, 1496 "Stray mailbox interrupt recvd," 1497 " mailbox data not valid\n"); 1498 csio_wr_reg32(hw, 0, ctl_reg); 1499 /* Flush */ 1500 csio_rd_reg32(hw, ctl_reg); 1501 return -EINVAL; 1502 } 1503 1504 hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg)); 1505 fw_hdr = (struct fw_cmd_hdr *)&hdr; 1506 1507 switch (FW_CMD_OP_G(ntohl(fw_hdr->hi))) { 1508 case FW_DEBUG_CMD: 1509 csio_mb_debug_cmd_handler(hw); 1510 return -EINVAL; 1511 #if 0 1512 case FW_ERROR_CMD: 1513 case FW_INITIALIZE_CMD: /* When we are not master */ 1514 #endif 1515 } 1516 1517 CSIO_ASSERT(mbp != NULL); 1518 1519 cmd = mbp->mb; 1520 size = mbp->mb_size; 1521 /* Get response */ 1522 for (i = 0; i < size; i += 8) 1523 *cmd++ = cpu_to_be64(csio_rd_reg64 1524 (hw, data_reg + i)); 1525 1526 csio_wr_reg32(hw, 0, ctl_reg); 1527 /* Flush */ 1528 csio_rd_reg32(hw, ctl_reg); 1529 1530 mbm->mcurrent = NULL; 1531 1532 /* Add completion to tail of cbfn queue */ 1533 list_add_tail(&mbp->list, &mbm->cbfn_q); 1534 CSIO_INC_STATS(mbm, n_cbfnq); 1535 1536 /* 1537 * Enqueue event to EventQ. Events processing happens 1538 * in Event worker thread context 1539 */ 1540 if (csio_enqueue_evt(hw, CSIO_EVT_MBX, mbp, sizeof(mbp))) 1541 CSIO_INC_STATS(hw, n_evt_drop); 1542 1543 return 0; 1544 1545 } else { 1546 /* 1547 * We can get here if mailbox MSIX vector is shared, 1548 * or in INTx case. Or a stray interrupt. 1549 */ 1550 csio_dbg(hw, "Host not owner, no mailbox interrupt\n"); 1551 CSIO_INC_STATS(hw, n_int_stray); 1552 return -EINVAL; 1553 } 1554 } 1555 1556 /* 1557 * csio_mb_tmo_handler - Timeout handler 1558 * @hw: The HW structure 1559 * 1560 */ 1561 struct csio_mb * 1562 csio_mb_tmo_handler(struct csio_hw *hw) 1563 { 1564 struct csio_mbm *mbm = &hw->mbm; 1565 struct csio_mb *mbp = mbm->mcurrent; 1566 struct fw_cmd_hdr *fw_hdr; 1567 1568 /* 1569 * Could be a race b/w the completion handler and the timer 1570 * and the completion handler won that race. 1571 */ 1572 if (mbp == NULL) { 1573 CSIO_DB_ASSERT(0); 1574 return NULL; 1575 } 1576 1577 fw_hdr = (struct fw_cmd_hdr *)(mbp->mb); 1578 1579 csio_dbg(hw, "Mailbox num:%x op:0x%x timed out\n", hw->pfn, 1580 FW_CMD_OP_G(ntohl(fw_hdr->hi))); 1581 1582 mbm->mcurrent = NULL; 1583 CSIO_INC_STATS(mbm, n_tmo); 1584 fw_hdr->lo = htonl(FW_CMD_RETVAL_V(FW_ETIMEDOUT)); 1585 1586 return mbp; 1587 } 1588 1589 /* 1590 * csio_mb_cancel_all - Cancel all waiting commands. 1591 * @hw: The HW structure 1592 * @cbfn_q: The callback queue. 1593 * 1594 * Caller should hold hw lock across this call. 1595 */ 1596 void 1597 csio_mb_cancel_all(struct csio_hw *hw, struct list_head *cbfn_q) 1598 { 1599 struct csio_mb *mbp; 1600 struct csio_mbm *mbm = &hw->mbm; 1601 struct fw_cmd_hdr *hdr; 1602 struct list_head *tmp; 1603 1604 if (mbm->mcurrent) { 1605 mbp = mbm->mcurrent; 1606 1607 /* Stop mailbox completion timer */ 1608 del_timer_sync(&mbm->timer); 1609 1610 /* Add completion to tail of cbfn queue */ 1611 list_add_tail(&mbp->list, cbfn_q); 1612 mbm->mcurrent = NULL; 1613 } 1614 1615 if (!list_empty(&mbm->req_q)) { 1616 list_splice_tail_init(&mbm->req_q, cbfn_q); 1617 mbm->stats.n_activeq = 0; 1618 } 1619 1620 if (!list_empty(&mbm->cbfn_q)) { 1621 list_splice_tail_init(&mbm->cbfn_q, cbfn_q); 1622 mbm->stats.n_cbfnq = 0; 1623 } 1624 1625 if (list_empty(cbfn_q)) 1626 return; 1627 1628 list_for_each(tmp, cbfn_q) { 1629 mbp = (struct csio_mb *)tmp; 1630 hdr = (struct fw_cmd_hdr *)(mbp->mb); 1631 1632 csio_dbg(hw, "Cancelling pending mailbox num %x op:%x\n", 1633 hw->pfn, FW_CMD_OP_G(ntohl(hdr->hi))); 1634 1635 CSIO_INC_STATS(mbm, n_cancel); 1636 hdr->lo = htonl(FW_CMD_RETVAL_V(FW_HOSTERROR)); 1637 } 1638 } 1639 1640 /* 1641 * csio_mbm_init - Initialize Mailbox module 1642 * @mbm: Mailbox module 1643 * @hw: The HW structure 1644 * @timer: Timing function for interrupting mailboxes 1645 * 1646 * Initialize timer and the request/response queues. 1647 */ 1648 int 1649 csio_mbm_init(struct csio_mbm *mbm, struct csio_hw *hw, 1650 void (*timer_fn)(struct timer_list *)) 1651 { 1652 mbm->hw = hw; 1653 timer_setup(&mbm->timer, timer_fn, 0); 1654 1655 INIT_LIST_HEAD(&mbm->req_q); 1656 INIT_LIST_HEAD(&mbm->cbfn_q); 1657 csio_set_mb_intr_idx(mbm, -1); 1658 1659 return 0; 1660 } 1661 1662 /* 1663 * csio_mbm_exit - Uninitialize mailbox module 1664 * @mbm: Mailbox module 1665 * 1666 * Stop timer. 1667 */ 1668 void 1669 csio_mbm_exit(struct csio_mbm *mbm) 1670 { 1671 del_timer_sync(&mbm->timer); 1672 1673 CSIO_DB_ASSERT(mbm->mcurrent == NULL); 1674 CSIO_DB_ASSERT(list_empty(&mbm->req_q)); 1675 CSIO_DB_ASSERT(list_empty(&mbm->cbfn_q)); 1676 } 1677