aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
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
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')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x.h3
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c23
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.c149
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h7
4 files changed, 155 insertions, 27 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
index 8fe4bcb2407d..5fb18cd99da2 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
@@ -1546,6 +1546,7 @@ struct bnx2x {
1546#define IS_VF_FLAG (1 << 22) 1546#define IS_VF_FLAG (1 << 22)
1547#define INTERRUPTS_ENABLED_FLAG (1 << 23) 1547#define INTERRUPTS_ENABLED_FLAG (1 << 23)
1548#define BC_SUPPORTS_RMMOD_CMD (1 << 24) 1548#define BC_SUPPORTS_RMMOD_CMD (1 << 24)
1549#define HAS_PHYS_PORT_ID (1 << 25)
1549 1550
1550#define BP_NOMCP(bp) ((bp)->flags & NO_MCP_FLAG) 1551#define BP_NOMCP(bp) ((bp)->flags & NO_MCP_FLAG)
1551 1552
@@ -1876,6 +1877,8 @@ struct bnx2x {
1876 u32 dump_preset_idx; 1877 u32 dump_preset_idx;
1877 bool stats_started; 1878 bool stats_started;
1878 struct semaphore stats_sema; 1879 struct semaphore stats_sema;
1880
1881 u8 phys_port_id[ETH_ALEN];
1879}; 1882};
1880 1883
1881/* Tx queues may be less or equal to Rx queues */ 1884/* Tx queues may be less or equal to Rx queues */
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 13a569460ef2..e53ff1eb3a84 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -11149,6 +11149,14 @@ static void bnx2x_get_mac_hwinfo(struct bnx2x *bp)
11149 bnx2x_get_cnic_mac_hwinfo(bp); 11149 bnx2x_get_cnic_mac_hwinfo(bp);
11150 } 11150 }
11151 11151
11152 if (!BP_NOMCP(bp)) {
11153 /* Read physical port identifier from shmem */
11154 val2 = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_upper);
11155 val = SHMEM_RD(bp, dev_info.port_hw_config[port].mac_lower);
11156 bnx2x_set_mac_buf(bp->phys_port_id, val, val2);
11157 bp->flags |= HAS_PHYS_PORT_ID;
11158 }
11159
11152 memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN); 11160 memcpy(bp->link_params.mac_addr, bp->dev->dev_addr, ETH_ALEN);
11153 11161
11154 if (!bnx2x_is_valid_ether_addr(bp, bp->dev->dev_addr)) 11162 if (!bnx2x_is_valid_ether_addr(bp, bp->dev->dev_addr))
@@ -12044,6 +12052,20 @@ static int bnx2x_validate_addr(struct net_device *dev)
12044 return 0; 12052 return 0;
12045} 12053}
12046 12054
12055static int bnx2x_get_phys_port_id(struct net_device *netdev,
12056 struct netdev_phys_port_id *ppid)
12057{
12058 struct bnx2x *bp = netdev_priv(netdev);
12059
12060 if (!(bp->flags & HAS_PHYS_PORT_ID))
12061 return -EOPNOTSUPP;
12062
12063 ppid->id_len = sizeof(bp->phys_port_id);
12064 memcpy(ppid->id, bp->phys_port_id, ppid->id_len);
12065
12066 return 0;
12067}
12068
12047static const struct net_device_ops bnx2x_netdev_ops = { 12069static const struct net_device_ops bnx2x_netdev_ops = {
12048 .ndo_open = bnx2x_open, 12070 .ndo_open = bnx2x_open,
12049 .ndo_stop = bnx2x_close, 12071 .ndo_stop = bnx2x_close,
@@ -12073,6 +12095,7 @@ static const struct net_device_ops bnx2x_netdev_ops = {
12073#ifdef CONFIG_NET_RX_BUSY_POLL 12095#ifdef CONFIG_NET_RX_BUSY_POLL
12074 .ndo_busy_poll = bnx2x_low_latency_recv, 12096 .ndo_busy_poll = bnx2x_low_latency_recv,
12075#endif 12097#endif
12098 .ndo_get_phys_port_id = bnx2x_get_phys_port_id,
12076}; 12099};
12077 12100
12078static int bnx2x_set_coherency_mask(struct bnx2x *bp) 12101static int bnx2x_set_coherency_mask(struct bnx2x *bp)
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;
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
index 1179fe06d0c7..208568bc7a71 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_vfpf.h
@@ -188,6 +188,12 @@ struct pfvf_acquire_resp_tlv {
188 } resc; 188 } resc;
189}; 189};
190 190
191struct vfpf_port_phys_id_resp_tlv {
192 struct channel_tlv tl;
193 u8 id[ETH_ALEN];
194 u8 padding[2];
195};
196
191#define VFPF_INIT_FLG_STATS_COALESCE (1 << 0) /* when set the VFs queues 197#define VFPF_INIT_FLG_STATS_COALESCE (1 << 0) /* when set the VFs queues
192 * stats will be coalesced on 198 * stats will be coalesced on
193 * the leading RSS queue 199 * the leading RSS queue
@@ -398,6 +404,7 @@ enum channel_tlvs {
398 CHANNEL_TLV_PF_SET_MAC, 404 CHANNEL_TLV_PF_SET_MAC,
399 CHANNEL_TLV_PF_SET_VLAN, 405 CHANNEL_TLV_PF_SET_VLAN,
400 CHANNEL_TLV_UPDATE_RSS, 406 CHANNEL_TLV_UPDATE_RSS,
407 CHANNEL_TLV_PHYS_PORT_ID,
401 CHANNEL_TLV_MAX 408 CHANNEL_TLV_MAX
402}; 409};
403 410