static int kplib_num_cpus(ktap_state *ks) { set_number(ks->top, num_online_cpus()); incr_top(ks); return 1; }
static void __ref intelli_plug_work_fn(struct work_struct *work) { unsigned int nr_run_stat; unsigned int cpu_count = 0; unsigned int nr_cpus = 0; int i; if (intelli_plug_active) { nr_run_stat = calculate_thread_stats(); update_per_cpu_stat(); #ifdef DEBUG_INTELLI_PLUG pr_info("nr_run_stat: %u\n", nr_run_stat); #endif cpu_count = nr_run_stat; nr_cpus = num_online_cpus(); if (!suspended) { if (persist_count > 0) persist_count--; switch (cpu_count) { case 1: if (persist_count == 0) { //take down everyone unplug_cpu(0); } #ifdef DEBUG_INTELLI_PLUG pr_info("case 1: %u\n", persist_count); #endif break; case 2: if (persist_count == 0) persist_count = DUAL_PERSISTENCE; if (nr_cpus < 2) { for (i = 1; i < cpu_count; i++) cpu_up(i); } else { unplug_cpu(1); } #ifdef DEBUG_INTELLI_PLUG pr_info("case 2: %u\n", persist_count); #endif break; case 3: if (persist_count == 0) persist_count = TRI_PERSISTENCE; if (nr_cpus < 3) { for (i = 1; i < cpu_count; i++) cpu_up(i); } else { unplug_cpu(2); } #ifdef DEBUG_INTELLI_PLUG pr_info("case 3: %u\n", persist_count); #endif break; case 4: if (persist_count == 0) persist_count = QUAD_PERSISTENCE; if (nr_cpus < 4) for (i = 1; i < cpu_count; i++) cpu_up(i); #ifdef DEBUG_INTELLI_PLUG pr_info("case 4: %u\n", persist_count); #endif break; default: pr_err("Run Stat Error: Bad value %u\n", nr_run_stat); break; } } #ifdef DEBUG_INTELLI_PLUG else pr_info("intelli_plug is suspened!\n"); #endif } queue_delayed_work_on(0, intelliplug_wq, &intelli_plug_work, msecs_to_jiffies(sampling_time)); }
static bool dpidle_can_enter(void) { int reason = NR_REASONS; int i = 0; unsigned long long dpidle_block_curr_time = 0; #if 0 /* Temporarily disable deepidle/SODI for Turbo-mode */ if (is_ext_buck_exist()) { reason = BY_OTH; goto out; } #endif #if 0 if(dpidle_by_pass_cg==0){ if (!mt_cpufreq_earlysuspend_status_get()){ reason = BY_VTG; goto out; } } #endif #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) >= 1)||(num_online_cpus() != 1)) { reason = BY_CPU; goto out; } #endif if(idle_spm_lock){ reason = BY_VTG; goto out; } if(dpidle_by_pass_cg==0){ memset(dpidle_block_mask, 0, NR_GRPS * sizeof(unsigned int)); if (!clkmgr_idle_can_enter(dpidle_condition_mask, dpidle_block_mask)) { reason = BY_CLK; goto out; } } #ifdef CONFIG_SMP dpidle_timer_left = localtimer_get_counter(); if ((int)dpidle_timer_left < dpidle_time_critera || ((int)dpidle_timer_left) < 0) { reason = BY_TMR; goto out; } #else gpt_get_cnt(GPT1, &dpidle_timer_left); gpt_get_cmp(GPT1, &dpidle_timer_cmp); if((dpidle_timer_cmp-dpidle_timer_left)<dpidle_time_critera) { reason = BY_TMR; goto out; } #endif out: if (reason < NR_REASONS) { if( dpidle_block_prev_time == 0 ) dpidle_block_prev_time = idle_get_current_time_ms(); dpidle_block_curr_time = idle_get_current_time_ms(); if((dpidle_block_curr_time - dpidle_block_prev_time) > dpidle_block_time_critera) { if ((smp_processor_id() == 0)) { for (i = 0; i < nr_cpu_ids; i++) { idle_ver("dpidle_cnt[%d]=%lu, rgidle_cnt[%d]=%lu\n", i, dpidle_cnt[i], i, rgidle_cnt[i]); } for (i = 0; i < NR_REASONS; i++) { idle_ver("[%d]dpidle_block_cnt[%s]=%lu\n", i, reason_name[i], dpidle_block_cnt[i]); } for (i = 0; i < NR_GRPS; i++) { idle_ver("[%02d]dpidle_condition_mask[%-8s]=0x%08x\t\t" "dpidle_block_mask[%-8s]=0x%08x\n", i, grp_get_name(i), dpidle_condition_mask[i], grp_get_name(i), dpidle_block_mask[i]); } memset(dpidle_block_cnt, 0, sizeof(dpidle_block_cnt)); dpidle_block_prev_time = idle_get_current_time_ms(); } } dpidle_block_cnt[reason]++; return false; } else { dpidle_block_prev_time = idle_get_current_time_ms(); return true; } }
void soft_restart(unsigned long addr) { _soft_restart(addr, num_online_cpus() == 1); }
void __devinit igb_check_options(struct igb_adapter *adapter) { int bd = adapter->bd_number; struct e1000_hw *hw = &adapter->hw; if (bd >= IGB_MAX_NIC) { DPRINTK(PROBE, NOTICE, "Warning: no configuration for board #%d\n", bd); DPRINTK(PROBE, NOTICE, "Using defaults for all values\n"); #ifndef module_param_array bd = IGB_MAX_NIC; #endif } { /* Interrupt Throttling Rate */ struct igb_option opt = { .type = range_option, .name = "Interrupt Throttling Rate (ints/sec)", .err = "using default of " __MODULE_STRING(DEFAULT_ITR), .def = DEFAULT_ITR, .arg = { .r = { .min = MIN_ITR, .max = MAX_ITR } } }; #ifdef module_param_array if (num_InterruptThrottleRate > bd) { #endif unsigned int itr = InterruptThrottleRate[bd]; switch (itr) { case 0: DPRINTK(PROBE, INFO, "%s turned off\n", opt.name); if(hw->mac.type >= e1000_i350) adapter->dmac = IGB_DMAC_DISABLE; adapter->rx_itr_setting = itr; break; case 1: DPRINTK(PROBE, INFO, "%s set to dynamic mode\n", opt.name); adapter->rx_itr_setting = itr; break; case 3: DPRINTK(PROBE, INFO, "%s set to dynamic conservative mode\n", opt.name); adapter->rx_itr_setting = itr; break; default: igb_validate_option(&itr, &opt, adapter); /* Save the setting, because the dynamic bits * change itr. In case of invalid user value, * default to conservative mode, else need to * clear the lower two bits because they are * used as control */ if (itr == 3) { adapter->rx_itr_setting = itr; } else { adapter->rx_itr_setting = 1000000000 / (itr * 256); adapter->rx_itr_setting &= ~3; } break; } #ifdef module_param_array } else { adapter->rx_itr_setting = opt.def; } #endif adapter->tx_itr_setting = adapter->rx_itr_setting; } { /* Interrupt Mode */ struct igb_option opt = { .type = range_option, .name = "Interrupt Mode", .err = "defaulting to 2 (MSI-X)", .def = IGB_INT_MODE_MSIX, .arg = { .r = { .min = MIN_INTMODE, .max = MAX_INTMODE } } }; #ifdef module_param_array if (num_IntMode > bd) { #endif unsigned int int_mode = IntMode[bd]; igb_validate_option(&int_mode, &opt, adapter); adapter->int_mode = int_mode; #ifdef module_param_array } else { adapter->int_mode = opt.def; } #endif } { /* Low Latency Interrupt TCP Port */ struct igb_option opt = { .type = range_option, .name = "Low Latency Interrupt TCP Port", .err = "using default of " __MODULE_STRING(DEFAULT_LLIPORT), .def = DEFAULT_LLIPORT, .arg = { .r = { .min = MIN_LLIPORT, .max = MAX_LLIPORT } } }; #ifdef module_param_array if (num_LLIPort > bd) { #endif adapter->lli_port = LLIPort[bd]; if (adapter->lli_port) { igb_validate_option(&adapter->lli_port, &opt, adapter); } else { DPRINTK(PROBE, INFO, "%s turned off\n", opt.name); } #ifdef module_param_array } else { adapter->lli_port = opt.def; } #endif } { /* Low Latency Interrupt on Packet Size */ struct igb_option opt = { .type = range_option, .name = "Low Latency Interrupt on Packet Size", .err = "using default of " __MODULE_STRING(DEFAULT_LLISIZE), .def = DEFAULT_LLISIZE, .arg = { .r = { .min = MIN_LLISIZE, .max = MAX_LLISIZE } } }; #ifdef module_param_array if (num_LLISize > bd) { #endif adapter->lli_size = LLISize[bd]; if (adapter->lli_size) { igb_validate_option(&adapter->lli_size, &opt, adapter); } else { DPRINTK(PROBE, INFO, "%s turned off\n", opt.name); } #ifdef module_param_array } else { adapter->lli_size = opt.def; } #endif } { /* Low Latency Interrupt on TCP Push flag */ struct igb_option opt = { .type = enable_option, .name = "Low Latency Interrupt on TCP Push flag", .err = "defaulting to Disabled", .def = OPTION_DISABLED }; #ifdef module_param_array if (num_LLIPush > bd) { #endif unsigned int lli_push = LLIPush[bd]; igb_validate_option(&lli_push, &opt, adapter); adapter->flags |= lli_push ? IGB_FLAG_LLI_PUSH : 0; #ifdef module_param_array } else { adapter->flags |= opt.def ? IGB_FLAG_LLI_PUSH : 0; } #endif } { /* SRIOV - Enable SR-IOV VF devices */ struct igb_option opt = { .type = range_option, .name = "max_vfs - SR-IOV VF devices", .err = "using default of " __MODULE_STRING(DEFAULT_SRIOV), .def = DEFAULT_SRIOV, .arg = { .r = { .min = MIN_SRIOV, .max = MAX_SRIOV } } }; #ifdef module_param_array if (num_max_vfs > bd) { #endif adapter->vfs_allocated_count = max_vfs[bd]; igb_validate_option(&adapter->vfs_allocated_count, &opt, adapter); #ifdef module_param_array } else { adapter->vfs_allocated_count = opt.def; } #endif if (adapter->vfs_allocated_count) { switch (hw->mac.type) { case e1000_82575: case e1000_82580: adapter->vfs_allocated_count = 0; DPRINTK(PROBE, INFO, "SR-IOV option max_vfs not supported.\n"); default: break; } } } { /* VMDQ - Enable VMDq multiqueue receive */ struct igb_option opt = { .type = range_option, .name = "VMDQ - VMDq multiqueue queue count", .err = "using default of " __MODULE_STRING(DEFAULT_VMDQ), .def = DEFAULT_VMDQ, .arg = { .r = { .min = MIN_VMDQ, .max = (MAX_VMDQ - adapter->vfs_allocated_count) } } }; #ifdef module_param_array if (num_VMDQ > bd) { #endif adapter->vmdq_pools = (VMDQ[bd] == 1 ? 0 : VMDQ[bd]); if (adapter->vfs_allocated_count && !adapter->vmdq_pools) { DPRINTK(PROBE, INFO, "Enabling SR-IOV requires VMDq be set to at least 1\n"); adapter->vmdq_pools = 1; } igb_validate_option(&adapter->vmdq_pools, &opt, adapter); #ifdef module_param_array } else { if (!adapter->vfs_allocated_count) adapter->vmdq_pools = (opt.def == 1 ? 0 : opt.def); else adapter->vmdq_pools = 1; } #endif #ifdef CONFIG_IGB_VMDQ_NETDEV if (hw->mac.type == e1000_82575 && adapter->vmdq_pools) { DPRINTK(PROBE, INFO, "VMDq not supported on this part.\n"); adapter->vmdq_pools = 0; } #endif } { /* RSS - Enable RSS multiqueue receives */ struct igb_option opt = { .type = range_option, .name = "RSS - RSS multiqueue receive count", .err = "using default of " __MODULE_STRING(DEFAULT_RSS), .def = DEFAULT_RSS, .arg = { .r = { .min = MIN_RSS, .max = MAX_RSS } } }; if (adapter->vmdq_pools) { switch (hw->mac.type) { #ifndef CONFIG_IGB_VMDQ_NETDEV case e1000_82576: opt.arg.r.max = 2; break; case e1000_82575: if (adapter->vmdq_pools == 2) opt.arg.r.max = 3; if (adapter->vmdq_pools <= 2) break; #endif default: opt.arg.r.max = 1; break; } } #ifdef module_param_array if (num_RSS > bd) { #endif adapter->rss_queues = RSS[bd]; switch (adapter->rss_queues) { case 1: break; default: igb_validate_option(&adapter->rss_queues, &opt, adapter); if (adapter->rss_queues) break; case 0: adapter->rss_queues = min_t(u32, opt.arg.r.max, num_online_cpus()); break; } #ifdef module_param_array } else { adapter->rss_queues = opt.def ?: min_t(u32, opt.arg.r.max, num_online_cpus()); } #endif } { /* QueuePairs - Enable TX/RX queue pairs for interrupt handling */ struct igb_option opt = { .type = enable_option, .name = "QueuePairs - TX/RX queue pairs for interrupt handling", .err = "defaulting to Enabled", .def = OPTION_ENABLED }; #ifdef module_param_array if (num_QueuePairs > bd) { #endif unsigned int qp = QueuePairs[bd]; /* * we must enable queue pairs if the number of queues * exceeds the number of avaialble interrupts. We are * limited to 10, or 3 per unallocated vf. */ if ((adapter->rss_queues > 4) || (adapter->vmdq_pools > 4) || ((adapter->rss_queues > 1) && ((adapter->vmdq_pools > 3) || (adapter->vfs_allocated_count > 6)))) { if (qp == OPTION_DISABLED) { qp = OPTION_ENABLED; DPRINTK(PROBE, INFO, "Number of queues exceeds available interrupts, %s\n",opt.err); } } igb_validate_option(&qp, &opt, adapter); adapter->flags |= qp ? IGB_FLAG_QUEUE_PAIRS : 0; #ifdef module_param_array } else { adapter->flags |= opt.def ? IGB_FLAG_QUEUE_PAIRS : 0; } #endif } { /* EEE - Enable EEE for capable adapters */ if (hw->mac.type >= e1000_i350) { struct igb_option opt = { .type = enable_option, .name = "EEE Support", .err = "defaulting to Enabled", .def = OPTION_ENABLED }; #ifdef module_param_array if (num_EEE > bd) { #endif unsigned int eee = EEE[bd]; igb_validate_option(&eee, &opt, adapter); adapter->flags |= eee ? IGB_FLAG_EEE : 0; if (eee) hw->dev_spec._82575.eee_disable = false; else hw->dev_spec._82575.eee_disable = true; #ifdef module_param_array } else { adapter->flags |= opt.def ? IGB_FLAG_EEE : 0; if (adapter->flags & IGB_FLAG_EEE) hw->dev_spec._82575.eee_disable = false; else hw->dev_spec._82575.eee_disable = true; } #endif } } { /* DMAC - Enable DMA Coalescing for capable adapters */ if (hw->mac.type >= e1000_i350) { struct igb_opt_list list [] = { { IGB_DMAC_DISABLE, "DMAC Disable"}, { IGB_DMAC_MIN, "DMAC 250 usec"}, { IGB_DMAC_500, "DMAC 500 usec"}, { IGB_DMAC_EN_DEFAULT, "DMAC 1000 usec"}, { IGB_DMAC_2000, "DMAC 2000 usec"}, { IGB_DMAC_3000, "DMAC 3000 usec"}, { IGB_DMAC_4000, "DMAC 4000 usec"}, { IGB_DMAC_5000, "DMAC 5000 usec"}, { IGB_DMAC_6000, "DMAC 6000 usec"}, { IGB_DMAC_7000, "DMAC 7000 usec"}, { IGB_DMAC_8000, "DMAC 8000 usec"}, { IGB_DMAC_9000, "DMAC 9000 usec"}, { IGB_DMAC_MAX, "DMAC 10000 usec"} }; struct igb_option opt = { .type = list_option, .name = "DMA Coalescing", .err = "using default of "__MODULE_STRING(IGB_DMAC_DISABLE), .def = IGB_DMAC_DISABLE, .arg = { .l = { .nr = 13, .p = list } } }; #ifdef module_param_array if (num_DMAC > bd) { #endif unsigned int dmac = DMAC[bd]; if (adapter->rx_itr_setting == IGB_DMAC_DISABLE) dmac = IGB_DMAC_DISABLE; igb_validate_option(&dmac, &opt, adapter); switch (dmac) { case IGB_DMAC_DISABLE: adapter->dmac = dmac; break; case IGB_DMAC_MIN: adapter->dmac = dmac; break; case IGB_DMAC_500: adapter->dmac = dmac; break; case IGB_DMAC_EN_DEFAULT: adapter->dmac = dmac; break; case IGB_DMAC_2000: adapter->dmac = dmac; break; case IGB_DMAC_3000: adapter->dmac = dmac; break; case IGB_DMAC_4000: adapter->dmac = dmac; break; case IGB_DMAC_5000: adapter->dmac = dmac; break; case IGB_DMAC_6000: adapter->dmac = dmac; break; case IGB_DMAC_7000: adapter->dmac = dmac; break; case IGB_DMAC_8000: adapter->dmac = dmac; break; case IGB_DMAC_9000: adapter->dmac = dmac; break; case IGB_DMAC_MAX: adapter->dmac = dmac; break; default: adapter->dmac = opt.def; DPRINTK(PROBE, INFO, "Invalid DMAC setting, " "resetting DMAC to %d\n", opt.def); } #ifdef module_param_array } else adapter->dmac = opt.def; #endif } } #ifndef IGB_NO_LRO { /* LRO - Enable Large Receive Offload */ struct igb_option opt = { .type = enable_option, .name = "LRO - Large Receive Offload", .err = "defaulting to Disabled", .def = OPTION_DISABLED }; struct net_device *netdev = adapter->netdev; #ifdef module_param_array if (num_LRO > bd) { #endif unsigned int lro = LRO[bd]; igb_validate_option(&lro, &opt, adapter); netdev->features |= lro ? NETIF_F_LRO : 0; #ifdef module_param_array } else if (opt.def == OPTION_ENABLED) { netdev->features |= NETIF_F_LRO; } #endif } #endif /* IGB_NO_LRO */ { /* Node assignment */ static struct igb_option opt = { .type = range_option, .name = "Node to start on", .err = "defaulting to -1", #ifdef HAVE_EARLY_VMALLOC_NODE .def = 0, #else .def = -1, #endif .arg = { .r = { .min = 0, .max = (MAX_NUMNODES - 1)}} }; int node_param = opt.def; /* if the default was zero then we need to set the * default value to an online node, which is not * necessarily zero, and the constant initializer * above can't take first_online_node */ if (node_param == 0) /* must set opt.def for validate */ opt.def = node_param = first_online_node; #ifdef module_param_array if (num_Node > bd) { #endif node_param = Node[bd]; igb_validate_option((uint *)&node_param, &opt, adapter); if (node_param != OPTION_UNSET) { DPRINTK(PROBE, INFO, "node set to %d\n", node_param); } #ifdef module_param_array } #endif /* check sanity of the value */ if (node_param != -1 && !node_online(node_param)) { DPRINTK(PROBE, INFO, "ignoring node set to invalid value %d\n", node_param); node_param = opt.def; } adapter->node = node_param; } { /* MDD - Enable Malicious Driver Detection. Only available when SR-IOV is enabled. */ struct igb_option opt = { .type = enable_option, .name = "Malicious Driver Detection", .err = "defaulting to 1", .def = OPTION_ENABLED, .arg = { .r = { .min = OPTION_DISABLED, .max = OPTION_ENABLED } } }; #ifdef module_param_array if (num_MDD > bd) { #endif adapter->mdd = MDD[bd]; igb_validate_option((uint *)&adapter->mdd, &opt, adapter); #ifdef module_param_array } else { adapter->mdd = opt.def; } #endif } }
/** * ixgbe_check_options - Range Checking for Command Line Parameters * @adapter: board private structure * * This routine checks all command line parameters for valid user * input. If an invalid value is given, or if no user specified * value exists, a default value is used. The final value is stored * in a variable in the adapter structure. **/ void __devinit ixgbe_check_options(struct ixgbe_adapter *adapter) { unsigned int mdd; int bd = adapter->bd_number; u32 *aflags = &adapter->flags; struct ixgbe_ring_feature *feature = adapter->ring_feature; unsigned int vmdq; if (bd >= IXGBE_MAX_NIC) { printk(KERN_NOTICE "Warning: no configuration for board #%d\n", bd); printk(KERN_NOTICE "Using defaults for all values\n"); #ifndef module_param_array bd = IXGBE_MAX_NIC; #endif } { /* Interrupt Mode */ unsigned int int_mode; static struct ixgbe_option opt = { .type = range_option, .name = "Interrupt Mode", .err = "using default of "__MODULE_STRING(IXGBE_DEFAULT_INT), .def = IXGBE_DEFAULT_INT, .arg = { .r = { .min = IXGBE_INT_LEGACY, .max = IXGBE_INT_MSIX} } }; #ifdef module_param_array if (num_IntMode > bd || num_InterruptType > bd) { #endif int_mode = IntMode[bd]; if (int_mode == OPTION_UNSET) int_mode = InterruptType[bd]; ixgbe_validate_option(&int_mode, &opt); switch (int_mode) { case IXGBE_INT_MSIX: if (!(*aflags & IXGBE_FLAG_MSIX_CAPABLE)) printk(KERN_INFO "Ignoring MSI-X setting; " "support unavailable\n"); break; case IXGBE_INT_MSI: if (!(*aflags & IXGBE_FLAG_MSI_CAPABLE)) { printk(KERN_INFO "Ignoring MSI setting; " "support unavailable\n"); } else { *aflags &= ~IXGBE_FLAG_MSIX_CAPABLE; } break; case IXGBE_INT_LEGACY: default: *aflags &= ~IXGBE_FLAG_MSIX_CAPABLE; *aflags &= ~IXGBE_FLAG_MSI_CAPABLE; break; } #ifdef module_param_array } else { /* default settings */ if (opt.def == IXGBE_INT_MSIX && *aflags & IXGBE_FLAG_MSIX_CAPABLE) { *aflags |= IXGBE_FLAG_MSIX_CAPABLE; *aflags |= IXGBE_FLAG_MSI_CAPABLE; } else if (opt.def == IXGBE_INT_MSI && *aflags & IXGBE_FLAG_MSI_CAPABLE) { *aflags &= ~IXGBE_FLAG_MSIX_CAPABLE; *aflags |= IXGBE_FLAG_MSI_CAPABLE; } else { *aflags &= ~IXGBE_FLAG_MSIX_CAPABLE; *aflags &= ~IXGBE_FLAG_MSI_CAPABLE; } } #endif } { /* Multiple Queue Support */ static struct ixgbe_option opt = { .type = enable_option, .name = "Multiple Queue Support", .err = "defaulting to Enabled", .def = OPTION_ENABLED }; #ifdef module_param_array if (num_MQ > bd) { #endif unsigned int mq = MQ[bd]; ixgbe_validate_option(&mq, &opt); if (mq) *aflags |= IXGBE_FLAG_MQ_CAPABLE; else *aflags &= ~IXGBE_FLAG_MQ_CAPABLE; #ifdef module_param_array } else { if (opt.def == OPTION_ENABLED) *aflags |= IXGBE_FLAG_MQ_CAPABLE; else *aflags &= ~IXGBE_FLAG_MQ_CAPABLE; } #endif /* Check Interoperability */ if ((*aflags & IXGBE_FLAG_MQ_CAPABLE) && !(*aflags & IXGBE_FLAG_MSIX_CAPABLE)) { DPRINTK(PROBE, INFO, "Multiple queues are not supported while MSI-X " "is disabled. Disabling Multiple Queues.\n"); *aflags &= ~IXGBE_FLAG_MQ_CAPABLE; } } #if IS_ENABLED(CONFIG_DCA) { /* Direct Cache Access (DCA) */ static struct ixgbe_option opt = { .type = range_option, .name = "Direct Cache Access (DCA)", .err = "defaulting to Enabled", .def = IXGBE_MAX_DCA, .arg = { .r = { .min = OPTION_DISABLED, .max = IXGBE_MAX_DCA} } }; unsigned int dca = opt.def; #ifdef module_param_array if (num_DCA > bd) { #endif dca = DCA[bd]; ixgbe_validate_option(&dca, &opt); if (!dca) *aflags &= ~IXGBE_FLAG_DCA_CAPABLE; /* Check Interoperability */ if (!(*aflags & IXGBE_FLAG_DCA_CAPABLE)) { DPRINTK(PROBE, INFO, "DCA is disabled\n"); *aflags &= ~IXGBE_FLAG_DCA_ENABLED; } if (dca == IXGBE_MAX_DCA) { DPRINTK(PROBE, INFO, "DCA enabled for rx data\n"); adapter->flags |= IXGBE_FLAG_DCA_ENABLED_DATA; } #ifdef module_param_array } else { /* make sure to clear the capability flag if the * option is disabled by default above */ if (opt.def == OPTION_DISABLED) *aflags &= ~IXGBE_FLAG_DCA_CAPABLE; } #endif if (dca == IXGBE_MAX_DCA) adapter->flags |= IXGBE_FLAG_DCA_ENABLED_DATA; } #endif /* CONFIG_DCA */ { /* Receive-Side Scaling (RSS) */ static struct ixgbe_option opt = { .type = range_option, .name = "Receive-Side Scaling (RSS)", .err = "using default.", .def = 0, .arg = { .r = { .min = 0, .max = 1} } }; unsigned int rss = RSS[bd]; /* adjust Max allowed RSS queues based on MAC type */ opt.arg.r.max = ixgbe_max_rss_indices(adapter); #ifdef module_param_array if (num_RSS > bd) { #endif ixgbe_validate_option(&rss, &opt); /* base it off num_online_cpus() with hardware limit */ if (!rss) rss = min_t(int, opt.arg.r.max, num_online_cpus()); else feature[RING_F_FDIR].limit = rss; feature[RING_F_RSS].limit = rss; #ifdef module_param_array } else if (opt.def == 0) {
static void set_cpu_config(enum ux500_uc new_uc) { bool update = false; int cpu; int min_freq, max_freq; if (new_uc != current_uc) update = true; else if ((user_config_updated) && (new_uc == UX500_UC_USER)) update = true; pr_debug("%s: new_usecase=%d, current_usecase=%d, update=%d\n", __func__, new_uc, current_uc, update); if (!update) goto exit; /* Cpu hotplug */ if (!(usecase_conf[new_uc].second_cpu_online) && (num_online_cpus() > 1)) cpu_down(1); else if ((usecase_conf[new_uc].second_cpu_online) && (num_online_cpus() < 2)) cpu_up(1); if (usecase_conf[new_uc].max_arm) max_freq = usecase_conf[new_uc].max_arm; else max_freq = system_max_freq; if (usecase_conf[new_uc].min_arm) min_freq = usecase_conf[new_uc].min_arm; else min_freq = system_min_freq; for_each_online_cpu(cpu) set_cpufreq(cpu, min_freq, max_freq); /* Kinda doing the job twice, but this is needed for reference keeping */ if (usecase_conf[new_uc].min_arm) prcmu_qos_update_requirement(PRCMU_QOS_ARM_KHZ, "usecase", usecase_conf[new_uc].min_arm); else prcmu_qos_update_requirement(PRCMU_QOS_ARM_KHZ, "usecase", PRCMU_QOS_DEFAULT_VALUE); /* Cpu idle */ cpuidle_set_multiplier(usecase_conf[new_uc].cpuidle_multiplier); /* L2 prefetch */ if (usecase_conf[new_uc].l2_prefetch_en) outer_prefetch_enable(); else outer_prefetch_disable(); /* Force cpuidle state */ cpuidle_force_state(usecase_conf[new_uc].forced_state); /* QOS override */ prcmu_qos_voice_call_override(usecase_conf[new_uc].vc_override); current_uc = new_uc; exit: /* Its ok to clear even if new_uc != UX500_UC_USER */ user_config_updated = false; }
/* Requires cpu_add_remove_lock to be held */ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) { int err, nr_calls = 0; void *hcpu = (void *)(long)cpu; unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; struct take_cpu_down_param tcd_param = { .mod = mod, .hcpu = hcpu, }; if (num_online_cpus() == 1) return -EBUSY; if (!cpu_online(cpu)) return -EINVAL; cpu_hotplug_begin(); err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls); if (err) { nr_calls--; __cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL); printk("%s: attempt to take down CPU %u failed\n", __func__, cpu); goto out_release; } /* * By now we've cleared cpu_active_mask, wait for all preempt-disabled * and RCU users of this state to go away such that all new such users * will observe it. * * For CONFIG_PREEMPT we have preemptible RCU and its sync_rcu() might * not imply sync_sched(), so explicitly call both. * * Do sync before park smpboot threads to take care the rcu boost case. */ #ifdef CONFIG_PREEMPT synchronize_sched(); #endif synchronize_rcu(); smpboot_park_threads(cpu); /* * So now all preempt/rcu users must observe !cpu_active(). */ err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); if (err) { /* CPU didn't die: tell everyone. Can't complain. */ smpboot_unpark_threads(cpu); cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); goto out_release; } BUG_ON(cpu_online(cpu)); /* * The migration_call() CPU_DYING callback will have removed all * runnable tasks from the cpu, there's only the idle task left now * that the migration thread is done doing the stop_machine thing. * * Wait for the stop thread to go away. */ while (!idle_cpu(cpu)) cpu_relax(); /* This actually kills the CPU. */ __cpu_die(cpu); /* CPU is completely dead: tell everyone. Too late to complain. */ cpu_notify_nofail(CPU_DEAD | mod, hcpu); check_for_tasks(cpu); out_release: cpu_hotplug_done(); if (!err) cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu); return err; }
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) { int r; /* Assume we're using HV mode when the HV module is loaded */ int hv_enabled = kvmppc_hv_ops ? 1 : 0; if (kvm) { /* * Hooray - we know which VM type we're running on. Depend on * that rather than the guess above. */ hv_enabled = is_kvmppc_hv_enabled(kvm); } switch (ext) { #ifdef CONFIG_BOOKE case KVM_CAP_PPC_BOOKE_SREGS: case KVM_CAP_PPC_BOOKE_WATCHDOG: case KVM_CAP_PPC_EPR: #else case KVM_CAP_PPC_SEGSTATE: case KVM_CAP_PPC_HIOR: case KVM_CAP_PPC_PAPR: #endif case KVM_CAP_PPC_UNSET_IRQ: case KVM_CAP_PPC_IRQ_LEVEL: case KVM_CAP_ENABLE_CAP: case KVM_CAP_ENABLE_CAP_VM: case KVM_CAP_ONE_REG: case KVM_CAP_IOEVENTFD: case KVM_CAP_DEVICE_CTRL: r = 1; break; case KVM_CAP_PPC_PAIRED_SINGLES: case KVM_CAP_PPC_OSI: case KVM_CAP_PPC_GET_PVINFO: #if defined(CONFIG_KVM_E500V2) || defined(CONFIG_KVM_E500MC) case KVM_CAP_SW_TLB: #endif /* We support this only for PR */ r = !hv_enabled; break; #ifdef CONFIG_KVM_MMIO case KVM_CAP_COALESCED_MMIO: r = KVM_COALESCED_MMIO_PAGE_OFFSET; break; #endif #ifdef CONFIG_KVM_MPIC case KVM_CAP_IRQ_MPIC: r = 1; break; #endif #ifdef CONFIG_PPC_BOOK3S_64 case KVM_CAP_SPAPR_TCE: case KVM_CAP_SPAPR_TCE_64: case KVM_CAP_PPC_ALLOC_HTAB: case KVM_CAP_PPC_RTAS: case KVM_CAP_PPC_FIXUP_HCALL: case KVM_CAP_PPC_ENABLE_HCALL: #ifdef CONFIG_KVM_XICS case KVM_CAP_IRQ_XICS: #endif r = 1; break; #endif /* CONFIG_PPC_BOOK3S_64 */ #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE case KVM_CAP_PPC_SMT: if (hv_enabled) r = threads_per_subcore; else r = 0; break; case KVM_CAP_PPC_RMA: r = 0; break; case KVM_CAP_PPC_HWRNG: r = kvmppc_hwrng_present(); break; #endif case KVM_CAP_SYNC_MMU: #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE r = hv_enabled; #elif defined(KVM_ARCH_WANT_MMU_NOTIFIER) r = 1; #else r = 0; #endif break; #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE case KVM_CAP_PPC_HTAB_FD: r = hv_enabled; break; #endif case KVM_CAP_NR_VCPUS: /* * Recommending a number of CPUs is somewhat arbitrary; we * return the number of present CPUs for -HV (since a host * will have secondary threads "offline"), and for other KVM * implementations just count online CPUs. */ if (hv_enabled) r = num_present_cpus(); else r = num_online_cpus(); break; case KVM_CAP_NR_MEMSLOTS: r = KVM_USER_MEM_SLOTS; break; case KVM_CAP_MAX_VCPUS: r = KVM_MAX_VCPUS; break; #ifdef CONFIG_PPC_BOOK3S_64 case KVM_CAP_PPC_GET_SMMU_INFO: r = 1; break; case KVM_CAP_SPAPR_MULTITCE: r = 1; break; #endif default: r = 0; break; } return r; }
static void crash_kexec_prepare_cpus(int cpu) { unsigned int msecs; unsigned int ncpus = num_online_cpus() - 1;/* Excluding the panic cpu */ int tries = 0; int (*old_handler)(struct pt_regs *regs); printk(KERN_EMERG "Sending IPI to other CPUs\n"); crash_send_ipi(crash_ipi_callback); smp_wmb(); again: /* * FIXME: Until we will have the way to stop other CPUs reliably, * the crash CPU will send an IPI and wait for other CPUs to * respond. */ msecs = IPI_TIMEOUT; while ((atomic_read(&cpus_in_crash) < ncpus) && (--msecs > 0)) mdelay(1); /* Would it be better to replace the trap vector here? */ if (atomic_read(&cpus_in_crash) >= ncpus) { printk(KERN_EMERG "IPI complete\n"); return; } printk(KERN_EMERG "ERROR: %d cpu(s) not responding\n", ncpus - atomic_read(&cpus_in_crash)); /* * If we have a panic timeout set then we can't wait indefinitely * for someone to activate system reset. We also give up on the * second time through if system reset fail to work. */ if ((panic_timeout > 0) || (tries > 0)) return; /* * A system reset will cause all CPUs to take an 0x100 exception. * The primary CPU returns here via setjmp, and the secondary * CPUs reexecute the crash_kexec_secondary path. */ old_handler = __debugger; __debugger = handle_fault; crash_shutdown_cpu = smp_processor_id(); if (setjmp(crash_shutdown_buf) == 0) { printk(KERN_EMERG "Activate system reset (dumprestart) " "to stop other cpu(s)\n"); /* * A system reset will force all CPUs to execute the * crash code again. We need to reset cpus_in_crash so we * wait for everyone to do this. */ atomic_set(&cpus_in_crash, 0); smp_mb(); while (atomic_read(&cpus_in_crash) < ncpus) cpu_relax(); } crash_shutdown_cpu = -1; __debugger = old_handler; tries++; goto again; }
static void hotplug_decision_work_fn(struct work_struct *work) { unsigned int running, disable_load, sampling_rate, enable_load, avg_running, min_sampling_rate_jiffies = 0; unsigned int online_cpus, available_cpus, i, j; unsigned int k; online_cpus = num_online_cpus(); available_cpus = CPUS_AVAILABLE; disable_load = disable_load_threshold * online_cpus; enable_load = enable_load_threshold * online_cpus; min_sampling_rate_jiffies = msecs_to_jiffies(min_sampling_rate); /* * Multiply nr_running() by 100 so we don't have to * use fp division to get the average. */ running = nr_running() * 100; history[index] = running; if (debug) { pr_info("online_cpus is: %d\n", online_cpus); pr_info("enable_load is: %d\n", enable_load); pr_info("disable_load is: %d\n", disable_load); pr_info("index is: %d\n", index); pr_info("running is: %d\n", running); } /* * Use a circular buffer to calculate the average load * over the sampling periods. * This will absorb load spikes of short duration where * we don't want additional cores to be onlined because * the cpufreq driver should take care of those load spikes. */ for (i = 0, j = index; i < SAMPLING_PERIODS; i++, j--) { avg_running += history[j]; if (unlikely(j == 0)) j = INDEX_MAX_VALUE; } /* * If we are at the end of the buffer, return to the beginning. */ if (unlikely(index++ == INDEX_MAX_VALUE)) index = 0; if (debug) { pr_info("array contents: "); for (k = 0; k < SAMPLING_PERIODS; k++) { pr_info("%d: %d\t",k, history[k]); } pr_info("\n"); pr_info("avg_running before division: %d\n", avg_running); } avg_running = avg_running / SAMPLING_PERIODS; if (debug) { pr_info("average_running is: %d\n", avg_running); } if (likely(!(flags & HOTPLUG_DISABLED))) { if (unlikely((avg_running >= ENABLE_ALL_LOAD_THRESHOLD) && (online_cpus < available_cpus) && (max_online_cpus > online_cpus))) { if (debug) { pr_info("auto_hotplug: Onlining all CPUs, avg running: %d\n", avg_running); } /* * Flush any delayed offlining work from the workqueue. * No point in having expensive unnecessary hotplug transitions. * We still online after flushing, because load is high enough to * warrant it. * We set the paused flag so the sampling can continue but no more * hotplug events will occur. */ flags |= HOTPLUG_PAUSED; if (delayed_work_pending(&hotplug_offline_work)) cancel_delayed_work(&hotplug_offline_work); schedule_work(&hotplug_online_all_work); return; } else if (flags & HOTPLUG_PAUSED) { schedule_delayed_work_on(0, &hotplug_decision_work, min_sampling_rate_jiffies); return; } else if ((avg_running >= enable_load) && (online_cpus < available_cpus) && (max_online_cpus > online_cpus)) { if (debug) { pr_info("auto_hotplug: Onlining single CPU, avg running: %d\n", avg_running); } if (delayed_work_pending(&hotplug_offline_work)) cancel_delayed_work(&hotplug_offline_work); schedule_work(&hotplug_online_single_work); return; } else if ((avg_running <= disable_load) && (min_online_cpus < online_cpus)) { /* Only queue a cpu_down() if there isn't one already pending */ if (!(delayed_work_pending(&hotplug_offline_work))) { if (online_cpus == 2 && avg_running < (disable_load/2)) { if (debug) { pr_info("auto_hotplug: Online CPUs = 2; Offlining CPU, avg running: %d\n", avg_running); } flags |= HOTPLUG_PAUSED; schedule_delayed_work_on(0, &hotplug_offline_work, min_sampling_rate_jiffies); } else if (online_cpus > 2) { if (debug) { pr_info("auto_hotplug: Offlining CPU, avg running: %d\n", avg_running); } schedule_delayed_work_on(0, &hotplug_offline_work, HZ); } } /* If boostpulse is active, clear the flags */ if (flags & BOOSTPULSE_ACTIVE) { flags &= ~BOOSTPULSE_ACTIVE; if (debug) { pr_info("auto_hotplug: Clearing boostpulse flags\n"); } } } } /* * Reduce the sampling rate dynamically based on online cpus. */ sampling_rate = min_sampling_rate_jiffies * (online_cpus * online_cpus); if (debug) { pr_info("sampling_rate is: %d\n", jiffies_to_msecs(sampling_rate)); } schedule_delayed_work_on(0, &hotplug_decision_work, sampling_rate); }
static void native_stop_other_cpus(int wait) { unsigned long flags; unsigned long timeout; if (reboot_force) return; /* * Use an own vector here because smp_call_function * does lots of things not suitable in a panic situation. */ /* * We start by using the REBOOT_VECTOR irq. * The irq is treated as a sync point to allow critical * regions of code on other cpus to release their spin locks * and re-enable irqs. Jumping straight to an NMI might * accidentally cause deadlocks with further shutdown/panic * code. By syncing, we give the cpus up to one second to * finish their work before we force them off with the NMI. */ if (num_online_cpus() > 1) { /* did someone beat us here? */ if (atomic_cmpxchg(&stopping_cpu, -1, safe_smp_processor_id()) != -1) return; /* sync above data before sending IRQ */ wmb(); apic->send_IPI_allbutself(REBOOT_VECTOR); /* * Don't wait longer than a second if the caller * didn't ask us to wait. */ timeout = USEC_PER_SEC; while (num_online_cpus() > 1 && (wait || timeout--)) udelay(1); } /* if the REBOOT_VECTOR didn't work, try with the NMI */ if ((num_online_cpus() > 1) && (!smp_no_nmi_ipi)) { if (register_nmi_handler(NMI_LOCAL, smp_stop_nmi_callback, NMI_FLAG_FIRST, "smp_stop")) /* Note: we ignore failures here */ /* Hope the REBOOT_IRQ is good enough */ goto finish; /* sync above data before sending IRQ */ wmb(); pr_emerg("Shutting down cpus with NMI\n"); apic->send_IPI_allbutself(NMI_VECTOR); /* * Don't wait longer than a 10 ms if the caller * didn't ask us to wait. */ timeout = USEC_PER_MSEC * 10; while (num_online_cpus() > 1 && (wait || timeout--)) udelay(1); } finish: local_irq_save(flags); disable_local_APIC(); mcheck_cpu_clear(this_cpu_ptr(&cpu_info)); local_irq_restore(flags); }
/** * acpi_idle_enter_bm - enters C3 with proper BM handling * @dev: the target CPU * @drv: cpuidle driver containing state data * @index: the index of suggested state * * If BM is detected, the deepest non-C3 idle state is entered instead. */ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct cpuidle_driver *drv, int index) { struct acpi_processor *pr; struct acpi_processor_cx *cx = per_cpu(acpi_cstate[index], dev->cpu); pr = __this_cpu_read(processors); if (unlikely(!pr)) return -EINVAL; if (!cx->bm_sts_skip && acpi_idle_bm_check()) { if (drv->safe_state_index >= 0) { return drv->states[drv->safe_state_index].enter(dev, drv, drv->safe_state_index); } else { acpi_safe_halt(); return -EBUSY; } } if (cx->entry_method != ACPI_CSTATE_FFH) { current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we test * NEED_RESCHED: */ smp_mb(); if (unlikely(need_resched())) { current_thread_info()->status |= TS_POLLING; return -EINVAL; } } acpi_unlazy_tlb(smp_processor_id()); /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); /* * Must be done before busmaster disable as we might need to * access HPET ! */ lapic_timer_state_broadcast(pr, cx, 1); /* * disable bus master * bm_check implies we need ARB_DIS * !bm_check implies we need cache flush * bm_control implies whether we can do ARB_DIS * * That leaves a case where bm_check is set and bm_control is * not set. In that case we cannot do much, we enter C3 * without doing anything. */ if (pr->flags.bm_check && pr->flags.bm_control) { raw_spin_lock(&c3_lock); c3_cpu_count++; /* Disable bus master arbitration when all CPUs are in C3 */ if (c3_cpu_count == num_online_cpus()) acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); raw_spin_unlock(&c3_lock); } else if (!pr->flags.bm_check) { ACPI_FLUSH_CPU_CACHE(); } acpi_idle_do_entry(cx); /* Re-enable bus master arbitration */ if (pr->flags.bm_check && pr->flags.bm_control) { raw_spin_lock(&c3_lock); acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; raw_spin_unlock(&c3_lock); } sched_clock_idle_wakeup_event(0); if (cx->entry_method != ACPI_CSTATE_FFH) current_thread_info()->status |= TS_POLLING; lapic_timer_state_broadcast(pr, cx, 0); return index; }
static int netvsc_set_channels(struct net_device *net, struct ethtool_channels *channels) { struct net_device_context *net_device_ctx = netdev_priv(net); struct hv_device *dev = net_device_ctx->device_ctx; struct netvsc_device *nvdev = net_device_ctx->nvdev; struct netvsc_device_info device_info; u32 num_chn; u32 max_chn; int ret = 0; bool recovering = false; if (net_device_ctx->start_remove || !nvdev || nvdev->destroy) return -ENODEV; num_chn = nvdev->num_chn; max_chn = min_t(u32, nvdev->max_chn, num_online_cpus()); if (nvdev->nvsp_version < NVSP_PROTOCOL_VERSION_5) { pr_info("vRSS unsupported before NVSP Version 5\n"); return -EINVAL; } /* We do not support rx, tx, or other */ if (!channels || channels->rx_count || channels->tx_count || channels->other_count || (channels->combined_count < 1)) return -EINVAL; if (channels->combined_count > max_chn) { pr_info("combined channels too high, using %d\n", max_chn); channels->combined_count = max_chn; } ret = netvsc_close(net); if (ret) goto out; do_set: net_device_ctx->start_remove = true; rndis_filter_device_remove(dev); nvdev->num_chn = channels->combined_count; memset(&device_info, 0, sizeof(device_info)); device_info.num_chn = nvdev->num_chn; /* passed to RNDIS */ device_info.ring_size = ring_size; device_info.max_num_vrss_chns = max_num_vrss_chns; ret = rndis_filter_device_add(dev, &device_info); if (ret) { if (recovering) { netdev_err(net, "unable to add netvsc device (ret %d)\n", ret); return ret; } goto recover; } nvdev = net_device_ctx->nvdev; ret = netif_set_real_num_tx_queues(net, nvdev->num_chn); if (ret) { if (recovering) { netdev_err(net, "could not set tx queue count (ret %d)\n", ret); return ret; } goto recover; } ret = netif_set_real_num_rx_queues(net, nvdev->num_chn); if (ret) { if (recovering) { netdev_err(net, "could not set rx queue count (ret %d)\n", ret); return ret; } goto recover; } out: netvsc_open(net); net_device_ctx->start_remove = false; /* We may have missed link change notifications */ schedule_delayed_work(&net_device_ctx->dwork, 0); return ret; recover: /* If the above failed, we attempt to recover through the same * process but with the original number of channels. */ netdev_err(net, "could not set channels, recovering\n"); recovering = true; channels->combined_count = num_chn; goto do_set; }
static int acpi_processor_get_info(struct acpi_device *device) { acpi_status status = 0; union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; struct acpi_processor *pr; int cpu_index, device_declaration = 0; static int cpu0_initialized; pr = acpi_driver_data(device); if (!pr) return -EINVAL; if (num_online_cpus() > 1) errata.smp = TRUE; acpi_processor_errata(pr); /* * Check to see if we have bus mastering arbitration control. This * is required for proper C3 usage (to maintain cache coherency). */ if (acpi_gbl_FADT.pm2_control_block && acpi_gbl_FADT.pm2_control_length) { pr->flags.bm_control = 1; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Bus mastering arbitration control present\n")); } else ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No bus mastering arbitration control\n")); if (!strcmp(acpi_device_hid(device), ACPI_PROCESSOR_OBJECT_HID)) { /* Declared with "Processor" statement; match ProcessorID */ status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); if (ACPI_FAILURE(status)) { dev_err(&device->dev, "Failed to evaluate processor object (0x%x)\n", status); return -ENODEV; } /* * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. * >>> 'acpi_get_processor_id(acpi_id, &id)' in * arch/xxx/acpi.c */ pr->acpi_id = object.processor.proc_id; } else { /* * Declared with "Device" statement; match _UID. * Note that we don't handle string _UIDs yet. */ unsigned long long value; status = acpi_evaluate_integer(pr->handle, METHOD_NAME__UID, NULL, &value); if (ACPI_FAILURE(status)) { dev_err(&device->dev, "Failed to evaluate processor _UID (0x%x)\n", status); return -ENODEV; } device_declaration = 1; pr->acpi_id = value; } cpu_index = acpi_get_cpuid(pr->handle, device_declaration, pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ if (!cpu0_initialized && (cpu_index == -1) && (num_online_cpus() == 1)) { cpu_index = 0; } cpu0_initialized = 1; pr->id = cpu_index; /* * Extra Processor objects may be enumerated on MP systems with * less than the max # of CPUs. They should be ignored _iff * they are physically not present. */ if (pr->id == -1) { if (ACPI_FAILURE(acpi_processor_hotadd_init(pr))) return -ENODEV; } /* * On some boxes several processors use the same processor bus id. * But they are located in different scope. For example: * \_SB.SCK0.CPU0 * \_SB.SCK1.CPU0 * Rename the processor device bus id. And the new bus id will be * generated as the following format: * CPU+CPU ID. */ sprintf(acpi_device_bid(device), "CPU%X", pr->id); ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, pr->acpi_id)); if (!object.processor.pblk_address) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); else if (object.processor.pblk_length != 6) dev_err(&device->dev, "Invalid PBLK length [%d]\n", object.processor.pblk_length); else { pr->throttling.address = object.processor.pblk_address; pr->throttling.duty_offset = acpi_gbl_FADT.duty_offset; pr->throttling.duty_width = acpi_gbl_FADT.duty_width; pr->pblk = object.processor.pblk_address; /* * We don't care about error returns - we just try to mark * these reserved so that nobody else is confused into thinking * that this region might be unused.. * * (In particular, allocating the IO range for Cardbus) */ request_region(pr->throttling.address, 6, "ACPI CPU throttle"); } /* * If ACPI describes a slot number for this CPU, we can use it * ensure we get the right value in the "physical id" field * of /proc/cpuinfo */ status = acpi_evaluate_object(pr->handle, "_SUN", NULL, &buffer); if (ACPI_SUCCESS(status)) arch_fix_phys_package_id(pr->id, object.integer.value); return 0; }
/* * Put CPU in low power mode. */ void arch_idle(void) { bool allow[MSM_PM_SLEEP_MODE_NR]; uint32_t sleep_limit = SLEEP_LIMIT_NONE; int64_t timer_expiration; int latency_qos; int ret; int i; unsigned int cpu; int64_t t1; static DEFINE_PER_CPU(int64_t, t2); int exit_stat; if (!atomic_read(&msm_pm_init_done)) return; cpu = smp_processor_id(); latency_qos = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); /* get the next timer expiration */ timer_expiration = ktime_to_ns(tick_nohz_get_sleep_length()); t1 = ktime_to_ns(ktime_get()); msm_pm_add_stat(MSM_PM_STAT_NOT_IDLE, t1 - __get_cpu_var(t2)); msm_pm_add_stat(MSM_PM_STAT_REQUESTED_IDLE, timer_expiration); exit_stat = MSM_PM_STAT_IDLE_SPIN; for (i = 0; i < ARRAY_SIZE(allow); i++) allow[i] = true; if (num_online_cpus() > 1 || (timer_expiration < msm_pm_idle_sleep_min_time) || !msm_pm_irq_extns->idle_sleep_allowed()) { allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = false; allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = false; } for (i = 0; i < ARRAY_SIZE(allow); i++) { struct msm_pm_platform_data *mode = &msm_pm_modes[MSM_PM_MODE(cpu, i)]; if (!mode->idle_supported || !mode->idle_enabled || mode->latency >= latency_qos || mode->residency * 1000ULL >= timer_expiration) allow[i] = false; } if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] || allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN]) { uint32_t wait_us = CONFIG_MSM_IDLE_WAIT_ON_MODEM; while (msm_pm_modem_busy() && wait_us) { if (wait_us > 100) { udelay(100); wait_us -= 100; } else { udelay(wait_us); wait_us = 0; } } if (msm_pm_modem_busy()) { allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] = false; allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN] = false; } } MSM_PM_DPRINTK(MSM_PM_DEBUG_IDLE, KERN_INFO, "%s(): latency qos %d, next timer %lld, sleep limit %u\n", __func__, latency_qos, timer_expiration, sleep_limit); for (i = 0; i < ARRAY_SIZE(allow); i++) MSM_PM_DPRINTK(MSM_PM_DEBUG_IDLE, KERN_INFO, "%s(): allow %s: %d\n", __func__, msm_pm_sleep_mode_labels[i], (int)allow[i]); if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE] || allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_NO_XO_SHUTDOWN]) { /* Sync the timer with SCLK, it is needed only for modem * assissted pollapse case. */ int64_t next_timer_exp = msm_timer_enter_idle(); uint32_t sleep_delay; bool low_power = false; sleep_delay = (uint32_t) msm_pm_convert_and_cap_time( next_timer_exp, MSM_PM_SLEEP_TICK_LIMIT); if (sleep_delay == 0) /* 0 would mean infinite time */ sleep_delay = 1; if (!allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE]) sleep_limit = SLEEP_LIMIT_NO_TCXO_SHUTDOWN; #if defined(CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_ACTIVE) sleep_limit |= SLEEP_RESOURCE_MEMORY_BIT1; #elif defined(CONFIG_MSM_MEMORY_LOW_POWER_MODE_IDLE_RETENTION) sleep_limit |= SLEEP_RESOURCE_MEMORY_BIT0; #endif ret = msm_pm_power_collapse(true, sleep_delay, sleep_limit); low_power = (ret != -EBUSY && ret != -ETIMEDOUT); msm_timer_exit_idle(low_power); if (ret) exit_stat = MSM_PM_STAT_IDLE_FAILED_POWER_COLLAPSE; else { exit_stat = MSM_PM_STAT_IDLE_POWER_COLLAPSE; msm_pm_sleep_limit = sleep_limit; } } else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) { ret = msm_pm_power_collapse_standalone(true); exit_stat = ret ? MSM_PM_STAT_IDLE_FAILED_STANDALONE_POWER_COLLAPSE : MSM_PM_STAT_IDLE_STANDALONE_POWER_COLLAPSE; } else if (allow[MSM_PM_SLEEP_MODE_RAMP_DOWN_AND_WAIT_FOR_INTERRUPT]) { ret = msm_pm_swfi(true); if (ret) while (!msm_pm_irq_extns->irq_pending()) udelay(1); exit_stat = ret ? MSM_PM_STAT_IDLE_SPIN : MSM_PM_STAT_IDLE_WFI; } else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) { msm_pm_swfi(false); exit_stat = MSM_PM_STAT_IDLE_WFI; } else { while (!msm_pm_irq_extns->irq_pending()) udelay(1); exit_stat = MSM_PM_STAT_IDLE_SPIN; } __get_cpu_var(t2) = ktime_to_ns(ktime_get()); msm_pm_add_stat(exit_stat, __get_cpu_var(t2) - t1); }
/*---------------------------------------------------------------------------*/ struct xio_context *xio_context_create(struct xio_context_params *ctx_params, int polling_timeout, int cpu_hint) { struct xio_context *ctx; struct xio_loop_ops *loop_ops; struct task_struct *worker; struct xio_transport *transport; int flags, cpu; if (!ctx_params) { xio_set_error(EINVAL); ERROR_LOG("ctx_params is NULL\n"); goto cleanup0; } loop_ops = ctx_params->loop_ops; worker = ctx_params->worker; flags = ctx_params->flags; if (cpu_hint > 0 && cpu_hint >= num_online_cpus()) { xio_set_error(EINVAL); ERROR_LOG("cpu_hint(%d) >= num_online_cpus(%d)\n", cpu_hint, num_online_cpus()); goto cleanup0; } if ((flags == XIO_LOOP_USER_LOOP) && (!(loop_ops && loop_ops->add_event && loop_ops->ev_loop))) { xio_set_error(EINVAL); ERROR_LOG("loop_ops and ev_loop and ev_loop_add_event are " \ "mandatory with loop_ops\n"); goto cleanup0; } xio_read_logging_level(); /* no need to disable preemption */ cpu = raw_smp_processor_id(); if (cpu == -1) goto cleanup0; /* allocate new context */ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) { xio_set_error(ENOMEM); ERROR_LOG("kzalloc failed\n"); goto cleanup0; } if (cpu_hint < 0) cpu_hint = cpu; ctx->run_private = 0; ctx->user_context = ctx_params->user_context; ctx->flags = flags; ctx->cpuid = cpu_hint; ctx->nodeid = cpu_to_node(cpu_hint); ctx->polling_timeout = polling_timeout; ctx->prealloc_xio_inline_bufs = !!ctx_params->prealloc_xio_inline_bufs; ctx->rq_depth = ctx_params->rq_depth; if (!ctx_params->max_conns_per_ctx) ctx->max_conns_per_ctx = 100; else ctx->max_conns_per_ctx = max(ctx_params->max_conns_per_ctx , 2); ctx->workqueue = xio_workqueue_create(ctx); if (!ctx->workqueue) { xio_set_error(ENOMEM); ERROR_LOG("xio_workqueue_init failed.\n"); goto cleanup1; } ctx->msg_pool = xio_objpool_create(sizeof(struct xio_msg), MSGPOOL_INIT_NR, MSGPOOL_GROW_NR); if (!ctx->msg_pool) { xio_set_error(ENOMEM); ERROR_LOG("context's msg_pool create failed. %m\n"); goto cleanup2; } XIO_OBSERVABLE_INIT(&ctx->observable, ctx); INIT_LIST_HEAD(&ctx->ctx_list); switch (flags) { case XIO_LOOP_USER_LOOP: break; case XIO_LOOP_GIVEN_THREAD: set_cpus_allowed_ptr(worker, cpumask_of(cpu_hint)); ctx->worker = (uint64_t)worker; break; case XIO_LOOP_TASKLET: break; case XIO_LOOP_WORKQUEUE: break; default: ERROR_LOG("wrong type. %u\n", flags); goto cleanup3; } ctx->ev_loop = xio_ev_loop_init(flags, ctx, loop_ops); if (!ctx->ev_loop) goto cleanup3; ctx->stats.hertz = HZ; /* Initialize default counters' name */ ctx->stats.name[XIO_STAT_TX_MSG] = kstrdup("TX_MSG", GFP_KERNEL); ctx->stats.name[XIO_STAT_RX_MSG] = kstrdup("RX_MSG", GFP_KERNEL); ctx->stats.name[XIO_STAT_TX_BYTES] = kstrdup("TX_BYTES", GFP_KERNEL); ctx->stats.name[XIO_STAT_RX_BYTES] = kstrdup("RX_BYTES", GFP_KERNEL); ctx->stats.name[XIO_STAT_DELAY] = kstrdup("DELAY", GFP_KERNEL); ctx->stats.name[XIO_STAT_APPDELAY] = kstrdup("APPDELAY", GFP_KERNEL); /* initialize rdma pools only */ transport = xio_get_transport("rdma"); if (transport && ctx->prealloc_xio_inline_bufs) { int retval = xio_ctx_pool_create(ctx, XIO_PROTO_RDMA, XIO_CONTEXT_POOL_CLASS_INITIAL); if (retval) { ERROR_LOG("Failed to create initial pool. ctx:%p\n", ctx); goto cleanup2; } retval = xio_ctx_pool_create(ctx, XIO_PROTO_RDMA, XIO_CONTEXT_POOL_CLASS_PRIMARY); if (retval) { ERROR_LOG("Failed to create primary pool. ctx:%p\n", ctx); goto cleanup2; } } spin_lock_init(&ctx->ctx_list_lock); xio_idr_add_uobj(usr_idr, ctx, "xio_context"); return ctx; cleanup3: xio_objpool_destroy(ctx->msg_pool); cleanup2: xio_workqueue_destroy(ctx->workqueue); cleanup1: kfree(ctx); cleanup0: ERROR_LOG("xio_ctx_open failed\n"); return NULL; }
static int acpi_processor_get_info(struct acpi_processor *pr) { acpi_status status = 0; union acpi_object object = { 0 }; struct acpi_buffer buffer = { sizeof(union acpi_object), &object }; int cpu_index; static int cpu0_initialized; if (!pr) return -EINVAL; if (num_online_cpus() > 1) errata.smp = TRUE; acpi_processor_errata(pr); /* * Check to see if we have bus mastering arbitration control. This * is required for proper C3 usage (to maintain cache coherency). */ if (acpi_fadt.V1_pm2_cnt_blk && acpi_fadt.pm2_cnt_len) { pr->flags.bm_control = 1; ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Bus mastering arbitration control present\n")); } else ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No bus mastering arbitration control\n")); /* * Evalute the processor object. Note that it is common on SMP to * have the first (boot) processor with a valid PBLK address while * all others have a NULL address. */ status = acpi_evaluate_object(pr->handle, NULL, NULL, &buffer); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "Evaluating processor object\n"); return -ENODEV; } /* * TBD: Synch processor ID (via LAPIC/LSAPIC structures) on SMP. * >>> 'acpi_get_processor_id(acpi_id, &id)' in arch/xxx/acpi.c */ pr->acpi_id = object.processor.proc_id; cpu_index = convert_acpiid_to_cpu(pr->acpi_id); /* Handle UP system running SMP kernel, with no LAPIC in MADT */ if (!cpu0_initialized && (cpu_index == -1) && (num_online_cpus() == 1)) { cpu_index = 0; } cpu0_initialized = 1; pr->id = cpu_index; /* * Extra Processor objects may be enumerated on MP systems with * less than the max # of CPUs. They should be ignored _iff * they are physically not present. */ if (cpu_index == -1) { if (ACPI_FAILURE (acpi_processor_hotadd_init(pr->handle, &pr->id))) { return -ENODEV; } } ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Processor [%d:%d]\n", pr->id, pr->acpi_id)); if (!object.processor.pblk_address) ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No PBLK (NULL address)\n")); else if (object.processor.pblk_length != 6) printk(KERN_ERR PREFIX "Invalid PBLK length [%d]\n", object.processor.pblk_length); else { pr->throttling.address = object.processor.pblk_address; pr->throttling.duty_offset = acpi_fadt.duty_offset; pr->throttling.duty_width = acpi_fadt.duty_width; pr->pblk = object.processor.pblk_address; /* * We don't care about error returns - we just try to mark * these reserved so that nobody else is confused into thinking * that this region might be unused.. * * (In particular, allocating the IO range for Cardbus) */ request_region(pr->throttling.address, 6, "ACPI CPU throttle"); } #ifdef CONFIG_CPU_FREQ acpi_processor_ppc_has_changed(pr); #endif acpi_processor_get_throttling_info(pr); acpi_processor_get_limit_info(pr); return 0; }
/* This is an SVR4 system call that is undocumented except for some * hints in a header file. It appears to be a forerunner to the * POSIX sysconf() call. */ int svr4_sysconfig(int name) { switch (name) { case _CONFIG_NGROUPS: /* From limits.h */ return (NGROUPS_MAX); case _CONFIG_CHILD_MAX: /* From limits.h */ return (CHILD_MAX); case _CONFIG_OPEN_FILES: /* From limits.h */ return (OPEN_MAX); case _CONFIG_POSIX_VER: /* The version of the POSIX standard we conform * to. SCO defines _POSIX_VERSION as 198808L * sys/unistd.h. What are we? We are 199009L. */ return (199009L); case _CONFIG_PAGESIZE: return (PAGE_SIZE); case _CONFIG_CLK_TCK: return (HZ); case _CONFIG_XOPEN_VER: return 4; case _CONFIG_NACLS_MAX: return 0; case _CONFIG_NPROC: return 4000; /* max_threads */ case _CONFIG_NENGINE: case _CONFIG_NENGINE_ONLN: return (num_online_cpus()); case _CONFIG_TOTAL_MEMORY: return (max_mapnr << (PAGE_SHIFT-10)); case _CONFIG_USEABLE_MEMORY: case _CONFIG_GENERAL_MEMORY: return (max_mapnr << (PAGE_SHIFT-10)); /* return ((unsigned long) (nr_free_pages()) << (PAGE_SHIFT-10)); */ case _CONFIG_DEDICATED_MEMORY: return 0; case _CONFIG_NCGS_CONF: case _CONFIG_NCGS_ONLN: case _CONFIG_MAX_ENG_PER_CG: return 1; /* no NUMA-Q support on Linux yet */ /* well, there is. we lie anyway --hch */ case _CONFIG_CACHE_LINE: return 32; /* XXX is there a more accurate way? */ case _CONFIG_KERNEL_VM: return -EINVAL; case _CONFIG_ARG_MAX: /* From limits.h */ return (ARG_MAX); } #if defined(CONFIG_ABI_TRACE) abi_trace(ABI_TRACE_API, "unsupported sysconfig call %d\n", name); #endif return -EINVAL; }
static inline bool lp_possible(void) { return !is_lp_cluster() && !no_lp && !(tegra_cpq_min_cpus() >= 2) && num_online_cpus() == 1; }
void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk) { unsigned int i, id, cpu = smp_processor_id(); unsigned long *map; /* No lockless fast path .. yet */ raw_spin_lock(&context_lock); pr_hard("[%d] activating context for mm @%p, active=%d, id=%d", cpu, next, next->context.active, next->context.id); #ifdef CONFIG_SMP /* Mark us active and the previous one not anymore */ next->context.active++; if (prev) { pr_hardcont(" (old=0x%p a=%d)", prev, prev->context.active); WARN_ON(prev->context.active < 1); prev->context.active--; } again: #endif /* CONFIG_SMP */ /* If we already have a valid assigned context, skip all that */ id = next->context.id; if (likely(id != MMU_NO_CONTEXT)) { #ifdef DEBUG_MAP_CONSISTENCY if (context_mm[id] != next) pr_err("MMU: mm 0x%p has id %d but context_mm[%d] says 0x%p\n", next, id, id, context_mm[id]); #endif goto ctxt_ok; } /* We really don't have a context, let's try to acquire one */ id = next_context; if (id > last_context) id = first_context; map = context_map; /* No more free contexts, let's try to steal one */ if (nr_free_contexts == 0) { #ifdef CONFIG_SMP if (num_online_cpus() > 1) { id = steal_context_smp(id); if (id == MMU_NO_CONTEXT) goto again; goto stolen; } #endif /* CONFIG_SMP */ if (no_selective_tlbil) id = steal_all_contexts(); else id = steal_context_up(id); goto stolen; } nr_free_contexts--; /* We know there's at least one free context, try to find it */ while (__test_and_set_bit(id, map)) { id = find_next_zero_bit(map, last_context+1, id); if (id > last_context) id = first_context; } stolen: next_context = id + 1; context_mm[id] = next; next->context.id = id; pr_hardcont(" | new id=%d,nrf=%d", id, nr_free_contexts); context_check_map(); ctxt_ok: /* If that context got marked stale on this CPU, then flush the * local TLB for it and unmark it before we use it */ if (test_bit(id, stale_map[cpu])) { pr_hardcont(" | stale flush %d [%d..%d]", id, cpu_first_thread_sibling(cpu), cpu_last_thread_sibling(cpu)); local_flush_tlb_mm(next); /* XXX This clear should ultimately be part of local_flush_tlb_mm */ for (i = cpu_first_thread_sibling(cpu); i <= cpu_last_thread_sibling(cpu); i++) { if (stale_map[i]) __clear_bit(id, stale_map[i]); } } /* Flick the MMU and release lock */ pr_hardcont(" -> %d\n", id); set_context(id, next->pgd); raw_spin_unlock(&context_lock); }
/** * acpi_processor_setup_cpuidle - prepares and configures CPUIDLE * @pr: the ACPI processor */ static int acpi_processor_setup_cpuidle(struct acpi_processor *pr) { int i, count = CPUIDLE_DRIVER_STATE_START; struct acpi_processor_cx *cx; struct cpuidle_state *state; struct cpuidle_device *dev = &pr->power.dev; if (!pr->flags.power_setup_done) return -EINVAL; if (pr->flags.power == 0) { return -EINVAL; } dev->cpu = pr->id; for (i = 0; i < CPUIDLE_STATE_MAX; i++) { dev->states[i].name[0] = '\0'; dev->states[i].desc[0] = '\0'; } if (max_cstate == 0) max_cstate = 1; for (i = 1; i < ACPI_PROCESSOR_MAX_POWER && i <= max_cstate; i++) { cx = &pr->power.states[i]; state = &dev->states[count]; if (!cx->valid) continue; #ifdef CONFIG_HOTPLUG_CPU if ((cx->type != ACPI_STATE_C1) && (num_online_cpus() > 1) && !pr->flags.has_cst && !(acpi_gbl_FADT.flags & ACPI_FADT_C2_MP_SUPPORTED)) continue; #endif cpuidle_set_statedata(state, cx); snprintf(state->name, CPUIDLE_NAME_LEN, "C%d", i); strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN); state->exit_latency = cx->latency; state->target_residency = cx->latency * latency_factor; state->power_usage = cx->power; state->flags = 0; switch (cx->type) { case ACPI_STATE_C1: state->flags |= CPUIDLE_FLAG_SHALLOW; if (cx->entry_method == ACPI_CSTATE_FFH) state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_c1; dev->safe_state = state; break; case ACPI_STATE_C2: state->flags |= CPUIDLE_FLAG_BALANCED; state->flags |= CPUIDLE_FLAG_TIME_VALID; state->enter = acpi_idle_enter_simple; dev->safe_state = state; break; case ACPI_STATE_C3: state->flags |= CPUIDLE_FLAG_DEEP; state->flags |= CPUIDLE_FLAG_TIME_VALID; state->flags |= CPUIDLE_FLAG_CHECK_BM; state->enter = pr->flags.bm_check ? acpi_idle_enter_bm : acpi_idle_enter_simple; break; } count++; if (count == CPUIDLE_STATE_MAX) break; } dev->state_count = count; if (!count) return -EINVAL; return 0; }
return; for (cpu = 3; cpu > 0 , should_on_cpu != 0; cpu--) { if (!cpu_online(cpu)) { cpu_up(cpu); pr_info("[cpu] cpu %d is on", cpu); should_on_cpu--; mdelay(cpu_on_mdelay); } } } static ssize_t show_cpu_on(struct sysdev_class *class, struct sysdev_class_attribute *attr, char *buf) { unsigned int cpu = num_online_cpus(); return sprintf(buf, "%u\n", cpu); } static ssize_t store_cpu_on(struct sysdev_class *class, struct sysdev_class_attribute *attr, const char *buf, size_t count) { strict_strtol(buf, 0, &target_number_of_online_cpus ); if(target_number_of_online_cpus < 2) return; if(target_number_of_online_cpus > 4)
/** * acpi_idle_enter_bm - enters C3 with proper BM handling * @dev: the target CPU * @state: the state data * * If BM is detected, the deepest non-C3 idle state is entered instead. */ static int acpi_idle_enter_bm(struct cpuidle_device *dev, struct cpuidle_state *state) { struct acpi_processor *pr; struct acpi_processor_cx *cx = cpuidle_get_statedata(state); ktime_t kt1, kt2; s64 idle_time; s64 sleep_ticks = 0; pr = __get_cpu_var(processors); if (unlikely(!pr)) return 0; if (acpi_idle_suspend) return(acpi_idle_enter_c1(dev, state)); if (acpi_idle_bm_check()) { if (dev->safe_state) { dev->last_state = dev->safe_state; return dev->safe_state->enter(dev, dev->safe_state); } else { local_irq_disable(); acpi_safe_halt(); local_irq_enable(); return 0; } } local_irq_disable(); if (cx->entry_method != ACPI_CSTATE_FFH) { current_thread_info()->status &= ~TS_POLLING; /* * TS_POLLING-cleared state must be visible before we test * NEED_RESCHED: */ smp_mb(); } if (unlikely(need_resched())) { current_thread_info()->status |= TS_POLLING; local_irq_enable(); return 0; } acpi_unlazy_tlb(smp_processor_id()); /* Tell the scheduler that we are going deep-idle: */ sched_clock_idle_sleep_event(); /* * Must be done before busmaster disable as we might need to * access HPET ! */ lapic_timer_state_broadcast(pr, cx, 1); kt1 = ktime_get_real(); /* * disable bus master * bm_check implies we need ARB_DIS * !bm_check implies we need cache flush * bm_control implies whether we can do ARB_DIS * * That leaves a case where bm_check is set and bm_control is * not set. In that case we cannot do much, we enter C3 * without doing anything. */ if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); c3_cpu_count++; /* Disable bus master arbitration when all CPUs are in C3 */ if (c3_cpu_count == num_online_cpus()) acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 1); spin_unlock(&c3_lock); } else if (!pr->flags.bm_check) { ACPI_FLUSH_CPU_CACHE(); } acpi_idle_do_entry(cx); /* Re-enable bus master arbitration */ if (pr->flags.bm_check && pr->flags.bm_control) { spin_lock(&c3_lock); acpi_write_bit_register(ACPI_BITREG_ARB_DISABLE, 0); c3_cpu_count--; spin_unlock(&c3_lock); } kt2 = ktime_get_real(); idle_time = ktime_to_us(ktime_sub(kt2, kt1)); sleep_ticks = us_to_pm_timer_ticks(idle_time); /* Tell the scheduler how much we idled: */ sched_clock_idle_wakeup_event(sleep_ticks*PM_TIMER_TICK_NS); local_irq_enable(); current_thread_info()->status |= TS_POLLING; cx->usage++; lapic_timer_state_broadcast(pr, cx, 0); cx->time += sleep_ticks; return idle_time; }
/* Main interface to do xen specific suspend/resume */ static int enter_state(u32 state) { unsigned long flags; int error; if ( (state <= ACPI_STATE_S0) || (state > ACPI_S_STATES_MAX) ) return -EINVAL; if ( !spin_trylock(&pm_lock) ) return -EBUSY; printk(XENLOG_INFO "Preparing system for ACPI S%d state.", state); freeze_domains(); disable_nonboot_cpus(); if ( num_online_cpus() != 1 ) { error = -EBUSY; goto enable_cpu; } cpufreq_del_cpu(0); hvm_cpu_down(); acpi_sleep_prepare(state); console_start_sync(); printk("Entering ACPI S%d state.\n", state); local_irq_save(flags); spin_debug_disable(); if ( (error = device_power_down()) ) { printk(XENLOG_ERR "Some devices failed to power down."); goto done; } ACPI_FLUSH_CPU_CACHE(); switch ( state ) { case ACPI_STATE_S3: do_suspend_lowlevel(); system_reset_counter++; error = tboot_s3_resume(); break; case ACPI_STATE_S5: acpi_enter_sleep_state(ACPI_STATE_S5); break; default: error = -EINVAL; break; } /* Restore CR4 and EFER from cached values. */ write_cr4(read_cr4()); if ( cpu_has_efer ) write_efer(read_efer()); device_power_up(); printk(XENLOG_INFO "Finishing wakeup from ACPI S%d state.\n", state); if ( (state == ACPI_STATE_S3) && error ) panic("Memory integrity was lost on resume (%d)\n", error); done: spin_debug_enable(); local_irq_restore(flags); console_end_sync(); acpi_sleep_post(state); if ( !hvm_cpu_up() ) BUG(); enable_cpu: cpufreq_add_cpu(0); microcode_resume_cpu(0); enable_nonboot_cpus(); thaw_domains(); spin_unlock(&pm_lock); return error; }
/*---------------------------------------------------------------------------*/ struct xio_context *xio_context_create(unsigned int flags, struct xio_loop_ops *loop_ops, struct task_struct *worker, int polling_timeout, int cpu_hint) { struct xio_context *ctx; struct dentry *xio_root; char name[32]; int cpu; if (cpu_hint > 0 && cpu_hint >= num_online_cpus()) { xio_set_error(EINVAL); ERROR_LOG("cpu_hint(%d) >= num_online_cpus(%d)\n", cpu_hint, num_online_cpus()); goto cleanup0; } if ((flags == XIO_LOOP_USER_LOOP) && (!(loop_ops && loop_ops->add_event && loop_ops->ev_loop))) { xio_set_error(EINVAL); ERROR_LOG("loop_ops and ev_loop and ev_loop_add_event are mandatory with loop_ops\n"); goto cleanup0; } xio_read_logging_level(); /* no need to disable preemption */ cpu = raw_smp_processor_id(); if (cpu == -1) goto cleanup0; /* allocate new context */ ctx = kzalloc(sizeof(struct xio_context), GFP_KERNEL); if (ctx == NULL) { xio_set_error(ENOMEM); ERROR_LOG("kzalloc failed\n"); goto cleanup0; } if (cpu_hint < 0) cpu_hint = cpu; ctx->flags = flags; ctx->cpuid = cpu_hint; ctx->nodeid = cpu_to_node(cpu_hint); ctx->polling_timeout = polling_timeout; ctx->workqueue = xio_workqueue_create(ctx); if (!ctx->workqueue) { xio_set_error(ENOMEM); ERROR_LOG("xio_workqueue_init failed.\n"); goto cleanup1; } XIO_OBSERVABLE_INIT(&ctx->observable, ctx); INIT_LIST_HEAD(&ctx->ctx_list); switch (flags) { case XIO_LOOP_USER_LOOP: break; case XIO_LOOP_GIVEN_THREAD: set_cpus_allowed_ptr(worker, cpumask_of(cpu_hint)); ctx->worker = (uint64_t) worker; break; case XIO_LOOP_TASKLET: break; case XIO_LOOP_WORKQUEUE: break; default: ERROR_LOG("wrong type. %u\n", flags); goto cleanup2; } xio_root = xio_debugfs_root(); if (xio_root) { /* More then one contexts can share the core */ sprintf(name, "ctx-%d-%p", cpu_hint, worker); ctx->ctx_dentry = debugfs_create_dir(name, xio_root); if (!ctx->ctx_dentry) { ERROR_LOG("debugfs entry %s create failed\n", name); goto cleanup2; } } ctx->ev_loop = xio_ev_loop_init(flags, ctx, loop_ops); if (!ctx->ev_loop) goto cleanup3; ctx->stats.hertz = HZ; /* Initialize default counters' name */ ctx->stats.name[XIO_STAT_TX_MSG] = kstrdup("TX_MSG", GFP_KERNEL); ctx->stats.name[XIO_STAT_RX_MSG] = kstrdup("RX_MSG", GFP_KERNEL); ctx->stats.name[XIO_STAT_TX_BYTES] = kstrdup("TX_BYTES", GFP_KERNEL); ctx->stats.name[XIO_STAT_RX_BYTES] = kstrdup("RX_BYTES", GFP_KERNEL); ctx->stats.name[XIO_STAT_DELAY] = kstrdup("DELAY", GFP_KERNEL); ctx->stats.name[XIO_STAT_APPDELAY] = kstrdup("APPDELAY", GFP_KERNEL); return ctx; cleanup3: debugfs_remove_recursive(ctx->ctx_dentry); ctx->ctx_dentry = NULL; cleanup2: xio_workqueue_destroy(ctx->workqueue); cleanup1: kfree(ctx); cleanup0: ERROR_LOG("xio_ctx_open failed\n"); return NULL; }
bool soidle_can_enter(int cpu) { int reason = NR_REASONS; unsigned long long soidle_block_curr_time = 0; #ifdef CONFIG_SMP if ((atomic_read(&is_in_hotplug) == 1)||(num_online_cpus() != 1)) { reason = BY_CPU; goto out; } #endif if(idle_spm_lock){ reason = BY_VTG; goto out; } #if !defined(SODI_DISPLAY_DRV_CHK_DIS) || (SODI_DISPLAY_DRV_CHK_DIS == 0) // decide when to enable SODI by display driver if(spm_get_sodi_en()==0){ reason = BY_OTH; goto out; } #endif #if 0 //workaround for ultra CPU mode if (is_ext_buck_exist()) { reason = BY_OTH; goto out; } #endif if (soidle_by_pass_cg == 0) { memset(soidle_block_mask, 0, NR_GRPS * sizeof(unsigned int)); if (!clkmgr_idle_can_enter(soidle_condition_mask, soidle_block_mask)) { #if !defined(SODI_CG_CHK_DIS) || (SODI_CG_CHK_DIS == 0) reason = BY_CLK; goto out; #endif } } #ifdef CONFIG_SMP soidle_timer_left = localtimer_get_counter(); if ((int)soidle_timer_left < soidle_time_critera || ((int)soidle_timer_left) < 0) { reason = BY_TMR; goto out; } #else gpt_get_cnt(GPT1, &soidle_timer_left); gpt_get_cmp(GPT1, &soidle_timer_cmp); if((soidle_timer_cmp-soidle_timer_left)<soidle_time_critera) { reason = BY_TMR; goto out; } #endif out: if (reason < NR_REASONS) { if( soidle_block_prev_time == 0 ) soidle_block_prev_time = idle_get_current_time_ms(); soidle_block_curr_time = idle_get_current_time_ms(); if((soidle_block_curr_time - soidle_block_prev_time) > soidle_block_time_critera) { if ((smp_processor_id() == 0)) { int i = 0; for (i = 0; i < nr_cpu_ids; i++) { idle_ver("soidle_cnt[%d]=%lu, rgidle_cnt[%d]=%lu\n", i, soidle_cnt[i], i, rgidle_cnt[i]); } for (i = 0; i < NR_REASONS; i++) { idle_ver("[%d]soidle_block_cnt[0][%s]=%lu\n", i, reason_name[i], soidle_block_cnt[0][i]); } for (i = 0; i < NR_GRPS; i++) { idle_ver("[%02d]soidle_condition_mask[%-8s]=0x%08x\t\t" "soidle_block_mask[%-8s]=0x%08x\n", i, grp_get_name(i), soidle_condition_mask[i], grp_get_name(i), soidle_block_mask[i]); } memset(soidle_block_cnt, 0, sizeof(soidle_block_cnt)); soidle_block_prev_time = idle_get_current_time_ms(); } } soidle_block_cnt[cpu][reason]++; return false; } else { soidle_block_prev_time = idle_get_current_time_ms(); return true; } }
/* Requires cpu_add_remove_lock to be held */ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) { int err, nr_calls = 0; void *hcpu = (void *)(long)cpu; unsigned long mod = tasks_frozen ? CPU_TASKS_FROZEN : 0; struct take_cpu_down_param tcd_param = { .mod = mod, .hcpu = hcpu, }; if (num_online_cpus() == 1) return -EBUSY; if (!cpu_online(cpu)) return -EINVAL; cpu_hotplug_begin(); err = __cpu_notify(CPU_DOWN_PREPARE | mod, hcpu, -1, &nr_calls); if (err) { nr_calls--; __cpu_notify(CPU_DOWN_FAILED | mod, hcpu, nr_calls, NULL); printk("%s: attempt to take down CPU %u failed\n", __func__, cpu); goto out_release; } smpboot_park_threads(cpu); err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu)); if (err) { /* CPU didn't die: tell everyone. Can't complain. */ smpboot_unpark_threads(cpu); cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu); goto out_release; } BUG_ON(cpu_online(cpu)); /* * The migration_call() CPU_DYING callback will have removed all * runnable tasks from the cpu, there's only the idle task left now * that the migration thread is done doing the stop_machine thing. * * Wait for the stop thread to go away. */ while (!idle_cpu(cpu)) cpu_relax(); /* This actually kills the CPU. */ __cpu_die(cpu); /* CPU is completely dead: tell everyone. Too late to complain. */ cpu_notify_nofail(CPU_DEAD | mod, hcpu); check_for_tasks(cpu); out_release: cpu_hotplug_done(); if (!err) cpu_notify_nofail(CPU_POST_DEAD | mod, hcpu); return err; }
static void update_load_stats_state(void) { unsigned int load; unsigned int nr_cpu_online; unsigned int max_cpus = cpq_max_cpus(); unsigned int min_cpus = cpq_min_cpus(); u64 current_time; u64 this_time = 0; int index; if (load_stats_state == DISABLED) return; current_time = ktime_to_ms(ktime_get()); if (current_time <= start_delay){ load_stats_state = IDLE; return; } if (first_call) { first_call = false; } else { this_time = current_time - last_time; } total_time += this_time; load = report_load(); nr_cpu_online = num_online_cpus(); load_stats_state = IDLE; if (nr_cpu_online) { index = (nr_cpu_online - 1) * 2; if ((nr_cpu_online < CONFIG_NR_CPUS) && (load >= load_threshold[index])) { if (total_time >= twts_threshold[index]) { if (nr_cpu_online < max_cpus){ hotplug_info("UP load=%d total_time=%lld load_threshold[index]=%d twts_threshold[index]=%d nr_cpu_online=%d min_cpus=%d max_cpus=%d\n", load, total_time, load_threshold[index], twts_threshold[index], nr_cpu_online, min_cpus, max_cpus); load_stats_state = UP; } } } else if (load <= load_threshold[index+1]) { if (total_time >= twts_threshold[index+1] ) { if ((nr_cpu_online > 1) && (nr_cpu_online > min_cpus)){ hotplug_info("DOWN load=%d total_time=%lld load_threshold[index+1]=%d twts_threshold[index+1]=%d nr_cpu_online=%d min_cpus=%d max_cpus=%d\n", load, total_time, load_threshold[index+1], twts_threshold[index+1], nr_cpu_online, min_cpus, max_cpus); load_stats_state = DOWN; } } } else { load_stats_state = IDLE; total_time = 0; } } else { total_time = 0; } if (input_boost_running && current_time > input_boost_end_time) input_boost_running = false; if (input_boost_running){ if (load_stats_state != UP){ load_stats_state = IDLE; hotplug_info("IDLE because of input boost\n"); } } if (load_stats_state != IDLE) total_time = 0; last_time = ktime_to_ms(ktime_get()); }
void __init smp_cpus_done(unsigned int max_cpus) { pr_info("SMP: Total of %d processors activated.\n", num_online_cpus()); }