aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
diff options
context:
space:
mode:
authorAriel Elior <ariele@broadcom.com>2013-01-01 00:22:33 -0500
committerDavid S. Miller <davem@davemloft.net>2013-01-02 04:45:06 -0500
commitfd1fc79dd6deb88ebf38ae9673190da999b3209f (patch)
tree0e9ff0dda51c3f200b7d40609532f16c8d0f2a90 /drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
parentb56e9670ffa4de1a3cf0ca2f89ff5e2e0c31a1f7 (diff)
bnx2x: Infrastructure for VF <-> PF request on PF side
Support interrupt from device which indicates VF has placed A request on the VF <-> PF channel. The PF driver issues a DMAE to retrieve the request from the VM memory (the Ghost Physical Address of the request is contained in the interrupt. The PF driver uses the GPA in the DMAE request, which is translated by the IOMMU to the correct physical address). The request which arrives is examined to recognize the sending VF. The PF driver allocates a workitem to handle the VF Operation (vfop). Signed-off-by: Ariel Elior <ariele@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c154
1 files changed, 154 insertions, 0 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index d1a8644200d9..6e5e0638ee81 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -79,6 +79,24 @@ void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list)
79 tlv->type, tlv->length); 79 tlv->type, tlv->length);
80} 80}
81 81
82/* test whether we support a tlv type */
83bool bnx2x_tlv_supported(u16 tlvtype)
84{
85 return CHANNEL_TLV_NONE < tlvtype && tlvtype < CHANNEL_TLV_MAX;
86}
87
88static inline int bnx2x_pfvf_status_codes(int rc)
89{
90 switch (rc) {
91 case 0:
92 return PFVF_STATUS_SUCCESS;
93 case -ENOMEM:
94 return PFVF_STATUS_NO_RESOURCE;
95 default:
96 return PFVF_STATUS_FAILURE;
97 }
98}
99
82/* General service functions */ 100/* General service functions */
83static void storm_memset_vf_mbx_ack(struct bnx2x *bp, u16 abs_fid) 101static void storm_memset_vf_mbx_ack(struct bnx2x *bp, u16 abs_fid)
84{ 102{
@@ -116,3 +134,139 @@ void bnx2x_vf_enable_mbx(struct bnx2x *bp, u8 abs_vfid)
116 /* enable the VF access to the mailbox */ 134 /* enable the VF access to the mailbox */
117 bnx2x_vf_enable_access(bp, abs_vfid); 135 bnx2x_vf_enable_access(bp, abs_vfid);
118} 136}
137
138/* this works only on !E1h */
139static int bnx2x_copy32_vf_dmae(struct bnx2x *bp, u8 from_vf,
140 dma_addr_t pf_addr, u8 vfid, u32 vf_addr_hi,
141 u32 vf_addr_lo, u32 len32)
142{
143 struct dmae_command dmae;
144
145 if (CHIP_IS_E1x(bp)) {
146 BNX2X_ERR("Chip revision does not support VFs\n");
147 return DMAE_NOT_RDY;
148 }
149
150 if (!bp->dmae_ready) {
151 BNX2X_ERR("DMAE is not ready, can not copy\n");
152 return DMAE_NOT_RDY;
153 }
154
155 /* set opcode and fixed command fields */
156 bnx2x_prep_dmae_with_comp(bp, &dmae, DMAE_SRC_PCI, DMAE_DST_PCI);
157
158 if (from_vf) {
159 dmae.opcode_iov = (vfid << DMAE_COMMAND_SRC_VFID_SHIFT) |
160 (DMAE_SRC_VF << DMAE_COMMAND_SRC_VFPF_SHIFT) |
161 (DMAE_DST_PF << DMAE_COMMAND_DST_VFPF_SHIFT);
162
163 dmae.opcode |= (DMAE_C_DST << DMAE_COMMAND_C_FUNC_SHIFT);
164
165 dmae.src_addr_lo = vf_addr_lo;
166 dmae.src_addr_hi = vf_addr_hi;
167 dmae.dst_addr_lo = U64_LO(pf_addr);
168 dmae.dst_addr_hi = U64_HI(pf_addr);
169 } else {
170 dmae.opcode_iov = (vfid << DMAE_COMMAND_DST_VFID_SHIFT) |
171 (DMAE_DST_VF << DMAE_COMMAND_DST_VFPF_SHIFT) |
172 (DMAE_SRC_PF << DMAE_COMMAND_SRC_VFPF_SHIFT);
173
174 dmae.opcode |= (DMAE_C_SRC << DMAE_COMMAND_C_FUNC_SHIFT);
175
176 dmae.src_addr_lo = U64_LO(pf_addr);
177 dmae.src_addr_hi = U64_HI(pf_addr);
178 dmae.dst_addr_lo = vf_addr_lo;
179 dmae.dst_addr_hi = vf_addr_hi;
180 }
181 dmae.len = len32;
182 bnx2x_dp_dmae(bp, &dmae, BNX2X_MSG_DMAE);
183
184 /* issue the command and wait for completion */
185 return bnx2x_issue_dmae_with_comp(bp, &dmae);
186}
187
188/* dispatch request */
189static void bnx2x_vf_mbx_request(struct bnx2x *bp, struct bnx2x_virtf *vf,
190 struct bnx2x_vf_mbx *mbx)
191{
192 int i;
193
194 /* check if tlv type is known */
195 if (bnx2x_tlv_supported(mbx->first_tlv.tl.type)) {
196 /* switch on the opcode */
197 switch (mbx->first_tlv.tl.type) {
198 }
199 } else {
200 /* unknown TLV - this may belong to a VF driver from the future
201 * - a version written after this PF driver was written, which
202 * supports features unknown as of yet. Too bad since we don't
203 * support them. Or this may be because someone wrote a crappy
204 * VF driver and is sending garbage over the channel.
205 */
206 BNX2X_ERR("unknown TLV. type %d length %d. first 20 bytes of mailbox buffer:\n",
207 mbx->first_tlv.tl.type, mbx->first_tlv.tl.length);
208 for (i = 0; i < 20; i++)
209 DP_CONT(BNX2X_MSG_IOV, "%x ",
210 mbx->msg->req.tlv_buf_size.tlv_buffer[i]);
211 }
212}
213
214/* handle new vf-pf message */
215void bnx2x_vf_mbx(struct bnx2x *bp, struct vf_pf_event_data *vfpf_event)
216{
217 struct bnx2x_virtf *vf;
218 struct bnx2x_vf_mbx *mbx;
219 u8 vf_idx;
220 int rc;
221
222 DP(BNX2X_MSG_IOV,
223 "vf pf event received: vfid %d, address_hi %x, address lo %x",
224 vfpf_event->vf_id, vfpf_event->msg_addr_hi, vfpf_event->msg_addr_lo);
225 /* Sanity checks consider removing later */
226
227 /* check if the vf_id is valid */
228 if (vfpf_event->vf_id - BP_VFDB(bp)->sriov.first_vf_in_pf >
229 BNX2X_NR_VIRTFN(bp)) {
230 BNX2X_ERR("Illegal vf_id %d max allowed: %d\n",
231 vfpf_event->vf_id, BNX2X_NR_VIRTFN(bp));
232 goto mbx_done;
233 }
234 vf_idx = bnx2x_vf_idx_by_abs_fid(bp, vfpf_event->vf_id);
235 mbx = BP_VF_MBX(bp, vf_idx);
236
237 /* verify an event is not currently being processed -
238 * debug failsafe only
239 */
240 if (mbx->flags & VF_MSG_INPROCESS) {
241 BNX2X_ERR("Previous message is still being processed, vf_id %d\n",
242 vfpf_event->vf_id);
243 goto mbx_done;
244 }
245 vf = BP_VF(bp, vf_idx);
246
247 /* save the VF message address */
248 mbx->vf_addr_hi = vfpf_event->msg_addr_hi;
249 mbx->vf_addr_lo = vfpf_event->msg_addr_lo;
250 DP(BNX2X_MSG_IOV, "mailbox vf address hi 0x%x, lo 0x%x, offset 0x%x\n",
251 mbx->vf_addr_hi, mbx->vf_addr_lo, mbx->first_tlv.resp_msg_offset);
252
253 /* dmae to get the VF request */
254 rc = bnx2x_copy32_vf_dmae(bp, true, mbx->msg_mapping, vf->abs_vfid,
255 mbx->vf_addr_hi, mbx->vf_addr_lo,
256 sizeof(union vfpf_tlvs)/4);
257 if (rc) {
258 BNX2X_ERR("Failed to copy request VF %d\n", vf->abs_vfid);
259 goto mbx_error;
260 }
261
262 /* process the VF message header */
263 mbx->first_tlv = mbx->msg->req.first_tlv;
264
265 /* dispatch the request (will prepare the response) */
266 bnx2x_vf_mbx_request(bp, vf, mbx);
267 goto mbx_done;
268
269mbx_error:
270mbx_done:
271 return;
272}