forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-14 bedbef8ad3e75a304af6361af235302bcc61d06b
kernel/drivers/soc/fsl/qbman/qman.c
....@@ -36,6 +36,8 @@
3636 #define MAX_IRQNAME 16 /* big enough for "QMan portal %d" */
3737 #define QMAN_POLL_LIMIT 32
3838 #define QMAN_PIRQ_DQRR_ITHRESH 12
39
+#define QMAN_DQRR_IT_MAX 15
40
+#define QMAN_ITP_MAX 0xFFF
3941 #define QMAN_PIRQ_MR_ITHRESH 4
4042 #define QMAN_PIRQ_IPERIOD 100
4143
....@@ -447,11 +449,6 @@
447449 return 0;
448450 }
449451
450
-static inline unsigned int qm_eqcr_get_ci_stashing(struct qm_portal *portal)
451
-{
452
- return (qm_in(portal, QM_REG_CFG) >> 28) & 0x7;
453
-}
454
-
455452 static inline void qm_eqcr_finish(struct qm_portal *portal)
456453 {
457454 struct qm_eqcr *eqcr = &portal->eqcr;
....@@ -727,9 +724,15 @@
727724 qm_out(portal, QM_REG_DQRR_VDQCR, vdqcr);
728725 }
729726
730
-static inline void qm_dqrr_set_ithresh(struct qm_portal *portal, u8 ithresh)
727
+static inline int qm_dqrr_set_ithresh(struct qm_portal *portal, u8 ithresh)
731728 {
729
+
730
+ if (ithresh > QMAN_DQRR_IT_MAX)
731
+ return -EINVAL;
732
+
732733 qm_out(portal, QM_REG_DQRR_ITR, ithresh);
734
+
735
+ return 0;
733736 }
734737
735738 /* --- MR API --- */
....@@ -850,12 +853,24 @@
850853
851854 static inline int qm_mc_init(struct qm_portal *portal)
852855 {
856
+ u8 rr0, rr1;
853857 struct qm_mc *mc = &portal->mc;
854858
855859 mc->cr = portal->addr.ce + QM_CL_CR;
856860 mc->rr = portal->addr.ce + QM_CL_RR0;
857
- mc->rridx = (mc->cr->_ncw_verb & QM_MCC_VERB_VBIT)
858
- ? 0 : 1;
861
+ /*
862
+ * The expected valid bit polarity for the next CR command is 0
863
+ * if RR1 contains a valid response, and is 1 if RR0 contains a
864
+ * valid response. If both RR contain all 0, this indicates either
865
+ * that no command has been executed since reset (in which case the
866
+ * expected valid bit polarity is 1)
867
+ */
868
+ rr0 = mc->rr->verb;
869
+ rr1 = (mc->rr+1)->verb;
870
+ if ((rr0 == 0 && rr1 == 0) || rr0 != 0)
871
+ mc->rridx = 1;
872
+ else
873
+ mc->rridx = 0;
859874 mc->vbit = mc->rridx ? QM_MCC_VERB_VBIT : 0;
860875 #ifdef CONFIG_FSL_DPAA_CHECKING
861876 mc->state = qman_mc_idle;
....@@ -998,7 +1013,63 @@
9981013 put_cpu_var(qman_affine_portal);
9991014 }
10001015
1016
+
1017
+static inline struct qman_portal *get_portal_for_channel(u16 channel)
1018
+{
1019
+ int i;
1020
+
1021
+ for (i = 0; i < num_possible_cpus(); i++) {
1022
+ if (affine_portals[i] &&
1023
+ affine_portals[i]->config->channel == channel)
1024
+ return affine_portals[i];
1025
+ }
1026
+
1027
+ return NULL;
1028
+}
1029
+
10011030 static struct workqueue_struct *qm_portal_wq;
1031
+
1032
+int qman_dqrr_set_ithresh(struct qman_portal *portal, u8 ithresh)
1033
+{
1034
+ int res;
1035
+
1036
+ if (!portal)
1037
+ return -EINVAL;
1038
+
1039
+ res = qm_dqrr_set_ithresh(&portal->p, ithresh);
1040
+ if (res)
1041
+ return res;
1042
+
1043
+ portal->p.dqrr.ithresh = ithresh;
1044
+
1045
+ return 0;
1046
+}
1047
+EXPORT_SYMBOL(qman_dqrr_set_ithresh);
1048
+
1049
+void qman_dqrr_get_ithresh(struct qman_portal *portal, u8 *ithresh)
1050
+{
1051
+ if (portal && ithresh)
1052
+ *ithresh = qm_in(&portal->p, QM_REG_DQRR_ITR);
1053
+}
1054
+EXPORT_SYMBOL(qman_dqrr_get_ithresh);
1055
+
1056
+void qman_portal_get_iperiod(struct qman_portal *portal, u32 *iperiod)
1057
+{
1058
+ if (portal && iperiod)
1059
+ *iperiod = qm_in(&portal->p, QM_REG_ITPR);
1060
+}
1061
+EXPORT_SYMBOL(qman_portal_get_iperiod);
1062
+
1063
+int qman_portal_set_iperiod(struct qman_portal *portal, u32 iperiod)
1064
+{
1065
+ if (!portal || iperiod > QMAN_ITP_MAX)
1066
+ return -EINVAL;
1067
+
1068
+ qm_out(&portal->p, QM_REG_ITPR, iperiod);
1069
+
1070
+ return 0;
1071
+}
1072
+EXPORT_SYMBOL(qman_portal_set_iperiod);
10021073
10031074 int qman_wq_alloc(void)
10041075 {
....@@ -1006,6 +1077,20 @@
10061077 if (!qm_portal_wq)
10071078 return -ENOMEM;
10081079 return 0;
1080
+}
1081
+
1082
+
1083
+void qman_enable_irqs(void)
1084
+{
1085
+ int i;
1086
+
1087
+ for (i = 0; i < num_possible_cpus(); i++) {
1088
+ if (affine_portals[i]) {
1089
+ qm_out(&affine_portals[i]->p, QM_REG_ISR, 0xffffffff);
1090
+ qm_out(&affine_portals[i]->p, QM_REG_IIR, 0);
1091
+ }
1092
+
1093
+ }
10091094 }
10101095
10111096 /*
....@@ -1102,6 +1187,7 @@
11021187 {
11031188 const union qm_mr_entry *msg;
11041189 loop:
1190
+ qm_mr_pvb_update(p);
11051191 msg = qm_mr_current(p);
11061192 if (!msg) {
11071193 /*
....@@ -1118,7 +1204,8 @@
11181204 * entries well before the ring has been fully consumed, so
11191205 * we're being *really* paranoid here.
11201206 */
1121
- msleep(1);
1207
+ mdelay(1);
1208
+ qm_mr_pvb_update(p);
11221209 msg = qm_mr_current(p);
11231210 if (!msg)
11241211 return 0;
....@@ -1205,17 +1292,15 @@
12051292 qm_out(p, QM_REG_ISDR, isdr);
12061293 portal->irq_sources = 0;
12071294 qm_out(p, QM_REG_IER, 0);
1208
- qm_out(p, QM_REG_ISR, 0xffffffff);
12091295 snprintf(portal->irqname, MAX_IRQNAME, IRQNAME, c->cpu);
1296
+ qm_out(p, QM_REG_IIR, 1);
12101297 if (request_irq(c->irq, portal_isr, 0, portal->irqname, portal)) {
12111298 dev_err(c->dev, "request_irq() failed\n");
12121299 goto fail_irq;
12131300 }
1214
- if (c->cpu != -1 && irq_can_set_affinity(c->irq) &&
1215
- irq_set_affinity(c->irq, cpumask_of(c->cpu))) {
1216
- dev_err(c->dev, "irq_set_affinity() failed\n");
1301
+
1302
+ if (dpaa_set_portal_irq_affinity(c->dev, c->irq, c->cpu))
12171303 goto fail_affinity;
1218
- }
12191304
12201305 /* Need EQCR to be empty before continuing */
12211306 isdr &= ~QM_PIRQ_EQCI;
....@@ -1228,7 +1313,7 @@
12281313 isdr &= ~(QM_PIRQ_DQRI | QM_PIRQ_MRI);
12291314 qm_out(p, QM_REG_ISDR, isdr);
12301315 if (qm_dqrr_current(p)) {
1231
- dev_err(c->dev, "DQRR unclean\n");
1316
+ dev_dbg(c->dev, "DQRR unclean\n");
12321317 qm_dqrr_cdc_consume_n(p, 0xffff);
12331318 }
12341319 if (qm_mr_current(p) && drain_mr_fqrni(p)) {
....@@ -1241,8 +1326,10 @@
12411326 }
12421327 /* Success */
12431328 portal->config = c;
1329
+ qm_out(p, QM_REG_ISR, 0xffffffff);
12441330 qm_out(p, QM_REG_ISDR, 0);
1245
- qm_out(p, QM_REG_IIR, 0);
1331
+ if (!qman_requires_cleanup())
1332
+ qm_out(p, QM_REG_IIR, 0);
12461333 /* Write a sane SDQCR */
12471334 qm_dqrr_sdqcr_set(p, portal->sdqcr);
12481335 return 0;
....@@ -1656,6 +1743,13 @@
16561743 return affine_portals[cpu];
16571744 }
16581745 EXPORT_SYMBOL(qman_get_affine_portal);
1746
+
1747
+int qman_start_using_portal(struct qman_portal *p, struct device *dev)
1748
+{
1749
+ return (!device_link_add(dev, p->config->dev,
1750
+ DL_FLAG_AUTOREMOVE_CONSUMER)) ? -EINVAL : 0;
1751
+}
1752
+EXPORT_SYMBOL(qman_start_using_portal);
16591753
16601754 int qman_p_poll_dqrr(struct qman_portal *p, unsigned int limit)
16611755 {
....@@ -2521,9 +2615,9 @@
25212615 #define qm_dqrr_drain_nomatch(p) \
25222616 _qm_dqrr_consume_and_match(p, 0, 0, false)
25232617
2524
-static int qman_shutdown_fq(u32 fqid)
2618
+int qman_shutdown_fq(u32 fqid)
25252619 {
2526
- struct qman_portal *p;
2620
+ struct qman_portal *p, *channel_portal;
25272621 struct device *dev;
25282622 union qm_mc_command *mcc;
25292623 union qm_mc_result *mcr;
....@@ -2563,23 +2657,37 @@
25632657 channel = qm_fqd_get_chan(&mcr->queryfq.fqd);
25642658 wq = qm_fqd_get_wq(&mcr->queryfq.fqd);
25652659
2660
+ if (channel < qm_channel_pool1) {
2661
+ channel_portal = get_portal_for_channel(channel);
2662
+ if (channel_portal == NULL) {
2663
+ dev_err(dev, "Can't find portal for dedicated channel 0x%x\n",
2664
+ channel);
2665
+ ret = -EIO;
2666
+ goto out;
2667
+ }
2668
+ } else
2669
+ channel_portal = p;
2670
+
25662671 switch (state) {
25672672 case QM_MCR_NP_STATE_TEN_SCHED:
25682673 case QM_MCR_NP_STATE_TRU_SCHED:
25692674 case QM_MCR_NP_STATE_ACTIVE:
25702675 case QM_MCR_NP_STATE_PARKED:
25712676 orl_empty = 0;
2572
- mcc = qm_mc_start(&p->p);
2677
+ mcc = qm_mc_start(&channel_portal->p);
25732678 qm_fqid_set(&mcc->fq, fqid);
2574
- qm_mc_commit(&p->p, QM_MCC_VERB_ALTER_RETIRE);
2575
- if (!qm_mc_result_timeout(&p->p, &mcr)) {
2576
- dev_err(dev, "QUERYFQ_NP timeout\n");
2679
+ qm_mc_commit(&channel_portal->p, QM_MCC_VERB_ALTER_RETIRE);
2680
+ if (!qm_mc_result_timeout(&channel_portal->p, &mcr)) {
2681
+ dev_err(dev, "ALTER_RETIRE timeout\n");
25772682 ret = -ETIMEDOUT;
25782683 goto out;
25792684 }
25802685 DPAA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
25812686 QM_MCR_VERB_ALTER_RETIRE);
25822687 res = mcr->result; /* Make a copy as we reuse MCR below */
2688
+
2689
+ if (res == QM_MCR_RESULT_OK)
2690
+ drain_mr_fqrni(&channel_portal->p);
25832691
25842692 if (res == QM_MCR_RESULT_PENDING) {
25852693 /*
....@@ -2610,21 +2718,25 @@
26102718 }
26112719 /* Set the sdqcr to drain this channel */
26122720 if (channel < qm_channel_pool1)
2613
- qm_dqrr_sdqcr_set(&p->p,
2721
+ qm_dqrr_sdqcr_set(&channel_portal->p,
26142722 QM_SDQCR_TYPE_ACTIVE |
26152723 QM_SDQCR_CHANNELS_DEDICATED);
26162724 else
2617
- qm_dqrr_sdqcr_set(&p->p,
2725
+ qm_dqrr_sdqcr_set(&channel_portal->p,
26182726 QM_SDQCR_TYPE_ACTIVE |
26192727 QM_SDQCR_CHANNELS_POOL_CONV
26202728 (channel));
26212729 do {
26222730 /* Keep draining DQRR while checking the MR*/
2623
- qm_dqrr_drain_nomatch(&p->p);
2731
+ qm_dqrr_drain_nomatch(&channel_portal->p);
26242732 /* Process message ring too */
2625
- found_fqrn = qm_mr_drain(&p->p, FQRN);
2733
+ found_fqrn = qm_mr_drain(&channel_portal->p,
2734
+ FQRN);
26262735 cpu_relax();
26272736 } while (!found_fqrn);
2737
+ /* Restore SDQCR */
2738
+ qm_dqrr_sdqcr_set(&channel_portal->p,
2739
+ channel_portal->sdqcr);
26282740
26292741 }
26302742 if (res != QM_MCR_RESULT_OK &&
....@@ -2655,9 +2767,8 @@
26552767 * Wait for a dequeue and process the dequeues,
26562768 * making sure to empty the ring completely
26572769 */
2658
- } while (qm_dqrr_drain_wait(&p->p, fqid, FQ_EMPTY));
2770
+ } while (!qm_dqrr_drain_wait(&p->p, fqid, FQ_EMPTY));
26592771 }
2660
- qm_dqrr_sdqcr_set(&p->p, 0);
26612772
26622773 while (!orl_empty) {
26632774 /* Wait for the ORL to have been completely drained */
....@@ -2694,7 +2805,7 @@
26942805
26952806 DPAA_ASSERT((mcr->verb & QM_MCR_VERB_MASK) ==
26962807 QM_MCR_VERB_ALTER_OOS);
2697
- if (mcr->result) {
2808
+ if (mcr->result != QM_MCR_RESULT_OK) {
26982809 dev_err(dev, "OOS fail: FQ 0x%x (0x%x)\n",
26992810 fqid, mcr->result);
27002811 ret = -EIO;