aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYuval Mintz <Yuval.Mintz@qlogic.com>2016-08-22 06:25:11 -0400
committerDavid S. Miller <davem@davemloft.net>2016-08-22 21:24:52 -0400
commitd8c2c7e3404e5bcaeae4af78d6935e5b8fcc97ee (patch)
treee9beb5dc5d4bf584102e0e96830590ee5e0535cd
parent11a85d759ea5064c986c47112607681c09cdcdd9 (diff)
qed*: Add support for VFs over legacy PFs
Modern VFs can't run on old non-compatible as the fastpath HSI is slightly changed - but as the HSI is actually very close [basically, a single bit whose meaning flipped] this can be supported with small modifications. The major differences would be in: - Recognizing that VF is running on top of a legacy PF. - Returning some slowpath configurations that are no longer needed on top of modern PFs, but would be required when working over the legacy ones. Signed-off-by: Yuval Mintz <Yuval.Mintz@qlogic.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_l2.c2
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_vf.c107
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_vf.h5
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede.h2
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_main.c10
-rw-r--r--include/linux/qed/qed_eth_if.h3
6 files changed, 109 insertions, 20 deletions
diff --git a/drivers/net/ethernet/qlogic/qed/qed_l2.c b/drivers/net/ethernet/qlogic/qed/qed_l2.c
index bf433016551a..4409ea3f7d40 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_l2.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_l2.c
@@ -1685,6 +1685,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
1685 qed_vf_get_num_vlan_filters(&cdev->hwfns[0], 1685 qed_vf_get_num_vlan_filters(&cdev->hwfns[0],
1686 &info->num_vlan_filters); 1686 &info->num_vlan_filters);
1687 qed_vf_get_port_mac(&cdev->hwfns[0], info->port_mac); 1687 qed_vf_get_port_mac(&cdev->hwfns[0], info->port_mac);
1688
1689 info->is_legacy = !!cdev->hwfns[0].vf_iov_info->b_pre_fp_hsi;
1688 } 1690 }
1689 1691
1690 qed_fill_dev_info(cdev, &info->common); 1692 qed_fill_dev_info(cdev, &info->common);
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.c b/drivers/net/ethernet/qlogic/qed/qed_vf.c
index 9b780b31b15c..f9f68da8b277 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.c
@@ -191,6 +191,9 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
191 DP_VERBOSE(p_hwfn, 191 DP_VERBOSE(p_hwfn,
192 QED_MSG_IOV, "attempting to acquire resources\n"); 192 QED_MSG_IOV, "attempting to acquire resources\n");
193 193
194 /* Clear response buffer, as this might be a re-send */
195 memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs));
196
194 /* send acquire request */ 197 /* send acquire request */
195 rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp)); 198 rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
196 if (rc) 199 if (rc)
@@ -205,9 +208,12 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
205 /* PF agrees to allocate our resources */ 208 /* PF agrees to allocate our resources */
206 if (!(resp->pfdev_info.capabilities & 209 if (!(resp->pfdev_info.capabilities &
207 PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE)) { 210 PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE)) {
208 DP_INFO(p_hwfn, 211 /* It's possible legacy PF mistakenly accepted;
209 "PF is using old incompatible driver; Either downgrade driver or request provider to update hypervisor version\n"); 212 * but we don't care - simply mark it as
210 return -EINVAL; 213 * legacy and continue.
214 */
215 req->vfdev_info.capabilities |=
216 VFPF_ACQUIRE_CAP_PRE_FP_HSI;
211 } 217 }
212 DP_VERBOSE(p_hwfn, QED_MSG_IOV, "resources acquired\n"); 218 DP_VERBOSE(p_hwfn, QED_MSG_IOV, "resources acquired\n");
213 resources_acquired = true; 219 resources_acquired = true;
@@ -215,27 +221,55 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
215 attempts < VF_ACQUIRE_THRESH) { 221 attempts < VF_ACQUIRE_THRESH) {
216 qed_vf_pf_acquire_reduce_resc(p_hwfn, p_resc, 222 qed_vf_pf_acquire_reduce_resc(p_hwfn, p_resc,
217 &resp->resc); 223 &resp->resc);
224 } else if (resp->hdr.status == PFVF_STATUS_NOT_SUPPORTED) {
225 if (pfdev_info->major_fp_hsi &&
226 (pfdev_info->major_fp_hsi != ETH_HSI_VER_MAJOR)) {
227 DP_NOTICE(p_hwfn,
228 "PF uses an incompatible fastpath HSI %02x.%02x [VF requires %02x.%02x]. Please change to a VF driver using %02x.xx.\n",
229 pfdev_info->major_fp_hsi,
230 pfdev_info->minor_fp_hsi,
231 ETH_HSI_VER_MAJOR,
232 ETH_HSI_VER_MINOR,
233 pfdev_info->major_fp_hsi);
234 rc = -EINVAL;
235 goto exit;
236 }
218 237
219 /* Clear response buffer */ 238 if (!pfdev_info->major_fp_hsi) {
220 memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs)); 239 if (req->vfdev_info.capabilities &
221 } else if ((resp->hdr.status == PFVF_STATUS_NOT_SUPPORTED) && 240 VFPF_ACQUIRE_CAP_PRE_FP_HSI) {
222 pfdev_info->major_fp_hsi && 241 DP_NOTICE(p_hwfn,
223 (pfdev_info->major_fp_hsi != ETH_HSI_VER_MAJOR)) { 242 "PF uses very old drivers. Please change to a VF driver using no later than 8.8.x.x.\n");
224 DP_NOTICE(p_hwfn, 243 rc = -EINVAL;
225 "PF uses an incompatible fastpath HSI %02x.%02x [VF requires %02x.%02x]. Please change to a VF driver using %02x.xx.\n", 244 goto exit;
226 pfdev_info->major_fp_hsi, 245 } else {
227 pfdev_info->minor_fp_hsi, 246 DP_INFO(p_hwfn,
228 ETH_HSI_VER_MAJOR, 247 "PF is old - try re-acquire to see if it supports FW-version override\n");
229 ETH_HSI_VER_MINOR, pfdev_info->major_fp_hsi); 248 req->vfdev_info.capabilities |=
230 return -EINVAL; 249 VFPF_ACQUIRE_CAP_PRE_FP_HSI;
250 continue;
251 }
252 }
253
254 /* If PF/VF are using same Major, PF must have had
255 * it's reasons. Simply fail.
256 */
257 DP_NOTICE(p_hwfn, "PF rejected acquisition by VF\n");
258 rc = -EINVAL;
259 goto exit;
231 } else { 260 } else {
232 DP_ERR(p_hwfn, 261 DP_ERR(p_hwfn,
233 "PF returned error %d to VF acquisition request\n", 262 "PF returned error %d to VF acquisition request\n",
234 resp->hdr.status); 263 resp->hdr.status);
235 return -EAGAIN; 264 rc = -EAGAIN;
265 goto exit;
236 } 266 }
237 } 267 }
238 268
269 /* Mark the PF as legacy, if needed */
270 if (req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_PRE_FP_HSI)
271 p_iov->b_pre_fp_hsi = true;
272
239 /* Update bulletin board size with response from PF */ 273 /* Update bulletin board size with response from PF */
240 p_iov->bulletin.size = resp->bulletin_size; 274 p_iov->bulletin.size = resp->bulletin_size;
241 275
@@ -253,14 +287,16 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
253 } 287 }
254 } 288 }
255 289
256 if (ETH_HSI_VER_MINOR && 290 if (!p_iov->b_pre_fp_hsi &&
291 ETH_HSI_VER_MINOR &&
257 (resp->pfdev_info.minor_fp_hsi < ETH_HSI_VER_MINOR)) { 292 (resp->pfdev_info.minor_fp_hsi < ETH_HSI_VER_MINOR)) {
258 DP_INFO(p_hwfn, 293 DP_INFO(p_hwfn,
259 "PF is using older fastpath HSI; %02x.%02x is configured\n", 294 "PF is using older fastpath HSI; %02x.%02x is configured\n",
260 ETH_HSI_VER_MAJOR, resp->pfdev_info.minor_fp_hsi); 295 ETH_HSI_VER_MAJOR, resp->pfdev_info.minor_fp_hsi);
261 } 296 }
262 297
263 return 0; 298exit:
299 return rc;
264} 300}
265 301
266int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn) 302int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn)
@@ -347,6 +383,9 @@ free_p_iov:
347 383
348 return -ENOMEM; 384 return -ENOMEM;
349} 385}
386#define TSTORM_QZONE_START PXP_VF_BAR0_START_SDM_ZONE_A
387#define MSTORM_QZONE_START(dev) (TSTORM_QZONE_START + \
388 (TSTORM_QZONE_SIZE * NUM_OF_L2_QUEUES(dev)))
350 389
351int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn, 390int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
352 u8 rx_qid, 391 u8 rx_qid,
@@ -374,6 +413,21 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
374 req->bd_max_bytes = bd_max_bytes; 413 req->bd_max_bytes = bd_max_bytes;
375 req->stat_id = -1; 414 req->stat_id = -1;
376 415
416 /* If PF is legacy, we'll need to calculate producers ourselves
417 * as well as clean them.
418 */
419 if (pp_prod && p_iov->b_pre_fp_hsi) {
420 u8 hw_qid = p_iov->acquire_resp.resc.hw_qid[rx_qid];
421 u32 init_prod_val = 0;
422
423 *pp_prod = (u8 __iomem *)p_hwfn->regview +
424 MSTORM_QZONE_START(p_hwfn->cdev) +
425 hw_qid * MSTORM_QZONE_SIZE;
426
427 /* Init the rcq, rx bd and rx sge (if valid) producers to 0 */
428 __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32),
429 (u32 *)(&init_prod_val));
430 }
377 /* add list termination tlv */ 431 /* add list termination tlv */
378 qed_add_tlv(p_hwfn, &p_iov->offset, 432 qed_add_tlv(p_hwfn, &p_iov->offset,
379 CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv)); 433 CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
@@ -387,7 +441,7 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
387 return -EINVAL; 441 return -EINVAL;
388 442
389 /* Learn the address of the producer from the response */ 443 /* Learn the address of the producer from the response */
390 if (pp_prod) { 444 if (pp_prod && !p_iov->b_pre_fp_hsi) {
391 u32 init_prod_val = 0; 445 u32 init_prod_val = 0;
392 446
393 *pp_prod = (u8 __iomem *)p_hwfn->regview + resp->offset; 447 *pp_prod = (u8 __iomem *)p_hwfn->regview + resp->offset;
@@ -470,7 +524,20 @@ int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
470 } 524 }
471 525
472 if (pp_doorbell) { 526 if (pp_doorbell) {
473 *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells + resp->offset; 527 /* Modern PFs provide the actual offsets, while legacy
528 * provided only the queue id.
529 */
530 if (!p_iov->b_pre_fp_hsi) {
531 *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
532 resp->offset;
533 } else {
534 u8 cid = p_iov->acquire_resp.resc.cid[tx_queue_id];
535 u32 db_addr;
536
537 db_addr = qed_db_addr(cid, DQ_DEMS_LEGACY);
538 *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
539 db_addr;
540 }
474 541
475 DP_VERBOSE(p_hwfn, QED_MSG_IOV, 542 DP_VERBOSE(p_hwfn, QED_MSG_IOV,
476 "Txq[0x%02x]: doorbell at %p [offset 0x%08x]\n", 543 "Txq[0x%02x]: doorbell at %p [offset 0x%08x]\n",
diff --git a/drivers/net/ethernet/qlogic/qed/qed_vf.h b/drivers/net/ethernet/qlogic/qed/qed_vf.h
index 60a599b579bd..35db7a28aa13 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_vf.h
+++ b/drivers/net/ethernet/qlogic/qed/qed_vf.h
@@ -551,6 +551,11 @@ struct qed_vf_iov {
551 551
552 /* we set aside a copy of the acquire response */ 552 /* we set aside a copy of the acquire response */
553 struct pfvf_acquire_resp_tlv acquire_resp; 553 struct pfvf_acquire_resp_tlv acquire_resp;
554
555 /* In case PF originates prior to the fp-hsi version comparison,
556 * this has to be propagated as it affects the fastpath.
557 */
558 bool b_pre_fp_hsi;
554}; 559};
555 560
556#ifdef CONFIG_QED_SRIOV 561#ifdef CONFIG_QED_SRIOV
diff --git a/drivers/net/ethernet/qlogic/qede/qede.h b/drivers/net/ethernet/qlogic/qede/qede.h
index 32325ca5951f..700b509f7143 100644
--- a/drivers/net/ethernet/qlogic/qede/qede.h
+++ b/drivers/net/ethernet/qlogic/qede/qede.h
@@ -268,6 +268,8 @@ struct qede_tx_queue {
268 u16 num_tx_buffers; 268 u16 num_tx_buffers;
269 u64 xmit_pkts; 269 u64 xmit_pkts;
270 u64 stopped_cnt; 270 u64 stopped_cnt;
271
272 bool is_legacy;
271}; 273};
272 274
273#define BD_UNMAP_ADDR(bd) HILO_U64(le32_to_cpu((bd)->addr.hi), \ 275#define BD_UNMAP_ADDR(bd) HILO_U64(le32_to_cpu((bd)->addr.hi), \
diff --git a/drivers/net/ethernet/qlogic/qede/qede_main.c b/drivers/net/ethernet/qlogic/qede/qede_main.c
index a05459f96962..ac126e6067ae 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_main.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_main.c
@@ -598,6 +598,14 @@ static netdev_tx_t qede_start_xmit(struct sk_buff *skb,
598 1 << ETH_TX_DATA_1ST_BD_TUNN_FLAG_SHIFT; 598 1 << ETH_TX_DATA_1ST_BD_TUNN_FLAG_SHIFT;
599 } 599 }
600 600
601 /* Legacy FW had flipped behavior in regard to this bit -
602 * I.e., needed to set to prevent FW from touching encapsulated
603 * packets when it didn't need to.
604 */
605 if (unlikely(txq->is_legacy))
606 first_bd->data.bitfields ^=
607 1 << ETH_TX_DATA_1ST_BD_TUNN_FLAG_SHIFT;
608
601 /* If the packet is IPv6 with extension header, indicate that 609 /* If the packet is IPv6 with extension header, indicate that
602 * to FW and pass few params, since the device cracker doesn't 610 * to FW and pass few params, since the device cracker doesn't
603 * support parsing IPv6 with extension header/s. 611 * support parsing IPv6 with extension header/s.
@@ -2991,6 +2999,8 @@ static void qede_init_fp(struct qede_dev *edev)
2991 for (tc = 0; tc < edev->num_tc; tc++) { 2999 for (tc = 0; tc < edev->num_tc; tc++) {
2992 txq_index = tc * QEDE_RSS_CNT(edev) + rss_id; 3000 txq_index = tc * QEDE_RSS_CNT(edev) + rss_id;
2993 fp->txqs[tc].index = txq_index; 3001 fp->txqs[tc].index = txq_index;
3002 if (edev->dev_info.is_legacy)
3003 fp->txqs[tc].is_legacy = true;
2994 } 3004 }
2995 3005
2996 snprintf(fp->name, sizeof(fp->name), "%s-fp-%d", 3006 snprintf(fp->name, sizeof(fp->name), "%s-fp-%d",
diff --git a/include/linux/qed/qed_eth_if.h b/include/linux/qed/qed_eth_if.h
index 4475a9d8ae15..33c24ebc9b7f 100644
--- a/include/linux/qed/qed_eth_if.h
+++ b/include/linux/qed/qed_eth_if.h
@@ -23,6 +23,9 @@ struct qed_dev_eth_info {
23 23
24 u8 port_mac[ETH_ALEN]; 24 u8 port_mac[ETH_ALEN];
25 u8 num_vlan_filters; 25 u8 num_vlan_filters;
26
27 /* Legacy VF - this affects the datapath, so qede has to know */
28 bool is_legacy;
26}; 29};
27 30
28struct qed_update_vport_rss_params { 31struct qed_update_vport_rss_params {