11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * S/390 common I/O routines -- low level i/o calls 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 4a53c8fab3f87c995c30ac226a03af95361243144Heiko Carstens * Copyright IBM Corp. 1999, 2008 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author(s): Ingo Adlung (adlung@de.ibm.com) 64ce3b30cf32c5c078518f0f3e6623bcb6eee9872Cornelia Huck * Cornelia Huck (cornelia.huck@de.ibm.com) 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Arnd Bergmann (arndb@de.ibm.com) 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Martin Schwidefsky (schwidefsky@de.ibm.com) 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 11e6d5a428e01b1387852f17b3dd7934239a0be0d4Michael Ernst#define KMSG_COMPONENT "cio" 12e6d5a428e01b1387852f17b3dd7934239a0be0d4Michael Ernst#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 13e6d5a428e01b1387852f17b3dd7934239a0be0d4Michael Ernst 1488dbd2037229bd2ed7543ffd0d8f2d9dec9d31d2Heiko Carstens#include <linux/ftrace.h> 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h> 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h> 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/slab.h> 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h> 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel_stat.h> 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h> 21257ceab7456bd2a2657fd1c689384cabc95e3d30Thomas Gleixner#include <linux/irq.h> 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/cio.h> 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/delay.h> 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h> 255a489b9846f688db7e69aa7ccb23c53459a9c20eHeiko Carstens#include <asm/irq_regs.h> 26e87bfe51b5ca2db99dd680bbb1e8fe3c94b607dfHeiko Carstens#include <asm/setup.h> 2715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens#include <asm/reset.h> 2846b05d2617c8efd8ec6b19acd2c95541a0118c13Michael Holzheu#include <asm/ipl.h> 29e5854a5839fa426a7873f038080f63587de5f1f1Peter Oberparleiter#include <asm/chpid.h> 304e8e56c6713398f417317d449f50c08bf2756c66Peter Oberparleiter#include <asm/airq.h> 313a3fc29a6d0626fb4897b7391c4e956efbacd394Cornelia Huck#include <asm/isc.h> 32bfc3f0281e08066fa8111c3972cff6edc1049864Frederic Weisbecker#include <linux/cputime.h> 3383262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter#include <asm/fcx.h> 34f5daba1d4116d964435ddd99f32b6c80448a496bHeiko Carstens#include <asm/nmi.h> 35f5daba1d4116d964435ddd99f32b6c80448a496bHeiko Carstens#include <asm/crw.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "cio.h" 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "css.h" 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "chsc.h" 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "ioasm.h" 40cd6b4f27b9bb2a6a5ec82b96b87c85421257be6cCornelia Huck#include "io_sch.h" 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "blacklist.h" 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "cio_debug.h" 43e6b6e10ac1de116fc6d2288f185393014851cccfPeter Oberparleiter#include "chp.h" 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdebug_info_t *cio_debug_msg_id; 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdebug_info_t *cio_debug_trace_id; 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdebug_info_t *cio_debug_crw_id; 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 4963aef00b55d37e9fad837a8b38a2c261f0d32041Martin SchwidefskyDEFINE_PER_CPU_ALIGNED(struct irb, cio_irb); 5063aef00b55d37e9fad837a8b38a2c261f0d32041Martin SchwidefskyEXPORT_PER_CPU_SYMBOL(cio_irb); 5163aef00b55d37e9fad837a8b38a2c261f0d32041Martin Schwidefsky 521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function: cio_debug_init 54bc698bcf8897363732226dc9ecba044771679996Cornelia Huck * Initializes three debug logs for common I/O: 55bc698bcf8897363732226dc9ecba044771679996Cornelia Huck * - cio_msg logs generic cio messages 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * - cio_trace logs the calling of different functions 57bc698bcf8897363732226dc9ecba044771679996Cornelia Huck * - cio_crw logs machine check related cio messages 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 59bc698bcf8897363732226dc9ecba044771679996Cornelia Huckstatic int __init cio_debug_init(void) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 61f7e1e65d29636d050cdde0770b9544572959a67dSebastian Ott cio_debug_msg_id = debug_register("cio_msg", 16, 1, 11 * sizeof(long)); 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!cio_debug_msg_id) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_unregister; 64bc698bcf8897363732226dc9ecba044771679996Cornelia Huck debug_register_view(cio_debug_msg_id, &debug_sprintf_view); 65bc698bcf8897363732226dc9ecba044771679996Cornelia Huck debug_set_level(cio_debug_msg_id, 2); 66361f494d4e62ee5f7a971bf34945deeb69392159Peter Tiedemann cio_debug_trace_id = debug_register("cio_trace", 16, 1, 16); 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!cio_debug_trace_id) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_unregister; 69bc698bcf8897363732226dc9ecba044771679996Cornelia Huck debug_register_view(cio_debug_trace_id, &debug_hex_ascii_view); 70bc698bcf8897363732226dc9ecba044771679996Cornelia Huck debug_set_level(cio_debug_trace_id, 2); 71f7e1e65d29636d050cdde0770b9544572959a67dSebastian Ott cio_debug_crw_id = debug_register("cio_crw", 8, 1, 8 * sizeof(long)); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!cio_debug_crw_id) 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto out_unregister; 74bc698bcf8897363732226dc9ecba044771679996Cornelia Huck debug_register_view(cio_debug_crw_id, &debug_sprintf_view); 75bc698bcf8897363732226dc9ecba044771679996Cornelia Huck debug_set_level(cio_debug_crw_id, 4); 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsout_unregister: 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cio_debug_msg_id) 80bc698bcf8897363732226dc9ecba044771679996Cornelia Huck debug_unregister(cio_debug_msg_id); 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cio_debug_trace_id) 82bc698bcf8897363732226dc9ecba044771679996Cornelia Huck debug_unregister(cio_debug_trace_id); 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cio_debug_crw_id) 84bc698bcf8897363732226dc9ecba044771679996Cornelia Huck debug_unregister(cio_debug_crw_id); 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsarch_initcall (cio_debug_init); 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 90c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ottint cio_set_options(struct subchannel *sch, int flags) 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 92c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott struct io_subchannel_private *priv = to_io_private(sch); 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 94c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott priv->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0; 95c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott priv->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0; 96c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott priv->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0; 97c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott return 0; 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1004d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic int 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscio_start_handle_notoper(struct subchannel *sch, __u8 lpm) 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char dbf_text[15]; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (lpm != 0) 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sch->lpm &= ~lpm; 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sch->lpm = 0; 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 110139b83dd57248a3c8fcfb256e562311ad61478e9Michael Ernst CIO_MSG_EVENT(2, "cio_start: 'not oper' status for " 111fb6958a594da49ece869793e6ec163b89fc5f79fCornelia Huck "subchannel 0.%x.%04x!\n", sch->schid.ssid, 112fb6958a594da49ece869793e6ec163b89fc5f79fCornelia Huck sch->schid.sch_no); 113cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott 114cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott if (cio_update_schib(sch)) 115cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott return -ENODEV; 116cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott 1172a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers sprintf(dbf_text, "no%s", dev_name(&sch->dev)); 1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CIO_TRACE_EVENT(0, dbf_text); 1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds CIO_HEX_EVENT(0, &sch->schib, sizeof (struct schib)); 1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (sch->lpm ? -EACCES : -ENODEV); 1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscio_start_key (struct subchannel *sch, /* subchannel structure */ 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct ccw1 * cpa, /* logical channel prog addr */ 1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 lpm, /* logical path mask */ 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u8 key) /* storage key */ 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 130c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott struct io_subchannel_private *priv = to_io_private(sch); 131c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott union orb *orb = &priv->orb; 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ccode; 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 134efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_TRACE_EVENT(5, "stIO"); 135efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_TRACE_EVENT(5, dev_name(&sch->dev)); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1379adb8c1d4f0ac78b3469e377ce5f8a846cbaedafStefan Weinhuber memset(orb, 0, sizeof(union orb)); 1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* sch is always under 2G. */ 13983262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->cmd.intparm = (u32)(addr_t)sch; 14083262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->cmd.fmt = 1; 1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 142c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott orb->cmd.pfch = priv->options.prefetch == 0; 143c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott orb->cmd.spnd = priv->options.suspend; 144c513d07a2df0f7076c1707274e29737f09df3b7fSebastian Ott orb->cmd.ssic = priv->options.suspend && priv->options.inter; 14583262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm; 146347a8dc3b815f0c0fa62a1df075184ffe4cbdcf1Martin Schwidefsky#ifdef CONFIG_64BIT 1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * for 64 bit we always support 64 bit IDAWs with 4k page size only 1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 15083262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->cmd.c64 = 1; 15183262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->cmd.i2k = 0; 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif 15383262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->cmd.key = key >> 4; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* issue "Start Subchannel" */ 15583262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->cmd.cpa = (__u32) __pa(cpa); 156cd6b4f27b9bb2a6a5ec82b96b87c85421257be6cCornelia Huck ccode = ssch(sch->schid, orb); 1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* process condition code */ 159efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_HEX_EVENT(5, &ccode, sizeof(ccode)); 1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ccode) { 1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * initialize device status information 1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 16623d805b647db6c2063a13089497615efa9deacddPeter Oberparleiter sch->schib.scsw.cmd.actl |= SCSW_ACTL_START_PEND; 1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: /* status pending */ 1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: /* busy */ 1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 171c91ebe496120e05301465fff31094bfecf798e9fCornelia Huck case 3: /* device/path not operational */ 1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return cio_start_handle_notoper(sch, lpm); 173c91ebe496120e05301465fff31094bfecf798e9fCornelia Huck default: 174c91ebe496120e05301465fff31094bfecf798e9fCornelia Huck return ccode; 1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscio_start (struct subchannel *sch, struct ccw1 *cpa, __u8 lpm) 1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1810b642ede47969d4180b0922d982777fe64379228Peter Oberparleiter return cio_start_key(sch, cpa, lpm, PAGE_DEFAULT_KEY); 1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * resume suspended I/O operation 1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscio_resume (struct subchannel *sch) 1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ccode; 1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 192efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_TRACE_EVENT(4, "resIO"); 1932a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers CIO_TRACE_EVENT(4, dev_name(&sch->dev)); 1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 195a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck ccode = rsch (sch->schid); 1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 197efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_HEX_EVENT(4, &ccode, sizeof(ccode)); 1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ccode) { 2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 20123d805b647db6c2063a13089497615efa9deacddPeter Oberparleiter sch->schib.scsw.cmd.actl |= SCSW_ACTL_RESUME_PEND; 2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: 2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: 2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: 2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * useless to wait for request completion 2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * as device is no longer operational ! 2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * halt I/O operation 2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscio_halt(struct subchannel *sch) 2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ccode; 2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sch) 2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 227efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_TRACE_EVENT(2, "haltIO"); 2282a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers CIO_TRACE_EVENT(2, dev_name(&sch->dev)); 2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issue "Halt subchannel" and process condition code 2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 233a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck ccode = hsch (sch->schid); 2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 235efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_HEX_EVENT(2, &ccode, sizeof(ccode)); 2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ccode) { 2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 23923d805b647db6c2063a13089497615efa9deacddPeter Oberparleiter sch->schib.scsw.cmd.actl |= SCSW_ACTL_HALT_PEND; 2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: /* status pending */ 2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: /* busy */ 2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: /* device not operational */ 2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Clear I/O operation 2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscio_clear(struct subchannel *sch) 2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ccode; 2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sch) 2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 260efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_TRACE_EVENT(2, "clearIO"); 2612a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers CIO_TRACE_EVENT(2, dev_name(&sch->dev)); 2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issue "Clear subchannel" and process condition code 2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 266a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck ccode = csch (sch->schid); 2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 268efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_HEX_EVENT(2, &ccode, sizeof(ccode)); 2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ccode) { 2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: 27223d805b647db6c2063a13089497615efa9deacddPeter Oberparleiter sch->schib.scsw.cmd.actl |= SCSW_ACTL_CLEAR_PEND; 2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: /* device not operational */ 2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Function: cio_cancel 2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Issues a "Cancel Subchannel" on the specified subchannel 2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Note: We don't need any fancy intparms and flags here 2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * since xsch is executed synchronously. 2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Only for common I/O internal use as for now. 2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint 2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldscio_cancel (struct subchannel *sch) 2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ccode; 2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sch) 2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 294efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_TRACE_EVENT(2, "cancelIO"); 2952a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers CIO_TRACE_EVENT(2, dev_name(&sch->dev)); 2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 297a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck ccode = xsch (sch->schid); 2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 299efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_HEX_EVENT(2, &ccode, sizeof(ccode)); 3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ccode) { 3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 0: /* success */ 3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Update information in scsw. */ 304cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott if (cio_update_schib(sch)) 305cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott return -ENODEV; 3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 1: /* status pending */ 3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds case 2: /* not applicable */ 3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EINVAL; 3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds default: /* not oper */ 3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 31613952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott 31713952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ottstatic void cio_apply_config(struct subchannel *sch, struct schib *schib) 31813952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott{ 31913952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott schib->pmcw.intparm = sch->config.intparm; 32013952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott schib->pmcw.mbi = sch->config.mbi; 32113952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott schib->pmcw.isc = sch->config.isc; 32213952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott schib->pmcw.ena = sch->config.ena; 32313952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott schib->pmcw.mme = sch->config.mme; 32413952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott schib->pmcw.mp = sch->config.mp; 32513952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott schib->pmcw.csense = sch->config.csense; 32613952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott schib->pmcw.mbfc = sch->config.mbfc; 32713952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott if (sch->config.mbfc) 32813952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott schib->mba = sch->config.mba; 32913952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott} 33013952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott 33113952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ottstatic int cio_check_config(struct subchannel *sch, struct schib *schib) 33213952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott{ 33313952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott return (schib->pmcw.intparm == sch->config.intparm) && 33413952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott (schib->pmcw.mbi == sch->config.mbi) && 33513952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott (schib->pmcw.isc == sch->config.isc) && 33613952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott (schib->pmcw.ena == sch->config.ena) && 33713952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott (schib->pmcw.mme == sch->config.mme) && 33813952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott (schib->pmcw.mp == sch->config.mp) && 33913952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott (schib->pmcw.csense == sch->config.csense) && 34013952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott (schib->pmcw.mbfc == sch->config.mbfc) && 34113952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott (!sch->config.mbfc || (schib->mba == sch->config.mba)); 34213952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott} 34313952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott 3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 34513952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott * cio_commit_config - apply configuration to the subchannel 3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 34713952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ottint cio_commit_config(struct subchannel *sch) 3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 34913952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott int ccode, retry, ret = 0; 3501bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott struct schib schib; 3511bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott struct irb irb; 35213952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott 3538821d24cd261aede9b0436cd3252b17a60ccc33aSebastian Ott if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib)) 35413952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott return -ENODEV; 3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (retry = 0; retry < 5; retry++) { 35713952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott /* copy desired changes to local schib */ 35813952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott cio_apply_config(sch, &schib); 35913952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott ccode = msch_err(sch->schid, &schib); 36013952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott if (ccode < 0) /* -EIO if msch gets a program check. */ 3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ccode; 3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds switch (ccode) { 36373ac36ea14fd18ea3dc057e41b16ff31a3c0bd5aColy Li case 0: /* successful */ 3648821d24cd261aede9b0436cd3252b17a60ccc33aSebastian Ott if (stsch_err(sch->schid, &schib) || 36513952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott !css_sch_is_valid(&schib)) 36613952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott return -ENODEV; 36713952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott if (cio_check_config(sch, &schib)) { 36813952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott /* commit changes from local schib */ 36913952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott memcpy(&sch->schib, &schib, sizeof(schib)); 37013952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott return 0; 37113952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott } 37213952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott ret = -EAGAIN; 37313952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott break; 37413952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott case 1: /* status pending */ 3751bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott ret = -EBUSY; 3761bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott if (tsch(sch->schid, &irb)) 3771bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott return ret; 3781bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott break; 37913952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott case 2: /* busy */ 38013952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott udelay(100); /* allow for recovery */ 3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds ret = -EBUSY; 3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 38313952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott case 3: /* not operational */ 3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 39044a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia Huck/** 391cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott * cio_update_schib - Perform stsch and update schib if subchannel is valid. 392cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott * @sch: subchannel on which to perform stsch 393cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott * Return zero on success, -ENODEV otherwise. 394cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott */ 395cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ottint cio_update_schib(struct subchannel *sch) 396cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott{ 397cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott struct schib schib; 398cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott 3998821d24cd261aede9b0436cd3252b17a60ccc33aSebastian Ott if (stsch_err(sch->schid, &schib) || !css_sch_is_valid(&schib)) 400cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott return -ENODEV; 401cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott 402cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott memcpy(&sch->schib, &schib, sizeof(schib)); 403cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott return 0; 404cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott} 405cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian OttEXPORT_SYMBOL_GPL(cio_update_schib); 406cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott 407cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott/** 40844a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia Huck * cio_enable_subchannel - enable a subchannel. 40944a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia Huck * @sch: subchannel to be enabled 41044a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia Huck * @intparm: interruption parameter to set 4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 412edf2209692769d3e461c0351553098bc017c2cafCornelia Huckint cio_enable_subchannel(struct subchannel *sch, u32 intparm) 4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 416efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_TRACE_EVENT(2, "ensch"); 4172a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers CIO_TRACE_EVENT(2, dev_name(&sch->dev)); 4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 419d7b5a4c94f49131811112526f7d404a50f0b5ca7Cornelia Huck if (sch_is_pseudo_sch(sch)) 420d7b5a4c94f49131811112526f7d404a50f0b5ca7Cornelia Huck return -EINVAL; 421cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott if (cio_update_schib(sch)) 4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 42413952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott sch->config.ena = 1; 42513952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott sch->config.isc = sch->isc; 42613952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott sch->config.intparm = intparm; 42713952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott 4281bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott ret = cio_commit_config(sch); 4291bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott if (ret == -EIO) { 4301bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott /* 4311bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott * Got a program check in msch. Try without 4321bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott * the concurrent sense bit the next time. 4331bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott */ 4341bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott sch->config.csense = 0; 43513952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott ret = cio_commit_config(sch); 4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 437efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_HEX_EVENT(2, &ret, sizeof(ret)); 4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 44044a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia HuckEXPORT_SYMBOL_GPL(cio_enable_subchannel); 4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 44244a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia Huck/** 44344a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia Huck * cio_disable_subchannel - disable a subchannel. 44444a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia Huck * @sch: subchannel to disable 4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 44644a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia Huckint cio_disable_subchannel(struct subchannel *sch) 4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ret; 4491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 450efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_TRACE_EVENT(2, "dissch"); 4512a0217d5c7d22d6dd28f8ae5d20b06d24dc426b8Kay Sievers CIO_TRACE_EVENT(2, dev_name(&sch->dev)); 4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 453d7b5a4c94f49131811112526f7d404a50f0b5ca7Cornelia Huck if (sch_is_pseudo_sch(sch)) 454d7b5a4c94f49131811112526f7d404a50f0b5ca7Cornelia Huck return 0; 455cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott if (cio_update_schib(sch)) 4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 45813952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott sch->config.ena = 0; 4591bc8927cc5b57c4d9198e4c4ac6b426b7c7d72c7Sebastian Ott ret = cio_commit_config(sch); 46013952ec12dfeea793ff83c2a96139ed57eb0b897Sebastian Ott 461efd986db2d720e8f6660ec2c292509ee7d28cc6aSebastian Ott CIO_HEX_EVENT(2, &ret, sizeof(ret)); 4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ret; 4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 46444a1c19e3b47a7ac596808177ccd250b95f5e688Cornelia HuckEXPORT_SYMBOL_GPL(cio_disable_subchannel); 4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 466b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huckstatic int cio_check_devno_blacklisted(struct subchannel *sch) 4670ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck{ 4680ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck if (is_blacklisted(sch->schid.ssid, sch->schib.pmcw.dev)) { 4690ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck /* 4700ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck * This device must not be known to Linux. So we simply 4710ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck * say that there is no device and return ENODEV. 4720ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck */ 4730ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck CIO_MSG_EVENT(6, "Blacklisted device detected " 4740ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck "at devno %04X, subchannel set %x\n", 4750ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck sch->schib.pmcw.dev, sch->schid.ssid); 4760ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck return -ENODEV; 4770ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck } 4780ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck return 0; 4790ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck} 4800ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck 481b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huckstatic int cio_validate_io_subchannel(struct subchannel *sch) 482b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck{ 483b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck /* Initialization for io subchannels. */ 484b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck if (!css_sch_is_valid(&sch->schib)) 485b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck return -ENODEV; 486b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck 487b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck /* Devno is valid. */ 488b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck return cio_check_devno_blacklisted(sch); 489b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck} 490b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck 491b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huckstatic int cio_validate_msg_subchannel(struct subchannel *sch) 492b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck{ 493b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck /* Initialization for message subchannels. */ 494b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck if (!css_sch_is_valid(&sch->schib)) 495b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck return -ENODEV; 496b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck 497b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck /* Devno is valid. */ 498b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck return cio_check_devno_blacklisted(sch); 499b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck} 500b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck 5010ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck/** 5020ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck * cio_validate_subchannel - basic validation of subchannel 5030ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck * @sch: subchannel structure to be filled out 5040ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck * @schid: subchannel id 5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Find out subchannel type and initialize struct subchannel. 5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Return codes: 5080ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck * 0 on success 5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * -ENXIO for non-defined subchannels 5100ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck * -ENODEV for invalid subchannels or blacklisted devices 5110ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck * -EIO for subchannels in an invalid subchannel set 5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5130ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huckint cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) 5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds char dbf_txt[15]; 5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int ccode; 5172ec2298412e1ab4674b3780005058d4f0b8bd858Cornelia Huck int err; 5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5190ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck sprintf(dbf_txt, "valsch%x", schid.sch_no); 5200ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck CIO_TRACE_EVENT(4, dbf_txt); 5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* 5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * The first subchannel that is not-operational (ccode==3) 524e5dcf0025d7af58f525590ac86ac27cb44714e8dSebastian Ott * indicates that there aren't any more devices available. 525fb6958a594da49ece869793e6ec163b89fc5f79fCornelia Huck * If stsch gets an exception, it means the current subchannel set 526e5dcf0025d7af58f525590ac86ac27cb44714e8dSebastian Ott * is not valid. 5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 528e5dcf0025d7af58f525590ac86ac27cb44714e8dSebastian Ott ccode = stsch_err(schid, &sch->schib); 5292ec2298412e1ab4674b3780005058d4f0b8bd858Cornelia Huck if (ccode) { 5302ec2298412e1ab4674b3780005058d4f0b8bd858Cornelia Huck err = (ccode == 3) ? -ENXIO : ccode; 5312ec2298412e1ab4674b3780005058d4f0b8bd858Cornelia Huck goto out; 5322ec2298412e1ab4674b3780005058d4f0b8bd858Cornelia Huck } 5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sch->st = sch->schib.pmcw.st; 534e5dcf0025d7af58f525590ac86ac27cb44714e8dSebastian Ott sch->schid = schid; 535c820de39bd083222f5be2563181c87493e436f7cCornelia Huck 5360ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck switch (sch->st) { 5370ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck case SUBCHANNEL_TYPE_IO: 5380ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck err = cio_validate_io_subchannel(sch); 5390ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck break; 540b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck case SUBCHANNEL_TYPE_MSG: 541b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck err = cio_validate_msg_subchannel(sch); 542b3a686f47a3615fcfec0a01c4103c50bb9621369Cornelia Huck break; 5430ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck default: 5440ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck err = 0; 5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 5460ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck if (err) 547808e48882316dd4a325cd1cc382516945edad77dMichael Ernst goto out; 548808e48882316dd4a325cd1cc382516945edad77dMichael Ernst 5490ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck CIO_MSG_EVENT(4, "Subchannel 0.%x.%04x reports subchannel type %04X\n", 5500ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck sch->schid.ssid, sch->schid.sch_no, sch->st); 5512ec2298412e1ab4674b3780005058d4f0b8bd858Cornelia Huckout: 5522ec2298412e1ab4674b3780005058d4f0b8bd858Cornelia Huck return err; 5531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* 5561f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky * do_cio_interrupt() handles all normal I/O device IRQ's 5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 5581f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefskystatic irqreturn_t do_cio_interrupt(int irq, void *dummy) 5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 5601f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky struct tpi_info *tpi_info; 5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct subchannel *sch; 5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct irb *irb; 5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 564fe0f49768d807a8fe6336b097feb8c4441951710Martin Schwidefsky set_cpu_flag(CIF_NOHZ_DELAY); 5651f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; 5660bf7fcf155160fd483af7ffdc50efd4be96f1c96Christoph Lameter irb = this_cpu_ptr(&cio_irb); 56748f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky sch = (struct subchannel *)(unsigned long) tpi_info->intparm; 56848f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky if (!sch) { 56948f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky /* Clear pending interrupt condition. */ 57048f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky inc_irq_stat(IRQIO_CIO); 57148f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky tsch(tpi_info->schid, irb); 5721f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky return IRQ_HANDLED; 57348f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky } 57448f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky spin_lock(sch->lock); 57548f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky /* Store interrupt response block to lowcore. */ 57648f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky if (tsch(tpi_info->schid, irb) == 0) { 57748f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky /* Keep subchannel information word up to date. */ 57848f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky memcpy (&sch->schib.scsw, &irb->scsw, sizeof (irb->scsw)); 57948f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky /* Call interrupt handler if there is one. */ 58048f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky if (sch->driver && sch->driver->irq) 58148f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky sch->driver->irq(sch); 58248f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky else 583420f42ecf48a926ba775ec7d7294425f004b6adeHeiko Carstens inc_irq_stat(IRQIO_CIO); 58448f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky } else 58548f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky inc_irq_stat(IRQIO_CIO); 58648f6b00c6e3190b786c44731b25ac124c81c2247Martin Schwidefsky spin_unlock(sch->lock); 5871f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky 5881f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky return IRQ_HANDLED; 5891f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky} 5901f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky 5911f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefskystatic struct irqaction io_interrupt = { 5921f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky .name = "IO", 5931f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky .handler = do_cio_interrupt, 5941f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky}; 5951f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky 5961f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefskyvoid __init init_cio_interrupts(void) 5971f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky{ 5981f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky irq_set_chip_and_handler(IO_INTERRUPT, 5991f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky &dummy_irq_chip, handle_percpu_irq); 6001f44a225777e40fd9a945b09f958052c47494e1eMartin Schwidefsky setup_irq(IO_INTERRUPT, &io_interrupt); 6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef CONFIG_CCW_CONSOLE 604863fc8492734822b95671780db803cd9a4b7d923Sebastian Ottstatic struct subchannel *console_sch; 605dbe33fc9ad0cd965afe71cd6fca9539afd704e38Sebastian Ottstatic struct lock_class_key console_sch_key; 6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 607191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens/* 608b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky * Use cio_tsch to update the subchannel status and call the interrupt handler 609188561a462d3b82451d6ba09e2e32c9ba2c9938cSebastian Ott * if status had been pending. Called with the subchannel's lock held. 610191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens */ 611188561a462d3b82451d6ba09e2e32c9ba2c9938cSebastian Ottvoid cio_tsch(struct subchannel *sch) 612191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens{ 613191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens struct irb *irb; 614191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens int irq_context; 615191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens 6160bf7fcf155160fd483af7ffdc50efd4be96f1c96Christoph Lameter irb = this_cpu_ptr(&cio_irb); 617191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens /* Store interrupt response block to lowcore. */ 618b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky if (tsch(sch->schid, irb) != 0) 619191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens /* Not status pending or not operational. */ 620b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky return; 621b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky memcpy(&sch->schib.scsw, &irb->scsw, sizeof(union scsw)); 622b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky /* Call interrupt handler with updated status. */ 623191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens irq_context = in_interrupt(); 624b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky if (!irq_context) { 625191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens local_bh_disable(); 626b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky irq_enter(); 627b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky } 628bc5dfcff65f24f15567f766d8bd081d594ef8cc2Thomas Gleixner kstat_incr_irq_this_cpu(IO_INTERRUPT); 629191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens if (sch->driver && sch->driver->irq) 630191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens sch->driver->irq(sch); 631de400d6b78d15a73023485f050bc6b1709dc7a79Peter Oberparleiter else 632420f42ecf48a926ba775ec7d7294425f004b6adeHeiko Carstens inc_irq_stat(IRQIO_CIO); 633b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky if (!irq_context) { 634b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky irq_exit(); 635191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens _local_bh_enable(); 636b603d258a43b4e7339660bdd3b5c25eacd603e54Martin Schwidefsky } 637191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens} 638191fd44c11e10daf9d2cabd16935952e9c735949Heiko Carstens 639863fc8492734822b95671780db803cd9a4b7d923Sebastian Ottstatic int cio_test_for_console(struct subchannel_id schid, void *data) 640cd6b4f27b9bb2a6a5ec82b96b87c85421257be6cCornelia Huck{ 641863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott struct schib schib; 642cd6b4f27b9bb2a6a5ec82b96b87c85421257be6cCornelia Huck 643863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott if (stsch_err(schid, &schib) != 0) 644f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck return -ENXIO; 645863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv && 646863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott (schib.pmcw.dev == console_devno)) { 647f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck console_irq = schid.sch_no; 648f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck return 1; /* found */ 649f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck } 650f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck return 0; 651f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck} 652f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck 653863fc8492734822b95671780db803cd9a4b7d923Sebastian Ottstatic int cio_get_console_sch_no(void) 6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 655a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck struct subchannel_id schid; 656863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott struct schib schib; 657863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott 658a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck init_subchannel_id(&schid); 6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (console_irq != -1) { 6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* VM provided us with the irq number of the console. */ 661a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck schid.sch_no = console_irq; 662863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott if (stsch_err(schid, &schib) != 0 || 663863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott (schib.pmcw.st != SUBCHANNEL_TYPE_IO) || !schib.pmcw.dnv) 6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -1; 665863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott console_devno = schib.pmcw.dev; 6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } else if (console_devno != -1) { 6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* At least the console device number is known. */ 668f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck for_each_subchannel(cio_test_for_console, NULL); 6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return console_irq; 6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 673863fc8492734822b95671780db803cd9a4b7d923Sebastian Ottstruct subchannel *cio_probe_console(void) 6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 675a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck struct subchannel_id schid; 676863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott struct subchannel *sch; 677863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott int sch_no, ret; 6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 679f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck sch_no = cio_get_console_sch_no(); 680f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck if (sch_no == -1) { 681e6d5a428e01b1387852f17b3dd7934239a0be0d4Michael Ernst pr_warning("No CCW console was found\n"); 6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(-ENODEV); 6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 684a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck init_subchannel_id(&schid); 685f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck schid.sch_no = sch_no; 686863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott sch = css_alloc_subchannel(schid); 687863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott if (IS_ERR(sch)) 688863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott return sch; 6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 690dbe33fc9ad0cd965afe71cd6fca9539afd704e38Sebastian Ott lockdep_set_class(sch->lock, &console_sch_key); 6916ef556ccc8fd256259745c4f0d0ab65aaf703824Cornelia Huck isc_register(CONSOLE_ISC); 692863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott sch->config.isc = CONSOLE_ISC; 693863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott sch->config.intparm = (u32)(addr_t)sch; 694863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott ret = cio_commit_config(sch); 6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (ret) { 6966ef556ccc8fd256259745c4f0d0ab65aaf703824Cornelia Huck isc_unregister(CONSOLE_ISC); 697863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott put_device(&sch->dev); 6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return ERR_PTR(ret); 6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 700863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott console_sch = sch; 701863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott return sch; 7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 704863fc8492734822b95671780db803cd9a4b7d923Sebastian Ottint cio_is_console(struct subchannel_id schid) 7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 706863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott if (!console_sch) 7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 708863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott return schid_equal(&schid, &console_sch->schid); 7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 71114556b33f2a5d6a3bc75cd33b709452a31555b25Sebastian Ottvoid cio_register_early_subchannels(void) 7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 71314556b33f2a5d6a3bc75cd33b709452a31555b25Sebastian Ott int ret; 71414556b33f2a5d6a3bc75cd33b709452a31555b25Sebastian Ott 71514556b33f2a5d6a3bc75cd33b709452a31555b25Sebastian Ott if (!console_sch) 71614556b33f2a5d6a3bc75cd33b709452a31555b25Sebastian Ott return; 71714556b33f2a5d6a3bc75cd33b709452a31555b25Sebastian Ott 71814556b33f2a5d6a3bc75cd33b709452a31555b25Sebastian Ott ret = css_register_subchannel(console_sch); 71914556b33f2a5d6a3bc75cd33b709452a31555b25Sebastian Ott if (ret) 72014556b33f2a5d6a3bc75cd33b709452a31555b25Sebastian Ott put_device(&console_sch->dev); 7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 722863fc8492734822b95671780db803cd9a4b7d923Sebastian Ott#endif /* CONFIG_CCW_CONSOLE */ 7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7244d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic int 725a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck__disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) 7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retry, cc; 7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds cc = 0; 7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (retry=0;retry<3;retry++) { 7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds schib->pmcw.ena = 0; 7328821d24cd261aede9b0436cd3252b17a60ccc33aSebastian Ott cc = msch_err(schid, schib); 7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (cc) 7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return (cc==3?-ENODEV:-EBUSY); 7358821d24cd261aede9b0436cd3252b17a60ccc33aSebastian Ott if (stsch_err(schid, schib) || !css_sch_is_valid(schib)) 736cdb912a40df8b8507ab60b3d52f9980c0ba1f44dSebastian Ott return -ENODEV; 7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!schib->pmcw.ena) 7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 7391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; /* uhm... */ 7411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7434d284cac76d0bfebc42d76b428c4e44d921200a9Heiko Carstensstatic int 7440ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck__clear_io_subchannel_easy(struct subchannel_id schid) 7451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 7461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int retry; 7471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (csch(schid)) 7491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -ENODEV; 7501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds for (retry=0;retry<20;retry++) { 7511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct tpi_info ti; 7521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (tpi(&ti)) { 7540bf7fcf155160fd483af7ffdc50efd4be96f1c96Christoph Lameter tsch(ti.schid, this_cpu_ptr(&cio_irb)); 755a8237fc4108060402d904bea5e1062e22e731969Cornelia Huck if (schid_equal(&ti.schid, &schid)) 7564c24da79e29537f0e240a331220a1c46cb9bc085Cornelia Huck return 0; 7571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7585a0d0e65379256b4da2c9092e197a2c761f51c01Heiko Carstens udelay_simple(100); 7591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EBUSY; 7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7639d92a7e1b0d095c8be96ce5e592c6c5541684631Cornelia Huckstatic void __clear_chsc_subchannel_easy(void) 7649d92a7e1b0d095c8be96ce5e592c6c5541684631Cornelia Huck{ 7659d92a7e1b0d095c8be96ce5e592c6c5541684631Cornelia Huck /* It seems we can only wait for a bit here :/ */ 7665a0d0e65379256b4da2c9092e197a2c761f51c01Heiko Carstens udelay_simple(100); 7679d92a7e1b0d095c8be96ce5e592c6c5541684631Cornelia Huck} 7689d92a7e1b0d095c8be96ce5e592c6c5541684631Cornelia Huck 769a45e14148fb34175cba042df8979e7982758635fMichael Holzheustatic int pgm_check_occured; 770a45e14148fb34175cba042df8979e7982758635fMichael Holzheu 771a45e14148fb34175cba042df8979e7982758635fMichael Holzheustatic void cio_reset_pgm_check_handler(void) 772a45e14148fb34175cba042df8979e7982758635fMichael Holzheu{ 773a45e14148fb34175cba042df8979e7982758635fMichael Holzheu pgm_check_occured = 1; 774a45e14148fb34175cba042df8979e7982758635fMichael Holzheu} 775a45e14148fb34175cba042df8979e7982758635fMichael Holzheu 776f9c9fe3ecfc0c5ff17728d0c5ee95a4e269ec190Peter Oberparleiterstatic int stsch_reset(struct subchannel_id schid, struct schib *addr) 777a45e14148fb34175cba042df8979e7982758635fMichael Holzheu{ 778a45e14148fb34175cba042df8979e7982758635fMichael Holzheu int rc; 779a45e14148fb34175cba042df8979e7982758635fMichael Holzheu 780a45e14148fb34175cba042df8979e7982758635fMichael Holzheu pgm_check_occured = 0; 781ab14de6c37fae22911ba99f4171613e6d758050bHeiko Carstens s390_base_pgm_handler_fn = cio_reset_pgm_check_handler; 7828821d24cd261aede9b0436cd3252b17a60ccc33aSebastian Ott rc = stsch_err(schid, addr); 783ab14de6c37fae22911ba99f4171613e6d758050bHeiko Carstens s390_base_pgm_handler_fn = NULL; 784aa77015c4e94cb1d30680646c163d7ae1f93f941Michael Holzheu 785ab14de6c37fae22911ba99f4171613e6d758050bHeiko Carstens /* The program check handler could have changed pgm_check_occured. */ 7866faf4444f2445b068a4f75a86ae81b104c0eed2cHeiko Carstens barrier(); 787aa77015c4e94cb1d30680646c163d7ae1f93f941Michael Holzheu 788a45e14148fb34175cba042df8979e7982758635fMichael Holzheu if (pgm_check_occured) 789a45e14148fb34175cba042df8979e7982758635fMichael Holzheu return -EIO; 790a45e14148fb34175cba042df8979e7982758635fMichael Holzheu else 791a45e14148fb34175cba042df8979e7982758635fMichael Holzheu return rc; 792a45e14148fb34175cba042df8979e7982758635fMichael Holzheu} 793a45e14148fb34175cba042df8979e7982758635fMichael Holzheu 79415e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensstatic int __shutdown_subchannel_easy(struct subchannel_id schid, void *data) 795f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck{ 796f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck struct schib schib; 797f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck 798a45e14148fb34175cba042df8979e7982758635fMichael Holzheu if (stsch_reset(schid, &schib)) 799f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck return -ENXIO; 800f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck if (!schib.pmcw.ena) 801f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck return 0; 802f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck switch(__disable_subchannel_easy(schid, &schib)) { 803f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck case 0: 804f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck case -ENODEV: 805f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck break; 806f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck default: /* -EBUSY */ 8070ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck switch (schib.pmcw.st) { 8080ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck case SUBCHANNEL_TYPE_IO: 8090ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck if (__clear_io_subchannel_easy(schid)) 8100ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck goto out; /* give up... */ 8110ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck break; 8129d92a7e1b0d095c8be96ce5e592c6c5541684631Cornelia Huck case SUBCHANNEL_TYPE_CHSC: 8139d92a7e1b0d095c8be96ce5e592c6c5541684631Cornelia Huck __clear_chsc_subchannel_easy(); 8149d92a7e1b0d095c8be96ce5e592c6c5541684631Cornelia Huck break; 8150ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck default: 8160ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck /* No default clear strategy */ 8170ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck break; 8180ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huck } 8198821d24cd261aede9b0436cd3252b17a60ccc33aSebastian Ott stsch_err(schid, &schib); 820f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck __disable_subchannel_easy(schid, &schib); 821f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck } 8220ae7a7b250bdf7ee87c8346164ef3c47fb79dfbdCornelia Huckout: 823f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck return 0; 824f97a56fb768e5fe9cd07c56ca47870136bb5530cCornelia Huck} 8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 82615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensstatic atomic_t chpid_reset_count; 82715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 82815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensstatic void s390_reset_chpids_mcck_handler(void) 82915e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens{ 83015e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens struct crw crw; 83115e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens struct mci *mci; 83215e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 83315e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Check for pending channel report word. */ 83415e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens mci = (struct mci *)&S390_lowcore.mcck_interruption_code; 83515e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens if (!mci->cp) 83615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens return; 83715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Process channel report words. */ 83815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens while (stcrw(&crw) == 0) { 83915e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Check for responses to RCHP. */ 84015e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens if (crw.slct && crw.rsc == CRW_RSC_CPATH) 84115e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens atomic_dec(&chpid_reset_count); 84215e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens } 84315e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens} 84415e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 84515e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens#define RCHP_TIMEOUT (30 * USEC_PER_SEC) 84615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensstatic void css_reset(void) 84715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens{ 84815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens int i, ret; 84915e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens unsigned long long timeout; 850f86635fad14c4a6810cf0e08488fc9129a3b3b32Peter Oberparleiter struct chp_id chpid; 85115e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 85215e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Reset subchannels. */ 85315e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens for_each_subchannel(__shutdown_subchannel_easy, NULL); 85415e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Reset channel paths. */ 855ab14de6c37fae22911ba99f4171613e6d758050bHeiko Carstens s390_base_mcck_handler_fn = s390_reset_chpids_mcck_handler; 85615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Enable channel report machine checks. */ 85715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens __ctl_set_bit(14, 28); 85815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Temporarily reenable machine checks. */ 85915e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens local_mcck_enable(); 860f86635fad14c4a6810cf0e08488fc9129a3b3b32Peter Oberparleiter chp_id_init(&chpid); 86115e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens for (i = 0; i <= __MAX_CHPID; i++) { 862f86635fad14c4a6810cf0e08488fc9129a3b3b32Peter Oberparleiter chpid.id = i; 863f86635fad14c4a6810cf0e08488fc9129a3b3b32Peter Oberparleiter ret = rchp(chpid); 86415e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens if ((ret == 0) || (ret == 2)) 86515e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* 86615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens * rchp either succeeded, or another rchp is already 86715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens * in progress. In either case, we'll get a crw. 86815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens */ 86915e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens atomic_inc(&chpid_reset_count); 87015e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens } 87115e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Wait for machine check for all channel paths. */ 8728c071b0f19dfa230335d22ce56a8fab5bd20cedcMartin Schwidefsky timeout = get_tod_clock_fast() + (RCHP_TIMEOUT << 12); 87315e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens while (atomic_read(&chpid_reset_count) != 0) { 8748c071b0f19dfa230335d22ce56a8fab5bd20cedcMartin Schwidefsky if (get_tod_clock_fast() > timeout) 87515e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens break; 87615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens cpu_relax(); 87715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens } 87815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Disable machine checks again. */ 87915e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens local_mcck_disable(); 88015e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens /* Disable channel report machine checks. */ 88115e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens __ctl_clear_bit(14, 28); 882ab14de6c37fae22911ba99f4171613e6d758050bHeiko Carstens s390_base_mcck_handler_fn = NULL; 88315e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens} 88415e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 88515e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensstatic struct reset_call css_reset_call = { 88615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens .fn = css_reset, 88715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens}; 88815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 88915e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensstatic int __init init_css_reset_call(void) 89015e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens{ 89115e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens atomic_set(&chpid_reset_count, 0); 89215e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens register_reset_call(&css_reset_call); 89315e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens return 0; 89415e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens} 89515e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 89615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensarch_initcall(init_css_reset_call); 89715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 89815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensstruct sch_match_id { 89915e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens struct subchannel_id schid; 90015e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens struct ccw_dev_id devid; 90115e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens int rc; 90215e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens}; 90315e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 90415e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensstatic int __reipl_subchannel_match(struct subchannel_id schid, void *data) 90515e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens{ 90615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens struct schib schib; 90715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens struct sch_match_id *match_id = data; 90815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 909a45e14148fb34175cba042df8979e7982758635fMichael Holzheu if (stsch_reset(schid, &schib)) 91015e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens return -ENXIO; 911b279a4f56d5476a0b9b0a97397f7a7bbe00b9b2fCornelia Huck if ((schib.pmcw.st == SUBCHANNEL_TYPE_IO) && schib.pmcw.dnv && 91215e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens (schib.pmcw.dev == match_id->devid.devno) && 91315e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens (schid.ssid == match_id->devid.ssid)) { 91415e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens match_id->schid = schid; 91515e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens match_id->rc = 0; 91615e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens return 1; 91715e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens } 91815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens return 0; 91915e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens} 92015e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens 92115e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstensstatic int reipl_find_schid(struct ccw_dev_id *devid, 92215e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens struct subchannel_id *schid) 9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 924ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu struct sch_match_id match_id; 925ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu 926ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu match_id.devid = *devid; 927ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu match_id.rc = -ENODEV; 92815e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens for_each_subchannel(__reipl_subchannel_match, &match_id); 929ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu if (match_id.rc == 0) 930ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu *schid = match_id.schid; 931ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu return match_id.rc; 9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 934ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheuextern void do_reipl_asm(__u32 schid); 935ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu 9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Make sure all subchannels are quiet before we re-ipl an lpar. */ 937ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheuvoid reipl_ccw_dev(struct ccw_dev_id *devid) 9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 93941459d36cf0d57813017dae6080a879cc038e5feHeiko Carstens struct subchannel_id uninitialized_var(schid); 940ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu 94160a0c68df2632feaa4a986af084650d1165d89c5Michael Holzheu s390_reset_system(NULL, NULL); 94215e9b586e0bd3692e2a21c5be178810d9d32214eHeiko Carstens if (reipl_find_schid(devid, &schid) != 0) 943ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu panic("IPL Device not found\n"); 944ff6b8ea68f4b7353f88b97024f28127e2148aa00Michael Holzheu do_reipl_asm(*((__u32*)&schid)); 9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 946e87bfe51b5ca2db99dd680bbb1e8fe3c94b607dfHeiko Carstens 9476fc321fd7dd91f0592f37503219196835314fbb7Heiko Carstensint __init cio_get_iplinfo(struct cio_iplinfo *iplinfo) 948e87bfe51b5ca2db99dd680bbb1e8fe3c94b607dfHeiko Carstens{ 949e87bfe51b5ca2db99dd680bbb1e8fe3c94b607dfHeiko Carstens struct subchannel_id schid; 9506fc321fd7dd91f0592f37503219196835314fbb7Heiko Carstens struct schib schib; 951e87bfe51b5ca2db99dd680bbb1e8fe3c94b607dfHeiko Carstens 952cbb870c8221147ae337612e04b2bb0211f31a74bHeiko Carstens schid = *(struct subchannel_id *)&S390_lowcore.subchannel_id; 953e87bfe51b5ca2db99dd680bbb1e8fe3c94b607dfHeiko Carstens if (!schid.one) 9546fc321fd7dd91f0592f37503219196835314fbb7Heiko Carstens return -ENODEV; 9558821d24cd261aede9b0436cd3252b17a60ccc33aSebastian Ott if (stsch_err(schid, &schib)) 9566fc321fd7dd91f0592f37503219196835314fbb7Heiko Carstens return -ENODEV; 957b279a4f56d5476a0b9b0a97397f7a7bbe00b9b2fCornelia Huck if (schib.pmcw.st != SUBCHANNEL_TYPE_IO) 958b279a4f56d5476a0b9b0a97397f7a7bbe00b9b2fCornelia Huck return -ENODEV; 9596fc321fd7dd91f0592f37503219196835314fbb7Heiko Carstens if (!schib.pmcw.dnv) 9606fc321fd7dd91f0592f37503219196835314fbb7Heiko Carstens return -ENODEV; 9616fc321fd7dd91f0592f37503219196835314fbb7Heiko Carstens iplinfo->devno = schib.pmcw.dev; 9626fc321fd7dd91f0592f37503219196835314fbb7Heiko Carstens iplinfo->is_qdio = schib.pmcw.qf; 9636fc321fd7dd91f0592f37503219196835314fbb7Heiko Carstens return 0; 964e87bfe51b5ca2db99dd680bbb1e8fe3c94b607dfHeiko Carstens} 96583262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter 96683262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter/** 96783262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * cio_tm_start_key - perform start function 96883262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * @sch: subchannel on which to perform the start function 96983262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * @tcw: transport-command word to be started 97083262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * @lpm: mask of paths to use 97183262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * @key: storage key to use for storage access 97283262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * 97383262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * Start the tcw on the given subchannel. Return zero on success, non-zero 97483262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * otherwise. 97583262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter */ 97683262d6349e60b9d10798d489719d80029c00798Peter Oberparleiterint cio_tm_start_key(struct subchannel *sch, struct tcw *tcw, u8 lpm, u8 key) 97783262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter{ 97883262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter int cc; 97983262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter union orb *orb = &to_io_private(sch)->orb; 98083262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter 98183262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter memset(orb, 0, sizeof(union orb)); 98283262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->tm.intparm = (u32) (addr_t) sch; 98383262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->tm.key = key >> 4; 98483262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->tm.b = 1; 98583262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->tm.lpm = lpm ? lpm : sch->lpm; 98683262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter orb->tm.tcw = (u32) (addr_t) tcw; 98783262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter cc = ssch(sch->schid, orb); 98883262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter switch (cc) { 98983262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter case 0: 99083262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter return 0; 99183262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter case 1: 99283262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter case 2: 99383262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter return -EBUSY; 99483262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter default: 99583262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter return cio_start_handle_notoper(sch, lpm); 99683262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter } 99783262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter} 99883262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter 99983262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter/** 100083262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * cio_tm_intrg - perform interrogate function 100183262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * @sch - subchannel on which to perform the interrogate function 100283262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * 100383262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * If the specified subchannel is running in transport-mode, perform the 100483262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter * interrogate function. Return zero on success, non-zero otherwie. 100583262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter */ 100683262d6349e60b9d10798d489719d80029c00798Peter Oberparleiterint cio_tm_intrg(struct subchannel *sch) 100783262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter{ 100883262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter int cc; 100983262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter 101083262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter if (!to_io_private(sch)->orb.tm.b) 101183262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter return -EINVAL; 101283262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter cc = xsch(sch->schid); 101383262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter switch (cc) { 101483262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter case 0: 101583262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter case 2: 101683262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter return 0; 101783262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter case 1: 101883262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter return -EBUSY; 101983262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter default: 102083262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter return -ENODEV; 102183262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter } 102283262d6349e60b9d10798d489719d80029c00798Peter Oberparleiter} 1023