aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
diff options
context:
space:
mode:
authorYuval Mintz <yuvalmin@broadcom.com>2013-10-09 10:06:28 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-09 14:55:13 -0400
commit3d7d562ca4a884089344eb13451b5903a18d3817 (patch)
tree5d3f9cc7175ed152d6451b438cc7975df594afa3 /drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
parentc2bb06db59eaf92eb5ca9c6faed590597c6ceccb (diff)
bnx2x: Add ndo_get_phys_port_id support
Each network interface (either PF or VF) is identified by its port's MAC id. Signed-off-by: Yuval Mintz <yuvalmin@broadcom.com> 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.c149
1 files changed, 122 insertions, 27 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
index da16953eb2ec..58dc89af7c6a 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c
@@ -60,6 +60,30 @@ void bnx2x_vfpf_finalize(struct bnx2x *bp, struct vfpf_first_tlv *first_tlv)
60 mutex_unlock(&bp->vf2pf_mutex); 60 mutex_unlock(&bp->vf2pf_mutex);
61} 61}
62 62
63/* Finds a TLV by type in a TLV buffer; If found, returns pointer to the TLV */
64static void *bnx2x_search_tlv_list(struct bnx2x *bp, void *tlvs_list,
65 enum channel_tlvs req_tlv)
66{
67 struct channel_tlv *tlv = (struct channel_tlv *)tlvs_list;
68
69 do {
70 if (tlv->type == req_tlv)
71 return tlv;
72
73 if (!tlv->length) {
74 BNX2X_ERR("Found TLV with length 0\n");
75 return NULL;
76 }
77
78 tlvs_list += tlv->length;
79 tlv = (struct channel_tlv *)tlvs_list;
80 } while (tlv->type != CHANNEL_TLV_LIST_END);
81
82 DP(BNX2X_MSG_IOV, "TLV list does not contain %d TLV\n", req_tlv);
83
84 return NULL;
85}
86
63/* list the types and lengths of the tlvs on the buffer */ 87/* list the types and lengths of the tlvs on the buffer */
64void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list) 88void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list)
65{ 89{
@@ -196,6 +220,7 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
196 int rc = 0, attempts = 0; 220 int rc = 0, attempts = 0;
197 struct vfpf_acquire_tlv *req = &bp->vf2pf_mbox->req.acquire; 221 struct vfpf_acquire_tlv *req = &bp->vf2pf_mbox->req.acquire;
198 struct pfvf_acquire_resp_tlv *resp = &bp->vf2pf_mbox->resp.acquire_resp; 222 struct pfvf_acquire_resp_tlv *resp = &bp->vf2pf_mbox->resp.acquire_resp;
223 struct vfpf_port_phys_id_resp_tlv *phys_port_resp;
199 u32 vf_id; 224 u32 vf_id;
200 bool resources_acquired = false; 225 bool resources_acquired = false;
201 226
@@ -219,8 +244,14 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
219 /* pf 2 vf bulletin board address */ 244 /* pf 2 vf bulletin board address */
220 req->bulletin_addr = bp->pf2vf_bulletin_mapping; 245 req->bulletin_addr = bp->pf2vf_bulletin_mapping;
221 246
247 /* Request physical port identifier */
248 bnx2x_add_tlv(bp, req, req->first_tlv.tl.length,
249 CHANNEL_TLV_PHYS_PORT_ID, sizeof(struct channel_tlv));
250
222 /* add list termination tlv */ 251 /* add list termination tlv */
223 bnx2x_add_tlv(bp, req, req->first_tlv.tl.length, CHANNEL_TLV_LIST_END, 252 bnx2x_add_tlv(bp, req,
253 req->first_tlv.tl.length + sizeof(struct channel_tlv),
254 CHANNEL_TLV_LIST_END,
224 sizeof(struct channel_list_end_tlv)); 255 sizeof(struct channel_list_end_tlv));
225 256
226 /* output tlvs list */ 257 /* output tlvs list */
@@ -287,6 +318,15 @@ int bnx2x_vfpf_acquire(struct bnx2x *bp, u8 tx_count, u8 rx_count)
287 } 318 }
288 } 319 }
289 320
321 /* Retrieve physical port id (if possible) */
322 phys_port_resp = (struct vfpf_port_phys_id_resp_tlv *)
323 bnx2x_search_tlv_list(bp, resp,
324 CHANNEL_TLV_PHYS_PORT_ID);
325 if (phys_port_resp) {
326 memcpy(bp->phys_port_id, phys_port_resp->id, ETH_ALEN);
327 bp->flags |= HAS_PHYS_PORT_ID;
328 }
329
290 /* get HW info */ 330 /* get HW info */
291 bp->common.chip_id |= (bp->acquire_resp.pfdev_info.chip_num & 0xffff); 331 bp->common.chip_id |= (bp->acquire_resp.pfdev_info.chip_num & 0xffff);
292 bp->link_params.chip_id = bp->common.chip_id; 332 bp->link_params.chip_id = bp->common.chip_id;
@@ -983,53 +1023,59 @@ static int bnx2x_copy32_vf_dmae(struct bnx2x *bp, u8 from_vf,
983 return bnx2x_issue_dmae_with_comp(bp, &dmae); 1023 return bnx2x_issue_dmae_with_comp(bp, &dmae);
984} 1024}
985 1025
986static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf) 1026static void bnx2x_vf_mbx_resp_single_tlv(struct bnx2x *bp,
1027 struct bnx2x_virtf *vf)
987{ 1028{
988 struct bnx2x_vf_mbx *mbx = BP_VF_MBX(bp, vf->index); 1029 struct bnx2x_vf_mbx *mbx = BP_VF_MBX(bp, vf->index);
989 u64 vf_addr;
990 dma_addr_t pf_addr;
991 u16 length, type; 1030 u16 length, type;
992 int rc;
993 struct pfvf_general_resp_tlv *resp = &mbx->msg->resp.general_resp;
994 1031
995 /* prepare response */ 1032 /* prepare response */
996 type = mbx->first_tlv.tl.type; 1033 type = mbx->first_tlv.tl.type;
997 length = type == CHANNEL_TLV_ACQUIRE ? 1034 length = type == CHANNEL_TLV_ACQUIRE ?
998 sizeof(struct pfvf_acquire_resp_tlv) : 1035 sizeof(struct pfvf_acquire_resp_tlv) :
999 sizeof(struct pfvf_general_resp_tlv); 1036 sizeof(struct pfvf_general_resp_tlv);
1000 bnx2x_add_tlv(bp, resp, 0, type, length); 1037 bnx2x_add_tlv(bp, &mbx->msg->resp, 0, type, length);
1001 resp->hdr.status = bnx2x_pfvf_status_codes(vf->op_rc); 1038 bnx2x_add_tlv(bp, &mbx->msg->resp, length, CHANNEL_TLV_LIST_END,
1002 bnx2x_add_tlv(bp, resp, length, CHANNEL_TLV_LIST_END,
1003 sizeof(struct channel_list_end_tlv)); 1039 sizeof(struct channel_list_end_tlv));
1040}
1041
1042static void bnx2x_vf_mbx_resp_send_msg(struct bnx2x *bp,
1043 struct bnx2x_virtf *vf)
1044{
1045 struct bnx2x_vf_mbx *mbx = BP_VF_MBX(bp, vf->index);
1046 struct pfvf_general_resp_tlv *resp = &mbx->msg->resp.general_resp;
1047 dma_addr_t pf_addr;
1048 u64 vf_addr;
1049 int rc;
1050
1004 bnx2x_dp_tlv_list(bp, resp); 1051 bnx2x_dp_tlv_list(bp, resp);
1005 DP(BNX2X_MSG_IOV, "mailbox vf address hi 0x%x, lo 0x%x, offset 0x%x\n", 1052 DP(BNX2X_MSG_IOV, "mailbox vf address hi 0x%x, lo 0x%x, offset 0x%x\n",
1006 mbx->vf_addr_hi, mbx->vf_addr_lo, mbx->first_tlv.resp_msg_offset); 1053 mbx->vf_addr_hi, mbx->vf_addr_lo, mbx->first_tlv.resp_msg_offset);
1007 1054
1055 resp->hdr.status = bnx2x_pfvf_status_codes(vf->op_rc);
1056
1008 /* send response */ 1057 /* send response */
1009 vf_addr = HILO_U64(mbx->vf_addr_hi, mbx->vf_addr_lo) + 1058 vf_addr = HILO_U64(mbx->vf_addr_hi, mbx->vf_addr_lo) +
1010 mbx->first_tlv.resp_msg_offset; 1059 mbx->first_tlv.resp_msg_offset;
1011 pf_addr = mbx->msg_mapping + 1060 pf_addr = mbx->msg_mapping +
1012 offsetof(struct bnx2x_vf_mbx_msg, resp); 1061 offsetof(struct bnx2x_vf_mbx_msg, resp);
1013 1062
1014 /* copy the response body, if there is one, before the header, as the vf 1063 /* Copy the response buffer. The first u64 is written afterwards, as
1015 * is sensitive to the header being written 1064 * the vf is sensitive to the header being written
1016 */ 1065 */
1017 if (resp->hdr.tl.length > sizeof(u64)) { 1066 vf_addr += sizeof(u64);
1018 length = resp->hdr.tl.length - sizeof(u64); 1067 pf_addr += sizeof(u64);
1019 vf_addr += sizeof(u64); 1068 rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr, vf->abs_vfid,
1020 pf_addr += sizeof(u64); 1069 U64_HI(vf_addr),
1021 rc = bnx2x_copy32_vf_dmae(bp, false, pf_addr, vf->abs_vfid, 1070 U64_LO(vf_addr),
1022 U64_HI(vf_addr), 1071 (sizeof(union pfvf_tlvs) - sizeof(u64))/4);
1023 U64_LO(vf_addr), 1072 if (rc) {
1024 length/4); 1073 BNX2X_ERR("Failed to copy response body to VF %d\n",
1025 if (rc) { 1074 vf->abs_vfid);
1026 BNX2X_ERR("Failed to copy response body to VF %d\n", 1075 goto mbx_error;
1027 vf->abs_vfid);
1028 goto mbx_error;
1029 }
1030 vf_addr -= sizeof(u64);
1031 pf_addr -= sizeof(u64);
1032 } 1076 }
1077 vf_addr -= sizeof(u64);
1078 pf_addr -= sizeof(u64);
1033 1079
1034 /* ack the FW */ 1080 /* ack the FW */
1035 storm_memset_vf_mbx_ack(bp, vf->abs_vfid); 1081 storm_memset_vf_mbx_ack(bp, vf->abs_vfid);
@@ -1060,6 +1106,36 @@ mbx_error:
1060 bnx2x_vf_release(bp, vf, false); /* non blocking */ 1106 bnx2x_vf_release(bp, vf, false); /* non blocking */
1061} 1107}
1062 1108
1109static void bnx2x_vf_mbx_resp(struct bnx2x *bp,
1110 struct bnx2x_virtf *vf)
1111{
1112 bnx2x_vf_mbx_resp_single_tlv(bp, vf);
1113 bnx2x_vf_mbx_resp_send_msg(bp, vf);
1114}
1115
1116static void bnx2x_vf_mbx_resp_phys_port(struct bnx2x *bp,
1117 struct bnx2x_virtf *vf,
1118 void *buffer,
1119 u16 *offset)
1120{
1121 struct vfpf_port_phys_id_resp_tlv *port_id;
1122
1123 if (!(bp->flags & HAS_PHYS_PORT_ID))
1124 return;
1125
1126 bnx2x_add_tlv(bp, buffer, *offset, CHANNEL_TLV_PHYS_PORT_ID,
1127 sizeof(struct vfpf_port_phys_id_resp_tlv));
1128
1129 port_id = (struct vfpf_port_phys_id_resp_tlv *)
1130 (((u8 *)buffer) + *offset);
1131 memcpy(port_id->id, bp->phys_port_id, ETH_ALEN);
1132
1133 /* Offset should continue representing the offset to the tail
1134 * of TLV data (outside this function scope)
1135 */
1136 *offset += sizeof(struct vfpf_port_phys_id_resp_tlv);
1137}
1138
1063static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, 1139static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
1064 struct bnx2x_vf_mbx *mbx, int vfop_status) 1140 struct bnx2x_vf_mbx *mbx, int vfop_status)
1065{ 1141{
@@ -1067,6 +1143,7 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
1067 struct pfvf_acquire_resp_tlv *resp = &mbx->msg->resp.acquire_resp; 1143 struct pfvf_acquire_resp_tlv *resp = &mbx->msg->resp.acquire_resp;
1068 struct pf_vf_resc *resc = &resp->resc; 1144 struct pf_vf_resc *resc = &resp->resc;
1069 u8 status = bnx2x_pfvf_status_codes(vfop_status); 1145 u8 status = bnx2x_pfvf_status_codes(vfop_status);
1146 u16 length;
1070 1147
1071 memset(resp, 0, sizeof(*resp)); 1148 memset(resp, 0, sizeof(*resp));
1072 1149
@@ -1140,9 +1217,24 @@ static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf,
1140 resc->hw_sbs[i].sb_qid); 1217 resc->hw_sbs[i].sb_qid);
1141 DP_CONT(BNX2X_MSG_IOV, "]\n"); 1218 DP_CONT(BNX2X_MSG_IOV, "]\n");
1142 1219
1220 /* prepare response */
1221 length = sizeof(struct pfvf_acquire_resp_tlv);
1222 bnx2x_add_tlv(bp, &mbx->msg->resp, 0, CHANNEL_TLV_ACQUIRE, length);
1223
1224 /* Handle possible VF requests for physical port identifiers.
1225 * 'length' should continue to indicate the offset of the first empty
1226 * place in the buffer (i.e., where next TLV should be inserted)
1227 */
1228 if (bnx2x_search_tlv_list(bp, &mbx->msg->req,
1229 CHANNEL_TLV_PHYS_PORT_ID))
1230 bnx2x_vf_mbx_resp_phys_port(bp, vf, &mbx->msg->resp, &length);
1231
1232 bnx2x_add_tlv(bp, &mbx->msg->resp, length, CHANNEL_TLV_LIST_END,
1233 sizeof(struct channel_list_end_tlv));
1234
1143 /* send the response */ 1235 /* send the response */
1144 vf->op_rc = vfop_status; 1236 vf->op_rc = vfop_status;
1145 bnx2x_vf_mbx_resp(bp, vf); 1237 bnx2x_vf_mbx_resp_send_msg(bp, vf);
1146} 1238}
1147 1239
1148static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf, 1240static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf,
@@ -1874,6 +1966,9 @@ void bnx2x_vf_mbx(struct bnx2x *bp, struct vf_pf_event_data *vfpf_event)
1874 /* process the VF message header */ 1966 /* process the VF message header */
1875 mbx->first_tlv = mbx->msg->req.first_tlv; 1967 mbx->first_tlv = mbx->msg->req.first_tlv;
1876 1968
1969 /* Clean response buffer to refrain from falsely seeing chains */
1970 memset(&mbx->msg->resp, 0, sizeof(union pfvf_tlvs));
1971
1877 /* dispatch the request (will prepare the response) */ 1972 /* dispatch the request (will prepare the response) */
1878 bnx2x_vf_mbx_request(bp, vf, mbx); 1973 bnx2x_vf_mbx_request(bp, vf, mbx);
1879 goto mbx_done; 1974 goto mbx_done;