Commit e35db92b authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

Merge branches 'pm-cpuidle', 'pm-opp' and 'pm-avs'

* pm-cpuidle:
  ARM: cpuidle: Fix error return code

* pm-opp:
  PM / OPP: Don't support OPP if it provides supported-hw but platform does not
  PM / OPP: avoid maybe-uninitialized warning

* pm-avs:
  PM / AVS: SmartReflex: Neaten logging
...@@ -584,7 +584,6 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) ...@@ -584,7 +584,6 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
struct clk *clk; struct clk *clk;
unsigned long freq, old_freq; unsigned long freq, old_freq;
unsigned long u_volt, u_volt_min, u_volt_max; unsigned long u_volt, u_volt_min, u_volt_max;
unsigned long ou_volt, ou_volt_min, ou_volt_max;
int ret; int ret;
if (unlikely(!target_freq)) { if (unlikely(!target_freq)) {
...@@ -620,11 +619,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) ...@@ -620,11 +619,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
} }
old_opp = _find_freq_ceil(opp_table, &old_freq); old_opp = _find_freq_ceil(opp_table, &old_freq);
if (!IS_ERR(old_opp)) { if (IS_ERR(old_opp)) {
ou_volt = old_opp->u_volt;
ou_volt_min = old_opp->u_volt_min;
ou_volt_max = old_opp->u_volt_max;
} else {
dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n", dev_err(dev, "%s: failed to find current OPP for freq %lu (%ld)\n",
__func__, old_freq, PTR_ERR(old_opp)); __func__, old_freq, PTR_ERR(old_opp));
} }
...@@ -683,7 +678,8 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) ...@@ -683,7 +678,8 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq)
restore_voltage: restore_voltage:
/* This shouldn't harm even if the voltages weren't updated earlier */ /* This shouldn't harm even if the voltages weren't updated earlier */
if (!IS_ERR(old_opp)) if (!IS_ERR(old_opp))
_set_opp_voltage(dev, reg, ou_volt, ou_volt_min, ou_volt_max); _set_opp_voltage(dev, reg, old_opp->u_volt,
old_opp->u_volt_min, old_opp->u_volt_max);
return ret; return ret;
} }
......
...@@ -71,8 +71,18 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table, ...@@ -71,8 +71,18 @@ static bool _opp_is_supported(struct device *dev, struct opp_table *opp_table,
u32 version; u32 version;
int ret; int ret;
if (!opp_table->supported_hw) if (!opp_table->supported_hw) {
return true; /*
* In the case that no supported_hw has been set by the
* platform but there is an opp-supported-hw value set for
* an OPP then the OPP should not be enabled as there is
* no way to see if the hardware supports it.
*/
if (of_find_property(np, "opp-supported-hw", NULL))
return false;
else
return true;
}
while (count--) { while (count--) {
ret = of_property_read_u32_index(np, "opp-supported-hw", count, ret = of_property_read_u32_index(np, "opp-supported-hw", count,
......
...@@ -121,6 +121,7 @@ static int __init arm_idle_init(void) ...@@ -121,6 +121,7 @@ static int __init arm_idle_init(void)
dev = kzalloc(sizeof(*dev), GFP_KERNEL); dev = kzalloc(sizeof(*dev), GFP_KERNEL);
if (!dev) { if (!dev) {
pr_err("Failed to allocate cpuidle device\n"); pr_err("Failed to allocate cpuidle device\n");
ret = -ENOMEM;
goto out_fail; goto out_fail;
} }
dev->cpu = cpu; dev->cpu = cpu;
......
...@@ -136,7 +136,7 @@ static void sr_set_clk_length(struct omap_sr *sr) ...@@ -136,7 +136,7 @@ static void sr_set_clk_length(struct omap_sr *sr)
if (IS_ERR(fck)) { if (IS_ERR(fck)) {
dev_err(&sr->pdev->dev, "%s: unable to get fck for device %s\n", dev_err(&sr->pdev->dev, "%s: unable to get fck for device %s\n",
__func__, dev_name(&sr->pdev->dev)); __func__, dev_name(&sr->pdev->dev));
return; return;
} }
...@@ -170,8 +170,8 @@ static void sr_start_vddautocomp(struct omap_sr *sr) ...@@ -170,8 +170,8 @@ static void sr_start_vddautocomp(struct omap_sr *sr)
{ {
if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
dev_warn(&sr->pdev->dev, dev_warn(&sr->pdev->dev,
"%s: smartreflex class driver not registered\n", "%s: smartreflex class driver not registered\n",
__func__); __func__);
return; return;
} }
...@@ -183,8 +183,8 @@ static void sr_stop_vddautocomp(struct omap_sr *sr) ...@@ -183,8 +183,8 @@ static void sr_stop_vddautocomp(struct omap_sr *sr)
{ {
if (!sr_class || !(sr_class->disable)) { if (!sr_class || !(sr_class->disable)) {
dev_warn(&sr->pdev->dev, dev_warn(&sr->pdev->dev,
"%s: smartreflex class driver not registered\n", "%s: smartreflex class driver not registered\n",
__func__); __func__);
return; return;
} }
...@@ -225,9 +225,8 @@ static int sr_late_init(struct omap_sr *sr_info) ...@@ -225,9 +225,8 @@ static int sr_late_init(struct omap_sr *sr_info)
error: error:
list_del(&sr_info->node); list_del(&sr_info->node);
dev_err(&sr_info->pdev->dev, "%s: ERROR in registering" dev_err(&sr_info->pdev->dev, "%s: ERROR in registering interrupt handler. Smartreflex will not function as desired\n",
"interrupt handler. Smartreflex will" __func__);
"not function as desired\n", __func__);
return ret; return ret;
} }
...@@ -263,7 +262,7 @@ static void sr_v1_disable(struct omap_sr *sr) ...@@ -263,7 +262,7 @@ static void sr_v1_disable(struct omap_sr *sr)
if (timeout >= SR_DISABLE_TIMEOUT) if (timeout >= SR_DISABLE_TIMEOUT)
dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
__func__); __func__);
/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */ /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN, sr_modify_reg(sr, ERRCONFIG_V1, ERRCONFIG_MCUDISACKINTEN,
...@@ -308,7 +307,7 @@ static void sr_v2_disable(struct omap_sr *sr) ...@@ -308,7 +307,7 @@ static void sr_v2_disable(struct omap_sr *sr)
if (timeout >= SR_DISABLE_TIMEOUT) if (timeout >= SR_DISABLE_TIMEOUT)
dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n", dev_warn(&sr->pdev->dev, "%s: Smartreflex disable timedout\n",
__func__); __func__);
/* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */ /* Disable MCUDisableAcknowledge interrupt & clear pending interrupt */
sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT); sr_write_reg(sr, IRQENABLE_CLR, IRQENABLE_MCUDISABLEACKINT);
...@@ -322,7 +321,7 @@ static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row( ...@@ -322,7 +321,7 @@ static struct omap_sr_nvalue_table *sr_retrieve_nvalue_row(
if (!sr->nvalue_table) { if (!sr->nvalue_table) {
dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n", dev_warn(&sr->pdev->dev, "%s: Missing ntarget value table\n",
__func__); __func__);
return NULL; return NULL;
} }
...@@ -356,8 +355,8 @@ int sr_configure_errgen(struct omap_sr *sr) ...@@ -356,8 +355,8 @@ int sr_configure_errgen(struct omap_sr *sr)
u8 senp_shift, senn_shift; u8 senp_shift, senn_shift;
if (!sr) { if (!sr) {
pr_warn("%s: NULL omap_sr from %pF\n", __func__, pr_warn("%s: NULL omap_sr from %pF\n",
(void *)_RET_IP_); __func__, (void *)_RET_IP_);
return -EINVAL; return -EINVAL;
} }
...@@ -387,8 +386,8 @@ int sr_configure_errgen(struct omap_sr *sr) ...@@ -387,8 +386,8 @@ int sr_configure_errgen(struct omap_sr *sr)
vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2; vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
break; break;
default: default:
dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n",
"module without specifying the ip\n", __func__); __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -423,8 +422,8 @@ int sr_disable_errgen(struct omap_sr *sr) ...@@ -423,8 +422,8 @@ int sr_disable_errgen(struct omap_sr *sr)
u32 vpboundint_en, vpboundint_st; u32 vpboundint_en, vpboundint_st;
if (!sr) { if (!sr) {
pr_warn("%s: NULL omap_sr from %pF\n", __func__, pr_warn("%s: NULL omap_sr from %pF\n",
(void *)_RET_IP_); __func__, (void *)_RET_IP_);
return -EINVAL; return -EINVAL;
} }
...@@ -440,8 +439,8 @@ int sr_disable_errgen(struct omap_sr *sr) ...@@ -440,8 +439,8 @@ int sr_disable_errgen(struct omap_sr *sr)
vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2; vpboundint_st = ERRCONFIG_VPBOUNDINTST_V2;
break; break;
default: default:
dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n",
"module without specifying the ip\n", __func__); __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -478,8 +477,8 @@ int sr_configure_minmax(struct omap_sr *sr) ...@@ -478,8 +477,8 @@ int sr_configure_minmax(struct omap_sr *sr)
u8 senp_shift, senn_shift; u8 senp_shift, senn_shift;
if (!sr) { if (!sr) {
pr_warn("%s: NULL omap_sr from %pF\n", __func__, pr_warn("%s: NULL omap_sr from %pF\n",
(void *)_RET_IP_); __func__, (void *)_RET_IP_);
return -EINVAL; return -EINVAL;
} }
...@@ -504,8 +503,8 @@ int sr_configure_minmax(struct omap_sr *sr) ...@@ -504,8 +503,8 @@ int sr_configure_minmax(struct omap_sr *sr)
senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT; senp_shift = SRCONFIG_SENPENABLE_V2_SHIFT;
break; break;
default: default:
dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n",
"module without specifying the ip\n", __func__); __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -537,8 +536,8 @@ int sr_configure_minmax(struct omap_sr *sr) ...@@ -537,8 +536,8 @@ int sr_configure_minmax(struct omap_sr *sr)
IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT); IRQENABLE_MCUBOUNDSINT | IRQENABLE_MCUDISABLEACKINT);
break; break;
default: default:
dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex" dev_err(&sr->pdev->dev, "%s: Trying to Configure smartreflex module without specifying the ip\n",
"module without specifying the ip\n", __func__); __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -563,16 +562,16 @@ int sr_enable(struct omap_sr *sr, unsigned long volt) ...@@ -563,16 +562,16 @@ int sr_enable(struct omap_sr *sr, unsigned long volt)
int ret; int ret;
if (!sr) { if (!sr) {
pr_warn("%s: NULL omap_sr from %pF\n", __func__, pr_warn("%s: NULL omap_sr from %pF\n",
(void *)_RET_IP_); __func__, (void *)_RET_IP_);
return -EINVAL; return -EINVAL;
} }
volt_data = omap_voltage_get_voltdata(sr->voltdm, volt); volt_data = omap_voltage_get_voltdata(sr->voltdm, volt);
if (IS_ERR(volt_data)) { if (IS_ERR(volt_data)) {
dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table" dev_warn(&sr->pdev->dev, "%s: Unable to get voltage table for nominal voltage %ld\n",
"for nominal voltage %ld\n", __func__, volt); __func__, volt);
return PTR_ERR(volt_data); return PTR_ERR(volt_data);
} }
...@@ -615,8 +614,8 @@ int sr_enable(struct omap_sr *sr, unsigned long volt) ...@@ -615,8 +614,8 @@ int sr_enable(struct omap_sr *sr, unsigned long volt)
void sr_disable(struct omap_sr *sr) void sr_disable(struct omap_sr *sr)
{ {
if (!sr) { if (!sr) {
pr_warn("%s: NULL omap_sr from %pF\n", __func__, pr_warn("%s: NULL omap_sr from %pF\n",
(void *)_RET_IP_); __func__, (void *)_RET_IP_);
return; return;
} }
...@@ -658,13 +657,13 @@ int sr_register_class(struct omap_sr_class_data *class_data) ...@@ -658,13 +657,13 @@ int sr_register_class(struct omap_sr_class_data *class_data)
struct omap_sr *sr_info; struct omap_sr *sr_info;
if (!class_data) { if (!class_data) {
pr_warning("%s:, Smartreflex class data passed is NULL\n", pr_warn("%s:, Smartreflex class data passed is NULL\n",
__func__); __func__);
return -EINVAL; return -EINVAL;
} }
if (sr_class) { if (sr_class) {
pr_warning("%s: Smartreflex class driver already registered\n", pr_warn("%s: Smartreflex class driver already registered\n",
__func__); __func__);
return -EBUSY; return -EBUSY;
} }
...@@ -696,7 +695,7 @@ void omap_sr_enable(struct voltagedomain *voltdm) ...@@ -696,7 +695,7 @@ void omap_sr_enable(struct voltagedomain *voltdm)
struct omap_sr *sr = _sr_lookup(voltdm); struct omap_sr *sr = _sr_lookup(voltdm);
if (IS_ERR(sr)) { if (IS_ERR(sr)) {
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); pr_warn("%s: omap_sr struct for voltdm not found\n", __func__);
return; return;
} }
...@@ -704,8 +703,8 @@ void omap_sr_enable(struct voltagedomain *voltdm) ...@@ -704,8 +703,8 @@ void omap_sr_enable(struct voltagedomain *voltdm)
return; return;
if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) { if (!sr_class || !(sr_class->enable) || !(sr_class->configure)) {
dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",
"registered\n", __func__); __func__);
return; return;
} }
...@@ -728,7 +727,7 @@ void omap_sr_disable(struct voltagedomain *voltdm) ...@@ -728,7 +727,7 @@ void omap_sr_disable(struct voltagedomain *voltdm)
struct omap_sr *sr = _sr_lookup(voltdm); struct omap_sr *sr = _sr_lookup(voltdm);
if (IS_ERR(sr)) { if (IS_ERR(sr)) {
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); pr_warn("%s: omap_sr struct for voltdm not found\n", __func__);
return; return;
} }
...@@ -736,8 +735,8 @@ void omap_sr_disable(struct voltagedomain *voltdm) ...@@ -736,8 +735,8 @@ void omap_sr_disable(struct voltagedomain *voltdm)
return; return;
if (!sr_class || !(sr_class->disable)) { if (!sr_class || !(sr_class->disable)) {
dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",
"registered\n", __func__); __func__);
return; return;
} }
...@@ -760,7 +759,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) ...@@ -760,7 +759,7 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
struct omap_sr *sr = _sr_lookup(voltdm); struct omap_sr *sr = _sr_lookup(voltdm);
if (IS_ERR(sr)) { if (IS_ERR(sr)) {
pr_warning("%s: omap_sr struct for voltdm not found\n", __func__); pr_warn("%s: omap_sr struct for voltdm not found\n", __func__);
return; return;
} }
...@@ -768,8 +767,8 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) ...@@ -768,8 +767,8 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
return; return;
if (!sr_class || !(sr_class->disable)) { if (!sr_class || !(sr_class->disable)) {
dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not" dev_warn(&sr->pdev->dev, "%s: smartreflex class driver not registered\n",
"registered\n", __func__); __func__);
return; return;
} }
...@@ -787,8 +786,8 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm) ...@@ -787,8 +786,8 @@ void omap_sr_disable_reset_volt(struct voltagedomain *voltdm)
void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data) void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data)
{ {
if (!pmic_data) { if (!pmic_data) {
pr_warning("%s: Trying to register NULL PMIC data structure" pr_warn("%s: Trying to register NULL PMIC data structure with smartreflex\n",
"with smartreflex\n", __func__); __func__);
return; return;
} }
...@@ -801,7 +800,7 @@ static int omap_sr_autocomp_show(void *data, u64 *val) ...@@ -801,7 +800,7 @@ static int omap_sr_autocomp_show(void *data, u64 *val)
struct omap_sr *sr_info = data; struct omap_sr *sr_info = data;
if (!sr_info) { if (!sr_info) {
pr_warning("%s: omap_sr struct not found\n", __func__); pr_warn("%s: omap_sr struct not found\n", __func__);
return -EINVAL; return -EINVAL;
} }
...@@ -815,13 +814,13 @@ static int omap_sr_autocomp_store(void *data, u64 val) ...@@ -815,13 +814,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)
struct omap_sr *sr_info = data; struct omap_sr *sr_info = data;
if (!sr_info) { if (!sr_info) {
pr_warning("%s: omap_sr struct not found\n", __func__); pr_warn("%s: omap_sr struct not found\n", __func__);
return -EINVAL; return -EINVAL;
} }
/* Sanity check */ /* Sanity check */
if (val > 1) { if (val > 1) {
pr_warning("%s: Invalid argument %lld\n", __func__, val); pr_warn("%s: Invalid argument %lld\n", __func__, val);
return -EINVAL; return -EINVAL;
} }
...@@ -848,19 +847,13 @@ static int __init omap_sr_probe(struct platform_device *pdev) ...@@ -848,19 +847,13 @@ static int __init omap_sr_probe(struct platform_device *pdev)
int i, ret = 0; int i, ret = 0;
sr_info = devm_kzalloc(&pdev->dev, sizeof(struct omap_sr), GFP_KERNEL); sr_info = devm_kzalloc(&pdev->dev, sizeof(struct omap_sr), GFP_KERNEL);
if (!sr_info) { if (!sr_info)
dev_err(&pdev->dev, "%s: unable to allocate sr_info\n",
__func__);
return -ENOMEM; return -ENOMEM;
}
sr_info->name = devm_kzalloc(&pdev->dev, sr_info->name = devm_kzalloc(&pdev->dev,
SMARTREFLEX_NAME_LEN, GFP_KERNEL); SMARTREFLEX_NAME_LEN, GFP_KERNEL);
if (!sr_info->name) { if (!sr_info->name)
dev_err(&pdev->dev, "%s: unable to allocate SR instance name\n",
__func__);
return -ENOMEM; return -ENOMEM;
}
platform_set_drvdata(pdev, sr_info); platform_set_drvdata(pdev, sr_info);
...@@ -912,7 +905,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) ...@@ -912,7 +905,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
if (sr_class) { if (sr_class) {
ret = sr_late_init(sr_info); ret = sr_late_init(sr_info);
if (ret) { if (ret) {
pr_warning("%s: Error in SR late init\n", __func__); pr_warn("%s: Error in SR late init\n", __func__);
goto err_list_del; goto err_list_del;
} }
} }
...@@ -923,7 +916,7 @@ static int __init omap_sr_probe(struct platform_device *pdev) ...@@ -923,7 +916,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
if (IS_ERR_OR_NULL(sr_dbg_dir)) { if (IS_ERR_OR_NULL(sr_dbg_dir)) {
ret = PTR_ERR(sr_dbg_dir); ret = PTR_ERR(sr_dbg_dir);
pr_err("%s:sr debugfs dir creation failed(%d)\n", pr_err("%s:sr debugfs dir creation failed(%d)\n",
__func__, ret); __func__, ret);
goto err_list_del; goto err_list_del;
} }
} }
...@@ -945,8 +938,8 @@ static int __init omap_sr_probe(struct platform_device *pdev) ...@@ -945,8 +938,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir); nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
if (IS_ERR_OR_NULL(nvalue_dir)) { if (IS_ERR_OR_NULL(nvalue_dir)) {
dev_err(&pdev->dev, "%s: Unable to create debugfs directory" dev_err(&pdev->dev, "%s: Unable to create debugfs directory for n-values\n",
"for n-values\n", __func__); __func__);
ret = PTR_ERR(nvalue_dir); ret = PTR_ERR(nvalue_dir);
goto err_debugfs; goto err_debugfs;
} }
...@@ -1053,12 +1046,12 @@ static int __init sr_init(void) ...@@ -1053,12 +1046,12 @@ static int __init sr_init(void)
if (sr_pmic_data && sr_pmic_data->sr_pmic_init) if (sr_pmic_data && sr_pmic_data->sr_pmic_init)
sr_pmic_data->sr_pmic_init(); sr_pmic_data->sr_pmic_init();
else else
pr_warning("%s: No PMIC hook to init smartreflex\n", __func__); pr_warn("%s: No PMIC hook to init smartreflex\n", __func__);
ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe); ret = platform_driver_probe(&smartreflex_driver, omap_sr_probe);
if (ret) { if (ret) {
pr_err("%s: platform driver register failed for SR\n", pr_err("%s: platform driver register failed for SR\n",
__func__); __func__);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment