aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390/cio
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-03-31 17:35:30 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-03-31 17:35:30 -0400
commit1f8c538ed6a3323b06c2459e9ca36e0ae8bb0ebc (patch)
tree852cfd52103939d2ddcba38f4f1c34b9da258d97 /drivers/s390/cio
parent190f918660a69d1c56fd05dc8c6cbb8336a8a0af (diff)
parent233faec97a1dfef1f4bc271f9e5d33f2ba4845ca (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
Pull s390 updates from Martin Schwidefsky: "There are two memory management related changes, the CMMA support for KVM to avoid swap-in of freed pages and the split page table lock for the PMD level. These two come with common code changes in mm/. A fix for the long standing theoretical TLB flush problem, this one comes with a common code change in kernel/sched/. Another set of changes is Heikos uaccess work, included is the initial set of patches with more to come. And fixes and cleanups as usual" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux: (36 commits) s390/con3270: optionally disable auto update s390/mm: remove unecessary parameter from pgste_ipte_notify s390/mm: remove unnecessary parameter from gmap_do_ipte_notify s390/mm: fixing comment so that parameter name match s390/smp: limit number of cpus in possible cpu mask hypfs: Add clarification for "weight_min" attribute s390: update defconfigs s390/ptrace: add support for PTRACE_SINGLEBLOCK s390/perf: make print_debug_cf() static s390/topology: Remove call to update_cpu_masks() s390/compat: remove compat exec domain s390: select CONFIG_TTY for use of tty in unconditional keyboard driver s390/appldata_os: fix cpu array size calculation s390/checksum: remove memset() within csum_partial_copy_from_user() s390/uaccess: remove copy_from_user_real() s390/sclp_early: Return correct HSA block count also for zero s390: add some drivers/subsystems to the MAINTAINERS file s390: improve debug feature usage s390/airq: add support for irq ranges s390/mm: enable split page table lock for PMD level ...
Diffstat (limited to 'drivers/s390/cio')
-rw-r--r--drivers/s390/cio/airq.c66
-rw-r--r--drivers/s390/cio/chsc_sch.c3
-rw-r--r--drivers/s390/cio/cio.c4
-rw-r--r--drivers/s390/cio/device.c52
4 files changed, 76 insertions, 49 deletions
diff --git a/drivers/s390/cio/airq.c b/drivers/s390/cio/airq.c
index f055df0b167f..445564c790f6 100644
--- a/drivers/s390/cio/airq.c
+++ b/drivers/s390/cio/airq.c
@@ -186,55 +186,71 @@ void airq_iv_release(struct airq_iv *iv)
186EXPORT_SYMBOL(airq_iv_release); 186EXPORT_SYMBOL(airq_iv_release);
187 187
188/** 188/**
189 * airq_iv_alloc_bit - allocate an irq bit from an interrupt vector 189 * airq_iv_alloc - allocate irq bits from an interrupt vector
190 * @iv: pointer to an interrupt vector structure 190 * @iv: pointer to an interrupt vector structure
191 * @num: number of consecutive irq bits to allocate
191 * 192 *
192 * Returns the bit number of the allocated irq, or -1UL if no bit 193 * Returns the bit number of the first irq in the allocated block of irqs,
193 * is available or the AIRQ_IV_ALLOC flag has not been specified 194 * or -1UL if no bit is available or the AIRQ_IV_ALLOC flag has not been
195 * specified
194 */ 196 */
195unsigned long airq_iv_alloc_bit(struct airq_iv *iv) 197unsigned long airq_iv_alloc(struct airq_iv *iv, unsigned long num)
196{ 198{
197 unsigned long bit; 199 unsigned long bit, i;
198 200
199 if (!iv->avail) 201 if (!iv->avail || num == 0)
200 return -1UL; 202 return -1UL;
201 spin_lock(&iv->lock); 203 spin_lock(&iv->lock);
202 bit = find_first_bit_inv(iv->avail, iv->bits); 204 bit = find_first_bit_inv(iv->avail, iv->bits);
203 if (bit < iv->bits) { 205 while (bit + num <= iv->bits) {
204 clear_bit_inv(bit, iv->avail); 206 for (i = 1; i < num; i++)
205 if (bit >= iv->end) 207 if (!test_bit_inv(bit + i, iv->avail))
206 iv->end = bit + 1; 208 break;
207 } else 209 if (i >= num) {
210 /* Found a suitable block of irqs */
211 for (i = 0; i < num; i++)
212 clear_bit_inv(bit + i, iv->avail);
213 if (bit + num >= iv->end)
214 iv->end = bit + num + 1;
215 break;
216 }
217 bit = find_next_bit_inv(iv->avail, iv->bits, bit + i + 1);
218 }
219 if (bit + num > iv->bits)
208 bit = -1UL; 220 bit = -1UL;
209 spin_unlock(&iv->lock); 221 spin_unlock(&iv->lock);
210 return bit; 222 return bit;
211 223
212} 224}
213EXPORT_SYMBOL(airq_iv_alloc_bit); 225EXPORT_SYMBOL(airq_iv_alloc);
214 226
215/** 227/**
216 * airq_iv_free_bit - free an irq bit of an interrupt vector 228 * airq_iv_free - free irq bits of an interrupt vector
217 * @iv: pointer to interrupt vector structure 229 * @iv: pointer to interrupt vector structure
218 * @bit: number of the irq bit to free 230 * @bit: number of the first irq bit to free
231 * @num: number of consecutive irq bits to free
219 */ 232 */
220void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) 233void airq_iv_free(struct airq_iv *iv, unsigned long bit, unsigned long num)
221{ 234{
222 if (!iv->avail) 235 unsigned long i;
236
237 if (!iv->avail || num == 0)
223 return; 238 return;
224 spin_lock(&iv->lock); 239 spin_lock(&iv->lock);
225 /* Clear (possibly left over) interrupt bit */ 240 for (i = 0; i < num; i++) {
226 clear_bit_inv(bit, iv->vector); 241 /* Clear (possibly left over) interrupt bit */
227 /* Make the bit position available again */ 242 clear_bit_inv(bit + i, iv->vector);
228 set_bit_inv(bit, iv->avail); 243 /* Make the bit positions available again */
229 if (bit == iv->end - 1) { 244 set_bit_inv(bit + i, iv->avail);
245 }
246 if (bit + num >= iv->end) {
230 /* Find new end of bit-field */ 247 /* Find new end of bit-field */
231 while (--iv->end > 0) 248 while (iv->end > 0 && !test_bit_inv(iv->end - 1, iv->avail))
232 if (!test_bit_inv(iv->end - 1, iv->avail)) 249 iv->end--;
233 break;
234 } 250 }
235 spin_unlock(&iv->lock); 251 spin_unlock(&iv->lock);
236} 252}
237EXPORT_SYMBOL(airq_iv_free_bit); 253EXPORT_SYMBOL(airq_iv_free);
238 254
239/** 255/**
240 * airq_iv_scan - scan interrupt vector for non-zero bits 256 * airq_iv_scan - scan interrupt vector for non-zero bits
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 7b29d0be0ca3..1d3661af7bd8 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -173,8 +173,7 @@ static struct css_driver chsc_subchannel_driver = {
173 173
174static int __init chsc_init_dbfs(void) 174static int __init chsc_init_dbfs(void)
175{ 175{
176 chsc_debug_msg_id = debug_register("chsc_msg", 16, 1, 176 chsc_debug_msg_id = debug_register("chsc_msg", 8, 1, 4 * sizeof(long));
177 16 * sizeof(long));
178 if (!chsc_debug_msg_id) 177 if (!chsc_debug_msg_id)
179 goto out; 178 goto out;
180 debug_register_view(chsc_debug_msg_id, &debug_sprintf_view); 179 debug_register_view(chsc_debug_msg_id, &debug_sprintf_view);
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 8ee88c4ebd83..97c48b38d67d 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -54,7 +54,7 @@ debug_info_t *cio_debug_crw_id;
54 */ 54 */
55static int __init cio_debug_init(void) 55static int __init cio_debug_init(void)
56{ 56{
57 cio_debug_msg_id = debug_register("cio_msg", 16, 1, 16 * sizeof(long)); 57 cio_debug_msg_id = debug_register("cio_msg", 16, 1, 11 * sizeof(long));
58 if (!cio_debug_msg_id) 58 if (!cio_debug_msg_id)
59 goto out_unregister; 59 goto out_unregister;
60 debug_register_view(cio_debug_msg_id, &debug_sprintf_view); 60 debug_register_view(cio_debug_msg_id, &debug_sprintf_view);
@@ -64,7 +64,7 @@ static int __init cio_debug_init(void)
64 goto out_unregister; 64 goto out_unregister;
65 debug_register_view(cio_debug_trace_id, &debug_hex_ascii_view); 65 debug_register_view(cio_debug_trace_id, &debug_hex_ascii_view);
66 debug_set_level(cio_debug_trace_id, 2); 66 debug_set_level(cio_debug_trace_id, 2);
67 cio_debug_crw_id = debug_register("cio_crw", 16, 1, 16 * sizeof(long)); 67 cio_debug_crw_id = debug_register("cio_crw", 8, 1, 8 * sizeof(long));
68 if (!cio_debug_crw_id) 68 if (!cio_debug_crw_id)
69 goto out_unregister; 69 goto out_unregister;
70 debug_register_view(cio_debug_crw_id, &debug_sprintf_view); 70 debug_register_view(cio_debug_crw_id, &debug_sprintf_view);
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index e9d783563cbb..d8d9b5b5cc56 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -1571,12 +1571,27 @@ out:
1571 return rc; 1571 return rc;
1572} 1572}
1573 1573
1574static void ccw_device_set_int_class(struct ccw_device *cdev)
1575{
1576 struct ccw_driver *cdrv = cdev->drv;
1577
1578 /* Note: we interpret class 0 in this context as an uninitialized
1579 * field since it translates to a non-I/O interrupt class. */
1580 if (cdrv->int_class != 0)
1581 cdev->private->int_class = cdrv->int_class;
1582 else
1583 cdev->private->int_class = IRQIO_CIO;
1584}
1585
1574#ifdef CONFIG_CCW_CONSOLE 1586#ifdef CONFIG_CCW_CONSOLE
1575static int ccw_device_console_enable(struct ccw_device *cdev, 1587int __init ccw_device_enable_console(struct ccw_device *cdev)
1576 struct subchannel *sch)
1577{ 1588{
1589 struct subchannel *sch = to_subchannel(cdev->dev.parent);
1578 int rc; 1590 int rc;
1579 1591
1592 if (!cdev->drv || !cdev->handler)
1593 return -EINVAL;
1594
1580 io_subchannel_init_fields(sch); 1595 io_subchannel_init_fields(sch);
1581 rc = cio_commit_config(sch); 1596 rc = cio_commit_config(sch);
1582 if (rc) 1597 if (rc)
@@ -1609,12 +1624,11 @@ out_unlock:
1609 return rc; 1624 return rc;
1610} 1625}
1611 1626
1612struct ccw_device *ccw_device_probe_console(void) 1627struct ccw_device * __init ccw_device_create_console(struct ccw_driver *drv)
1613{ 1628{
1614 struct io_subchannel_private *io_priv; 1629 struct io_subchannel_private *io_priv;
1615 struct ccw_device *cdev; 1630 struct ccw_device *cdev;
1616 struct subchannel *sch; 1631 struct subchannel *sch;
1617 int ret;
1618 1632
1619 sch = cio_probe_console(); 1633 sch = cio_probe_console();
1620 if (IS_ERR(sch)) 1634 if (IS_ERR(sch))
@@ -1631,18 +1645,23 @@ struct ccw_device *ccw_device_probe_console(void)
1631 kfree(io_priv); 1645 kfree(io_priv);
1632 return cdev; 1646 return cdev;
1633 } 1647 }
1648 cdev->drv = drv;
1634 set_io_private(sch, io_priv); 1649 set_io_private(sch, io_priv);
1635 ret = ccw_device_console_enable(cdev, sch); 1650 ccw_device_set_int_class(cdev);
1636 if (ret) {
1637 set_io_private(sch, NULL);
1638 put_device(&sch->dev);
1639 put_device(&cdev->dev);
1640 kfree(io_priv);
1641 return ERR_PTR(ret);
1642 }
1643 return cdev; 1651 return cdev;
1644} 1652}
1645 1653
1654void __init ccw_device_destroy_console(struct ccw_device *cdev)
1655{
1656 struct subchannel *sch = to_subchannel(cdev->dev.parent);
1657 struct io_subchannel_private *io_priv = to_io_private(sch);
1658
1659 set_io_private(sch, NULL);
1660 put_device(&sch->dev);
1661 put_device(&cdev->dev);
1662 kfree(io_priv);
1663}
1664
1646/** 1665/**
1647 * ccw_device_wait_idle() - busy wait for device to become idle 1666 * ccw_device_wait_idle() - busy wait for device to become idle
1648 * @cdev: ccw device 1667 * @cdev: ccw device
@@ -1726,15 +1745,8 @@ ccw_device_probe (struct device *dev)
1726 int ret; 1745 int ret;
1727 1746
1728 cdev->drv = cdrv; /* to let the driver call _set_online */ 1747 cdev->drv = cdrv; /* to let the driver call _set_online */
1729 /* Note: we interpret class 0 in this context as an uninitialized 1748 ccw_device_set_int_class(cdev);
1730 * field since it translates to a non-I/O interrupt class. */
1731 if (cdrv->int_class != 0)
1732 cdev->private->int_class = cdrv->int_class;
1733 else
1734 cdev->private->int_class = IRQIO_CIO;
1735
1736 ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV; 1749 ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV;
1737
1738 if (ret) { 1750 if (ret) {
1739 cdev->drv = NULL; 1751 cdev->drv = NULL;
1740 cdev->private->int_class = IRQIO_CIO; 1752 cdev->private->int_class = IRQIO_CIO;