5ac197ea7f285c5521b4c3a48ccacb21f7823c12
[dpdk.git] / drivers / net / bnxt / bnxt_cpr.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2014-2018 Broadcom
3  * All rights reserved.
4  */
5
6 #include <rte_malloc.h>
7
8 #include "bnxt.h"
9 #include "bnxt_cpr.h"
10 #include "bnxt_hwrm.h"
11 #include "bnxt_ring.h"
12 #include "hsi_struct_def_dpdk.h"
13
14 /*
15  * Async event handling
16  */
17 void bnxt_handle_async_event(struct bnxt *bp,
18                              struct cmpl_base *cmp)
19 {
20         struct hwrm_async_event_cmpl *async_cmp =
21                                 (struct hwrm_async_event_cmpl *)cmp;
22         uint16_t event_id = rte_le_to_cpu_16(async_cmp->event_id);
23
24         /* TODO: HWRM async events are not defined yet */
25         /* Needs to handle: link events, error events, etc. */
26         switch (event_id) {
27         case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_STATUS_CHANGE:
28         case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CHANGE:
29         case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_LINK_SPEED_CFG_CHANGE:
30                 bnxt_link_update_op(bp->eth_dev, 1);
31                 break;
32         case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PF_DRVR_UNLOAD:
33                 PMD_DRV_LOG(INFO, "Async event: PF driver unloaded\n");
34                 break;
35         case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_VF_CFG_CHANGE:
36                 PMD_DRV_LOG(INFO, "Async event: VF config changed\n");
37                 break;
38         case HWRM_ASYNC_EVENT_CMPL_EVENT_ID_PORT_CONN_NOT_ALLOWED:
39                 PMD_DRV_LOG(INFO, "Port conn async event\n");
40                 break;
41         default:
42                 PMD_DRV_LOG(INFO, "handle_async_event id = 0x%x\n", event_id);
43                 break;
44         }
45 }
46
47 void bnxt_handle_fwd_req(struct bnxt *bp, struct cmpl_base *cmpl)
48 {
49         struct hwrm_exec_fwd_resp_input *fwreq;
50         struct hwrm_fwd_req_cmpl *fwd_cmpl = (struct hwrm_fwd_req_cmpl *)cmpl;
51         struct input *fwd_cmd;
52         uint16_t fw_vf_id;
53         uint16_t vf_id;
54         uint16_t req_len;
55         int rc;
56
57         if (bp->pf.active_vfs <= 0) {
58                 PMD_DRV_LOG(ERR, "Forwarded VF with no active VFs\n");
59                 return;
60         }
61
62         /* Qualify the fwd request */
63         fw_vf_id = rte_le_to_cpu_16(fwd_cmpl->source_id);
64         vf_id = fw_vf_id - bp->pf.first_vf_id;
65
66         req_len = (rte_le_to_cpu_16(fwd_cmpl->req_len_type) &
67                    HWRM_FWD_REQ_CMPL_REQ_LEN_MASK) >>
68                 HWRM_FWD_REQ_CMPL_REQ_LEN_SFT;
69         if (req_len > sizeof(fwreq->encap_request))
70                 req_len = sizeof(fwreq->encap_request);
71
72         /* Locate VF's forwarded command */
73         fwd_cmd = (struct input *)bp->pf.vf_info[vf_id].req_buf;
74
75         if (fw_vf_id < bp->pf.first_vf_id ||
76             fw_vf_id >= (bp->pf.first_vf_id) + bp->pf.active_vfs) {
77                 PMD_DRV_LOG(ERR,
78                 "FWD req's source_id 0x%x out of range 0x%x - 0x%x (%d %d)\n",
79                         fw_vf_id, bp->pf.first_vf_id,
80                         (bp->pf.first_vf_id) + bp->pf.active_vfs - 1,
81                         bp->pf.first_vf_id, bp->pf.active_vfs);
82                 goto reject;
83         }
84
85         if (bnxt_rcv_msg_from_vf(bp, vf_id, fwd_cmd) == true) {
86                 /*
87                  * In older firmware versions, the MAC had to be all zeros for
88                  * the VF to set it's MAC via hwrm_func_vf_cfg. Set to all
89                  * zeros if it's being configured and has been ok'd by caller.
90                  */
91                 if (fwd_cmd->req_type == HWRM_FUNC_VF_CFG) {
92                         struct hwrm_func_vf_cfg_input *vfc = (void *)fwd_cmd;
93
94                         if (vfc->enables &
95                             HWRM_FUNC_VF_CFG_INPUT_ENABLES_DFLT_MAC_ADDR) {
96                                 bnxt_hwrm_func_vf_mac(bp, vf_id,
97                                 (const uint8_t *)"\x00\x00\x00\x00\x00");
98                         }
99                 }
100                 if (fwd_cmd->req_type == HWRM_CFA_L2_SET_RX_MASK) {
101                         struct hwrm_cfa_l2_set_rx_mask_input *srm =
102                                                         (void *)fwd_cmd;
103
104                         srm->vlan_tag_tbl_addr = rte_cpu_to_le_64(0);
105                         srm->num_vlan_tags = rte_cpu_to_le_32(0);
106                         srm->mask &= ~rte_cpu_to_le_32(
107                                 HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLANONLY |
108                             HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_VLAN_NONVLAN |
109                             HWRM_CFA_L2_SET_RX_MASK_INPUT_MASK_ANYVLAN_NONVLAN);
110                 }
111                 /* Forward */
112                 rc = bnxt_hwrm_exec_fwd_resp(bp, fw_vf_id, fwd_cmd, req_len);
113                 if (rc) {
114                         PMD_DRV_LOG(ERR,
115                                 "Failed to send FWD req VF 0x%x, type 0x%x.\n",
116                                 fw_vf_id - bp->pf.first_vf_id,
117                                 rte_le_to_cpu_16(fwd_cmd->req_type));
118                 }
119                 return;
120         }
121
122 reject:
123         rc = bnxt_hwrm_reject_fwd_resp(bp, fw_vf_id, fwd_cmd, req_len);
124         if (rc) {
125                 PMD_DRV_LOG(ERR,
126                         "Failed to send REJECT req VF 0x%x, type 0x%x.\n",
127                         fw_vf_id - bp->pf.first_vf_id,
128                         rte_le_to_cpu_16(fwd_cmd->req_type));
129         }
130
131         return;
132 }
133
134 /* For the default completion ring only */
135 int bnxt_alloc_def_cp_ring(struct bnxt *bp)
136 {
137         struct bnxt_cp_ring_info *cpr = bp->def_cp_ring;
138         struct bnxt_ring *cp_ring = cpr->cp_ring_struct;
139         int rc;
140
141         rc = bnxt_hwrm_ring_alloc(bp, cp_ring,
142                                   HWRM_RING_ALLOC_INPUT_RING_TYPE_L2_CMPL,
143                                   0, HWRM_NA_SIGNATURE,
144                                   HWRM_NA_SIGNATURE);
145         if (rc)
146                 goto err_out;
147         cpr->cp_doorbell = bp->pdev->mem_resource[2].addr;
148         B_CP_DIS_DB(cpr, cpr->cp_raw_cons);
149         if (BNXT_PF(bp))
150                 rc = bnxt_hwrm_func_cfg_def_cp(bp);
151         else
152                 rc = bnxt_hwrm_vf_func_cfg_def_cp(bp);
153
154 err_out:
155         return rc;
156 }
157
158 void bnxt_free_def_cp_ring(struct bnxt *bp)
159 {
160         struct bnxt_cp_ring_info *cpr = bp->def_cp_ring;
161
162         if (cpr == NULL)
163                 return;
164
165         bnxt_free_ring(cpr->cp_ring_struct);
166         cpr->cp_ring_struct = NULL;
167         rte_free(cpr->cp_ring_struct);
168         rte_free(cpr);
169         bp->def_cp_ring = NULL;
170 }
171
172 /* For the default completion ring only */
173 int bnxt_init_def_ring_struct(struct bnxt *bp, unsigned int socket_id)
174 {
175         struct bnxt_cp_ring_info *cpr;
176         struct bnxt_ring *ring;
177
178         cpr = rte_zmalloc_socket("cpr",
179                                  sizeof(struct bnxt_cp_ring_info),
180                                  RTE_CACHE_LINE_SIZE, socket_id);
181         if (cpr == NULL)
182                 return -ENOMEM;
183         bp->def_cp_ring = cpr;
184
185         ring = rte_zmalloc_socket("bnxt_cp_ring_struct",
186                                   sizeof(struct bnxt_ring),
187                                   RTE_CACHE_LINE_SIZE, socket_id);
188         if (ring == NULL)
189                 return -ENOMEM;
190         cpr->cp_ring_struct = ring;
191         ring->bd = (void *)cpr->cp_desc_ring;
192         ring->bd_dma = cpr->cp_desc_mapping;
193         ring->ring_size = rte_align32pow2(DEFAULT_CP_RING_SIZE);
194         ring->ring_mask = ring->ring_size - 1;
195         ring->vmem_size = 0;
196         ring->vmem = NULL;
197
198         return 0;
199 }