diff options
author | Yuval Mintz <yuvalmin@broadcom.com> | 2013-10-09 10:06:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-09 14:55:13 -0400 |
commit | 3d7d562ca4a884089344eb13451b5903a18d3817 (patch) | |
tree | 5d3f9cc7175ed152d6451b438cc7975df594afa3 /drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c | |
parent | c2bb06db59eaf92eb5ca9c6faed590597c6ceccb (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.c | 149 |
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 */ | ||
64 | static 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 */ |
64 | void bnx2x_dp_tlv_list(struct bnx2x *bp, void *tlvs_list) | 88 | void 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 | ||
986 | static void bnx2x_vf_mbx_resp(struct bnx2x *bp, struct bnx2x_virtf *vf) | 1026 | static 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 | |||
1042 | static 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 | ||
1109 | static 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 | |||
1116 | static 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 | |||
1063 | static void bnx2x_vf_mbx_acquire_resp(struct bnx2x *bp, struct bnx2x_virtf *vf, | 1139 | static 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 | ||
1148 | static void bnx2x_vf_mbx_acquire(struct bnx2x *bp, struct bnx2x_virtf *vf, | 1240 | static 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; |