forked from Mirrors/opensbi
		
	lib: sbi: Use sbi_hartmask in sbi_hsm_hart_interruptible_mask()
This removes several hartid/hartindex conversions, as well as two loops through the mask for broadcast IPIs. Signed-off-by: Samuel Holland <samuel.holland@sifive.com> Reviewed-by: Anup Patel <anup@brainfault.org>
This commit is contained in:
		
				
					committed by
					
						
						Anup Patel
					
				
			
			
				
	
			
			
			
						parent
						
							ebe0f31446
						
					
				
				
					commit
					fe153c5516
				
			@@ -226,14 +226,13 @@ extern struct sbi_dlist domain_list;
 | 
			
		||||
bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get ulong assigned HART mask for given domain and HART base ID
 | 
			
		||||
 * Get the assigned HART mask for given domain
 | 
			
		||||
 * @param dom pointer to domain
 | 
			
		||||
 * @param hbase the HART base ID
 | 
			
		||||
 * @return ulong possible HART mask
 | 
			
		||||
 * Note: the return ulong mask will be set to zero on failure.
 | 
			
		||||
 * @param mask the output hartmask to fill
 | 
			
		||||
 * @return 0 on success and SBI_Exxx (< 0) on failure
 | 
			
		||||
 */
 | 
			
		||||
ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
 | 
			
		||||
				       ulong hbase);
 | 
			
		||||
int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
 | 
			
		||||
				     struct sbi_hartmask *mask);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Initialize a domain memory region based on it's physical
 | 
			
		||||
 
 | 
			
		||||
@@ -127,6 +127,18 @@ static inline void sbi_hartmask_clear_all(struct sbi_hartmask *dstp)
 | 
			
		||||
	bitmap_zero(sbi_hartmask_bits(dstp), SBI_HARTMASK_MAX_BITS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * *dstp = *srcp
 | 
			
		||||
 * @param dstp the hartmask destination
 | 
			
		||||
 * @param srcp the hartmask source
 | 
			
		||||
 */
 | 
			
		||||
static inline void sbi_hartmask_copy(struct sbi_hartmask *dstp,
 | 
			
		||||
				     const struct sbi_hartmask *srcp)
 | 
			
		||||
{
 | 
			
		||||
	bitmap_copy(sbi_hartmask_bits(dstp), sbi_hartmask_bits(srcp),
 | 
			
		||||
		    SBI_HARTMASK_MAX_BITS);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * *dstp = *src1p & *src2p
 | 
			
		||||
 * @param dstp the hartmask result
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@
 | 
			
		||||
#ifndef __SBI_HSM_H__
 | 
			
		||||
#define __SBI_HSM_H__
 | 
			
		||||
 | 
			
		||||
#include <sbi/sbi_hartmask.h>
 | 
			
		||||
#include <sbi/sbi_types.h>
 | 
			
		||||
 | 
			
		||||
/** Hart state managment device */
 | 
			
		||||
@@ -75,7 +76,7 @@ bool sbi_hsm_hart_change_state(struct sbi_scratch *scratch, long oldstate,
 | 
			
		||||
int __sbi_hsm_hart_get_state(u32 hartindex);
 | 
			
		||||
int sbi_hsm_hart_get_state(const struct sbi_domain *dom, u32 hartid);
 | 
			
		||||
int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom,
 | 
			
		||||
				    ulong hbase, ulong *out_hmask);
 | 
			
		||||
				    struct sbi_hartmask *mask);
 | 
			
		||||
void __sbi_hsm_suspend_non_ret_save(struct sbi_scratch *scratch);
 | 
			
		||||
void __noreturn sbi_hsm_hart_start_finish(struct sbi_scratch *scratch,
 | 
			
		||||
					  u32 hartid);
 | 
			
		||||
 
 | 
			
		||||
@@ -75,20 +75,19 @@ bool sbi_domain_is_assigned_hart(const struct sbi_domain *dom, u32 hartid)
 | 
			
		||||
	return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ulong sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
 | 
			
		||||
				       ulong hbase)
 | 
			
		||||
int sbi_domain_get_assigned_hartmask(const struct sbi_domain *dom,
 | 
			
		||||
				     struct sbi_hartmask *mask)
 | 
			
		||||
{
 | 
			
		||||
	ulong ret = 0;
 | 
			
		||||
	struct sbi_domain *tdom = (struct sbi_domain *)dom;
 | 
			
		||||
 | 
			
		||||
	if (!dom)
 | 
			
		||||
	if (!dom) {
 | 
			
		||||
		sbi_hartmask_clear_all(mask);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	spin_lock(&tdom->assigned_harts_lock);
 | 
			
		||||
	for (int i = 0; i < 8 * sizeof(ret); i++) {
 | 
			
		||||
		if (sbi_hartmask_test_hartid(hbase + i, &tdom->assigned_harts))
 | 
			
		||||
			ret |= 1UL << i;
 | 
			
		||||
	}
 | 
			
		||||
	sbi_hartmask_copy(mask, &tdom->assigned_harts);
 | 
			
		||||
	spin_unlock(&tdom->assigned_harts_lock);
 | 
			
		||||
 | 
			
		||||
	return ret;
 | 
			
		||||
 
 | 
			
		||||
@@ -110,36 +110,27 @@ static void hsm_start_ticket_release(struct sbi_hsm_data *hdata)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Get ulong HART mask for given HART base ID
 | 
			
		||||
 * Get the mask of harts which are valid IPI targets
 | 
			
		||||
 * @param dom the domain to be used for output HART mask
 | 
			
		||||
 * @param hbase the HART base ID
 | 
			
		||||
 * @param out_hmask the output ulong HART mask
 | 
			
		||||
 * @param mask the output hartmask to fill
 | 
			
		||||
 * @return 0 on success and SBI_Exxx (< 0) on failure
 | 
			
		||||
 * Note: the output HART mask will be set to zero on failure as well.
 | 
			
		||||
 */
 | 
			
		||||
int sbi_hsm_hart_interruptible_mask(const struct sbi_domain *dom,
 | 
			
		||||
				    ulong hbase, ulong *out_hmask)
 | 
			
		||||
				    struct sbi_hartmask *mask)
 | 
			
		||||
{
 | 
			
		||||
	int hstate;
 | 
			
		||||
	ulong i, hmask, dmask;
 | 
			
		||||
	u32 hartindex;
 | 
			
		||||
	int hstate, ret;
 | 
			
		||||
	u32 i;
 | 
			
		||||
 | 
			
		||||
	*out_hmask = 0;
 | 
			
		||||
	if (!sbi_hartid_valid(hbase))
 | 
			
		||||
		return SBI_EINVAL;
 | 
			
		||||
	ret = sbi_domain_get_assigned_hartmask(dom, mask);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ret;
 | 
			
		||||
 | 
			
		||||
	dmask = sbi_domain_get_assigned_hartmask(dom, hbase);
 | 
			
		||||
	for (i = 0; i < BITS_PER_LONG; i++) {
 | 
			
		||||
		hmask = 1UL << i;
 | 
			
		||||
		if (!(dmask & hmask))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		hartindex = sbi_hartid_to_hartindex(hbase + i);
 | 
			
		||||
		hstate = __sbi_hsm_hart_get_state(hartindex);
 | 
			
		||||
		if (hstate == SBI_HSM_STATE_STARTED ||
 | 
			
		||||
		    hstate == SBI_HSM_STATE_SUSPENDED ||
 | 
			
		||||
		    hstate == SBI_HSM_STATE_RESUME_PENDING)
 | 
			
		||||
			*out_hmask |= hmask;
 | 
			
		||||
	sbi_hartmask_for_each_hartindex(i, mask) {
 | 
			
		||||
		hstate = __sbi_hsm_hart_get_state(i);
 | 
			
		||||
		if (hstate != SBI_HSM_STATE_STARTED &&
 | 
			
		||||
		    hstate != SBI_HSM_STATE_SUSPENDED &&
 | 
			
		||||
		    hstate != SBI_HSM_STATE_RESUME_PENDING)
 | 
			
		||||
			sbi_hartmask_clear_hartindex(i, mask);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -111,31 +111,25 @@ int sbi_ipi_send_many(ulong hmask, ulong hbase, u32 event, void *data)
 | 
			
		||||
{
 | 
			
		||||
	int rc = 0;
 | 
			
		||||
	bool retry_needed;
 | 
			
		||||
	ulong i, m;
 | 
			
		||||
	struct sbi_hartmask target_mask = {0};
 | 
			
		||||
	ulong i;
 | 
			
		||||
	struct sbi_hartmask target_mask;
 | 
			
		||||
	struct sbi_domain *dom = sbi_domain_thishart_ptr();
 | 
			
		||||
	struct sbi_scratch *scratch = sbi_scratch_thishart_ptr();
 | 
			
		||||
 | 
			
		||||
	/* Find the target harts */
 | 
			
		||||
	if (hbase != -1UL) {
 | 
			
		||||
		rc = sbi_hsm_hart_interruptible_mask(dom, hbase, &m);
 | 
			
		||||
		if (rc)
 | 
			
		||||
			return rc;
 | 
			
		||||
		m &= hmask;
 | 
			
		||||
	rc = sbi_hsm_hart_interruptible_mask(dom, &target_mask);
 | 
			
		||||
	if (rc)
 | 
			
		||||
		return rc;
 | 
			
		||||
 | 
			
		||||
		for (i = hbase; m; i++, m >>= 1) {
 | 
			
		||||
			if (m & 1UL)
 | 
			
		||||
				sbi_hartmask_set_hartid(i, &target_mask);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		hbase = 0;
 | 
			
		||||
		while (!sbi_hsm_hart_interruptible_mask(dom, hbase, &m)) {
 | 
			
		||||
			for (i = hbase; m; i++, m >>= 1) {
 | 
			
		||||
				if (m & 1UL)
 | 
			
		||||
					sbi_hartmask_set_hartid(i, &target_mask);
 | 
			
		||||
			}
 | 
			
		||||
			hbase += BITS_PER_LONG;
 | 
			
		||||
	if (hbase != -1UL) {
 | 
			
		||||
		struct sbi_hartmask tmp_mask = { 0 };
 | 
			
		||||
 | 
			
		||||
		for (i = hbase; hmask; i++, hmask >>= 1) {
 | 
			
		||||
			if (hmask & 1UL)
 | 
			
		||||
				sbi_hartmask_set_hartid(i, &tmp_mask);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		sbi_hartmask_and(&target_mask, &target_mask, &tmp_mask);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Send IPIs */
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user