Merge remote-tracking branch 'regulator/for-next'
[deliverable/linux.git] / drivers / net / ethernet / qlogic / qed / qed_vf.c
index 9b780b31b15c84c92c754d58e9a7ebd7d6eead53..85334ceaf69cb9dad4020c393c94f7e16e5ce802 100644 (file)
@@ -46,6 +46,17 @@ static void *qed_vf_pf_prep(struct qed_hwfn *p_hwfn, u16 type, u16 length)
        return p_tlv;
 }
 
+static void qed_vf_pf_req_end(struct qed_hwfn *p_hwfn, int req_status)
+{
+       union pfvf_tlvs *resp = p_hwfn->vf_iov_info->pf2vf_reply;
+
+       DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+                  "VF request status = 0x%x, PF reply status = 0x%x\n",
+                  req_status, resp->default_resp.hdr.status);
+
+       mutex_unlock(&(p_hwfn->vf_iov_info->mutex));
+}
+
 static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size)
 {
        union vfpf_tlvs *p_req = p_hwfn->vf_iov_info->vf2pf_request;
@@ -103,16 +114,12 @@ static int qed_send_msg2pf(struct qed_hwfn *p_hwfn, u8 *done, u32 resp_size)
                           "VF <-- PF Timeout [Type %d]\n",
                           p_req->first_tlv.tl.type);
                rc = -EBUSY;
-               goto exit;
        } else {
                DP_VERBOSE(p_hwfn, QED_MSG_IOV,
                           "PF response: %d [Type %d]\n",
                           *done, p_req->first_tlv.tl.type);
        }
 
-exit:
-       mutex_unlock(&(p_hwfn->vf_iov_info->mutex));
-
        return rc;
 }
 
@@ -191,6 +198,9 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
                DP_VERBOSE(p_hwfn,
                           QED_MSG_IOV, "attempting to acquire resources\n");
 
+               /* Clear response buffer, as this might be a re-send */
+               memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs));
+
                /* send acquire request */
                rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
                if (rc)
@@ -205,9 +215,12 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
                        /* PF agrees to allocate our resources */
                        if (!(resp->pfdev_info.capabilities &
                              PFVF_ACQUIRE_CAP_POST_FW_OVERRIDE)) {
-                               DP_INFO(p_hwfn,
-                                       "PF is using old incompatible driver; Either downgrade driver or request provider to update hypervisor version\n");
-                               return -EINVAL;
+                               /* It's possible legacy PF mistakenly accepted;
+                                * but we don't care - simply mark it as
+                                * legacy and continue.
+                                */
+                               req->vfdev_info.capabilities |=
+                                   VFPF_ACQUIRE_CAP_PRE_FP_HSI;
                        }
                        DP_VERBOSE(p_hwfn, QED_MSG_IOV, "resources acquired\n");
                        resources_acquired = true;
@@ -215,27 +228,55 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
                           attempts < VF_ACQUIRE_THRESH) {
                        qed_vf_pf_acquire_reduce_resc(p_hwfn, p_resc,
                                                      &resp->resc);
+               } else if (resp->hdr.status == PFVF_STATUS_NOT_SUPPORTED) {
+                       if (pfdev_info->major_fp_hsi &&
+                           (pfdev_info->major_fp_hsi != ETH_HSI_VER_MAJOR)) {
+                               DP_NOTICE(p_hwfn,
+                                         "PF uses an incompatible fastpath HSI %02x.%02x [VF requires %02x.%02x]. Please change to a VF driver using %02x.xx.\n",
+                                         pfdev_info->major_fp_hsi,
+                                         pfdev_info->minor_fp_hsi,
+                                         ETH_HSI_VER_MAJOR,
+                                         ETH_HSI_VER_MINOR,
+                                         pfdev_info->major_fp_hsi);
+                               rc = -EINVAL;
+                               goto exit;
+                       }
 
-                       /* Clear response buffer */
-                       memset(p_iov->pf2vf_reply, 0, sizeof(union pfvf_tlvs));
-               } else if ((resp->hdr.status == PFVF_STATUS_NOT_SUPPORTED) &&
-                          pfdev_info->major_fp_hsi &&
-                          (pfdev_info->major_fp_hsi != ETH_HSI_VER_MAJOR)) {
-                       DP_NOTICE(p_hwfn,
-                                 "PF uses an incompatible fastpath HSI %02x.%02x [VF requires %02x.%02x]. Please change to a VF driver using %02x.xx.\n",
-                                 pfdev_info->major_fp_hsi,
-                                 pfdev_info->minor_fp_hsi,
-                                 ETH_HSI_VER_MAJOR,
-                                 ETH_HSI_VER_MINOR, pfdev_info->major_fp_hsi);
-                       return -EINVAL;
+                       if (!pfdev_info->major_fp_hsi) {
+                               if (req->vfdev_info.capabilities &
+                                   VFPF_ACQUIRE_CAP_PRE_FP_HSI) {
+                                       DP_NOTICE(p_hwfn,
+                                                 "PF uses very old drivers. Please change to a VF driver using no later than 8.8.x.x.\n");
+                                       rc = -EINVAL;
+                                       goto exit;
+                               } else {
+                                       DP_INFO(p_hwfn,
+                                               "PF is old - try re-acquire to see if it supports FW-version override\n");
+                                       req->vfdev_info.capabilities |=
+                                           VFPF_ACQUIRE_CAP_PRE_FP_HSI;
+                                       continue;
+                               }
+                       }
+
+                       /* If PF/VF are using same Major, PF must have had
+                        * it's reasons. Simply fail.
+                        */
+                       DP_NOTICE(p_hwfn, "PF rejected acquisition by VF\n");
+                       rc = -EINVAL;
+                       goto exit;
                } else {
                        DP_ERR(p_hwfn,
                               "PF returned error %d to VF acquisition request\n",
                               resp->hdr.status);
-                       return -EAGAIN;
+                       rc = -EAGAIN;
+                       goto exit;
                }
        }
 
+       /* Mark the PF as legacy, if needed */
+       if (req->vfdev_info.capabilities & VFPF_ACQUIRE_CAP_PRE_FP_HSI)
+               p_iov->b_pre_fp_hsi = true;
+
        /* Update bulletin board size with response from PF */
        p_iov->bulletin.size = resp->bulletin_size;
 
@@ -253,14 +294,18 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
                }
        }
 
-       if (ETH_HSI_VER_MINOR &&
+       if (!p_iov->b_pre_fp_hsi &&
+           ETH_HSI_VER_MINOR &&
            (resp->pfdev_info.minor_fp_hsi < ETH_HSI_VER_MINOR)) {
                DP_INFO(p_hwfn,
                        "PF is using older fastpath HSI; %02x.%02x is configured\n",
                        ETH_HSI_VER_MAJOR, resp->pfdev_info.minor_fp_hsi);
        }
 
-       return 0;
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
+
+       return rc;
 }
 
 int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn)
@@ -286,31 +331,23 @@ int qed_vf_hw_prepare(struct qed_hwfn *p_hwfn)
 
        /* Allocate vf sriov info */
        p_iov = kzalloc(sizeof(*p_iov), GFP_KERNEL);
-       if (!p_iov) {
-               DP_NOTICE(p_hwfn, "Failed to allocate `struct qed_sriov'\n");
+       if (!p_iov)
                return -ENOMEM;
-       }
 
        /* Allocate vf2pf msg */
        p_iov->vf2pf_request = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
                                                  sizeof(union vfpf_tlvs),
                                                  &p_iov->vf2pf_request_phys,
                                                  GFP_KERNEL);
-       if (!p_iov->vf2pf_request) {
-               DP_NOTICE(p_hwfn,
-                         "Failed to allocate `vf2pf_request' DMA memory\n");
+       if (!p_iov->vf2pf_request)
                goto free_p_iov;
-       }
 
        p_iov->pf2vf_reply = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
                                                sizeof(union pfvf_tlvs),
                                                &p_iov->pf2vf_reply_phys,
                                                GFP_KERNEL);
-       if (!p_iov->pf2vf_reply) {
-               DP_NOTICE(p_hwfn,
-                         "Failed to allocate `pf2vf_reply' DMA memory\n");
+       if (!p_iov->pf2vf_reply)
                goto free_vf2pf_request;
-       }
 
        DP_VERBOSE(p_hwfn,
                   QED_MSG_IOV,
@@ -347,6 +384,9 @@ free_p_iov:
 
        return -ENOMEM;
 }
+#define TSTORM_QZONE_START   PXP_VF_BAR0_START_SDM_ZONE_A
+#define MSTORM_QZONE_START(dev)   (TSTORM_QZONE_START +        \
+                                  (TSTORM_QZONE_SIZE * NUM_OF_L2_QUEUES(dev)))
 
 int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
                        u8 rx_qid,
@@ -374,6 +414,21 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
        req->bd_max_bytes = bd_max_bytes;
        req->stat_id = -1;
 
+       /* If PF is legacy, we'll need to calculate producers ourselves
+        * as well as clean them.
+        */
+       if (pp_prod && p_iov->b_pre_fp_hsi) {
+               u8 hw_qid = p_iov->acquire_resp.resc.hw_qid[rx_qid];
+               u32 init_prod_val = 0;
+
+               *pp_prod = (u8 __iomem *)p_hwfn->regview +
+                                        MSTORM_QZONE_START(p_hwfn->cdev) +
+                                        hw_qid * MSTORM_QZONE_SIZE;
+
+               /* Init the rcq, rx bd and rx sge (if valid) producers to 0 */
+               __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32),
+                                 (u32 *)(&init_prod_val));
+       }
        /* add list termination tlv */
        qed_add_tlv(p_hwfn, &p_iov->offset,
                    CHANNEL_TLV_LIST_END, sizeof(struct channel_list_end_tlv));
@@ -381,13 +436,15 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
        resp = &p_iov->pf2vf_reply->queue_start;
        rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
        if (rc)
-               return rc;
+               goto exit;
 
-       if (resp->hdr.status != PFVF_STATUS_SUCCESS)
-               return -EINVAL;
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               rc = -EINVAL;
+               goto exit;
+       }
 
        /* Learn the address of the producer from the response */
-       if (pp_prod) {
+       if (pp_prod && !p_iov->b_pre_fp_hsi) {
                u32 init_prod_val = 0;
 
                *pp_prod = (u8 __iomem *)p_hwfn->regview + resp->offset;
@@ -399,6 +456,8 @@ int qed_vf_pf_rxq_start(struct qed_hwfn *p_hwfn,
                __internal_ram_wr(p_hwfn, *pp_prod, sizeof(u32),
                                  (u32 *)&init_prod_val);
        }
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
 
        return rc;
 }
@@ -424,10 +483,15 @@ int qed_vf_pf_rxq_stop(struct qed_hwfn *p_hwfn, u16 rx_qid, bool cqe_completion)
        resp = &p_iov->pf2vf_reply->default_resp;
        rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
        if (rc)
-               return rc;
+               goto exit;
+
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               rc = -EINVAL;
+               goto exit;
+       }
 
-       if (resp->hdr.status != PFVF_STATUS_SUCCESS)
-               return -EINVAL;
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
 
        return rc;
 }
@@ -470,13 +534,27 @@ int qed_vf_pf_txq_start(struct qed_hwfn *p_hwfn,
        }
 
        if (pp_doorbell) {
-               *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells + resp->offset;
+               /* Modern PFs provide the actual offsets, while legacy
+                * provided only the queue id.
+                */
+               if (!p_iov->b_pre_fp_hsi) {
+                       *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
+                                                    resp->offset;
+               } else {
+                       u8 cid = p_iov->acquire_resp.resc.cid[tx_queue_id];
+                       u32 db_addr;
+
+                       db_addr = qed_db_addr(cid, DQ_DEMS_LEGACY);
+                       *pp_doorbell = (u8 __iomem *)p_hwfn->doorbells +
+                                                    db_addr;
+               }
 
                DP_VERBOSE(p_hwfn, QED_MSG_IOV,
                           "Txq[0x%02x]: doorbell at %p [offset 0x%08x]\n",
                           tx_queue_id, *pp_doorbell, resp->offset);
        }
 exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
 
        return rc;
 }
@@ -501,10 +579,15 @@ int qed_vf_pf_txq_stop(struct qed_hwfn *p_hwfn, u16 tx_qid)
        resp = &p_iov->pf2vf_reply->default_resp;
        rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
        if (rc)
-               return rc;
+               goto exit;
 
-       if (resp->hdr.status != PFVF_STATUS_SUCCESS)
-               return -EINVAL;
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               rc = -EINVAL;
+               goto exit;
+       }
+
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
 
        return rc;
 }
@@ -543,10 +626,15 @@ int qed_vf_pf_vport_start(struct qed_hwfn *p_hwfn,
        resp = &p_iov->pf2vf_reply->default_resp;
        rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
        if (rc)
-               return rc;
+               goto exit;
 
-       if (resp->hdr.status != PFVF_STATUS_SUCCESS)
-               return -EINVAL;
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               rc = -EINVAL;
+               goto exit;
+       }
+
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
 
        return rc;
 }
@@ -567,10 +655,15 @@ int qed_vf_pf_vport_stop(struct qed_hwfn *p_hwfn)
 
        rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
        if (rc)
-               return rc;
+               goto exit;
+
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               rc = -EINVAL;
+               goto exit;
+       }
 
-       if (resp->hdr.status != PFVF_STATUS_SUCCESS)
-               return -EINVAL;
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
 
        return rc;
 }
@@ -770,13 +863,18 @@ int qed_vf_pf_vport_update(struct qed_hwfn *p_hwfn,
 
        rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, resp_size);
        if (rc)
-               return rc;
+               goto exit;
 
-       if (resp->hdr.status != PFVF_STATUS_SUCCESS)
-               return -EINVAL;
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               rc = -EINVAL;
+               goto exit;
+       }
 
        qed_vf_handle_vp_update_tlvs_resp(p_hwfn, p_params);
 
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
+
        return rc;
 }
 
@@ -797,14 +895,19 @@ int qed_vf_pf_reset(struct qed_hwfn *p_hwfn)
        resp = &p_iov->pf2vf_reply->default_resp;
        rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
        if (rc)
-               return rc;
+               goto exit;
 
-       if (resp->hdr.status != PFVF_STATUS_SUCCESS)
-               return -EAGAIN;
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               rc = -EAGAIN;
+               goto exit;
+       }
 
        p_hwfn->b_int_enabled = 0;
 
-       return 0;
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
+
+       return rc;
 }
 
 int qed_vf_pf_release(struct qed_hwfn *p_hwfn)
@@ -828,6 +931,8 @@ int qed_vf_pf_release(struct qed_hwfn *p_hwfn)
        if (!rc && resp->hdr.status != PFVF_STATUS_SUCCESS)
                rc = -EAGAIN;
 
+       qed_vf_pf_req_end(p_hwfn, rc);
+
        p_hwfn->b_int_enabled = 0;
 
        if (p_iov->vf2pf_request)
@@ -896,12 +1001,17 @@ int qed_vf_pf_filter_ucast(struct qed_hwfn *p_hwfn,
        resp = &p_iov->pf2vf_reply->default_resp;
        rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
        if (rc)
-               return rc;
+               goto exit;
 
-       if (resp->hdr.status != PFVF_STATUS_SUCCESS)
-               return -EAGAIN;
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               rc = -EAGAIN;
+               goto exit;
+       }
 
-       return 0;
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
+
+       return rc;
 }
 
 int qed_vf_pf_int_cleanup(struct qed_hwfn *p_hwfn)
@@ -920,12 +1030,17 @@ int qed_vf_pf_int_cleanup(struct qed_hwfn *p_hwfn)
 
        rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
        if (rc)
-               return rc;
+               goto exit;
 
-       if (resp->hdr.status != PFVF_STATUS_SUCCESS)
-               return -EINVAL;
+       if (resp->hdr.status != PFVF_STATUS_SUCCESS) {
+               rc = -EINVAL;
+               goto exit;
+       }
 
-       return 0;
+exit:
+       qed_vf_pf_req_end(p_hwfn, rc);
+
+       return rc;
 }
 
 u16 qed_vf_get_igu_sb_id(struct qed_hwfn *p_hwfn, u16 sb_id)
@@ -1071,8 +1186,8 @@ bool qed_vf_check_mac(struct qed_hwfn *p_hwfn, u8 *mac)
        return false;
 }
 
-bool qed_vf_bulletin_get_forced_mac(struct qed_hwfn *hwfn,
-                                   u8 *dst_mac, u8 *p_is_forced)
+static bool qed_vf_bulletin_get_forced_mac(struct qed_hwfn *hwfn,
+                                          u8 *dst_mac, u8 *p_is_forced)
 {
        struct qed_bulletin_content *bulletin;
 
This page took 0.030707 seconds and 5 git commands to generate.