2 * This file is part of the Chelsio FCoE driver for Linux.
4 * Copyright (c) 2008-2012 Chelsio Communications, Inc. All rights reserved.
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:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
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.
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
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>
42 #include "csio_lnode.h"
43 #include "csio_rnode.h"
47 #define csio_mb_is_host_owner(__owner) ((__owner) == CSIO_MBOWNER_PL)
49 /* MB Command/Response Helpers */
51 * csio_mb_fw_retval - FW return value from a mailbox response.
52 * @mbp: Mailbox structure
56 csio_mb_fw_retval(struct csio_mb *mbp)
58 struct fw_cmd_hdr *hdr;
60 hdr = (struct fw_cmd_hdr *)(mbp->mb);
62 return FW_CMD_RETVAL_GET(ntohl(hdr->lo));
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.
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 *))
80 struct fw_hello_cmd *cmdp = (struct fw_hello_cmd *)(mbp->mb);
82 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
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);
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.
108 csio_mb_process_hello_rsp(struct csio_hw *hw, struct csio_mb *mbp,
109 enum fw_retval *retval, enum csio_dev_state *state,
112 struct fw_hello_cmd *rsp = (struct fw_hello_cmd *)(mbp->mb);
115 *retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
117 if (*retval == FW_SUCCESS) {
118 hw->fwrev = ntohl(rsp->fwrev);
120 value = ntohl(rsp->err_to_clearinit);
121 *mpfn = FW_HELLO_CMD_MBMASTER_GET(value);
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;
128 *state = CSIO_DEV_STATE_UNINIT;
133 * csio_mb_bye - FW BYE command helper
134 * @hw: The HW structure
135 * @mbp: Mailbox structure
136 * @cbfn: Callback, if any.
140 csio_mb_bye(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
141 void (*cbfn) (struct csio_hw *, struct csio_mb *))
143 struct fw_bye_cmd *cmdp = (struct fw_bye_cmd *)(mbp->mb);
145 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
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));
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.
162 csio_mb_reset(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
164 void (*cbfn) (struct csio_hw *, struct csio_mb *))
166 struct fw_reset_cmd *cmdp = (struct fw_reset_cmd *)(mbp->mb);
168 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
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);
179 * csio_mb_params - FW PARAMS command helper
180 * @hw: The HW structure
181 * @mbp: Mailbox structure
182 * @tmo: Command timeout.
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.
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 *))
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;
203 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
205 cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_PARAMS_CMD) |
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));
215 temp_params = *params++;
218 *p++ = htonl(temp_params);
219 *p++ = htonl(temp_val);
222 for (i = 0; i < nparams; i++, p += 2) {
223 temp_params = *params++;
224 *p = htonl(temp_params);
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.
240 csio_mb_process_read_params_rsp(struct csio_hw *hw, struct csio_mb *mbp,
241 enum fw_retval *retval, unsigned int nparams,
244 struct fw_params_cmd *rsp = (struct fw_params_cmd *)(mbp->mb);
246 __be32 *p = &rsp->param[0].val;
248 *retval = FW_CMD_RETVAL_GET(ntohl(rsp->retval_len16));
250 if (*retval == FW_SUCCESS)
251 for (i = 0; i < nparams; i++, p += 2)
256 * csio_mb_ldst - FW LDST command
257 * @hw: The HW structure
258 * @mbp: Mailbox structure
264 csio_mb_ldst(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo, int reg)
266 struct fw_ldst_cmd *ldst_cmd = (struct fw_ldst_cmd *)(mbp->mb);
267 CSIO_INIT_MBP(mbp, ldst_cmd, tmo, hw, NULL, 1);
270 * Construct and send the Firmware LDST Command to retrieve the
271 * specified PCI-E Configuration Space register.
273 ldst_cmd->op_to_addrspace =
274 htonl(FW_CMD_OP(FW_LDST_CMD) |
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;
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.
296 * This helper assumes that cmdp has MB payload from a previous CAPS
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 *))
304 struct fw_caps_config_cmd *cmdp =
305 (struct fw_caps_config_cmd *)(mbp->mb);
307 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, wr ? 0 : 1);
309 cmdp->op_to_write = htonl(FW_CMD_OP(FW_CAPS_CONFIG_CMD) |
311 (wr ? FW_CMD_WRITE : FW_CMD_READ));
312 cmdp->cfvalid_to_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
322 cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_CTRL_OFLD);
324 cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_INITIATOR);
326 cmdp->fcoecaps |= htons(FW_CAPS_CONFIG_FCOE_TARGET);
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 *))
334 struct fw_rss_glb_config_cmd *cmdp =
335 (struct fw_rss_glb_config_cmd *)(mbp->mb);
337 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
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));
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);
355 * csio_mb_pfvf - FW Write PF/VF capabilities command helper.
356 * @hw: The HW structure
357 * @mbp: Mailbox structure
369 * @cbfn: Callback, if any.
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 *))
381 struct fw_pfvf_cmd *cmdp = (struct fw_pfvf_cmd *)(mbp->mb);
383 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
385 cmdp->op_to_vfn = htonl(FW_CMD_OP(FW_PFVF_CMD) |
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));
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));
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)
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.
417 * @caps: Port capabilites to set.
418 * @cbfn: Callback, if any.
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 *))
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);
429 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
431 cmdp->op_to_portid = htonl(FW_CMD_OP(FW_PORT_CMD) |
433 (wr ? FW_CMD_EXEC : FW_CMD_READ) |
434 FW_PORT_CMD_PORTID(portid));
436 cmdp->action_to_len16 = htonl(
437 FW_PORT_CMD_ACTION(FW_PORT_ACTION_GET_PORT_INFO) |
438 FW_CMD_LEN16(sizeof(*cmdp) / 16));
443 cmdp->action_to_len16 = htonl(
444 FW_PORT_CMD_ACTION(FW_PORT_ACTION_L1_CFG) |
445 FW_CMD_LEN16(sizeof(*cmdp) / 16));
448 lfc |= FW_PORT_CAP_FC_RX;
450 lfc |= FW_PORT_CAP_FC_TX;
452 if (!(caps & FW_PORT_CAP_ANEG))
453 cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) | lfc);
455 cmdp->u.l1cfg.rcap = htonl((caps & CSIO_ADVERT_MASK) |
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
468 csio_mb_process_read_port_rsp(struct csio_hw *hw, struct csio_mb *mbp,
469 enum fw_retval *retval, uint16_t *caps)
471 struct fw_port_cmd *rsp = (struct fw_port_cmd *)(mbp->mb);
473 *retval = FW_CMD_RETVAL_GET(ntohl(rsp->action_to_len16));
475 if (*retval == FW_SUCCESS)
476 *caps = ntohs(rsp->u.info.pcap);
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.
488 csio_mb_initialize(struct csio_hw *hw, struct csio_mb *mbp, uint32_t tmo,
489 void (*cbfn) (struct csio_hw *, struct csio_mb *))
491 struct fw_initialize_cmd *cmdp = (struct fw_initialize_cmd *)(mbp->mb);
493 CSIO_INIT_MBP(mbp, cmdp, tmo, hw, cbfn, 1);
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));
502 * csio_mb_iq_alloc - Initializes the mailbox to allocate an
503 * Ingress DMA queue in the firmware.
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
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 *))
519 struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
521 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
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));
528 cmdp->alloc_to_len16 = htonl(FW_IQ_CMD_ALLOC |
529 FW_CMD_LEN16(sizeof(*cmdp) / 16));
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));
536 cmdp->fl0size = htons(iq_params->fl0size);
537 cmdp->fl0size = htons(iq_params->fl1size);
539 } /* csio_mb_iq_alloc */
542 * csio_mb_iq_write - Initializes the mailbox for writing into an
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
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.
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 *))
565 struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
567 uint32_t iq_start_stop = (iq_params->iq_start) ?
568 FW_IQ_CMD_IQSTART(1) :
572 * If this IQ write is cascaded with IQ alloc request, do not
573 * re-initialize with 0's.
577 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
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));
601 cmdp->iqsize |= htons(iq_params->iqsize);
602 cmdp->iqaddr |= cpu_to_be64(iq_params->iqaddr);
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));
610 if (iq_params->fl0size && iq_params->fl0addr &&
611 (iq_params->fl0id != 0xFFFF)) {
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);
627 } /* csio_mb_iq_write */
630 * csio_mb_iq_alloc_write - Initializes the mailbox for allocating an
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
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 *))
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 */
652 * csio_mb_iq_alloc_write_rsp - Process the allocation & writing
653 * of ingress DMA queue mailbox's response.
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.
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)
666 struct fw_iq_cmd *rsp = (struct fw_iq_cmd *)(mbp->mb);
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);
675 iq_params->physiqid = iq_params->iqid =
676 iq_params->fl0id = iq_params->fl1id = 0;
678 } /* csio_mb_iq_alloc_write_rsp */
681 * csio_mb_iq_free - Initializes the mailbox for freeing a
682 * specified Ingress DMA Queue.
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
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 *))
698 struct fw_iq_cmd *cmdp = (struct fw_iq_cmd *)(mbp->mb);
700 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
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));
710 cmdp->iqid = htons(iq_params->iqid);
711 cmdp->fl0id = htons(iq_params->fl0id);
712 cmdp->fl1id = htons(iq_params->fl1id);
714 } /* csio_mb_iq_free */
717 * csio_mb_eq_ofld_alloc - Initializes the mailbox for allocating
718 * an offload-egress queue.
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
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 *))
734 struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
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));
744 } /* csio_mb_eq_ofld_alloc */
747 * csio_mb_eq_ofld_write - Initializes the mailbox for writing
748 * an alloacted offload-egress queue.
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
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.
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 *))
771 struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
773 uint32_t eq_start_stop = (eq_ofld_params->eqstart) ?
774 FW_EQ_OFLD_CMD_EQSTART : FW_EQ_OFLD_CMD_EQSTOP;
777 * If this EQ write is cascaded with EQ alloc request, do not
778 * re-initialize with 0's.
782 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
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));
791 cmdp->eqid_pkd |= htonl(FW_EQ_OFLD_CMD_EQID(eq_ofld_params->eqid));
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));
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));
808 cmdp->eqaddr |= cpu_to_be64(eq_ofld_params->eqaddr);
810 } /* csio_mb_eq_ofld_write */
813 * csio_mb_eq_ofld_alloc_write - Initializes the mailbox for allocation
814 * writing into an Engress DMA Queue.
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
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 *))
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 */
837 * csio_mb_eq_ofld_alloc_write_rsp - Process the allocation
838 * & write egress DMA queue mailbox's response.
840 * @hw: The HW structure.
841 * @mbp: Mailbox structure to initialize.
842 * @retval: Firmware return value.
843 * @eq_ofld_params: (Offload) Egress queue parameters.
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)
851 struct fw_eq_ofld_cmd *rsp = (struct fw_eq_ofld_cmd *)(mbp->mb);
853 *ret_val = FW_CMD_RETVAL_GET(ntohl(rsp->alloc_to_len16));
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));
861 eq_ofld_params->eqid = 0;
863 } /* csio_mb_eq_ofld_alloc_write_rsp */
866 * csio_mb_eq_ofld_free - Initializes the mailbox for freeing a
867 * specified Engress DMA Queue.
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
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 *))
883 struct fw_eq_ofld_cmd *cmdp = (struct fw_eq_ofld_cmd *)(mbp->mb);
885 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, priv, cbfn, 1);
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));
895 } /* csio_mb_eq_ofld_free */
898 * csio_write_fcoe_link_cond_init_mb - Initialize Mailbox to write FCoE link
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.
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 *))
914 struct fw_fcoe_link_cmd *cmdp =
915 (struct fw_fcoe_link_cmd *)(mbp->mb);
917 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
919 cmdp->op_to_portid = htonl((
920 FW_CMD_OP(FW_FCOE_LINK_CMD) |
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));
930 } /* csio_write_fcoe_link_cond_init_mb */
933 * csio_fcoe_read_res_info_init_mb - Initializes the mailbox for reading FCoE
934 * resource information(FW_GET_RES_INFO_CMD).
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
944 csio_fcoe_read_res_info_init_mb(struct csio_hw *hw, struct csio_mb *mbp,
946 void (*cbfn) (struct csio_hw *, struct csio_mb *))
948 struct fw_fcoe_res_info_cmd *cmdp =
949 (struct fw_fcoe_res_info_cmd *)(mbp->mb);
951 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1);
953 cmdp->op_to_read = htonl((FW_CMD_OP(FW_FCOE_RES_INFO_CMD) |
957 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
959 } /* csio_fcoe_read_res_info_init_mb */
962 * csio_fcoe_vnp_alloc_init_mb - Initializes the mailbox for allocating VNP
963 * in the firmware (FW_FCOE_VNP_CMD).
965 * @ln: The Lnode structure.
966 * @mbp: Mailbox structure to initialize.
967 * @mb_tmo: Mailbox time-out period (in ms).
971 * @vnport_wwnn: vnport WWNN
972 * @vnport_wwpn: vnport WWPN
973 * @cbfn: The call-back function.
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 *))
983 struct fw_fcoe_vnp_cmd *cmdp =
984 (struct fw_fcoe_vnp_cmd *)(mbp->mb);
986 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
988 cmdp->op_to_fcfi = htonl((FW_CMD_OP(FW_FCOE_VNP_CMD) |
991 FW_FCOE_VNP_CMD_FCFI(fcfi)));
993 cmdp->alloc_to_len16 = htonl(FW_FCOE_VNP_CMD_ALLOC |
994 FW_CMD_LEN16(sizeof(*cmdp) / 16));
996 cmdp->gen_wwn_to_vnpi = htonl(FW_FCOE_VNP_CMD_VNPI(vnpi));
998 cmdp->iqid = htons(iqid);
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);
1004 memcpy(cmdp->vnport_wwnn, vnport_wwnn, 8);
1006 memcpy(cmdp->vnport_wwpn, vnport_wwpn, 8);
1008 } /* csio_fcoe_vnp_alloc_init_mb */
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).
1017 * @cbfn: The call-back handler.
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 *))
1024 struct fw_fcoe_vnp_cmd *cmdp =
1025 (struct fw_fcoe_vnp_cmd *)(mbp->mb);
1027 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
1028 cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_VNP_CMD) |
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));
1037 * csio_fcoe_vnp_free_init_mb - Initializes the mailbox for freeing an
1038 * alloacted VNP in the firmware (FW_FCOE_VNP_CMD).
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.
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 *))
1053 struct fw_fcoe_vnp_cmd *cmdp =
1054 (struct fw_fcoe_vnp_cmd *)(mbp->mb);
1056 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
1058 cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_VNP_CMD) |
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));
1068 * csio_fcoe_read_fcf_init_mb - Initializes the mailbox to read the
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
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 *))
1084 struct fw_fcoe_fcf_cmd *cmdp =
1085 (struct fw_fcoe_fcf_cmd *)(mbp->mb);
1087 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, ln, cbfn, 1);
1089 cmdp->op_to_fcfi = htonl(FW_CMD_OP(FW_FCOE_FCF_CMD) |
1092 FW_FCOE_FCF_CMD_FCFI(fcfi));
1093 cmdp->retval_len16 = htonl(FW_CMD_LEN16(sizeof(*cmdp) / 16));
1095 } /* csio_fcoe_read_fcf_init_mb */
1098 csio_fcoe_read_portparams_init_mb(struct csio_hw *hw, struct csio_mb *mbp,
1100 struct fw_fcoe_port_cmd_params *portparams,
1101 void (*cbfn)(struct csio_hw *,
1104 struct fw_fcoe_stats_cmd *cmdp = (struct fw_fcoe_stats_cmd *)(mbp->mb);
1106 CSIO_INIT_MBP(mbp, cmdp, mb_tmo, hw, cbfn, 1);
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));
1113 cmdp->u.ctl.nstats_port = FW_FCOE_STATS_CMD_NSTATS(portparams->nstats) |
1114 FW_FCOE_STATS_CMD_PORT(portparams->portid);
1116 cmdp->u.ctl.port_valid_ix = FW_FCOE_STATS_CMD_IX(portparams->idx) |
1117 FW_FCOE_STATS_CMD_PORT_VALID;
1119 } /* csio_fcoe_read_portparams_init_mb */
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)
1128 struct fw_fcoe_stats_cmd *rsp = (struct fw_fcoe_stats_cmd *)(mbp->mb);
1129 struct fw_fcoe_port_stats stats;
1133 *retval = FW_CMD_RETVAL_GET(ntohl(rsp->free_to_len16));
1135 memset(&stats, 0, sizeof(struct fw_fcoe_port_stats));
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;
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;
1156 portstats->rx_pf_bytes = stats.rx_pf_bytes;
1157 portstats->rx_pf_frames = stats.rx_pf_frames;
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;
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;
1173 /* Entry points/APIs for MB module */
1175 * csio_mb_intr_enable - Enable Interrupts from mailboxes.
1176 * @hw: The HW structure
1178 * Enables CIM interrupt bit in appropriate INT_ENABLE registers.
1181 csio_mb_intr_enable(struct csio_hw *hw)
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));
1188 * csio_mb_intr_disable - Disable Interrupts from mailboxes.
1189 * @hw: The HW structure
1191 * Disable bit in HostInterruptEnable CIM register.
1194 csio_mb_intr_disable(struct csio_hw *hw)
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));
1201 csio_mb_dump_fw_dbg(struct csio_hw *hw, __be64 *cmd)
1203 struct fw_debug_cmd *dbg = (struct fw_debug_cmd *)cmd;
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));
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));
1228 csio_mb_debug_cmd_handler(struct csio_hw *hw)
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);
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));
1240 csio_mb_dump_fw_dbg(hw, cmd);
1242 /* Notify FW of mailbox by setting owner as UP */
1243 csio_wr_reg32(hw, MBMSGVALID | MBINTREQ | MBOWNER(CSIO_MBOWNER_FW),
1246 csio_rd_reg32(hw, ctl_reg);
1251 * csio_mb_issue - generic routine for issuing Mailbox commands.
1252 * @hw: The HW structure
1253 * @mbp: Mailbox command to issue
1255 * Caller should hold hw lock across this call.
1258 csio_mb_issue(struct csio_hw *hw, struct csio_mb *mbp)
1260 uint32_t owner, ctl;
1263 __be64 *cmd = mbp->mb;
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;
1270 struct fw_cmd_hdr *fw_hdr;
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);
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));
1286 if (mbm->mcurrent != NULL) {
1287 /* Queue mbox cmd, if another mbox cmd is active */
1288 if (mbp->mb_cbfn == NULL) {
1290 csio_dbg(hw, "Couldnt own Mailbox %x op:0x%x\n",
1291 hw->pfn, *((uint8_t *)mbp->mb));
1295 list_add_tail(&mbp->list, &mbm->req_q);
1296 CSIO_INC_STATS(mbm, n_activeq);
1302 /* Now get ownership of mailbox */
1303 owner = MBOWNER_GET(csio_rd_reg32(hw, ctl_reg));
1305 if (!csio_mb_is_host_owner(owner)) {
1307 for (i = 0; (owner == CSIO_MBOWNER_NONE) && (i < 3); i++)
1308 owner = MBOWNER_GET(csio_rd_reg32(hw, ctl_reg));
1310 * Mailbox unavailable. In immediate mode, fail the command.
1311 * In other modes, enqueue the request.
1313 if (!csio_mb_is_host_owner(owner)) {
1314 if (mbp->mb_cbfn == NULL) {
1315 rv = owner ? -EBUSY : -ETIMEDOUT;
1318 "Couldnt own Mailbox %x op:0x%x "
1320 hw->pfn, *((uint8_t *)mbp->mb), owner);
1323 if (mbm->mcurrent == NULL) {
1325 "Couldnt own Mailbox %x "
1326 "op:0x%x owner:%x\n",
1327 hw->pfn, *((uint8_t *)mbp->mb),
1330 "No outstanding driver"
1331 " mailbox as well\n");
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);
1344 CSIO_DUMP_MB(hw, hw->pfn, data_reg);
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);
1353 csio_wr_reg32(hw, MBMSGVALID | MBOWNER(CSIO_MBOWNER_FW),
1356 /* Flush posted writes */
1357 csio_rd_reg32(hw, ctl_reg);
1360 CSIO_INC_STATS(mbm, n_req);
1365 /* Poll for completion in immediate mode */
1368 for (ii = 0; ii < mbp->tmo; ii += CSIO_MB_POLL_FREQ) {
1369 mdelay(CSIO_MB_POLL_FREQ);
1371 /* Check for response */
1372 ctl = csio_rd_reg32(hw, ctl_reg);
1373 if (csio_mb_is_host_owner(MBOWNER_GET(ctl))) {
1375 if (!(ctl & MBMSGVALID)) {
1376 csio_wr_reg32(hw, 0, ctl_reg);
1380 CSIO_DUMP_MB(hw, hw->pfn, data_reg);
1382 hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg));
1383 fw_hdr = (struct fw_cmd_hdr *)&hdr;
1385 switch (FW_CMD_OP_GET(ntohl(fw_hdr->hi))) {
1387 csio_mb_debug_cmd_handler(hw);
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);
1397 if (csio_mb_fw_retval(mbp) != FW_SUCCESS)
1398 CSIO_INC_STATS(mbm, n_err);
1400 CSIO_INC_STATS(mbm, n_rsp);
1405 CSIO_INC_STATS(mbm, n_tmo);
1407 csio_err(hw, "Mailbox %x op:0x%x timed out!\n",
1408 hw->pfn, *((uint8_t *)cmd));
1413 CSIO_INC_STATS(mbm, n_err);
1418 * csio_mb_completions - Completion handler for Mailbox commands
1419 * @hw: The HW structure
1420 * @cbfn_q: Completion queue.
1424 csio_mb_completions(struct csio_hw *hw, struct list_head *cbfn_q)
1426 struct csio_mb *mbp;
1427 struct csio_mbm *mbm = &hw->mbm;
1430 while (!list_empty(cbfn_q)) {
1431 mbp = list_first_entry(cbfn_q, struct csio_mb, list);
1432 list_del_init(&mbp->list);
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);
1441 mbp->mb_cbfn(hw, mbp);
1446 csio_mb_portmod_changed(struct csio_hw *hw, uint8_t port_id)
1448 static char *mod_str[] = {
1449 NULL, "LR", "SR", "ER", "TWINAX", "active TWINAX", "LRM"
1452 struct csio_pport *port = &hw->pport[port_id];
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)
1461 "Port:%d - unsupported optical port module "
1462 "inserted\n", port_id);
1463 else if (port->mod_type == FW_PORT_MOD_TYPE_UNKNOWN)
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);
1470 csio_info(hw, "Port:%d - unknown module type %d inserted\n",
1471 port_id, port->mod_type);
1475 csio_mb_fwevt_handler(struct csio_hw *hw, __be64 *cmd)
1477 uint8_t opcode = *(uint8_t *)cmd;
1478 struct fw_port_cmd *pcmd;
1480 uint32_t link_status;
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",
1496 link_status = ntohl(pcmd->u.info.lstatus_to_modtype);
1497 mod_type = FW_PORT_CMD_MODTYPE_GET(link_status);
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);
1504 csio_info(hw, "Port:%x - LINK %s\n", port_id,
1505 FW_PORT_CMD_LSTATUS_GET(link_status) ? "UP" : "DOWN");
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);
1511 } else if (opcode == FW_DEBUG_CMD) {
1512 csio_mb_dump_fw_dbg(hw, cmd);
1514 csio_dbg(hw, "Gen MB can't handle op:0x%x on evtq.\n", opcode);
1522 * csio_mb_isr_handler - Handle mailboxes related interrupts.
1523 * @hw: The HW structure
1525 * Called from the ISR to handle Mailbox related interrupts.
1526 * HW Lock should be held across this call.
1529 csio_mb_isr_handler(struct csio_hw *hw)
1531 struct csio_mbm *mbm = &hw->mbm;
1532 struct csio_mb *mbp = mbm->mcurrent;
1534 uint32_t ctl, cim_cause, pl_cause;
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);
1540 struct fw_cmd_hdr *fw_hdr;
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));
1545 if (!(pl_cause & PFCIM) || !(cim_cause & MBMSGRDYINT)) {
1546 CSIO_INC_STATS(hw, n_mbint_unexp);
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.
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));
1559 ctl = csio_rd_reg32(hw, ctl_reg);
1561 if (csio_mb_is_host_owner(MBOWNER_GET(ctl))) {
1563 CSIO_DUMP_MB(hw, hw->pfn, data_reg);
1565 if (!(ctl & MBMSGVALID)) {
1567 "Stray mailbox interrupt recvd,"
1568 " mailbox data not valid\n");
1569 csio_wr_reg32(hw, 0, ctl_reg);
1571 csio_rd_reg32(hw, ctl_reg);
1575 hdr = cpu_to_be64(csio_rd_reg64(hw, data_reg));
1576 fw_hdr = (struct fw_cmd_hdr *)&hdr;
1578 switch (FW_CMD_OP_GET(ntohl(fw_hdr->hi))) {
1580 csio_mb_debug_cmd_handler(hw);
1584 case FW_INITIALIZE_CMD: /* When we are not master */
1588 CSIO_ASSERT(mbp != NULL);
1591 size = mbp->mb_size;
1593 for (i = 0; i < size; i += 8)
1594 *cmd++ = cpu_to_be64(csio_rd_reg64
1595 (hw, data_reg + i));
1597 csio_wr_reg32(hw, 0, ctl_reg);
1599 csio_rd_reg32(hw, ctl_reg);
1601 mbm->mcurrent = NULL;
1603 /* Add completion to tail of cbfn queue */
1604 list_add_tail(&mbp->list, &mbm->cbfn_q);
1605 CSIO_INC_STATS(mbm, n_cbfnq);
1608 * Enqueue event to EventQ. Events processing happens
1609 * in Event worker thread context
1611 if (csio_enqueue_evt(hw, CSIO_EVT_MBX, mbp, sizeof(mbp)))
1612 CSIO_INC_STATS(hw, n_evt_drop);
1618 * We can get here if mailbox MSIX vector is shared,
1619 * or in INTx case. Or a stray interrupt.
1621 csio_dbg(hw, "Host not owner, no mailbox interrupt\n");
1622 CSIO_INC_STATS(hw, n_int_stray);
1628 * csio_mb_tmo_handler - Timeout handler
1629 * @hw: The HW structure
1633 csio_mb_tmo_handler(struct csio_hw *hw)
1635 struct csio_mbm *mbm = &hw->mbm;
1636 struct csio_mb *mbp = mbm->mcurrent;
1637 struct fw_cmd_hdr *fw_hdr;
1640 * Could be a race b/w the completion handler and the timer
1641 * and the completion handler won that race.
1648 fw_hdr = (struct fw_cmd_hdr *)(mbp->mb);
1650 csio_dbg(hw, "Mailbox num:%x op:0x%x timed out\n", hw->pfn,
1651 FW_CMD_OP_GET(ntohl(fw_hdr->hi)));
1653 mbm->mcurrent = NULL;
1654 CSIO_INC_STATS(mbm, n_tmo);
1655 fw_hdr->lo = htonl(FW_CMD_RETVAL(FW_ETIMEDOUT));
1661 * csio_mb_cancel_all - Cancel all waiting commands.
1662 * @hw: The HW structure
1663 * @cbfn_q: The callback queue.
1665 * Caller should hold hw lock across this call.
1668 csio_mb_cancel_all(struct csio_hw *hw, struct list_head *cbfn_q)
1670 struct csio_mb *mbp;
1671 struct csio_mbm *mbm = &hw->mbm;
1672 struct fw_cmd_hdr *hdr;
1673 struct list_head *tmp;
1675 if (mbm->mcurrent) {
1676 mbp = mbm->mcurrent;
1678 /* Stop mailbox completion timer */
1679 del_timer_sync(&mbm->timer);
1681 /* Add completion to tail of cbfn queue */
1682 list_add_tail(&mbp->list, cbfn_q);
1683 mbm->mcurrent = NULL;
1686 if (!list_empty(&mbm->req_q)) {
1687 list_splice_tail_init(&mbm->req_q, cbfn_q);
1688 mbm->stats.n_activeq = 0;
1691 if (!list_empty(&mbm->cbfn_q)) {
1692 list_splice_tail_init(&mbm->cbfn_q, cbfn_q);
1693 mbm->stats.n_cbfnq = 0;
1696 if (list_empty(cbfn_q))
1699 list_for_each(tmp, cbfn_q) {
1700 mbp = (struct csio_mb *)tmp;
1701 hdr = (struct fw_cmd_hdr *)(mbp->mb);
1703 csio_dbg(hw, "Cancelling pending mailbox num %x op:%x\n",
1704 hw->pfn, FW_CMD_OP_GET(ntohl(hdr->hi)));
1706 CSIO_INC_STATS(mbm, n_cancel);
1707 hdr->lo = htonl(FW_CMD_RETVAL(FW_HOSTERROR));
1712 * csio_mbm_init - Initialize Mailbox module
1713 * @mbm: Mailbox module
1714 * @hw: The HW structure
1715 * @timer: Timing function for interrupting mailboxes
1717 * Initialize timer and the request/response queues.
1720 csio_mbm_init(struct csio_mbm *mbm, struct csio_hw *hw,
1721 void (*timer_fn)(uintptr_t))
1723 struct timer_list *timer = &mbm->timer;
1726 timer->function = timer_fn;
1727 timer->data = (unsigned long)hw;
1729 INIT_LIST_HEAD(&mbm->req_q);
1730 INIT_LIST_HEAD(&mbm->cbfn_q);
1731 csio_set_mb_intr_idx(mbm, -1);
1737 * csio_mbm_exit - Uninitialize mailbox module
1738 * @mbm: Mailbox module
1743 csio_mbm_exit(struct csio_mbm *mbm)
1745 del_timer_sync(&mbm->timer);
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));