Commit 3c443cbc authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6

* 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6:
  [S390] smsgiucv_app: deliver z/VM CP special messages (SMSG) as uevents
  [S390] smsgiucv: declare char pointers as "const"
  [S390] dasd: automatic recognition of read-only devices
  [S390] remove unused qdio flags in zfcp and qeth
  [S390] Cleanup xtime usage
  [S390] qdio: add missing bracket
  [S390] cio: fix init_count in case of recognition after steal lock
  [S390] dasd: security and PSF update patch for EMC CKD ioctl
  [S390] hvc_iucv: allocate memory buffers for IUCV in zone DMA
  [S390] uaccess: make sure copy_from_user_overflow is builtin
parents d4014030 1ffaa640
......@@ -321,11 +321,6 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
#define QDIO_ERROR_ACTIVATE_CHECK_CONDITION 0x40
#define QDIO_ERROR_SLSB_STATE 0x80
/* for qdio_initialize */
#define QDIO_INBOUND_0COPY_SBALS 0x01
#define QDIO_OUTBOUND_0COPY_SBALS 0x02
#define QDIO_USE_OUTBOUND_PCIS 0x04
/* for qdio_cleanup */
#define QDIO_FLAG_CLEANUP_USING_CLEAR 0x01
#define QDIO_FLAG_CLEANUP_USING_HALT 0x02
......@@ -344,7 +339,6 @@ typedef void qdio_handler_t(struct ccw_device *, unsigned int, int,
* @input_handler: handler to be called for input queues
* @output_handler: handler to be called for output queues
* @int_parm: interruption parameter
* @flags: initialization flags
* @input_sbal_addr_array: address of no_input_qs * 128 pointers
* @output_sbal_addr_array: address of no_output_qs * 128 pointers
*/
......@@ -361,7 +355,6 @@ struct qdio_initialize {
qdio_handler_t *input_handler;
qdio_handler_t *output_handler;
unsigned long int_parm;
unsigned long flags;
void **input_sbal_addr_array;
void **output_sbal_addr_array;
};
......
......@@ -73,15 +73,15 @@ unsigned long long monotonic_clock(void)
}
EXPORT_SYMBOL(monotonic_clock);
void tod_to_timeval(__u64 todval, struct timespec *xtime)
void tod_to_timeval(__u64 todval, struct timespec *xt)
{
unsigned long long sec;
sec = todval >> 12;
do_div(sec, 1000000);
xtime->tv_sec = sec;
xt->tv_sec = sec;
todval -= (sec * 1000000) << 12;
xtime->tv_nsec = ((todval * 1000) >> 12);
xt->tv_nsec = ((todval * 1000) >> 12);
}
EXPORT_SYMBOL(tod_to_timeval);
......@@ -216,8 +216,8 @@ void update_vsyscall(struct timespec *wall_time, struct clocksource *clock,
++vdso_data->tb_update_count;
smp_wmb();
vdso_data->xtime_tod_stamp = clock->cycle_last;
vdso_data->xtime_clock_sec = xtime.tv_sec;
vdso_data->xtime_clock_nsec = xtime.tv_nsec;
vdso_data->xtime_clock_sec = wall_time->tv_sec;
vdso_data->xtime_clock_nsec = wall_time->tv_nsec;
vdso_data->wtom_clock_sec = wall_to_monotonic.tv_sec;
vdso_data->wtom_clock_nsec = wall_to_monotonic.tv_nsec;
smp_wmb();
......
......@@ -2,7 +2,8 @@
# Makefile for s390-specific library files..
#
lib-y += delay.o string.o uaccess_std.o uaccess_pt.o usercopy.o
lib-y += delay.o string.o uaccess_std.o uaccess_pt.o
obj-y += usercopy.o
obj-$(CONFIG_32BIT) += div64.o qrnnd.o ucmpdi2.o
lib-$(CONFIG_64BIT) += uaccess_mvcos.o
lib-$(CONFIG_SMP) += spinlock.o
......@@ -374,7 +374,7 @@ static struct ctl_table cmm_dir_table[] = {
#ifdef CONFIG_CMM_IUCV
#define SMSG_PREFIX "CMM"
static void
cmm_smsg_target(char *from, char *msg)
cmm_smsg_target(const char *from, char *msg)
{
long nr, seconds;
......
......@@ -139,6 +139,8 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num)
*
* This function allocates a new struct iucv_tty_buffer element and, optionally,
* allocates an internal data buffer with the specified size @size.
* The internal data buffer is always allocated with GFP_DMA which is
* required for receiving and sending data with IUCV.
* Note: The total message size arises from the internal buffer size and the
* members of the iucv_tty_msg structure.
* The function returns NULL if memory allocation has failed.
......@@ -154,7 +156,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags)
if (size > 0) {
bufp->msg.length = MSG_SIZE(size);
bufp->mbuf = kmalloc(bufp->msg.length, flags);
bufp->mbuf = kmalloc(bufp->msg.length, flags | GFP_DMA);
if (!bufp->mbuf) {
mempool_free(bufp, hvc_iucv_mempool);
return NULL;
......@@ -237,7 +239,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv,
if (!rb->mbuf) { /* message not yet received ... */
/* allocate mem to store msg data; if no memory is available
* then leave the buffer on the list and re-try later */
rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC);
rb->mbuf = kmalloc(rb->msg.length, GFP_ATOMIC | GFP_DMA);
if (!rb->mbuf)
return -ENOMEM;
......
......@@ -26,6 +26,7 @@
#include <asm/ebcdic.h>
#include <asm/idals.h>
#include <asm/itcw.h>
#include <asm/diag.h>
/* This is ugly... */
#define PRINTK_HEADER "dasd:"
......@@ -2212,6 +2213,13 @@ static int dasd_open(struct block_device *bdev, fmode_t mode)
goto out;
}
if ((mode & FMODE_WRITE) &&
(test_bit(DASD_FLAG_DEVICE_RO, &base->flags) ||
(base->features & DASD_FEATURE_READONLY))) {
rc = -EROFS;
goto out;
}
return 0;
out:
......@@ -2289,6 +2297,34 @@ dasd_exit(void)
* SECTION: common functions for ccw_driver use
*/
/*
* Is the device read-only?
* Note that this function does not report the setting of the
* readonly device attribute, but how it is configured in z/VM.
*/
int dasd_device_is_ro(struct dasd_device *device)
{
struct ccw_dev_id dev_id;
struct diag210 diag_data;
int rc;
if (!MACHINE_IS_VM)
return 0;
ccw_device_get_id(device->cdev, &dev_id);
memset(&diag_data, 0, sizeof(diag_data));
diag_data.vrdcdvno = dev_id.devno;
diag_data.vrdclen = sizeof(diag_data);
rc = diag210(&diag_data);
if (rc == 0 || rc == 2) {
return diag_data.vrdcvfla & 0x80;
} else {
DBF_EVENT(DBF_WARNING, "diag210 failed for dev=%04x with rc=%d",
dev_id.devno, rc);
return 0;
}
}
EXPORT_SYMBOL_GPL(dasd_device_is_ro);
static void dasd_generic_auto_online(void *data, async_cookie_t cookie)
{
struct ccw_device *cdev = data;
......
......@@ -1045,6 +1045,10 @@ dasd_3990_erp_com_rej(struct dasd_ccw_req * erp, char *sense)
erp->retries = 5;
} else if (sense[1] & SNS1_WRITE_INHIBITED) {
dev_err(&device->cdev->dev, "An I/O request was rejected"
" because writing is inhibited\n");
erp = dasd_3990_erp_cleanup(erp, DASD_CQR_FAILED);
} else {
/* fatal error - set status to FAILED
internal error 09 - Command Reject */
......
......@@ -742,6 +742,7 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct dasd_devmap *devmap;
struct dasd_device *device;
int val;
char *endp;
......@@ -758,12 +759,14 @@ dasd_ro_store(struct device *dev, struct device_attribute *attr,
devmap->features |= DASD_FEATURE_READONLY;
else
devmap->features &= ~DASD_FEATURE_READONLY;
if (devmap->device)
devmap->device->features = devmap->features;
if (devmap->device && devmap->device->block
&& devmap->device->block->gdp)
set_disk_ro(devmap->device->block->gdp, val);
device = devmap->device;
if (device) {
device->features = devmap->features;
val = val || test_bit(DASD_FLAG_DEVICE_RO, &device->flags);
}
spin_unlock(&dasd_devmap_lock);
if (device && device->block && device->block->gdp)
set_disk_ro(device->block->gdp, val);
return count;
}
......
......@@ -145,12 +145,10 @@ dasd_diag_erp(struct dasd_device *device)
mdsk_term_io(device);
rc = mdsk_init_io(device, device->block->bp_block, 0, NULL);
if (rc == 4) {
if (!(device->features & DASD_FEATURE_READONLY)) {
if (!(test_and_set_bit(DASD_FLAG_DEVICE_RO, &device->flags)))
pr_warning("%s: The access mode of a DIAG device "
"changed to read-only\n",
dev_name(&device->cdev->dev));
device->features |= DASD_FEATURE_READONLY;
}
rc = 0;
}
if (rc)
......@@ -449,7 +447,7 @@ dasd_diag_check_device(struct dasd_device *device)
rc = -EIO;
} else {
if (rc == 4)
device->features |= DASD_FEATURE_READONLY;
set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
pr_info("%s: New DASD with %ld byte/block, total size %ld "
"KB%s\n", dev_name(&device->cdev->dev),
(unsigned long) block->bp_block,
......
......@@ -1089,6 +1089,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
struct dasd_eckd_private *private;
struct dasd_block *block;
int is_known, rc;
int readonly;
if (!ccw_device_is_pathgroup(device->cdev)) {
dev_warn(&device->cdev->dev,
......@@ -1182,15 +1183,20 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
else
private->real_cyl = private->rdc_data.no_cyl;
readonly = dasd_device_is_ro(device);
if (readonly)
set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
dev_info(&device->cdev->dev, "New DASD %04X/%02X (CU %04X/%02X) "
"with %d cylinders, %d heads, %d sectors\n",
"with %d cylinders, %d heads, %d sectors%s\n",
private->rdc_data.dev_type,
private->rdc_data.dev_model,
private->rdc_data.cu_type,
private->rdc_data.cu_model.model,
private->real_cyl,
private->rdc_data.trk_per_cyl,
private->rdc_data.sec_per_trk);
private->rdc_data.sec_per_trk,
readonly ? ", read-only device" : "");
return 0;
out_err3:
......@@ -2839,8 +2845,13 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
char *psf_data, *rssd_result;
struct dasd_ccw_req *cqr;
struct ccw1 *ccw;
char psf0, psf1;
int rc;
if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
return -EACCES;
psf0 = psf1 = 0;
/* Copy parms from caller */
rc = -EFAULT;
if (copy_from_user(&usrparm, argp, sizeof(usrparm)))
......@@ -2869,12 +2880,8 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
(void __user *)(unsigned long) usrparm.psf_data,
usrparm.psf_data_len))
goto out_free;
/* sanity check on syscall header */
if (psf_data[0] != 0x17 && psf_data[1] != 0xce) {
rc = -EINVAL;
goto out_free;
}
psf0 = psf_data[0];
psf1 = psf_data[1];
/* setup CCWs for PSF + RSSD */
cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device);
......@@ -2925,7 +2932,9 @@ out_free:
kfree(rssd_result);
kfree(psf_data);
out:
DBF_DEV_EVENT(DBF_WARNING, device, "Symmetrix ioctl: rc=%d", rc);
DBF_DEV_EVENT(DBF_WARNING, device,
"Symmetrix ioctl (0x%02x 0x%02x): rc=%d",
(int) psf0, (int) psf1, rc);
return rc;
}
......
......@@ -124,6 +124,7 @@ dasd_fba_check_characteristics(struct dasd_device *device)
struct dasd_fba_private *private;
struct ccw_device *cdev = device->cdev;
int rc;
int readonly;
private = (struct dasd_fba_private *) device->private;
if (!private) {
......@@ -162,16 +163,21 @@ dasd_fba_check_characteristics(struct dasd_device *device)
return rc;
}
readonly = dasd_device_is_ro(device);
if (readonly)
set_bit(DASD_FLAG_DEVICE_RO, &device->flags);
dev_info(&device->cdev->dev,
"New FBA DASD %04X/%02X (CU %04X/%02X) with %d MB "
"and %d B/blk\n",
"and %d B/blk%s\n",
cdev->id.dev_type,
cdev->id.dev_model,
cdev->id.cu_type,
cdev->id.cu_model,
((private->rdc_data.blk_bdsa *
(private->rdc_data.blk_size >> 9)) >> 11),
private->rdc_data.blk_size);
private->rdc_data.blk_size,
readonly ? ", read-only device" : "");
return 0;
}
......
......@@ -70,7 +70,8 @@ int dasd_gendisk_alloc(struct dasd_block *block)
}
len += sprintf(gdp->disk_name + len, "%c", 'a'+(base->devindex%26));
if (block->base->features & DASD_FEATURE_READONLY)
if (base->features & DASD_FEATURE_READONLY ||
test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
set_disk_ro(gdp, 1);
gdp->private_data = block;
gdp->queue = block->request_queue;
......
......@@ -436,6 +436,10 @@ struct dasd_block {
#define DASD_FLAG_OFFLINE 3 /* device is in offline processing */
#define DASD_FLAG_EER_SNSS 4 /* A SNSS is required */
#define DASD_FLAG_EER_IN_USE 5 /* A SNSS request is running */
#define DASD_FLAG_DEVICE_RO 6 /* The device itself is read-only. Don't
* confuse this with the user specified
* read-only feature.
*/
void dasd_put_device_wake(struct dasd_device *);
......@@ -609,6 +613,9 @@ char *dasd_get_sense(struct irb *);
void dasd_device_set_stop_bits(struct dasd_device *, int);
void dasd_device_remove_stop_bits(struct dasd_device *, int);
int dasd_device_is_ro(struct dasd_device *);
/* externals in dasd_devmap.c */
extern int dasd_max_devindex;
extern int dasd_probeonly;
......
......@@ -199,7 +199,8 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp)
if (!argp)
return -EINVAL;
if (block->base->features & DASD_FEATURE_READONLY)
if (block->base->features & DASD_FEATURE_READONLY ||
test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
return -EROFS;
if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
return -EFAULT;
......@@ -349,7 +350,8 @@ dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
return -EINVAL;
if (get_user(intval, (int __user *)argp))
return -EFAULT;
if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
return -EROFS;
set_disk_ro(bdev->bd_disk, intval);
return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval);
}
......
......@@ -764,7 +764,7 @@ static void sch_create_and_recog_new_device(struct subchannel *sch)
static void io_subchannel_register(struct ccw_device *cdev)
{
struct subchannel *sch;
int ret;
int ret, adjust_init_count = 1;
unsigned long flags;
sch = to_subchannel(cdev->dev.parent);
......@@ -793,6 +793,7 @@ static void io_subchannel_register(struct ccw_device *cdev)
cdev->private->dev_id.ssid,
cdev->private->dev_id.devno);
}
adjust_init_count = 0;
goto out;
}
/*
......@@ -818,7 +819,7 @@ out:
cdev->private->flags.recog_done = 1;
wake_up(&cdev->private->wait_q);
out_err:
if (atomic_dec_and_test(&ccw_device_init_count))
if (adjust_init_count && atomic_dec_and_test(&ccw_device_init_count))
wake_up(&ccw_device_init_wq);
}
......
......@@ -33,7 +33,6 @@ void qdio_allocate_dbf(struct qdio_initialize *init_data,
DBF_HEX(&init_data->input_handler, sizeof(void *));
DBF_HEX(&init_data->output_handler, sizeof(void *));
DBF_HEX(&init_data->int_parm, sizeof(long));
DBF_HEX(&init_data->flags, sizeof(long));
DBF_HEX(&init_data->input_sbal_addr_array, sizeof(void *));
DBF_HEX(&init_data->output_sbal_addr_array, sizeof(void *));
DBF_EVENT("irq:%8lx", (unsigned long)irq_ptr);
......
......@@ -588,10 +588,11 @@ static void qdio_kick_handler(struct qdio_q *q)
if (q->is_input_q) {
qperf_inc(q, inbound_handler);
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count);
} else
} else {
qperf_inc(q, outbound_handler);
DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x",
start, count);
}
q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count,
q->irq_ptr->int_parm);
......
......@@ -43,6 +43,16 @@ config SMSGIUCV
Select this option if you want to be able to receive SMSG messages
from other VM guest systems.
config SMSGIUCV_EVENT
tristate "Deliver IUCV special messages as uevents (VM only)"
depends on SMSGIUCV
help
Select this option to deliver CP special messages (SMSGs) as
uevents. The driver handles only those special messages that
start with "APP".
To compile as a module, choose M. The module name is "smsgiucv_app".
config CLAW
tristate "CLAW device support"
depends on CCW && NETDEVICES
......
......@@ -6,6 +6,7 @@ ctcm-y += ctcm_main.o ctcm_fsms.o ctcm_mpc.o ctcm_sysfs.o ctcm_dbug.o
obj-$(CONFIG_CTCM) += ctcm.o fsm.o
obj-$(CONFIG_NETIUCV) += netiucv.o fsm.o
obj-$(CONFIG_SMSGIUCV) += smsgiucv.o
obj-$(CONFIG_SMSGIUCV_EVENT) += smsgiucv_app.o
obj-$(CONFIG_LCS) += lcs.o
obj-$(CONFIG_CLAW) += claw.o
qeth-y += qeth_core_sys.o qeth_core_main.o qeth_core_mpc.o
......
......@@ -3805,9 +3805,6 @@ static int qeth_qdio_establish(struct qeth_card *card)
init_data.input_handler = card->discipline.input_handler;
init_data.output_handler = card->discipline.output_handler;
init_data.int_parm = (unsigned long) card;
init_data.flags = QDIO_INBOUND_0COPY_SBALS |
QDIO_OUTBOUND_0COPY_SBALS |
QDIO_USE_OUTBOUND_PCIS;
init_data.input_sbal_addr_array = (void **) in_sbal_ptrs;
init_data.output_sbal_addr_array = (void **) out_sbal_ptrs;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment