+static void
+jme_attempt_pcc(struct dynpcc_info *dpi, int atmp)
+{
+ if(likely(atmp == dpi->cur))
+ return;
+
+ if(dpi->attempt == atmp) {
+ ++(dpi->cnt);
+ }
+ else {
+ dpi->attempt = atmp;
+ dpi->cnt = 0;
+ }
+
+}
+
+static void
+jme_dynamic_pcc(struct jme_adapter *jme)
+{
+ register struct dynpcc_info *dpi = &(jme->dpi);
+
+ if((NET_STAT(jme).rx_bytes - dpi->last_bytes) > PCC_P3_THRESHOLD)
+ jme_attempt_pcc(dpi, PCC_P3);
+ else if((NET_STAT(jme).rx_bytes - dpi->last_bytes) > PCC_P2_THRESHOLD
+ || dpi->intr_cnt > PCC_INTR_THRESHOLD)
+ jme_attempt_pcc(dpi, PCC_P2);
+ else
+ jme_attempt_pcc(dpi, PCC_P1);
+
+ if(unlikely(dpi->attempt != dpi->cur && dpi->cnt > 20)) {
+ jme_set_rx_pcc(jme, dpi->attempt);
+ dpi->cur = dpi->attempt;
+ dpi->cnt = 0;
+ }
+}
+
+static void
+jme_start_pcc_timer(struct jme_adapter *jme)
+{
+ struct dynpcc_info *dpi = &(jme->dpi);
+ dpi->last_bytes = NET_STAT(jme).rx_bytes;
+ dpi->last_pkts = NET_STAT(jme).rx_packets;
+ dpi->intr_cnt = 0;
+ jwrite32(jme, JME_TMCSR,
+ TMCSR_EN | ((0xFFFFFF - PCC_INTERVAL_US) & TMCSR_CNT));
+}
+
+static void
+jme_pcc_tasklet(unsigned long arg)
+{
+ struct jme_adapter *jme = (struct jme_adapter*)arg;
+ struct net_device *netdev = jme->dev;
+
+ if(netif_queue_stopped(netdev)) {
+ jwrite32(jme, JME_TMCSR, 0);
+ return;
+ }
+ jme_dynamic_pcc(jme);
+ jme_start_pcc_timer(jme);
+}
+