static void nicvf_get_ethtool_stats(struct net_device *netdev, struct ethtool_stats *stats, u64 *data) { struct nicvf *nic = netdev_priv(netdev); int stat, tmp_stats; int sqs, cpu; nicvf_update_stats(nic); /* Update LMAC stats */ nicvf_update_lmac_stats(nic); for (stat = 0; stat < nicvf_n_hw_stats; stat++) *(data++) = ((u64 *)&nic->hw_stats) [nicvf_hw_stats[stat].index]; for (stat = 0; stat < nicvf_n_drv_stats; stat++) { tmp_stats = 0; for_each_possible_cpu(cpu) tmp_stats += ((u64 *)per_cpu_ptr(nic->drv_stats, cpu)) [nicvf_drv_stats[stat].index]; *(data++) = tmp_stats; } nicvf_get_qset_stats(nic, stats, &data); for (sqs = 0; sqs < nic->sqs_count; sqs++) { if (!nic->snicvf[sqs]) continue; nicvf_get_qset_stats(nic->snicvf[sqs], stats, &data); } for (stat = 0; stat < BGX_RX_STATS_COUNT; stat++) *(data++) = nic->bgx_stats.rx_stats[stat]; for (stat = 0; stat < BGX_TX_STATS_COUNT; stat++) *(data++) = nic->bgx_stats.tx_stats[stat]; }
int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, const struct dp_upcall_info *upcall_info) { struct dp_stats_percpu *stats; int dp_ifindex; int err; if (upcall_info->pid == 0) { err = -ENOTCONN; goto err; } dp_ifindex = get_dpifindex(dp); if (!dp_ifindex) { err = -ENODEV; goto err; } if (!skb_is_gso(skb)) err = queue_userspace_packet(dp_ifindex, skb, upcall_info); else err = queue_gso_packets(dp_ifindex, skb, upcall_info); if (err) goto err; return 0; err: stats = per_cpu_ptr(dp->stats_percpu, smp_processor_id()); u64_stats_update_begin(&stats->sync); stats->n_lost++; u64_stats_update_end(&stats->sync); return err; }
static void probe_mt65xx_mon_tracepoint(void *ignore, struct task_struct *prev, struct task_struct *next) { struct trace_array_cpu *data; unsigned long flags; int cpu; int pc; if (unlikely(!mt65xx_mon_ref)) return; if (!mt65xx_mon_enabled || mt65xx_mon_stopped) return; if(prev) tracing_record_cmdline(prev); if(next) tracing_record_cmdline(next); tracing_record_cmdline(current); pc = preempt_count(); //local_irq_save(flags); spin_lock_irqsave(&mt65xx_mon_spinlock, flags); cpu = raw_smp_processor_id(); #if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0) data = mt65xx_mon_trace->data[cpu]; #else data = per_cpu_ptr(mt65xx_mon_trace->trace_buffer.data, cpu); #endif if (likely(!atomic_read(&data->disabled))) tracing_mt65xx_mon_function(mt65xx_mon_trace, prev, next, flags, pc); spin_unlock_irqrestore(&mt65xx_mon_spinlock, flags); //local_irq_restore(flags); }
/** * thread_group_cputime - Sum the thread group time fields across all CPUs. * * @tsk: The task we use to identify the thread group. * @times: task_cputime structure in which we return the summed fields. * * Walk the list of CPUs to sum the per-CPU time fields in the thread group * time structure. */ void thread_group_cputime( struct task_struct *tsk, struct task_cputime *times) { struct signal_struct *sig; int i; struct task_cputime *tot; sig = tsk->signal; if (unlikely(!sig) || !sig->cputime.totals) { times->utime = tsk->utime; times->stime = tsk->stime; times->sum_exec_runtime = tsk->se.sum_exec_runtime; return; } times->stime = times->utime = cputime_zero; times->sum_exec_runtime = 0; for_each_possible_cpu(i) { tot = per_cpu_ptr(tsk->signal->cputime.totals, i); times->utime = cputime_add(times->utime, tot->utime); times->stime = cputime_add(times->stime, tot->stime); times->sum_exec_runtime += tot->sum_exec_runtime; } }
static struct padata_priv *padata_get_next(struct parallel_data *pd) { int cpu, num_cpus; unsigned int next_nr, next_index; struct padata_parallel_queue *queue, *next_queue; struct padata_priv *padata; struct padata_list *reorder; num_cpus = cpumask_weight(pd->cpumask.pcpu); /* */ next_nr = pd->processed; next_index = next_nr % num_cpus; cpu = padata_index_to_cpu(pd, next_index); next_queue = per_cpu_ptr(pd->pqueue, cpu); padata = NULL; reorder = &next_queue->reorder; if (!list_empty(&reorder->list)) { padata = list_entry(reorder->list.next, struct padata_priv, list); spin_lock(&reorder->lock); list_del_init(&padata->list); atomic_dec(&pd->reorder_objects); spin_unlock(&reorder->lock); pd->processed++; goto out; }
static int minit(void) { int cpu; unsigned long *this; unsigned long file_size = (10 * 1024 * 1024 * 1024); unsigned long chunk_num = file_size / CHUNKSIZE; unsigned long bytes_num = chunk_num / sizeof(int); printk("Start %s.\n", THIS_MODULE->name); percpu_ptr = alloc_percpu(unsigned long); for_each_online_cpu(cpu) { this = *per_cpu_ptr(percpu_ptr, cpu);; //alloc memory for every percpu-value. this = vmalloc(bytes_num); if (!this) { printk(KERN_ERR "alloc bitmap failed."); return -ENOMEM; } } return 0; }
static struct net_device_stats *vlan_dev_get_stats(struct net_device *dev) { struct net_device_stats *stats = &dev->stats; dev_txq_stats_fold(dev, stats); if (vlan_dev_info(dev)->vlan_rx_stats) { struct vlan_rx_stats *p, rx = {0}; int i; for_each_possible_cpu(i) { p = per_cpu_ptr(vlan_dev_info(dev)->vlan_rx_stats, i); rx.rx_packets += p->rx_packets; rx.rx_bytes += p->rx_bytes; rx.rx_errors += p->rx_errors; rx.multicast += p->multicast; } stats->rx_packets = rx.rx_packets; stats->rx_bytes = rx.rx_bytes; stats->rx_errors = rx.rx_errors; stats->multicast = rx.multicast; } return stats; }
static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { if (vlan_dev_priv(dev)->vlan_pcpu_stats) { struct vlan_pcpu_stats *p; u32 rx_errors = 0, tx_dropped = 0; int i; for_each_possible_cpu(i) { u64 rxpackets, rxbytes, rxmulticast, txpackets, txbytes; unsigned int start; p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i); do { start = u64_stats_fetch_begin_bh(&p->syncp); rxpackets = p->rx_packets; rxbytes = p->rx_bytes; rxmulticast = p->rx_multicast; txpackets = p->tx_packets; txbytes = p->tx_bytes; } while (u64_stats_fetch_retry_bh(&p->syncp, start)); stats->rx_packets += rxpackets; stats->rx_bytes += rxbytes; stats->multicast += rxmulticast; stats->tx_packets += txpackets; stats->tx_bytes += txbytes; /* rx_errors & tx_dropped are u32 */ rx_errors += p->rx_errors; tx_dropped += p->tx_dropped; } stats->rx_errors = rx_errors; stats->tx_dropped = tx_dropped; } return stats; }
void caam_qi_shutdown(struct device *qidev) { int i; struct caam_qi_priv *priv = dev_get_drvdata(qidev); const cpumask_t *cpus = qman_affine_cpus(); for_each_cpu(i, cpus) { struct napi_struct *irqtask; irqtask = &per_cpu_ptr(&pcpu_qipriv.caam_napi, i)->irqtask; napi_disable(irqtask); netif_napi_del(irqtask); if (kill_fq(qidev, per_cpu(pcpu_qipriv.rsp_fq, i))) dev_err(qidev, "Rsp FQ kill failed, cpu: %d\n", i); } qman_delete_cgr_safe(&priv->cgr); qman_release_cgrid(priv->cgr.cgrid); kmem_cache_destroy(qi_cache); platform_device_unregister(priv->qi_pdev); }
static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node, const struct cpumask *affinity, struct module *owner) { int cpu; desc->irq_common_data.handler_data = NULL; desc->irq_common_data.msi_desc = NULL; desc->irq_data.common = &desc->irq_common_data; desc->irq_data.irq = irq; desc->irq_data.chip = &no_irq_chip; desc->irq_data.chip_data = NULL; irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); desc->handle_irq = handle_bad_irq; desc->depth = 1; desc->irq_count = 0; desc->irqs_unhandled = 0; desc->name = NULL; desc->owner = owner; for_each_possible_cpu(cpu) *per_cpu_ptr(desc->kstat_irqs, cpu) = 0; desc_smp_init(desc, node, affinity); }
/** * ixgbe_fcoe_ddp_setup - called to set up ddp context * @netdev: the corresponding net_device * @xid: the exchange id requesting ddp * @sgl: the scatter-gather list for this request * @sgc: the number of scatter-gather items * * Returns : 1 for success and 0 for no ddp */ static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid, struct scatterlist *sgl, unsigned int sgc, int target_mode) { struct ixgbe_adapter *adapter; struct ixgbe_hw *hw; struct ixgbe_fcoe *fcoe; struct ixgbe_fcoe_ddp *ddp; struct ixgbe_fcoe_ddp_pool *ddp_pool; struct scatterlist *sg; unsigned int i, j, dmacount; unsigned int len; static const unsigned int bufflen = IXGBE_FCBUFF_MIN; unsigned int firstoff = 0; unsigned int lastsize; unsigned int thisoff = 0; unsigned int thislen = 0; u32 fcbuff, fcdmarw, fcfltrw, fcrxctl; dma_addr_t addr = 0; if (!netdev || !sgl) return 0; adapter = netdev_priv(netdev); if (xid >= IXGBE_FCOE_DDP_MAX) { e_warn(drv, "xid=0x%x out-of-range\n", xid); return 0; } /* no DDP if we are already down or resetting */ if (test_bit(__IXGBE_DOWN, &adapter->state) || test_bit(__IXGBE_RESETTING, &adapter->state)) return 0; fcoe = &adapter->fcoe; ddp = &fcoe->ddp[xid]; if (ddp->sgl) { e_err(drv, "xid 0x%x w/ non-null sgl=%p nents=%d\n", xid, ddp->sgl, ddp->sgc); return 0; } ixgbe_fcoe_clear_ddp(ddp); if (!fcoe->ddp_pool) { e_warn(drv, "No ddp_pool resources allocated\n"); return 0; } ddp_pool = per_cpu_ptr(fcoe->ddp_pool, get_cpu()); if (!ddp_pool->pool) { e_warn(drv, "xid=0x%x no ddp pool for fcoe\n", xid); goto out_noddp; } /* setup dma from scsi command sgl */ dmacount = dma_map_sg(&adapter->pdev->dev, sgl, sgc, DMA_FROM_DEVICE); if (dmacount == 0) { e_err(drv, "xid 0x%x DMA map error\n", xid); goto out_noddp; } /* alloc the udl from per cpu ddp pool */ ddp->udl = dma_pool_alloc(ddp_pool->pool, GFP_ATOMIC, &ddp->udp); if (!ddp->udl) { e_err(drv, "failed allocated ddp context\n"); goto out_noddp_unmap; } ddp->pool = ddp_pool->pool; ddp->sgl = sgl; ddp->sgc = sgc; j = 0; for_each_sg(sgl, sg, dmacount, i) { addr = sg_dma_address(sg); len = sg_dma_len(sg); while (len) { /* max number of buffers allowed in one DDP context */ if (j >= IXGBE_BUFFCNT_MAX) { ddp_pool->noddp++; goto out_noddp_free; } /* get the offset of length of current buffer */ thisoff = addr & ((dma_addr_t)bufflen - 1); thislen = min((bufflen - thisoff), len); /* * all but the 1st buffer (j == 0) * must be aligned on bufflen */ if ((j != 0) && (thisoff)) goto out_noddp_free; /* * all but the last buffer * ((i == (dmacount - 1)) && (thislen == len)) * must end at bufflen */ if (((i != (dmacount - 1)) || (thislen != len)) && ((thislen + thisoff) != bufflen)) goto out_noddp_free; ddp->udl[j] = (u64)(addr - thisoff); /* only the first buffer may have none-zero offset */ if (j == 0) firstoff = thisoff; len -= thislen; addr += thislen; j++; } }
padata = list_entry(reorder->list.next, struct padata_priv, list); BUG_ON(next_nr != padata->seq_nr); spin_lock(&reorder->lock); list_del_init(&padata->list); atomic_dec(&pd->reorder_objects); spin_unlock(&reorder->lock); pd->processed++; goto out; } queue = per_cpu_ptr(pd->pqueue, smp_processor_id()); if (queue->cpu_index == next_queue->cpu_index) { padata = ERR_PTR(-ENODATA); goto out; } padata = ERR_PTR(-EINPROGRESS); out: return padata; } static void padata_reorder(struct parallel_data *pd) { struct padata_priv *padata; struct padata_serial_queue *squeue; struct padata_instance *pinst = pd->pinst;
static int __init tegra_init_timer(struct device_node *np, bool tegra20) { struct timer_of *to; int cpu, ret; to = this_cpu_ptr(&tegra_to); ret = timer_of_init(np, to); if (ret) goto out; timer_reg_base = timer_of_base(to); /* * Configure microsecond timers to have 1MHz clock * Config register is 0xqqww, where qq is "dividend", ww is "divisor" * Uses n+1 scheme */ switch (timer_of_rate(to)) { case 12000000: usec_config = 0x000b; /* (11+1)/(0+1) */ break; case 12800000: usec_config = 0x043f; /* (63+1)/(4+1) */ break; case 13000000: usec_config = 0x000c; /* (12+1)/(0+1) */ break; case 16800000: usec_config = 0x0453; /* (83+1)/(4+1) */ break; case 19200000: usec_config = 0x045f; /* (95+1)/(4+1) */ break; case 26000000: usec_config = 0x0019; /* (25+1)/(0+1) */ break; case 38400000: usec_config = 0x04bf; /* (191+1)/(4+1) */ break; case 48000000: usec_config = 0x002f; /* (47+1)/(0+1) */ break; default: ret = -EINVAL; goto out; } writel_relaxed(usec_config, timer_reg_base + TIMERUS_USEC_CFG); for_each_possible_cpu(cpu) { struct timer_of *cpu_to = per_cpu_ptr(&tegra_to, cpu); unsigned int base = tegra_base_for_cpu(cpu, tegra20); unsigned int idx = tegra_irq_idx_for_cpu(cpu, tegra20); /* * TIMER1-9 are fixed to 1MHz, TIMER10-13 are running off the * parent clock. */ if (tegra20) cpu_to->of_clk.rate = 1000000; cpu_to = per_cpu_ptr(&tegra_to, cpu); cpu_to->of_base.base = timer_reg_base + base; cpu_to->clkevt.cpumask = cpumask_of(cpu); cpu_to->clkevt.irq = irq_of_parse_and_map(np, idx); if (!cpu_to->clkevt.irq) { pr_err("failed to map irq for cpu%d\n", cpu); ret = -EINVAL; goto out_irq; } irq_set_status_flags(cpu_to->clkevt.irq, IRQ_NOAUTOEN); ret = request_irq(cpu_to->clkevt.irq, tegra_timer_isr, IRQF_TIMER | IRQF_NOBALANCING, cpu_to->clkevt.name, &cpu_to->clkevt); if (ret) { pr_err("failed to set up irq for cpu%d: %d\n", cpu, ret); irq_dispose_mapping(cpu_to->clkevt.irq); cpu_to->clkevt.irq = 0; goto out_irq; } } sched_clock_register(tegra_read_sched_clock, 32, 1000000); ret = clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US, "timer_us", 1000000, 300, 32, clocksource_mmio_readl_up); if (ret) pr_err("failed to register clocksource: %d\n", ret); #ifdef CONFIG_ARM register_current_timer_delay(&tegra_delay_timer); #endif ret = cpuhp_setup_state(CPUHP_AP_TEGRA_TIMER_STARTING, "AP_TEGRA_TIMER_STARTING", tegra_timer_setup, tegra_timer_stop); if (ret) pr_err("failed to set up cpu hp state: %d\n", ret); return ret; out_irq: for_each_possible_cpu(cpu) { struct timer_of *cpu_to; cpu_to = per_cpu_ptr(&tegra_to, cpu); if (cpu_to->clkevt.irq) { free_irq(cpu_to->clkevt.irq, &cpu_to->clkevt); irq_dispose_mapping(cpu_to->clkevt.irq); } } out: timer_of_cleanup(to); return ret; }
static struct cgroup_cpu_stat *cgroup_cpu_stat(struct cgroup *cgrp, int cpu) { return per_cpu_ptr(cgrp->cpu_stat, cpu); }
static int ipcomp_decompress(struct xfrm_state *x, struct sk_buff *skb) { struct ipcomp_data *ipcd = x->data; const int plen = skb->len; int dlen = IPCOMP_SCRATCH_SIZE; const u8 *start = skb->data; const int cpu = get_cpu(); u8 *scratch = *per_cpu_ptr(ipcomp_scratches, cpu); struct crypto_comp *tfm = *per_cpu_ptr(ipcd->tfms, cpu); int err = crypto_comp_decompress(tfm, start, plen, scratch, &dlen); int len; if (err) goto out; if (dlen < (plen + sizeof(struct ip_comp_hdr))) { err = -EINVAL; goto out; } len = dlen - plen; if (len > skb_tailroom(skb)) len = skb_tailroom(skb); __skb_put(skb, len); len += plen; skb_copy_to_linear_data(skb, scratch, len); while ((scratch += len, dlen -= len) > 0) { skb_frag_t *frag; struct page *page; err = -EMSGSIZE; if (WARN_ON(skb_shinfo(skb)->nr_frags >= MAX_SKB_FRAGS)) goto out; frag = skb_shinfo(skb)->frags + skb_shinfo(skb)->nr_frags; page = alloc_page(GFP_ATOMIC); err = -ENOMEM; if (!page) goto out; __skb_frag_set_page(frag, page); len = PAGE_SIZE; if (dlen < len) len = dlen; frag->page_offset = 0; skb_frag_size_set(frag, len); memcpy(skb_frag_address(frag), scratch, len); skb->truesize += len; skb->data_len += len; skb->len += len; skb_shinfo(skb)->nr_frags++; } err = 0; out: put_cpu(); return err; }
/** Fill in hardware counters, as returned by MC. */ static void dpaa2_eth_get_ethtool_stats(struct net_device *net_dev, struct ethtool_stats *stats, u64 *data) { int i = 0; int j, k, err; int num_cnt; union dpni_statistics dpni_stats; u32 fcnt, bcnt; u32 fcnt_rx_total = 0, fcnt_tx_total = 0; u32 bcnt_rx_total = 0, bcnt_tx_total = 0; u32 buf_cnt; struct dpaa2_eth_priv *priv = netdev_priv(net_dev); struct dpaa2_eth_drv_stats *extras; struct dpaa2_eth_ch_stats *ch_stats; memset(data, 0, sizeof(u64) * (DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS)); /* Print standard counters, from DPNI statistics */ for (j = 0; j <= 2; j++) { err = dpni_get_statistics(priv->mc_io, 0, priv->mc_token, j, &dpni_stats); if (err != 0) netdev_warn(net_dev, "dpni_get_stats(%d) failed\n", j); switch (j) { case 0: num_cnt = sizeof(dpni_stats.page_0) / sizeof(u64); break; case 1: num_cnt = sizeof(dpni_stats.page_1) / sizeof(u64); break; case 2: num_cnt = sizeof(dpni_stats.page_2) / sizeof(u64); break; } for (k = 0; k < num_cnt; k++) *(data + i++) = dpni_stats.raw.counter[k]; } /* Print per-cpu extra stats */ for_each_online_cpu(k) { extras = per_cpu_ptr(priv->percpu_extras, k); for (j = 0; j < sizeof(*extras) / sizeof(__u64); j++) *((__u64 *)data + i + j) += *((__u64 *)extras + j); } i += j; /* Per-channel stats */ for (k = 0; k < priv->num_channels; k++) { ch_stats = &priv->channel[k]->stats; for (j = 0; j < sizeof(*ch_stats) / sizeof(__u64); j++) *((__u64 *)data + i + j) += *((__u64 *)ch_stats + j); } i += j; for (j = 0; j < priv->num_fqs; j++) { /* Print FQ instantaneous counts */ err = dpaa2_io_query_fq_count(NULL, priv->fq[j].fqid, &fcnt, &bcnt); if (err) { netdev_warn(net_dev, "FQ query error %d", err); return; } if (priv->fq[j].type == DPAA2_TX_CONF_FQ) { fcnt_tx_total += fcnt; bcnt_tx_total += bcnt; } else { fcnt_rx_total += fcnt; bcnt_rx_total += bcnt; } } *(data + i++) = fcnt_rx_total; *(data + i++) = bcnt_rx_total; *(data + i++) = fcnt_tx_total; *(data + i++) = bcnt_tx_total; err = dpaa2_io_query_bp_count(NULL, priv->bpid, &buf_cnt); if (err) { netdev_warn(net_dev, "Buffer count query error %d\n", err); return; } *(data + i++) = buf_cnt; }
static int clamp_thread(void *arg) { int cpunr = (unsigned long)arg; DEFINE_TIMER(wakeup_timer, noop_timer, 0, 0); static const struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, }; unsigned int count = 0; unsigned int target_ratio; set_bit(cpunr, cpu_clamping_mask); set_freezable(); init_timer_on_stack(&wakeup_timer); sched_setscheduler(current, SCHED_FIFO, ¶m); while (true == clamping && !kthread_should_stop() && cpu_online(cpunr)) { int sleeptime; unsigned long target_jiffies; unsigned int guard; unsigned int compensated_ratio; int interval; /* jiffies to sleep for each attempt */ unsigned int duration_jiffies = msecs_to_jiffies(duration); unsigned int window_size_now; try_to_freeze(); /* * make sure user selected ratio does not take effect until * the next round. adjust target_ratio if user has changed * target such that we can converge quickly. */ target_ratio = set_target_ratio; guard = 1 + target_ratio/20; window_size_now = window_size; count++; /* * systems may have different ability to enter package level * c-states, thus we need to compensate the injected idle ratio * to achieve the actual target reported by the HW. */ compensated_ratio = target_ratio + get_compensation(target_ratio); if (compensated_ratio <= 0) compensated_ratio = 1; interval = duration_jiffies * 100 / compensated_ratio; /* align idle time */ target_jiffies = roundup(jiffies, interval); sleeptime = target_jiffies - jiffies; if (sleeptime <= 0) sleeptime = 1; schedule_timeout_interruptible(sleeptime); /* * only elected controlling cpu can collect stats and update * control parameters. */ if (cpunr == control_cpu && !(count%window_size_now)) { should_skip = powerclamp_adjust_controls(target_ratio, guard, window_size_now); smp_mb(); } if (should_skip) continue; target_jiffies = jiffies + duration_jiffies; mod_timer(&wakeup_timer, target_jiffies); if (unlikely(local_softirq_pending())) continue; /* * stop tick sched during idle time, interrupts are still * allowed. thus jiffies are updated properly. */ preempt_disable(); /* mwait until target jiffies is reached */ while (time_before(jiffies, target_jiffies)) { unsigned long ecx = 1; unsigned long eax = target_mwait; /* * REVISIT: may call enter_idle() to notify drivers who * can save power during cpu idle. same for exit_idle() */ local_touch_nmi(); stop_critical_timings(); mwait_idle_with_hints(eax, ecx); start_critical_timings(); atomic_inc(&idle_wakeup_counter); } preempt_enable(); } del_timer_sync(&wakeup_timer); clear_bit(cpunr, cpu_clamping_mask); return 0; } /* * 1 HZ polling while clamping is active, useful for userspace * to monitor actual idle ratio. */ static void poll_pkg_cstate(struct work_struct *dummy); static DECLARE_DELAYED_WORK(poll_pkg_cstate_work, poll_pkg_cstate); static void poll_pkg_cstate(struct work_struct *dummy) { static u64 msr_last; static u64 tsc_last; static unsigned long jiffies_last; u64 msr_now; unsigned long jiffies_now; u64 tsc_now; u64 val64; msr_now = pkg_state_counter(); tsc_now = rdtsc(); jiffies_now = jiffies; /* calculate pkg cstate vs tsc ratio */ if (!msr_last || !tsc_last) pkg_cstate_ratio_cur = 1; else { if (tsc_now - tsc_last) { val64 = 100 * (msr_now - msr_last); do_div(val64, (tsc_now - tsc_last)); pkg_cstate_ratio_cur = val64; } } /* update record */ msr_last = msr_now; jiffies_last = jiffies_now; tsc_last = tsc_now; if (true == clamping) schedule_delayed_work(&poll_pkg_cstate_work, HZ); } static int start_power_clamp(void) { unsigned long cpu; struct task_struct *thread; set_target_ratio = clamp(set_target_ratio, 0U, MAX_TARGET_RATIO - 1); /* prevent cpu hotplug */ get_online_cpus(); /* prefer BSP */ control_cpu = 0; if (!cpu_online(control_cpu)) control_cpu = smp_processor_id(); clamping = true; schedule_delayed_work(&poll_pkg_cstate_work, 0); /* start one thread per online cpu */ for_each_online_cpu(cpu) { struct task_struct **p = per_cpu_ptr(powerclamp_thread, cpu); thread = kthread_create_on_node(clamp_thread, (void *) cpu, cpu_to_node(cpu), "kidle_inject/%ld", cpu); /* bind to cpu here */ if (likely(!IS_ERR(thread))) { kthread_bind(thread, cpu); wake_up_process(thread); *p = thread; } } put_online_cpus(); return 0; }
static inline struct acpi_processor_performance *to_perf_data(struct acpi_cpufreq_data *data) { return per_cpu_ptr(acpi_perf_data, data->acpi_perf_cpu); }
static int prepare_elf64_headers(struct crash_elf_data *ced, void **addr, unsigned long *sz) { Elf64_Ehdr *ehdr; Elf64_Phdr *phdr; unsigned long nr_cpus = num_possible_cpus(), nr_phdr, elf_sz; unsigned char *buf, *bufp; unsigned int cpu; unsigned long long notes_addr; int ret; /* extra phdr for vmcoreinfo elf note */ nr_phdr = nr_cpus + 1; nr_phdr += ced->max_nr_ranges; /* * kexec-tools creates an extra PT_LOAD phdr for kernel text mapping * area on x86_64 (ffffffff80000000 - ffffffffa0000000). * I think this is required by tools like gdb. So same physical * memory will be mapped in two elf headers. One will contain kernel * text virtual addresses and other will have __va(physical) addresses. */ nr_phdr++; elf_sz = sizeof(Elf64_Ehdr) + nr_phdr * sizeof(Elf64_Phdr); elf_sz = ALIGN(elf_sz, ELF_CORE_HEADER_ALIGN); buf = vzalloc(elf_sz); if (!buf) return -ENOMEM; bufp = buf; ehdr = (Elf64_Ehdr *)bufp; bufp += sizeof(Elf64_Ehdr); memcpy(ehdr->e_ident, ELFMAG, SELFMAG); ehdr->e_ident[EI_CLASS] = ELFCLASS64; ehdr->e_ident[EI_DATA] = ELFDATA2LSB; ehdr->e_ident[EI_VERSION] = EV_CURRENT; ehdr->e_ident[EI_OSABI] = ELF_OSABI; memset(ehdr->e_ident + EI_PAD, 0, EI_NIDENT - EI_PAD); ehdr->e_type = ET_CORE; ehdr->e_machine = ELF_ARCH; ehdr->e_version = EV_CURRENT; ehdr->e_phoff = sizeof(Elf64_Ehdr); ehdr->e_ehsize = sizeof(Elf64_Ehdr); ehdr->e_phentsize = sizeof(Elf64_Phdr); /* Prepare one phdr of type PT_NOTE for each present cpu */ for_each_present_cpu(cpu) { phdr = (Elf64_Phdr *)bufp; bufp += sizeof(Elf64_Phdr); phdr->p_type = PT_NOTE; notes_addr = per_cpu_ptr_to_phys(per_cpu_ptr(crash_notes, cpu)); phdr->p_offset = phdr->p_paddr = notes_addr; phdr->p_filesz = phdr->p_memsz = sizeof(note_buf_t); (ehdr->e_phnum)++; } /* Prepare one PT_NOTE header for vmcoreinfo */ phdr = (Elf64_Phdr *)bufp; bufp += sizeof(Elf64_Phdr); phdr->p_type = PT_NOTE; phdr->p_offset = phdr->p_paddr = paddr_vmcoreinfo_note(); phdr->p_filesz = phdr->p_memsz = sizeof(vmcoreinfo_note); (ehdr->e_phnum)++; #ifdef CONFIG_X86_64 /* Prepare PT_LOAD type program header for kernel text region */ phdr = (Elf64_Phdr *)bufp; bufp += sizeof(Elf64_Phdr); phdr->p_type = PT_LOAD; phdr->p_flags = PF_R|PF_W|PF_X; phdr->p_vaddr = (Elf64_Addr)_text; phdr->p_filesz = phdr->p_memsz = _end - _text; phdr->p_offset = phdr->p_paddr = __pa_symbol(_text); (ehdr->e_phnum)++; #endif /* Prepare PT_LOAD headers for system ram chunks. */ ced->ehdr = ehdr; ced->bufp = bufp; ret = walk_system_ram_res(0, -1, ced, prepare_elf64_ram_headers_callback); if (ret < 0) return ret; *addr = buf; *sz = elf_sz; return 0; }
/* * The worker for the various blk_add_trace*() types. Fills out a * blk_io_trace structure and places it in a per-cpu subbuffer. */ static void __blk_add_trace(struct blk_trace *bt, sector_t sector, int bytes, int rw, u32 what, int error, int pdu_len, void *pdu_data) { struct task_struct *tsk = current; struct ring_buffer_event *event = NULL; struct ring_buffer *buffer = NULL; struct blk_io_trace *t; unsigned long flags = 0; unsigned long *sequence; pid_t pid; int cpu, pc = 0; bool blk_tracer = blk_tracer_enabled; if (unlikely(bt->trace_state != Blktrace_running && !blk_tracer)) return; what |= ddir_act[rw & WRITE]; what |= MASK_TC_BIT(rw, SYNCIO); what |= MASK_TC_BIT(rw, AHEAD); what |= MASK_TC_BIT(rw, META); what |= MASK_TC_BIT(rw, DISCARD); what |= MASK_TC_BIT(rw, FLUSH); what |= MASK_TC_BIT(rw, FUA); pid = tsk->pid; if (act_log_check(bt, what, sector, pid)) return; cpu = raw_smp_processor_id(); if (blk_tracer) { tracing_record_cmdline(current); buffer = blk_tr->buffer; pc = preempt_count(); event = trace_buffer_lock_reserve(buffer, TRACE_BLK, sizeof(*t) + pdu_len, 0, pc); if (!event) return; t = ring_buffer_event_data(event); goto record_it; } /* * A word about the locking here - we disable interrupts to reserve * some space in the relay per-cpu buffer, to prevent an irq * from coming in and stepping on our toes. */ local_irq_save(flags); if (unlikely(tsk->btrace_seq != blktrace_seq)) trace_note_tsk(bt, tsk); t = relay_reserve(bt->rchan, sizeof(*t) + pdu_len); if (t) { sequence = per_cpu_ptr(bt->sequence, cpu); t->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; t->sequence = ++(*sequence); t->time = ktime_to_ns(ktime_get()); record_it: /* * These two are not needed in ftrace as they are in the * generic trace_entry, filled by tracing_generic_entry_update, * but for the trace_event->bin() synthesizer benefit we do it * here too. */ t->cpu = cpu; t->pid = pid; t->sector = sector; t->bytes = bytes; t->action = what; t->device = bt->dev; t->error = error; t->pdu_len = pdu_len; if (pdu_len) memcpy((void *) t + sizeof(*t), pdu_data, pdu_len); if (blk_tracer) { trace_buffer_unlock_commit(buffer, event, 0, pc); return; } } local_irq_restore(flags); }
static void dump_traces(void) { int *index; struct trace_log_entry *ptr; int i, cpu, max_entries, idx; struct trace_log_header *header; header = (struct trace_log_header *)trace_log_data.start_vaddr; pr_info("\n-------TRACE LOG---->8---------\n"); max_entries = header->entries; pr_info("max entries:%d\n", max_entries); if (trace_log_data.entries != max_entries) pr_err("max entries mismatch - %d, %d\n", max_entries, trace_log_data.entries); for_each_possible_cpu(cpu) { idx = header->index[IRQ_TRACE][cpu]; pr_info("\nIRQ_TRACE, cpu:%d, current index:%d", cpu, idx - 1); index = per_cpu_ptr(trace_log_data.index[IRQ_TRACE], cpu); if (idx != *index) pr_err("IRQ_TRACE indices mismatch. %d, %d\n", idx, *index); for (i = 0; i < max_entries; i++) { ptr = trace_log_data.start[cpu] + (i * SIZEOF_ENTRIES); pr_info("%d:%s: irq:%d, timestamp:%lu\n", i, (ptr->itl.irq & 0x40000000) ? "ENTRY" : "EXIT", ptr->itl.irq & ~0x40000000, ptr->itl.timestamp); } idx = header->index[SOFTIRQ_TRACE][cpu]; pr_info("\nSOFTIRQ_TRACE, cpu:%d, current index:%d", cpu, idx - 1); index = per_cpu_ptr(trace_log_data.index[SOFTIRQ_TRACE], cpu); if (idx != *index) pr_err("SOFTIRQ_TRACE indices mismatch. %d, %d\n", idx, *index); for (i = 0; i < max_entries; i++) { ptr = trace_log_data.start[cpu] + (i * SIZEOF_ENTRIES); pr_info("%d:%s: vec_nr:%d, timestamp:%lu\n", i, (ptr->stl.vec_nr & 0x80000000) ? "ENTRY" : "EXIT", ptr->stl.vec_nr & ~0x80000000, ptr->stl.timestamp); } idx = header->index[SCHED_TRACE][cpu]; pr_info("\nSCHED_TRACE, cpu:%d, current index:%d", cpu, idx - 1); index = per_cpu_ptr(trace_log_data.index[SCHED_TRACE], cpu); if (idx != *index) pr_err("SCHED_TRACE indices mismatch. %d, %d\n", idx, *index); for (i = 0; i < max_entries; i++) { ptr = trace_log_data.start[cpu] + (i * SIZEOF_ENTRIES); pr_info("%d:pid:%d, timestamp:%lu\n", i, ptr->sstl.pid, ptr->sstl.timestamp); } idx = header->index[WORKQUEUE_TRACE][cpu]; pr_info("\nWORKQUEUE_TRACE, cpu:%d, current index:%d", cpu, idx - 1); index = per_cpu_ptr(trace_log_data.index[WORKQUEUE_TRACE], cpu); if (idx != *index) pr_err("WORKQUEUE_TRACE indices mismatch. %d, %d\n", idx, *index); for (i = 0; i < max_entries; i++) { ptr = trace_log_data.start[cpu] + (i * SIZEOF_ENTRIES); pr_info("%d:%s: %p, timestamp:%lu\n", i, ptr->wtl.entry ? "ENTRY" : "EXIT", ptr->wtl.func, ptr->wtl.timestamp); } } pr_info("------END OF TRACE LOG----->8-----------\n"); }
static u32 drv_read(struct acpi_cpufreq_data *data, const struct cpumask *mask) { struct acpi_processor_performance *perf = to_perf_data(data); struct drv_cmd cmd = { .reg = &perf->control_register, .func.read = data->cpu_freq_read, }; int err; err = smp_call_function_any(mask, do_drv_read, &cmd, 1); WARN_ON_ONCE(err); /* smp_call_function_any() was buggy? */ return cmd.val; } /* Called via smp_call_function_many(), on the target CPUs */ static void do_drv_write(void *_cmd) { struct drv_cmd *cmd = _cmd; cmd->func.write(cmd->reg, cmd->val); } static void drv_write(struct acpi_cpufreq_data *data, const struct cpumask *mask, u32 val) { struct acpi_processor_performance *perf = to_perf_data(data); struct drv_cmd cmd = { .reg = &perf->control_register, .val = val, .func.write = data->cpu_freq_write, }; int this_cpu; this_cpu = get_cpu(); if (cpumask_test_cpu(this_cpu, mask)) do_drv_write(&cmd); smp_call_function_many(mask, do_drv_write, &cmd, 1); put_cpu(); } static u32 get_cur_val(const struct cpumask *mask, struct acpi_cpufreq_data *data) { u32 val; if (unlikely(cpumask_empty(mask))) return 0; val = drv_read(data, mask); pr_debug("get_cur_val = %u\n", val); return val; } static unsigned int get_cur_freq_on_cpu(unsigned int cpu) { struct acpi_cpufreq_data *data; struct cpufreq_policy *policy; unsigned int freq; unsigned int cached_freq; pr_debug("get_cur_freq_on_cpu (%d)\n", cpu); policy = cpufreq_cpu_get_raw(cpu); if (unlikely(!policy)) return 0; data = policy->driver_data; if (unlikely(!data || !policy->freq_table)) return 0; cached_freq = policy->freq_table[to_perf_data(data)->state].frequency; freq = extract_freq(policy, get_cur_val(cpumask_of(cpu), data)); if (freq != cached_freq) { /* * The dreaded BIOS frequency change behind our back. * Force set the frequency on next target call. */ data->resume = 1; } pr_debug("cur freq = %u\n", freq); return freq; } static unsigned int check_freqs(struct cpufreq_policy *policy, const struct cpumask *mask, unsigned int freq) { struct acpi_cpufreq_data *data = policy->driver_data; unsigned int cur_freq; unsigned int i; for (i = 0; i < 100; i++) { cur_freq = extract_freq(policy, get_cur_val(mask, data)); if (cur_freq == freq) return 1; udelay(10); } return 0; } static int acpi_cpufreq_target(struct cpufreq_policy *policy, unsigned int index) { struct acpi_cpufreq_data *data = policy->driver_data; struct acpi_processor_performance *perf; const struct cpumask *mask; unsigned int next_perf_state = 0; /* Index into perf table */ int result = 0; if (unlikely(!data)) { return -ENODEV; } perf = to_perf_data(data); next_perf_state = policy->freq_table[index].driver_data; if (perf->state == next_perf_state) { if (unlikely(data->resume)) { pr_debug("Called after resume, resetting to P%d\n", next_perf_state); data->resume = 0; } else { pr_debug("Already at target state (P%d)\n", next_perf_state); return 0; } } /* * The core won't allow CPUs to go away until the governor has been * stopped, so we can rely on the stability of policy->cpus. */ mask = policy->shared_type == CPUFREQ_SHARED_TYPE_ANY ? cpumask_of(policy->cpu) : policy->cpus; drv_write(data, mask, perf->states[next_perf_state].control); if (acpi_pstate_strict) { if (!check_freqs(policy, mask, policy->freq_table[index].frequency)) { pr_debug("acpi_cpufreq_target failed (%d)\n", policy->cpu); result = -EAGAIN; } } if (!result) perf->state = next_perf_state; return result; } unsigned int acpi_cpufreq_fast_switch(struct cpufreq_policy *policy, unsigned int target_freq) { struct acpi_cpufreq_data *data = policy->driver_data; struct acpi_processor_performance *perf; struct cpufreq_frequency_table *entry; unsigned int next_perf_state, next_freq, index; /* * Find the closest frequency above target_freq. */ if (policy->cached_target_freq == target_freq) index = policy->cached_resolved_idx; else index = cpufreq_table_find_index_dl(policy, target_freq); entry = &policy->freq_table[index]; next_freq = entry->frequency; next_perf_state = entry->driver_data; perf = to_perf_data(data); if (perf->state == next_perf_state) { if (unlikely(data->resume)) data->resume = 0; else return next_freq; } data->cpu_freq_write(&perf->control_register, perf->states[next_perf_state].control); perf->state = next_perf_state; return next_freq; } static unsigned long acpi_cpufreq_guess_freq(struct acpi_cpufreq_data *data, unsigned int cpu) { struct acpi_processor_performance *perf; perf = to_perf_data(data); if (cpu_khz) { /* search the closest match to cpu_khz */ unsigned int i; unsigned long freq; unsigned long freqn = perf->states[0].core_frequency * 1000; for (i = 0; i < (perf->state_count-1); i++) { freq = freqn; freqn = perf->states[i+1].core_frequency * 1000; if ((2 * cpu_khz) > (freqn + freq)) { perf->state = i; return freq; } } perf->state = perf->state_count-1; return freqn; } else { /* assume CPU is at P0... */ perf->state = 0; return perf->states[0].core_frequency * 1000; } } static void free_acpi_perf_data(void) { unsigned int i; /* Freeing a NULL pointer is OK, and alloc_percpu zeroes. */ for_each_possible_cpu(i) free_cpumask_var(per_cpu_ptr(acpi_perf_data, i) ->shared_cpu_map); free_percpu(acpi_perf_data); }
static inline struct optimistic_spin_node *decode_cpu(int encoded_cpu_val) { int cpu_nr = encoded_cpu_val - 1; return per_cpu_ptr(&osq_node, cpu_nr); }
/* * Present statistical information for this VFS mountpoint */ static int nfs_show_stats(struct seq_file *m, struct vfsmount *mnt) { int i, cpu; struct nfs_server *nfss = NFS_SB(mnt->mnt_sb); struct rpc_auth *auth = nfss->client->cl_auth; struct nfs_iostats totals = { }; seq_printf(m, "statvers=%s", NFS_IOSTAT_VERS); /* * Display all mount option settings */ seq_printf(m, "\n\topts:\t"); seq_puts(m, mnt->mnt_sb->s_flags & MS_RDONLY ? "ro" : "rw"); seq_puts(m, mnt->mnt_sb->s_flags & MS_SYNCHRONOUS ? ",sync" : ""); seq_puts(m, mnt->mnt_sb->s_flags & MS_NOATIME ? ",noatime" : ""); seq_puts(m, mnt->mnt_sb->s_flags & MS_NODIRATIME ? ",nodiratime" : ""); nfs_show_mount_options(m, nfss, 1); seq_printf(m, "\n\tage:\t%lu", (jiffies - nfss->mount_time) / HZ); seq_printf(m, "\n\tcaps:\t"); seq_printf(m, "caps=0x%x", nfss->caps); seq_printf(m, ",wtmult=%d", nfss->wtmult); seq_printf(m, ",dtsize=%d", nfss->dtsize); seq_printf(m, ",bsize=%d", nfss->bsize); seq_printf(m, ",namelen=%d", nfss->namelen); #ifdef CONFIG_NFS_V4 if (nfss->nfs_client->cl_nfsversion == 4) { seq_printf(m, "\n\tnfsv4:\t"); seq_printf(m, "bm0=0x%x", nfss->attr_bitmask[0]); seq_printf(m, ",bm1=0x%x", nfss->attr_bitmask[1]); seq_printf(m, ",acl=0x%x", nfss->acl_bitmask); } #endif /* * Display security flavor in effect for this mount */ seq_printf(m, "\n\tsec:\tflavor=%d", auth->au_ops->au_flavor); if (auth->au_flavor) seq_printf(m, ",pseudoflavor=%d", auth->au_flavor); /* * Display superblock I/O counters */ for_each_possible_cpu(cpu) { struct nfs_iostats *stats; preempt_disable(); stats = per_cpu_ptr(nfss->io_stats, cpu); for (i = 0; i < __NFSIOS_COUNTSMAX; i++) totals.events[i] += stats->events[i]; for (i = 0; i < __NFSIOS_BYTESMAX; i++) totals.bytes[i] += stats->bytes[i]; preempt_enable(); } seq_printf(m, "\n\tevents:\t"); for (i = 0; i < __NFSIOS_COUNTSMAX; i++) seq_printf(m, "%lu ", totals.events[i]); seq_printf(m, "\n\tbytes:\t"); for (i = 0; i < __NFSIOS_BYTESMAX; i++) seq_printf(m, "%Lu ", totals.bytes[i]); seq_printf(m, "\n"); rpc_print_iostats(m, nfss->client); return 0; }
static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus, struct nd_region_desc *ndr_desc, struct device_type *dev_type, const char *caller) { struct nd_region *nd_region; struct device *dev; void *region_buf; unsigned int i; int ro = 0; for (i = 0; i < ndr_desc->num_mappings; i++) { struct nd_mapping *nd_mapping = &ndr_desc->nd_mapping[i]; struct nvdimm *nvdimm = nd_mapping->nvdimm; if ((nd_mapping->start | nd_mapping->size) % SZ_4K) { dev_err(&nvdimm_bus->dev, "%s: %s mapping%d is not 4K aligned\n", caller, dev_name(&nvdimm->dev), i); return NULL; } if (nvdimm->flags & NDD_UNARMED) ro = 1; } if (dev_type == &nd_blk_device_type) { struct nd_blk_region_desc *ndbr_desc; struct nd_blk_region *ndbr; ndbr_desc = to_blk_region_desc(ndr_desc); ndbr = kzalloc(sizeof(*ndbr) + sizeof(struct nd_mapping) * ndr_desc->num_mappings, GFP_KERNEL); if (ndbr) { nd_region = &ndbr->nd_region; ndbr->enable = ndbr_desc->enable; ndbr->disable = ndbr_desc->disable; ndbr->do_io = ndbr_desc->do_io; } region_buf = ndbr; } else { nd_region = kzalloc(sizeof(struct nd_region) + sizeof(struct nd_mapping) * ndr_desc->num_mappings, GFP_KERNEL); region_buf = nd_region; } if (!region_buf) return NULL; nd_region->id = ida_simple_get(®ion_ida, 0, 0, GFP_KERNEL); if (nd_region->id < 0) goto err_id; nd_region->lane = alloc_percpu(struct nd_percpu_lane); if (!nd_region->lane) goto err_percpu; for (i = 0; i < nr_cpu_ids; i++) { struct nd_percpu_lane *ndl; ndl = per_cpu_ptr(nd_region->lane, i); spin_lock_init(&ndl->lock); ndl->count = 0; } memcpy(nd_region->mapping, ndr_desc->nd_mapping, sizeof(struct nd_mapping) * ndr_desc->num_mappings); for (i = 0; i < ndr_desc->num_mappings; i++) { struct nd_mapping *nd_mapping = &ndr_desc->nd_mapping[i]; struct nvdimm *nvdimm = nd_mapping->nvdimm; get_device(&nvdimm->dev); } nd_region->ndr_mappings = ndr_desc->num_mappings; nd_region->provider_data = ndr_desc->provider_data; nd_region->nd_set = ndr_desc->nd_set; nd_region->num_lanes = ndr_desc->num_lanes; nd_region->flags = ndr_desc->flags; nd_region->ro = ro; nd_region->numa_node = ndr_desc->numa_node; ida_init(&nd_region->ns_ida); ida_init(&nd_region->btt_ida); ida_init(&nd_region->pfn_ida); dev = &nd_region->dev; dev_set_name(dev, "region%d", nd_region->id); dev->parent = &nvdimm_bus->dev; dev->type = dev_type; dev->groups = ndr_desc->attr_groups; nd_region->ndr_size = resource_size(ndr_desc->res); nd_region->ndr_start = ndr_desc->res->start; nd_device_register(dev); return nd_region; err_percpu: ida_simple_remove(®ion_ida, nd_region->id); err_id: kfree(region_buf); return NULL; }
static netdev_tx_t mlxsw_sx_port_xmit(struct sk_buff *skb, struct net_device *dev) { struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; struct mlxsw_sx_port_pcpu_stats *pcpu_stats; const struct mlxsw_tx_info tx_info = { .local_port = mlxsw_sx_port->local_port, .is_emad = false, }; u64 len; int err; if (mlxsw_core_skb_transmit_busy(mlxsw_sx, &tx_info)) return NETDEV_TX_BUSY; if (unlikely(skb_headroom(skb) < MLXSW_TXHDR_LEN)) { struct sk_buff *skb_orig = skb; skb = skb_realloc_headroom(skb, MLXSW_TXHDR_LEN); if (!skb) { this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped); dev_kfree_skb_any(skb_orig); return NETDEV_TX_OK; } } mlxsw_sx_txhdr_construct(skb, &tx_info); len = skb->len; /* Due to a race we might fail here because of a full queue. In that * unlikely case we simply drop the packet. */ err = mlxsw_core_skb_transmit(mlxsw_sx, skb, &tx_info); if (!err) { pcpu_stats = this_cpu_ptr(mlxsw_sx_port->pcpu_stats); u64_stats_update_begin(&pcpu_stats->syncp); pcpu_stats->tx_packets++; pcpu_stats->tx_bytes += len; u64_stats_update_end(&pcpu_stats->syncp); } else { this_cpu_inc(mlxsw_sx_port->pcpu_stats->tx_dropped); dev_kfree_skb_any(skb); } return NETDEV_TX_OK; } static int mlxsw_sx_port_change_mtu(struct net_device *dev, int mtu) { struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); int err; err = mlxsw_sx_port_mtu_set(mlxsw_sx_port, mtu); if (err) return err; dev->mtu = mtu; return 0; } static struct rtnl_link_stats64 * mlxsw_sx_port_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) { struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); struct mlxsw_sx_port_pcpu_stats *p; u64 rx_packets, rx_bytes, tx_packets, tx_bytes; u32 tx_dropped = 0; unsigned int start; int i; for_each_possible_cpu(i) { p = per_cpu_ptr(mlxsw_sx_port->pcpu_stats, i); do { start = u64_stats_fetch_begin_irq(&p->syncp); rx_packets = p->rx_packets; rx_bytes = p->rx_bytes; tx_packets = p->tx_packets; tx_bytes = p->tx_bytes; } while (u64_stats_fetch_retry_irq(&p->syncp, start)); stats->rx_packets += rx_packets; stats->rx_bytes += rx_bytes; stats->tx_packets += tx_packets; stats->tx_bytes += tx_bytes; /* tx_dropped is u32, updated without syncp protection. */ tx_dropped += p->tx_dropped; } stats->tx_dropped = tx_dropped; return stats; } static const struct net_device_ops mlxsw_sx_port_netdev_ops = { .ndo_open = mlxsw_sx_port_open, .ndo_stop = mlxsw_sx_port_stop, .ndo_start_xmit = mlxsw_sx_port_xmit, .ndo_change_mtu = mlxsw_sx_port_change_mtu, .ndo_get_stats64 = mlxsw_sx_port_get_stats64, }; static void mlxsw_sx_port_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *drvinfo) { struct mlxsw_sx_port *mlxsw_sx_port = netdev_priv(dev); struct mlxsw_sx *mlxsw_sx = mlxsw_sx_port->mlxsw_sx; strlcpy(drvinfo->driver, mlxsw_sx_driver_name, sizeof(drvinfo->driver)); strlcpy(drvinfo->version, mlxsw_sx_driver_version, sizeof(drvinfo->version)); snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), "%d.%d.%d", mlxsw_sx->bus_info->fw_rev.major, mlxsw_sx->bus_info->fw_rev.minor, mlxsw_sx->bus_info->fw_rev.subminor); strlcpy(drvinfo->bus_info, mlxsw_sx->bus_info->device_name, sizeof(drvinfo->bus_info)); } struct mlxsw_sx_port_hw_stats { char str[ETH_GSTRING_LEN]; u64 (*getter)(char *payload); }; static const struct mlxsw_sx_port_hw_stats mlxsw_sx_port_hw_stats[] = { { .str = "a_frames_transmitted_ok", .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get, }, { .str = "a_frames_received_ok",
static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) { unsigned int i; unsigned int valid_states = 0; unsigned int cpu = policy->cpu; struct acpi_cpufreq_data *data; unsigned int result = 0; struct cpuinfo_x86 *c = &cpu_data(policy->cpu); struct acpi_processor_performance *perf; #ifdef CONFIG_SMP static int blacklisted; #endif pr_debug("acpi_cpufreq_cpu_init\n"); #ifdef CONFIG_SMP if (blacklisted) return blacklisted; blacklisted = acpi_cpufreq_blacklist(c); if (blacklisted) return blacklisted; #endif data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; if (!zalloc_cpumask_var(&data->freqdomain_cpus, GFP_KERNEL)) { result = -ENOMEM; goto err_free; } perf = per_cpu_ptr(acpi_perf_data, cpu); data->acpi_perf_cpu = cpu; policy->driver_data = data; if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) acpi_cpufreq_driver.flags |= CPUFREQ_CONST_LOOPS; result = acpi_processor_register_performance(perf, cpu); if (result) goto err_free_mask; policy->shared_type = perf->shared_type; /* * Will let policy->cpus know about dependency only when software * coordination is required. */ if (policy->shared_type == CPUFREQ_SHARED_TYPE_ALL || policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { cpumask_copy(policy->cpus, perf->shared_cpu_map); } cpumask_copy(data->freqdomain_cpus, perf->shared_cpu_map); #ifdef CONFIG_SMP dmi_check_system(sw_any_bug_dmi_table); if (bios_with_sw_any_bug && !policy_is_shared(policy)) { policy->shared_type = CPUFREQ_SHARED_TYPE_ALL; cpumask_copy(policy->cpus, topology_core_cpumask(cpu)); } if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) { cpumask_clear(policy->cpus); cpumask_set_cpu(cpu, policy->cpus); cpumask_copy(data->freqdomain_cpus, topology_sibling_cpumask(cpu)); policy->shared_type = CPUFREQ_SHARED_TYPE_HW; pr_info_once(PFX "overriding BIOS provided _PSD data\n"); } #endif /* capability check */ if (perf->state_count <= 1) { pr_debug("No P-States\n"); result = -ENODEV; goto err_unreg; } if (perf->control_register.space_id != perf->status_register.space_id) { result = -ENODEV; goto err_unreg; } switch (perf->control_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD && boot_cpu_data.x86 == 0xf) { pr_debug("AMD K8 systems must use native drivers.\n"); result = -ENODEV; goto err_unreg; } pr_debug("SYSTEM IO addr space\n"); data->cpu_feature = SYSTEM_IO_CAPABLE; break; case ACPI_ADR_SPACE_FIXED_HARDWARE: pr_debug("HARDWARE addr space\n"); if (check_est_cpu(cpu)) { data->cpu_feature = SYSTEM_INTEL_MSR_CAPABLE; break; } if (check_amd_hwpstate_cpu(cpu)) { data->cpu_feature = SYSTEM_AMD_MSR_CAPABLE; break; } result = -ENODEV; goto err_unreg; default: pr_debug("Unknown addr space %d\n", (u32) (perf->control_register.space_id)); result = -ENODEV; goto err_unreg; } data->freq_table = kzalloc(sizeof(*data->freq_table) * (perf->state_count+1), GFP_KERNEL); if (!data->freq_table) { result = -ENOMEM; goto err_unreg; } /* detect transition latency */ policy->cpuinfo.transition_latency = 0; for (i = 0; i < perf->state_count; i++) { if ((perf->states[i].transition_latency * 1000) > policy->cpuinfo.transition_latency) policy->cpuinfo.transition_latency = perf->states[i].transition_latency * 1000; } /* Check for high latency (>20uS) from buggy BIOSes, like on T42 */ if (perf->control_register.space_id == ACPI_ADR_SPACE_FIXED_HARDWARE && policy->cpuinfo.transition_latency > 20 * 1000) { policy->cpuinfo.transition_latency = 20 * 1000; printk_once(KERN_INFO "P-state transition latency capped at 20 uS\n"); } /* table init */ for (i = 0; i < perf->state_count; i++) { if (i > 0 && perf->states[i].core_frequency >= data->freq_table[valid_states-1].frequency / 1000) continue; data->freq_table[valid_states].driver_data = i; data->freq_table[valid_states].frequency = perf->states[i].core_frequency * 1000; valid_states++; } data->freq_table[valid_states].frequency = CPUFREQ_TABLE_END; perf->state = 0; result = cpufreq_table_validate_and_show(policy, data->freq_table); if (result) goto err_freqfree; if (perf->states[0].core_frequency * 1000 != policy->cpuinfo.max_freq) printk(KERN_WARNING FW_WARN "P-state 0 is not max freq\n"); switch (perf->control_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: /* * The core will not set policy->cur, because * cpufreq_driver->get is NULL, so we need to set it here. * However, we have to guess it, because the current speed is * unknown and not detectable via IO ports. */ policy->cur = acpi_cpufreq_guess_freq(data, policy->cpu); break; case ACPI_ADR_SPACE_FIXED_HARDWARE: acpi_cpufreq_driver.get = get_cur_freq_on_cpu; break; default: break; } /* notify BIOS that we exist */ acpi_processor_notify_smm(THIS_MODULE); pr_debug("CPU%u - ACPI performance management activated.\n", cpu); for (i = 0; i < perf->state_count; i++) pr_debug(" %cP%d: %d MHz, %d mW, %d uS\n", (i == perf->state ? '*' : ' '), i, (u32) perf->states[i].core_frequency, (u32) perf->states[i].power, (u32) perf->states[i].transition_latency); /* * the first call to ->target() should result in us actually * writing something to the appropriate registers. */ data->resume = 1; return result; err_freqfree: kfree(data->freq_table); err_unreg: acpi_processor_unregister_performance(cpu); err_free_mask: free_cpumask_var(data->freqdomain_cpus); err_free: kfree(data); policy->driver_data = NULL; return result; }
static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler) { int i, err, irq, irqs; struct platform_device *pmu_device = cpu_pmu->plat_device; struct pmu_hw_events __percpu *hw_events = cpu_pmu->hw_events; if (!pmu_device) return -ENODEV; irqs = min(pmu_device->num_resources, num_possible_cpus()); if (irqs < 1) { pr_warn_once("perf/ARM: No irqs for PMU defined, sampling events not supported\n"); return 0; } irq = platform_get_irq(pmu_device, 0); if (irq >= 0 && irq_is_percpu(irq)) { err = request_percpu_irq(irq, handler, "arm-pmu", &hw_events->percpu_pmu); if (err) { pr_err("unable to request IRQ%d for ARM PMU counters\n", irq); return err; } on_each_cpu(cpu_pmu_enable_percpu_irq, &irq, 1); } else { for (i = 0; i < irqs; ++i) { int cpu = i; err = 0; irq = platform_get_irq(pmu_device, i); if (irq < 0) continue; if (cpu_pmu->irq_affinity) cpu = cpu_pmu->irq_affinity[i]; /* * If we have a single PMU interrupt that we can't shift, * assume that we're running on a uniprocessor machine and * continue. Otherwise, continue without this interrupt. */ if (irq_set_affinity(irq, cpumask_of(cpu)) && irqs > 1) { pr_warn("unable to set irq affinity (irq=%d, cpu=%u)\n", irq, cpu); continue; } err = request_irq(irq, handler, IRQF_NOBALANCING | IRQF_NO_THREAD, "arm-pmu", per_cpu_ptr(&hw_events->percpu_pmu, cpu)); if (err) { pr_err("unable to request IRQ%d for ARM PMU counters\n", irq); return err; } cpumask_set_cpu(cpu, &cpu_pmu->active_irqs); } } return 0; }
/* * Determine the packet's protocol ID. The rule here is that we * assume 802.3 if the type field is short enough to be a length. * This is normal practice and works for any 'now in use' protocol. * * Also, at this point we assume that we ARE dealing exclusively with * VLAN packets, or packets that should be made into VLAN packets based * on a default VLAN ID. * * NOTE: Should be similar to ethernet/eth.c. * * SANITY NOTE: This method is called when a packet is moving up the stack * towards userland. To get here, it would have already passed * through the ethernet/eth.c eth_type_trans() method. * SANITY NOTE 2: We are referencing to the VLAN_HDR frields, which MAY be * stored UNALIGNED in the memory. RISC systems don't like * such cases very much... * SANITY NOTE 2a: According to Dave Miller & Alexey, it will always be * aligned, so there doesn't need to be any of the unaligned * stuff. It has been commented out now... --Ben * */ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *orig_dev) { struct vlan_hdr *vhdr; struct vlan_rx_stats *rx_stats; u16 vlan_id; u16 vlan_tci; skb = skb_share_check(skb, GFP_ATOMIC); if (skb == NULL) goto err_free; if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) goto err_free; vhdr = (struct vlan_hdr *)skb->data; vlan_tci = ntohs(vhdr->h_vlan_TCI); vlan_id = vlan_tci & VLAN_VID_MASK; rcu_read_lock(); skb->dev = __find_vlan_dev(dev, vlan_id); if (!skb->dev) { pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n", __func__, vlan_id, dev->name); goto err_unlock; } rx_stats = per_cpu_ptr(vlan_dev_info(skb->dev)->vlan_rx_stats, smp_processor_id()); rx_stats->rx_packets++; rx_stats->rx_bytes += skb->len; skb_pull_rcsum(skb, VLAN_HLEN); skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tci); pr_debug("%s: priority: %u for TCI: %hu\n", __func__, skb->priority, vlan_tci); switch (skb->pkt_type) { case PACKET_BROADCAST: /* Yeah, stats collect these together.. */ /* stats->broadcast ++; // no such counter :-( */ break; case PACKET_MULTICAST: rx_stats->multicast++; break; case PACKET_OTHERHOST: /* Our lower layer thinks this is not local, let's make sure. * This allows the VLAN to have a different MAC than the * underlying device, and still route correctly. */ if (!compare_ether_addr(eth_hdr(skb)->h_dest, skb->dev->dev_addr)) skb->pkt_type = PACKET_HOST; break; default: break; } vlan_set_encap_proto(skb, vhdr); skb = vlan_check_reorder_header(skb); if (!skb) { rx_stats->rx_errors++; goto err_unlock; } netif_rx(skb); rcu_read_unlock(); return NET_RX_SUCCESS; err_unlock: rcu_read_unlock(); err_free: kfree_skb(skb); return NET_RX_DROP; }
// ARM10C 20141004 // irq: 0, desc: kmem_cache#28-o0, node: 0, owner: null static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node, struct module *owner) { int cpu; // desc->irq_data.irq: (kmem_cache#28-o0)->irq_data.irq, irq: 0 desc->irq_data.irq = irq; // desc->irq_data.irq: (kmem_cache#28-o0)->irq_data.irq: 0 // desc->irq_data.chip: (kmem_cache#28-o0)->irq_data.chip desc->irq_data.chip = &no_irq_chip; // desc->irq_data.chip: (kmem_cache#28-o0)->irq_data.chip: &no_irq_chip // desc->irq_data.chip_data: (kmem_cache#28-o0)->irq_data.chip_data desc->irq_data.chip_data = NULL; // desc->irq_data.chip_data: (kmem_cache#28-o0)->irq_data.chip_data: NULL // desc->irq_data.handler_data: (kmem_cache#28-o0)->irq_data.handler_data desc->irq_data.handler_data = NULL; // desc->irq_data.handler_data: (kmem_cache#28-o0)->irq_data.handler_data: NULL // desc->irq_data.msi_desc: (kmem_cache#28-o0)->irq_data.msi_desc desc->irq_data.msi_desc = NULL; // desc->irq_data.msi_desc: (kmem_cache#28-o0)->irq_data.msi_desc: NULL // desc: kmem_cache#28-o0, 0xFFFFFFFF, _IRQ_DEFAULT_INIT_FLAGS: 0xc00 irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); // irq_settings_clr_and_set에서 한일: // desc->status_use_accessors: (kmem_cache#28-o0)->status_use_accessors: 0xc00 // &desc->irq_data: &(kmem_cache#28-o0)->irq_data, IRQD_IRQ_DISABLED: 0x10000 irqd_set(&desc->irq_data, IRQD_IRQ_DISABLED); // irqd_set에서 한일: // d->state_use_accessors: (&(kmem_cache#28-o0)->irq_data)->state_use_accessors: 0x10000 // desc->handle_irq: (kmem_cache#28-o0)->handle_irq desc->handle_irq = handle_bad_irq; // desc->handle_irq: (kmem_cache#28-o0)->handle_irq: handle_bad_irq // desc->depth: (kmem_cache#28-o0)->depth desc->depth = 1; // desc->depth: (kmem_cache#28-o0)->depth: 1 // desc->irq_count: (kmem_cache#28-o0)->irq_count desc->irq_count = 0; // desc->irq_count: (kmem_cache#28-o0)->irq_count: 0 // desc->irqs_unhandled: (kmem_cache#28-o0)->irqs_unhandled desc->irqs_unhandled = 0; // desc->irqs_unhandled: (kmem_cache#28-o0)->irqs_unhandled: 0 // desc->name: (kmem_cache#28-o0)->name desc->name = NULL; // desc->name: (kmem_cache#28-o0)->name: NULL // desc->owner: (kmem_cache#28-o0)->owner, owner: null desc->owner = owner; // desc->owner: (kmem_cache#28-o0)->owner: null for_each_possible_cpu(cpu) // for ((cpu) = -1; (cpu) = cpumask_next((cpu), (cpu_possible_mask)), (cpu) < nr_cpu_ids; ) // desc->kstat_irqs: (kmem_cache#28-o0)->kstat_irqs, cpu: 0 *per_cpu_ptr(desc->kstat_irqs, cpu) = 0; // [pcp0] (kmem_cache#28-o0)->kstat_irqs: 0 // cpu: 1 .. 3 수행 // desc: kmem_cache#28-o0, node: 0 desc_smp_init(desc, node); // desc_smp_init에서 한일: // desc->irq_data.node: (kmem_cache#28-o0)->irq_data.node: 0 // desc->irq_data.affinity: (kmem_cache#28-o0)->irq_data.affinity.bits[0]: 0xF }