Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linu…
Browse files Browse the repository at this point in the history
…x-2.6

* 'for-linus' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
  [S390] Poison init section before freeing it.
  [S390] Use add_active_range() and free_area_init_nodes().
  [S390] Virtual memmap for s390.
  [S390] Update documentation for dynamic subchannel mapping.
  [S390] Use dev->groups for adding/removing the subchannel attribute group.
  [S390] Support for disconnected devices reappearing on another subchannel.
  [S390] subchannel lock conversion.
  [S390] Some preparations for the dynamic subchannel mapping patch.
  [S390] runtime switch for qdio performance statistics
  [S390] New DASD feature for ERP related logging
  [S390] add reset call handler to the ap bus.
  [S390] more workqueue fixes.
  [S390] workqueue fixes.
  [S390] uaccess_pt: add missing down_read() and convert to is_init().
  • Loading branch information
Linus Torvalds committed Dec 8, 2006
2 parents 63f3861 + 028d9b3 commit 88032b3
Show file tree
Hide file tree
Showing 35 changed files with 1,298 additions and 655 deletions.
7 changes: 7 additions & 0 deletions Documentation/s390/driver-model.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,18 @@ devices/
- 0.0.0002/
- 0.1.0000/0.1.1234/
...
- defunct/

In this example, device 0815 is accessed via subchannel 0 in subchannel set 0,
device 4711 via subchannel 1 in subchannel set 0, and subchannel 2 is a non-I/O
subchannel. Device 1234 is accessed via subchannel 0 in subchannel set 1.

The subchannel named 'defunct' does not represent any real subchannel on the
system; it is a pseudo subchannel where disconnnected ccw devices are moved to
if they are displaced by another ccw device becoming operational on their
former subchannel. The ccw devices will be moved again to a proper subchannel
if they become operational again on that subchannel.

You should address a ccw device via its bus id (e.g. 0.0.4711); the device can
be found under bus/ccw/devices/.

Expand Down
14 changes: 6 additions & 8 deletions arch/s390/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,14 @@ config WARN_STACK_SIZE
This allows you to specify the maximum frame size a function may
have without the compiler complaining about it.

config ARCH_POPULATES_NODE_MAP
def_bool y

source "mm/Kconfig"

config HOLES_IN_ZONE
def_bool y

comment "I/O subsystem configuration"

config MACHCHK_WARNING
Expand All @@ -266,14 +272,6 @@ config QDIO

If unsure, say Y.

config QDIO_PERF_STATS
bool "Performance statistics in /proc"
depends on QDIO
help
Say Y here to get performance statistics in /proc/qdio_perf

If unsure, say N.

config QDIO_DEBUG
bool "Extended debugging information"
depends on QDIO
Expand Down
1 change: 0 additions & 1 deletion arch/s390/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,6 @@ CONFIG_RESOURCES_64BIT=y
#
CONFIG_MACHCHK_WARNING=y
CONFIG_QDIO=y
# CONFIG_QDIO_PERF_STATS is not set
# CONFIG_QDIO_DEBUG is not set

#
Expand Down
55 changes: 13 additions & 42 deletions arch/s390/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,8 @@ unsigned int console_devno = -1;
unsigned int console_irq = -1;
unsigned long machine_flags = 0;

struct mem_chunk memory_chunk[MEMORY_CHUNKS];
struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
unsigned long __initdata zholes_size[MAX_NR_ZONES];
static unsigned long __initdata memory_end;

/*
Expand Down Expand Up @@ -354,21 +353,6 @@ void machine_power_off(void)
*/
void (*pm_power_off)(void) = machine_power_off;

static void __init
add_memory_hole(unsigned long start, unsigned long end)
{
unsigned long dma_pfn = MAX_DMA_ADDRESS >> PAGE_SHIFT;

if (end <= dma_pfn)
zholes_size[ZONE_DMA] += end - start + 1;
else if (start > dma_pfn)
zholes_size[ZONE_NORMAL] += end - start + 1;
else {
zholes_size[ZONE_DMA] += dma_pfn - start + 1;
zholes_size[ZONE_NORMAL] += end - dma_pfn;
}
}

static int __init early_parse_mem(char *p)
{
memory_end = memparse(p, &p);
Expand Down Expand Up @@ -521,7 +505,6 @@ setup_memory(void)
{
unsigned long bootmap_size;
unsigned long start_pfn, end_pfn, init_pfn;
unsigned long last_rw_end;
int i;

/*
Expand Down Expand Up @@ -577,39 +560,27 @@ setup_memory(void)
/*
* Register RAM areas with the bootmem allocator.
*/
last_rw_end = start_pfn;

for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
unsigned long start_chunk, end_chunk;
unsigned long start_chunk, end_chunk, pfn;

if (memory_chunk[i].type != CHUNK_READ_WRITE)
continue;
start_chunk = (memory_chunk[i].addr + PAGE_SIZE - 1);
start_chunk >>= PAGE_SHIFT;
end_chunk = (memory_chunk[i].addr + memory_chunk[i].size);
end_chunk >>= PAGE_SHIFT;
if (start_chunk < start_pfn)
start_chunk = start_pfn;
if (end_chunk > end_pfn)
end_chunk = end_pfn;
if (start_chunk < end_chunk) {
/* Initialize storage key for RAM pages */
for (init_pfn = start_chunk ; init_pfn < end_chunk;
init_pfn++)
page_set_storage_key(init_pfn << PAGE_SHIFT,
PAGE_DEFAULT_KEY);
free_bootmem(start_chunk << PAGE_SHIFT,
(end_chunk - start_chunk) << PAGE_SHIFT);
if (last_rw_end < start_chunk)
add_memory_hole(last_rw_end, start_chunk - 1);
last_rw_end = end_chunk;
}
start_chunk = PFN_DOWN(memory_chunk[i].addr);
end_chunk = start_chunk + PFN_DOWN(memory_chunk[i].size) - 1;
end_chunk = min(end_chunk, end_pfn);
if (start_chunk >= end_chunk)
continue;
add_active_range(0, start_chunk, end_chunk);
pfn = max(start_chunk, start_pfn);
for (; pfn <= end_chunk; pfn++)
page_set_storage_key(PFN_PHYS(pfn), PAGE_DEFAULT_KEY);
}

psw_set_key(PAGE_DEFAULT_KEY);

if (last_rw_end < end_pfn - 1)
add_memory_hole(last_rw_end, end_pfn - 1);
free_bootmem_with_active_regions(0, max_pfn);
reserve_bootmem(0, PFN_PHYS(start_pfn));

/*
* Reserve the bootmem bitmap itself as well. We do this in two
Expand Down
5 changes: 3 additions & 2 deletions arch/s390/lib/uaccess_pt.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
*/

#include <linux/errno.h>
#include <asm/uaccess.h>
#include <linux/mm.h>
#include <asm/uaccess.h>
#include <asm/futex.h>

static inline int __handle_fault(struct mm_struct *mm, unsigned long address,
Expand Down Expand Up @@ -60,8 +60,9 @@ static inline int __handle_fault(struct mm_struct *mm, unsigned long address,

out_of_memory:
up_read(&mm->mmap_sem);
if (current->pid == 1) {
if (is_init(current)) {
yield();
down_read(&mm->mmap_sem);
goto survive;
}
printk("VM: killing process %s\n", current->comm);
Expand Down
2 changes: 1 addition & 1 deletion arch/s390/mm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
# Makefile for the linux s390-specific parts of the memory manager.
#

obj-y := init.o fault.o ioremap.o extmem.o mmap.o
obj-y := init.o fault.o ioremap.o extmem.o mmap.o vmem.o
obj-$(CONFIG_CMM) += cmm.o

106 changes: 26 additions & 80 deletions arch/s390/mm/extmem.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/bootmem.h>
#include <linux/ctype.h>
#include <asm/page.h>
#include <asm/pgtable.h>
#include <asm/ebcdic.h>
#include <asm/errno.h>
#include <asm/extmem.h>
Expand Down Expand Up @@ -237,65 +238,6 @@ query_segment_type (struct dcss_segment *seg)
return rc;
}

/*
* check if the given segment collides with guest storage.
* returns 1 if this is the case, 0 if no collision was found
*/
static int
segment_overlaps_storage(struct dcss_segment *seg)
{
int i;

for (i = 0; i < MEMORY_CHUNKS && memory_chunk[i].size > 0; i++) {
if (memory_chunk[i].type != CHUNK_READ_WRITE)
continue;
if ((memory_chunk[i].addr >> 20) > (seg->end >> 20))
continue;
if (((memory_chunk[i].addr + memory_chunk[i].size - 1) >> 20)
< (seg->start_addr >> 20))
continue;
return 1;
}
return 0;
}

/*
* check if segment collides with other segments that are currently loaded
* returns 1 if this is the case, 0 if no collision was found
*/
static int
segment_overlaps_others (struct dcss_segment *seg)
{
struct list_head *l;
struct dcss_segment *tmp;

BUG_ON(!mutex_is_locked(&dcss_lock));
list_for_each(l, &dcss_list) {
tmp = list_entry(l, struct dcss_segment, list);
if ((tmp->start_addr >> 20) > (seg->end >> 20))
continue;
if ((tmp->end >> 20) < (seg->start_addr >> 20))
continue;
if (seg == tmp)
continue;
return 1;
}
return 0;
}

/*
* check if segment exceeds the kernel mapping range (detected or set via mem=)
* returns 1 if this is the case, 0 if segment fits into the range
*/
static inline int
segment_exceeds_range (struct dcss_segment *seg)
{
int seg_last_pfn = (seg->end) >> PAGE_SHIFT;
if (seg_last_pfn > max_pfn)
return 1;
return 0;
}

/*
* get info about a segment
* possible return values:
Expand Down Expand Up @@ -341,24 +283,26 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
rc = query_segment_type (seg);
if (rc < 0)
goto out_free;
if (segment_exceeds_range(seg)) {
PRINT_WARN ("segment_load: not loading segment %s - exceeds"
" kernel mapping range\n",name);
rc = -ERANGE;

rc = add_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);

switch (rc) {
case 0:
break;
case -ENOSPC:
PRINT_WARN("segment_load: not loading segment %s - overlaps "
"storage/segment\n", name);
goto out_free;
}
if (segment_overlaps_storage(seg)) {
PRINT_WARN ("segment_load: not loading segment %s - overlaps"
" storage\n",name);
rc = -ENOSPC;
case -ERANGE:
PRINT_WARN("segment_load: not loading segment %s - exceeds "
"kernel mapping range\n", name);
goto out_free;
}
if (segment_overlaps_others(seg)) {
PRINT_WARN ("segment_load: not loading segment %s - overlaps"
" other segments\n",name);
rc = -EBUSY;
default:
PRINT_WARN("segment_load: not loading segment %s (rc: %d)\n",
name, rc);
goto out_free;
}

if (do_nonshared)
dcss_command = DCSS_LOADNSR;
else
Expand All @@ -372,7 +316,7 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
rc = dcss_diag_translate_rc (seg->end);
dcss_diag(DCSS_PURGESEG, seg->dcss_name,
&seg->start_addr, &seg->end);
goto out_free;
goto out_shared;
}
seg->do_nonshared = do_nonshared;
atomic_set(&seg->ref_count, 1);
Expand All @@ -391,6 +335,8 @@ __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long
(void*)seg->start_addr, (void*)seg->end,
segtype_string[seg->vm_segtype]);
goto out;
out_shared:
remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
out_free:
kfree(seg);
out:
Expand Down Expand Up @@ -530,12 +476,12 @@ segment_unload(char *name)
"please report to linux390@de.ibm.com\n",name);
goto out_unlock;
}
if (atomic_dec_return(&seg->ref_count) == 0) {
list_del(&seg->list);
dcss_diag(DCSS_PURGESEG, seg->dcss_name,
&dummy, &dummy);
kfree(seg);
}
if (atomic_dec_return(&seg->ref_count) != 0)
goto out_unlock;
remove_shared_memory(seg->start_addr, seg->end - seg->start_addr + 1);
list_del(&seg->list);
dcss_diag(DCSS_PURGESEG, seg->dcss_name, &dummy, &dummy);
kfree(seg);
out_unlock:
mutex_unlock(&dcss_lock);
}
Expand Down
Loading

0 comments on commit 88032b3

Please sign in to comment.