diff options
Diffstat (limited to 'drivers/s390')
40 files changed, 533 insertions, 1240 deletions
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 749836668655..e109da4583a8 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
@@ -669,14 +669,14 @@ static void dasd_profile_end(struct dasd_block *block, | |||
669 | * memory and 2) dasd_smalloc_request uses the static ccw memory | 669 | * memory and 2) dasd_smalloc_request uses the static ccw memory |
670 | * that gets allocated for each device. | 670 | * that gets allocated for each device. |
671 | */ | 671 | */ |
672 | struct dasd_ccw_req *dasd_kmalloc_request(char *magic, int cplength, | 672 | struct dasd_ccw_req *dasd_kmalloc_request(int magic, int cplength, |
673 | int datasize, | 673 | int datasize, |
674 | struct dasd_device *device) | 674 | struct dasd_device *device) |
675 | { | 675 | { |
676 | struct dasd_ccw_req *cqr; | 676 | struct dasd_ccw_req *cqr; |
677 | 677 | ||
678 | /* Sanity checks */ | 678 | /* Sanity checks */ |
679 | BUG_ON( magic == NULL || datasize > PAGE_SIZE || | 679 | BUG_ON(datasize > PAGE_SIZE || |
680 | (cplength*sizeof(struct ccw1)) > PAGE_SIZE); | 680 | (cplength*sizeof(struct ccw1)) > PAGE_SIZE); |
681 | 681 | ||
682 | cqr = kzalloc(sizeof(struct dasd_ccw_req), GFP_ATOMIC); | 682 | cqr = kzalloc(sizeof(struct dasd_ccw_req), GFP_ATOMIC); |
@@ -700,14 +700,13 @@ struct dasd_ccw_req *dasd_kmalloc_request(char *magic, int cplength, | |||
700 | return ERR_PTR(-ENOMEM); | 700 | return ERR_PTR(-ENOMEM); |
701 | } | 701 | } |
702 | } | 702 | } |
703 | strncpy((char *) &cqr->magic, magic, 4); | 703 | cqr->magic = magic; |
704 | ASCEBC((char *) &cqr->magic, 4); | ||
705 | set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 704 | set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
706 | dasd_get_device(device); | 705 | dasd_get_device(device); |
707 | return cqr; | 706 | return cqr; |
708 | } | 707 | } |
709 | 708 | ||
710 | struct dasd_ccw_req *dasd_smalloc_request(char *magic, int cplength, | 709 | struct dasd_ccw_req *dasd_smalloc_request(int magic, int cplength, |
711 | int datasize, | 710 | int datasize, |
712 | struct dasd_device *device) | 711 | struct dasd_device *device) |
713 | { | 712 | { |
@@ -717,7 +716,7 @@ struct dasd_ccw_req *dasd_smalloc_request(char *magic, int cplength, | |||
717 | int size; | 716 | int size; |
718 | 717 | ||
719 | /* Sanity checks */ | 718 | /* Sanity checks */ |
720 | BUG_ON( magic == NULL || datasize > PAGE_SIZE || | 719 | BUG_ON(datasize > PAGE_SIZE || |
721 | (cplength*sizeof(struct ccw1)) > PAGE_SIZE); | 720 | (cplength*sizeof(struct ccw1)) > PAGE_SIZE); |
722 | 721 | ||
723 | size = (sizeof(struct dasd_ccw_req) + 7L) & -8L; | 722 | size = (sizeof(struct dasd_ccw_req) + 7L) & -8L; |
@@ -744,8 +743,7 @@ struct dasd_ccw_req *dasd_smalloc_request(char *magic, int cplength, | |||
744 | cqr->data = data; | 743 | cqr->data = data; |
745 | memset(cqr->data, 0, datasize); | 744 | memset(cqr->data, 0, datasize); |
746 | } | 745 | } |
747 | strncpy((char *) &cqr->magic, magic, 4); | 746 | cqr->magic = magic; |
748 | ASCEBC((char *) &cqr->magic, 4); | ||
749 | set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); | 747 | set_bit(DASD_CQR_FLAGS_USE_ERP, &cqr->flags); |
750 | dasd_get_device(device); | 748 | dasd_get_device(device); |
751 | return cqr; | 749 | return cqr; |
@@ -899,9 +897,6 @@ int dasd_start_IO(struct dasd_ccw_req *cqr) | |||
899 | switch (rc) { | 897 | switch (rc) { |
900 | case 0: | 898 | case 0: |
901 | cqr->status = DASD_CQR_IN_IO; | 899 | cqr->status = DASD_CQR_IN_IO; |
902 | DBF_DEV_EVENT(DBF_DEBUG, device, | ||
903 | "start_IO: request %p started successful", | ||
904 | cqr); | ||
905 | break; | 900 | break; |
906 | case -EBUSY: | 901 | case -EBUSY: |
907 | DBF_DEV_EVENT(DBF_DEBUG, device, "%s", | 902 | DBF_DEV_EVENT(DBF_DEBUG, device, "%s", |
@@ -1699,8 +1694,11 @@ static void __dasd_process_request_queue(struct dasd_block *block) | |||
1699 | * for that. State DASD_STATE_ONLINE is normal block device | 1694 | * for that. State DASD_STATE_ONLINE is normal block device |
1700 | * operation. | 1695 | * operation. |
1701 | */ | 1696 | */ |
1702 | if (basedev->state < DASD_STATE_READY) | 1697 | if (basedev->state < DASD_STATE_READY) { |
1698 | while ((req = blk_fetch_request(block->request_queue))) | ||
1699 | __blk_end_request_all(req, -EIO); | ||
1703 | return; | 1700 | return; |
1701 | } | ||
1704 | /* Now we try to fetch requests from the request queue */ | 1702 | /* Now we try to fetch requests from the request queue */ |
1705 | while (!blk_queue_plugged(queue) && (req = blk_peek_request(queue))) { | 1703 | while (!blk_queue_plugged(queue) && (req = blk_peek_request(queue))) { |
1706 | if (basedev->features & DASD_FEATURE_READONLY && | 1704 | if (basedev->features & DASD_FEATURE_READONLY && |
@@ -2135,9 +2133,9 @@ static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
2135 | struct dasd_device *base; | 2133 | struct dasd_device *base; |
2136 | 2134 | ||
2137 | block = bdev->bd_disk->private_data; | 2135 | block = bdev->bd_disk->private_data; |
2138 | base = block->base; | ||
2139 | if (!block) | 2136 | if (!block) |
2140 | return -ENODEV; | 2137 | return -ENODEV; |
2138 | base = block->base; | ||
2141 | 2139 | ||
2142 | if (!base->discipline || | 2140 | if (!base->discipline || |
2143 | !base->discipline->fill_geometry) | 2141 | !base->discipline->fill_geometry) |
@@ -2530,7 +2528,7 @@ EXPORT_SYMBOL_GPL(dasd_generic_restore_device); | |||
2530 | static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, | 2528 | static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, |
2531 | void *rdc_buffer, | 2529 | void *rdc_buffer, |
2532 | int rdc_buffer_size, | 2530 | int rdc_buffer_size, |
2533 | char *magic) | 2531 | int magic) |
2534 | { | 2532 | { |
2535 | struct dasd_ccw_req *cqr; | 2533 | struct dasd_ccw_req *cqr; |
2536 | struct ccw1 *ccw; | 2534 | struct ccw1 *ccw; |
@@ -2561,7 +2559,7 @@ static struct dasd_ccw_req *dasd_generic_build_rdc(struct dasd_device *device, | |||
2561 | } | 2559 | } |
2562 | 2560 | ||
2563 | 2561 | ||
2564 | int dasd_generic_read_dev_chars(struct dasd_device *device, char *magic, | 2562 | int dasd_generic_read_dev_chars(struct dasd_device *device, int magic, |
2565 | void *rdc_buffer, int rdc_buffer_size) | 2563 | void *rdc_buffer, int rdc_buffer_size) |
2566 | { | 2564 | { |
2567 | int ret; | 2565 | int ret; |
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 27991b692056..e8ff7b0c961d 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
@@ -7,7 +7,7 @@ | |||
7 | * | 7 | * |
8 | */ | 8 | */ |
9 | 9 | ||
10 | #define KMSG_COMPONENT "dasd" | 10 | #define KMSG_COMPONENT "dasd-eckd" |
11 | 11 | ||
12 | #include <linux/timer.h> | 12 | #include <linux/timer.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 5b7bbc87593b..70a008c00522 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Author(s): Stefan Weinhuber <wein@de.ibm.com> | 5 | * Author(s): Stefan Weinhuber <wein@de.ibm.com> |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define KMSG_COMPONENT "dasd" | 8 | #define KMSG_COMPONENT "dasd-eckd" |
9 | 9 | ||
10 | #include <linux/list.h> | 10 | #include <linux/list.h> |
11 | #include <asm/ebcdic.h> | 11 | #include <asm/ebcdic.h> |
@@ -379,8 +379,7 @@ static int read_unit_address_configuration(struct dasd_device *device, | |||
379 | int rc; | 379 | int rc; |
380 | unsigned long flags; | 380 | unsigned long flags; |
381 | 381 | ||
382 | cqr = dasd_kmalloc_request("ECKD", | 382 | cqr = dasd_kmalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */, |
383 | 1 /* PSF */ + 1 /* RSSD */ , | ||
384 | (sizeof(struct dasd_psf_prssd_data)), | 383 | (sizeof(struct dasd_psf_prssd_data)), |
385 | device); | 384 | device); |
386 | if (IS_ERR(cqr)) | 385 | if (IS_ERR(cqr)) |
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 644086ba2ede..4e49b4a6c880 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define KMSG_COMPONENT "dasd" | 11 | #define KMSG_COMPONENT "dasd-diag" |
12 | 12 | ||
13 | #include <linux/stddef.h> | 13 | #include <linux/stddef.h> |
14 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
@@ -523,8 +523,7 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev, | |||
523 | /* Build the request */ | 523 | /* Build the request */ |
524 | datasize = sizeof(struct dasd_diag_req) + | 524 | datasize = sizeof(struct dasd_diag_req) + |
525 | count*sizeof(struct dasd_diag_bio); | 525 | count*sizeof(struct dasd_diag_bio); |
526 | cqr = dasd_smalloc_request(dasd_diag_discipline.name, 0, | 526 | cqr = dasd_smalloc_request(DASD_DIAG_MAGIC, 0, datasize, memdev); |
527 | datasize, memdev); | ||
528 | if (IS_ERR(cqr)) | 527 | if (IS_ERR(cqr)) |
529 | return cqr; | 528 | return cqr; |
530 | 529 | ||
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index c11770f5b368..a1ce573648a2 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -10,7 +10,7 @@ | |||
10 | * Author.........: Nigel Hislop <hislop_nigel@emc.com> | 10 | * Author.........: Nigel Hislop <hislop_nigel@emc.com> |
11 | */ | 11 | */ |
12 | 12 | ||
13 | #define KMSG_COMPONENT "dasd" | 13 | #define KMSG_COMPONENT "dasd-eckd" |
14 | 14 | ||
15 | #include <linux/stddef.h> | 15 | #include <linux/stddef.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
@@ -730,7 +730,8 @@ static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, | |||
730 | struct dasd_ccw_req *cqr; | 730 | struct dasd_ccw_req *cqr; |
731 | struct ccw1 *ccw; | 731 | struct ccw1 *ccw; |
732 | 732 | ||
733 | cqr = dasd_smalloc_request("ECKD", 1 /* RCD */, ciw->count, device); | 733 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* RCD */, ciw->count, |
734 | device); | ||
734 | 735 | ||
735 | if (IS_ERR(cqr)) { | 736 | if (IS_ERR(cqr)) { |
736 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 737 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
@@ -934,8 +935,7 @@ static int dasd_eckd_read_features(struct dasd_device *device) | |||
934 | struct dasd_eckd_private *private; | 935 | struct dasd_eckd_private *private; |
935 | 936 | ||
936 | private = (struct dasd_eckd_private *) device->private; | 937 | private = (struct dasd_eckd_private *) device->private; |
937 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 938 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */, |
938 | 1 /* PSF */ + 1 /* RSSD */ , | ||
939 | (sizeof(struct dasd_psf_prssd_data) + | 939 | (sizeof(struct dasd_psf_prssd_data) + |
940 | sizeof(struct dasd_rssd_features)), | 940 | sizeof(struct dasd_rssd_features)), |
941 | device); | 941 | device); |
@@ -998,7 +998,7 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device, | |||
998 | struct dasd_psf_ssc_data *psf_ssc_data; | 998 | struct dasd_psf_ssc_data *psf_ssc_data; |
999 | struct ccw1 *ccw; | 999 | struct ccw1 *ccw; |
1000 | 1000 | ||
1001 | cqr = dasd_smalloc_request("ECKD", 1 /* PSF */ , | 1001 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ , |
1002 | sizeof(struct dasd_psf_ssc_data), | 1002 | sizeof(struct dasd_psf_ssc_data), |
1003 | device); | 1003 | device); |
1004 | 1004 | ||
@@ -1149,8 +1149,8 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
1149 | goto out_err3; | 1149 | goto out_err3; |
1150 | 1150 | ||
1151 | /* Read Device Characteristics */ | 1151 | /* Read Device Characteristics */ |
1152 | rc = dasd_generic_read_dev_chars(device, "ECKD", &private->rdc_data, | 1152 | rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC, |
1153 | 64); | 1153 | &private->rdc_data, 64); |
1154 | if (rc) { | 1154 | if (rc) { |
1155 | DBF_EVENT(DBF_WARNING, | 1155 | DBF_EVENT(DBF_WARNING, |
1156 | "Read device characteristics failed, rc=%d for " | 1156 | "Read device characteristics failed, rc=%d for " |
@@ -1217,8 +1217,7 @@ dasd_eckd_analysis_ccw(struct dasd_device *device) | |||
1217 | 1217 | ||
1218 | cplength = 8; | 1218 | cplength = 8; |
1219 | datasize = sizeof(struct DE_eckd_data) + 2*sizeof(struct LO_eckd_data); | 1219 | datasize = sizeof(struct DE_eckd_data) + 2*sizeof(struct LO_eckd_data); |
1220 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 1220 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, device); |
1221 | cplength, datasize, device); | ||
1222 | if (IS_ERR(cqr)) | 1221 | if (IS_ERR(cqr)) |
1223 | return cqr; | 1222 | return cqr; |
1224 | ccw = cqr->cpaddr; | 1223 | ccw = cqr->cpaddr; |
@@ -1499,8 +1498,7 @@ dasd_eckd_format_device(struct dasd_device * device, | |||
1499 | return ERR_PTR(-EINVAL); | 1498 | return ERR_PTR(-EINVAL); |
1500 | } | 1499 | } |
1501 | /* Allocate the format ccw request. */ | 1500 | /* Allocate the format ccw request. */ |
1502 | fcp = dasd_smalloc_request(dasd_eckd_discipline.name, | 1501 | fcp = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, device); |
1503 | cplength, datasize, device); | ||
1504 | if (IS_ERR(fcp)) | 1502 | if (IS_ERR(fcp)) |
1505 | return fcp; | 1503 | return fcp; |
1506 | 1504 | ||
@@ -1783,8 +1781,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_single( | |||
1783 | datasize += count*sizeof(struct LO_eckd_data); | 1781 | datasize += count*sizeof(struct LO_eckd_data); |
1784 | } | 1782 | } |
1785 | /* Allocate the ccw request. */ | 1783 | /* Allocate the ccw request. */ |
1786 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 1784 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, |
1787 | cplength, datasize, startdev); | 1785 | startdev); |
1788 | if (IS_ERR(cqr)) | 1786 | if (IS_ERR(cqr)) |
1789 | return cqr; | 1787 | return cqr; |
1790 | ccw = cqr->cpaddr; | 1788 | ccw = cqr->cpaddr; |
@@ -1948,8 +1946,8 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_cmd_track( | |||
1948 | cidaw * sizeof(unsigned long long); | 1946 | cidaw * sizeof(unsigned long long); |
1949 | 1947 | ||
1950 | /* Allocate the ccw request. */ | 1948 | /* Allocate the ccw request. */ |
1951 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 1949 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, cplength, datasize, |
1952 | cplength, datasize, startdev); | 1950 | startdev); |
1953 | if (IS_ERR(cqr)) | 1951 | if (IS_ERR(cqr)) |
1954 | return cqr; | 1952 | return cqr; |
1955 | ccw = cqr->cpaddr; | 1953 | ccw = cqr->cpaddr; |
@@ -2249,8 +2247,7 @@ static struct dasd_ccw_req *dasd_eckd_build_cp_tpm_track( | |||
2249 | 2247 | ||
2250 | /* Allocate the ccw request. */ | 2248 | /* Allocate the ccw request. */ |
2251 | itcw_size = itcw_calc_size(0, ctidaw, 0); | 2249 | itcw_size = itcw_calc_size(0, ctidaw, 0); |
2252 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 2250 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 0, itcw_size, startdev); |
2253 | 0, itcw_size, startdev); | ||
2254 | if (IS_ERR(cqr)) | 2251 | if (IS_ERR(cqr)) |
2255 | return cqr; | 2252 | return cqr; |
2256 | 2253 | ||
@@ -2557,8 +2554,7 @@ dasd_eckd_release(struct dasd_device *device) | |||
2557 | if (!capable(CAP_SYS_ADMIN)) | 2554 | if (!capable(CAP_SYS_ADMIN)) |
2558 | return -EACCES; | 2555 | return -EACCES; |
2559 | 2556 | ||
2560 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 2557 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); |
2561 | 1, 32, device); | ||
2562 | if (IS_ERR(cqr)) { | 2558 | if (IS_ERR(cqr)) { |
2563 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2559 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
2564 | "Could not allocate initialization request"); | 2560 | "Could not allocate initialization request"); |
@@ -2600,8 +2596,7 @@ dasd_eckd_reserve(struct dasd_device *device) | |||
2600 | if (!capable(CAP_SYS_ADMIN)) | 2596 | if (!capable(CAP_SYS_ADMIN)) |
2601 | return -EACCES; | 2597 | return -EACCES; |
2602 | 2598 | ||
2603 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 2599 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); |
2604 | 1, 32, device); | ||
2605 | if (IS_ERR(cqr)) { | 2600 | if (IS_ERR(cqr)) { |
2606 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2601 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
2607 | "Could not allocate initialization request"); | 2602 | "Could not allocate initialization request"); |
@@ -2642,8 +2637,7 @@ dasd_eckd_steal_lock(struct dasd_device *device) | |||
2642 | if (!capable(CAP_SYS_ADMIN)) | 2637 | if (!capable(CAP_SYS_ADMIN)) |
2643 | return -EACCES; | 2638 | return -EACCES; |
2644 | 2639 | ||
2645 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 2640 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1, 32, device); |
2646 | 1, 32, device); | ||
2647 | if (IS_ERR(cqr)) { | 2641 | if (IS_ERR(cqr)) { |
2648 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2642 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
2649 | "Could not allocate initialization request"); | 2643 | "Could not allocate initialization request"); |
@@ -2681,8 +2675,7 @@ dasd_eckd_performance(struct dasd_device *device, void __user *argp) | |||
2681 | struct ccw1 *ccw; | 2675 | struct ccw1 *ccw; |
2682 | int rc; | 2676 | int rc; |
2683 | 2677 | ||
2684 | cqr = dasd_smalloc_request(dasd_eckd_discipline.name, | 2678 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */, |
2685 | 1 /* PSF */ + 1 /* RSSD */ , | ||
2686 | (sizeof(struct dasd_psf_prssd_data) + | 2679 | (sizeof(struct dasd_psf_prssd_data) + |
2687 | sizeof(struct dasd_rssd_perf_stats_t)), | 2680 | sizeof(struct dasd_rssd_perf_stats_t)), |
2688 | device); | 2681 | device); |
@@ -2828,7 +2821,7 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp) | |||
2828 | } | 2821 | } |
2829 | 2822 | ||
2830 | /* setup CCWs for PSF + RSSD */ | 2823 | /* setup CCWs for PSF + RSSD */ |
2831 | cqr = dasd_smalloc_request("ECKD", 2 , 0, device); | 2824 | cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 2 , 0, device); |
2832 | if (IS_ERR(cqr)) { | 2825 | if (IS_ERR(cqr)) { |
2833 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", | 2826 | DBF_DEV_EVENT(DBF_WARNING, device, "%s", |
2834 | "Could not allocate initialization request"); | 2827 | "Could not allocate initialization request"); |
@@ -3254,7 +3247,7 @@ int dasd_eckd_restore_device(struct dasd_device *device) | |||
3254 | 3247 | ||
3255 | /* Read Device Characteristics */ | 3248 | /* Read Device Characteristics */ |
3256 | memset(&private->rdc_data, 0, sizeof(private->rdc_data)); | 3249 | memset(&private->rdc_data, 0, sizeof(private->rdc_data)); |
3257 | rc = dasd_generic_read_dev_chars(device, "ECKD", | 3250 | rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC, |
3258 | &private->rdc_data, 64); | 3251 | &private->rdc_data, 64); |
3259 | if (rc) { | 3252 | if (rc) { |
3260 | DBF_EVENT(DBF_WARNING, | 3253 | DBF_EVENT(DBF_WARNING, |
diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index c24c8c30380d..d96039eae59b 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c | |||
@@ -6,7 +6,7 @@ | |||
6 | * Author(s): Stefan Weinhuber <wein@de.ibm.com> | 6 | * Author(s): Stefan Weinhuber <wein@de.ibm.com> |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #define KMSG_COMPONENT "dasd" | 9 | #define KMSG_COMPONENT "dasd-eckd" |
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
@@ -464,7 +464,7 @@ int dasd_eer_enable(struct dasd_device *device) | |||
464 | if (!device->discipline || strcmp(device->discipline->name, "ECKD")) | 464 | if (!device->discipline || strcmp(device->discipline->name, "ECKD")) |
465 | return -EPERM; /* FIXME: -EMEDIUMTYPE ? */ | 465 | return -EPERM; /* FIXME: -EMEDIUMTYPE ? */ |
466 | 466 | ||
467 | cqr = dasd_kmalloc_request("ECKD", 1 /* SNSS */, | 467 | cqr = dasd_kmalloc_request(DASD_ECKD_MAGIC, 1 /* SNSS */, |
468 | SNSS_DATA_SIZE, device); | 468 | SNSS_DATA_SIZE, device); |
469 | if (IS_ERR(cqr)) | 469 | if (IS_ERR(cqr)) |
470 | return -ENOMEM; | 470 | return -ENOMEM; |
diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c index cb8f9cef7429..7656384a811d 100644 --- a/drivers/s390/block/dasd_erp.c +++ b/drivers/s390/block/dasd_erp.c | |||
@@ -99,8 +99,8 @@ dasd_default_erp_action(struct dasd_ccw_req *cqr) | |||
99 | cqr->lpm = LPM_ANYPATH; | 99 | cqr->lpm = LPM_ANYPATH; |
100 | cqr->status = DASD_CQR_FILLED; | 100 | cqr->status = DASD_CQR_FILLED; |
101 | } else { | 101 | } else { |
102 | dev_err(&device->cdev->dev, | 102 | pr_err("%s: default ERP has run out of retries and failed\n", |
103 | "default ERP has run out of retries and failed\n"); | 103 | dev_name(&device->cdev->dev)); |
104 | cqr->status = DASD_CQR_FAILED; | 104 | cqr->status = DASD_CQR_FAILED; |
105 | cqr->stopclk = get_clock(); | 105 | cqr->stopclk = get_clock(); |
106 | } | 106 | } |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index 31849ad5e59f..f245377e8e27 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -5,7 +5,7 @@ | |||
5 | * Copyright IBM Corp. 1999, 2009 | 5 | * Copyright IBM Corp. 1999, 2009 |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #define KMSG_COMPONENT "dasd" | 8 | #define KMSG_COMPONENT "dasd-fba" |
9 | 9 | ||
10 | #include <linux/stddef.h> | 10 | #include <linux/stddef.h> |
11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
@@ -152,8 +152,8 @@ dasd_fba_check_characteristics(struct dasd_device *device) | |||
152 | block->base = device; | 152 | block->base = device; |
153 | 153 | ||
154 | /* Read Device Characteristics */ | 154 | /* Read Device Characteristics */ |
155 | rc = dasd_generic_read_dev_chars(device, "FBA ", &private->rdc_data, | 155 | rc = dasd_generic_read_dev_chars(device, DASD_FBA_MAGIC, |
156 | 32); | 156 | &private->rdc_data, 32); |
157 | if (rc) { | 157 | if (rc) { |
158 | DBF_EVENT(DBF_WARNING, "Read device characteristics returned " | 158 | DBF_EVENT(DBF_WARNING, "Read device characteristics returned " |
159 | "error %d for device: %s", | 159 | "error %d for device: %s", |
@@ -305,8 +305,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev, | |||
305 | datasize += (count - 1)*sizeof(struct LO_fba_data); | 305 | datasize += (count - 1)*sizeof(struct LO_fba_data); |
306 | } | 306 | } |
307 | /* Allocate the ccw request. */ | 307 | /* Allocate the ccw request. */ |
308 | cqr = dasd_smalloc_request(dasd_fba_discipline.name, | 308 | cqr = dasd_smalloc_request(DASD_FBA_MAGIC, cplength, datasize, memdev); |
309 | cplength, datasize, memdev); | ||
310 | if (IS_ERR(cqr)) | 309 | if (IS_ERR(cqr)) |
311 | return cqr; | 310 | return cqr; |
312 | ccw = cqr->cpaddr; | 311 | ccw = cqr->cpaddr; |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index b699ca356ac5..5e47a1ee52b9 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -59,6 +59,11 @@ | |||
59 | #include <asm/dasd.h> | 59 | #include <asm/dasd.h> |
60 | #include <asm/idals.h> | 60 | #include <asm/idals.h> |
61 | 61 | ||
62 | /* DASD discipline magic */ | ||
63 | #define DASD_ECKD_MAGIC 0xC5C3D2C4 | ||
64 | #define DASD_DIAG_MAGIC 0xC4C9C1C7 | ||
65 | #define DASD_FBA_MAGIC 0xC6C2C140 | ||
66 | |||
62 | /* | 67 | /* |
63 | * SECTION: Type definitions | 68 | * SECTION: Type definitions |
64 | */ | 69 | */ |
@@ -540,9 +545,9 @@ extern struct block_device_operations dasd_device_operations; | |||
540 | extern struct kmem_cache *dasd_page_cache; | 545 | extern struct kmem_cache *dasd_page_cache; |
541 | 546 | ||
542 | struct dasd_ccw_req * | 547 | struct dasd_ccw_req * |
543 | dasd_kmalloc_request(char *, int, int, struct dasd_device *); | 548 | dasd_kmalloc_request(int , int, int, struct dasd_device *); |
544 | struct dasd_ccw_req * | 549 | struct dasd_ccw_req * |
545 | dasd_smalloc_request(char *, int, int, struct dasd_device *); | 550 | dasd_smalloc_request(int , int, int, struct dasd_device *); |
546 | void dasd_kfree_request(struct dasd_ccw_req *, struct dasd_device *); | 551 | void dasd_kfree_request(struct dasd_ccw_req *, struct dasd_device *); |
547 | void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *); | 552 | void dasd_sfree_request(struct dasd_ccw_req *, struct dasd_device *); |
548 | 553 | ||
@@ -587,7 +592,7 @@ void dasd_generic_handle_state_change(struct dasd_device *); | |||
587 | int dasd_generic_pm_freeze(struct ccw_device *); | 592 | int dasd_generic_pm_freeze(struct ccw_device *); |
588 | int dasd_generic_restore_device(struct ccw_device *); | 593 | int dasd_generic_restore_device(struct ccw_device *); |
589 | 594 | ||
590 | int dasd_generic_read_dev_chars(struct dasd_device *, char *, void *, int); | 595 | int dasd_generic_read_dev_chars(struct dasd_device *, int, void *, int); |
591 | char *dasd_get_sense(struct irb *); | 596 | char *dasd_get_sense(struct irb *); |
592 | 597 | ||
593 | /* externals in dasd_devmap.c */ | 598 | /* externals in dasd_devmap.c */ |
diff --git a/drivers/s390/block/dasd_ioctl.c b/drivers/s390/block/dasd_ioctl.c index df918ef27965..f756a1b0c57a 100644 --- a/drivers/s390/block/dasd_ioctl.c +++ b/drivers/s390/block/dasd_ioctl.c | |||
@@ -98,8 +98,8 @@ static int dasd_ioctl_quiesce(struct dasd_block *block) | |||
98 | if (!capable (CAP_SYS_ADMIN)) | 98 | if (!capable (CAP_SYS_ADMIN)) |
99 | return -EACCES; | 99 | return -EACCES; |
100 | 100 | ||
101 | dev_info(&base->cdev->dev, "The DASD has been put in the quiesce " | 101 | pr_info("%s: The DASD has been put in the quiesce " |
102 | "state\n"); | 102 | "state\n", dev_name(&base->cdev->dev)); |
103 | spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); | 103 | spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); |
104 | base->stopped |= DASD_STOPPED_QUIESCE; | 104 | base->stopped |= DASD_STOPPED_QUIESCE; |
105 | spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); | 105 | spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); |
@@ -119,8 +119,8 @@ static int dasd_ioctl_resume(struct dasd_block *block) | |||
119 | if (!capable (CAP_SYS_ADMIN)) | 119 | if (!capable (CAP_SYS_ADMIN)) |
120 | return -EACCES; | 120 | return -EACCES; |
121 | 121 | ||
122 | dev_info(&base->cdev->dev, "I/O operations have been resumed " | 122 | pr_info("%s: I/O operations have been resumed " |
123 | "on the DASD\n"); | 123 | "on the DASD\n", dev_name(&base->cdev->dev)); |
124 | spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); | 124 | spin_lock_irqsave(get_ccwdev_lock(base->cdev), flags); |
125 | base->stopped &= ~DASD_STOPPED_QUIESCE; | 125 | base->stopped &= ~DASD_STOPPED_QUIESCE; |
126 | spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); | 126 | spin_unlock_irqrestore(get_ccwdev_lock(base->cdev), flags); |
@@ -146,8 +146,8 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata) | |||
146 | return -EPERM; | 146 | return -EPERM; |
147 | 147 | ||
148 | if (base->state != DASD_STATE_BASIC) { | 148 | if (base->state != DASD_STATE_BASIC) { |
149 | dev_warn(&base->cdev->dev, | 149 | pr_warning("%s: The DASD cannot be formatted while it is " |
150 | "The DASD cannot be formatted while it is enabled\n"); | 150 | "enabled\n", dev_name(&base->cdev->dev)); |
151 | return -EBUSY; | 151 | return -EBUSY; |
152 | } | 152 | } |
153 | 153 | ||
@@ -175,9 +175,9 @@ static int dasd_format(struct dasd_block *block, struct format_data_t *fdata) | |||
175 | dasd_sfree_request(cqr, cqr->memdev); | 175 | dasd_sfree_request(cqr, cqr->memdev); |
176 | if (rc) { | 176 | if (rc) { |
177 | if (rc != -ERESTARTSYS) | 177 | if (rc != -ERESTARTSYS) |
178 | dev_err(&base->cdev->dev, | 178 | pr_err("%s: Formatting unit %d failed with " |
179 | "Formatting unit %d failed with " | 179 | "rc=%d\n", dev_name(&base->cdev->dev), |
180 | "rc=%d\n", fdata->start_unit, rc); | 180 | fdata->start_unit, rc); |
181 | return rc; | 181 | return rc; |
182 | } | 182 | } |
183 | fdata->start_unit++; | 183 | fdata->start_unit++; |
@@ -204,9 +204,9 @@ dasd_ioctl_format(struct block_device *bdev, void __user *argp) | |||
204 | if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) | 204 | if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) |
205 | return -EFAULT; | 205 | return -EFAULT; |
206 | if (bdev != bdev->bd_contains) { | 206 | if (bdev != bdev->bd_contains) { |
207 | dev_warn(&block->base->cdev->dev, | 207 | pr_warning("%s: The specified DASD is a partition and cannot " |
208 | "The specified DASD is a partition and cannot be " | 208 | "be formatted\n", |
209 | "formatted\n"); | 209 | dev_name(&block->base->cdev->dev)); |
210 | return -EINVAL; | 210 | return -EINVAL; |
211 | } | 211 | } |
212 | return dasd_format(block, &fdata); | 212 | return dasd_format(block, &fdata); |
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index db442cd6621e..ee604e92a5fa 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c | |||
@@ -42,7 +42,6 @@ | |||
42 | #include <linux/suspend.h> | 42 | #include <linux/suspend.h> |
43 | #include <linux/platform_device.h> | 43 | #include <linux/platform_device.h> |
44 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
45 | #include <asm/checksum.h> | ||
46 | 45 | ||
47 | #define XPRAM_NAME "xpram" | 46 | #define XPRAM_NAME "xpram" |
48 | #define XPRAM_DEVS 1 /* one partition */ | 47 | #define XPRAM_DEVS 1 /* one partition */ |
@@ -51,7 +50,6 @@ | |||
51 | typedef struct { | 50 | typedef struct { |
52 | unsigned int size; /* size of xpram segment in pages */ | 51 | unsigned int size; /* size of xpram segment in pages */ |
53 | unsigned int offset; /* start page of xpram segment */ | 52 | unsigned int offset; /* start page of xpram segment */ |
54 | unsigned int csum; /* partition checksum for suspend */ | ||
55 | } xpram_device_t; | 53 | } xpram_device_t; |
56 | 54 | ||
57 | static xpram_device_t xpram_devices[XPRAM_MAX_DEVS]; | 55 | static xpram_device_t xpram_devices[XPRAM_MAX_DEVS]; |
@@ -387,58 +385,6 @@ out: | |||
387 | } | 385 | } |
388 | 386 | ||
389 | /* | 387 | /* |
390 | * Save checksums for all partitions. | ||
391 | */ | ||
392 | static int xpram_save_checksums(void) | ||
393 | { | ||
394 | unsigned long mem_page; | ||
395 | int rc, i; | ||
396 | |||
397 | rc = 0; | ||
398 | mem_page = (unsigned long) __get_free_page(GFP_KERNEL); | ||
399 | if (!mem_page) | ||
400 | return -ENOMEM; | ||
401 | for (i = 0; i < xpram_devs; i++) { | ||
402 | rc = xpram_page_in(mem_page, xpram_devices[i].offset); | ||
403 | if (rc) | ||
404 | goto fail; | ||
405 | xpram_devices[i].csum = csum_partial((const void *) mem_page, | ||
406 | PAGE_SIZE, 0); | ||
407 | } | ||
408 | fail: | ||
409 | free_page(mem_page); | ||
410 | return rc ? -ENXIO : 0; | ||
411 | } | ||
412 | |||
413 | /* | ||
414 | * Verify checksums for all partitions. | ||
415 | */ | ||
416 | static int xpram_validate_checksums(void) | ||
417 | { | ||
418 | unsigned long mem_page; | ||
419 | unsigned int csum; | ||
420 | int rc, i; | ||
421 | |||
422 | rc = 0; | ||
423 | mem_page = (unsigned long) __get_free_page(GFP_KERNEL); | ||
424 | if (!mem_page) | ||
425 | return -ENOMEM; | ||
426 | for (i = 0; i < xpram_devs; i++) { | ||
427 | rc = xpram_page_in(mem_page, xpram_devices[i].offset); | ||
428 | if (rc) | ||
429 | goto fail; | ||
430 | csum = csum_partial((const void *) mem_page, PAGE_SIZE, 0); | ||
431 | if (xpram_devices[i].csum != csum) { | ||
432 | rc = -EINVAL; | ||
433 | goto fail; | ||
434 | } | ||
435 | } | ||
436 | fail: | ||
437 | free_page(mem_page); | ||
438 | return rc ? -ENXIO : 0; | ||
439 | } | ||
440 | |||
441 | /* | ||
442 | * Resume failed: Print error message and call panic. | 388 | * Resume failed: Print error message and call panic. |
443 | */ | 389 | */ |
444 | static void xpram_resume_error(const char *message) | 390 | static void xpram_resume_error(const char *message) |
@@ -458,21 +404,10 @@ static int xpram_restore(struct device *dev) | |||
458 | xpram_resume_error("xpram disappeared"); | 404 | xpram_resume_error("xpram disappeared"); |
459 | if (xpram_pages != xpram_highest_page_index() + 1) | 405 | if (xpram_pages != xpram_highest_page_index() + 1) |
460 | xpram_resume_error("Size of xpram changed"); | 406 | xpram_resume_error("Size of xpram changed"); |
461 | if (xpram_validate_checksums()) | ||
462 | xpram_resume_error("Data of xpram changed"); | ||
463 | return 0; | 407 | return 0; |
464 | } | 408 | } |
465 | 409 | ||
466 | /* | ||
467 | * Save necessary state in suspend. | ||
468 | */ | ||
469 | static int xpram_freeze(struct device *dev) | ||
470 | { | ||
471 | return xpram_save_checksums(); | ||
472 | } | ||
473 | |||
474 | static struct dev_pm_ops xpram_pm_ops = { | 410 | static struct dev_pm_ops xpram_pm_ops = { |
475 | .freeze = xpram_freeze, | ||
476 | .restore = xpram_restore, | 411 | .restore = xpram_restore, |
477 | }; | 412 | }; |
478 | 413 | ||
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 0769ced52dbd..4e34d3686c23 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig | |||
@@ -82,6 +82,16 @@ config SCLP_CPI | |||
82 | You should only select this option if you know what you are doing, | 82 | You should only select this option if you know what you are doing, |
83 | need this feature and intend to run your kernel in LPAR. | 83 | need this feature and intend to run your kernel in LPAR. |
84 | 84 | ||
85 | config SCLP_ASYNC | ||
86 | tristate "Support for Call Home via Asynchronous SCLP Records" | ||
87 | depends on S390 | ||
88 | help | ||
89 | This option enables the call home function, which is able to inform | ||
90 | the service element and connected organisations about a kernel panic. | ||
91 | You should only select this option if you know what you are doing, | ||
92 | want for inform other people about your kernel panics, | ||
93 | need this feature and intend to run your kernel in LPAR. | ||
94 | |||
85 | config S390_TAPE | 95 | config S390_TAPE |
86 | tristate "S/390 tape device support" | 96 | tristate "S/390 tape device support" |
87 | depends on CCW | 97 | depends on CCW |
diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile index 7e73e39a1741..efb500ab66c0 100644 --- a/drivers/s390/char/Makefile +++ b/drivers/s390/char/Makefile | |||
@@ -16,6 +16,7 @@ obj-$(CONFIG_SCLP_TTY) += sclp_tty.o | |||
16 | obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o | 16 | obj-$(CONFIG_SCLP_CONSOLE) += sclp_con.o |
17 | obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o | 17 | obj-$(CONFIG_SCLP_VT220_TTY) += sclp_vt220.o |
18 | obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o | 18 | obj-$(CONFIG_SCLP_CPI) += sclp_cpi.o |
19 | obj-$(CONFIG_SCLP_ASYNC) += sclp_async.o | ||
19 | 20 | ||
20 | obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o | 21 | obj-$(CONFIG_ZVM_WATCHDOG) += vmwatchdog.o |
21 | obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o | 22 | obj-$(CONFIG_VMLOGRDR) += vmlogrdr.o |
diff --git a/drivers/s390/char/monreader.c b/drivers/s390/char/monreader.c index 3234e90bd7f9..89ece1c235aa 100644 --- a/drivers/s390/char/monreader.c +++ b/drivers/s390/char/monreader.c | |||
@@ -581,7 +581,7 @@ static int __init mon_init(void) | |||
581 | monreader_device->release = (void (*)(struct device *))kfree; | 581 | monreader_device->release = (void (*)(struct device *))kfree; |
582 | rc = device_register(monreader_device); | 582 | rc = device_register(monreader_device); |
583 | if (rc) { | 583 | if (rc) { |
584 | kfree(monreader_device); | 584 | put_device(monreader_device); |
585 | goto out_driver; | 585 | goto out_driver; |
586 | } | 586 | } |
587 | 587 | ||
diff --git a/drivers/s390/char/sclp.h b/drivers/s390/char/sclp.h index 60e7cb07095b..6bb5a6bdfab5 100644 --- a/drivers/s390/char/sclp.h +++ b/drivers/s390/char/sclp.h | |||
@@ -27,6 +27,7 @@ | |||
27 | #define EVTYP_VT220MSG 0x1A | 27 | #define EVTYP_VT220MSG 0x1A |
28 | #define EVTYP_CONFMGMDATA 0x04 | 28 | #define EVTYP_CONFMGMDATA 0x04 |
29 | #define EVTYP_SDIAS 0x1C | 29 | #define EVTYP_SDIAS 0x1C |
30 | #define EVTYP_ASYNC 0x0A | ||
30 | 31 | ||
31 | #define EVTYP_OPCMD_MASK 0x80000000 | 32 | #define EVTYP_OPCMD_MASK 0x80000000 |
32 | #define EVTYP_MSG_MASK 0x40000000 | 33 | #define EVTYP_MSG_MASK 0x40000000 |
@@ -38,6 +39,7 @@ | |||
38 | #define EVTYP_VT220MSG_MASK 0x00000040 | 39 | #define EVTYP_VT220MSG_MASK 0x00000040 |
39 | #define EVTYP_CONFMGMDATA_MASK 0x10000000 | 40 | #define EVTYP_CONFMGMDATA_MASK 0x10000000 |
40 | #define EVTYP_SDIAS_MASK 0x00000010 | 41 | #define EVTYP_SDIAS_MASK 0x00000010 |
42 | #define EVTYP_ASYNC_MASK 0x00400000 | ||
41 | 43 | ||
42 | #define GNRLMSGFLGS_DOM 0x8000 | 44 | #define GNRLMSGFLGS_DOM 0x8000 |
43 | #define GNRLMSGFLGS_SNDALRM 0x4000 | 45 | #define GNRLMSGFLGS_SNDALRM 0x4000 |
@@ -85,12 +87,12 @@ struct sccb_header { | |||
85 | } __attribute__((packed)); | 87 | } __attribute__((packed)); |
86 | 88 | ||
87 | extern u64 sclp_facilities; | 89 | extern u64 sclp_facilities; |
88 | |||
89 | #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) | 90 | #define SCLP_HAS_CHP_INFO (sclp_facilities & 0x8000000000000000ULL) |
90 | #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) | 91 | #define SCLP_HAS_CHP_RECONFIG (sclp_facilities & 0x2000000000000000ULL) |
91 | #define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL) | 92 | #define SCLP_HAS_CPU_INFO (sclp_facilities & 0x0800000000000000ULL) |
92 | #define SCLP_HAS_CPU_RECONFIG (sclp_facilities & 0x0400000000000000ULL) | 93 | #define SCLP_HAS_CPU_RECONFIG (sclp_facilities & 0x0400000000000000ULL) |
93 | 94 | ||
95 | |||
94 | struct gds_subvector { | 96 | struct gds_subvector { |
95 | u8 length; | 97 | u8 length; |
96 | u8 key; | 98 | u8 key; |
diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c new file mode 100644 index 000000000000..daaec185ed36 --- /dev/null +++ b/drivers/s390/char/sclp_async.c | |||
@@ -0,0 +1,224 @@ | |||
1 | /* | ||
2 | * Enable Asynchronous Notification via SCLP. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2009 | ||
5 | * Author(s): Hans-Joachim Picht <hans@linux.vnet.ibm.com> | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #include <linux/init.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/device.h> | ||
12 | #include <linux/stat.h> | ||
13 | #include <linux/string.h> | ||
14 | #include <linux/ctype.h> | ||
15 | #include <linux/kmod.h> | ||
16 | #include <linux/err.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/proc_fs.h> | ||
19 | #include <linux/sysctl.h> | ||
20 | #include <linux/utsname.h> | ||
21 | #include "sclp.h" | ||
22 | |||
23 | static int callhome_enabled; | ||
24 | static struct sclp_req *request; | ||
25 | static struct sclp_async_sccb *sccb; | ||
26 | static int sclp_async_send_wait(char *message); | ||
27 | static struct ctl_table_header *callhome_sysctl_header; | ||
28 | static DEFINE_SPINLOCK(sclp_async_lock); | ||
29 | static char nodename[64]; | ||
30 | #define SCLP_NORMAL_WRITE 0x00 | ||
31 | |||
32 | struct async_evbuf { | ||
33 | struct evbuf_header header; | ||
34 | u64 reserved; | ||
35 | u8 rflags; | ||
36 | u8 empty; | ||
37 | u8 rtype; | ||
38 | u8 otype; | ||
39 | char comp_id[12]; | ||
40 | char data[3000]; /* there is still some space left */ | ||
41 | } __attribute__((packed)); | ||
42 | |||
43 | struct sclp_async_sccb { | ||
44 | struct sccb_header header; | ||
45 | struct async_evbuf evbuf; | ||
46 | } __attribute__((packed)); | ||
47 | |||
48 | static struct sclp_register sclp_async_register = { | ||
49 | .send_mask = EVTYP_ASYNC_MASK, | ||
50 | }; | ||
51 | |||
52 | static int call_home_on_panic(struct notifier_block *self, | ||
53 | unsigned long event, void *data) | ||
54 | { | ||
55 | strncat(data, nodename, strlen(nodename)); | ||
56 | sclp_async_send_wait(data); | ||
57 | return NOTIFY_DONE; | ||
58 | } | ||
59 | |||
60 | static struct notifier_block call_home_panic_nb = { | ||
61 | .notifier_call = call_home_on_panic, | ||
62 | .priority = INT_MAX, | ||
63 | }; | ||
64 | |||
65 | static int proc_handler_callhome(ctl_table *ctl, int write, struct file *filp, | ||
66 | void __user *buffer, size_t *count, | ||
67 | loff_t *ppos) | ||
68 | { | ||
69 | unsigned long val; | ||
70 | int len, rc; | ||
71 | char buf[2]; | ||
72 | |||
73 | if (!*count | (*ppos && !write)) { | ||
74 | *count = 0; | ||
75 | return 0; | ||
76 | } | ||
77 | if (!write) { | ||
78 | len = sprintf(buf, "%d\n", callhome_enabled); | ||
79 | buf[len] = '\0'; | ||
80 | rc = copy_to_user(buffer, buf, sizeof(buf)); | ||
81 | if (rc != 0) | ||
82 | return -EFAULT; | ||
83 | } else { | ||
84 | len = *count; | ||
85 | rc = copy_from_user(buf, buffer, sizeof(buf)); | ||
86 | if (rc != 0) | ||
87 | return -EFAULT; | ||
88 | if (strict_strtoul(buf, 0, &val) != 0) | ||
89 | return -EINVAL; | ||
90 | if (val != 0 && val != 1) | ||
91 | return -EINVAL; | ||
92 | callhome_enabled = val; | ||
93 | } | ||
94 | *count = len; | ||
95 | *ppos += len; | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | static struct ctl_table callhome_table[] = { | ||
100 | { | ||
101 | .procname = "callhome", | ||
102 | .mode = 0644, | ||
103 | .proc_handler = &proc_handler_callhome, | ||
104 | }, | ||
105 | { .ctl_name = 0 } | ||
106 | }; | ||
107 | |||
108 | static struct ctl_table kern_dir_table[] = { | ||
109 | { | ||
110 | .ctl_name = CTL_KERN, | ||
111 | .procname = "kernel", | ||
112 | .maxlen = 0, | ||
113 | .mode = 0555, | ||
114 | .child = callhome_table, | ||
115 | }, | ||
116 | { .ctl_name = 0 } | ||
117 | }; | ||
118 | |||
119 | /* | ||
120 | * Function used to transfer asynchronous notification | ||
121 | * records which waits for send completion | ||
122 | */ | ||
123 | static int sclp_async_send_wait(char *message) | ||
124 | { | ||
125 | struct async_evbuf *evb; | ||
126 | int rc; | ||
127 | unsigned long flags; | ||
128 | |||
129 | if (!callhome_enabled) | ||
130 | return 0; | ||
131 | sccb->evbuf.header.type = EVTYP_ASYNC; | ||
132 | sccb->evbuf.rtype = 0xA5; | ||
133 | sccb->evbuf.otype = 0x00; | ||
134 | evb = &sccb->evbuf; | ||
135 | request->command = SCLP_CMDW_WRITE_EVENT_DATA; | ||
136 | request->sccb = sccb; | ||
137 | request->status = SCLP_REQ_FILLED; | ||
138 | strncpy(sccb->evbuf.data, message, sizeof(sccb->evbuf.data)); | ||
139 | /* | ||
140 | * Retain Queue | ||
141 | * e.g. 5639CC140 500 Red Hat RHEL5 Linux for zSeries (RHEL AS) | ||
142 | */ | ||
143 | strncpy(sccb->evbuf.comp_id, "000000000", sizeof(sccb->evbuf.comp_id)); | ||
144 | sccb->evbuf.header.length = sizeof(sccb->evbuf); | ||
145 | sccb->header.length = sizeof(sccb->evbuf) + sizeof(sccb->header); | ||
146 | sccb->header.function_code = SCLP_NORMAL_WRITE; | ||
147 | rc = sclp_add_request(request); | ||
148 | if (rc) | ||
149 | return rc; | ||
150 | spin_lock_irqsave(&sclp_async_lock, flags); | ||
151 | while (request->status != SCLP_REQ_DONE && | ||
152 | request->status != SCLP_REQ_FAILED) { | ||
153 | sclp_sync_wait(); | ||
154 | } | ||
155 | spin_unlock_irqrestore(&sclp_async_lock, flags); | ||
156 | if (request->status != SCLP_REQ_DONE) | ||
157 | return -EIO; | ||
158 | rc = ((struct sclp_async_sccb *) | ||
159 | request->sccb)->header.response_code; | ||
160 | if (rc != 0x0020) | ||
161 | return -EIO; | ||
162 | if (evb->header.flags != 0x80) | ||
163 | return -EIO; | ||
164 | return rc; | ||
165 | } | ||
166 | |||
167 | static int __init sclp_async_init(void) | ||
168 | { | ||
169 | int rc; | ||
170 | |||
171 | rc = sclp_register(&sclp_async_register); | ||
172 | if (rc) | ||
173 | return rc; | ||
174 | callhome_sysctl_header = register_sysctl_table(kern_dir_table); | ||
175 | if (!callhome_sysctl_header) { | ||
176 | rc = -ENOMEM; | ||
177 | goto out_sclp; | ||
178 | } | ||
179 | if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) { | ||
180 | rc = -EOPNOTSUPP; | ||
181 | goto out_sclp; | ||
182 | } | ||
183 | rc = -ENOMEM; | ||
184 | request = kzalloc(sizeof(struct sclp_req), GFP_KERNEL); | ||
185 | if (!request) | ||
186 | goto out_sys; | ||
187 | sccb = (struct sclp_async_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA); | ||
188 | if (!sccb) | ||
189 | goto out_mem; | ||
190 | rc = atomic_notifier_chain_register(&panic_notifier_list, | ||
191 | &call_home_panic_nb); | ||
192 | if (rc) | ||
193 | goto out_mem; | ||
194 | |||
195 | strncpy(nodename, init_utsname()->nodename, 64); | ||
196 | return 0; | ||
197 | |||
198 | out_mem: | ||
199 | kfree(request); | ||
200 | free_page((unsigned long) sccb); | ||
201 | out_sys: | ||
202 | unregister_sysctl_table(callhome_sysctl_header); | ||
203 | out_sclp: | ||
204 | sclp_unregister(&sclp_async_register); | ||
205 | return rc; | ||
206 | |||
207 | } | ||
208 | module_init(sclp_async_init); | ||
209 | |||
210 | static void __exit sclp_async_exit(void) | ||
211 | { | ||
212 | atomic_notifier_chain_unregister(&panic_notifier_list, | ||
213 | &call_home_panic_nb); | ||
214 | unregister_sysctl_table(callhome_sysctl_header); | ||
215 | sclp_unregister(&sclp_async_register); | ||
216 | free_page((unsigned long) sccb); | ||
217 | kfree(request); | ||
218 | } | ||
219 | module_exit(sclp_async_exit); | ||
220 | |||
221 | MODULE_AUTHOR("Copyright IBM Corp. 2009"); | ||
222 | MODULE_AUTHOR("Hans-Joachim Picht <hans@linux.vnet.ibm.com>"); | ||
223 | MODULE_LICENSE("GPL"); | ||
224 | MODULE_DESCRIPTION("SCLP Asynchronous Notification Records"); | ||
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 5a519fac37b7..2fe45ff77b75 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define KMSG_COMPONENT "tape" | 11 | #define KMSG_COMPONENT "tape_34xx" |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 418f72dd39b4..e4cc3aae9162 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> | 8 | * Martin Schwidefsky <schwidefsky@de.ibm.com> |
9 | */ | 9 | */ |
10 | 10 | ||
11 | #define KMSG_COMPONENT "tape" | 11 | #define KMSG_COMPONENT "tape_3590" |
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
@@ -39,8 +39,6 @@ EXPORT_SYMBOL(TAPE_DBF_AREA); | |||
39 | * - Read Alternate: implemented | 39 | * - Read Alternate: implemented |
40 | *******************************************************************/ | 40 | *******************************************************************/ |
41 | 41 | ||
42 | #define KMSG_COMPONENT "tape" | ||
43 | |||
44 | static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = { | 42 | static const char *tape_3590_msg[TAPE_3590_MAX_MSG] = { |
45 | [0x00] = "", | 43 | [0x00] = "", |
46 | [0x10] = "Lost Sense", | 44 | [0x10] = "Lost Sense", |
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index 47ff695255ea..4cb9e70507ab 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c | |||
@@ -302,8 +302,6 @@ tapeblock_revalidate_disk(struct gendisk *disk) | |||
302 | if (!device->blk_data.medium_changed) | 302 | if (!device->blk_data.medium_changed) |
303 | return 0; | 303 | return 0; |
304 | 304 | ||
305 | dev_info(&device->cdev->dev, "Determining the size of the recorded " | ||
306 | "area...\n"); | ||
307 | rc = tape_mtop(device, MTFSFM, 1); | 305 | rc = tape_mtop(device, MTFSFM, 1); |
308 | if (rc) | 306 | if (rc) |
309 | return rc; | 307 | return rc; |
@@ -312,6 +310,8 @@ tapeblock_revalidate_disk(struct gendisk *disk) | |||
312 | if (rc < 0) | 310 | if (rc < 0) |
313 | return rc; | 311 | return rc; |
314 | 312 | ||
313 | pr_info("%s: Determining the size of the recorded area...\n", | ||
314 | dev_name(&device->cdev->dev)); | ||
315 | DBF_LH(3, "Image file ends at %d\n", rc); | 315 | DBF_LH(3, "Image file ends at %d\n", rc); |
316 | nr_of_blks = rc; | 316 | nr_of_blks = rc; |
317 | 317 | ||
@@ -330,8 +330,8 @@ tapeblock_revalidate_disk(struct gendisk *disk) | |||
330 | device->bof = rc; | 330 | device->bof = rc; |
331 | nr_of_blks -= rc; | 331 | nr_of_blks -= rc; |
332 | 332 | ||
333 | dev_info(&device->cdev->dev, "The size of the recorded area is %i " | 333 | pr_info("%s: The size of the recorded area is %i blocks\n", |
334 | "blocks\n", nr_of_blks); | 334 | dev_name(&device->cdev->dev), nr_of_blks); |
335 | set_capacity(device->blk_data.disk, | 335 | set_capacity(device->blk_data.disk, |
336 | nr_of_blks*(TAPEBLOCK_HSEC_SIZE/512)); | 336 | nr_of_blks*(TAPEBLOCK_HSEC_SIZE/512)); |
337 | 337 | ||
@@ -366,8 +366,8 @@ tapeblock_open(struct block_device *bdev, fmode_t mode) | |||
366 | 366 | ||
367 | if (device->required_tapemarks) { | 367 | if (device->required_tapemarks) { |
368 | DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); | 368 | DBF_EVENT(2, "TBLOCK: missing tapemarks\n"); |
369 | dev_warn(&device->cdev->dev, "Opening the tape failed because" | 369 | pr_warning("%s: Opening the tape failed because of missing " |
370 | " of missing end-of-file marks\n"); | 370 | "end-of-file marks\n", dev_name(&device->cdev->dev)); |
371 | rc = -EPERM; | 371 | rc = -EPERM; |
372 | goto put_device; | 372 | goto put_device; |
373 | } | 373 | } |
diff --git a/drivers/s390/char/tape_core.c b/drivers/s390/char/tape_core.c index 1d420d947596..5cd31e071647 100644 --- a/drivers/s390/char/tape_core.c +++ b/drivers/s390/char/tape_core.c | |||
@@ -214,13 +214,15 @@ tape_med_state_set(struct tape_device *device, enum tape_medium_state newstate) | |||
214 | switch(newstate){ | 214 | switch(newstate){ |
215 | case MS_UNLOADED: | 215 | case MS_UNLOADED: |
216 | device->tape_generic_status |= GMT_DR_OPEN(~0); | 216 | device->tape_generic_status |= GMT_DR_OPEN(~0); |
217 | dev_info(&device->cdev->dev, "The tape cartridge has been " | 217 | if (device->medium_state == MS_LOADED) |
218 | "successfully unloaded\n"); | 218 | pr_info("%s: The tape cartridge has been successfully " |
219 | "unloaded\n", dev_name(&device->cdev->dev)); | ||
219 | break; | 220 | break; |
220 | case MS_LOADED: | 221 | case MS_LOADED: |
221 | device->tape_generic_status &= ~GMT_DR_OPEN(~0); | 222 | device->tape_generic_status &= ~GMT_DR_OPEN(~0); |
222 | dev_info(&device->cdev->dev, "A tape cartridge has been " | 223 | if (device->medium_state == MS_UNLOADED) |
223 | "mounted\n"); | 224 | pr_info("%s: A tape cartridge has been mounted\n", |
225 | dev_name(&device->cdev->dev)); | ||
224 | break; | 226 | break; |
225 | default: | 227 | default: |
226 | // print nothing | 228 | // print nothing |
@@ -358,11 +360,11 @@ tape_generic_online(struct tape_device *device, | |||
358 | 360 | ||
359 | out_char: | 361 | out_char: |
360 | tapechar_cleanup_device(device); | 362 | tapechar_cleanup_device(device); |
363 | out_minor: | ||
364 | tape_remove_minor(device); | ||
361 | out_discipline: | 365 | out_discipline: |
362 | device->discipline->cleanup_device(device); | 366 | device->discipline->cleanup_device(device); |
363 | device->discipline = NULL; | 367 | device->discipline = NULL; |
364 | out_minor: | ||
365 | tape_remove_minor(device); | ||
366 | out: | 368 | out: |
367 | module_put(discipline->owner); | 369 | module_put(discipline->owner); |
368 | return rc; | 370 | return rc; |
@@ -654,8 +656,8 @@ tape_generic_remove(struct ccw_device *cdev) | |||
654 | */ | 656 | */ |
655 | DBF_EVENT(3, "(%08x): Drive in use vanished!\n", | 657 | DBF_EVENT(3, "(%08x): Drive in use vanished!\n", |
656 | device->cdev_id); | 658 | device->cdev_id); |
657 | dev_warn(&device->cdev->dev, "A tape unit was detached" | 659 | pr_warning("%s: A tape unit was detached while in " |
658 | " while in use\n"); | 660 | "use\n", dev_name(&device->cdev->dev)); |
659 | tape_state_set(device, TS_NOT_OPER); | 661 | tape_state_set(device, TS_NOT_OPER); |
660 | __tape_discard_requests(device); | 662 | __tape_discard_requests(device); |
661 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | 663 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); |
diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 1a9420ba518d..750354ad16e5 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c | |||
@@ -68,7 +68,7 @@ tape_std_assign(struct tape_device *device) | |||
68 | * to another host (actually this shouldn't happen but it does). | 68 | * to another host (actually this shouldn't happen but it does). |
69 | * So we set up a timeout for this call. | 69 | * So we set up a timeout for this call. |
70 | */ | 70 | */ |
71 | init_timer(&timeout); | 71 | init_timer_on_stack(&timeout); |
72 | timeout.function = tape_std_assign_timeout; | 72 | timeout.function = tape_std_assign_timeout; |
73 | timeout.data = (unsigned long) request; | 73 | timeout.data = (unsigned long) request; |
74 | timeout.expires = jiffies + 2 * HZ; | 74 | timeout.expires = jiffies + 2 * HZ; |
diff --git a/drivers/s390/char/vmlogrdr.c b/drivers/s390/char/vmlogrdr.c index c20a4fe6da51..d1a142fa3eb4 100644 --- a/drivers/s390/char/vmlogrdr.c +++ b/drivers/s390/char/vmlogrdr.c | |||
@@ -765,8 +765,10 @@ static int vmlogrdr_register_device(struct vmlogrdr_priv_t *priv) | |||
765 | } else | 765 | } else |
766 | return -ENOMEM; | 766 | return -ENOMEM; |
767 | ret = device_register(dev); | 767 | ret = device_register(dev); |
768 | if (ret) | 768 | if (ret) { |
769 | put_device(dev); | ||
769 | return ret; | 770 | return ret; |
771 | } | ||
770 | 772 | ||
771 | ret = sysfs_create_group(&dev->kobj, &vmlogrdr_attr_group); | 773 | ret = sysfs_create_group(&dev->kobj, &vmlogrdr_attr_group); |
772 | if (ret) { | 774 | if (ret) { |
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 31b902e94f7b..77571b68539a 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c | |||
@@ -1026,9 +1026,15 @@ static int __init ur_init(void) | |||
1026 | 1026 | ||
1027 | debug_set_level(vmur_dbf, 6); | 1027 | debug_set_level(vmur_dbf, 6); |
1028 | 1028 | ||
1029 | vmur_class = class_create(THIS_MODULE, "vmur"); | ||
1030 | if (IS_ERR(vmur_class)) { | ||
1031 | rc = PTR_ERR(vmur_class); | ||
1032 | goto fail_free_dbf; | ||
1033 | } | ||
1034 | |||
1029 | rc = ccw_driver_register(&ur_driver); | 1035 | rc = ccw_driver_register(&ur_driver); |
1030 | if (rc) | 1036 | if (rc) |
1031 | goto fail_free_dbf; | 1037 | goto fail_class_destroy; |
1032 | 1038 | ||
1033 | rc = alloc_chrdev_region(&dev, 0, NUM_MINORS, "vmur"); | 1039 | rc = alloc_chrdev_region(&dev, 0, NUM_MINORS, "vmur"); |
1034 | if (rc) { | 1040 | if (rc) { |
@@ -1038,18 +1044,13 @@ static int __init ur_init(void) | |||
1038 | } | 1044 | } |
1039 | ur_first_dev_maj_min = MKDEV(MAJOR(dev), 0); | 1045 | ur_first_dev_maj_min = MKDEV(MAJOR(dev), 0); |
1040 | 1046 | ||
1041 | vmur_class = class_create(THIS_MODULE, "vmur"); | ||
1042 | if (IS_ERR(vmur_class)) { | ||
1043 | rc = PTR_ERR(vmur_class); | ||
1044 | goto fail_unregister_region; | ||
1045 | } | ||
1046 | pr_info("%s loaded.\n", ur_banner); | 1047 | pr_info("%s loaded.\n", ur_banner); |
1047 | return 0; | 1048 | return 0; |
1048 | 1049 | ||
1049 | fail_unregister_region: | ||
1050 | unregister_chrdev_region(ur_first_dev_maj_min, NUM_MINORS); | ||
1051 | fail_unregister_driver: | 1050 | fail_unregister_driver: |
1052 | ccw_driver_unregister(&ur_driver); | 1051 | ccw_driver_unregister(&ur_driver); |
1052 | fail_class_destroy: | ||
1053 | class_destroy(vmur_class); | ||
1053 | fail_free_dbf: | 1054 | fail_free_dbf: |
1054 | debug_unregister(vmur_dbf); | 1055 | debug_unregister(vmur_dbf); |
1055 | return rc; | 1056 | return rc; |
@@ -1057,9 +1058,9 @@ fail_free_dbf: | |||
1057 | 1058 | ||
1058 | static void __exit ur_exit(void) | 1059 | static void __exit ur_exit(void) |
1059 | { | 1060 | { |
1060 | class_destroy(vmur_class); | ||
1061 | unregister_chrdev_region(ur_first_dev_maj_min, NUM_MINORS); | 1061 | unregister_chrdev_region(ur_first_dev_maj_min, NUM_MINORS); |
1062 | ccw_driver_unregister(&ur_driver); | 1062 | ccw_driver_unregister(&ur_driver); |
1063 | class_destroy(vmur_class); | ||
1063 | debug_unregister(vmur_dbf); | 1064 | debug_unregister(vmur_dbf); |
1064 | pr_info("%s unloaded.\n", ur_banner); | 1065 | pr_info("%s unloaded.\n", ur_banner); |
1065 | } | 1066 | } |
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 1bbae433fbd8..c431198bdbc4 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -275,7 +275,7 @@ struct zcore_header { | |||
275 | u32 num_pages; | 275 | u32 num_pages; |
276 | u32 pad1; | 276 | u32 pad1; |
277 | u64 tod; | 277 | u64 tod; |
278 | cpuid_t cpu_id; | 278 | struct cpuid cpu_id; |
279 | u32 arch_id; | 279 | u32 arch_id; |
280 | u32 volnr; | 280 | u32 volnr; |
281 | u32 build_arch; | 281 | u32 build_arch; |
diff --git a/drivers/s390/cio/Makefile b/drivers/s390/cio/Makefile index adb3dd301528..fa4c9662f65e 100644 --- a/drivers/s390/cio/Makefile +++ b/drivers/s390/cio/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the S/390 common i/o drivers | 2 | # Makefile for the S/390 common i/o drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o scsw.o \ | 5 | obj-y += airq.o blacklist.o chsc.o cio.o css.o chp.o idset.o isc.o \ |
6 | fcx.o itcw.o crw.o | 6 | fcx.o itcw.o crw.o |
7 | ccw_device-objs += device.o device_fsm.o device_ops.o | 7 | ccw_device-objs += device.o device_fsm.o device_ops.o |
8 | ccw_device-objs += device_id.o device_pgid.o device_status.o | 8 | ccw_device-objs += device_id.o device_pgid.o device_status.o |
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 3e5f304ad88f..40002830d48a 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c | |||
@@ -417,7 +417,8 @@ int chp_new(struct chp_id chpid) | |||
417 | if (ret) { | 417 | if (ret) { |
418 | CIO_MSG_EVENT(0, "Could not register chp%x.%02x: %d\n", | 418 | CIO_MSG_EVENT(0, "Could not register chp%x.%02x: %d\n", |
419 | chpid.cssid, chpid.id, ret); | 419 | chpid.cssid, chpid.id, ret); |
420 | goto out_free; | 420 | put_device(&chp->dev); |
421 | goto out; | ||
421 | } | 422 | } |
422 | ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); | 423 | ret = sysfs_create_group(&chp->dev.kobj, &chp_attr_group); |
423 | if (ret) { | 424 | if (ret) { |
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 425e8f89a6c5..37aa611d4ac5 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -37,29 +37,6 @@ struct channel_path_desc { | |||
37 | 37 | ||
38 | struct channel_path; | 38 | struct channel_path; |
39 | 39 | ||
40 | struct css_general_char { | ||
41 | u64 : 12; | ||
42 | u32 dynio : 1; /* bit 12 */ | ||
43 | u32 : 28; | ||
44 | u32 aif : 1; /* bit 41 */ | ||
45 | u32 : 3; | ||
46 | u32 mcss : 1; /* bit 45 */ | ||
47 | u32 fcs : 1; /* bit 46 */ | ||
48 | u32 : 1; | ||
49 | u32 ext_mb : 1; /* bit 48 */ | ||
50 | u32 : 7; | ||
51 | u32 aif_tdd : 1; /* bit 56 */ | ||
52 | u32 : 1; | ||
53 | u32 qebsm : 1; /* bit 58 */ | ||
54 | u32 : 8; | ||
55 | u32 aif_osa : 1; /* bit 67 */ | ||
56 | u32 : 14; | ||
57 | u32 cib : 1; /* bit 82 */ | ||
58 | u32 : 5; | ||
59 | u32 fcx : 1; /* bit 88 */ | ||
60 | u32 : 7; | ||
61 | }__attribute__((packed)); | ||
62 | |||
63 | struct css_chsc_char { | 40 | struct css_chsc_char { |
64 | u64 res; | 41 | u64 res; |
65 | u64 : 20; | 42 | u64 : 20; |
@@ -72,7 +49,6 @@ struct css_chsc_char { | |||
72 | u32 : 19; | 49 | u32 : 19; |
73 | }__attribute__((packed)); | 50 | }__attribute__((packed)); |
74 | 51 | ||
75 | extern struct css_general_char css_general_characteristics; | ||
76 | extern struct css_chsc_char css_chsc_characteristics; | 52 | extern struct css_chsc_char css_chsc_characteristics; |
77 | 53 | ||
78 | struct chsc_ssd_info { | 54 | struct chsc_ssd_info { |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5ec7789bd9d8..138124fcfcad 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -139,12 +139,11 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ | |||
139 | __u8 lpm, /* logical path mask */ | 139 | __u8 lpm, /* logical path mask */ |
140 | __u8 key) /* storage key */ | 140 | __u8 key) /* storage key */ |
141 | { | 141 | { |
142 | char dbf_txt[15]; | ||
143 | int ccode; | 142 | int ccode; |
144 | union orb *orb; | 143 | union orb *orb; |
145 | 144 | ||
146 | CIO_TRACE_EVENT(4, "stIO"); | 145 | CIO_TRACE_EVENT(5, "stIO"); |
147 | CIO_TRACE_EVENT(4, dev_name(&sch->dev)); | 146 | CIO_TRACE_EVENT(5, dev_name(&sch->dev)); |
148 | 147 | ||
149 | orb = &to_io_private(sch)->orb; | 148 | orb = &to_io_private(sch)->orb; |
150 | memset(orb, 0, sizeof(union orb)); | 149 | memset(orb, 0, sizeof(union orb)); |
@@ -169,8 +168,7 @@ cio_start_key (struct subchannel *sch, /* subchannel structure */ | |||
169 | ccode = ssch(sch->schid, orb); | 168 | ccode = ssch(sch->schid, orb); |
170 | 169 | ||
171 | /* process condition code */ | 170 | /* process condition code */ |
172 | sprintf(dbf_txt, "ccode:%d", ccode); | 171 | CIO_HEX_EVENT(5, &ccode, sizeof(ccode)); |
173 | CIO_TRACE_EVENT(4, dbf_txt); | ||
174 | 172 | ||
175 | switch (ccode) { | 173 | switch (ccode) { |
176 | case 0: | 174 | case 0: |
@@ -201,16 +199,14 @@ cio_start (struct subchannel *sch, struct ccw1 *cpa, __u8 lpm) | |||
201 | int | 199 | int |
202 | cio_resume (struct subchannel *sch) | 200 | cio_resume (struct subchannel *sch) |
203 | { | 201 | { |
204 | char dbf_txt[15]; | ||
205 | int ccode; | 202 | int ccode; |
206 | 203 | ||
207 | CIO_TRACE_EVENT (4, "resIO"); | 204 | CIO_TRACE_EVENT(4, "resIO"); |
208 | CIO_TRACE_EVENT(4, dev_name(&sch->dev)); | 205 | CIO_TRACE_EVENT(4, dev_name(&sch->dev)); |
209 | 206 | ||
210 | ccode = rsch (sch->schid); | 207 | ccode = rsch (sch->schid); |
211 | 208 | ||
212 | sprintf (dbf_txt, "ccode:%d", ccode); | 209 | CIO_HEX_EVENT(4, &ccode, sizeof(ccode)); |
213 | CIO_TRACE_EVENT (4, dbf_txt); | ||
214 | 210 | ||
215 | switch (ccode) { | 211 | switch (ccode) { |
216 | case 0: | 212 | case 0: |
@@ -235,13 +231,12 @@ cio_resume (struct subchannel *sch) | |||
235 | int | 231 | int |
236 | cio_halt(struct subchannel *sch) | 232 | cio_halt(struct subchannel *sch) |
237 | { | 233 | { |
238 | char dbf_txt[15]; | ||
239 | int ccode; | 234 | int ccode; |
240 | 235 | ||
241 | if (!sch) | 236 | if (!sch) |
242 | return -ENODEV; | 237 | return -ENODEV; |
243 | 238 | ||
244 | CIO_TRACE_EVENT (2, "haltIO"); | 239 | CIO_TRACE_EVENT(2, "haltIO"); |
245 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); | 240 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
246 | 241 | ||
247 | /* | 242 | /* |
@@ -249,8 +244,7 @@ cio_halt(struct subchannel *sch) | |||
249 | */ | 244 | */ |
250 | ccode = hsch (sch->schid); | 245 | ccode = hsch (sch->schid); |
251 | 246 | ||
252 | sprintf (dbf_txt, "ccode:%d", ccode); | 247 | CIO_HEX_EVENT(2, &ccode, sizeof(ccode)); |
253 | CIO_TRACE_EVENT (2, dbf_txt); | ||
254 | 248 | ||
255 | switch (ccode) { | 249 | switch (ccode) { |
256 | case 0: | 250 | case 0: |
@@ -270,13 +264,12 @@ cio_halt(struct subchannel *sch) | |||
270 | int | 264 | int |
271 | cio_clear(struct subchannel *sch) | 265 | cio_clear(struct subchannel *sch) |
272 | { | 266 | { |
273 | char dbf_txt[15]; | ||
274 | int ccode; | 267 | int ccode; |
275 | 268 | ||
276 | if (!sch) | 269 | if (!sch) |
277 | return -ENODEV; | 270 | return -ENODEV; |
278 | 271 | ||
279 | CIO_TRACE_EVENT (2, "clearIO"); | 272 | CIO_TRACE_EVENT(2, "clearIO"); |
280 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); | 273 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
281 | 274 | ||
282 | /* | 275 | /* |
@@ -284,8 +277,7 @@ cio_clear(struct subchannel *sch) | |||
284 | */ | 277 | */ |
285 | ccode = csch (sch->schid); | 278 | ccode = csch (sch->schid); |
286 | 279 | ||
287 | sprintf (dbf_txt, "ccode:%d", ccode); | 280 | CIO_HEX_EVENT(2, &ccode, sizeof(ccode)); |
288 | CIO_TRACE_EVENT (2, dbf_txt); | ||
289 | 281 | ||
290 | switch (ccode) { | 282 | switch (ccode) { |
291 | case 0: | 283 | case 0: |
@@ -306,19 +298,17 @@ cio_clear(struct subchannel *sch) | |||
306 | int | 298 | int |
307 | cio_cancel (struct subchannel *sch) | 299 | cio_cancel (struct subchannel *sch) |
308 | { | 300 | { |
309 | char dbf_txt[15]; | ||
310 | int ccode; | 301 | int ccode; |
311 | 302 | ||
312 | if (!sch) | 303 | if (!sch) |
313 | return -ENODEV; | 304 | return -ENODEV; |
314 | 305 | ||
315 | CIO_TRACE_EVENT (2, "cancelIO"); | 306 | CIO_TRACE_EVENT(2, "cancelIO"); |
316 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); | 307 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
317 | 308 | ||
318 | ccode = xsch (sch->schid); | 309 | ccode = xsch (sch->schid); |
319 | 310 | ||
320 | sprintf (dbf_txt, "ccode:%d", ccode); | 311 | CIO_HEX_EVENT(2, &ccode, sizeof(ccode)); |
321 | CIO_TRACE_EVENT (2, dbf_txt); | ||
322 | 312 | ||
323 | switch (ccode) { | 313 | switch (ccode) { |
324 | case 0: /* success */ | 314 | case 0: /* success */ |
@@ -429,11 +419,10 @@ EXPORT_SYMBOL_GPL(cio_update_schib); | |||
429 | */ | 419 | */ |
430 | int cio_enable_subchannel(struct subchannel *sch, u32 intparm) | 420 | int cio_enable_subchannel(struct subchannel *sch, u32 intparm) |
431 | { | 421 | { |
432 | char dbf_txt[15]; | ||
433 | int retry; | 422 | int retry; |
434 | int ret; | 423 | int ret; |
435 | 424 | ||
436 | CIO_TRACE_EVENT (2, "ensch"); | 425 | CIO_TRACE_EVENT(2, "ensch"); |
437 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); | 426 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
438 | 427 | ||
439 | if (sch_is_pseudo_sch(sch)) | 428 | if (sch_is_pseudo_sch(sch)) |
@@ -460,8 +449,7 @@ int cio_enable_subchannel(struct subchannel *sch, u32 intparm) | |||
460 | } else | 449 | } else |
461 | break; | 450 | break; |
462 | } | 451 | } |
463 | sprintf (dbf_txt, "ret:%d", ret); | 452 | CIO_HEX_EVENT(2, &ret, sizeof(ret)); |
464 | CIO_TRACE_EVENT (2, dbf_txt); | ||
465 | return ret; | 453 | return ret; |
466 | } | 454 | } |
467 | EXPORT_SYMBOL_GPL(cio_enable_subchannel); | 455 | EXPORT_SYMBOL_GPL(cio_enable_subchannel); |
@@ -472,11 +460,10 @@ EXPORT_SYMBOL_GPL(cio_enable_subchannel); | |||
472 | */ | 460 | */ |
473 | int cio_disable_subchannel(struct subchannel *sch) | 461 | int cio_disable_subchannel(struct subchannel *sch) |
474 | { | 462 | { |
475 | char dbf_txt[15]; | ||
476 | int retry; | 463 | int retry; |
477 | int ret; | 464 | int ret; |
478 | 465 | ||
479 | CIO_TRACE_EVENT (2, "dissch"); | 466 | CIO_TRACE_EVENT(2, "dissch"); |
480 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); | 467 | CIO_TRACE_EVENT(2, dev_name(&sch->dev)); |
481 | 468 | ||
482 | if (sch_is_pseudo_sch(sch)) | 469 | if (sch_is_pseudo_sch(sch)) |
@@ -495,8 +482,7 @@ int cio_disable_subchannel(struct subchannel *sch) | |||
495 | } else | 482 | } else |
496 | break; | 483 | break; |
497 | } | 484 | } |
498 | sprintf (dbf_txt, "ret:%d", ret); | 485 | CIO_HEX_EVENT(2, &ret, sizeof(ret)); |
499 | CIO_TRACE_EVENT (2, dbf_txt); | ||
500 | return ret; | 486 | return ret; |
501 | } | 487 | } |
502 | EXPORT_SYMBOL_GPL(cio_disable_subchannel); | 488 | EXPORT_SYMBOL_GPL(cio_disable_subchannel); |
@@ -578,11 +564,6 @@ int cio_validate_subchannel(struct subchannel *sch, struct subchannel_id schid) | |||
578 | goto out; | 564 | goto out; |
579 | } | 565 | } |
580 | mutex_init(&sch->reg_mutex); | 566 | mutex_init(&sch->reg_mutex); |
581 | /* Set a name for the subchannel */ | ||
582 | if (cio_is_console(schid)) | ||
583 | sch->dev.init_name = cio_get_console_sch_name(schid); | ||
584 | else | ||
585 | dev_set_name(&sch->dev, "0.%x.%04x", schid.ssid, schid.sch_no); | ||
586 | 567 | ||
587 | /* | 568 | /* |
588 | * The first subchannel that is not-operational (ccode==3) | 569 | * The first subchannel that is not-operational (ccode==3) |
@@ -686,7 +667,6 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
686 | 667 | ||
687 | #ifdef CONFIG_CCW_CONSOLE | 668 | #ifdef CONFIG_CCW_CONSOLE |
688 | static struct subchannel console_subchannel; | 669 | static struct subchannel console_subchannel; |
689 | static char console_sch_name[10] = "0.x.xxxx"; | ||
690 | static struct io_subchannel_private console_priv; | 670 | static struct io_subchannel_private console_priv; |
691 | static int console_subchannel_in_use; | 671 | static int console_subchannel_in_use; |
692 | 672 | ||
@@ -873,12 +853,6 @@ cio_get_console_subchannel(void) | |||
873 | return &console_subchannel; | 853 | return &console_subchannel; |
874 | } | 854 | } |
875 | 855 | ||
876 | const char *cio_get_console_sch_name(struct subchannel_id schid) | ||
877 | { | ||
878 | snprintf(console_sch_name, 10, "0.%x.%04x", schid.ssid, schid.sch_no); | ||
879 | return (const char *)console_sch_name; | ||
880 | } | ||
881 | |||
882 | #endif | 856 | #endif |
883 | static int | 857 | static int |
884 | __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) | 858 | __disable_subchannel_easy(struct subchannel_id schid, struct schib *schib) |
diff --git a/drivers/s390/cio/cio.h b/drivers/s390/cio/cio.h index 5150fba742ac..2e43558c704b 100644 --- a/drivers/s390/cio/cio.h +++ b/drivers/s390/cio/cio.h | |||
@@ -133,15 +133,11 @@ extern int cio_is_console(struct subchannel_id); | |||
133 | extern struct subchannel *cio_get_console_subchannel(void); | 133 | extern struct subchannel *cio_get_console_subchannel(void); |
134 | extern spinlock_t * cio_get_console_lock(void); | 134 | extern spinlock_t * cio_get_console_lock(void); |
135 | extern void *cio_get_console_priv(void); | 135 | extern void *cio_get_console_priv(void); |
136 | extern const char *cio_get_console_sch_name(struct subchannel_id schid); | ||
137 | extern const char *cio_get_console_cdev_name(struct subchannel *sch); | ||
138 | #else | 136 | #else |
139 | #define cio_is_console(schid) 0 | 137 | #define cio_is_console(schid) 0 |
140 | #define cio_get_console_subchannel() NULL | 138 | #define cio_get_console_subchannel() NULL |
141 | #define cio_get_console_lock() NULL | 139 | #define cio_get_console_lock() NULL |
142 | #define cio_get_console_priv() NULL | 140 | #define cio_get_console_priv() NULL |
143 | #define cio_get_console_sch_name(schid) NULL | ||
144 | #define cio_get_console_cdev_name(sch) NULL | ||
145 | #endif | 141 | #endif |
146 | 142 | ||
147 | #endif | 143 | #endif |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 85d43c6bcb66..e995123fd805 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -152,24 +152,15 @@ css_alloc_subchannel(struct subchannel_id schid) | |||
152 | } | 152 | } |
153 | 153 | ||
154 | static void | 154 | static void |
155 | css_free_subchannel(struct subchannel *sch) | ||
156 | { | ||
157 | if (sch) { | ||
158 | /* Reset intparm to zeroes. */ | ||
159 | sch->config.intparm = 0; | ||
160 | cio_commit_config(sch); | ||
161 | kfree(sch->lock); | ||
162 | kfree(sch); | ||
163 | } | ||
164 | } | ||
165 | |||
166 | static void | ||
167 | css_subchannel_release(struct device *dev) | 155 | css_subchannel_release(struct device *dev) |
168 | { | 156 | { |
169 | struct subchannel *sch; | 157 | struct subchannel *sch; |
170 | 158 | ||
171 | sch = to_subchannel(dev); | 159 | sch = to_subchannel(dev); |
172 | if (!cio_is_console(sch->schid)) { | 160 | if (!cio_is_console(sch->schid)) { |
161 | /* Reset intparm to zeroes. */ | ||
162 | sch->config.intparm = 0; | ||
163 | cio_commit_config(sch); | ||
173 | kfree(sch->lock); | 164 | kfree(sch->lock); |
174 | kfree(sch); | 165 | kfree(sch); |
175 | } | 166 | } |
@@ -180,6 +171,8 @@ static int css_sch_device_register(struct subchannel *sch) | |||
180 | int ret; | 171 | int ret; |
181 | 172 | ||
182 | mutex_lock(&sch->reg_mutex); | 173 | mutex_lock(&sch->reg_mutex); |
174 | dev_set_name(&sch->dev, "0.%x.%04x", sch->schid.ssid, | ||
175 | sch->schid.sch_no); | ||
183 | ret = device_register(&sch->dev); | 176 | ret = device_register(&sch->dev); |
184 | mutex_unlock(&sch->reg_mutex); | 177 | mutex_unlock(&sch->reg_mutex); |
185 | return ret; | 178 | return ret; |
@@ -327,7 +320,7 @@ int css_probe_device(struct subchannel_id schid) | |||
327 | return PTR_ERR(sch); | 320 | return PTR_ERR(sch); |
328 | ret = css_register_subchannel(sch); | 321 | ret = css_register_subchannel(sch); |
329 | if (ret) | 322 | if (ret) |
330 | css_free_subchannel(sch); | 323 | put_device(&sch->dev); |
331 | return ret; | 324 | return ret; |
332 | } | 325 | } |
333 | 326 | ||
@@ -644,7 +637,10 @@ __init_channel_subsystem(struct subchannel_id schid, void *data) | |||
644 | * not working) so we do it now. This is true e.g. for the | 637 | * not working) so we do it now. This is true e.g. for the |
645 | * console subchannel. | 638 | * console subchannel. |
646 | */ | 639 | */ |
647 | css_register_subchannel(sch); | 640 | if (css_register_subchannel(sch)) { |
641 | if (!cio_is_console(schid)) | ||
642 | put_device(&sch->dev); | ||
643 | } | ||
648 | return 0; | 644 | return 0; |
649 | } | 645 | } |
650 | 646 | ||
@@ -661,8 +657,8 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | |||
661 | css->global_pgid.pgid_high.cpu_addr = 0; | 657 | css->global_pgid.pgid_high.cpu_addr = 0; |
662 | #endif | 658 | #endif |
663 | } | 659 | } |
664 | css->global_pgid.cpu_id = ((cpuid_t *) __LC_CPUID)->ident; | 660 | css->global_pgid.cpu_id = S390_lowcore.cpu_id.ident; |
665 | css->global_pgid.cpu_model = ((cpuid_t *) __LC_CPUID)->machine; | 661 | css->global_pgid.cpu_model = S390_lowcore.cpu_id.machine; |
666 | css->global_pgid.tod_high = tod_high; | 662 | css->global_pgid.tod_high = tod_high; |
667 | 663 | ||
668 | } | 664 | } |
@@ -920,8 +916,10 @@ init_channel_subsystem (void) | |||
920 | goto out_device; | 916 | goto out_device; |
921 | } | 917 | } |
922 | ret = device_register(&css->pseudo_subchannel->dev); | 918 | ret = device_register(&css->pseudo_subchannel->dev); |
923 | if (ret) | 919 | if (ret) { |
920 | put_device(&css->pseudo_subchannel->dev); | ||
924 | goto out_file; | 921 | goto out_file; |
922 | } | ||
925 | } | 923 | } |
926 | ret = register_reboot_notifier(&css_reboot_notifier); | 924 | ret = register_reboot_notifier(&css_reboot_notifier); |
927 | if (ret) | 925 | if (ret) |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 3c57c1a18bb8..0f95405c2c5e 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -307,8 +307,11 @@ int ccw_device_is_orphan(struct ccw_device *cdev) | |||
307 | 307 | ||
308 | static void ccw_device_unregister(struct ccw_device *cdev) | 308 | static void ccw_device_unregister(struct ccw_device *cdev) |
309 | { | 309 | { |
310 | if (test_and_clear_bit(1, &cdev->private->registered)) | 310 | if (test_and_clear_bit(1, &cdev->private->registered)) { |
311 | device_del(&cdev->dev); | 311 | device_del(&cdev->dev); |
312 | /* Release reference from device_initialize(). */ | ||
313 | put_device(&cdev->dev); | ||
314 | } | ||
312 | } | 315 | } |
313 | 316 | ||
314 | static void ccw_device_remove_orphan_cb(struct work_struct *work) | 317 | static void ccw_device_remove_orphan_cb(struct work_struct *work) |
@@ -319,7 +322,6 @@ static void ccw_device_remove_orphan_cb(struct work_struct *work) | |||
319 | priv = container_of(work, struct ccw_device_private, kick_work); | 322 | priv = container_of(work, struct ccw_device_private, kick_work); |
320 | cdev = priv->cdev; | 323 | cdev = priv->cdev; |
321 | ccw_device_unregister(cdev); | 324 | ccw_device_unregister(cdev); |
322 | put_device(&cdev->dev); | ||
323 | /* Release cdev reference for workqueue processing. */ | 325 | /* Release cdev reference for workqueue processing. */ |
324 | put_device(&cdev->dev); | 326 | put_device(&cdev->dev); |
325 | } | 327 | } |
@@ -333,15 +335,15 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) | |||
333 | * Forced offline in disconnected state means | 335 | * Forced offline in disconnected state means |
334 | * 'throw away device'. | 336 | * 'throw away device'. |
335 | */ | 337 | */ |
336 | /* Get cdev reference for workqueue processing. */ | ||
337 | if (!get_device(&cdev->dev)) | ||
338 | return; | ||
339 | if (ccw_device_is_orphan(cdev)) { | 338 | if (ccw_device_is_orphan(cdev)) { |
340 | /* | 339 | /* |
341 | * Deregister ccw device. | 340 | * Deregister ccw device. |
342 | * Unfortunately, we cannot do this directly from the | 341 | * Unfortunately, we cannot do this directly from the |
343 | * attribute method. | 342 | * attribute method. |
344 | */ | 343 | */ |
344 | /* Get cdev reference for workqueue processing. */ | ||
345 | if (!get_device(&cdev->dev)) | ||
346 | return; | ||
345 | spin_lock_irqsave(cdev->ccwlock, flags); | 347 | spin_lock_irqsave(cdev->ccwlock, flags); |
346 | cdev->private->state = DEV_STATE_NOT_OPER; | 348 | cdev->private->state = DEV_STATE_NOT_OPER; |
347 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 349 | spin_unlock_irqrestore(cdev->ccwlock, flags); |
@@ -380,30 +382,34 @@ int ccw_device_set_offline(struct ccw_device *cdev) | |||
380 | } | 382 | } |
381 | cdev->online = 0; | 383 | cdev->online = 0; |
382 | spin_lock_irq(cdev->ccwlock); | 384 | spin_lock_irq(cdev->ccwlock); |
383 | ret = ccw_device_offline(cdev); | 385 | /* Wait until a final state or DISCONNECTED is reached */ |
384 | if (ret == -ENODEV) { | 386 | while (!dev_fsm_final_state(cdev) && |
385 | if (cdev->private->state != DEV_STATE_NOT_OPER) { | 387 | cdev->private->state != DEV_STATE_DISCONNECTED) { |
386 | cdev->private->state = DEV_STATE_OFFLINE; | ||
387 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); | ||
388 | } | ||
389 | spin_unlock_irq(cdev->ccwlock); | 388 | spin_unlock_irq(cdev->ccwlock); |
390 | /* Give up reference from ccw_device_set_online(). */ | 389 | wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) || |
391 | put_device(&cdev->dev); | 390 | cdev->private->state == DEV_STATE_DISCONNECTED)); |
392 | return ret; | 391 | spin_lock_irq(cdev->ccwlock); |
393 | } | 392 | } |
393 | ret = ccw_device_offline(cdev); | ||
394 | if (ret) | ||
395 | goto error; | ||
394 | spin_unlock_irq(cdev->ccwlock); | 396 | spin_unlock_irq(cdev->ccwlock); |
395 | if (ret == 0) { | 397 | wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) || |
396 | wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); | 398 | cdev->private->state == DEV_STATE_DISCONNECTED)); |
397 | /* Give up reference from ccw_device_set_online(). */ | 399 | /* Give up reference from ccw_device_set_online(). */ |
398 | put_device(&cdev->dev); | 400 | put_device(&cdev->dev); |
399 | } else { | 401 | return 0; |
400 | CIO_MSG_EVENT(0, "ccw_device_offline returned %d, " | 402 | |
401 | "device 0.%x.%04x\n", | 403 | error: |
402 | ret, cdev->private->dev_id.ssid, | 404 | CIO_MSG_EVENT(0, "ccw_device_offline returned %d, device 0.%x.%04x\n", |
403 | cdev->private->dev_id.devno); | 405 | ret, cdev->private->dev_id.ssid, |
404 | cdev->online = 1; | 406 | cdev->private->dev_id.devno); |
405 | } | 407 | cdev->private->state = DEV_STATE_OFFLINE; |
406 | return ret; | 408 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); |
409 | spin_unlock_irq(cdev->ccwlock); | ||
410 | /* Give up reference from ccw_device_set_online(). */ | ||
411 | put_device(&cdev->dev); | ||
412 | return -ENODEV; | ||
407 | } | 413 | } |
408 | 414 | ||
409 | /** | 415 | /** |
@@ -421,6 +427,7 @@ int ccw_device_set_offline(struct ccw_device *cdev) | |||
421 | int ccw_device_set_online(struct ccw_device *cdev) | 427 | int ccw_device_set_online(struct ccw_device *cdev) |
422 | { | 428 | { |
423 | int ret; | 429 | int ret; |
430 | int ret2; | ||
424 | 431 | ||
425 | if (!cdev) | 432 | if (!cdev) |
426 | return -ENODEV; | 433 | return -ENODEV; |
@@ -444,28 +451,53 @@ int ccw_device_set_online(struct ccw_device *cdev) | |||
444 | put_device(&cdev->dev); | 451 | put_device(&cdev->dev); |
445 | return ret; | 452 | return ret; |
446 | } | 453 | } |
447 | if (cdev->private->state != DEV_STATE_ONLINE) { | 454 | spin_lock_irq(cdev->ccwlock); |
455 | /* Check if online processing was successful */ | ||
456 | if ((cdev->private->state != DEV_STATE_ONLINE) && | ||
457 | (cdev->private->state != DEV_STATE_W4SENSE)) { | ||
458 | spin_unlock_irq(cdev->ccwlock); | ||
448 | /* Give up online reference since onlining failed. */ | 459 | /* Give up online reference since onlining failed. */ |
449 | put_device(&cdev->dev); | 460 | put_device(&cdev->dev); |
450 | return -ENODEV; | 461 | return -ENODEV; |
451 | } | 462 | } |
452 | if (!cdev->drv->set_online || cdev->drv->set_online(cdev) == 0) { | 463 | spin_unlock_irq(cdev->ccwlock); |
453 | cdev->online = 1; | 464 | if (cdev->drv->set_online) |
454 | return 0; | 465 | ret = cdev->drv->set_online(cdev); |
455 | } | 466 | if (ret) |
467 | goto rollback; | ||
468 | cdev->online = 1; | ||
469 | return 0; | ||
470 | |||
471 | rollback: | ||
456 | spin_lock_irq(cdev->ccwlock); | 472 | spin_lock_irq(cdev->ccwlock); |
457 | ret = ccw_device_offline(cdev); | 473 | /* Wait until a final state or DISCONNECTED is reached */ |
474 | while (!dev_fsm_final_state(cdev) && | ||
475 | cdev->private->state != DEV_STATE_DISCONNECTED) { | ||
476 | spin_unlock_irq(cdev->ccwlock); | ||
477 | wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) || | ||
478 | cdev->private->state == DEV_STATE_DISCONNECTED)); | ||
479 | spin_lock_irq(cdev->ccwlock); | ||
480 | } | ||
481 | ret2 = ccw_device_offline(cdev); | ||
482 | if (ret2) | ||
483 | goto error; | ||
484 | spin_unlock_irq(cdev->ccwlock); | ||
485 | wait_event(cdev->private->wait_q, (dev_fsm_final_state(cdev) || | ||
486 | cdev->private->state == DEV_STATE_DISCONNECTED)); | ||
487 | /* Give up online reference since onlining failed. */ | ||
488 | put_device(&cdev->dev); | ||
489 | return ret; | ||
490 | |||
491 | error: | ||
492 | CIO_MSG_EVENT(0, "rollback ccw_device_offline returned %d, " | ||
493 | "device 0.%x.%04x\n", | ||
494 | ret2, cdev->private->dev_id.ssid, | ||
495 | cdev->private->dev_id.devno); | ||
496 | cdev->private->state = DEV_STATE_OFFLINE; | ||
458 | spin_unlock_irq(cdev->ccwlock); | 497 | spin_unlock_irq(cdev->ccwlock); |
459 | if (ret == 0) | ||
460 | wait_event(cdev->private->wait_q, dev_fsm_final_state(cdev)); | ||
461 | else | ||
462 | CIO_MSG_EVENT(0, "ccw_device_offline returned %d, " | ||
463 | "device 0.%x.%04x\n", | ||
464 | ret, cdev->private->dev_id.ssid, | ||
465 | cdev->private->dev_id.devno); | ||
466 | /* Give up online reference since onlining failed. */ | 498 | /* Give up online reference since onlining failed. */ |
467 | put_device(&cdev->dev); | 499 | put_device(&cdev->dev); |
468 | return (ret == 0) ? -ENODEV : ret; | 500 | return ret; |
469 | } | 501 | } |
470 | 502 | ||
471 | static int online_store_handle_offline(struct ccw_device *cdev) | 503 | static int online_store_handle_offline(struct ccw_device *cdev) |
@@ -637,8 +669,12 @@ static int ccw_device_register(struct ccw_device *cdev) | |||
637 | int ret; | 669 | int ret; |
638 | 670 | ||
639 | dev->bus = &ccw_bus_type; | 671 | dev->bus = &ccw_bus_type; |
640 | 672 | ret = dev_set_name(&cdev->dev, "0.%x.%04x", cdev->private->dev_id.ssid, | |
641 | if ((ret = device_add(dev))) | 673 | cdev->private->dev_id.devno); |
674 | if (ret) | ||
675 | return ret; | ||
676 | ret = device_add(dev); | ||
677 | if (ret) | ||
642 | return ret; | 678 | return ret; |
643 | 679 | ||
644 | set_bit(1, &cdev->private->registered); | 680 | set_bit(1, &cdev->private->registered); |
@@ -772,10 +808,8 @@ static struct ccw_device * io_subchannel_create_ccwdev(struct subchannel *sch) | |||
772 | cdev = io_subchannel_allocate_dev(sch); | 808 | cdev = io_subchannel_allocate_dev(sch); |
773 | if (!IS_ERR(cdev)) { | 809 | if (!IS_ERR(cdev)) { |
774 | ret = io_subchannel_initialize_dev(sch, cdev); | 810 | ret = io_subchannel_initialize_dev(sch, cdev); |
775 | if (ret) { | 811 | if (ret) |
776 | kfree(cdev); | ||
777 | cdev = ERR_PTR(ret); | 812 | cdev = ERR_PTR(ret); |
778 | } | ||
779 | } | 813 | } |
780 | return cdev; | 814 | return cdev; |
781 | } | 815 | } |
@@ -1026,9 +1060,6 @@ static void ccw_device_call_sch_unregister(struct work_struct *work) | |||
1026 | return; | 1060 | return; |
1027 | sch = to_subchannel(cdev->dev.parent); | 1061 | sch = to_subchannel(cdev->dev.parent); |
1028 | css_sch_device_unregister(sch); | 1062 | css_sch_device_unregister(sch); |
1029 | /* Reset intparm to zeroes. */ | ||
1030 | sch->config.intparm = 0; | ||
1031 | cio_commit_config(sch); | ||
1032 | /* Release cdev reference for workqueue processing.*/ | 1063 | /* Release cdev reference for workqueue processing.*/ |
1033 | put_device(&cdev->dev); | 1064 | put_device(&cdev->dev); |
1034 | /* Release subchannel reference for local processing. */ | 1065 | /* Release subchannel reference for local processing. */ |
@@ -1037,6 +1068,9 @@ static void ccw_device_call_sch_unregister(struct work_struct *work) | |||
1037 | 1068 | ||
1038 | void ccw_device_schedule_sch_unregister(struct ccw_device *cdev) | 1069 | void ccw_device_schedule_sch_unregister(struct ccw_device *cdev) |
1039 | { | 1070 | { |
1071 | /* Get cdev reference for workqueue processing. */ | ||
1072 | if (!get_device(&cdev->dev)) | ||
1073 | return; | ||
1040 | PREPARE_WORK(&cdev->private->kick_work, | 1074 | PREPARE_WORK(&cdev->private->kick_work, |
1041 | ccw_device_call_sch_unregister); | 1075 | ccw_device_call_sch_unregister); |
1042 | queue_work(slow_path_wq, &cdev->private->kick_work); | 1076 | queue_work(slow_path_wq, &cdev->private->kick_work); |
@@ -1057,9 +1091,6 @@ io_subchannel_recog_done(struct ccw_device *cdev) | |||
1057 | /* Device did not respond in time. */ | 1091 | /* Device did not respond in time. */ |
1058 | case DEV_STATE_NOT_OPER: | 1092 | case DEV_STATE_NOT_OPER: |
1059 | cdev->private->flags.recog_done = 1; | 1093 | cdev->private->flags.recog_done = 1; |
1060 | /* Remove device found not operational. */ | ||
1061 | if (!get_device(&cdev->dev)) | ||
1062 | break; | ||
1063 | ccw_device_schedule_sch_unregister(cdev); | 1094 | ccw_device_schedule_sch_unregister(cdev); |
1064 | if (atomic_dec_and_test(&ccw_device_init_count)) | 1095 | if (atomic_dec_and_test(&ccw_device_init_count)) |
1065 | wake_up(&ccw_device_init_wq); | 1096 | wake_up(&ccw_device_init_wq); |
@@ -1097,13 +1128,6 @@ io_subchannel_recog(struct ccw_device *cdev, struct subchannel *sch) | |||
1097 | init_waitqueue_head(&priv->wait_q); | 1128 | init_waitqueue_head(&priv->wait_q); |
1098 | init_timer(&priv->timer); | 1129 | init_timer(&priv->timer); |
1099 | 1130 | ||
1100 | /* Set an initial name for the device. */ | ||
1101 | if (cio_is_console(sch->schid)) | ||
1102 | cdev->dev.init_name = cio_get_console_cdev_name(sch); | ||
1103 | else | ||
1104 | dev_set_name(&cdev->dev, "0.%x.%04x", | ||
1105 | sch->schid.ssid, sch->schib.pmcw.dev); | ||
1106 | |||
1107 | /* Increase counter of devices currently in recognition. */ | 1131 | /* Increase counter of devices currently in recognition. */ |
1108 | atomic_inc(&ccw_device_init_count); | 1132 | atomic_inc(&ccw_device_init_count); |
1109 | 1133 | ||
@@ -1173,8 +1197,8 @@ static void io_subchannel_irq(struct subchannel *sch) | |||
1173 | 1197 | ||
1174 | cdev = sch_get_cdev(sch); | 1198 | cdev = sch_get_cdev(sch); |
1175 | 1199 | ||
1176 | CIO_TRACE_EVENT(3, "IRQ"); | 1200 | CIO_TRACE_EVENT(6, "IRQ"); |
1177 | CIO_TRACE_EVENT(3, dev_name(&sch->dev)); | 1201 | CIO_TRACE_EVENT(6, dev_name(&sch->dev)); |
1178 | if (cdev) | 1202 | if (cdev) |
1179 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); | 1203 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); |
1180 | } | 1204 | } |
@@ -1212,9 +1236,6 @@ static void io_subchannel_do_unreg(struct work_struct *work) | |||
1212 | 1236 | ||
1213 | sch = container_of(work, struct subchannel, work); | 1237 | sch = container_of(work, struct subchannel, work); |
1214 | css_sch_device_unregister(sch); | 1238 | css_sch_device_unregister(sch); |
1215 | /* Reset intparm to zeroes. */ | ||
1216 | sch->config.intparm = 0; | ||
1217 | cio_commit_config(sch); | ||
1218 | put_device(&sch->dev); | 1239 | put_device(&sch->dev); |
1219 | } | 1240 | } |
1220 | 1241 | ||
@@ -1336,7 +1357,6 @@ io_subchannel_remove (struct subchannel *sch) | |||
1336 | cdev->private->state = DEV_STATE_NOT_OPER; | 1357 | cdev->private->state = DEV_STATE_NOT_OPER; |
1337 | spin_unlock_irqrestore(cdev->ccwlock, flags); | 1358 | spin_unlock_irqrestore(cdev->ccwlock, flags); |
1338 | ccw_device_unregister(cdev); | 1359 | ccw_device_unregister(cdev); |
1339 | put_device(&cdev->dev); | ||
1340 | kfree(sch->private); | 1360 | kfree(sch->private); |
1341 | sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); | 1361 | sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group); |
1342 | return 0; | 1362 | return 0; |
@@ -1573,8 +1593,6 @@ static int purge_fn(struct device *dev, void *data) | |||
1573 | spin_unlock_irq(cdev->ccwlock); | 1593 | spin_unlock_irq(cdev->ccwlock); |
1574 | if (!unreg) | 1594 | if (!unreg) |
1575 | goto out; | 1595 | goto out; |
1576 | if (!get_device(&cdev->dev)) | ||
1577 | goto out; | ||
1578 | CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid, | 1596 | CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", priv->dev_id.ssid, |
1579 | priv->dev_id.devno); | 1597 | priv->dev_id.devno); |
1580 | ccw_device_schedule_sch_unregister(cdev); | 1598 | ccw_device_schedule_sch_unregister(cdev); |
@@ -1690,10 +1708,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) | |||
1690 | spin_unlock_irqrestore(sch->lock, flags); | 1708 | spin_unlock_irqrestore(sch->lock, flags); |
1691 | css_sch_device_unregister(sch); | 1709 | css_sch_device_unregister(sch); |
1692 | spin_lock_irqsave(sch->lock, flags); | 1710 | spin_lock_irqsave(sch->lock, flags); |
1693 | |||
1694 | /* Reset intparm to zeroes. */ | ||
1695 | sch->config.intparm = 0; | ||
1696 | cio_commit_config(sch); | ||
1697 | break; | 1711 | break; |
1698 | case REPROBE: | 1712 | case REPROBE: |
1699 | ccw_device_trigger_reprobe(cdev); | 1713 | ccw_device_trigger_reprobe(cdev); |
@@ -1714,7 +1728,6 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) | |||
1714 | 1728 | ||
1715 | #ifdef CONFIG_CCW_CONSOLE | 1729 | #ifdef CONFIG_CCW_CONSOLE |
1716 | static struct ccw_device console_cdev; | 1730 | static struct ccw_device console_cdev; |
1717 | static char console_cdev_name[10] = "0.x.xxxx"; | ||
1718 | static struct ccw_device_private console_private; | 1731 | static struct ccw_device_private console_private; |
1719 | static int console_cdev_in_use; | 1732 | static int console_cdev_in_use; |
1720 | 1733 | ||
@@ -1798,13 +1811,6 @@ int ccw_device_force_console(void) | |||
1798 | return ccw_device_pm_restore(&console_cdev.dev); | 1811 | return ccw_device_pm_restore(&console_cdev.dev); |
1799 | } | 1812 | } |
1800 | EXPORT_SYMBOL_GPL(ccw_device_force_console); | 1813 | EXPORT_SYMBOL_GPL(ccw_device_force_console); |
1801 | |||
1802 | const char *cio_get_console_cdev_name(struct subchannel *sch) | ||
1803 | { | ||
1804 | snprintf(console_cdev_name, 10, "0.%x.%04x", | ||
1805 | sch->schid.ssid, sch->schib.pmcw.dev); | ||
1806 | return (const char *)console_cdev_name; | ||
1807 | } | ||
1808 | #endif | 1814 | #endif |
1809 | 1815 | ||
1810 | /* | 1816 | /* |
@@ -2022,7 +2028,9 @@ static void __ccw_device_pm_restore(struct ccw_device *cdev) | |||
2022 | spin_unlock_irq(sch->lock); | 2028 | spin_unlock_irq(sch->lock); |
2023 | if (ret) { | 2029 | if (ret) { |
2024 | CIO_MSG_EVENT(0, "Couldn't start recognition for device " | 2030 | CIO_MSG_EVENT(0, "Couldn't start recognition for device " |
2025 | "%s (ret=%d)\n", dev_name(&cdev->dev), ret); | 2031 | "0.%x.%04x (ret=%d)\n", |
2032 | cdev->private->dev_id.ssid, | ||
2033 | cdev->private->dev_id.devno, ret); | ||
2026 | spin_lock_irq(sch->lock); | 2034 | spin_lock_irq(sch->lock); |
2027 | cdev->private->state = DEV_STATE_DISCONNECTED; | 2035 | cdev->private->state = DEV_STATE_DISCONNECTED; |
2028 | spin_unlock_irq(sch->lock); | 2036 | spin_unlock_irq(sch->lock); |
@@ -2085,8 +2093,9 @@ static int ccw_device_pm_restore(struct device *dev) | |||
2085 | } | 2093 | } |
2086 | /* check if the device id has changed */ | 2094 | /* check if the device id has changed */ |
2087 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { | 2095 | if (sch->schib.pmcw.dev != cdev->private->dev_id.devno) { |
2088 | CIO_MSG_EVENT(0, "resume: sch %s: failed (devno changed from " | 2096 | CIO_MSG_EVENT(0, "resume: sch 0.%x.%04x: failed (devno " |
2089 | "%04x to %04x)\n", dev_name(&sch->dev), | 2097 | "changed from %04x to %04x)\n", |
2098 | sch->schid.ssid, sch->schid.sch_no, | ||
2090 | cdev->private->dev_id.devno, | 2099 | cdev->private->dev_id.devno, |
2091 | sch->schib.pmcw.dev); | 2100 | sch->schib.pmcw.dev); |
2092 | goto out_unreg_unlock; | 2101 | goto out_unreg_unlock; |
@@ -2119,8 +2128,9 @@ static int ccw_device_pm_restore(struct device *dev) | |||
2119 | if (cm_enabled) { | 2128 | if (cm_enabled) { |
2120 | ret = ccw_set_cmf(cdev, 1); | 2129 | ret = ccw_set_cmf(cdev, 1); |
2121 | if (ret) { | 2130 | if (ret) { |
2122 | CIO_MSG_EVENT(2, "resume: cdev %s: cmf failed " | 2131 | CIO_MSG_EVENT(2, "resume: cdev 0.%x.%04x: cmf failed " |
2123 | "(rc=%d)\n", dev_name(&cdev->dev), ret); | 2132 | "(rc=%d)\n", cdev->private->dev_id.ssid, |
2133 | cdev->private->dev_id.devno, ret); | ||
2124 | ret = 0; | 2134 | ret = 0; |
2125 | } | 2135 | } |
2126 | } | 2136 | } |
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 3db88c52d287..e728ce447f6e 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -394,6 +394,13 @@ ccw_device_done(struct ccw_device *cdev, int state) | |||
394 | ccw_device_schedule_sch_unregister(cdev); | 394 | ccw_device_schedule_sch_unregister(cdev); |
395 | cdev->private->flags.donotify = 0; | 395 | cdev->private->flags.donotify = 0; |
396 | } | 396 | } |
397 | if (state == DEV_STATE_NOT_OPER) { | ||
398 | CIO_MSG_EVENT(0, "Device %04x gone on subchannel %04x\n", | ||
399 | cdev->private->dev_id.devno, sch->schid.sch_no); | ||
400 | if (!ccw_device_notify(cdev, CIO_GONE)) | ||
401 | ccw_device_schedule_sch_unregister(cdev); | ||
402 | cdev->private->flags.donotify = 0; | ||
403 | } | ||
397 | 404 | ||
398 | if (cdev->private->flags.donotify) { | 405 | if (cdev->private->flags.donotify) { |
399 | cdev->private->flags.donotify = 0; | 406 | cdev->private->flags.donotify = 0; |
@@ -731,6 +738,17 @@ static void ccw_device_generic_notoper(struct ccw_device *cdev, | |||
731 | } | 738 | } |
732 | 739 | ||
733 | /* | 740 | /* |
741 | * Handle path verification event in offline state. | ||
742 | */ | ||
743 | static void ccw_device_offline_verify(struct ccw_device *cdev, | ||
744 | enum dev_event dev_event) | ||
745 | { | ||
746 | struct subchannel *sch = to_subchannel(cdev->dev.parent); | ||
747 | |||
748 | css_schedule_eval(sch->schid); | ||
749 | } | ||
750 | |||
751 | /* | ||
734 | * Handle path verification event. | 752 | * Handle path verification event. |
735 | */ | 753 | */ |
736 | static void | 754 | static void |
@@ -887,6 +905,8 @@ ccw_device_w4sense(struct ccw_device *cdev, enum dev_event dev_event) | |||
887 | } | 905 | } |
888 | call_handler: | 906 | call_handler: |
889 | cdev->private->state = DEV_STATE_ONLINE; | 907 | cdev->private->state = DEV_STATE_ONLINE; |
908 | /* In case sensing interfered with setting the device online */ | ||
909 | wake_up(&cdev->private->wait_q); | ||
890 | /* Call the handler. */ | 910 | /* Call the handler. */ |
891 | if (ccw_device_call_handler(cdev) && cdev->private->flags.doverify) | 911 | if (ccw_device_call_handler(cdev) && cdev->private->flags.doverify) |
892 | /* Start delayed path verification. */ | 912 | /* Start delayed path verification. */ |
@@ -1149,7 +1169,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { | |||
1149 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, | 1169 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1150 | [DEV_EVENT_INTERRUPT] = ccw_device_offline_irq, | 1170 | [DEV_EVENT_INTERRUPT] = ccw_device_offline_irq, |
1151 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, | 1171 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, |
1152 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1172 | [DEV_EVENT_VERIFY] = ccw_device_offline_verify, |
1153 | }, | 1173 | }, |
1154 | [DEV_STATE_VERIFY] = { | 1174 | [DEV_STATE_VERIFY] = { |
1155 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, | 1175 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index b1241f8fae88..ff7748a9199d 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/s390/cio/qdio.h | 2 | * linux/drivers/s390/cio/qdio.h |
3 | * | 3 | * |
4 | * Copyright 2000,2008 IBM Corp. | 4 | * Copyright 2000,2009 IBM Corp. |
5 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com> | 5 | * Author(s): Utz Bacher <utz.bacher@de.ibm.com> |
6 | * Jan Glauber <jang@linux.vnet.ibm.com> | 6 | * Jan Glauber <jang@linux.vnet.ibm.com> |
7 | */ | 7 | */ |
@@ -246,6 +246,7 @@ struct qdio_q { | |||
246 | atomic_t nr_buf_used; | 246 | atomic_t nr_buf_used; |
247 | 247 | ||
248 | struct qdio_irq *irq_ptr; | 248 | struct qdio_irq *irq_ptr; |
249 | struct dentry *debugfs_q; | ||
249 | struct tasklet_struct tasklet; | 250 | struct tasklet_struct tasklet; |
250 | 251 | ||
251 | /* error condition during a data transfer */ | 252 | /* error condition during a data transfer */ |
@@ -267,6 +268,7 @@ struct qdio_irq { | |||
267 | struct qib qib; | 268 | struct qib qib; |
268 | u32 *dsci; /* address of device state change indicator */ | 269 | u32 *dsci; /* address of device state change indicator */ |
269 | struct ccw_device *cdev; | 270 | struct ccw_device *cdev; |
271 | struct dentry *debugfs_dev; | ||
270 | 272 | ||
271 | unsigned long int_parm; | 273 | unsigned long int_parm; |
272 | struct subchannel_id schid; | 274 | struct subchannel_id schid; |
diff --git a/drivers/s390/cio/qdio_debug.c b/drivers/s390/cio/qdio_debug.c index b8626d4df116..1b78f639ead3 100644 --- a/drivers/s390/cio/qdio_debug.c +++ b/drivers/s390/cio/qdio_debug.c | |||
@@ -1,14 +1,12 @@ | |||
1 | /* | 1 | /* |
2 | * drivers/s390/cio/qdio_debug.c | 2 | * drivers/s390/cio/qdio_debug.c |
3 | * | 3 | * |
4 | * Copyright IBM Corp. 2008 | 4 | * Copyright IBM Corp. 2008,2009 |
5 | * | 5 | * |
6 | * Author: Jan Glauber (jang@linux.vnet.ibm.com) | 6 | * Author: Jan Glauber (jang@linux.vnet.ibm.com) |
7 | */ | 7 | */ |
8 | #include <linux/proc_fs.h> | ||
9 | #include <linux/seq_file.h> | 8 | #include <linux/seq_file.h> |
10 | #include <linux/debugfs.h> | 9 | #include <linux/debugfs.h> |
11 | #include <asm/qdio.h> | ||
12 | #include <asm/debug.h> | 10 | #include <asm/debug.h> |
13 | #include "qdio_debug.h" | 11 | #include "qdio_debug.h" |
14 | #include "qdio.h" | 12 | #include "qdio.h" |
@@ -17,10 +15,7 @@ debug_info_t *qdio_dbf_setup; | |||
17 | debug_info_t *qdio_dbf_error; | 15 | debug_info_t *qdio_dbf_error; |
18 | 16 | ||
19 | static struct dentry *debugfs_root; | 17 | static struct dentry *debugfs_root; |
20 | #define MAX_DEBUGFS_QUEUES 32 | 18 | #define QDIO_DEBUGFS_NAME_LEN 10 |
21 | static struct dentry *debugfs_queues[MAX_DEBUGFS_QUEUES] = { NULL }; | ||
22 | static DEFINE_MUTEX(debugfs_mutex); | ||
23 | #define QDIO_DEBUGFS_NAME_LEN 40 | ||
24 | 19 | ||
25 | void qdio_allocate_dbf(struct qdio_initialize *init_data, | 20 | void qdio_allocate_dbf(struct qdio_initialize *init_data, |
26 | struct qdio_irq *irq_ptr) | 21 | struct qdio_irq *irq_ptr) |
@@ -130,20 +125,6 @@ static int qstat_seq_open(struct inode *inode, struct file *filp) | |||
130 | filp->f_path.dentry->d_inode->i_private); | 125 | filp->f_path.dentry->d_inode->i_private); |
131 | } | 126 | } |
132 | 127 | ||
133 | static void remove_debugfs_entry(struct qdio_q *q) | ||
134 | { | ||
135 | int i; | ||
136 | |||
137 | for (i = 0; i < MAX_DEBUGFS_QUEUES; i++) { | ||
138 | if (!debugfs_queues[i]) | ||
139 | continue; | ||
140 | if (debugfs_queues[i]->d_inode->i_private == q) { | ||
141 | debugfs_remove(debugfs_queues[i]); | ||
142 | debugfs_queues[i] = NULL; | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static struct file_operations debugfs_fops = { | 128 | static struct file_operations debugfs_fops = { |
148 | .owner = THIS_MODULE, | 129 | .owner = THIS_MODULE, |
149 | .open = qstat_seq_open, | 130 | .open = qstat_seq_open, |
@@ -155,22 +136,15 @@ static struct file_operations debugfs_fops = { | |||
155 | 136 | ||
156 | static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev) | 137 | static void setup_debugfs_entry(struct qdio_q *q, struct ccw_device *cdev) |
157 | { | 138 | { |
158 | int i = 0; | ||
159 | char name[QDIO_DEBUGFS_NAME_LEN]; | 139 | char name[QDIO_DEBUGFS_NAME_LEN]; |
160 | 140 | ||
161 | while (debugfs_queues[i] != NULL) { | 141 | snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%d", |
162 | i++; | ||
163 | if (i >= MAX_DEBUGFS_QUEUES) | ||
164 | return; | ||
165 | } | ||
166 | snprintf(name, QDIO_DEBUGFS_NAME_LEN, "%s_%s_%d", | ||
167 | dev_name(&cdev->dev), | ||
168 | q->is_input_q ? "input" : "output", | 142 | q->is_input_q ? "input" : "output", |
169 | q->nr); | 143 | q->nr); |
170 | debugfs_queues[i] = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR, | 144 | q->debugfs_q = debugfs_create_file(name, S_IFREG | S_IRUGO | S_IWUSR, |
171 | debugfs_root, q, &debugfs_fops); | 145 | q->irq_ptr->debugfs_dev, q, &debugfs_fops); |
172 | if (IS_ERR(debugfs_queues[i])) | 146 | if (IS_ERR(q->debugfs_q)) |
173 | debugfs_queues[i] = NULL; | 147 | q->debugfs_q = NULL; |
174 | } | 148 | } |
175 | 149 | ||
176 | void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) | 150 | void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) |
@@ -178,12 +152,14 @@ void qdio_setup_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) | |||
178 | struct qdio_q *q; | 152 | struct qdio_q *q; |
179 | int i; | 153 | int i; |
180 | 154 | ||
181 | mutex_lock(&debugfs_mutex); | 155 | irq_ptr->debugfs_dev = debugfs_create_dir(dev_name(&cdev->dev), |
156 | debugfs_root); | ||
157 | if (IS_ERR(irq_ptr->debugfs_dev)) | ||
158 | irq_ptr->debugfs_dev = NULL; | ||
182 | for_each_input_queue(irq_ptr, q, i) | 159 | for_each_input_queue(irq_ptr, q, i) |
183 | setup_debugfs_entry(q, cdev); | 160 | setup_debugfs_entry(q, cdev); |
184 | for_each_output_queue(irq_ptr, q, i) | 161 | for_each_output_queue(irq_ptr, q, i) |
185 | setup_debugfs_entry(q, cdev); | 162 | setup_debugfs_entry(q, cdev); |
186 | mutex_unlock(&debugfs_mutex); | ||
187 | } | 163 | } |
188 | 164 | ||
189 | void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) | 165 | void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cdev) |
@@ -191,17 +167,16 @@ void qdio_shutdown_debug_entries(struct qdio_irq *irq_ptr, struct ccw_device *cd | |||
191 | struct qdio_q *q; | 167 | struct qdio_q *q; |
192 | int i; | 168 | int i; |
193 | 169 | ||
194 | mutex_lock(&debugfs_mutex); | ||
195 | for_each_input_queue(irq_ptr, q, i) | 170 | for_each_input_queue(irq_ptr, q, i) |
196 | remove_debugfs_entry(q); | 171 | debugfs_remove(q->debugfs_q); |
197 | for_each_output_queue(irq_ptr, q, i) | 172 | for_each_output_queue(irq_ptr, q, i) |
198 | remove_debugfs_entry(q); | 173 | debugfs_remove(q->debugfs_q); |
199 | mutex_unlock(&debugfs_mutex); | 174 | debugfs_remove(irq_ptr->debugfs_dev); |
200 | } | 175 | } |
201 | 176 | ||
202 | int __init qdio_debug_init(void) | 177 | int __init qdio_debug_init(void) |
203 | { | 178 | { |
204 | debugfs_root = debugfs_create_dir("qdio_queues", NULL); | 179 | debugfs_root = debugfs_create_dir("qdio", NULL); |
205 | 180 | ||
206 | qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16); | 181 | qdio_dbf_setup = debug_register("qdio_setup", 16, 1, 16); |
207 | debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view); | 182 | debug_register_view(qdio_dbf_setup, &debug_hex_ascii_view); |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 0038750ad945..9aef402a5f1b 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
@@ -798,8 +798,10 @@ static void __tiqdio_inbound_processing(struct qdio_q *q) | |||
798 | 798 | ||
799 | if (!qdio_inbound_q_done(q)) { | 799 | if (!qdio_inbound_q_done(q)) { |
800 | qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop); | 800 | qdio_perf_stat_inc(&perf_stats.thinint_inbound_loop); |
801 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) | 801 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { |
802 | tasklet_schedule(&q->tasklet); | 802 | tasklet_schedule(&q->tasklet); |
803 | return; | ||
804 | } | ||
803 | } | 805 | } |
804 | 806 | ||
805 | qdio_stop_polling(q); | 807 | qdio_stop_polling(q); |
diff --git a/drivers/s390/cio/scsw.c b/drivers/s390/cio/scsw.c deleted file mode 100644 index f8da25ab576d..000000000000 --- a/drivers/s390/cio/scsw.c +++ /dev/null | |||
@@ -1,843 +0,0 @@ | |||
1 | /* | ||
2 | * Helper functions for scsw access. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2008 | ||
5 | * Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/types.h> | ||
9 | #include <linux/module.h> | ||
10 | #include <asm/cio.h> | ||
11 | #include "css.h" | ||
12 | #include "chsc.h" | ||
13 | |||
14 | /** | ||
15 | * scsw_is_tm - check for transport mode scsw | ||
16 | * @scsw: pointer to scsw | ||
17 | * | ||
18 | * Return non-zero if the specified scsw is a transport mode scsw, zero | ||
19 | * otherwise. | ||
20 | */ | ||
21 | int scsw_is_tm(union scsw *scsw) | ||
22 | { | ||
23 | return css_general_characteristics.fcx && (scsw->tm.x == 1); | ||
24 | } | ||
25 | EXPORT_SYMBOL(scsw_is_tm); | ||
26 | |||
27 | /** | ||
28 | * scsw_key - return scsw key field | ||
29 | * @scsw: pointer to scsw | ||
30 | * | ||
31 | * Return the value of the key field of the specified scsw, regardless of | ||
32 | * whether it is a transport mode or command mode scsw. | ||
33 | */ | ||
34 | u32 scsw_key(union scsw *scsw) | ||
35 | { | ||
36 | if (scsw_is_tm(scsw)) | ||
37 | return scsw->tm.key; | ||
38 | else | ||
39 | return scsw->cmd.key; | ||
40 | } | ||
41 | EXPORT_SYMBOL(scsw_key); | ||
42 | |||
43 | /** | ||
44 | * scsw_eswf - return scsw eswf field | ||
45 | * @scsw: pointer to scsw | ||
46 | * | ||
47 | * Return the value of the eswf field of the specified scsw, regardless of | ||
48 | * whether it is a transport mode or command mode scsw. | ||
49 | */ | ||
50 | u32 scsw_eswf(union scsw *scsw) | ||
51 | { | ||
52 | if (scsw_is_tm(scsw)) | ||
53 | return scsw->tm.eswf; | ||
54 | else | ||
55 | return scsw->cmd.eswf; | ||
56 | } | ||
57 | EXPORT_SYMBOL(scsw_eswf); | ||
58 | |||
59 | /** | ||
60 | * scsw_cc - return scsw cc field | ||
61 | * @scsw: pointer to scsw | ||
62 | * | ||
63 | * Return the value of the cc field of the specified scsw, regardless of | ||
64 | * whether it is a transport mode or command mode scsw. | ||
65 | */ | ||
66 | u32 scsw_cc(union scsw *scsw) | ||
67 | { | ||
68 | if (scsw_is_tm(scsw)) | ||
69 | return scsw->tm.cc; | ||
70 | else | ||
71 | return scsw->cmd.cc; | ||
72 | } | ||
73 | EXPORT_SYMBOL(scsw_cc); | ||
74 | |||
75 | /** | ||
76 | * scsw_ectl - return scsw ectl field | ||
77 | * @scsw: pointer to scsw | ||
78 | * | ||
79 | * Return the value of the ectl field of the specified scsw, regardless of | ||
80 | * whether it is a transport mode or command mode scsw. | ||
81 | */ | ||
82 | u32 scsw_ectl(union scsw *scsw) | ||
83 | { | ||
84 | if (scsw_is_tm(scsw)) | ||
85 | return scsw->tm.ectl; | ||
86 | else | ||
87 | return scsw->cmd.ectl; | ||
88 | } | ||
89 | EXPORT_SYMBOL(scsw_ectl); | ||
90 | |||
91 | /** | ||
92 | * scsw_pno - return scsw pno field | ||
93 | * @scsw: pointer to scsw | ||
94 | * | ||
95 | * Return the value of the pno field of the specified scsw, regardless of | ||
96 | * whether it is a transport mode or command mode scsw. | ||
97 | */ | ||
98 | u32 scsw_pno(union scsw *scsw) | ||
99 | { | ||
100 | if (scsw_is_tm(scsw)) | ||
101 | return scsw->tm.pno; | ||
102 | else | ||
103 | return scsw->cmd.pno; | ||
104 | } | ||
105 | EXPORT_SYMBOL(scsw_pno); | ||
106 | |||
107 | /** | ||
108 | * scsw_fctl - return scsw fctl field | ||
109 | * @scsw: pointer to scsw | ||
110 | * | ||
111 | * Return the value of the fctl field of the specified scsw, regardless of | ||
112 | * whether it is a transport mode or command mode scsw. | ||
113 | */ | ||
114 | u32 scsw_fctl(union scsw *scsw) | ||
115 | { | ||
116 | if (scsw_is_tm(scsw)) | ||
117 | return scsw->tm.fctl; | ||
118 | else | ||
119 | return scsw->cmd.fctl; | ||
120 | } | ||
121 | EXPORT_SYMBOL(scsw_fctl); | ||
122 | |||
123 | /** | ||
124 | * scsw_actl - return scsw actl field | ||
125 | * @scsw: pointer to scsw | ||
126 | * | ||
127 | * Return the value of the actl field of the specified scsw, regardless of | ||
128 | * whether it is a transport mode or command mode scsw. | ||
129 | */ | ||
130 | u32 scsw_actl(union scsw *scsw) | ||
131 | { | ||
132 | if (scsw_is_tm(scsw)) | ||
133 | return scsw->tm.actl; | ||
134 | else | ||
135 | return scsw->cmd.actl; | ||
136 | } | ||
137 | EXPORT_SYMBOL(scsw_actl); | ||
138 | |||
139 | /** | ||
140 | * scsw_stctl - return scsw stctl field | ||
141 | * @scsw: pointer to scsw | ||
142 | * | ||
143 | * Return the value of the stctl field of the specified scsw, regardless of | ||
144 | * whether it is a transport mode or command mode scsw. | ||
145 | */ | ||
146 | u32 scsw_stctl(union scsw *scsw) | ||
147 | { | ||
148 | if (scsw_is_tm(scsw)) | ||
149 | return scsw->tm.stctl; | ||
150 | else | ||
151 | return scsw->cmd.stctl; | ||
152 | } | ||
153 | EXPORT_SYMBOL(scsw_stctl); | ||
154 | |||
155 | /** | ||
156 | * scsw_dstat - return scsw dstat field | ||
157 | * @scsw: pointer to scsw | ||
158 | * | ||
159 | * Return the value of the dstat field of the specified scsw, regardless of | ||
160 | * whether it is a transport mode or command mode scsw. | ||
161 | */ | ||
162 | u32 scsw_dstat(union scsw *scsw) | ||
163 | { | ||
164 | if (scsw_is_tm(scsw)) | ||
165 | return scsw->tm.dstat; | ||
166 | else | ||
167 | return scsw->cmd.dstat; | ||
168 | } | ||
169 | EXPORT_SYMBOL(scsw_dstat); | ||
170 | |||
171 | /** | ||
172 | * scsw_cstat - return scsw cstat field | ||
173 | * @scsw: pointer to scsw | ||
174 | * | ||
175 | * Return the value of the cstat field of the specified scsw, regardless of | ||
176 | * whether it is a transport mode or command mode scsw. | ||
177 | */ | ||
178 | u32 scsw_cstat(union scsw *scsw) | ||
179 | { | ||
180 | if (scsw_is_tm(scsw)) | ||
181 | return scsw->tm.cstat; | ||
182 | else | ||
183 | return scsw->cmd.cstat; | ||
184 | } | ||
185 | EXPORT_SYMBOL(scsw_cstat); | ||
186 | |||
187 | /** | ||
188 | * scsw_cmd_is_valid_key - check key field validity | ||
189 | * @scsw: pointer to scsw | ||
190 | * | ||
191 | * Return non-zero if the key field of the specified command mode scsw is | ||
192 | * valid, zero otherwise. | ||
193 | */ | ||
194 | int scsw_cmd_is_valid_key(union scsw *scsw) | ||
195 | { | ||
196 | return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC); | ||
197 | } | ||
198 | EXPORT_SYMBOL(scsw_cmd_is_valid_key); | ||
199 | |||
200 | /** | ||
201 | * scsw_cmd_is_valid_sctl - check fctl field validity | ||
202 | * @scsw: pointer to scsw | ||
203 | * | ||
204 | * Return non-zero if the fctl field of the specified command mode scsw is | ||
205 | * valid, zero otherwise. | ||
206 | */ | ||
207 | int scsw_cmd_is_valid_sctl(union scsw *scsw) | ||
208 | { | ||
209 | return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC); | ||
210 | } | ||
211 | EXPORT_SYMBOL(scsw_cmd_is_valid_sctl); | ||
212 | |||
213 | /** | ||
214 | * scsw_cmd_is_valid_eswf - check eswf field validity | ||
215 | * @scsw: pointer to scsw | ||
216 | * | ||
217 | * Return non-zero if the eswf field of the specified command mode scsw is | ||
218 | * valid, zero otherwise. | ||
219 | */ | ||
220 | int scsw_cmd_is_valid_eswf(union scsw *scsw) | ||
221 | { | ||
222 | return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND); | ||
223 | } | ||
224 | EXPORT_SYMBOL(scsw_cmd_is_valid_eswf); | ||
225 | |||
226 | /** | ||
227 | * scsw_cmd_is_valid_cc - check cc field validity | ||
228 | * @scsw: pointer to scsw | ||
229 | * | ||
230 | * Return non-zero if the cc field of the specified command mode scsw is | ||
231 | * valid, zero otherwise. | ||
232 | */ | ||
233 | int scsw_cmd_is_valid_cc(union scsw *scsw) | ||
234 | { | ||
235 | return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) && | ||
236 | (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND); | ||
237 | } | ||
238 | EXPORT_SYMBOL(scsw_cmd_is_valid_cc); | ||
239 | |||
240 | /** | ||
241 | * scsw_cmd_is_valid_fmt - check fmt field validity | ||
242 | * @scsw: pointer to scsw | ||
243 | * | ||
244 | * Return non-zero if the fmt field of the specified command mode scsw is | ||
245 | * valid, zero otherwise. | ||
246 | */ | ||
247 | int scsw_cmd_is_valid_fmt(union scsw *scsw) | ||
248 | { | ||
249 | return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC); | ||
250 | } | ||
251 | EXPORT_SYMBOL(scsw_cmd_is_valid_fmt); | ||
252 | |||
253 | /** | ||
254 | * scsw_cmd_is_valid_pfch - check pfch field validity | ||
255 | * @scsw: pointer to scsw | ||
256 | * | ||
257 | * Return non-zero if the pfch field of the specified command mode scsw is | ||
258 | * valid, zero otherwise. | ||
259 | */ | ||
260 | int scsw_cmd_is_valid_pfch(union scsw *scsw) | ||
261 | { | ||
262 | return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC); | ||
263 | } | ||
264 | EXPORT_SYMBOL(scsw_cmd_is_valid_pfch); | ||
265 | |||
266 | /** | ||
267 | * scsw_cmd_is_valid_isic - check isic field validity | ||
268 | * @scsw: pointer to scsw | ||
269 | * | ||
270 | * Return non-zero if the isic field of the specified command mode scsw is | ||
271 | * valid, zero otherwise. | ||
272 | */ | ||
273 | int scsw_cmd_is_valid_isic(union scsw *scsw) | ||
274 | { | ||
275 | return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC); | ||
276 | } | ||
277 | EXPORT_SYMBOL(scsw_cmd_is_valid_isic); | ||
278 | |||
279 | /** | ||
280 | * scsw_cmd_is_valid_alcc - check alcc field validity | ||
281 | * @scsw: pointer to scsw | ||
282 | * | ||
283 | * Return non-zero if the alcc field of the specified command mode scsw is | ||
284 | * valid, zero otherwise. | ||
285 | */ | ||
286 | int scsw_cmd_is_valid_alcc(union scsw *scsw) | ||
287 | { | ||
288 | return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC); | ||
289 | } | ||
290 | EXPORT_SYMBOL(scsw_cmd_is_valid_alcc); | ||
291 | |||
292 | /** | ||
293 | * scsw_cmd_is_valid_ssi - check ssi field validity | ||
294 | * @scsw: pointer to scsw | ||
295 | * | ||
296 | * Return non-zero if the ssi field of the specified command mode scsw is | ||
297 | * valid, zero otherwise. | ||
298 | */ | ||
299 | int scsw_cmd_is_valid_ssi(union scsw *scsw) | ||
300 | { | ||
301 | return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC); | ||
302 | } | ||
303 | EXPORT_SYMBOL(scsw_cmd_is_valid_ssi); | ||
304 | |||
305 | /** | ||
306 | * scsw_cmd_is_valid_zcc - check zcc field validity | ||
307 | * @scsw: pointer to scsw | ||
308 | * | ||
309 | * Return non-zero if the zcc field of the specified command mode scsw is | ||
310 | * valid, zero otherwise. | ||
311 | */ | ||
312 | int scsw_cmd_is_valid_zcc(union scsw *scsw) | ||
313 | { | ||
314 | return (scsw->cmd.fctl & SCSW_FCTL_START_FUNC) && | ||
315 | (scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS); | ||
316 | } | ||
317 | EXPORT_SYMBOL(scsw_cmd_is_valid_zcc); | ||
318 | |||
319 | /** | ||
320 | * scsw_cmd_is_valid_ectl - check ectl field validity | ||
321 | * @scsw: pointer to scsw | ||
322 | * | ||
323 | * Return non-zero if the ectl field of the specified command mode scsw is | ||
324 | * valid, zero otherwise. | ||
325 | */ | ||
326 | int scsw_cmd_is_valid_ectl(union scsw *scsw) | ||
327 | { | ||
328 | return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) && | ||
329 | !(scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS) && | ||
330 | (scsw->cmd.stctl & SCSW_STCTL_ALERT_STATUS); | ||
331 | } | ||
332 | EXPORT_SYMBOL(scsw_cmd_is_valid_ectl); | ||
333 | |||
334 | /** | ||
335 | * scsw_cmd_is_valid_pno - check pno field validity | ||
336 | * @scsw: pointer to scsw | ||
337 | * | ||
338 | * Return non-zero if the pno field of the specified command mode scsw is | ||
339 | * valid, zero otherwise. | ||
340 | */ | ||
341 | int scsw_cmd_is_valid_pno(union scsw *scsw) | ||
342 | { | ||
343 | return (scsw->cmd.fctl != 0) && | ||
344 | (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) && | ||
345 | (!(scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS) || | ||
346 | ((scsw->cmd.stctl & SCSW_STCTL_INTER_STATUS) && | ||
347 | (scsw->cmd.actl & SCSW_ACTL_SUSPENDED))); | ||
348 | } | ||
349 | EXPORT_SYMBOL(scsw_cmd_is_valid_pno); | ||
350 | |||
351 | /** | ||
352 | * scsw_cmd_is_valid_fctl - check fctl field validity | ||
353 | * @scsw: pointer to scsw | ||
354 | * | ||
355 | * Return non-zero if the fctl field of the specified command mode scsw is | ||
356 | * valid, zero otherwise. | ||
357 | */ | ||
358 | int scsw_cmd_is_valid_fctl(union scsw *scsw) | ||
359 | { | ||
360 | /* Only valid if pmcw.dnv == 1*/ | ||
361 | return 1; | ||
362 | } | ||
363 | EXPORT_SYMBOL(scsw_cmd_is_valid_fctl); | ||
364 | |||
365 | /** | ||
366 | * scsw_cmd_is_valid_actl - check actl field validity | ||
367 | * @scsw: pointer to scsw | ||
368 | * | ||
369 | * Return non-zero if the actl field of the specified command mode scsw is | ||
370 | * valid, zero otherwise. | ||
371 | */ | ||
372 | int scsw_cmd_is_valid_actl(union scsw *scsw) | ||
373 | { | ||
374 | /* Only valid if pmcw.dnv == 1*/ | ||
375 | return 1; | ||
376 | } | ||
377 | EXPORT_SYMBOL(scsw_cmd_is_valid_actl); | ||
378 | |||
379 | /** | ||
380 | * scsw_cmd_is_valid_stctl - check stctl field validity | ||
381 | * @scsw: pointer to scsw | ||
382 | * | ||
383 | * Return non-zero if the stctl field of the specified command mode scsw is | ||
384 | * valid, zero otherwise. | ||
385 | */ | ||
386 | int scsw_cmd_is_valid_stctl(union scsw *scsw) | ||
387 | { | ||
388 | /* Only valid if pmcw.dnv == 1*/ | ||
389 | return 1; | ||
390 | } | ||
391 | EXPORT_SYMBOL(scsw_cmd_is_valid_stctl); | ||
392 | |||
393 | /** | ||
394 | * scsw_cmd_is_valid_dstat - check dstat field validity | ||
395 | * @scsw: pointer to scsw | ||
396 | * | ||
397 | * Return non-zero if the dstat field of the specified command mode scsw is | ||
398 | * valid, zero otherwise. | ||
399 | */ | ||
400 | int scsw_cmd_is_valid_dstat(union scsw *scsw) | ||
401 | { | ||
402 | return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) && | ||
403 | (scsw->cmd.cc != 3); | ||
404 | } | ||
405 | EXPORT_SYMBOL(scsw_cmd_is_valid_dstat); | ||
406 | |||
407 | /** | ||
408 | * scsw_cmd_is_valid_cstat - check cstat field validity | ||
409 | * @scsw: pointer to scsw | ||
410 | * | ||
411 | * Return non-zero if the cstat field of the specified command mode scsw is | ||
412 | * valid, zero otherwise. | ||
413 | */ | ||
414 | int scsw_cmd_is_valid_cstat(union scsw *scsw) | ||
415 | { | ||
416 | return (scsw->cmd.stctl & SCSW_STCTL_STATUS_PEND) && | ||
417 | (scsw->cmd.cc != 3); | ||
418 | } | ||
419 | EXPORT_SYMBOL(scsw_cmd_is_valid_cstat); | ||
420 | |||
421 | /** | ||
422 | * scsw_tm_is_valid_key - check key field validity | ||
423 | * @scsw: pointer to scsw | ||
424 | * | ||
425 | * Return non-zero if the key field of the specified transport mode scsw is | ||
426 | * valid, zero otherwise. | ||
427 | */ | ||
428 | int scsw_tm_is_valid_key(union scsw *scsw) | ||
429 | { | ||
430 | return (scsw->tm.fctl & SCSW_FCTL_START_FUNC); | ||
431 | } | ||
432 | EXPORT_SYMBOL(scsw_tm_is_valid_key); | ||
433 | |||
434 | /** | ||
435 | * scsw_tm_is_valid_eswf - check eswf field validity | ||
436 | * @scsw: pointer to scsw | ||
437 | * | ||
438 | * Return non-zero if the eswf field of the specified transport mode scsw is | ||
439 | * valid, zero otherwise. | ||
440 | */ | ||
441 | int scsw_tm_is_valid_eswf(union scsw *scsw) | ||
442 | { | ||
443 | return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND); | ||
444 | } | ||
445 | EXPORT_SYMBOL(scsw_tm_is_valid_eswf); | ||
446 | |||
447 | /** | ||
448 | * scsw_tm_is_valid_cc - check cc field validity | ||
449 | * @scsw: pointer to scsw | ||
450 | * | ||
451 | * Return non-zero if the cc field of the specified transport mode scsw is | ||
452 | * valid, zero otherwise. | ||
453 | */ | ||
454 | int scsw_tm_is_valid_cc(union scsw *scsw) | ||
455 | { | ||
456 | return (scsw->tm.fctl & SCSW_FCTL_START_FUNC) && | ||
457 | (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND); | ||
458 | } | ||
459 | EXPORT_SYMBOL(scsw_tm_is_valid_cc); | ||
460 | |||
461 | /** | ||
462 | * scsw_tm_is_valid_fmt - check fmt field validity | ||
463 | * @scsw: pointer to scsw | ||
464 | * | ||
465 | * Return non-zero if the fmt field of the specified transport mode scsw is | ||
466 | * valid, zero otherwise. | ||
467 | */ | ||
468 | int scsw_tm_is_valid_fmt(union scsw *scsw) | ||
469 | { | ||
470 | return 1; | ||
471 | } | ||
472 | EXPORT_SYMBOL(scsw_tm_is_valid_fmt); | ||
473 | |||
474 | /** | ||
475 | * scsw_tm_is_valid_x - check x field validity | ||
476 | * @scsw: pointer to scsw | ||
477 | * | ||
478 | * Return non-zero if the x field of the specified transport mode scsw is | ||
479 | * valid, zero otherwise. | ||
480 | */ | ||
481 | int scsw_tm_is_valid_x(union scsw *scsw) | ||
482 | { | ||
483 | return 1; | ||
484 | } | ||
485 | EXPORT_SYMBOL(scsw_tm_is_valid_x); | ||
486 | |||
487 | /** | ||
488 | * scsw_tm_is_valid_q - check q field validity | ||
489 | * @scsw: pointer to scsw | ||
490 | * | ||
491 | * Return non-zero if the q field of the specified transport mode scsw is | ||
492 | * valid, zero otherwise. | ||
493 | */ | ||
494 | int scsw_tm_is_valid_q(union scsw *scsw) | ||
495 | { | ||
496 | return 1; | ||
497 | } | ||
498 | EXPORT_SYMBOL(scsw_tm_is_valid_q); | ||
499 | |||
500 | /** | ||
501 | * scsw_tm_is_valid_ectl - check ectl field validity | ||
502 | * @scsw: pointer to scsw | ||
503 | * | ||
504 | * Return non-zero if the ectl field of the specified transport mode scsw is | ||
505 | * valid, zero otherwise. | ||
506 | */ | ||
507 | int scsw_tm_is_valid_ectl(union scsw *scsw) | ||
508 | { | ||
509 | return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) && | ||
510 | !(scsw->tm.stctl & SCSW_STCTL_INTER_STATUS) && | ||
511 | (scsw->tm.stctl & SCSW_STCTL_ALERT_STATUS); | ||
512 | } | ||
513 | EXPORT_SYMBOL(scsw_tm_is_valid_ectl); | ||
514 | |||
515 | /** | ||
516 | * scsw_tm_is_valid_pno - check pno field validity | ||
517 | * @scsw: pointer to scsw | ||
518 | * | ||
519 | * Return non-zero if the pno field of the specified transport mode scsw is | ||
520 | * valid, zero otherwise. | ||
521 | */ | ||
522 | int scsw_tm_is_valid_pno(union scsw *scsw) | ||
523 | { | ||
524 | return (scsw->tm.fctl != 0) && | ||
525 | (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) && | ||
526 | (!(scsw->tm.stctl & SCSW_STCTL_INTER_STATUS) || | ||
527 | ((scsw->tm.stctl & SCSW_STCTL_INTER_STATUS) && | ||
528 | (scsw->tm.actl & SCSW_ACTL_SUSPENDED))); | ||
529 | } | ||
530 | EXPORT_SYMBOL(scsw_tm_is_valid_pno); | ||
531 | |||
532 | /** | ||
533 | * scsw_tm_is_valid_fctl - check fctl field validity | ||
534 | * @scsw: pointer to scsw | ||
535 | * | ||
536 | * Return non-zero if the fctl field of the specified transport mode scsw is | ||
537 | * valid, zero otherwise. | ||
538 | */ | ||
539 | int scsw_tm_is_valid_fctl(union scsw *scsw) | ||
540 | { | ||
541 | /* Only valid if pmcw.dnv == 1*/ | ||
542 | return 1; | ||
543 | } | ||
544 | EXPORT_SYMBOL(scsw_tm_is_valid_fctl); | ||
545 | |||
546 | /** | ||
547 | * scsw_tm_is_valid_actl - check actl field validity | ||
548 | * @scsw: pointer to scsw | ||
549 | * | ||
550 | * Return non-zero if the actl field of the specified transport mode scsw is | ||
551 | * valid, zero otherwise. | ||
552 | */ | ||
553 | int scsw_tm_is_valid_actl(union scsw *scsw) | ||
554 | { | ||
555 | /* Only valid if pmcw.dnv == 1*/ | ||
556 | return 1; | ||
557 | } | ||
558 | EXPORT_SYMBOL(scsw_tm_is_valid_actl); | ||
559 | |||
560 | /** | ||
561 | * scsw_tm_is_valid_stctl - check stctl field validity | ||
562 | * @scsw: pointer to scsw | ||
563 | * | ||
564 | * Return non-zero if the stctl field of the specified transport mode scsw is | ||
565 | * valid, zero otherwise. | ||
566 | */ | ||
567 | int scsw_tm_is_valid_stctl(union scsw *scsw) | ||
568 | { | ||
569 | /* Only valid if pmcw.dnv == 1*/ | ||
570 | return 1; | ||
571 | } | ||
572 | EXPORT_SYMBOL(scsw_tm_is_valid_stctl); | ||
573 | |||
574 | /** | ||
575 | * scsw_tm_is_valid_dstat - check dstat field validity | ||
576 | * @scsw: pointer to scsw | ||
577 | * | ||
578 | * Return non-zero if the dstat field of the specified transport mode scsw is | ||
579 | * valid, zero otherwise. | ||
580 | */ | ||
581 | int scsw_tm_is_valid_dstat(union scsw *scsw) | ||
582 | { | ||
583 | return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) && | ||
584 | (scsw->tm.cc != 3); | ||
585 | } | ||
586 | EXPORT_SYMBOL(scsw_tm_is_valid_dstat); | ||
587 | |||
588 | /** | ||
589 | * scsw_tm_is_valid_cstat - check cstat field validity | ||
590 | * @scsw: pointer to scsw | ||
591 | * | ||
592 | * Return non-zero if the cstat field of the specified transport mode scsw is | ||
593 | * valid, zero otherwise. | ||
594 | */ | ||
595 | int scsw_tm_is_valid_cstat(union scsw *scsw) | ||
596 | { | ||
597 | return (scsw->tm.stctl & SCSW_STCTL_STATUS_PEND) && | ||
598 | (scsw->tm.cc != 3); | ||
599 | } | ||
600 | EXPORT_SYMBOL(scsw_tm_is_valid_cstat); | ||
601 | |||
602 | /** | ||
603 | * scsw_tm_is_valid_fcxs - check fcxs field validity | ||
604 | * @scsw: pointer to scsw | ||
605 | * | ||
606 | * Return non-zero if the fcxs field of the specified transport mode scsw is | ||
607 | * valid, zero otherwise. | ||
608 | */ | ||
609 | int scsw_tm_is_valid_fcxs(union scsw *scsw) | ||
610 | { | ||
611 | return 1; | ||
612 | } | ||
613 | EXPORT_SYMBOL(scsw_tm_is_valid_fcxs); | ||
614 | |||
615 | /** | ||
616 | * scsw_tm_is_valid_schxs - check schxs field validity | ||
617 | * @scsw: pointer to scsw | ||
618 | * | ||
619 | * Return non-zero if the schxs field of the specified transport mode scsw is | ||
620 | * valid, zero otherwise. | ||
621 | */ | ||
622 | int scsw_tm_is_valid_schxs(union scsw *scsw) | ||
623 | { | ||
624 | return (scsw->tm.cstat & (SCHN_STAT_PROG_CHECK | | ||
625 | SCHN_STAT_INTF_CTRL_CHK | | ||
626 | SCHN_STAT_PROT_CHECK | | ||
627 | SCHN_STAT_CHN_DATA_CHK)); | ||
628 | } | ||
629 | EXPORT_SYMBOL(scsw_tm_is_valid_schxs); | ||
630 | |||
631 | /** | ||
632 | * scsw_is_valid_actl - check actl field validity | ||
633 | * @scsw: pointer to scsw | ||
634 | * | ||
635 | * Return non-zero if the actl field of the specified scsw is valid, | ||
636 | * regardless of whether it is a transport mode or command mode scsw. | ||
637 | * Return zero if the field does not contain a valid value. | ||
638 | */ | ||
639 | int scsw_is_valid_actl(union scsw *scsw) | ||
640 | { | ||
641 | if (scsw_is_tm(scsw)) | ||
642 | return scsw_tm_is_valid_actl(scsw); | ||
643 | else | ||
644 | return scsw_cmd_is_valid_actl(scsw); | ||
645 | } | ||
646 | EXPORT_SYMBOL(scsw_is_valid_actl); | ||
647 | |||
648 | /** | ||
649 | * scsw_is_valid_cc - check cc field validity | ||
650 | * @scsw: pointer to scsw | ||
651 | * | ||
652 | * Return non-zero if the cc field of the specified scsw is valid, | ||
653 | * regardless of whether it is a transport mode or command mode scsw. | ||
654 | * Return zero if the field does not contain a valid value. | ||
655 | */ | ||
656 | int scsw_is_valid_cc(union scsw *scsw) | ||
657 | { | ||
658 | if (scsw_is_tm(scsw)) | ||
659 | return scsw_tm_is_valid_cc(scsw); | ||
660 | else | ||
661 | return scsw_cmd_is_valid_cc(scsw); | ||
662 | } | ||
663 | EXPORT_SYMBOL(scsw_is_valid_cc); | ||
664 | |||
665 | /** | ||
666 | * scsw_is_valid_cstat - check cstat field validity | ||
667 | * @scsw: pointer to scsw | ||
668 | * | ||
669 | * Return non-zero if the cstat field of the specified scsw is valid, | ||
670 | * regardless of whether it is a transport mode or command mode scsw. | ||
671 | * Return zero if the field does not contain a valid value. | ||
672 | */ | ||
673 | int scsw_is_valid_cstat(union scsw *scsw) | ||
674 | { | ||
675 | if (scsw_is_tm(scsw)) | ||
676 | return scsw_tm_is_valid_cstat(scsw); | ||
677 | else | ||
678 | return scsw_cmd_is_valid_cstat(scsw); | ||
679 | } | ||
680 | EXPORT_SYMBOL(scsw_is_valid_cstat); | ||
681 | |||
682 | /** | ||
683 | * scsw_is_valid_dstat - check dstat field validity | ||
684 | * @scsw: pointer to scsw | ||
685 | * | ||
686 | * Return non-zero if the dstat field of the specified scsw is valid, | ||
687 | * regardless of whether it is a transport mode or command mode scsw. | ||
688 | * Return zero if the field does not contain a valid value. | ||
689 | */ | ||
690 | int scsw_is_valid_dstat(union scsw *scsw) | ||
691 | { | ||
692 | if (scsw_is_tm(scsw)) | ||
693 | return scsw_tm_is_valid_dstat(scsw); | ||
694 | else | ||
695 | return scsw_cmd_is_valid_dstat(scsw); | ||
696 | } | ||
697 | EXPORT_SYMBOL(scsw_is_valid_dstat); | ||
698 | |||
699 | /** | ||
700 | * scsw_is_valid_ectl - check ectl field validity | ||
701 | * @scsw: pointer to scsw | ||
702 | * | ||
703 | * Return non-zero if the ectl field of the specified scsw is valid, | ||
704 | * regardless of whether it is a transport mode or command mode scsw. | ||
705 | * Return zero if the field does not contain a valid value. | ||
706 | */ | ||
707 | int scsw_is_valid_ectl(union scsw *scsw) | ||
708 | { | ||
709 | if (scsw_is_tm(scsw)) | ||
710 | return scsw_tm_is_valid_ectl(scsw); | ||
711 | else | ||
712 | return scsw_cmd_is_valid_ectl(scsw); | ||
713 | } | ||
714 | EXPORT_SYMBOL(scsw_is_valid_ectl); | ||
715 | |||
716 | /** | ||
717 | * scsw_is_valid_eswf - check eswf field validity | ||
718 | * @scsw: pointer to scsw | ||
719 | * | ||
720 | * Return non-zero if the eswf field of the specified scsw is valid, | ||
721 | * regardless of whether it is a transport mode or command mode scsw. | ||
722 | * Return zero if the field does not contain a valid value. | ||
723 | */ | ||
724 | int scsw_is_valid_eswf(union scsw *scsw) | ||
725 | { | ||
726 | if (scsw_is_tm(scsw)) | ||
727 | return scsw_tm_is_valid_eswf(scsw); | ||
728 | else | ||
729 | return scsw_cmd_is_valid_eswf(scsw); | ||
730 | } | ||
731 | EXPORT_SYMBOL(scsw_is_valid_eswf); | ||
732 | |||
733 | /** | ||
734 | * scsw_is_valid_fctl - check fctl field validity | ||
735 | * @scsw: pointer to scsw | ||
736 | * | ||
737 | * Return non-zero if the fctl field of the specified scsw is valid, | ||
738 | * regardless of whether it is a transport mode or command mode scsw. | ||
739 | * Return zero if the field does not contain a valid value. | ||
740 | */ | ||
741 | int scsw_is_valid_fctl(union scsw *scsw) | ||
742 | { | ||
743 | if (scsw_is_tm(scsw)) | ||
744 | return scsw_tm_is_valid_fctl(scsw); | ||
745 | else | ||
746 | return scsw_cmd_is_valid_fctl(scsw); | ||
747 | } | ||
748 | EXPORT_SYMBOL(scsw_is_valid_fctl); | ||
749 | |||
750 | /** | ||
751 | * scsw_is_valid_key - check key field validity | ||
752 | * @scsw: pointer to scsw | ||
753 | * | ||
754 | * Return non-zero if the key field of the specified scsw is valid, | ||
755 | * regardless of whether it is a transport mode or command mode scsw. | ||
756 | * Return zero if the field does not contain a valid value. | ||
757 | */ | ||
758 | int scsw_is_valid_key(union scsw *scsw) | ||
759 | { | ||
760 | if (scsw_is_tm(scsw)) | ||
761 | return scsw_tm_is_valid_key(scsw); | ||
762 | else | ||
763 | return scsw_cmd_is_valid_key(scsw); | ||
764 | } | ||
765 | EXPORT_SYMBOL(scsw_is_valid_key); | ||
766 | |||
767 | /** | ||
768 | * scsw_is_valid_pno - check pno field validity | ||
769 | * @scsw: pointer to scsw | ||
770 | * | ||
771 | * Return non-zero if the pno field of the specified scsw is valid, | ||
772 | * regardless of whether it is a transport mode or command mode scsw. | ||
773 | * Return zero if the field does not contain a valid value. | ||
774 | */ | ||
775 | int scsw_is_valid_pno(union scsw *scsw) | ||
776 | { | ||
777 | if (scsw_is_tm(scsw)) | ||
778 | return scsw_tm_is_valid_pno(scsw); | ||
779 | else | ||
780 | return scsw_cmd_is_valid_pno(scsw); | ||
781 | } | ||
782 | EXPORT_SYMBOL(scsw_is_valid_pno); | ||
783 | |||
784 | /** | ||
785 | * scsw_is_valid_stctl - check stctl field validity | ||
786 | * @scsw: pointer to scsw | ||
787 | * | ||
788 | * Return non-zero if the stctl field of the specified scsw is valid, | ||
789 | * regardless of whether it is a transport mode or command mode scsw. | ||
790 | * Return zero if the field does not contain a valid value. | ||
791 | */ | ||
792 | int scsw_is_valid_stctl(union scsw *scsw) | ||
793 | { | ||
794 | if (scsw_is_tm(scsw)) | ||
795 | return scsw_tm_is_valid_stctl(scsw); | ||
796 | else | ||
797 | return scsw_cmd_is_valid_stctl(scsw); | ||
798 | } | ||
799 | EXPORT_SYMBOL(scsw_is_valid_stctl); | ||
800 | |||
801 | /** | ||
802 | * scsw_cmd_is_solicited - check for solicited scsw | ||
803 | * @scsw: pointer to scsw | ||
804 | * | ||
805 | * Return non-zero if the command mode scsw indicates that the associated | ||
806 | * status condition is solicited, zero if it is unsolicited. | ||
807 | */ | ||
808 | int scsw_cmd_is_solicited(union scsw *scsw) | ||
809 | { | ||
810 | return (scsw->cmd.cc != 0) || (scsw->cmd.stctl != | ||
811 | (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)); | ||
812 | } | ||
813 | EXPORT_SYMBOL(scsw_cmd_is_solicited); | ||
814 | |||
815 | /** | ||
816 | * scsw_tm_is_solicited - check for solicited scsw | ||
817 | * @scsw: pointer to scsw | ||
818 | * | ||
819 | * Return non-zero if the transport mode scsw indicates that the associated | ||
820 | * status condition is solicited, zero if it is unsolicited. | ||
821 | */ | ||
822 | int scsw_tm_is_solicited(union scsw *scsw) | ||
823 | { | ||
824 | return (scsw->tm.cc != 0) || (scsw->tm.stctl != | ||
825 | (SCSW_STCTL_STATUS_PEND | SCSW_STCTL_ALERT_STATUS)); | ||
826 | } | ||
827 | EXPORT_SYMBOL(scsw_tm_is_solicited); | ||
828 | |||
829 | /** | ||
830 | * scsw_is_solicited - check for solicited scsw | ||
831 | * @scsw: pointer to scsw | ||
832 | * | ||
833 | * Return non-zero if the transport or command mode scsw indicates that the | ||
834 | * associated status condition is solicited, zero if it is unsolicited. | ||
835 | */ | ||
836 | int scsw_is_solicited(union scsw *scsw) | ||
837 | { | ||
838 | if (scsw_is_tm(scsw)) | ||
839 | return scsw_tm_is_solicited(scsw); | ||
840 | else | ||
841 | return scsw_cmd_is_solicited(scsw); | ||
842 | } | ||
843 | EXPORT_SYMBOL(scsw_is_solicited); | ||
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index ed3dcdea7fe1..090b32a339c6 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -648,7 +648,9 @@ static int ap_bus_suspend(struct device *dev, pm_message_t state) | |||
648 | /* Poll on the device until all requests are finished. */ | 648 | /* Poll on the device until all requests are finished. */ |
649 | do { | 649 | do { |
650 | flags = 0; | 650 | flags = 0; |
651 | spin_lock_bh(&ap_dev->lock); | ||
651 | __ap_poll_device(ap_dev, &flags); | 652 | __ap_poll_device(ap_dev, &flags); |
653 | spin_unlock_bh(&ap_dev->lock); | ||
652 | } while ((flags & 1) || (flags & 2)); | 654 | } while ((flags & 1) || (flags & 2)); |
653 | 655 | ||
654 | ap_device_remove(dev); | 656 | ap_device_remove(dev); |
@@ -1109,12 +1111,15 @@ static void ap_scan_bus(struct work_struct *unused) | |||
1109 | 1111 | ||
1110 | ap_dev->device.bus = &ap_bus_type; | 1112 | ap_dev->device.bus = &ap_bus_type; |
1111 | ap_dev->device.parent = ap_root_device; | 1113 | ap_dev->device.parent = ap_root_device; |
1112 | dev_set_name(&ap_dev->device, "card%02x", | 1114 | if (dev_set_name(&ap_dev->device, "card%02x", |
1113 | AP_QID_DEVICE(ap_dev->qid)); | 1115 | AP_QID_DEVICE(ap_dev->qid))) { |
1116 | kfree(ap_dev); | ||
1117 | continue; | ||
1118 | } | ||
1114 | ap_dev->device.release = ap_device_release; | 1119 | ap_dev->device.release = ap_device_release; |
1115 | rc = device_register(&ap_dev->device); | 1120 | rc = device_register(&ap_dev->device); |
1116 | if (rc) { | 1121 | if (rc) { |
1117 | kfree(ap_dev); | 1122 | put_device(&ap_dev->device); |
1118 | continue; | 1123 | continue; |
1119 | } | 1124 | } |
1120 | /* Add device attributes. */ | 1125 | /* Add device attributes. */ |
@@ -1407,14 +1412,12 @@ static void ap_reset(struct ap_device *ap_dev) | |||
1407 | 1412 | ||
1408 | static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags) | 1413 | static int __ap_poll_device(struct ap_device *ap_dev, unsigned long *flags) |
1409 | { | 1414 | { |
1410 | spin_lock(&ap_dev->lock); | ||
1411 | if (!ap_dev->unregistered) { | 1415 | if (!ap_dev->unregistered) { |
1412 | if (ap_poll_queue(ap_dev, flags)) | 1416 | if (ap_poll_queue(ap_dev, flags)) |
1413 | ap_dev->unregistered = 1; | 1417 | ap_dev->unregistered = 1; |
1414 | if (ap_dev->reset == AP_RESET_DO) | 1418 | if (ap_dev->reset == AP_RESET_DO) |
1415 | ap_reset(ap_dev); | 1419 | ap_reset(ap_dev); |
1416 | } | 1420 | } |
1417 | spin_unlock(&ap_dev->lock); | ||
1418 | return 0; | 1421 | return 0; |
1419 | } | 1422 | } |
1420 | 1423 | ||
@@ -1441,7 +1444,9 @@ static void ap_poll_all(unsigned long dummy) | |||
1441 | flags = 0; | 1444 | flags = 0; |
1442 | spin_lock(&ap_device_list_lock); | 1445 | spin_lock(&ap_device_list_lock); |
1443 | list_for_each_entry(ap_dev, &ap_device_list, list) { | 1446 | list_for_each_entry(ap_dev, &ap_device_list, list) { |
1447 | spin_lock(&ap_dev->lock); | ||
1444 | __ap_poll_device(ap_dev, &flags); | 1448 | __ap_poll_device(ap_dev, &flags); |
1449 | spin_unlock(&ap_dev->lock); | ||
1445 | } | 1450 | } |
1446 | spin_unlock(&ap_device_list_lock); | 1451 | spin_unlock(&ap_device_list_lock); |
1447 | } while (flags & 1); | 1452 | } while (flags & 1); |
@@ -1487,7 +1492,9 @@ static int ap_poll_thread(void *data) | |||
1487 | flags = 0; | 1492 | flags = 0; |
1488 | spin_lock_bh(&ap_device_list_lock); | 1493 | spin_lock_bh(&ap_device_list_lock); |
1489 | list_for_each_entry(ap_dev, &ap_device_list, list) { | 1494 | list_for_each_entry(ap_dev, &ap_device_list, list) { |
1495 | spin_lock(&ap_dev->lock); | ||
1490 | __ap_poll_device(ap_dev, &flags); | 1496 | __ap_poll_device(ap_dev, &flags); |
1497 | spin_unlock(&ap_dev->lock); | ||
1491 | } | 1498 | } |
1492 | spin_unlock_bh(&ap_device_list_lock); | 1499 | spin_unlock_bh(&ap_device_list_lock); |
1493 | } | 1500 | } |
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index e38e5d306faf..2930fc763ac5 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -403,10 +403,14 @@ static __init int early_put_chars(u32 vtermno, const char *buf, int count) | |||
403 | return len; | 403 | return len; |
404 | } | 404 | } |
405 | 405 | ||
406 | void __init s390_virtio_console_init(void) | 406 | static int __init s390_virtio_console_init(void) |
407 | { | 407 | { |
408 | virtio_cons_early_init(early_put_chars); | 408 | if (!MACHINE_IS_KVM) |
409 | return -ENODEV; | ||
410 | return virtio_cons_early_init(early_put_chars); | ||
409 | } | 411 | } |
412 | console_initcall(s390_virtio_console_init); | ||
413 | |||
410 | 414 | ||
411 | /* | 415 | /* |
412 | * We do this after core stuff, but before the drivers. | 416 | * We do this after core stuff, but before the drivers. |
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c index 271c4a82e84b..9215fbbccc08 100644 --- a/drivers/s390/net/netiucv.c +++ b/drivers/s390/net/netiucv.c | |||
@@ -1838,9 +1838,10 @@ static int netiucv_register_device(struct net_device *ndev) | |||
1838 | return -ENOMEM; | 1838 | return -ENOMEM; |
1839 | 1839 | ||
1840 | ret = device_register(dev); | 1840 | ret = device_register(dev); |
1841 | 1841 | if (ret) { | |
1842 | if (ret) | 1842 | put_device(dev); |
1843 | return ret; | 1843 | return ret; |
1844 | } | ||
1844 | ret = netiucv_add_files(dev); | 1845 | ret = netiucv_add_files(dev); |
1845 | if (ret) | 1846 | if (ret) |
1846 | goto out_unreg; | 1847 | goto out_unreg; |
@@ -2225,8 +2226,10 @@ static int __init netiucv_init(void) | |||
2225 | netiucv_dev->release = (void (*)(struct device *))kfree; | 2226 | netiucv_dev->release = (void (*)(struct device *))kfree; |
2226 | netiucv_dev->driver = &netiucv_driver; | 2227 | netiucv_dev->driver = &netiucv_driver; |
2227 | rc = device_register(netiucv_dev); | 2228 | rc = device_register(netiucv_dev); |
2228 | if (rc) | 2229 | if (rc) { |
2230 | put_device(netiucv_dev); | ||
2229 | goto out_driver; | 2231 | goto out_driver; |
2232 | } | ||
2230 | netiucv_banner(); | 2233 | netiucv_banner(); |
2231 | return rc; | 2234 | return rc; |
2232 | 2235 | ||
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c index e76a320d373b..102000d1af6f 100644 --- a/drivers/s390/net/smsgiucv.c +++ b/drivers/s390/net/smsgiucv.c | |||
@@ -219,13 +219,13 @@ static int __init smsg_init(void) | |||
219 | smsg_dev->driver = &smsg_driver; | 219 | smsg_dev->driver = &smsg_driver; |
220 | rc = device_register(smsg_dev); | 220 | rc = device_register(smsg_dev); |
221 | if (rc) | 221 | if (rc) |
222 | goto out_free_dev; | 222 | goto out_put; |
223 | 223 | ||
224 | cpcmd("SET SMSG IUCV", NULL, 0, NULL); | 224 | cpcmd("SET SMSG IUCV", NULL, 0, NULL); |
225 | return 0; | 225 | return 0; |
226 | 226 | ||
227 | out_free_dev: | 227 | out_put: |
228 | kfree(smsg_dev); | 228 | put_device(smsg_dev); |
229 | out_free_path: | 229 | out_free_path: |
230 | iucv_path_free(smsg_path); | 230 | iucv_path_free(smsg_path); |
231 | smsg_path = NULL; | 231 | smsg_path = NULL; |