1 /* bnx2x_vfpf.c: Broadcom Everest network driver.
3 * Copyright 2009-2012 Broadcom Corporation
5 * Unless you and Broadcom execute a separate written software license
6 * agreement governing use of this software, this software is licensed to you
7 * under the terms of the GNU General Public License version 2, available
8 * at http://www.gnu.org/licenses/old-licenses/gpl-2.0.html (the "GPL").
10 * Notwithstanding the above, under no circumstances may you combine this
11 * software in any way with any other Broadcom software provided under a
12 * license other than the GPL, without Broadcom's express prior written
15 * Maintained by: Eilon Greenstein <eilong@broadcom.com>
16 * Written by: Shmulik Ravid <shmulikr@broadcom.com>
17 * Ariel Elior <ariele@broadcom.com>
21 #include "bnx2x_sriov.h"
22 #include <linux/crc32.h>
24 /* place a given tlv on the tlv buffer at a given offset */
25 void bnx2x_add_tlv(struct bnx2x
*bp
, void *tlvs_list
, u16 offset
, u16 type
,
28 struct channel_tlv
*tl
=
29 (struct channel_tlv
*)(tlvs_list
+ offset
);
35 /* Clear the mailbox and init the header of the first tlv */
36 void bnx2x_vfpf_prep(struct bnx2x
*bp
, struct vfpf_first_tlv
*first_tlv
,
39 DP(BNX2X_MSG_IOV
, "preparing to send %d tlv over vf pf channel\n",
43 memset(bp
->vf2pf_mbox
, 0, sizeof(struct bnx2x_vf_mbx_msg
));
45 /* init type and length */
46 bnx2x_add_tlv(bp
, &first_tlv
->tl
, 0, type
, length
);
48 /* init first tlv header */
49 first_tlv
->resp_msg_offset
= sizeof(bp
->vf2pf_mbox
->req
);
52 /* list the types and lengths of the tlvs on the buffer */
53 void bnx2x_dp_tlv_list(struct bnx2x
*bp
, void *tlvs_list
)
56 struct channel_tlv
*tlv
= (struct channel_tlv
*)tlvs_list
;
58 while (tlv
->type
!= CHANNEL_TLV_LIST_END
) {
60 DP(BNX2X_MSG_IOV
, "TLV number %d: type %d, length %d\n", i
,
61 tlv
->type
, tlv
->length
);
63 /* advance to next tlv */
64 tlvs_list
+= tlv
->length
;
66 /* cast general tlv list pointer to channel tlv header*/
67 tlv
= (struct channel_tlv
*)tlvs_list
;
71 /* break condition for this loop */
72 if (i
> MAX_TLVS_IN_LIST
) {
73 WARN(true, "corrupt tlvs");
79 DP(BNX2X_MSG_IOV
, "TLV number %d: type %d, length %d\n", i
,
80 tlv
->type
, tlv
->length
);
83 /* test whether we support a tlv type */
84 bool bnx2x_tlv_supported(u16 tlvtype
)
86 return CHANNEL_TLV_NONE
< tlvtype
&& tlvtype
< CHANNEL_TLV_MAX
;
89 static inline int bnx2x_pfvf_status_codes(int rc
)
93 return PFVF_STATUS_SUCCESS
;
95 return PFVF_STATUS_NO_RESOURCE
;
97 return PFVF_STATUS_FAILURE
;
101 /* General service functions */
102 static void storm_memset_vf_mbx_ack(struct bnx2x
*bp
, u16 abs_fid
)
104 u32 addr
= BAR_CSTRORM_INTMEM
+
105 CSTORM_VF_PF_CHANNEL_STATE_OFFSET(abs_fid
);
107 REG_WR8(bp
, addr
, VF_PF_CHANNEL_STATE_READY
);
110 static void storm_memset_vf_mbx_valid(struct bnx2x
*bp
, u16 abs_fid
)
112 u32 addr
= BAR_CSTRORM_INTMEM
+
113 CSTORM_VF_PF_CHANNEL_VALID_OFFSET(abs_fid
);
115 REG_WR8(bp
, addr
, 1);
118 static inline void bnx2x_set_vf_mbxs_valid(struct bnx2x
*bp
)
123 storm_memset_vf_mbx_valid(bp
, bnx2x_vf(bp
, i
, abs_vfid
));
126 /* enable vf_pf mailbox (aka vf-pf-chanell) */
127 void bnx2x_vf_enable_mbx(struct bnx2x
*bp
, u8 abs_vfid
)
129 bnx2x_vf_flr_clnup_epilog(bp
, abs_vfid
);
131 /* enable the mailbox in the FW */
132 storm_memset_vf_mbx_ack(bp
, abs_vfid
);
133 storm_memset_vf_mbx_valid(bp
, abs_vfid
);
135 /* enable the VF access to the mailbox */
136 bnx2x_vf_enable_access(bp
, abs_vfid
);
139 /* this works only on !E1h */
140 static int bnx2x_copy32_vf_dmae(struct bnx2x
*bp
, u8 from_vf
,
141 dma_addr_t pf_addr
, u8 vfid
, u32 vf_addr_hi
,
142 u32 vf_addr_lo
, u32 len32
)
144 struct dmae_command dmae
;
146 if (CHIP_IS_E1x(bp
)) {
147 BNX2X_ERR("Chip revision does not support VFs\n");
151 if (!bp
->dmae_ready
) {
152 BNX2X_ERR("DMAE is not ready, can not copy\n");
156 /* set opcode and fixed command fields */
157 bnx2x_prep_dmae_with_comp(bp
, &dmae
, DMAE_SRC_PCI
, DMAE_DST_PCI
);
160 dmae
.opcode_iov
= (vfid
<< DMAE_COMMAND_SRC_VFID_SHIFT
) |
161 (DMAE_SRC_VF
<< DMAE_COMMAND_SRC_VFPF_SHIFT
) |
162 (DMAE_DST_PF
<< DMAE_COMMAND_DST_VFPF_SHIFT
);
164 dmae
.opcode
|= (DMAE_C_DST
<< DMAE_COMMAND_C_FUNC_SHIFT
);
166 dmae
.src_addr_lo
= vf_addr_lo
;
167 dmae
.src_addr_hi
= vf_addr_hi
;
168 dmae
.dst_addr_lo
= U64_LO(pf_addr
);
169 dmae
.dst_addr_hi
= U64_HI(pf_addr
);
171 dmae
.opcode_iov
= (vfid
<< DMAE_COMMAND_DST_VFID_SHIFT
) |
172 (DMAE_DST_VF
<< DMAE_COMMAND_DST_VFPF_SHIFT
) |
173 (DMAE_SRC_PF
<< DMAE_COMMAND_SRC_VFPF_SHIFT
);
175 dmae
.opcode
|= (DMAE_C_SRC
<< DMAE_COMMAND_C_FUNC_SHIFT
);
177 dmae
.src_addr_lo
= U64_LO(pf_addr
);
178 dmae
.src_addr_hi
= U64_HI(pf_addr
);
179 dmae
.dst_addr_lo
= vf_addr_lo
;
180 dmae
.dst_addr_hi
= vf_addr_hi
;
183 bnx2x_dp_dmae(bp
, &dmae
, BNX2X_MSG_DMAE
);
185 /* issue the command and wait for completion */
186 return bnx2x_issue_dmae_with_comp(bp
, &dmae
);
189 static void bnx2x_vf_mbx_resp(struct bnx2x
*bp
, struct bnx2x_virtf
*vf
)
191 struct bnx2x_vf_mbx
*mbx
= BP_VF_MBX(bp
, vf
->index
);
196 struct pfvf_general_resp_tlv
*resp
= &mbx
->msg
->resp
.general_resp
;
198 /* prepare response */
199 type
= mbx
->first_tlv
.tl
.type
;
200 length
= type
== CHANNEL_TLV_ACQUIRE
?
201 sizeof(struct pfvf_acquire_resp_tlv
) :
202 sizeof(struct pfvf_general_resp_tlv
);
203 bnx2x_add_tlv(bp
, resp
, 0, type
, length
);
204 resp
->hdr
.status
= bnx2x_pfvf_status_codes(vf
->op_rc
);
205 bnx2x_add_tlv(bp
, resp
, length
, CHANNEL_TLV_LIST_END
,
206 sizeof(struct channel_list_end_tlv
));
207 bnx2x_dp_tlv_list(bp
, resp
);
208 DP(BNX2X_MSG_IOV
, "mailbox vf address hi 0x%x, lo 0x%x, offset 0x%x\n",
209 mbx
->vf_addr_hi
, mbx
->vf_addr_lo
, mbx
->first_tlv
.resp_msg_offset
);
212 vf_addr
= HILO_U64(mbx
->vf_addr_hi
, mbx
->vf_addr_lo
) +
213 mbx
->first_tlv
.resp_msg_offset
;
214 pf_addr
= mbx
->msg_mapping
+
215 offsetof(struct bnx2x_vf_mbx_msg
, resp
);
217 /* copy the response body, if there is one, before the header, as the vf
218 * is sensitive to the header being written
220 if (resp
->hdr
.tl
.length
> sizeof(u64
)) {
221 length
= resp
->hdr
.tl
.length
- sizeof(u64
);
222 vf_addr
+= sizeof(u64
);
223 pf_addr
+= sizeof(u64
);
224 rc
= bnx2x_copy32_vf_dmae(bp
, false, pf_addr
, vf
->abs_vfid
,
229 BNX2X_ERR("Failed to copy response body to VF %d\n",
233 vf_addr
-= sizeof(u64
);
234 pf_addr
-= sizeof(u64
);
238 storm_memset_vf_mbx_ack(bp
, vf
->abs_vfid
);
241 /* initiate dmae to send the response */
242 mbx
->flags
&= ~VF_MSG_INPROCESS
;
244 /* copy the response header including status-done field,
245 * must be last dmae, must be after FW is acked
247 rc
= bnx2x_copy32_vf_dmae(bp
, false, pf_addr
, vf
->abs_vfid
,
252 /* unlock channel mutex */
253 bnx2x_unlock_vf_pf_channel(bp
, vf
, mbx
->first_tlv
.tl
.type
);
256 BNX2X_ERR("Failed to copy response status to VF %d\n",
262 static void bnx2x_vf_mbx_acquire_resp(struct bnx2x
*bp
, struct bnx2x_virtf
*vf
,
263 struct bnx2x_vf_mbx
*mbx
, int vfop_status
)
266 struct pfvf_acquire_resp_tlv
*resp
= &mbx
->msg
->resp
.acquire_resp
;
267 struct pf_vf_resc
*resc
= &resp
->resc
;
268 u8 status
= bnx2x_pfvf_status_codes(vfop_status
);
270 memset(resp
, 0, sizeof(*resp
));
272 /* fill in pfdev info */
273 resp
->pfdev_info
.chip_num
= bp
->common
.chip_id
;
274 resp
->pfdev_info
.db_size
= (1 << BNX2X_DB_SHIFT
);
275 resp
->pfdev_info
.indices_per_sb
= HC_SB_MAX_INDICES_E2
;
276 resp
->pfdev_info
.pf_cap
= (PFVF_CAP_RSS
|
277 /* PFVF_CAP_DHC |*/ PFVF_CAP_TPA
);
278 bnx2x_fill_fw_str(bp
, resp
->pfdev_info
.fw_ver
,
279 sizeof(resp
->pfdev_info
.fw_ver
));
281 if (status
== PFVF_STATUS_NO_RESOURCE
||
282 status
== PFVF_STATUS_SUCCESS
) {
283 /* set resources numbers, if status equals NO_RESOURCE these
284 * are max possible numbers
286 resc
->num_rxqs
= vf_rxq_count(vf
) ? :
287 bnx2x_vf_max_queue_cnt(bp
, vf
);
288 resc
->num_txqs
= vf_txq_count(vf
) ? :
289 bnx2x_vf_max_queue_cnt(bp
, vf
);
290 resc
->num_sbs
= vf_sb_count(vf
);
291 resc
->num_mac_filters
= vf_mac_rules_cnt(vf
);
292 resc
->num_vlan_filters
= vf_vlan_rules_cnt(vf
);
293 resc
->num_mc_filters
= 0;
295 if (status
== PFVF_STATUS_SUCCESS
) {
298 vfq_qzone_id(vf
, vfq_get(vf
, i
));
300 for_each_vf_sb(vf
, i
) {
301 resc
->hw_sbs
[i
].hw_sb_id
= vf_igu_sb(vf
, i
);
302 resc
->hw_sbs
[i
].sb_qid
= vf_hc_qzone(vf
, i
);
307 DP(BNX2X_MSG_IOV
, "VF[%d] ACQUIRE_RESPONSE: pfdev_info- chip_num=0x%x, db_size=%d, idx_per_sb=%d, pf_cap=0x%x\n"
308 "resources- n_rxq-%d, n_txq-%d, n_sbs-%d, n_macs-%d, n_vlans-%d, n_mcs-%d, fw_ver: '%s'\n",
310 resp
->pfdev_info
.chip_num
,
311 resp
->pfdev_info
.db_size
,
312 resp
->pfdev_info
.indices_per_sb
,
313 resp
->pfdev_info
.pf_cap
,
317 resc
->num_mac_filters
,
318 resc
->num_vlan_filters
,
319 resc
->num_mc_filters
,
320 resp
->pfdev_info
.fw_ver
);
322 DP_CONT(BNX2X_MSG_IOV
, "hw_qids- [ ");
323 for (i
= 0; i
< vf_rxq_count(vf
); i
++)
324 DP_CONT(BNX2X_MSG_IOV
, "%d ", resc
->hw_qid
[i
]);
325 DP_CONT(BNX2X_MSG_IOV
, "], sb_info- [ ");
326 for (i
= 0; i
< vf_sb_count(vf
); i
++)
327 DP_CONT(BNX2X_MSG_IOV
, "%d:%d ",
328 resc
->hw_sbs
[i
].hw_sb_id
,
329 resc
->hw_sbs
[i
].sb_qid
);
330 DP_CONT(BNX2X_MSG_IOV
, "]\n");
332 /* send the response */
333 vf
->op_rc
= vfop_status
;
334 bnx2x_vf_mbx_resp(bp
, vf
);
337 static void bnx2x_vf_mbx_acquire(struct bnx2x
*bp
, struct bnx2x_virtf
*vf
,
338 struct bnx2x_vf_mbx
*mbx
)
341 struct vfpf_acquire_tlv
*acquire
= &mbx
->msg
->req
.acquire
;
345 "VF[%d] ACQUIRE: vfdev_info- vf_id %d, vf_os %d resources- n_rxq-%d, n_txq-%d, n_sbs-%d, n_macs-%d, n_vlans-%d, n_mcs-%d\n",
346 vf
->abs_vfid
, acquire
->vfdev_info
.vf_id
, acquire
->vfdev_info
.vf_os
,
347 acquire
->resc_request
.num_rxqs
, acquire
->resc_request
.num_txqs
,
348 acquire
->resc_request
.num_sbs
, acquire
->resc_request
.num_mac_filters
,
349 acquire
->resc_request
.num_vlan_filters
,
350 acquire
->resc_request
.num_mc_filters
);
352 /* acquire the resources */
353 rc
= bnx2x_vf_acquire(bp
, vf
, &acquire
->resc_request
);
356 bnx2x_vf_mbx_acquire_resp(bp
, vf
, mbx
, rc
);
359 static void bnx2x_vf_mbx_init_vf(struct bnx2x
*bp
, struct bnx2x_virtf
*vf
,
360 struct bnx2x_vf_mbx
*mbx
)
362 struct vfpf_init_tlv
*init
= &mbx
->msg
->req
.init
;
364 /* record ghost addresses from vf message */
365 vf
->spq_map
= init
->spq_addr
;
366 vf
->fw_stat_map
= init
->stats_addr
;
367 vf
->op_rc
= bnx2x_vf_init(bp
, vf
, (dma_addr_t
*)init
->sb_addr
);
370 bnx2x_vf_mbx_resp(bp
, vf
);
373 /* dispatch request */
374 static void bnx2x_vf_mbx_request(struct bnx2x
*bp
, struct bnx2x_virtf
*vf
,
375 struct bnx2x_vf_mbx
*mbx
)
379 /* check if tlv type is known */
380 if (bnx2x_tlv_supported(mbx
->first_tlv
.tl
.type
)) {
381 /* Lock the per vf op mutex and note the locker's identity.
382 * The unlock will take place in mbx response.
384 bnx2x_lock_vf_pf_channel(bp
, vf
, mbx
->first_tlv
.tl
.type
);
386 /* switch on the opcode */
387 switch (mbx
->first_tlv
.tl
.type
) {
388 case CHANNEL_TLV_ACQUIRE
:
389 bnx2x_vf_mbx_acquire(bp
, vf
, mbx
);
391 case CHANNEL_TLV_INIT
:
392 bnx2x_vf_mbx_init_vf(bp
, vf
, mbx
);
396 /* unknown TLV - this may belong to a VF driver from the future
397 * - a version written after this PF driver was written, which
398 * supports features unknown as of yet. Too bad since we don't
399 * support them. Or this may be because someone wrote a crappy
400 * VF driver and is sending garbage over the channel.
402 BNX2X_ERR("unknown TLV. type %d length %d. first 20 bytes of mailbox buffer:\n",
403 mbx
->first_tlv
.tl
.type
, mbx
->first_tlv
.tl
.length
);
404 for (i
= 0; i
< 20; i
++)
405 DP_CONT(BNX2X_MSG_IOV
, "%x ",
406 mbx
->msg
->req
.tlv_buf_size
.tlv_buffer
[i
]);
408 /* test whether we can respond to the VF (do we have an address
411 if (vf
->state
== VF_ACQUIRED
) {
412 /* mbx_resp uses the op_rc of the VF */
413 vf
->op_rc
= PFVF_STATUS_NOT_SUPPORTED
;
415 /* notify the VF that we do not support this request */
416 bnx2x_vf_mbx_resp(bp
, vf
);
418 /* can't send a response since this VF is unknown to us
419 * just unlock the channel and be done with.
421 bnx2x_unlock_vf_pf_channel(bp
, vf
,
422 mbx
->first_tlv
.tl
.type
);
427 /* handle new vf-pf message */
428 void bnx2x_vf_mbx(struct bnx2x
*bp
, struct vf_pf_event_data
*vfpf_event
)
430 struct bnx2x_virtf
*vf
;
431 struct bnx2x_vf_mbx
*mbx
;
436 "vf pf event received: vfid %d, address_hi %x, address lo %x",
437 vfpf_event
->vf_id
, vfpf_event
->msg_addr_hi
, vfpf_event
->msg_addr_lo
);
438 /* Sanity checks consider removing later */
440 /* check if the vf_id is valid */
441 if (vfpf_event
->vf_id
- BP_VFDB(bp
)->sriov
.first_vf_in_pf
>
442 BNX2X_NR_VIRTFN(bp
)) {
443 BNX2X_ERR("Illegal vf_id %d max allowed: %d\n",
444 vfpf_event
->vf_id
, BNX2X_NR_VIRTFN(bp
));
447 vf_idx
= bnx2x_vf_idx_by_abs_fid(bp
, vfpf_event
->vf_id
);
448 mbx
= BP_VF_MBX(bp
, vf_idx
);
450 /* verify an event is not currently being processed -
451 * debug failsafe only
453 if (mbx
->flags
& VF_MSG_INPROCESS
) {
454 BNX2X_ERR("Previous message is still being processed, vf_id %d\n",
458 vf
= BP_VF(bp
, vf_idx
);
460 /* save the VF message address */
461 mbx
->vf_addr_hi
= vfpf_event
->msg_addr_hi
;
462 mbx
->vf_addr_lo
= vfpf_event
->msg_addr_lo
;
463 DP(BNX2X_MSG_IOV
, "mailbox vf address hi 0x%x, lo 0x%x, offset 0x%x\n",
464 mbx
->vf_addr_hi
, mbx
->vf_addr_lo
, mbx
->first_tlv
.resp_msg_offset
);
466 /* dmae to get the VF request */
467 rc
= bnx2x_copy32_vf_dmae(bp
, true, mbx
->msg_mapping
, vf
->abs_vfid
,
468 mbx
->vf_addr_hi
, mbx
->vf_addr_lo
,
469 sizeof(union vfpf_tlvs
)/4);
471 BNX2X_ERR("Failed to copy request VF %d\n", vf
->abs_vfid
);
475 /* process the VF message header */
476 mbx
->first_tlv
= mbx
->msg
->req
.first_tlv
;
478 /* dispatch the request (will prepare the response) */
479 bnx2x_vf_mbx_request(bp
, vf
, mbx
);