return req_type;
}
+static int chk_conflict(struct memtype *new, struct memtype *entry,
+ unsigned long *type)
+{
+ if (new->type != entry->type) {
+ if (type) {
+ new->type = entry->type;
+ *type = entry->type;
+ } else
+ goto conflict;
+ }
+
+ /* check overlaps with more than one entry in the list */
+ list_for_each_entry_continue(entry, &memtype_list, nd) {
+ if (new->end <= entry->start)
+ break;
+ else if (new->type != entry->type)
+ goto conflict;
+ }
+ return 0;
+
+ conflict:
+ printk(KERN_INFO "%s:%d conflicting memory types "
+ "%Lx-%Lx %s<->%s\n", current->comm, current->pid, new->start,
+ new->end, cattr_name(new->type), cattr_name(entry->type));
+ return -EBUSY;
+}
+
/*
* req_type typically has one of the:
* - _PAGE_CACHE_WB
{
struct memtype *new, *entry;
unsigned long actual_type;
+ struct list_head *where;
int err = 0;
BUG_ON(start >= end); /* end is exclusive */
spin_lock(&memtype_lock);
/* Search for existing mapping that overlaps the current range */
+ where = NULL;
list_for_each_entry(entry, &memtype_list, nd) {
- struct memtype *saved_ptr;
-
- if (entry->start >= end) {
- dprintk("New Entry\n");
- list_add(&new->nd, entry->nd.prev);
- new = NULL;
+ if (end <= entry->start) {
+ where = entry->nd.prev;
break;
- }
-
- if (start <= entry->start && end >= entry->start) {
- if (actual_type != entry->type && new_type) {
- actual_type = entry->type;
- *new_type = actual_type;
- new->type = actual_type;
- }
-
- if (actual_type != entry->type) {
- printk(
- KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
- current->comm, current->pid,
- start, end,
- cattr_name(actual_type),
- cattr_name(entry->type));
- err = -EBUSY;
- break;
- }
-
- saved_ptr = entry;
- /*
- * Check to see whether the request overlaps more
- * than one entry in the list
- */
- list_for_each_entry_continue(entry, &memtype_list, nd) {
- if (end <= entry->start) {
- break;
- }
-
- if (actual_type != entry->type) {
- printk(
- KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
- current->comm, current->pid,
- start, end,
- cattr_name(actual_type),
- cattr_name(entry->type));
- err = -EBUSY;
- break;
- }
- }
-
- if (err) {
- break;
+ } else if (start <= entry->start) { /* end > entry->start */
+ err = chk_conflict(new, entry, new_type);
+ if (!err) {
+ dprintk("Overlap at 0x%Lx-0x%Lx\n",
+ entry->start, entry->end);
+ where = entry->nd.prev;
}
-
- dprintk("Overlap at 0x%Lx-0x%Lx\n",
- saved_ptr->start, saved_ptr->end);
- /* No conflict. Go ahead and add this new entry */
- list_add(&new->nd, saved_ptr->nd.prev);
- new = NULL;
break;
- }
-
- if (start < entry->end) {
- if (actual_type != entry->type && new_type) {
- actual_type = entry->type;
- *new_type = actual_type;
- new->type = actual_type;
- }
-
- if (actual_type != entry->type) {
- printk(
- KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
- current->comm, current->pid,
- start, end,
- cattr_name(actual_type),
- cattr_name(entry->type));
- err = -EBUSY;
- break;
- }
-
- saved_ptr = entry;
- /*
- * Check to see whether the request overlaps more
- * than one entry in the list
- */
- list_for_each_entry_continue(entry, &memtype_list, nd) {
- if (end <= entry->start) {
- break;
- }
-
- if (actual_type != entry->type) {
- printk(
- KERN_INFO "%s:%d conflicting memory types %Lx-%Lx %s<->%s\n",
- current->comm, current->pid,
- start, end,
- cattr_name(actual_type),
- cattr_name(entry->type));
- err = -EBUSY;
- break;
- }
- }
-
- if (err) {
- break;
+ } else if (start < entry->end) { /* start > entry->start */
+ err = chk_conflict(new, entry, new_type);
+ if (!err) {
+ dprintk("Overlap at 0x%Lx-0x%Lx\n",
+ entry->start, entry->end);
+ where = &entry->nd;
}
-
- dprintk("Overlap at 0x%Lx-0x%Lx\n",
- saved_ptr->start, saved_ptr->end);
- /* No conflict. Go ahead and add this new entry */
- list_add(&new->nd, &saved_ptr->nd);
- new = NULL;
break;
}
}
if (err) {
- printk(KERN_INFO
- "reserve_memtype failed 0x%Lx-0x%Lx, track %s, req %s\n",
- start, end, cattr_name(new->type),
- cattr_name(req_type));
+ printk(KERN_INFO "reserve_memtype failed 0x%Lx-0x%Lx, "
+ "track %s, req %s\n",
+ start, end, cattr_name(new->type), cattr_name(req_type));
kfree(new);
spin_unlock(&memtype_lock);
return err;
}
- if (new) {
- /* No conflict. Not yet added to the list. Add to the tail */
+ if (where)
+ list_add(&new->nd, where);
+ else
list_add_tail(&new->nd, &memtype_list);
- dprintk("New Entry\n");
- }
-
- if (new_type) {
- dprintk(
- "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
- start, end, cattr_name(actual_type),
- cattr_name(req_type), cattr_name(*new_type));
- } else {
- dprintk(
- "reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s\n",
- start, end, cattr_name(actual_type),
- cattr_name(req_type));
- }
spin_unlock(&memtype_lock);
+
+ dprintk("reserve_memtype added 0x%Lx-0x%Lx, track %s, req %s, ret %s\n",
+ start, end, cattr_name(new->type), cattr_name(req_type),
+ new_type ? cattr_name(*new_type) : "-");
+
return err;
}
if (retval < 0)
return 0;
- if (pfn <= max_pfn_mapped &&
+ if (((pfn < max_low_pfn_mapped) ||
+ (pfn >= (1UL<<(32 - PAGE_SHIFT)) && pfn < max_pfn_mapped)) &&
ioremap_change_attr((unsigned long)__va(offset), size, flags) < 0) {
free_memtype(offset, offset + size);
printk(KERN_INFO