#!/bin/sh

# cpuhotplug_hotplug.sh - Collection of functions for hotplugging
# operations.

# Routines in this library are set up to allow timing to be done
# by defining $TIME to a timing command.
TIME=${TIME:-""}

# get_all_irqs()
#
#  Gets list of all available IRQs in the system
#
get_all_irqs()
{
    echo `egrep [0-9]+: /proc/interrupts | cut -d ':' -f 1`
    return
}

# migrate_irq(CPU, IRQS)
#
#  Sets the smp_affinity for the list of $IRQS to the given
#  CPU number
#
migrate_irq()
{
    CPU=${1#cpu}
    MASK=$((1<<${CPU}))
    IRQS=$2
    for irq in ${IRQS}
      do
      echo $MASK > /proc/irq/${irq}/smp_affinity || \
        tst_resm TINFO "It is NOT permitted to change the IRQ $irq smp_affinity"
    done
}


# get_affinity(PID)
#
#  Echos the CPU affinity for the given process ID to stdout
#
get_affinity_mask()
{
    AFFINITY=`taskset -p ${1}`
    echo ${AFFINITY}
    return
}

# set_affinity(PID, CPU)
#
#  Sets the affinity for the given PID to the specified CPU.
#
set_affinity()
{
    PID="$1"
    CPU="$2"
    MASK=$((1<<${CPU_TO_TEST}))
    `taskset -p ${MASK} ${PID} > /dev/null 2>&1`
    return $?
}

# online_cpu(CPU)
#
#  Onlines the given CPU.  Returns a true value if it was able
#  to perform the online operation successfully, false otherwise.
#
#  $CPU should either be a specific number like 4, or the cpu name,
#  as in 'cpu4'.
#
online_cpu()
{
    CPU=${1#cpu}
    if [ ! -w /sys/devices/system/cpu/cpu${CPU}/online ]; then
        return 1
    fi
    $TIME echo 1 > /sys/devices/system/cpu/cpu${CPU}/online
    RC=$?
    report_timing "Online cpu ${CPU}"
    return $RC
}


# offline_cpu(CPU)
#
#  Offlines the given CPU.  Returns a true value if it was able
#  to perform the offline operation successfully, false otherwise.
#
offline_cpu()
{
    CPU=${1#cpu}
    if [ ! -w /sys/devices/system/cpu/cpu${CPU}/online ]; then
        return 1
    fi
    $TIME echo 0 > /sys/devices/system/cpu/cpu${CPU}/online
    RC=$?
    report_timing "Offline cpu ${CPU}"
    return $RC
}

# get_cpus_num()
#
#  Prints the number of all available CPUs, regardless of whether they're
#  currently online or offline.
#
get_cpus_num()
{
	[ -d /sys/devices/system/cpu/cpu0 ] || return -1
	NUM=`ls /sys/devices/system/cpu/ \
			| grep -c "cpu[0-9][0-9]*"`
	return $NUM
}

# get_all_cpus()
#
#  Prints a list of all available CPUs, regardless of whether they're
#  currently online or offline.
#
#  This routine will work even if the CPUs are not hotpluggable, however
#  it requires you have sysfs enabled in the kernel.
#
get_all_cpus()
{
    [ -d /sys/devices/system/cpu/cpu0 ] || return 1
    ls -dr /sys/devices/system/cpu/cpu[0-9]* | \
        sed "s/\/sys\/devices\/system\/cpu\///g" || return 2
}


# get_all_cpu_states()
#
#  Collects the current online/offline state of CPUs in the
#  system, printing it in a format that can be passed to
#  set_all_cpu_states() later.
#
get_all_cpu_states()
{
    echo `cd /sys/devices/system/cpu/ && grep '' */online | \
		sed -e 's/\/online//'`
    return
}

# set_all_cpu_states(STATES)
#
#  Sets all of the CPU states according to $STATE, which must be
#  of the form "cpuX:Y", where X is the CPU number and Y its state.
#  Each must be on a separate line.
#
set_all_cpu_states()
{
    for cpu_state in $STATE; do
        cpu=`echo $c | cut -d: -f 1`
        state=`echo $c | cut -d: -f 1`
        if [ $state = 1 ]; then
            echo "# Re-onlining $cpu"
            online_cpu $cpu
        else
            echo "# Re-offlining $cpu"
            offline_cpu $cpu
        fi
    done
}


# get_online_cpus()
#
#  Prints a list of all CPUs currently online.  This function only
#  works if the system's CPUs have hotplug capabilities
#
get_online_cpus()
{
    echo `cd /sys/devices/system/cpu/ && grep 1 */online | cut -d '/' -f 1`
    return
}


# get_offline_cpus()
#
#  Prints a list of all CPUs currently offline.  This function only
#  works if the system's CPUs have hotplug capabilities
#
get_offline_cpus()
{
    echo `cd /sys/devices/system/cpu/ && grep 0 */online | cut -d '/' -f 1`
    return
}

# cpu_is_valid(CPU)
#
#  Checks to see if the given CPU number is available for hotplugging
#  in the system.  Returns 0 if the CPU is available, 1 otherwise.
#
cpu_is_valid()
{
    CPU=${1#cpu}
    echo "CPU is $CPU"
    cat /sys/devices/system/cpu/cpu${CPU}/online > /dev/null 2>&1
    return $?
}


# cpu_is_online(CPU)
#
#  Returns a 0 value if the given CPU number is currently online,
#  1 otherwise.  This function requires the system's CPUs have
#  hotplug capabilities.
#
cpu_is_online()
{
    CPU=${1#cpu}
    if [ `cat /sys/devices/system/cpu/cpu${CPU}/online` = "1" ]; then
        return 0
    else
        return 1
    fi
}
