diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-03-31 17:35:30 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-03-31 17:35:30 -0400 |
| commit | 1f8c538ed6a3323b06c2459e9ca36e0ae8bb0ebc (patch) | |
| tree | 852cfd52103939d2ddcba38f4f1c34b9da258d97 /drivers/s390/cio | |
| parent | 190f918660a69d1c56fd05dc8c6cbb8336a8a0af (diff) | |
| parent | 233faec97a1dfef1f4bc271f9e5d33f2ba4845ca (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.c | 66 | ||||
| -rw-r--r-- | drivers/s390/cio/chsc_sch.c | 3 | ||||
| -rw-r--r-- | drivers/s390/cio/cio.c | 4 | ||||
| -rw-r--r-- | drivers/s390/cio/device.c | 52 |
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) | |||
| 186 | EXPORT_SYMBOL(airq_iv_release); | 186 | EXPORT_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 | */ |
| 195 | unsigned long airq_iv_alloc_bit(struct airq_iv *iv) | 197 | unsigned 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 | } |
| 213 | EXPORT_SYMBOL(airq_iv_alloc_bit); | 225 | EXPORT_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 | */ |
| 220 | void airq_iv_free_bit(struct airq_iv *iv, unsigned long bit) | 233 | void 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 | } |
| 237 | EXPORT_SYMBOL(airq_iv_free_bit); | 253 | EXPORT_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 | ||
| 174 | static int __init chsc_init_dbfs(void) | 174 | static 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 | */ |
| 55 | static int __init cio_debug_init(void) | 55 | static 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 | ||
| 1574 | static 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 |
| 1575 | static int ccw_device_console_enable(struct ccw_device *cdev, | 1587 | int __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 | ||
| 1612 | struct ccw_device *ccw_device_probe_console(void) | 1627 | struct 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 | ||
| 1654 | void __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; |
