summaryrefslogtreecommitdiff
path: root/drivers/staging
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging')
-rw-r--r--drivers/staging/fsl_qbman/qman_high.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/drivers/staging/fsl_qbman/qman_high.c b/drivers/staging/fsl_qbman/qman_high.c
index 370e260..9b8a924 100644
--- a/drivers/staging/fsl_qbman/qman_high.c
+++ b/drivers/staging/fsl_qbman/qman_high.c
@@ -3223,7 +3223,7 @@ static int qman_ceetm_write_statistics(u16 cid, enum qm_dc_portal dcp_idx,
return 0;
}
-int qman_ceetm_bps2tokenrate(u32 bps, struct qm_ceetm_rate *token_rate,
+int qman_ceetm_bps2tokenrate(u64 bps, struct qm_ceetm_rate *token_rate,
int rounding)
{
u16 pres;
@@ -3254,16 +3254,20 @@ int qman_ceetm_bps2tokenrate(u32 bps, struct qm_ceetm_rate *token_rate,
* token-rate = (bps*2^19) / (PRES*QHZ)
* N = (bps*2^32) / (PRES*QHz)
*
+ * And to avoid 64-bit overflow if 'bps' is larger than 4Gbps
+ * (yet minimise rounding error if 'bps' is small), we reorganise
+ * the formula to use two 16-bit shifts rather than 1 32-bit shift.
+ * N = (((bps*2^16)/PRES)*2^16)/QHz
*/
- temp = ROUNDING(((u64)bps << 32), pres, rounding);
- temp = ROUNDING(temp, qman_freq, rounding);
+ temp = ROUNDING((bps << 16), pres, rounding);
+ temp = ROUNDING((temp << 16), qman_freq, rounding);
token_rate->whole = temp >> 13;
token_rate->fraction = temp & (((u64)1 << 13) - 1);
return 0;
}
EXPORT_SYMBOL(qman_ceetm_bps2tokenrate);
-int qman_ceetm_tokenrate2bps(const struct qm_ceetm_rate *token_rate, u32 *bps,
+int qman_ceetm_tokenrate2bps(const struct qm_ceetm_rate *token_rate, u64 *bps,
int rounding)
{
u16 pres;