2002-08-05 16:12:45

by Arnd Bergmann

[permalink] [raw]
Subject: 0/18 2.4.19 architecture updates for s390 following

Last friday, we had a new code drop on developerworks with
s390 patches against 2.4.17. The patches following this mail
contain that code, updated to 2.4.19. They were prepared by Martin
Schwidefsky, but he's on holidays now, so I'm sending them instead.

The first eleven patches contains large updates for s390 architecture
dependent files that are maintained here, so I'm not sending
them to lkml. The rest are smaller bits, some of which are more
controversial.

Arnd <><


2002-08-05 16:10:28

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH] 16/18 add more possible root devices

This patch adds some more s/390 specific devices to the list of root devices.

diff -urN linux-2.4.19-rc3/init/do_mounts.c linux-2.4.19-s390/init/do_mounts.c
--- linux-2.4.19-rc3/init/do_mounts.c Tue Jul 30 09:02:32 2002
+++ linux-2.4.19-s390/init/do_mounts.c Tue Jul 30 09:02:57 2002
@@ -162,6 +162,58 @@
{ "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
{ "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
{ "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
+ { "dasdi", (DASD_MAJOR << MINORBITS) + (8 << 2) },
+ { "dasdj", (DASD_MAJOR << MINORBITS) + (9 << 2) },
+ { "dasdk", (DASD_MAJOR << MINORBITS) + (10 << 2) },
+ { "dasdl", (DASD_MAJOR << MINORBITS) + (11 << 2) },
+ { "dasdm", (DASD_MAJOR << MINORBITS) + (12 << 2) },
+ { "dasdn", (DASD_MAJOR << MINORBITS) + (13 << 2) },
+ { "dasdo", (DASD_MAJOR << MINORBITS) + (14 << 2) },
+ { "dasdp", (DASD_MAJOR << MINORBITS) + (15 << 2) },
+ { "dasdq", (DASD_MAJOR << MINORBITS) + (16 << 2) },
+ { "dasdr", (DASD_MAJOR << MINORBITS) + (17 << 2) },
+ { "dasds", (DASD_MAJOR << MINORBITS) + (18 << 2) },
+ { "dasdt", (DASD_MAJOR << MINORBITS) + (19 << 2) },
+ { "dasdu", (DASD_MAJOR << MINORBITS) + (20 << 2) },
+ { "dasdv", (DASD_MAJOR << MINORBITS) + (21 << 2) },
+ { "dasdw", (DASD_MAJOR << MINORBITS) + (22 << 2) },
+ { "dasdx", (DASD_MAJOR << MINORBITS) + (23 << 2) },
+ { "dasdy", (DASD_MAJOR << MINORBITS) + (24 << 2) },
+ { "dasdz", (DASD_MAJOR << MINORBITS) + (25 << 2) },
+#endif
+#ifdef CONFIG_BLK_DEV_XPRAM
+ { "xpram0", (XPRAM_MAJOR << MINORBITS) },
+ { "xpram1", (XPRAM_MAJOR << MINORBITS) + 1 },
+ { "xpram2", (XPRAM_MAJOR << MINORBITS) + 2 },
+ { "xpram3", (XPRAM_MAJOR << MINORBITS) + 3 },
+ { "xpram4", (XPRAM_MAJOR << MINORBITS) + 4 },
+ { "xpram5", (XPRAM_MAJOR << MINORBITS) + 5 },
+ { "xpram6", (XPRAM_MAJOR << MINORBITS) + 6 },
+ { "xpram7", (XPRAM_MAJOR << MINORBITS) + 7 },
+ { "xpram8", (XPRAM_MAJOR << MINORBITS) + 8 },
+ { "xpram9", (XPRAM_MAJOR << MINORBITS) + 9 },
+ { "xpram10", (XPRAM_MAJOR << MINORBITS) + 10 },
+ { "xpram11", (XPRAM_MAJOR << MINORBITS) + 11 },
+ { "xpram12", (XPRAM_MAJOR << MINORBITS) + 12 },
+ { "xpram13", (XPRAM_MAJOR << MINORBITS) + 13 },
+ { "xpram14", (XPRAM_MAJOR << MINORBITS) + 14 },
+ { "xpram15", (XPRAM_MAJOR << MINORBITS) + 15 },
+ { "xpram16", (XPRAM_MAJOR << MINORBITS) + 16 },
+ { "xpram17", (XPRAM_MAJOR << MINORBITS) + 17 },
+ { "xpram18", (XPRAM_MAJOR << MINORBITS) + 18 },
+ { "xpram19", (XPRAM_MAJOR << MINORBITS) + 19 },
+ { "xpram20", (XPRAM_MAJOR << MINORBITS) + 20 },
+ { "xpram21", (XPRAM_MAJOR << MINORBITS) + 21 },
+ { "xpram22", (XPRAM_MAJOR << MINORBITS) + 22 },
+ { "xpram23", (XPRAM_MAJOR << MINORBITS) + 23 },
+ { "xpram24", (XPRAM_MAJOR << MINORBITS) + 24 },
+ { "xpram25", (XPRAM_MAJOR << MINORBITS) + 25 },
+ { "xpram26", (XPRAM_MAJOR << MINORBITS) + 26 },
+ { "xpram27", (XPRAM_MAJOR << MINORBITS) + 27 },
+ { "xpram28", (XPRAM_MAJOR << MINORBITS) + 28 },
+ { "xpram29", (XPRAM_MAJOR << MINORBITS) + 29 },
+ { "xpram30", (XPRAM_MAJOR << MINORBITS) + 30 },
+ { "xpram31", (XPRAM_MAJOR << MINORBITS) + 31 },
#endif
#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
{ "ida/c0d0p",0x4800 },


2002-08-05 16:12:43

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH] 14/18 support for partition labels in devfs

This patch adds a new feature to the partition code. It will automatically
generate links in the device filesystem from the label name of a dasd to
the device node. This is only needed if the device filesystem is used.

diff -urN linux-2.4.19-rc3/fs/partitions/check.c linux-2.4.19-s390/fs/partitions/check.c
--- linux-2.4.19-rc3/fs/partitions/check.c Wed Jul 24 17:14:40 2002
+++ linux-2.4.19-s390/fs/partitions/check.c Wed Jul 24 17:12:17 2002
@@ -85,7 +85,7 @@
#ifdef CONFIG_ARCH_S390
int (*genhd_dasd_name)(char*,int,int,struct gendisk*) = NULL;
int (*genhd_dasd_ioctl)(struct inode *inp, struct file *filp,
- unsigned int no, unsigned long data);
+ unsigned int no, unsigned long data);
EXPORT_SYMBOL(genhd_dasd_name);
EXPORT_SYMBOL(genhd_dasd_ioctl);
#endif
@@ -277,6 +277,7 @@
int devnum = minor >> dev->minor_shift;
devfs_handle_t dir;
unsigned int devfs_flags = DEVFS_FL_DEFAULT;
+ umode_t devfs_perm = S_IFBLK | S_IRUSR | S_IWUSR;
char devname[16];

if (dev->part[minor + part].de) return;
@@ -284,11 +285,14 @@
if (!dir) return;
if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
devfs_flags |= DEVFS_FL_REMOVABLE;
+ if (is_read_only(MKDEV(dev->major, minor+part))) {
+ devfs_perm &= ~(S_IWUSR);
+ }
sprintf (devname, "part%d", part);
dev->part[minor + part].de =
devfs_register (dir, devname, devfs_flags,
dev->major, minor + part,
- S_IFBLK | S_IRUSR | S_IWUSR,
+ devfs_perm,
dev->fops, NULL);
}

@@ -300,12 +304,16 @@
int devnum = minor >> dev->minor_shift;
devfs_handle_t dir, slave;
unsigned int devfs_flags = DEVFS_FL_DEFAULT;
+ umode_t devfs_perm = S_IFBLK | S_IRUSR | S_IWUSR;
char dirname[64], symlink[16];
static devfs_handle_t devfs_handle;

if (dev->part[minor].de) return;
if ( dev->flags && (dev->flags[devnum] & GENHD_FL_REMOVABLE) )
devfs_flags |= DEVFS_FL_REMOVABLE;
+ if (is_read_only(MKDEV(dev->major, minor))) {
+ devfs_perm &= ~(S_IWUSR);
+ }
if (dev->de_arr) {
dir = dev->de_arr[devnum];
if (!dir) /* Aware driver wants to block disc management */
@@ -327,7 +335,7 @@
dirname + pos, &slave, NULL);
dev->part[minor].de =
devfs_register (dir, "disc", devfs_flags, dev->major, minor,
- S_IFBLK | S_IRUSR | S_IWUSR, dev->fops, NULL);
+ devfs_perm, dev->fops, NULL);
devfs_auto_unregister (dev->part[minor].de, slave);
if (!dev->de_arr)
devfs_auto_unregister (slave, dir);
@@ -355,6 +363,10 @@
dev->part[minor].de = NULL;
devfs_dealloc_unique_number (&disc_numspace,
dev->part[minor].number);
+ if(dev->label_arr && dev->label_arr[minor >> dev->minor_shift]) {
+ devfs_unregister(dev->label_arr[minor >> dev->minor_shift]);
+ dev->label_arr[minor >> dev->minor_shift] = NULL;
+ }
}
#endif /* CONFIG_DEVFS_FS */
}
@@ -409,6 +421,93 @@
for (i = first_minor; i < end_minor; i++)
dev->sizes[i] = dev->part[i].nr_sects >> (BLOCK_SIZE_BITS - 9);
}
+}
+
+/*
+ * This function creates a link from /dev/labels/<labelname> to the devfs
+ * device directory. The device driver must allocate memory to the label_arr
+ * for this to work.
+ * This enables devices/partition tables that support labels to be accessed
+ * by that name instead of the device name (which can change if devices are
+ * moved around).
+ *
+ * Current restictions:
+ * - Only the first device that uses a certain label creates the link
+ * (which can also be good in case there is a backup device)
+ * - When removing devices that created labels previously suppressed
+ * devices won't show up.
+ */
+void register_disk_label(struct gendisk *hd, int minor, char *label) {
+#ifdef CONFIG_DEVFS_FS
+ int disknum = minor >> hd->minor_shift;
+ static devfs_handle_t devfs_label_dir = NULL;
+ int i;
+
+ /*
+ * Check the given label. Trailing whitespaces are removed. Otherwise
+ * only alphanumeric characters are allowed. (fstab)
+ * Added [$#%@] since these are allowed by fdasd and seem
+ * to work in fstab.
+ */
+ for(i=0; label[i] != '\0'; i++);
+ for(i--; i >= 0; i--) {
+ if(label[i] == ' ' && label[i+1] == '\0') {
+ label[i] = '\0';
+ continue;
+ }
+ if(
+ label[i] == '$' || label[i] == '#' ||
+ label[i] == '@' || label[i] == '%'
+ )
+ continue;
+ if(label[i] >= 'a' && label[i] <= 'z')
+ continue;
+ if(label[i] >= 'A' && label[i] <= 'Z')
+ continue;
+ if(label[i] >= '0' && label[i] <= '9')
+ continue;
+
+ printk(KERN_WARNING "\nregister_disk_label: invalid character(s)"
+ " in label <%s>\n", label);
+ printk(KERN_WARNING "register_label: refusing to create devfs entry.\n");
+ return;
+ }
+
+ if(!hd->label_arr)
+ return;
+
+ if(!devfs_label_dir)
+ if(!(devfs_label_dir = devfs_mk_dir(NULL, "labels", NULL)))
+ return;
+
+ if(hd->label_arr[disknum]) {
+ if(strcmp(devfs_get_name(hd->label_arr[disknum], NULL), label) == 0)
+ return;
+
+ devfs_unregister(hd->label_arr[disknum]);
+ hd->label_arr[disknum] = NULL;
+ }
+ if(!devfs_find_handle(devfs_label_dir, label, 0, 0, 0, 0)) {
+ int pos = 0;
+ char path[64];
+
+ if(hd->de_arr) {
+ if(!hd->de_arr[disknum])
+ return;
+
+ pos = devfs_generate_path(hd->de_arr[disknum], path+3, sizeof(path)-3);
+ if(pos < 0)
+ return;
+
+ strncpy(path+pos, "../", 3);
+ } else {
+ sprintf(path, "../%s/disc/%d", hd->major_name, disknum);
+ }
+ devfs_mk_symlink(
+ devfs_label_dir, label, DEVFS_FL_DEFAULT, path+pos,
+ &hd->label_arr[disknum], NULL);
+ }
+#endif
}

unsigned char *read_dev_sector(struct block_device *bdev, unsigned long n, Sector *p)
diff -urN linux-2.4.19-rc3/fs/partitions/check.h linux-2.4.19-s390/fs/partitions/check.h
--- linux-2.4.19-rc3/fs/partitions/check.h Tue Oct 2 05:03:26 2001
+++ linux-2.4.19-s390/fs/partitions/check.h Wed Jul 24 17:01:16 2002
@@ -13,4 +13,6 @@
page_cache_release(p.v);
}

+void register_disk_label(struct gendisk *hd, int minor, char *label);
+
extern int warn_no_part;
diff -urN linux-2.4.19-rc3/fs/partitions/ibm.c linux-2.4.19-s390/fs/partitions/ibm.c
--- linux-2.4.19-rc3/fs/partitions/ibm.c Wed Jul 24 17:14:40 2002
+++ linux-2.4.19-s390/fs/partitions/ibm.c Wed Jul 24 17:01:16 2002
@@ -123,6 +123,7 @@
data = read_dev_sector(bdev, info->label_block*(blocksize/512), &sect);
if (data == NULL)
goto out_readerr;
+
strncpy (type, data, 4);
if ((!info->FBA_layout) && (!strcmp(info->type, "ECKD")))
strncpy(name, data + 8, 6);
@@ -134,6 +135,9 @@
EBCASC(type, 4);
EBCASC(name, 6);

+ if(name[0] != '\0')
+ register_disk_label(hd, MINOR(to_kdev_t(bdev->bd_dev)), name);
+
/*
* Three different types: CMS1, VOL1 and LNX1/unlabeled
*/
@@ -214,7 +218,7 @@
// add_gd_partition(hd, first_part_minor - 1, 0, size);
add_gd_partition(hd, first_part_minor,
offset*(blocksize >> 9),
- size-offset*(blocksize >> 9));
+ size-offset*(blocksize >> 9));
}

printk("\n");
diff -urN linux-2.4.19-rc3/include/linux/genhd.h linux-2.4.19-s390/include/linux/genhd.h
--- linux-2.4.19-rc3/include/linux/genhd.h Wed Jul 24 17:14:42 2002
+++ linux-2.4.19-s390/include/linux/genhd.h Wed Jul 24 17:12:30 2002
@@ -100,6 +100,7 @@

devfs_handle_t *de_arr; /* one per physical disc */
char *flags; /* one per physical disc */
+ devfs_handle_t *label_arr; /* one per physical disc */
};

/* drivers/block/genhd.c */


2002-08-05 16:12:45

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH] 18/18 scsi core changes

This patch does not look fit for inclusion to me, but appearantly it's
needed if anyone actually wants to use the new zfcp driver I sent with
patch 10/18...

diff -urN linux-2.4.19-rc3/drivers/scsi/Config.in linux-2.4.19-s390/drivers/scsi/Config.in
--- linux-2.4.19-rc3/drivers/scsi/Config.in Tue Jul 30 09:02:28 2002
+++ linux-2.4.19-s390/drivers/scsi/Config.in Tue Jul 30 09:02:54 2002
@@ -45,6 +45,8 @@
if [ "$CONFIG_PCI" = "y" ]; then
dep_tristate '3ware Hardware ATA-RAID support' CONFIG_BLK_DEV_3W_XXXX_RAID $CONFIG_SCSI
fi
+
+if [ "$CONFIG_ARCH_S390" != "y" ]; then
dep_tristate '7000FASST SCSI support' CONFIG_SCSI_7000FASST $CONFIG_SCSI
dep_tristate 'ACARD SCSI support' CONFIG_SCSI_ACARD $CONFIG_SCSI
dep_tristate 'Adaptec AHA152X/2825 support' CONFIG_SCSI_AHA152X $CONFIG_SCSI
@@ -251,6 +253,12 @@
# bool 'Cyberstorm Mk III SCSI support (EXPERIMENTAL)' CONFIG_CYBERSTORMIII_SCSI
# bool 'GVP Turbo 040/060 SCSI support (EXPERIMENTAL)' CONFIG_GVP_TURBO_SCSI
fi
+fi
+
+fi
+
+if [ "$CONFIG_ARCH_S390" = "y" ]; then
+dep_tristate 'IBM z900 FCP host bus adapter driver' CONFIG_ZFCP $CONFIG_QDIO
fi

endmenu
diff -urN linux-2.4.19-rc3/drivers/scsi/hosts.c linux-2.4.19-s390/drivers/scsi/hosts.c
--- linux-2.4.19-rc3/drivers/scsi/hosts.c Tue Jul 30 09:02:22 2002
+++ linux-2.4.19-s390/drivers/scsi/hosts.c Tue Jul 30 09:02:34 2002
@@ -81,13 +81,31 @@
struct Scsi_Host * scsi_hostlist;
struct Scsi_Device_Template * scsi_devicelist;

-int max_scsi_hosts;
-int next_scsi_host;
+int max_scsi_hosts; /* host_no for next new host */
+int next_scsi_host; /* count of registered scsi hosts */

void
scsi_unregister(struct Scsi_Host * sh){
struct Scsi_Host * shpnt;
Scsi_Host_Name *shn;
+ char name[10];
+
+ /* kill error handling thread */
+ if (sh->hostt->use_new_eh_code
+ && sh->ehandler != NULL) {
+ DECLARE_MUTEX_LOCKED(sem);
+
+ sh->eh_notify = &sem;
+ send_sig(SIGHUP, sh->ehandler, 1);
+ down(&sem);
+ sh->eh_notify = NULL;
+ }
+
+ /* remove proc entry */
+#ifdef CONFIG_PROC_FS
+ sprintf(name, "%d", sh->host_no);
+ remove_proc_entry(name, sh->hostt->proc_dir);
+#endif

if(scsi_hostlist == sh)
scsi_hostlist = sh->next;
@@ -107,6 +125,18 @@
if (shn) shn->host_registered = 0;
/* else {} : This should not happen, we should panic here... */

+#if 1
+ /* We shoult not decrement max_scsi_hosts (and make this value
+ * candidate for re-allocation by a different driver).
+ * Reason: the device is _still_ on the
+ * scsi_host_no_list and it's identified by its name. When the same
+ * device is re-registered it will get the same host_no again while
+ * new devices may use the allocation scheme and get this very same
+ * host_no.
+ * It's OK to have "holes" in the allocation but it does not mean
+ * "leaks".
+ */
+#else // if 0
/* If we are removing the last host registered, it is safe to reuse
* its host number (this avoids "holes" at boot time) (DB)
* It is also safe to reuse those of numbers directly below which have
@@ -121,7 +151,9 @@
break;
}
}
+#endif
next_scsi_host--;
+
kfree((char *) sh);
}

@@ -135,6 +167,7 @@
Scsi_Host_Name *shn, *shn2;
int flag_new = 1;
const char * hname;
+ char *name;
size_t hname_len;
retval = (struct Scsi_Host *)kmalloc(sizeof(struct Scsi_Host) + j,
(tpnt->unchecked_isa_dma && j ?
@@ -262,6 +295,35 @@
o_shp->next = retval;
}
}
+
+#ifdef CONFIG_PROC_FS
+ build_proc_dir_entry(retval);
+#endif
+
+ /* Start error handling thread */
+ if (retval->hostt->use_new_eh_code) {
+ DECLARE_MUTEX_LOCKED(sem);
+
+ retval->eh_notify = &sem;
+ kernel_thread((int (*)(void *)) scsi_error_handler,
+ (void *) retval, 0);
+
+ /*
+ * Now wait for the kernel error thread to initialize itself
+ * as it might be needed when we scan the bus.
+ */
+ down(&sem);
+ retval->eh_notify = NULL;
+ }
+
+ if (tpnt->info) {
+ name = (char *)tpnt->info(retval);
+ } else {
+ name = (char *)tpnt->name;
+ }
+ printk(KERN_INFO "scsi%d : %s\n", /* And print a little message */
+ retval->host_no, name);
+

return retval;
}
diff -urN linux-2.4.19-rc3/drivers/scsi/hosts.h linux-2.4.19-s390/drivers/scsi/hosts.h
--- linux-2.4.19-rc3/drivers/scsi/hosts.h Tue Jul 30 09:02:22 2002
+++ linux-2.4.19-s390/drivers/scsi/hosts.h Tue Jul 30 09:02:34 2002
@@ -464,7 +464,10 @@

extern Scsi_Host_Template * scsi_hosts;

-extern void build_proc_dir_entries(Scsi_Host_Template *);
+#ifdef CONFIG_PROC_FS
+extern void build_proc_dir(Scsi_Host_Template *);
+extern void build_proc_dir_entry(struct Scsi_Host *);
+#endif

/*
* scsi_init initializes the scsi hosts.
diff -urN linux-2.4.19-rc3/drivers/scsi/scsi.c linux-2.4.19-s390/drivers/scsi/scsi.c
--- linux-2.4.19-rc3/drivers/scsi/scsi.c Tue Jul 30 09:02:28 2002
+++ linux-2.4.19-s390/drivers/scsi/scsi.c Tue Jul 30 09:02:55 2002
@@ -533,22 +533,10 @@
SCpnt->target,
atomic_read(&SCpnt->host->host_active),
SCpnt->host->host_failed));
- if (SCpnt->host->host_failed != 0) {
- SCSI_LOG_ERROR_RECOVERY(5, printk("Error handler thread %d %d\n",
- SCpnt->host->in_recovery,
- SCpnt->host->eh_active));
- }
- /*
- * If the host is having troubles, then look to see if this was the last
- * command that might have failed. If so, wake up the error handler.
- */
- if (SCpnt->host->in_recovery
- && !SCpnt->host->eh_active
- && SCpnt->host->host_busy == SCpnt->host->host_failed) {
- SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread (%d)\n",
- atomic_read(&SCpnt->host->eh_wait->count)));
- up(SCpnt->host->eh_wait);
- }
+
+ /* Note: The eh_thread is now started in scsi_bottom_half_handler for
+ * all cases except command timeout
+ */

spin_unlock_irqrestore(&device_request_lock, flags);

@@ -1296,26 +1284,38 @@
SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;
SCpnt->state = SCSI_STATE_FAILED;
SCpnt->host->in_recovery = 1;
- /*
- * If the host is having troubles, then look to see if this was the last
- * command that might have failed. If so, wake up the error handler.
- */
- if (SCpnt->host->host_busy == SCpnt->host->host_failed) {
- SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread (%d)\n",
- atomic_read(&SCpnt->host->eh_wait->count)));
- up(SCpnt->host->eh_wait);
- }
- } else {
- /*
- * We only get here if the error recovery thread has died.
- */
+ } else {
+ /* eh not present....trying to continue anyway */
scsi_finish_command(SCpnt);
- }
+ }
+ break;
+ } // switch
+ if (SCpnt->host->eh_wait != NULL) {
+ /*
+ * If the host is having troubles, then look to see if this was the last
+ * command that might have failed. If so, wake up the error handler.
+ */
+ if (SCpnt->host->in_recovery &&
+ !SCpnt->host->eh_active &&
+ (SCpnt->host->host_busy == SCpnt->host->host_failed)) {
+ SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread (%d)\n",
+ atomic_read(&SCpnt->host->eh_wait->count)));
+ printk("(in_recovery=%d, host_busy=%d, host_failed=%d) "
+ "Waking error handler thread bh(%d)\n",
+ SCpnt->host->in_recovery,
+ SCpnt->host->host_busy,
+ SCpnt->host->host_failed,
+ atomic_read(&SCpnt->host->eh_wait->count));
+ up(SCpnt->host->eh_wait);
+ }
+ } else {
+ SCSI_LOG_ERROR_RECOVERY(5, printk("Warning: eh_thread not present\n"));
}
+
} /* for(; SCpnt...) */
-
+
} /* while(1==1) */
-
+
}

/*
@@ -1864,7 +1864,6 @@
struct Scsi_Host *shpnt;
Scsi_Device *SDpnt;
struct Scsi_Device_Template *sdtpnt;
- const char *name;
unsigned long flags;
int out_of_space = 0;

@@ -1896,6 +1895,11 @@
} else
tpnt->present = tpnt->detect(tpnt);

+ /* Add the new driver to /proc/scsi (directory only) */
+#ifdef CONFIG_PROC_FS
+ build_proc_dir(tpnt);
+#endif
+
if (tpnt->present) {
if (pcount == next_scsi_host) {
if (tpnt->present > 1) {
@@ -1917,45 +1921,6 @@
tpnt->next = scsi_hosts; /* Add to the linked list */
scsi_hosts = tpnt;

- /* Add the new driver to /proc/scsi */
-#ifdef CONFIG_PROC_FS
- build_proc_dir_entries(tpnt);
-#endif
-
-
- /*
- * Add the kernel threads for each host adapter that will
- * handle error correction.
- */
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt == tpnt && shpnt->hostt->use_new_eh_code) {
- DECLARE_MUTEX_LOCKED(sem);
-
- shpnt->eh_notify = &sem;
- kernel_thread((int (*)(void *)) scsi_error_handler,
- (void *) shpnt, 0);
-
- /*
- * Now wait for the kernel error thread to initialize itself
- * as it might be needed when we scan the bus.
- */
- down(&sem);
- shpnt->eh_notify = NULL;
- }
- }
-
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt == tpnt) {
- if (tpnt->info) {
- name = tpnt->info(shpnt);
- } else {
- name = tpnt->name;
- }
- printk(KERN_INFO "scsi%d : %s\n", /* And print a little message */
- shpnt->host_no, name);
- }
- }
-
/* The next step is to call scan_scsis here. This generates the
* Scsi_Devices entries
*/
@@ -2032,7 +1997,6 @@
struct Scsi_Device_Template *sdtpnt;
struct Scsi_Host *sh1;
struct Scsi_Host *shpnt;
- char name[10]; /* host_no>=10^9? I don't think so. */

/* get the big kernel lock, so we don't race with open() */
lock_kernel();
@@ -2134,18 +2098,6 @@
/*
* Next, kill the kernel error recovery thread for this host.
*/
- for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
- if (shpnt->hostt == tpnt
- && shpnt->hostt->use_new_eh_code
- && shpnt->ehandler != NULL) {
- DECLARE_MUTEX_LOCKED(sem);
-
- shpnt->eh_notify = &sem;
- send_sig(SIGHUP, shpnt->ehandler, 1);
- down(&sem);
- shpnt->eh_notify = NULL;
- }
- }

/* Next we free up the Scsi_Cmnd structures for this host */

@@ -2174,9 +2126,6 @@
if (shpnt->hostt != tpnt)
continue;
pcount = next_scsi_host;
- /* Remove the /proc/scsi directory entry */
- sprintf(name,"%d",shpnt->host_no);
- remove_proc_entry(name, tpnt->proc_dir);
if (tpnt->release)
(*tpnt->release) (shpnt);
else {
diff -urN linux-2.4.19-rc3/drivers/scsi/scsi.h linux-2.4.19-s390/drivers/scsi/scsi.h
--- linux-2.4.19-rc3/drivers/scsi/scsi.h Tue Jul 30 09:02:28 2002
+++ linux-2.4.19-s390/drivers/scsi/scsi.h Tue Jul 30 09:02:55 2002
@@ -390,6 +390,17 @@
#include <asm/pgtable.h>
#define CONTIGUOUS_BUFFERS(X,Y) \
(virt_to_phys((X)->b_data+(X)->b_size-1)+1==virt_to_phys((Y)->b_data))
+#elif defined(CONFIG_ARCH_S390) || defined(CONFIG_ARCH_S390X)
+#define _CONTIGUOUS_BUFFERS(xd, xs, yd, ys) \
+ (((xd + xs) == yd) \
+ && ((xd & PAGE_MASK) == ((yd + ys - 1) & PAGE_MASK)))
+
+#define CONTIGUOUS_BUFFERS(X,Y) \
+ _CONTIGUOUS_BUFFERS( \
+ (unsigned long)(X)->b_data, \
+ (unsigned long)(X)->b_size, \
+ (unsigned long)(Y)->b_data, \
+ (unsigned long)(Y)->b_size)
#else
#define CONTIGUOUS_BUFFERS(X,Y) ((X->b_data+X->b_size) == Y->b_data)
#endif
diff -urN linux-2.4.19-rc3/drivers/scsi/scsi_lib.c linux-2.4.19-s390/drivers/scsi/scsi_lib.c
--- linux-2.4.19-rc3/drivers/scsi/scsi_lib.c Tue Jul 30 09:02:29 2002
+++ linux-2.4.19-s390/drivers/scsi/scsi_lib.c Tue Jul 30 09:02:55 2002
@@ -262,6 +262,15 @@
* the bad sector.
*/
SCpnt->request.special = (void *) SCpnt;
+ /*
+ * We need to recount the number of
+ * scatter-gather segments here - the
+ * normal case code assumes this to be
+ * correct, as it would be a performance
+ * loss to always recount. Handling
+ * errors is always unusual, of course.
+ */
+ recount_segments(SCpnt);
list_add(&SCpnt->request.queue, &q->queue_head);
}

@@ -969,15 +978,6 @@
*/
if( req->special != NULL ) {
SCpnt = (Scsi_Cmnd *) req->special;
- /*
- * We need to recount the number of
- * scatter-gather segments here - the
- * normal case code assumes this to be
- * correct, as it would be a performance
- * lose to always recount. Handling
- * errors is always unusual, of course.
- */
- recount_segments(SCpnt);
} else {
SCpnt = scsi_allocate_device(SDpnt, FALSE, FALSE);
}
diff -urN linux-2.4.19-rc3/drivers/scsi/scsi_proc.c linux-2.4.19-s390/drivers/scsi/scsi_proc.c
--- linux-2.4.19-rc3/drivers/scsi/scsi_proc.c Thu Jun 28 02:10:55 2001
+++ linux-2.4.19-s390/drivers/scsi/scsi_proc.c Tue Jul 30 09:01:23 2002
@@ -120,35 +120,34 @@
return(ret);
}

-void build_proc_dir_entries(Scsi_Host_Template * tpnt)
-{
- struct Scsi_Host *hpnt;
- char name[10]; /* see scsi_unregister_host() */
+void build_proc_dir_entry(struct Scsi_Host *shpnt) {
+ char name[10]; /* host_no>=10^9? I don't think so. */
+ struct proc_dir_entry *p;

- tpnt->proc_dir = proc_mkdir(tpnt->proc_name, proc_scsi);
- if (!tpnt->proc_dir) {
- printk(KERN_ERR "Unable to proc_mkdir in scsi.c/build_proc_dir_entries");
- return;
- }
- tpnt->proc_dir->owner = tpnt->module;
+ if(shpnt->hostt->proc_dir) {
+ sprintf(name, "%d", shpnt->host_no);
+ p = create_proc_read_entry(
+ name,
+ S_IFREG | S_IRUGO | S_IWUSR,
+ shpnt->hostt->proc_dir,
+ proc_scsi_read,
+ (void *) shpnt
+ );
+ if (!p)
+ panic("Not enough memory to register SCSI HBA in /proc/scsi !\n");
+ p->write_proc=proc_scsi_write;
+ p->owner = shpnt->hostt->module;
+ }
+}

- hpnt = scsi_hostlist;
- while (hpnt) {
- if (tpnt == hpnt->hostt) {
- struct proc_dir_entry *p;
- sprintf(name,"%d",hpnt->host_no);
- p = create_proc_read_entry(name,
- S_IFREG | S_IRUGO | S_IWUSR,
- tpnt->proc_dir,
- proc_scsi_read,
- (void *)hpnt);
- if (!p)
- panic("Not enough memory to register SCSI HBA in /proc/scsi !\n");
- p->write_proc=proc_scsi_write;
- p->owner = tpnt->module;
- }
- hpnt = hpnt->next;
+void build_proc_dir(Scsi_Host_Template * tpnt)
+{
+ tpnt->proc_dir = proc_mkdir(tpnt->proc_name, proc_scsi);
+ if (!tpnt->proc_dir) {
+ printk(KERN_ERR "Unable to proc_mkdir in scsi.c/build_proc_dir_entries");
+ return;
}
+ tpnt->proc_dir->owner = tpnt->module;
}

/*


2002-08-05 16:09:23

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH] 13/18 Export elevator_init

Problem: The dasd driver wants to switch to the noop elevator function but
it can do that if the driver is compiled as a module because
elevator_init is not exported.
Solution: Export elevator_init. Has been accepted to 2.5.

diff -urN linux-2.4.19-rc3/drivers/block/Makefile linux-2.4.19-s390/drivers/block/Makefile
--- linux-2.4.19-rc3/drivers/block/Makefile Tue Jul 30 09:02:27 2002
+++ linux-2.4.19-s390/drivers/block/Makefile Tue Jul 30 09:02:43 2002
@@ -10,7 +10,7 @@

O_TARGET := block.o

-export-objs := ll_rw_blk.o blkpg.o loop.o DAC960.o genhd.o
+export-objs := ll_rw_blk.o blkpg.o elevator.o loop.o DAC960.o genhd.o

obj-y := ll_rw_blk.o blkpg.o genhd.o elevator.o

diff -urN linux-2.4.19-rc3/drivers/block/elevator.c linux-2.4.19-s390/drivers/block/elevator.c
--- linux-2.4.19-rc3/drivers/block/elevator.c Fri Jul 20 05:59:41 2001
+++ linux-2.4.19-s390/drivers/block/elevator.c Tue Jul 30 09:01:22 2002
@@ -220,3 +220,5 @@
*elevator = type;
elevator->queue_ID = queue_ID++;
}
+
+EXPORT_SYMBOL(elevator_init);


2002-08-05 16:09:21

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH] 12/18 console_unblank bug fix

Problem: console_unblank can cause an endless trap loop if the console
semaphore is already taken and console_unblank is called in
interrupt context.
Solution: To avoid the trap loop just try to take the console semaphore
with down_trylock and exit if it fails. It is not perfect
since c->unblank() is not called in this case but way better
than an endless trap loop. s390/s390x are the only two
architectures that still use console_unblank. This patch
has been accepted to 2.5.

diff -urN linux-2.4.19-rc3/kernel/printk.c linux-2.4.19-s390/kernel/printk.c
--- linux-2.4.19-rc3/kernel/printk.c Tue Jul 30 09:02:32 2002
+++ linux-2.4.19-s390/kernel/printk.c Tue Jul 30 09:02:57 2002
@@ -556,7 +556,14 @@
{
struct console *c;

- acquire_console_sem();
+ /*
+ * Try to get the console semaphore. If someone else owns it
+ * we have to return without unblanking because console_unblank
+ * may be called in interrupt context.
+ */
+ if (down_trylock(&console_sem) != 0)
+ return;
+ console_may_schedule = 0;
for (c = console_drivers; c != NULL; c = c->next)
if ((c->flags & CON_ENABLED) && c->unblank)
c->unblank();


2002-08-05 16:11:04

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH] 15/18 better pte invalidation

This is a patch that changes the memory management to allow s390/s390x to
make best use of its memory subsystem. There are three problems:

1) the dirty and the referenced bit is kept in the storage key (there is
one for every physical page) and not in the page table entries.
Because of this difference the following piece of code is suboptimal:

if (pte_present(pte)) {
struct page *page = pte_page(pte);
if (VALID_PAGE(page) && !PageReserved(page) &&
ptep_test_and_clear_dirty(ptep)) {
flush_tlb_page(vma, address);
set_page_dirty(page);
}
}

The dirty bit is tested and cleared with ptep_test_and_clear_dirty and
if it is set the tlb for the page is flushed. But the tlb flush is
completly superflous on s/390 because ptep_test_and_clear_dirty has
already done everything that is needed (the magic behind that is
the sske instruction - see include/asm-s390/pgtable.h). To allow
s/390 to optimize the ptep_test_and_clear_and_flush_dirty function
is introduced that does what its name implies.

2) s/390 has an instruction called ipte (invalidate page table entry) that
is used to get rid of virtual pages. It does two things, first it set
the invalid bit in the pte and second it flushes the tlbs for this
page on all cpus. Very handy but it requires that the pte it should
flush is still valid. The introduction of establish_pte was a step
into the right direction but it is defined in mm/memory.c. We need
to be able to replace this function with a special s/390 variant.
I tried to move establish_pte to include/asm/pgtable.h but this
failed because of include order conflicts. Therefore I moved it
to include/asm/pgalloc.h (and renamed it to ptep_establish). To make
ptep_establish available on architectures that do not want to replace
it (all others), I added asm-generic/pgalloc.h and an include in
asm-<arch>/pgalloc.h for all architectures != s390. The same problem
as with establish_pte exists with invalidating ptes. The sequence
used in e.g. mm/vmscan.c is

flush_cache_page(vma, address);
pte = ptep_get_and_clear(page_table);
flush_tlb_page(vma, addess);

Again this makes it impossible to use the ipte in flush_tlb_page. The
sequence of these tree lines is replaced by ptep_invalidate. The "old"
implementation is moved to asm-generic/pgalloc.h and s/390 has its own
implementation with ipte.

3) The 4 pages middle directory problem. This is related to the order2 patch
for 64 bit s/390. The page size for 64 bit is 4096K but a full page middle
directories requires 16K = 4 pages. This is bad because get_free_pages
won't guarantee us that we can get 4 consecutive pages. The idea behind
the order2 patch is to use a hardware feature of 64 bit s/390 that allows
to use incomplete page middle directories. To pages is enough in 99.9% of
all cases. To make use of this feature we have to be able to "replace"
the pmd __pmd_alloc allocated by a large unit that contains a full page
middle directory:

#if defined(CONFIG_ARCH_S390X)
new = pgd_populate(mm, pgd, new);
if (!new)
return NULL;
#else
pgd_populate(mm, pgd, new);
#endif

See arch/s390x/mm/init.c and include/asm-s390x/pgalloc.h for the details.

And finally the last change is a pure pure compiler optimization: move
pte_alloc and make in extern inline. The compiler will generate a copy
that can be called from other modules AND inline it in mm/memory.c. This
saves a function call on the minor fault path and function calling is
expensive on s/390.


diff -urN linux-2.4.19-rc3/include/asm-alpha/pgalloc.h linux-2.4.19-s390/include/asm-alpha/pgalloc.h
--- linux-2.4.19-rc3/include/asm-alpha/pgalloc.h Tue Jul 30 09:02:30 2002
+++ linux-2.4.19-s390/include/asm-alpha/pgalloc.h Tue Jul 30 09:02:56 2002
@@ -347,4 +347,6 @@

extern int do_check_pgt_cache(int, int);

+#include <asm-generic/pgalloc.h>
+
#endif /* _ALPHA_PGALLOC_H */
diff -urN linux-2.4.19-rc3/include/asm-arm/pgalloc.h linux-2.4.19-s390/include/asm-arm/pgalloc.h
--- linux-2.4.19-rc3/include/asm-arm/pgalloc.h Sun Aug 12 20:14:00 2001
+++ linux-2.4.19-s390/include/asm-arm/pgalloc.h Tue Jul 30 09:01:23 2002
@@ -138,4 +138,6 @@

extern int do_check_pgt_cache(int, int);

+#include <asm-generic/pgalloc.h>
+
#endif
diff -urN linux-2.4.19-rc3/include/asm-generic/pgalloc.h linux-2.4.19-s390/include/asm-generic/pgalloc.h
--- linux-2.4.19-rc3/include/asm-generic/pgalloc.h Thu Jan 1 01:00:00 1970
+++ linux-2.4.19-s390/include/asm-generic/pgalloc.h Tue Jul 30 09:01:23 2002
@@ -0,0 +1,37 @@
+#ifndef _ASM_GENERIC_PGALLOC_H
+#define _ASM_GENERIC_PGALLOC_H
+
+static inline int ptep_test_and_clear_and_flush_young(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
+{
+ if (!ptep_test_and_clear_young(ptep))
+ return 0;
+ flush_tlb_page(vma, address);
+ return 1;
+}
+
+static inline int ptep_test_and_clear_and_flush_dirty(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
+{
+ if (!ptep_test_and_clear_dirty(ptep))
+ return 0;
+ flush_tlb_page(vma, address);
+ return 1;
+}
+
+static inline void ptep_establish(struct vm_area_struct *vma, unsigned long address, pte_t *ptep, pte_t entry)
+{
+ set_pte(ptep, entry);
+ flush_tlb_page(vma, address);
+ update_mmu_cache(vma, address, entry);
+}
+
+static inline pte_t ptep_invalidate(struct vm_area_struct *vma, unsigned long address, pte_t *ptep)
+{
+ pte_t pte;
+
+ flush_cache_page(vma, address);
+ pte = ptep_get_and_clear(ptep);
+ flush_tlb_page(vma, address);
+ return pte;
+}
+
+#endif /* _ASM_GENERIC_PGALLOC_H */
diff -urN linux-2.4.19-rc3/include/asm-i386/pgalloc.h linux-2.4.19-s390/include/asm-i386/pgalloc.h
--- linux-2.4.19-rc3/include/asm-i386/pgalloc.h Tue Jul 30 09:02:30 2002
+++ linux-2.4.19-s390/include/asm-i386/pgalloc.h Tue Jul 30 09:02:56 2002
@@ -235,4 +235,6 @@
flush_tlb_mm(mm);
}

+#include <asm-generic/pgalloc.h>
+
#endif /* _I386_PGALLOC_H */
diff -urN linux-2.4.19-rc3/include/asm-ia64/pgalloc.h linux-2.4.19-s390/include/asm-ia64/pgalloc.h
--- linux-2.4.19-rc3/include/asm-ia64/pgalloc.h Fri Nov 9 23:26:17 2001
+++ linux-2.4.19-s390/include/asm-ia64/pgalloc.h Tue Jul 30 09:01:23 2002
@@ -268,4 +268,6 @@
set_bit(PG_arch_1, &page->flags); /* mark page as clean */
}

+#include <asm-generic/pgalloc.h>
+
#endif /* _ASM_IA64_PGALLOC_H */
diff -urN linux-2.4.19-rc3/include/asm-m68k/pgalloc.h linux-2.4.19-s390/include/asm-m68k/pgalloc.h
--- linux-2.4.19-rc3/include/asm-m68k/pgalloc.h Tue Jul 30 09:02:31 2002
+++ linux-2.4.19-s390/include/asm-m68k/pgalloc.h Tue Jul 30 09:02:57 2002
@@ -164,4 +164,6 @@
#include <asm/motorola_pgalloc.h>
#endif

+#include <asm-generic/pgalloc.h>
+
#endif /* M68K_PGALLOC_H */
diff -urN linux-2.4.19-rc3/include/asm-mips/pgalloc.h linux-2.4.19-s390/include/asm-mips/pgalloc.h
--- linux-2.4.19-rc3/include/asm-mips/pgalloc.h Tue Jul 30 09:02:31 2002
+++ linux-2.4.19-s390/include/asm-mips/pgalloc.h Tue Jul 30 09:02:57 2002
@@ -194,4 +194,6 @@

extern int do_check_pgt_cache(int, int);

+#include <asm-generic/pgalloc.h>
+
#endif /* _ASM_PGALLOC_H */
diff -urN linux-2.4.19-rc3/include/asm-mips64/pgalloc.h linux-2.4.19-s390/include/asm-mips64/pgalloc.h
--- linux-2.4.19-rc3/include/asm-mips64/pgalloc.h Tue Jul 30 09:02:31 2002
+++ linux-2.4.19-s390/include/asm-mips64/pgalloc.h Tue Jul 30 09:02:57 2002
@@ -198,4 +198,6 @@

extern int do_check_pgt_cache(int, int);

+#include <asm-generic/pgalloc.h>
+
#endif /* _ASM_PGALLOC_H */
diff -urN linux-2.4.19-rc3/include/asm-parisc/pgalloc.h linux-2.4.19-s390/include/asm-parisc/pgalloc.h
--- linux-2.4.19-rc3/include/asm-parisc/pgalloc.h Tue Jul 30 09:02:32 2002
+++ linux-2.4.19-s390/include/asm-parisc/pgalloc.h Tue Jul 30 09:02:57 2002
@@ -404,4 +404,6 @@

extern int do_check_pgt_cache(int, int);

+#include <asm-generic/pgalloc.h>
+
#endif
diff -urN linux-2.4.19-rc3/include/asm-ppc/pgalloc.h linux-2.4.19-s390/include/asm-ppc/pgalloc.h
--- linux-2.4.19-rc3/include/asm-ppc/pgalloc.h Tue May 22 00:02:06 2001
+++ linux-2.4.19-s390/include/asm-ppc/pgalloc.h Tue Jul 30 09:01:23 2002
@@ -146,5 +146,7 @@

extern int do_check_pgt_cache(int, int);

+#include <asm-generic/pgalloc.h>
+
#endif /* _PPC_PGALLOC_H */
#endif /* __KERNEL__ */
diff -urN linux-2.4.19-rc3/include/asm-sh/pgalloc.h linux-2.4.19-s390/include/asm-sh/pgalloc.h
--- linux-2.4.19-rc3/include/asm-sh/pgalloc.h Sat Sep 8 21:29:09 2001
+++ linux-2.4.19-s390/include/asm-sh/pgalloc.h Tue Jul 30 09:01:23 2002
@@ -153,4 +153,7 @@
pte_t old_pte = *ptep;
set_pte(ptep, pte_mkdirty(old_pte));
}
+
+#include <asm-generic/pgalloc.h>
+
#endif /* __ASM_SH_PGALLOC_H */
diff -urN linux-2.4.19-rc3/include/asm-sparc/pgalloc.h linux-2.4.19-s390/include/asm-sparc/pgalloc.h
--- linux-2.4.19-rc3/include/asm-sparc/pgalloc.h Tue Jul 30 09:02:32 2002
+++ linux-2.4.19-s390/include/asm-sparc/pgalloc.h Tue Jul 30 09:02:57 2002
@@ -141,4 +141,6 @@

#define pte_free(pte) free_pte_fast(pte)

+#include <asm-generic/pgalloc.h>
+
#endif /* _SPARC_PGALLOC_H */
diff -urN linux-2.4.19-rc3/include/asm-sparc64/pgalloc.h linux-2.4.19-s390/include/asm-sparc64/pgalloc.h
--- linux-2.4.19-rc3/include/asm-sparc64/pgalloc.h Tue Jul 30 09:02:32 2002
+++ linux-2.4.19-s390/include/asm-sparc64/pgalloc.h Tue Jul 30 09:02:57 2002
@@ -304,4 +304,6 @@

extern int do_check_pgt_cache(int, int);

+#include <asm-generic/pgalloc.h>
+
#endif /* _SPARC64_PGALLOC_H */
diff -urN linux-2.4.19-rc3/mm/filemap.c linux-2.4.19-s390/mm/filemap.c
--- linux-2.4.19-rc3/mm/filemap.c Tue Jul 30 09:02:32 2002
+++ linux-2.4.19-s390/mm/filemap.c Tue Jul 30 09:02:57 2002
@@ -1296,7 +1296,7 @@
* bit. Otherwise, just mark it for future
* action..
*/
-void mark_page_accessed(struct page *page)
+inline void mark_page_accessed(struct page *page)
{
if (!PageActive(page) && PageReferenced(page)) {
activate_page(page);
@@ -2062,8 +2062,8 @@

if (pte_present(pte)) {
struct page *page = pte_page(pte);
- if (VALID_PAGE(page) && !PageReserved(page) && ptep_test_and_clear_dirty(ptep)) {
- flush_tlb_page(vma, address);
+ if (VALID_PAGE(page) && !PageReserved(page) &&
+ ptep_test_and_clear_and_flush_dirty(vma, address, ptep)) {
set_page_dirty(page);
}
}
diff -urN linux-2.4.19-rc3/mm/memory.c linux-2.4.19-s390/mm/memory.c
--- linux-2.4.19-rc3/mm/memory.c Tue Jul 30 09:02:32 2002
+++ linux-2.4.19-s390/mm/memory.c Tue Jul 30 09:02:57 2002
@@ -166,6 +166,84 @@
#define PMD_TABLE_MASK ((PTRS_PER_PMD-1) * sizeof(pmd_t))

/*
+ * Allocate page middle directory.
+ *
+ * We've already handled the fast-path in-line, and we own the
+ * page table lock.
+ *
+ * On a two-level page table, this ends up actually being entirely
+ * optimized away.
+ */
+pmd_t *__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
+{
+ pmd_t *new;
+
+ /* "fast" allocation can happen without dropping the lock.. */
+ new = pmd_alloc_one_fast(mm, address);
+ if (!new) {
+ spin_unlock(&mm->page_table_lock);
+ new = pmd_alloc_one(mm, address);
+ spin_lock(&mm->page_table_lock);
+ if (!new)
+ return NULL;
+
+ /*
+ * Because we dropped the lock, we should re-check the
+ * entry, as somebody else could have populated it..
+ */
+ if (!pgd_none(*pgd)) {
+ pmd_free(new);
+ goto out;
+ }
+ }
+#if defined(CONFIG_ARCH_S390X)
+ new = pgd_populate(mm, pgd, new);
+ if (!new)
+ return NULL;
+#else
+ pgd_populate(mm, pgd, new);
+#endif
+out:
+ return pmd_offset(pgd, address);
+}
+
+/*
+ * Allocate the page table directory.
+ *
+ * We've already handled the fast-path in-line, and we own the
+ * page table lock.
+ */
+inline pte_t *
+pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
+{
+ if (pmd_none(*pmd)) {
+ pte_t *new;
+
+ /* "fast" allocation can happen without dropping the lock.. */
+ new = pte_alloc_one_fast(mm, address);
+ if (!new) {
+ spin_unlock(&mm->page_table_lock);
+ new = pte_alloc_one(mm, address);
+ spin_lock(&mm->page_table_lock);
+ if (!new)
+ return NULL;
+
+ /*
+ * Because we dropped the lock, we should re-check the
+ * entry, as somebody else could have populated it..
+ */
+ if (!pmd_none(*pmd)) {
+ pte_free(new);
+ goto out;
+ }
+ }
+ pmd_populate(mm, pmd, new);
+ }
+out:
+ return pte_offset(pmd, address);
+}
+
+/*
* copy one vm_area from one task to the other. Assumes the page tables
* already present in the new task to be cleared in the whole range
* covered by this vma.
@@ -900,20 +978,6 @@
return error;
}

-/*
- * Establish a new mapping:
- * - flush the old one
- * - update the page tables
- * - inform the TLB about the new one
- *
- * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock
- */
-static inline void establish_pte(struct vm_area_struct * vma, unsigned long address, pte_t *page_table, pte_t entry)
-{
- set_pte(page_table, entry);
- flush_tlb_page(vma, address);
- update_mmu_cache(vma, address, entry);
-}

/*
* We hold the mm semaphore for reading and vma->vm_mm->page_table_lock
@@ -923,7 +987,8 @@
{
flush_page_to_ram(new_page);
flush_cache_page(vma, address);
- establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
+ ptep_establish(vma, address, page_table,
+ pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
}

/*
@@ -960,7 +1025,8 @@
unlock_page(old_page);
if (reuse) {
flush_cache_page(vma, address);
- establish_pte(vma, address, page_table, pte_mkyoung(pte_mkdirty(pte_mkwrite(pte))));
+ ptep_establish(vma, address, page_table,
+ pte_mkyoung(pte_mkdirty(pte_mkwrite(pte))));
spin_unlock(&mm->page_table_lock);
return 1; /* Minor fault */
}
@@ -1354,7 +1420,7 @@
entry = pte_mkdirty(entry);
}
entry = pte_mkyoung(entry);
- establish_pte(vma, address, pte, entry);
+ ptep_establish(vma, address, pte, entry);
spin_unlock(&mm->page_table_lock);
return 1;
}
@@ -1385,77 +1451,6 @@
}
spin_unlock(&mm->page_table_lock);
return -1;
-}
-
-/*
- * Allocate page middle directory.
- *
- * We've already handled the fast-path in-line, and we own the
- * page table lock.
- *
- * On a two-level page table, this ends up actually being entirely
- * optimized away.
- */
-pmd_t *__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
-{
- pmd_t *new;
-
- /* "fast" allocation can happen without dropping the lock.. */
- new = pmd_alloc_one_fast(mm, address);
- if (!new) {
- spin_unlock(&mm->page_table_lock);
- new = pmd_alloc_one(mm, address);
- spin_lock(&mm->page_table_lock);
- if (!new)
- return NULL;
-
- /*
- * Because we dropped the lock, we should re-check the
- * entry, as somebody else could have populated it..
- */
- if (!pgd_none(*pgd)) {
- pmd_free(new);
- goto out;
- }
- }
- pgd_populate(mm, pgd, new);
-out:
- return pmd_offset(pgd, address);
-}
-
-/*
- * Allocate the page table directory.
- *
- * We've already handled the fast-path in-line, and we own the
- * page table lock.
- */
-pte_t *pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
-{
- if (pmd_none(*pmd)) {
- pte_t *new;
-
- /* "fast" allocation can happen without dropping the lock.. */
- new = pte_alloc_one_fast(mm, address);
- if (!new) {
- spin_unlock(&mm->page_table_lock);
- new = pte_alloc_one(mm, address);
- spin_lock(&mm->page_table_lock);
- if (!new)
- return NULL;
-
- /*
- * Because we dropped the lock, we should re-check the
- * entry, as somebody else could have populated it..
- */
- if (!pmd_none(*pmd)) {
- pte_free(new);
- goto out;
- }
- }
- pmd_populate(mm, pmd, new);
- }
-out:
- return pte_offset(pmd, address);
}

int make_pages_present(unsigned long addr, unsigned long end)
diff -urN linux-2.4.19-rc3/mm/vmscan.c linux-2.4.19-s390/mm/vmscan.c
--- linux-2.4.19-rc3/mm/vmscan.c Tue Jul 30 09:02:32 2002
+++ linux-2.4.19-s390/mm/vmscan.c Tue Jul 30 09:02:57 2002
@@ -68,9 +68,7 @@
* is needed on CPUs which update the accessed and dirty
* bits in hardware.
*/
- flush_cache_page(vma, address);
- pte = ptep_get_and_clear(page_table);
- flush_tlb_page(vma, address);
+ pte = ptep_invalidate(vma, address, page_table);

if (pte_dirty(pte))
set_page_dirty(page);


2002-08-05 16:12:44

by Arnd Bergmann

[permalink] [raw]
Subject: [PATCH] 17/18 support arbitrary devfs names for tty devices

This patch introduces two functions tty_io. They are needed by the 3270 driver
to generate the correct entries in the device file system. We do not want
the 3270 device to get device names according to their minor number but
we want to see the real device number. If the device file system is not
used this can be replaced by a call to tty_register_devfs.

diff -urN linux-2.4.19-rc3/drivers/char/tty_io.c linux-2.4.19-s390/drivers/char/tty_io.c
--- linux-2.4.19-rc3/drivers/char/tty_io.c Tue Jul 30 09:02:27 2002
+++ linux-2.4.19-s390/drivers/char/tty_io.c Tue Jul 30 09:02:43 2002
@@ -2058,8 +2058,63 @@
#endif /* CONFIG_DEVFS_FS */
}

+/*
+ * Register a tty device described by <driver>, with minor number <minor>,
+ * device name <name> and in the /dev directory given by <dir>.
+ */
+void tty_register_devfs_name (struct tty_driver *driver, unsigned int flags,
+ unsigned minor, devfs_handle_t dir,
+ const char *name)
+{
+#ifdef CONFIG_DEVFS_FS
+ umode_t mode = S_IFCHR | S_IRUSR | S_IWUSR;
+ kdev_t device = MKDEV (driver->major, minor);
+
+ switch (device) {
+ case TTY_DEV:
+ case PTMX_DEV:
+ mode |= S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
+ break;
+ default:
+ if (driver->major == PTY_MASTER_MAJOR)
+ flags |= DEVFS_FL_AUTO_OWNER;
+ break;
+ }
+ if ( (minor < driver->minor_start) ||
+ (minor >= driver->minor_start + driver->num) ) {
+ printk(KERN_ERR "Attempt to register invalid minor number "
+ "with devfs (%d:%d).\n", (int)driver->major,(int)minor);
+ return;
+ }
+# ifdef CONFIG_UNIX98_PTYS
+ if ( (driver->major >= UNIX98_PTY_SLAVE_MAJOR) &&
+ (driver->major < UNIX98_PTY_SLAVE_MAJOR + UNIX98_NR_MAJORS) )
+ flags |= DEVFS_FL_CURRENT_OWNER;
+# endif
+ devfs_register (dir, name, flags | DEVFS_FL_DEFAULT,
+ driver->major, minor, mode, &tty_fops, NULL);
+#endif /* CONFIG_DEVFS_FS */
+}
+
+void tty_unregister_devfs_name (struct tty_driver *driver, unsigned minor,
+ devfs_handle_t dir, const char *name)
+{
+#ifdef CONFIG_DEVFS_FS
+ void * handle;
+
+ handle = devfs_find_handle (dir, name, driver->major, minor,
+ DEVFS_SPECIAL_CHR, 0);
+ devfs_unregister (handle);
+#endif /* CONFIG_DEVFS_FS */
+}
+
+extern void tty_unregister_devfs_name (struct tty_driver *driver,
+ unsigned minor, devfs_handle_t dir,
+ const char *name);
EXPORT_SYMBOL(tty_register_devfs);
EXPORT_SYMBOL(tty_unregister_devfs);
+EXPORT_SYMBOL(tty_register_devfs_name);
+EXPORT_SYMBOL(tty_unregister_devfs_name);

/*
* Called by a tty driver to register itself.
diff -urN linux-2.4.19-rc3/include/linux/tty.h linux-2.4.19-s390/include/linux/tty.h
--- linux-2.4.19-rc3/include/linux/tty.h Thu Nov 22 20:46:19 2001
+++ linux-2.4.19-s390/include/linux/tty.h Tue Jul 30 09:01:23 2002
@@ -381,6 +381,13 @@
extern void tty_register_devfs (struct tty_driver *driver, unsigned int flags,
unsigned minor);
extern void tty_unregister_devfs (struct tty_driver *driver, unsigned minor);
+struct devfs_entry;
+extern void tty_register_devfs_name (struct tty_driver *driver,
+ unsigned int flags, unsigned minor,
+ struct devfs_entry *dir, const char *name);
+extern void tty_unregister_devfs_name (struct tty_driver *driver,
+ unsigned minor, struct devfs_entry *dir,
+ const char *name);
extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
int buflen);
extern void tty_write_message(struct tty_struct *tty, char *msg);


2002-08-05 16:57:30

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] 15/18 better pte invalidation

On Mon, Aug 05, 2002 at 07:54:55PM +0200, Arnd Bergmann wrote:
> This is a patch that changes the memory management to allow s390/s390x to
> make best use of its memory subsystem. There are three problems:

Implementation comment: make pgd_populate return something on all
architectures, not just on s390.

Otherwise please try to get all this in 2.5 first, it's a major VM change.

2002-08-05 17:11:12

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] 14/18 support for partition labels in devfs

On Mon, Aug 05, 2002 at 07:50:10PM +0200, Arnd Bergmann wrote:
> This patch adds a new feature to the partition code. It will automatically
> generate links in the device filesystem from the label name of a dasd to
> the device node. This is only needed if the device filesystem is used.

Sorry, a s390-only /dev/labels/ is not acceptable. There are more than
enough storage devices that can support labels. And even a generic
implementation should go into 2.5 first.

2002-08-05 17:09:01

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] 18/18 scsi core changes

On Mon, Aug 05, 2002 at 08:08:35PM +0200, Arnd Bergmann wrote:
> This patch does not look fit for inclusion to me,

It absolutely does not look good for inclusion.

> but appearantly it's
> needed if anyone actually wants to use the new zfcp driver I sent with
> patch 10/18...

the zfcp driver itself is so ugly that I wonder you even show it publically..

> +if [ "$CONFIG_ARCH_S390" != "y" ]; then
> dep_tristate '7000FASST SCSI support' CONFIG_SCSI_7000FASST $CONFIG_SCSI
> dep_tristate 'ACARD SCSI support' CONFIG_SCSI_ACARD $CONFIG_SCSI
> dep_tristate 'Adaptec AHA152X/2825 support' CONFIG_SCSI_AHA152X $CONFIG_SCSI

all these entries want indentation by three spaces. See
Documentation/CodingStyle.

> +if [ "$CONFIG_ARCH_S390" = "y" ]; then
> +dep_tristate 'IBM z900 FCP host bus adapter driver' CONFIG_ZFCP $CONFIG_QDIO

dito.

> scsi_unregister(struct Scsi_Host * sh){
> struct Scsi_Host * shpnt;
> Scsi_Host_Name *shn;
> + char name[10];
> +
> + /* kill error handling thread */
> + if (sh->hostt->use_new_eh_code
> + && sh->ehandler != NULL) {
> + DECLARE_MUTEX_LOCKED(sem);
> +
> + sh->eh_notify = &sem;
> + send_sig(SIGHUP, sh->ehandler, 1);
> + down(&sem);
> + sh->eh_notify = NULL;
> + }
> +
> + /* remove proc entry */
> +#ifdef CONFIG_PROC_FS
> + sprintf(name, "%d", sh->host_no);
> + remove_proc_entry(name, sh->hostt->proc_dir);
> +#endif

this change actually looks useful. but I don't think it's suitable for
stable series.

> diff -urN linux-2.4.19-rc3/drivers/scsi/scsi.h linux-2.4.19-s390/drivers/scsi/scsi.h
> --- linux-2.4.19-rc3/drivers/scsi/scsi.h Tue Jul 30 09:02:28 2002
> +++ linux-2.4.19-s390/drivers/scsi/scsi.h Tue Jul 30 09:02:55 2002
> @@ -390,6 +390,17 @@
> #include <asm/pgtable.h>
> #define CONTIGUOUS_BUFFERS(X,Y) \
> (virt_to_phys((X)->b_data+(X)->b_size-1)+1==virt_to_phys((Y)->b_data))
> +#elif defined(CONFIG_ARCH_S390) || defined(CONFIG_ARCH_S390X)
> +#define _CONTIGUOUS_BUFFERS(xd, xs, yd, ys) \
> + (((xd + xs) == yd) \
> + && ((xd & PAGE_MASK) == ((yd + ys - 1) & PAGE_MASK)))
> +
> +#define CONTIGUOUS_BUFFERS(X,Y) \
> + _CONTIGUOUS_BUFFERS( \
> + (unsigned long)(X)->b_data, \
> + (unsigned long)(X)->b_size, \
> + (unsigned long)(Y)->b_data, \
> + (unsigned long)(Y)->b_size)

This area is going to change heavily with block-highmem in 2.4.20.
Please don't touch it just now.

> + /*
> + * We need to recount the number of
> + * scatter-gather segments here - the
> + * normal case code assumes this to be
> + * correct, as it would be a performance
> + * loss to always recount. Handling
> + * errors is always unusual, of course.
> + */
> + recount_segments(SCpnt);

might be worth to get the indentation right, heh?

What is the exact reason to move it around?


2002-08-05 17:11:46

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] 16/18 add more possible root devices

On Mon, Aug 05, 2002 at 07:56:39PM +0200, Arnd Bergmann wrote:
> This patch adds some more s/390 specific devices to the list of root devices.

Indentation is b0rked.

2002-08-06 09:03:00

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH] 15/18 better pte invalidation

On Monday 05 August 2002 19:01, Christoph Hellwig wrote:
> Implementation comment: make pgd_populate return something on all
> architectures, not just on s390.
Makes sense to me. Martin?

> Otherwise please try to get all this in 2.5 first, it's a major VM change.
Right. I guess this one falls more in the category "If anyone wants to build
an s390 2.4.19 kernel, use this patch, because it's what we have tested at
IBM".

Since the 18 patches reflect what our recommended 2.4.17 patch contains
(roughly sorted by relevance), not all of it is necessarily good for 2.4.20.
You can see it as "this is all we have -- take what you like". Of course,
anything that gets merged makes life easier for us.

Arnd <><

2002-08-06 09:03:58

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH] 18/18 scsi core changes

On Monday 05 August 2002 19:12, Christoph Hellwig wrote:
> It absolutely does not look good for inclusion.
OK, thanks for looking at it. Maybe the zfcp developers can
find a less intrusive way of getting the driver to work
if they want it to work out of the box.

> the zfcp driver itself is so ugly that I wonder you even show it
> publically..
The other new drivers I sent (lcs, z90crypt and qdio) and some of
the s390 stuff that's already in 2.4 are not really any better.
These three have all been closed source before and you can see
them as a warning of what happens to your code if you skip
public peer review ;-)
Still, it's the stuff IBM recommends for use and it's not going
away (at least not in 2.4), so I guess it might just as well be
included.

OTOH, if Marcello wants to the next patch size small, it might be
a good idea to leave out the uglier drivers.

Arnd <><

2002-08-06 09:14:32

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] 18/18 scsi core changes

On Tue, Aug 06, 2002 at 01:06:03PM +0200, Arnd Bergmann wrote:
> Still, it's the stuff IBM recommends for use and it's not going
> away (at least not in 2.4), so I guess it might just as well be
> included.

Following that argumentation we could also include the broken qlogic driver
and the nvidia glue..

2002-08-06 09:21:02

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH] 16/18 add more possible root devices

On Monday 05 August 2002 19:15, Christoph Hellwig wrote:
> On Mon, Aug 05, 2002 at 07:56:39PM +0200, Arnd Bergmann wrote:
> > This patch adds some more s/390 specific devices to the list of root
> > devices.
>
> Indentation is b0rked.

Thanks, this fixes indentation and removes the extra xpram entries noticed
by Bernd.

diff -ur linux-2.4.19-s390/init/do_mounts.c linux-2.4.19-s390-bootdev/init/do_mounts.c
--- linux-2.4.19-s390/init/do_mounts.c Tue Aug 6 11:10:06 2002
+++ linux-2.4.19-s390-bootdev/init/do_mounts.c Tue Aug 6 11:14:20 2002
@@ -162,6 +162,27 @@
{ "dasdf", (DASD_MAJOR << MINORBITS) + (5 << 2) },
{ "dasdg", (DASD_MAJOR << MINORBITS) + (6 << 2) },
{ "dasdh", (DASD_MAJOR << MINORBITS) + (7 << 2) },
+ { "dasdi", (DASD_MAJOR << MINORBITS) + (8 << 2) },
+ { "dasdj", (DASD_MAJOR << MINORBITS) + (9 << 2) },
+ { "dasdk", (DASD_MAJOR << MINORBITS) + (10 << 2) },
+ { "dasdl", (DASD_MAJOR << MINORBITS) + (11 << 2) },
+ { "dasdm", (DASD_MAJOR << MINORBITS) + (12 << 2) },
+ { "dasdn", (DASD_MAJOR << MINORBITS) + (13 << 2) },
+ { "dasdo", (DASD_MAJOR << MINORBITS) + (14 << 2) },
+ { "dasdp", (DASD_MAJOR << MINORBITS) + (15 << 2) },
+ { "dasdq", (DASD_MAJOR << MINORBITS) + (16 << 2) },
+ { "dasdr", (DASD_MAJOR << MINORBITS) + (17 << 2) },
+ { "dasds", (DASD_MAJOR << MINORBITS) + (18 << 2) },
+ { "dasdt", (DASD_MAJOR << MINORBITS) + (19 << 2) },
+ { "dasdu", (DASD_MAJOR << MINORBITS) + (20 << 2) },
+ { "dasdv", (DASD_MAJOR << MINORBITS) + (21 << 2) },
+ { "dasdw", (DASD_MAJOR << MINORBITS) + (22 << 2) },
+ { "dasdx", (DASD_MAJOR << MINORBITS) + (23 << 2) },
+ { "dasdy", (DASD_MAJOR << MINORBITS) + (24 << 2) },
+ { "dasdz", (DASD_MAJOR << MINORBITS) + (25 << 2) },
+#endif
+#ifdef CONFIG_BLK_DEV_XPRAM
+ { "xpram", (XPRAM_MAJOR << MINORBITS) },
#endif
#if defined(CONFIG_BLK_CPQ_DA) || defined(CONFIG_BLK_CPQ_DA_MODULE)
{ "ida/c0d0p",0x4800 },

2002-08-06 09:40:06

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] 15/18 better pte invalidation

On Tue, Aug 06, 2002 at 01:05:17PM +0200, Arnd Bergmann wrote:
> > Otherwise please try to get all this in 2.5 first, it's a major VM change.
> Right. I guess this one falls more in the category "If anyone wants to build
> an s390 2.4.19 kernel, use this patch, because it's what we have tested at
> IBM".

Umm. 2.4.19 _does_ build on S/390. By getting in a truckload of patches
that update everything to IBM's latest & greatest that just require a few
unacceptable / not yet acceptable intrusive core changes you break that.

You probably don't care a lot, but people trying to test S/390 compatiblity
on Hercules (or a Multiprise in the basement..) really want to compile
kernels out-of-the-box.

2002-08-06 23:08:47

by Christoph Hellwig

[permalink] [raw]
Subject: Re: [PATCH] 18/18 scsi core changes

On Wed, Aug 07, 2002 at 01:10:16AM +0200, Ingo Adlung wrote:
> > Following that argumentation we could also include the broken qlogic driver
> > and the nvidia glue..
> >
>
> Well, if the hardware implementation would always be straight forward to
> what you know from PCs, it wouldn't be required to apply additional
> patches to the common code, but it would be easy to stay within the
> architecture specifics.

That above statement was about the horrible code quality of most if not
all s390 drivers. Yes there are similarly bad vendor drivers around for
intel hardware - buf fortunately they are not in the tree.

2002-08-06 23:03:52

by Ingo.Adlung

[permalink] [raw]
Subject: Re: [PATCH] 18/18 scsi core changes



Christoph Hellwig wrote:

> On Tue, Aug 06, 2002 at 01:06:03PM +0200, Arnd Bergmann wrote:
>
>>Still, it's the stuff IBM recommends for use and it's not going
>>away (at least not in 2.4), so I guess it might just as well be
>>included.
>>
>
> Following that argumentation we could also include the broken qlogic driver
> and the nvidia glue..
>

Well, if the hardware implementation would always be straight forward to
what you know from PCs, it wouldn't be required to apply additional
patches to the common code, but it would be easy to stay within the
architecture specifics. Unfortunately it is not always that easy, by
large related to virtualization issues ... not an excuse, but an
explanation. Those not intending to use Linux on IBM's mainframes, and
what's worth in this context its FCP support can safely ignore the SCSI
related patch. Anybody else will need it - but you're welcome to show
alternatives, I'm sure the folks having written the code do very much
appreciate any guidance you can provide 'em getting to a nicer/cleaner
implementation finding everybody's appreciation :-)

Ingo




2002-08-10 12:27:57

by Paul Mackerras

[permalink] [raw]
Subject: Re: [PATCH] 15/18 better pte invalidation

Arnd Bergmann writes:

> 2) s/390 has an instruction called ipte (invalidate page table entry) that
> is used to get rid of virtual pages. It does two things, first it set
> the invalid bit in the pte and second it flushes the tlbs for this
> page on all cpus. Very handy but it requires that the pte it should
> flush is still valid. The introduction of establish_pte was a step
> into the right direction but it is defined in mm/memory.c. We need
> to be able to replace this function with a special s/390 variant.

It's now possible in 2.5 to go from a PTE pointer to the mm and
virtual address that it maps - see ptep_to_mm and ptep_to_address in
include/asm-generic/rmap.h. I'm planning to use this to do MMU
hashtable management on PPC in set_pte et al. and thus avoid the
second walk of the Linux page tables that we currently do in
flush_tlb_* on PPC. You could use those functions to let you use the
ipte instruction in set_pte et al. and then make the flush_tlb_*
functions be no-ops.

The ptep_to_mm and ptep_to_address functions came in with rmap, but
all they rely on is having the page->mapping and page->index fields
filled in for pagetable pages. It should only be a minor addition to
the 2.4 MM system to set those fields, and it would be useful on ppc,
ppc64, s390 and s390x.

Paul.