|
@@ -429,6 +429,95 @@ int t4vf_set_params(struct adapter *adapter, unsigned int nparams,
|
|
|
return t4vf_wr_mbox(adapter, &cmd, sizeof(cmd), NULL);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * t4_bar2_sge_qregs - return BAR2 SGE Queue register information
|
|
|
+ * @adapter: the adapter
|
|
|
+ * @qid: the Queue ID
|
|
|
+ * @qtype: the Ingress or Egress type for @qid
|
|
|
+ * @pbar2_qoffset: BAR2 Queue Offset
|
|
|
+ * @pbar2_qid: BAR2 Queue ID or 0 for Queue ID inferred SGE Queues
|
|
|
+ *
|
|
|
+ * Returns the BAR2 SGE Queue Registers information associated with the
|
|
|
+ * indicated Absolute Queue ID. These are passed back in return value
|
|
|
+ * pointers. @qtype should be T4_BAR2_QTYPE_EGRESS for Egress Queue
|
|
|
+ * and T4_BAR2_QTYPE_INGRESS for Ingress Queues.
|
|
|
+ *
|
|
|
+ * This may return an error which indicates that BAR2 SGE Queue
|
|
|
+ * registers aren't available. If an error is not returned, then the
|
|
|
+ * following values are returned:
|
|
|
+ *
|
|
|
+ * *@pbar2_qoffset: the BAR2 Offset of the @qid Registers
|
|
|
+ * *@pbar2_qid: the BAR2 SGE Queue ID or 0 of @qid
|
|
|
+ *
|
|
|
+ * If the returned BAR2 Queue ID is 0, then BAR2 SGE registers which
|
|
|
+ * require the "Inferred Queue ID" ability may be used. E.g. the
|
|
|
+ * Write Combining Doorbell Buffer. If the BAR2 Queue ID is not 0,
|
|
|
+ * then these "Inferred Queue ID" register may not be used.
|
|
|
+ */
|
|
|
+int t4_bar2_sge_qregs(struct adapter *adapter,
|
|
|
+ unsigned int qid,
|
|
|
+ enum t4_bar2_qtype qtype,
|
|
|
+ u64 *pbar2_qoffset,
|
|
|
+ unsigned int *pbar2_qid)
|
|
|
+{
|
|
|
+ unsigned int page_shift, page_size, qpp_shift, qpp_mask;
|
|
|
+ u64 bar2_page_offset, bar2_qoffset;
|
|
|
+ unsigned int bar2_qid, bar2_qid_offset, bar2_qinferred;
|
|
|
+
|
|
|
+ /* T4 doesn't support BAR2 SGE Queue registers.
|
|
|
+ */
|
|
|
+ if (is_t4(adapter->params.chip))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ /* Get our SGE Page Size parameters.
|
|
|
+ */
|
|
|
+ page_shift = adapter->params.sge.sge_vf_hps + 10;
|
|
|
+ page_size = 1 << page_shift;
|
|
|
+
|
|
|
+ /* Get the right Queues per Page parameters for our Queue.
|
|
|
+ */
|
|
|
+ qpp_shift = (qtype == T4_BAR2_QTYPE_EGRESS
|
|
|
+ ? adapter->params.sge.sge_vf_eq_qpp
|
|
|
+ : adapter->params.sge.sge_vf_iq_qpp);
|
|
|
+ qpp_mask = (1 << qpp_shift) - 1;
|
|
|
+
|
|
|
+ /* Calculate the basics of the BAR2 SGE Queue register area:
|
|
|
+ * o The BAR2 page the Queue registers will be in.
|
|
|
+ * o The BAR2 Queue ID.
|
|
|
+ * o The BAR2 Queue ID Offset into the BAR2 page.
|
|
|
+ */
|
|
|
+ bar2_page_offset = ((qid >> qpp_shift) << page_shift);
|
|
|
+ bar2_qid = qid & qpp_mask;
|
|
|
+ bar2_qid_offset = bar2_qid * SGE_UDB_SIZE;
|
|
|
+
|
|
|
+ /* If the BAR2 Queue ID Offset is less than the Page Size, then the
|
|
|
+ * hardware will infer the Absolute Queue ID simply from the writes to
|
|
|
+ * the BAR2 Queue ID Offset within the BAR2 Page (and we need to use a
|
|
|
+ * BAR2 Queue ID of 0 for those writes). Otherwise, we'll simply
|
|
|
+ * write to the first BAR2 SGE Queue Area within the BAR2 Page with
|
|
|
+ * the BAR2 Queue ID and the hardware will infer the Absolute Queue ID
|
|
|
+ * from the BAR2 Page and BAR2 Queue ID.
|
|
|
+ *
|
|
|
+ * One important censequence of this is that some BAR2 SGE registers
|
|
|
+ * have a "Queue ID" field and we can write the BAR2 SGE Queue ID
|
|
|
+ * there. But other registers synthesize the SGE Queue ID purely
|
|
|
+ * from the writes to the registers -- the Write Combined Doorbell
|
|
|
+ * Buffer is a good example. These BAR2 SGE Registers are only
|
|
|
+ * available for those BAR2 SGE Register areas where the SGE Absolute
|
|
|
+ * Queue ID can be inferred from simple writes.
|
|
|
+ */
|
|
|
+ bar2_qoffset = bar2_page_offset;
|
|
|
+ bar2_qinferred = (bar2_qid_offset < page_size);
|
|
|
+ if (bar2_qinferred) {
|
|
|
+ bar2_qoffset += bar2_qid_offset;
|
|
|
+ bar2_qid = 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ *pbar2_qoffset = bar2_qoffset;
|
|
|
+ *pbar2_qid = bar2_qid;
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* t4vf_get_sge_params - retrieve adapter Scatter gather Engine parameters
|
|
|
* @adapter: the adapter
|
|
@@ -507,7 +596,7 @@ int t4vf_get_sge_params(struct adapter *adapter)
|
|
|
*/
|
|
|
if (!is_t4(adapter->params.chip)) {
|
|
|
u32 whoami;
|
|
|
- unsigned int pf, s_qpp;
|
|
|
+ unsigned int pf, s_hps, s_qpp;
|
|
|
|
|
|
params[0] = (FW_PARAMS_MNEM_V(FW_PARAMS_MNEM_REG) |
|
|
|
FW_PARAMS_PARAM_XYZ_V(
|
|
@@ -533,6 +622,13 @@ int t4vf_get_sge_params(struct adapter *adapter)
|
|
|
whoami = t4_read_reg(adapter,
|
|
|
T4VF_PL_BASE_ADDR + A_PL_VF_WHOAMI);
|
|
|
pf = SOURCEPF_GET(whoami);
|
|
|
+
|
|
|
+ s_hps = (HOSTPAGESIZEPF0_S +
|
|
|
+ (HOSTPAGESIZEPF1_S - HOSTPAGESIZEPF0_S) * pf);
|
|
|
+ sge_params->sge_vf_hps =
|
|
|
+ ((sge_params->sge_host_page_size >> s_hps)
|
|
|
+ & HOSTPAGESIZEPF0_M);
|
|
|
+
|
|
|
s_qpp = (QUEUESPERPAGEPF0_S +
|
|
|
(QUEUESPERPAGEPF1_S - QUEUESPERPAGEPF0_S) * pf);
|
|
|
sge_params->sge_vf_eq_qpp =
|