summaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/char/Makefile2
-rw-r--r--drivers/s390/char/sclp_early.c34
-rw-r--r--drivers/s390/char/zcore.c44
-rw-r--r--drivers/s390/cio/ccwreq.c4
-rw-r--r--drivers/s390/cio/chp.c2
-rw-r--r--drivers/s390/cio/chp.h2
-rw-r--r--drivers/s390/cio/chsc.h11
-rw-r--r--drivers/s390/cio/chsc_sch.c2
-rw-r--r--drivers/s390/cio/cio.c9
-rw-r--r--drivers/s390/cio/cio.h2
-rw-r--r--drivers/s390/cio/device_fsm.c4
-rw-r--r--drivers/s390/cio/device_ops.c13
-rw-r--r--drivers/s390/cio/eadm_sch.c2
-rw-r--r--drivers/s390/crypto/ap_bus.c2
-rw-r--r--drivers/s390/kvm/virtio_ccw.c49
-rw-r--r--drivers/s390/net/qeth_core_main.c12
16 files changed, 114 insertions, 80 deletions
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile
index b69ab17..629fcc2 100644
--- a/drivers/s390/char/Makefile
+++ b/drivers/s390/char/Makefile
@@ -33,4 +33,4 @@ obj-$(CONFIG_MONWRITER) += monwriter.o
obj-$(CONFIG_S390_VMUR) += vmur.o
zcore_mod-objs := sclp_sdias.o zcore.o
-obj-$(CONFIG_ZFCPDUMP) += zcore_mod.o
+obj-$(CONFIG_CRASH_DUMP) += zcore_mod.o
diff --git a/drivers/s390/char/sclp_early.c b/drivers/s390/char/sclp_early.c
index 14196ea..1918d9d 100644
--- a/drivers/s390/char/sclp_early.c
+++ b/drivers/s390/char/sclp_early.c
@@ -22,11 +22,14 @@ struct read_info_sccb {
u8 rnsize; /* 10 */
u8 _reserved0[16 - 11]; /* 11-15 */
u16 ncpurl; /* 16-17 */
- u8 _reserved7[24 - 18]; /* 18-23 */
+ u16 cpuoff; /* 18-19 */
+ u8 _reserved7[24 - 20]; /* 20-23 */
u8 loadparm[8]; /* 24-31 */
u8 _reserved1[48 - 32]; /* 32-47 */
u64 facilities; /* 48-55 */
- u8 _reserved2[84 - 56]; /* 56-83 */
+ u8 _reserved2a[76 - 56]; /* 56-75 */
+ u32 ibc; /* 76-79 */
+ u8 _reserved2b[84 - 80]; /* 80-83 */
u8 fac84; /* 84 */
u8 fac85; /* 85 */
u8 _reserved3[91 - 86]; /* 86-90 */
@@ -45,6 +48,8 @@ static unsigned int sclp_con_has_linemode __initdata;
static unsigned long sclp_hsa_size;
static unsigned int sclp_max_cpu;
static struct sclp_ipl_info sclp_ipl_info;
+static unsigned char sclp_siif;
+static u32 sclp_ibc;
u64 sclp_facilities;
u8 sclp_fac84;
@@ -96,6 +101,9 @@ static int __init sclp_read_info_early(struct read_info_sccb *sccb)
static void __init sclp_facilities_detect(struct read_info_sccb *sccb)
{
+ struct sclp_cpu_entry *cpue;
+ u16 boot_cpu_address, cpu;
+
if (sclp_read_info_early(sccb))
return;
@@ -106,6 +114,7 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb)
sclp_rnmax = sccb->rnmax ? sccb->rnmax : sccb->rnmax2;
sclp_rzm = sccb->rnsize ? sccb->rnsize : sccb->rnsize2;
sclp_rzm <<= 20;
+ sclp_ibc = sccb->ibc;
if (!sccb->hcpua) {
if (MACHINE_IS_VM)
@@ -116,6 +125,15 @@ static void __init sclp_facilities_detect(struct read_info_sccb *sccb)
sclp_max_cpu = sccb->hcpua + 1;
}
+ boot_cpu_address = stap();
+ cpue = (void *)sccb + sccb->cpuoff;
+ for (cpu = 0; cpu < sccb->ncpurl; cpue++, cpu++) {
+ if (boot_cpu_address != cpue->address)
+ continue;
+ sclp_siif = cpue->siif;
+ break;
+ }
+
/* Save IPL information */
sclp_ipl_info.is_valid = 1;
if (sccb->flags & 0x2)
@@ -148,6 +166,18 @@ unsigned int sclp_get_max_cpu(void)
return sclp_max_cpu;
}
+int sclp_has_siif(void)
+{
+ return sclp_siif;
+}
+EXPORT_SYMBOL(sclp_has_siif);
+
+unsigned int sclp_get_ibc(void)
+{
+ return sclp_ibc;
+}
+EXPORT_SYMBOL(sclp_get_ibc);
+
/*
* This function will be called after sclp_facilities_detect(), which gets
* called from early.c code. The sclp_facilities_detect() function retrieves
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c
index 3d8e4d6..1884653 100644
--- a/drivers/s390/char/zcore.c
+++ b/drivers/s390/char/zcore.c
@@ -17,6 +17,8 @@
#include <linux/miscdevice.h>
#include <linux/debugfs.h>
#include <linux/module.h>
+#include <linux/memblock.h>
+
#include <asm/asm-offsets.h>
#include <asm/ipl.h>
#include <asm/sclp.h>
@@ -411,33 +413,24 @@ static ssize_t zcore_memmap_read(struct file *filp, char __user *buf,
size_t count, loff_t *ppos)
{
return simple_read_from_buffer(buf, count, ppos, filp->private_data,
- MEMORY_CHUNKS * CHUNK_INFO_SIZE);
+ memblock.memory.cnt * CHUNK_INFO_SIZE);
}
static int zcore_memmap_open(struct inode *inode, struct file *filp)
{
- int i;
+ struct memblock_region *reg;
char *buf;
- struct mem_chunk *chunk_array;
+ int i = 0;
- chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
- GFP_KERNEL);
- if (!chunk_array)
- return -ENOMEM;
- detect_memory_layout(chunk_array, 0);
- buf = kzalloc(MEMORY_CHUNKS * CHUNK_INFO_SIZE, GFP_KERNEL);
+ buf = kzalloc(memblock.memory.cnt * CHUNK_INFO_SIZE, GFP_KERNEL);
if (!buf) {
- kfree(chunk_array);
return -ENOMEM;
}
- for (i = 0; i < MEMORY_CHUNKS; i++) {
- sprintf(buf + (i * CHUNK_INFO_SIZE), "%016llx %016llx ",
- (unsigned long long) chunk_array[i].addr,
- (unsigned long long) chunk_array[i].size);
- if (chunk_array[i].size == 0)
- break;
+ for_each_memblock(memory, reg) {
+ sprintf(buf + (i++ * CHUNK_INFO_SIZE), "%016llx %016llx ",
+ (unsigned long long) reg->base,
+ (unsigned long long) reg->size);
}
- kfree(chunk_array);
filp->private_data = buf;
return nonseekable_open(inode, filp);
}
@@ -593,21 +586,12 @@ static int __init check_sdias(void)
static int __init get_mem_info(unsigned long *mem, unsigned long *end)
{
- int i;
- struct mem_chunk *chunk_array;
+ struct memblock_region *reg;
- chunk_array = kzalloc(MEMORY_CHUNKS * sizeof(struct mem_chunk),
- GFP_KERNEL);
- if (!chunk_array)
- return -ENOMEM;
- detect_memory_layout(chunk_array, 0);
- for (i = 0; i < MEMORY_CHUNKS; i++) {
- if (chunk_array[i].size == 0)
- break;
- *mem += chunk_array[i].size;
- *end = max(*end, chunk_array[i].addr + chunk_array[i].size);
+ for_each_memblock(memory, reg) {
+ *mem += reg->size;
+ *end = max_t(unsigned long, *end, reg->base + reg->size);
}
- kfree(chunk_array);
return 0;
}
diff --git a/drivers/s390/cio/ccwreq.c b/drivers/s390/cio/ccwreq.c
index 5156264..07676c2 100644
--- a/drivers/s390/cio/ccwreq.c
+++ b/drivers/s390/cio/ccwreq.c
@@ -46,7 +46,7 @@ static u16 ccwreq_next_path(struct ccw_device *cdev)
goto out;
}
req->retries = req->maxretries;
- req->mask = lpm_adjust(req->mask >>= 1, req->lpm);
+ req->mask = lpm_adjust(req->mask >> 1, req->lpm);
out:
return req->mask;
}
@@ -252,7 +252,7 @@ static void ccwreq_log_status(struct ccw_device *cdev, enum io_status status)
*/
void ccw_request_handler(struct ccw_device *cdev)
{
- struct irb *irb = (struct irb *)&S390_lowcore.irb;
+ struct irb *irb = &__get_cpu_var(cio_irb);
struct ccw_request *req = &cdev->private->req;
enum io_status status;
int rc = -EOPNOTSUPP;
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c
index 6c440d4..d497aa0 100644
--- a/drivers/s390/cio/chp.c
+++ b/drivers/s390/cio/chp.c
@@ -509,7 +509,7 @@ out:
* On success return a newly allocated copy of the channel-path description
* data associated with the given channel-path ID. Return %NULL on error.
*/
-void *chp_get_chp_desc(struct chp_id chpid)
+struct channel_path_desc *chp_get_chp_desc(struct chp_id chpid)
{
struct channel_path *chp;
struct channel_path_desc *desc;
diff --git a/drivers/s390/cio/chp.h b/drivers/s390/cio/chp.h
index 9284b78..4efd5b8 100644
--- a/drivers/s390/cio/chp.h
+++ b/drivers/s390/cio/chp.h
@@ -60,7 +60,7 @@ static inline struct channel_path *chpid_to_chp(struct chp_id chpid)
int chp_get_status(struct chp_id chpid);
u8 chp_get_sch_opm(struct subchannel *sch);
int chp_is_registered(struct chp_id chpid);
-void *chp_get_chp_desc(struct chp_id chpid);
+struct channel_path_desc *chp_get_chp_desc(struct chp_id chpid);
void chp_remove_cmg_attr(struct channel_path *chp);
int chp_add_cmg_attr(struct channel_path *chp);
int chp_update_desc(struct channel_path *chp);
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h
index 7e53a9c..76c9b50 100644
--- a/drivers/s390/cio/chsc.h
+++ b/drivers/s390/cio/chsc.h
@@ -21,17 +21,6 @@ struct cmg_entry {
u32 values[NR_MEASUREMENT_ENTRIES];
} __attribute__ ((packed));
-struct channel_path_desc {
- u8 flags;
- u8 lsn;
- u8 desc;
- u8 chpid;
- u8 swla;
- u8 zeroes;
- u8 chla;
- u8 chpp;
-} __attribute__ ((packed));
-
struct channel_path_desc_fmt1 {
u8 flags;
u8 lsn;
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 1d3661a..3d22d2a 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -58,7 +58,7 @@ static void chsc_subchannel_irq(struct subchannel *sch)
{
struct chsc_private *private = dev_get_drvdata(&sch->dev);
struct chsc_request *request = private->request;
- struct irb *irb = (struct irb *)&S390_lowcore.irb;
+ struct irb *irb = &__get_cpu_var(cio_irb);
CHSC_LOG(4, "irb");
CHSC_LOG_HEX(4, irb, sizeof(*irb));
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 9e058c4..77f9c92d 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -46,6 +46,9 @@ debug_info_t *cio_debug_msg_id;
debug_info_t *cio_debug_trace_id;
debug_info_t *cio_debug_crw_id;
+DEFINE_PER_CPU_ALIGNED(struct irb, cio_irb);
+EXPORT_PER_CPU_SYMBOL(cio_irb);
+
/*
* Function: cio_debug_init
* Initializes three debug logs for common I/O:
@@ -560,7 +563,7 @@ static irqreturn_t do_cio_interrupt(int irq, void *dummy)
__this_cpu_write(s390_idle.nohz_delay, 1);
tpi_info = (struct tpi_info *) &get_irq_regs()->int_code;
- irb = (struct irb *) &S390_lowcore.irb;
+ irb = &__get_cpu_var(cio_irb);
sch = (struct subchannel *)(unsigned long) tpi_info->intparm;
if (!sch) {
/* Clear pending interrupt condition. */
@@ -609,7 +612,7 @@ void cio_tsch(struct subchannel *sch)
struct irb *irb;
int irq_context;
- irb = (struct irb *)&S390_lowcore.irb;
+ irb = &__get_cpu_var(cio_irb);
/* Store interrupt response block to lowcore. */
if (tsch(sch->schid, irb) != 0)
/* Not status pending or not operational. */
@@ -746,7 +749,7 @@ __clear_io_subchannel_easy(struct subchannel_id schid)
struct tpi_info ti;
if (tpi(&ti)) {
- tsch(ti.schid, (struct irb *)&S390_lowcore.irb);
+ tsch(ti.schid, &__get_cpu_var(cio_irb));
if (schid_equal(&ti.schid, &schid))
return 0;
}
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h
index d42f674..a01376a 100644
--- a/drivers/s390/cio/cio.h
+++ b/drivers/s390/cio/cio.h
@@ -102,6 +102,8 @@ struct subchannel {
struct schib_config config;
} __attribute__ ((aligned(8)));
+DECLARE_PER_CPU(struct irb, cio_irb);
+
#define to_subchannel(n) container_of(n, struct subchannel, dev)
extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c
index c7638c5..0bc902b 100644
--- a/drivers/s390/cio/device_fsm.c
+++ b/drivers/s390/cio/device_fsm.c
@@ -739,7 +739,7 @@ ccw_device_irq(struct ccw_device *cdev, enum dev_event dev_event)
struct irb *irb;
int is_cmd;
- irb = (struct irb *)&S390_lowcore.irb;
+ irb = &__get_cpu_var(cio_irb);
is_cmd = !scsw_is_tm(&irb->scsw);
/* Check for unsolicited interrupt. */
if (!scsw_is_solicited(&irb->scsw)) {
@@ -805,7 +805,7 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event)
{
struct irb *irb;
- irb = (struct irb *)&S390_lowcore.irb;
+ irb = &__get_cpu_var(cio_irb);
/* Check for unsolicited interrupt. */
if (scsw_stctl(&irb->scsw) ==
(SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)) {
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c
index 4845d64..f3c4179 100644
--- a/drivers/s390/cio/device_ops.c
+++ b/drivers/s390/cio/device_ops.c
@@ -563,14 +563,23 @@ out_unlock:
return rc;
}
-void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no)
+/**
+ * chp_get_chp_desc - return newly allocated channel-path descriptor
+ * @cdev: device to obtain the descriptor for
+ * @chp_idx: index of the channel path
+ *
+ * On success return a newly allocated copy of the channel-path description
+ * data associated with the given channel path. Return %NULL on error.
+ */
+struct channel_path_desc *ccw_device_get_chp_desc(struct ccw_device *cdev,
+ int chp_idx)
{
struct subchannel *sch;
struct chp_id chpid;
sch = to_subchannel(cdev->dev.parent);
chp_id_init(&chpid);
- chpid.id = sch->schib.pmcw.chpid[chp_no];
+ chpid.id = sch->schib.pmcw.chpid[chp_idx];
return chp_get_chp_desc(chpid);
}
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index 3a2ee4a..c4f7bf3 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -134,7 +134,7 @@ static void eadm_subchannel_irq(struct subchannel *sch)
{
struct eadm_private *private = get_eadm_private(sch);
struct eadm_scsw *scsw = &sch->schib.scsw.eadm;
- struct irb *irb = (struct irb *)&S390_lowcore.irb;
+ struct irb *irb = &__get_cpu_var(cio_irb);
int error = 0;
EADM_LOG(6, "irq");
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index ab3baa7..8eec165 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -1803,7 +1803,7 @@ static int ap_poll_thread(void *data)
int requests;
struct ap_device *ap_dev;
- set_user_nice(current, 19);
+ set_user_nice(current, MAX_NICE);
while (1) {
if (ap_suspend_flag)
return 0;
diff --git a/drivers/s390/kvm/virtio_ccw.c b/drivers/s390/kvm/virtio_ccw.c
index 1e1fc67..d2c0b44 100644
--- a/drivers/s390/kvm/virtio_ccw.c
+++ b/drivers/s390/kvm/virtio_ccw.c
@@ -27,6 +27,7 @@
#include <linux/module.h>
#include <linux/io.h>
#include <linux/kvm_para.h>
+#include <linux/notifier.h>
#include <asm/setup.h>
#include <asm/irq.h>
#include <asm/cio.h>
@@ -62,6 +63,7 @@ struct virtio_ccw_device {
struct vq_config_block *config_block;
bool is_thinint;
bool going_away;
+ bool device_lost;
void *airq_info;
};
@@ -1010,11 +1012,14 @@ static void virtio_ccw_remove(struct ccw_device *cdev)
unsigned long flags;
struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev);
- if (vcdev && cdev->online)
+ if (vcdev && cdev->online) {
+ if (vcdev->device_lost)
+ virtio_break_device(&vcdev->vdev);
unregister_virtio_device(&vcdev->vdev);
- spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
- dev_set_drvdata(&cdev->dev, NULL);
- spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ dev_set_drvdata(&cdev->dev, NULL);
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
+ }
cdev->handler = NULL;
}
@@ -1023,12 +1028,14 @@ static int virtio_ccw_offline(struct ccw_device *cdev)
unsigned long flags;
struct virtio_ccw_device *vcdev = virtio_grab_drvdata(cdev);
- if (vcdev) {
- unregister_virtio_device(&vcdev->vdev);
- spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
- dev_set_drvdata(&cdev->dev, NULL);
- spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
- }
+ if (!vcdev)
+ return 0;
+ if (vcdev->device_lost)
+ virtio_break_device(&vcdev->vdev);
+ unregister_virtio_device(&vcdev->vdev);
+ spin_lock_irqsave(get_ccwdev_lock(cdev), flags);
+ dev_set_drvdata(&cdev->dev, NULL);
+ spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags);
return 0;
}
@@ -1096,8 +1103,26 @@ out_free:
static int virtio_ccw_cio_notify(struct ccw_device *cdev, int event)
{
- /* TODO: Check whether we need special handling here. */
- return 0;
+ int rc;
+ struct virtio_ccw_device *vcdev = dev_get_drvdata(&cdev->dev);
+
+ /*
+ * Make sure vcdev is set
+ * i.e. set_offline/remove callback not already running
+ */
+ if (!vcdev)
+ return NOTIFY_DONE;
+
+ switch (event) {
+ case CIO_GONE:
+ vcdev->device_lost = true;
+ rc = NOTIFY_DONE;
+ break;
+ default:
+ rc = NOTIFY_DONE;
+ break;
+ }
+ return rc;
}
static struct ccw_device_id virtio_ids[] = {
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 18ddb24..f54bec5 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -23,6 +23,7 @@
#include <net/dsfield.h>
#include <asm/ebcdic.h>
+#include <asm/chpid.h>
#include <asm/io.h>
#include <asm/sysinfo.h>
#include <asm/compat.h>
@@ -1345,16 +1346,7 @@ static void qeth_set_multiple_write_queues(struct qeth_card *card)
static void qeth_update_from_chp_desc(struct qeth_card *card)
{
struct ccw_device *ccwdev;
- struct channelPath_dsc {
- u8 flags;
- u8 lsn;
- u8 desc;
- u8 chpid;
- u8 swla;
- u8 zeroes;
- u8 chla;
- u8 chpp;
- } *chp_dsc;
+ struct channel_path_desc *chp_dsc;
QETH_DBF_TEXT(SETUP, 2, "chp_desc");
OpenPOWER on IntegriCloud