Changeset View
Changeset View
Standalone View
Standalone View
sys/dev/iommu/iommu_gas.c
Show All 25 Lines | |||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#define RB_AUGMENT(entry) iommu_gas_augment_entry(entry) | #define RB_AUGMENT_CHECK(entry) iommu_gas_augment_entry(entry) | ||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/systm.h> | #include <sys/systm.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/bus.h> | #include <sys/bus.h> | ||||
#include <sys/interrupt.h> | #include <sys/interrupt.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/ktr.h> | #include <sys/ktr.h> | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | iommu_gas_cmp_entries(struct iommu_map_entry *a, struct iommu_map_entry *b) | ||||
if (a->end < b->end) | if (a->end < b->end) | ||||
return (-1); | return (-1); | ||||
else if (b->end < a->end) | else if (b->end < a->end) | ||||
return (1); | return (1); | ||||
return (0); | return (0); | ||||
} | } | ||||
static void | static bool | ||||
iommu_gas_augment_entry(struct iommu_map_entry *entry) | iommu_gas_augment_entry(struct iommu_map_entry *entry) | ||||
{ | { | ||||
struct iommu_map_entry *child; | struct iommu_map_entry *left, *right; | ||||
iommu_gaddr_t free_down; | iommu_gaddr_t free_down; | ||||
bool changed; | |||||
free_down = 0; | left = RB_LEFT(entry, rb_entry); | ||||
if ((child = RB_LEFT(entry, rb_entry)) != NULL) { | right = RB_RIGHT(entry, rb_entry); | ||||
free_down = MAX(free_down, child->free_down); | if (left == NULL && right == NULL) { | ||||
free_down = MAX(free_down, entry->start - child->last); | |||||
entry->first = child->first; | |||||
} else | |||||
entry->first = entry->start; | entry->first = entry->start; | ||||
if ((child = RB_RIGHT(entry, rb_entry)) != NULL) { | |||||
free_down = MAX(free_down, child->free_down); | |||||
free_down = MAX(free_down, child->first - entry->end); | |||||
entry->last = child->last; | |||||
} else | |||||
entry->last = entry->end; | entry->last = entry->end; | ||||
entry->free_down = 0; | |||||
return (true); | |||||
} | |||||
if (left == NULL) { | |||||
entry->first = entry->start; | |||||
entry->last = right->last; | |||||
entry->free_down = right->first - entry->end; | |||||
return (true); | |||||
} | |||||
if (right == NULL) { | |||||
entry->first = left->start; | |||||
entry->last = entry->end; | |||||
entry->free_down = entry->start - left->last; | |||||
return (true); | |||||
} | |||||
free_down = MAX( | |||||
MAX(left->free_down, entry->start - left->last), | |||||
MAX(right->free_down, right->first - entry->end)); | |||||
changed = free_down != entry->free_down || | |||||
left->first != entry->first || | |||||
right->last != entry->last; | |||||
entry->free_down = free_down; | entry->free_down = free_down; | ||||
entry->first = left->first; | |||||
entry->last = right->last; | |||||
return (changed); | |||||
} | } | ||||
RB_GENERATE(iommu_gas_entries_tree, iommu_map_entry, rb_entry, | RB_GENERATE(iommu_gas_entries_tree, iommu_map_entry, rb_entry, | ||||
iommu_gas_cmp_entries); | iommu_gas_cmp_entries); | ||||
#ifdef INVARIANTS | #ifdef INVARIANTS | ||||
static void | static void | ||||
iommu_gas_check_free(struct iommu_domain *domain) | iommu_gas_check_free(struct iommu_domain *domain) | ||||
▲ Show 20 Lines • Show All 726 Lines • Show Last 20 Lines |