diff options
Diffstat (limited to 'drivers/s390')
28 files changed, 696 insertions, 426 deletions
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index aeda52682446..d427daeef511 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <linux/genhd.h> | 53 | #include <linux/genhd.h> |
54 | #include <linux/hdreg.h> | 54 | #include <linux/hdreg.h> |
55 | #include <linux/interrupt.h> | 55 | #include <linux/interrupt.h> |
56 | #include <linux/log2.h> | ||
56 | #include <asm/ccwdev.h> | 57 | #include <asm/ccwdev.h> |
57 | #include <linux/workqueue.h> | 58 | #include <linux/workqueue.h> |
58 | #include <asm/debug.h> | 59 | #include <asm/debug.h> |
@@ -456,7 +457,7 @@ dasd_free_chunk(struct list_head *chunk_list, void *mem) | |||
456 | static inline int | 457 | static inline int |
457 | dasd_check_blocksize(int bsize) | 458 | dasd_check_blocksize(int bsize) |
458 | { | 459 | { |
459 | if (bsize < 512 || bsize > 4096 || (bsize & (bsize - 1)) != 0) | 460 | if (bsize < 512 || bsize > 4096 || !is_power_of_2(bsize)) |
460 | return -EMEDIUMTYPE; | 461 | return -EMEDIUMTYPE; |
461 | return 0; | 462 | return 0; |
462 | } | 463 | } |
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 0fbacc8b1063..f231bc21b1ca 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c | |||
@@ -230,7 +230,7 @@ static int xpram_make_request(struct request_queue *q, struct bio *bio) | |||
230 | } | 230 | } |
231 | } | 231 | } |
232 | set_bit(BIO_UPTODATE, &bio->bi_flags); | 232 | set_bit(BIO_UPTODATE, &bio->bi_flags); |
233 | bio_end_io(bio, 0); | 233 | bio_endio(bio, 0); |
234 | return 0; | 234 | return 0; |
235 | fail: | 235 | fail: |
236 | bio_io_error(bio); | 236 | bio_io_error(bio); |
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 6000bdee4082..0e1f35c9ed9d 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c | |||
@@ -667,6 +667,9 @@ raw3215_probe (struct ccw_device *cdev) | |||
667 | struct raw3215_info *raw; | 667 | struct raw3215_info *raw; |
668 | int line; | 668 | int line; |
669 | 669 | ||
670 | /* Console is special. */ | ||
671 | if (raw3215[0] && (cdev->dev.driver_data == raw3215[0])) | ||
672 | return 0; | ||
670 | raw = kmalloc(sizeof(struct raw3215_info) + | 673 | raw = kmalloc(sizeof(struct raw3215_info) + |
671 | RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA); | 674 | RAW3215_INBUF_SIZE, GFP_KERNEL|GFP_DMA); |
672 | if (raw == NULL) | 675 | if (raw == NULL) |
diff --git a/drivers/s390/char/con3270.c b/drivers/s390/char/con3270.c index fd3479119eb4..0b040557db02 100644 --- a/drivers/s390/char/con3270.c +++ b/drivers/s390/char/con3270.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <asm/ebcdic.h> | 22 | #include <asm/ebcdic.h> |
23 | 23 | ||
24 | #include "raw3270.h" | 24 | #include "raw3270.h" |
25 | #include "tty3270.h" | ||
25 | #include "ctrlchar.h" | 26 | #include "ctrlchar.h" |
26 | 27 | ||
27 | #define CON3270_OUTPUT_BUFFER_SIZE 1024 | 28 | #define CON3270_OUTPUT_BUFFER_SIZE 1024 |
@@ -507,8 +508,6 @@ con3270_write(struct console *co, const char *str, unsigned int count) | |||
507 | spin_unlock_irqrestore(&cp->view.lock,flags); | 508 | spin_unlock_irqrestore(&cp->view.lock,flags); |
508 | } | 509 | } |
509 | 510 | ||
510 | extern struct tty_driver *tty3270_driver; | ||
511 | |||
512 | static struct tty_driver * | 511 | static struct tty_driver * |
513 | con3270_device(struct console *c, int *index) | 512 | con3270_device(struct console *c, int *index) |
514 | { | 513 | { |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index fa62e6944057..25629b92dec3 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
@@ -93,6 +93,7 @@ static volatile enum sclp_mask_state_t { | |||
93 | #define SCLP_RETRY_INTERVAL 30 | 93 | #define SCLP_RETRY_INTERVAL 30 |
94 | 94 | ||
95 | static void sclp_process_queue(void); | 95 | static void sclp_process_queue(void); |
96 | static void __sclp_make_read_req(void); | ||
96 | static int sclp_init_mask(int calculate); | 97 | static int sclp_init_mask(int calculate); |
97 | static int sclp_init(void); | 98 | static int sclp_init(void); |
98 | 99 | ||
@@ -115,7 +116,6 @@ sclp_service_call(sclp_cmdw_t command, void *sccb) | |||
115 | return 0; | 116 | return 0; |
116 | } | 117 | } |
117 | 118 | ||
118 | static inline void __sclp_make_read_req(void); | ||
119 | 119 | ||
120 | static void | 120 | static void |
121 | __sclp_queue_read_req(void) | 121 | __sclp_queue_read_req(void) |
@@ -318,8 +318,7 @@ sclp_read_cb(struct sclp_req *req, void *data) | |||
318 | } | 318 | } |
319 | 319 | ||
320 | /* Prepare read event data request. Called while sclp_lock is locked. */ | 320 | /* Prepare read event data request. Called while sclp_lock is locked. */ |
321 | static inline void | 321 | static void __sclp_make_read_req(void) |
322 | __sclp_make_read_req(void) | ||
323 | { | 322 | { |
324 | struct sccb_header *sccb; | 323 | struct sccb_header *sccb; |
325 | 324 | ||
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 9f244c591eeb..da25f8e24152 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -708,16 +708,22 @@ static void tape_3590_med_state_set(struct tape_device *device, | |||
708 | 708 | ||
709 | c_info = &TAPE_3590_CRYPT_INFO(device); | 709 | c_info = &TAPE_3590_CRYPT_INFO(device); |
710 | 710 | ||
711 | if (sense->masst == MSENSE_UNASSOCIATED) { | 711 | DBF_EVENT(6, "medium state: %x:%x\n", sense->macst, sense->masst); |
712 | switch (sense->macst) { | ||
713 | case 0x04: | ||
714 | case 0x05: | ||
715 | case 0x06: | ||
712 | tape_med_state_set(device, MS_UNLOADED); | 716 | tape_med_state_set(device, MS_UNLOADED); |
713 | TAPE_3590_CRYPT_INFO(device).medium_status = 0; | 717 | TAPE_3590_CRYPT_INFO(device).medium_status = 0; |
714 | return; | 718 | return; |
715 | } | 719 | case 0x08: |
716 | if (sense->masst != MSENSE_ASSOCIATED_MOUNT) { | 720 | case 0x09: |
717 | PRINT_ERR("Unknown medium state: %x\n", sense->masst); | 721 | tape_med_state_set(device, MS_LOADED); |
722 | break; | ||
723 | default: | ||
724 | tape_med_state_set(device, MS_UNKNOWN); | ||
718 | return; | 725 | return; |
719 | } | 726 | } |
720 | tape_med_state_set(device, MS_LOADED); | ||
721 | c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK; | 727 | c_info->medium_status |= TAPE390_MEDIUM_LOADED_MASK; |
722 | if (sense->flags & MSENSE_CRYPT_MASK) { | 728 | if (sense->flags & MSENSE_CRYPT_MASK) { |
723 | PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags); | 729 | PRINT_INFO("Medium is encrypted (%04x)\n", sense->flags); |
@@ -835,15 +841,17 @@ tape_3590_unsolicited_irq(struct tape_device *device, struct irb *irb) | |||
835 | /* Probably result of halt ssch */ | 841 | /* Probably result of halt ssch */ |
836 | return TAPE_IO_PENDING; | 842 | return TAPE_IO_PENDING; |
837 | else if (irb->scsw.dstat == 0x85) | 843 | else if (irb->scsw.dstat == 0x85) |
838 | /* Device Ready -> check medium state */ | 844 | /* Device Ready */ |
839 | tape_3590_schedule_work(device, TO_MSEN); | 845 | DBF_EVENT(3, "unsol.irq! tape ready: %08x\n", device->cdev_id); |
840 | else if (irb->scsw.dstat & DEV_STAT_ATTENTION) | 846 | else if (irb->scsw.dstat & DEV_STAT_ATTENTION) { |
841 | tape_3590_schedule_work(device, TO_READ_ATTMSG); | 847 | tape_3590_schedule_work(device, TO_READ_ATTMSG); |
842 | else { | 848 | } else { |
843 | DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); | 849 | DBF_EVENT(3, "unsol.irq! dev end: %08x\n", device->cdev_id); |
844 | PRINT_WARN("Unsolicited IRQ (Device End) caught.\n"); | 850 | PRINT_WARN("Unsolicited IRQ (Device End) caught.\n"); |
845 | tape_dump_sense(device, NULL, irb); | 851 | tape_dump_sense(device, NULL, irb); |
846 | } | 852 | } |
853 | /* check medium state */ | ||
854 | tape_3590_schedule_work(device, TO_MSEN); | ||
847 | return TAPE_IO_SUCCESS; | 855 | return TAPE_IO_SUCCESS; |
848 | } | 856 | } |
849 | 857 | ||
diff --git a/drivers/s390/char/tty3270.c b/drivers/s390/char/tty3270.c index bc33068b9ce2..70b1980a08b6 100644 --- a/drivers/s390/char/tty3270.c +++ b/drivers/s390/char/tty3270.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include <asm/ebcdic.h> | 25 | #include <asm/ebcdic.h> |
26 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
27 | 27 | ||
28 | |||
29 | #include "raw3270.h" | 28 | #include "raw3270.h" |
29 | #include "tty3270.h" | ||
30 | #include "keyboard.h" | 30 | #include "keyboard.h" |
31 | 31 | ||
32 | #define TTY3270_CHAR_BUF_SIZE 256 | 32 | #define TTY3270_CHAR_BUF_SIZE 256 |
@@ -1338,8 +1338,11 @@ tty3270_getpar(struct tty3270 *tp, int ix) | |||
1338 | static void | 1338 | static void |
1339 | tty3270_goto_xy(struct tty3270 *tp, int cx, int cy) | 1339 | tty3270_goto_xy(struct tty3270 *tp, int cx, int cy) |
1340 | { | 1340 | { |
1341 | tp->cx = min_t(int, tp->view.cols - 1, max_t(int, 0, cx)); | 1341 | int max_cx = max(0, cx); |
1342 | cy = min_t(int, tp->view.rows - 3, max_t(int, 0, cy)); | 1342 | int max_cy = max(0, cy); |
1343 | |||
1344 | tp->cx = min_t(int, tp->view.cols - 1, max_cx); | ||
1345 | cy = min_t(int, tp->view.rows - 3, max_cy); | ||
1343 | if (cy != tp->cy) { | 1346 | if (cy != tp->cy) { |
1344 | tty3270_convert_line(tp, tp->cy); | 1347 | tty3270_convert_line(tp, tp->cy); |
1345 | tp->cy = cy; | 1348 | tp->cy = cy; |
diff --git a/drivers/s390/char/tty3270.h b/drivers/s390/char/tty3270.h new file mode 100644 index 000000000000..799da57f0390 --- /dev/null +++ b/drivers/s390/char/tty3270.h | |||
@@ -0,0 +1,16 @@ | |||
1 | /* | ||
2 | * drivers/s390/char/tty3270.h | ||
3 | * | ||
4 | * Copyright IBM Corp. 2007 | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #ifndef __DRIVERS_S390_CHAR_TTY3270_H | ||
9 | #define __DRIVERS_S390_CHAR_TTY3270_H | ||
10 | |||
11 | #include <linux/tty.h> | ||
12 | #include <linux/tty_driver.h> | ||
13 | |||
14 | extern struct tty_driver *tty3270_driver; | ||
15 | |||
16 | #endif /* __DRIVERS_S390_CHAR_TTY3270_H */ | ||
diff --git a/drivers/s390/char/vmwatchdog.c b/drivers/s390/char/vmwatchdog.c index 680b9b58b80e..6f40facb1c4d 100644 --- a/drivers/s390/char/vmwatchdog.c +++ b/drivers/s390/char/vmwatchdog.c | |||
@@ -66,8 +66,8 @@ static int __diag288(enum vmwdt_func func, unsigned int timeout, | |||
66 | "0: la %0,0\n" | 66 | "0: la %0,0\n" |
67 | "1:\n" | 67 | "1:\n" |
68 | EX_TABLE(0b,1b) | 68 | EX_TABLE(0b,1b) |
69 | : "=d" (err) : "d"(__func), "d"(__timeout), | 69 | : "+d" (err) : "d"(__func), "d"(__timeout), |
70 | "d"(__cmdp), "d"(__cmdl), "0" (-EINVAL) : "1", "cc"); | 70 | "d"(__cmdp), "d"(__cmdl) : "1", "cc"); |
71 | return err; | 71 | return err; |
72 | } | 72 | } |
73 | 73 | ||
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 3712ede16723..7073daf77981 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
@@ -141,15 +141,16 @@ static int memcpy_real(void *dest, unsigned long src, size_t count) | |||
141 | 141 | ||
142 | if (count == 0) | 142 | if (count == 0) |
143 | return 0; | 143 | return 0; |
144 | flags = __raw_local_irq_stnsm(0xf8); /* switch to real mode */ | 144 | flags = __raw_local_irq_stnsm(0xf8UL); /* switch to real mode */ |
145 | asm volatile ( | 145 | asm volatile ( |
146 | "0: mvcle %1,%2,0x0\n" | 146 | "0: mvcle %1,%2,0x0\n" |
147 | "1: jo 0b\n" | 147 | "1: jo 0b\n" |
148 | " lhi %0,0x0\n" | 148 | " lhi %0,0x0\n" |
149 | "2:\n" | 149 | "2:\n" |
150 | EX_TABLE(1b,2b) | 150 | EX_TABLE(1b,2b) |
151 | : "+d" (rc) | 151 | : "+d" (rc), "+d" (_dest), "+d" (_src), "+d" (_len1), |
152 | : "d" (_dest), "d" (_src), "d" (_len1), "d" (_len2) | 152 | "+d" (_len2), "=m" (*((long*)dest)) |
153 | : "m" (*((long*)src)) | ||
153 | : "cc", "memory"); | 154 | : "cc", "memory"); |
154 | __raw_local_irq_ssm(flags); | 155 | __raw_local_irq_ssm(flags); |
155 | 156 | ||
diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 5d967c439822..5baa517c3b66 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c | |||
@@ -151,16 +151,24 @@ __ccwgroup_create_symlinks(struct ccwgroup_device *gdev) | |||
151 | return 0; | 151 | return 0; |
152 | } | 152 | } |
153 | 153 | ||
154 | /* | 154 | /** |
155 | * try to add a new ccwgroup device for one driver | 155 | * ccwgroup_create() - create and register a ccw group device |
156 | * argc and argv[] are a list of bus_id's of devices | 156 | * @root: parent device for the new device |
157 | * belonging to the driver. | 157 | * @creator_id: identifier of creating driver |
158 | * @cdrv: ccw driver of slave devices | ||
159 | * @argc: number of slave devices | ||
160 | * @argv: bus ids of slave devices | ||
161 | * | ||
162 | * Create and register a new ccw group device as a child of @root. Slave | ||
163 | * devices are obtained from the list of bus ids given in @argv[] and must all | ||
164 | * belong to @cdrv. | ||
165 | * Returns: | ||
166 | * %0 on success and an error code on failure. | ||
167 | * Context: | ||
168 | * non-atomic | ||
158 | */ | 169 | */ |
159 | int | 170 | int ccwgroup_create(struct device *root, unsigned int creator_id, |
160 | ccwgroup_create(struct device *root, | 171 | struct ccw_driver *cdrv, int argc, char *argv[]) |
161 | unsigned int creator_id, | ||
162 | struct ccw_driver *cdrv, | ||
163 | int argc, char *argv[]) | ||
164 | { | 172 | { |
165 | struct ccwgroup_device *gdev; | 173 | struct ccwgroup_device *gdev; |
166 | int i; | 174 | int i; |
@@ -389,8 +397,13 @@ static struct bus_type ccwgroup_bus_type = { | |||
389 | .remove = ccwgroup_remove, | 397 | .remove = ccwgroup_remove, |
390 | }; | 398 | }; |
391 | 399 | ||
392 | int | 400 | /** |
393 | ccwgroup_driver_register (struct ccwgroup_driver *cdriver) | 401 | * ccwgroup_driver_register() - register a ccw group driver |
402 | * @cdriver: driver to be registered | ||
403 | * | ||
404 | * This function is mainly a wrapper around driver_register(). | ||
405 | */ | ||
406 | int ccwgroup_driver_register(struct ccwgroup_driver *cdriver) | ||
394 | { | 407 | { |
395 | /* register our new driver with the core */ | 408 | /* register our new driver with the core */ |
396 | cdriver->driver.bus = &ccwgroup_bus_type; | 409 | cdriver->driver.bus = &ccwgroup_bus_type; |
@@ -405,8 +418,13 @@ __ccwgroup_match_all(struct device *dev, void *data) | |||
405 | return 1; | 418 | return 1; |
406 | } | 419 | } |
407 | 420 | ||
408 | void | 421 | /** |
409 | ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | 422 | * ccwgroup_driver_unregister() - deregister a ccw group driver |
423 | * @cdriver: driver to be deregistered | ||
424 | * | ||
425 | * This function is mainly a wrapper around driver_unregister(). | ||
426 | */ | ||
427 | void ccwgroup_driver_unregister(struct ccwgroup_driver *cdriver) | ||
410 | { | 428 | { |
411 | struct device *dev; | 429 | struct device *dev; |
412 | 430 | ||
@@ -426,8 +444,16 @@ ccwgroup_driver_unregister (struct ccwgroup_driver *cdriver) | |||
426 | driver_unregister(&cdriver->driver); | 444 | driver_unregister(&cdriver->driver); |
427 | } | 445 | } |
428 | 446 | ||
429 | int | 447 | /** |
430 | ccwgroup_probe_ccwdev(struct ccw_device *cdev) | 448 | * ccwgroup_probe_ccwdev() - probe function for slave devices |
449 | * @cdev: ccw device to be probed | ||
450 | * | ||
451 | * This is a dummy probe function for ccw devices that are slave devices in | ||
452 | * a ccw group device. | ||
453 | * Returns: | ||
454 | * always %0 | ||
455 | */ | ||
456 | int ccwgroup_probe_ccwdev(struct ccw_device *cdev) | ||
431 | { | 457 | { |
432 | return 0; | 458 | return 0; |
433 | } | 459 | } |
@@ -451,8 +477,15 @@ __ccwgroup_get_gdev_by_cdev(struct ccw_device *cdev) | |||
451 | return NULL; | 477 | return NULL; |
452 | } | 478 | } |
453 | 479 | ||
454 | void | 480 | /** |
455 | ccwgroup_remove_ccwdev(struct ccw_device *cdev) | 481 | * ccwgroup_remove_ccwdev() - remove function for slave devices |
482 | * @cdev: ccw device to be removed | ||
483 | * | ||
484 | * This is a remove function for ccw devices that are slave devices in a ccw | ||
485 | * group device. It sets the ccw device offline and also deregisters the | ||
486 | * embedding ccw group device. | ||
487 | */ | ||
488 | void ccwgroup_remove_ccwdev(struct ccw_device *cdev) | ||
456 | { | 489 | { |
457 | struct ccwgroup_device *gdev; | 490 | struct ccwgroup_device *gdev; |
458 | 491 | ||
diff --git a/drivers/s390/cio/chp.c b/drivers/s390/cio/chp.c index 920dd71e6434..42c1f4659adb 100644 --- a/drivers/s390/cio/chp.c +++ b/drivers/s390/cio/chp.c | |||
@@ -14,7 +14,7 @@ | |||
14 | #include <linux/jiffies.h> | 14 | #include <linux/jiffies.h> |
15 | #include <linux/wait.h> | 15 | #include <linux/wait.h> |
16 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
17 | #include <asm/errno.h> | 17 | #include <linux/errno.h> |
18 | #include <asm/chpid.h> | 18 | #include <asm/chpid.h> |
19 | #include <asm/sclp.h> | 19 | #include <asm/sclp.h> |
20 | 20 | ||
@@ -55,7 +55,7 @@ static wait_queue_head_t cfg_wait_queue; | |||
55 | /* Return channel_path struct for given chpid. */ | 55 | /* Return channel_path struct for given chpid. */ |
56 | static inline struct channel_path *chpid_to_chp(struct chp_id chpid) | 56 | static inline struct channel_path *chpid_to_chp(struct chp_id chpid) |
57 | { | 57 | { |
58 | return css[chpid.cssid]->chps[chpid.id]; | 58 | return channel_subsystems[chpid.cssid]->chps[chpid.id]; |
59 | } | 59 | } |
60 | 60 | ||
61 | /* Set vary state for given chpid. */ | 61 | /* Set vary state for given chpid. */ |
@@ -86,7 +86,7 @@ u8 chp_get_sch_opm(struct subchannel *sch) | |||
86 | 86 | ||
87 | opm = 0; | 87 | opm = 0; |
88 | chp_id_init(&chpid); | 88 | chp_id_init(&chpid); |
89 | for (i=0; i < 8; i++) { | 89 | for (i = 0; i < 8; i++) { |
90 | opm <<= 1; | 90 | opm <<= 1; |
91 | chpid.id = sch->schib.pmcw.chpid[i]; | 91 | chpid.id = sch->schib.pmcw.chpid[i]; |
92 | if (chp_get_status(chpid) != 0) | 92 | if (chp_get_status(chpid) != 0) |
@@ -118,7 +118,7 @@ static int s390_vary_chpid(struct chp_id chpid, int on) | |||
118 | 118 | ||
119 | sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid, | 119 | sprintf(dbf_text, on?"varyon%x.%02x":"varyoff%x.%02x", chpid.cssid, |
120 | chpid.id); | 120 | chpid.id); |
121 | CIO_TRACE_EVENT( 2, dbf_text); | 121 | CIO_TRACE_EVENT(2, dbf_text); |
122 | 122 | ||
123 | status = chp_get_status(chpid); | 123 | status = chp_get_status(chpid); |
124 | if (!on && !status) { | 124 | if (!on && !status) { |
@@ -140,9 +140,11 @@ static ssize_t chp_measurement_chars_read(struct kobject *kobj, | |||
140 | char *buf, loff_t off, size_t count) | 140 | char *buf, loff_t off, size_t count) |
141 | { | 141 | { |
142 | struct channel_path *chp; | 142 | struct channel_path *chp; |
143 | struct device *device; | ||
143 | unsigned int size; | 144 | unsigned int size; |
144 | 145 | ||
145 | chp = to_channelpath(container_of(kobj, struct device, kobj)); | 146 | device = container_of(kobj, struct device, kobj); |
147 | chp = to_channelpath(device); | ||
146 | if (!chp->cmg_chars) | 148 | if (!chp->cmg_chars) |
147 | return 0; | 149 | return 0; |
148 | 150 | ||
@@ -193,9 +195,11 @@ static ssize_t chp_measurement_read(struct kobject *kobj, | |||
193 | { | 195 | { |
194 | struct channel_path *chp; | 196 | struct channel_path *chp; |
195 | struct channel_subsystem *css; | 197 | struct channel_subsystem *css; |
198 | struct device *device; | ||
196 | unsigned int size; | 199 | unsigned int size; |
197 | 200 | ||
198 | chp = to_channelpath(container_of(kobj, struct device, kobj)); | 201 | device = container_of(kobj, struct device, kobj); |
202 | chp = to_channelpath(device); | ||
199 | css = to_css(chp->dev.parent); | 203 | css = to_css(chp->dev.parent); |
200 | 204 | ||
201 | size = sizeof(struct cmg_entry); | 205 | size = sizeof(struct cmg_entry); |
@@ -353,7 +357,7 @@ static ssize_t chp_shared_show(struct device *dev, | |||
353 | 357 | ||
354 | static DEVICE_ATTR(shared, 0444, chp_shared_show, NULL); | 358 | static DEVICE_ATTR(shared, 0444, chp_shared_show, NULL); |
355 | 359 | ||
356 | static struct attribute * chp_attrs[] = { | 360 | static struct attribute *chp_attrs[] = { |
357 | &dev_attr_status.attr, | 361 | &dev_attr_status.attr, |
358 | &dev_attr_configure.attr, | 362 | &dev_attr_configure.attr, |
359 | &dev_attr_type.attr, | 363 | &dev_attr_type.attr, |
@@ -395,7 +399,7 @@ int chp_new(struct chp_id chpid) | |||
395 | /* fill in status, etc. */ | 399 | /* fill in status, etc. */ |
396 | chp->chpid = chpid; | 400 | chp->chpid = chpid; |
397 | chp->state = 1; | 401 | chp->state = 1; |
398 | chp->dev.parent = &css[chpid.cssid]->device; | 402 | chp->dev.parent = &channel_subsystems[chpid.cssid]->device; |
399 | chp->dev.release = chp_release; | 403 | chp->dev.release = chp_release; |
400 | snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid, | 404 | snprintf(chp->dev.bus_id, BUS_ID_SIZE, "chp%x.%02x", chpid.cssid, |
401 | chpid.id); | 405 | chpid.id); |
@@ -430,18 +434,18 @@ int chp_new(struct chp_id chpid) | |||
430 | device_unregister(&chp->dev); | 434 | device_unregister(&chp->dev); |
431 | goto out_free; | 435 | goto out_free; |
432 | } | 436 | } |
433 | mutex_lock(&css[chpid.cssid]->mutex); | 437 | mutex_lock(&channel_subsystems[chpid.cssid]->mutex); |
434 | if (css[chpid.cssid]->cm_enabled) { | 438 | if (channel_subsystems[chpid.cssid]->cm_enabled) { |
435 | ret = chp_add_cmg_attr(chp); | 439 | ret = chp_add_cmg_attr(chp); |
436 | if (ret) { | 440 | if (ret) { |
437 | sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); | 441 | sysfs_remove_group(&chp->dev.kobj, &chp_attr_group); |
438 | device_unregister(&chp->dev); | 442 | device_unregister(&chp->dev); |
439 | mutex_unlock(&css[chpid.cssid]->mutex); | 443 | mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); |
440 | goto out_free; | 444 | goto out_free; |
441 | } | 445 | } |
442 | } | 446 | } |
443 | css[chpid.cssid]->chps[chpid.id] = chp; | 447 | channel_subsystems[chpid.cssid]->chps[chpid.id] = chp; |
444 | mutex_unlock(&css[chpid.cssid]->mutex); | 448 | mutex_unlock(&channel_subsystems[chpid.cssid]->mutex); |
445 | return ret; | 449 | return ret; |
446 | out_free: | 450 | out_free: |
447 | kfree(chp); | 451 | kfree(chp); |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index f2708d65be5a..46905345159e 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -619,6 +619,11 @@ cio_validate_subchannel (struct subchannel *sch, struct subchannel_id schid) | |||
619 | sch->schib.pmcw.ena = 0; | 619 | sch->schib.pmcw.ena = 0; |
620 | if ((sch->lpm & (sch->lpm - 1)) != 0) | 620 | if ((sch->lpm & (sch->lpm - 1)) != 0) |
621 | sch->schib.pmcw.mp = 1; /* multipath mode */ | 621 | sch->schib.pmcw.mp = 1; /* multipath mode */ |
622 | /* clean up possible residual cmf stuff */ | ||
623 | sch->schib.pmcw.mme = 0; | ||
624 | sch->schib.pmcw.mbfc = 0; | ||
625 | sch->schib.pmcw.mbi = 0; | ||
626 | sch->schib.mba = 0; | ||
622 | return 0; | 627 | return 0; |
623 | out: | 628 | out: |
624 | if (!cio_is_console(schid)) | 629 | if (!cio_is_console(schid)) |
diff --git a/drivers/s390/cio/cmf.c b/drivers/s390/cio/cmf.c index 34a796913b06..b960f66843e4 100644 --- a/drivers/s390/cio/cmf.c +++ b/drivers/s390/cio/cmf.c | |||
@@ -45,7 +45,8 @@ | |||
45 | #include "ioasm.h" | 45 | #include "ioasm.h" |
46 | #include "chsc.h" | 46 | #include "chsc.h" |
47 | 47 | ||
48 | /* parameter to enable cmf during boot, possible uses are: | 48 | /* |
49 | * parameter to enable cmf during boot, possible uses are: | ||
49 | * "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be | 50 | * "s390cmf" -- enable cmf and allocate 2 MB of ram so measuring can be |
50 | * used on any subchannel | 51 | * used on any subchannel |
51 | * "s390cmf=<num>" -- enable cmf and allocate enough memory to measure | 52 | * "s390cmf=<num>" -- enable cmf and allocate enough memory to measure |
@@ -73,18 +74,20 @@ enum cmb_index { | |||
73 | * enum cmb_format - types of supported measurement block formats | 74 | * enum cmb_format - types of supported measurement block formats |
74 | * | 75 | * |
75 | * @CMF_BASIC: traditional channel measurement blocks supported | 76 | * @CMF_BASIC: traditional channel measurement blocks supported |
76 | * by all machines that we run on | 77 | * by all machines that we run on |
77 | * @CMF_EXTENDED: improved format that was introduced with the z990 | 78 | * @CMF_EXTENDED: improved format that was introduced with the z990 |
78 | * machine | 79 | * machine |
79 | * @CMF_AUTODETECT: default: use extended format when running on a z990 | 80 | * @CMF_AUTODETECT: default: use extended format when running on a machine |
80 | * or later machine, otherwise fall back to basic format | 81 | * supporting extended format, otherwise fall back to |
81 | **/ | 82 | * basic format |
83 | */ | ||
82 | enum cmb_format { | 84 | enum cmb_format { |
83 | CMF_BASIC, | 85 | CMF_BASIC, |
84 | CMF_EXTENDED, | 86 | CMF_EXTENDED, |
85 | CMF_AUTODETECT = -1, | 87 | CMF_AUTODETECT = -1, |
86 | }; | 88 | }; |
87 | /** | 89 | |
90 | /* | ||
88 | * format - actual format for all measurement blocks | 91 | * format - actual format for all measurement blocks |
89 | * | 92 | * |
90 | * The format module parameter can be set to a value of 0 (zero) | 93 | * The format module parameter can be set to a value of 0 (zero) |
@@ -105,20 +108,21 @@ module_param(format, bool, 0444); | |||
105 | * either with the help of a special pool or with kmalloc | 108 | * either with the help of a special pool or with kmalloc |
106 | * @free: free memory allocated with @alloc | 109 | * @free: free memory allocated with @alloc |
107 | * @set: enable or disable measurement | 110 | * @set: enable or disable measurement |
111 | * @read: read a measurement entry at an index | ||
108 | * @readall: read a measurement block in a common format | 112 | * @readall: read a measurement block in a common format |
109 | * @reset: clear the data in the associated measurement block and | 113 | * @reset: clear the data in the associated measurement block and |
110 | * reset its time stamp | 114 | * reset its time stamp |
111 | * @align: align an allocated block so that the hardware can use it | 115 | * @align: align an allocated block so that the hardware can use it |
112 | */ | 116 | */ |
113 | struct cmb_operations { | 117 | struct cmb_operations { |
114 | int (*alloc) (struct ccw_device*); | 118 | int (*alloc) (struct ccw_device *); |
115 | void(*free) (struct ccw_device*); | 119 | void (*free) (struct ccw_device *); |
116 | int (*set) (struct ccw_device*, u32); | 120 | int (*set) (struct ccw_device *, u32); |
117 | u64 (*read) (struct ccw_device*, int); | 121 | u64 (*read) (struct ccw_device *, int); |
118 | int (*readall)(struct ccw_device*, struct cmbdata *); | 122 | int (*readall)(struct ccw_device *, struct cmbdata *); |
119 | void (*reset) (struct ccw_device*); | 123 | void (*reset) (struct ccw_device *); |
120 | void * (*align) (void *); | 124 | void *(*align) (void *); |
121 | 125 | /* private: */ | |
122 | struct attribute_group *attr_group; | 126 | struct attribute_group *attr_group; |
123 | }; | 127 | }; |
124 | static struct cmb_operations *cmbops; | 128 | static struct cmb_operations *cmbops; |
@@ -130,9 +134,11 @@ struct cmb_data { | |||
130 | unsigned long long last_update; /* when last_block was updated */ | 134 | unsigned long long last_update; /* when last_block was updated */ |
131 | }; | 135 | }; |
132 | 136 | ||
133 | /* our user interface is designed in terms of nanoseconds, | 137 | /* |
138 | * Our user interface is designed in terms of nanoseconds, | ||
134 | * while the hardware measures total times in its own | 139 | * while the hardware measures total times in its own |
135 | * unit.*/ | 140 | * unit. |
141 | */ | ||
136 | static inline u64 time_to_nsec(u32 value) | 142 | static inline u64 time_to_nsec(u32 value) |
137 | { | 143 | { |
138 | return ((u64)value) * 128000ull; | 144 | return ((u64)value) * 128000ull; |
@@ -159,12 +165,13 @@ static inline u64 time_to_avg_nsec(u32 value, u32 count) | |||
159 | return ret; | 165 | return ret; |
160 | } | 166 | } |
161 | 167 | ||
162 | /* activate or deactivate the channel monitor. When area is NULL, | 168 | /* |
169 | * Activate or deactivate the channel monitor. When area is NULL, | ||
163 | * the monitor is deactivated. The channel monitor needs to | 170 | * the monitor is deactivated. The channel monitor needs to |
164 | * be active in order to measure subchannels, which also need | 171 | * be active in order to measure subchannels, which also need |
165 | * to be enabled. */ | 172 | * to be enabled. |
166 | static inline void | 173 | */ |
167 | cmf_activate(void *area, unsigned int onoff) | 174 | static inline void cmf_activate(void *area, unsigned int onoff) |
168 | { | 175 | { |
169 | register void * __gpr2 asm("2"); | 176 | register void * __gpr2 asm("2"); |
170 | register long __gpr1 asm("1"); | 177 | register long __gpr1 asm("1"); |
@@ -175,8 +182,8 @@ cmf_activate(void *area, unsigned int onoff) | |||
175 | asm("schm" : : "d" (__gpr2), "d" (__gpr1) ); | 182 | asm("schm" : : "d" (__gpr2), "d" (__gpr1) ); |
176 | } | 183 | } |
177 | 184 | ||
178 | static int | 185 | static int set_schib(struct ccw_device *cdev, u32 mme, int mbfc, |
179 | set_schib(struct ccw_device *cdev, u32 mme, int mbfc, unsigned long address) | 186 | unsigned long address) |
180 | { | 187 | { |
181 | int ret; | 188 | int ret; |
182 | int retry; | 189 | int retry; |
@@ -466,6 +473,7 @@ static void cmf_generic_reset(struct ccw_device *cdev) | |||
466 | * | 473 | * |
467 | * @mem: pointer to CMBs (only in basic measurement mode) | 474 | * @mem: pointer to CMBs (only in basic measurement mode) |
468 | * @list: contains a linked list of all subchannels | 475 | * @list: contains a linked list of all subchannels |
476 | * @num_channels: number of channels to be measured | ||
469 | * @lock: protect concurrent access to @mem and @list | 477 | * @lock: protect concurrent access to @mem and @list |
470 | */ | 478 | */ |
471 | struct cmb_area { | 479 | struct cmb_area { |
@@ -481,28 +489,36 @@ static struct cmb_area cmb_area = { | |||
481 | .num_channels = 1024, | 489 | .num_channels = 1024, |
482 | }; | 490 | }; |
483 | 491 | ||
484 | |||
485 | /* ****** old style CMB handling ********/ | 492 | /* ****** old style CMB handling ********/ |
486 | 493 | ||
487 | /** int maxchannels | 494 | /* |
488 | * | ||
489 | * Basic channel measurement blocks are allocated in one contiguous | 495 | * Basic channel measurement blocks are allocated in one contiguous |
490 | * block of memory, which can not be moved as long as any channel | 496 | * block of memory, which can not be moved as long as any channel |
491 | * is active. Therefore, a maximum number of subchannels needs to | 497 | * is active. Therefore, a maximum number of subchannels needs to |
492 | * be defined somewhere. This is a module parameter, defaulting to | 498 | * be defined somewhere. This is a module parameter, defaulting to |
493 | * a resonable value of 1024, or 32 kb of memory. | 499 | * a resonable value of 1024, or 32 kb of memory. |
494 | * Current kernels don't allow kmalloc with more than 128kb, so the | 500 | * Current kernels don't allow kmalloc with more than 128kb, so the |
495 | * maximum is 4096 | 501 | * maximum is 4096. |
496 | */ | 502 | */ |
497 | 503 | ||
498 | module_param_named(maxchannels, cmb_area.num_channels, uint, 0444); | 504 | module_param_named(maxchannels, cmb_area.num_channels, uint, 0444); |
499 | 505 | ||
500 | /** | 506 | /** |
501 | * struct cmb - basic channel measurement block | 507 | * struct cmb - basic channel measurement block |
508 | * @ssch_rsch_count: number of ssch and rsch | ||
509 | * @sample_count: number of samples | ||
510 | * @device_connect_time: time of device connect | ||
511 | * @function_pending_time: time of function pending | ||
512 | * @device_disconnect_time: time of device disconnect | ||
513 | * @control_unit_queuing_time: time of control unit queuing | ||
514 | * @device_active_only_time: time of device active only | ||
515 | * @reserved: unused in basic measurement mode | ||
516 | * | ||
517 | * The measurement block as used by the hardware. The fields are described | ||
518 | * further in z/Architecture Principles of Operation, chapter 17. | ||
502 | * | 519 | * |
503 | * cmb as used by the hardware the fields are described in z/Architecture | 520 | * The cmb area made up from these blocks must be a contiguous array and may |
504 | * Principles of Operation, chapter 17. | 521 | * not be reallocated or freed. |
505 | * The area to be a contiguous array and may not be reallocated or freed. | ||
506 | * Only one cmb area can be present in the system. | 522 | * Only one cmb area can be present in the system. |
507 | */ | 523 | */ |
508 | struct cmb { | 524 | struct cmb { |
@@ -516,8 +532,9 @@ struct cmb { | |||
516 | u32 reserved[2]; | 532 | u32 reserved[2]; |
517 | }; | 533 | }; |
518 | 534 | ||
519 | /* insert a single device into the cmb_area list | 535 | /* |
520 | * called with cmb_area.lock held from alloc_cmb | 536 | * Insert a single device into the cmb_area list. |
537 | * Called with cmb_area.lock held from alloc_cmb. | ||
521 | */ | 538 | */ |
522 | static int alloc_cmb_single(struct ccw_device *cdev, | 539 | static int alloc_cmb_single(struct ccw_device *cdev, |
523 | struct cmb_data *cmb_data) | 540 | struct cmb_data *cmb_data) |
@@ -532,9 +549,11 @@ static int alloc_cmb_single(struct ccw_device *cdev, | |||
532 | goto out; | 549 | goto out; |
533 | } | 550 | } |
534 | 551 | ||
535 | /* find first unused cmb in cmb_area.mem. | 552 | /* |
536 | * this is a little tricky: cmb_area.list | 553 | * Find first unused cmb in cmb_area.mem. |
537 | * remains sorted by ->cmb->hw_data pointers */ | 554 | * This is a little tricky: cmb_area.list |
555 | * remains sorted by ->cmb->hw_data pointers. | ||
556 | */ | ||
538 | cmb = cmb_area.mem; | 557 | cmb = cmb_area.mem; |
539 | list_for_each_entry(node, &cmb_area.list, cmb_list) { | 558 | list_for_each_entry(node, &cmb_area.list, cmb_list) { |
540 | struct cmb_data *data; | 559 | struct cmb_data *data; |
@@ -558,8 +577,7 @@ out: | |||
558 | return ret; | 577 | return ret; |
559 | } | 578 | } |
560 | 579 | ||
561 | static int | 580 | static int alloc_cmb(struct ccw_device *cdev) |
562 | alloc_cmb (struct ccw_device *cdev) | ||
563 | { | 581 | { |
564 | int ret; | 582 | int ret; |
565 | struct cmb *mem; | 583 | struct cmb *mem; |
@@ -670,7 +688,7 @@ static int set_cmb(struct ccw_device *cdev, u32 mme) | |||
670 | return set_schib_wait(cdev, mme, 0, offset); | 688 | return set_schib_wait(cdev, mme, 0, offset); |
671 | } | 689 | } |
672 | 690 | ||
673 | static u64 read_cmb (struct ccw_device *cdev, int index) | 691 | static u64 read_cmb(struct ccw_device *cdev, int index) |
674 | { | 692 | { |
675 | struct cmb *cmb; | 693 | struct cmb *cmb; |
676 | u32 val; | 694 | u32 val; |
@@ -720,7 +738,7 @@ out: | |||
720 | return ret; | 738 | return ret; |
721 | } | 739 | } |
722 | 740 | ||
723 | static int readall_cmb (struct ccw_device *cdev, struct cmbdata *data) | 741 | static int readall_cmb(struct ccw_device *cdev, struct cmbdata *data) |
724 | { | 742 | { |
725 | struct cmb *cmb; | 743 | struct cmb *cmb; |
726 | struct cmb_data *cmb_data; | 744 | struct cmb_data *cmb_data; |
@@ -793,14 +811,25 @@ static struct cmb_operations cmbops_basic = { | |||
793 | .align = align_cmb, | 811 | .align = align_cmb, |
794 | .attr_group = &cmf_attr_group, | 812 | .attr_group = &cmf_attr_group, |
795 | }; | 813 | }; |
796 | 814 | ||
797 | /* ******** extended cmb handling ********/ | 815 | /* ******** extended cmb handling ********/ |
798 | 816 | ||
799 | /** | 817 | /** |
800 | * struct cmbe - extended channel measurement block | 818 | * struct cmbe - extended channel measurement block |
819 | * @ssch_rsch_count: number of ssch and rsch | ||
820 | * @sample_count: number of samples | ||
821 | * @device_connect_time: time of device connect | ||
822 | * @function_pending_time: time of function pending | ||
823 | * @device_disconnect_time: time of device disconnect | ||
824 | * @control_unit_queuing_time: time of control unit queuing | ||
825 | * @device_active_only_time: time of device active only | ||
826 | * @device_busy_time: time of device busy | ||
827 | * @initial_command_response_time: initial command response time | ||
828 | * @reserved: unused | ||
801 | * | 829 | * |
802 | * cmb as used by the hardware, may be in any 64 bit physical location, | 830 | * The measurement block as used by the hardware. May be in any 64 bit physical |
803 | * the fields are described in z/Architecture Principles of Operation, | 831 | * location. |
832 | * The fields are described further in z/Architecture Principles of Operation, | ||
804 | * third edition, chapter 17. | 833 | * third edition, chapter 17. |
805 | */ | 834 | */ |
806 | struct cmbe { | 835 | struct cmbe { |
@@ -816,10 +845,12 @@ struct cmbe { | |||
816 | u32 reserved[7]; | 845 | u32 reserved[7]; |
817 | }; | 846 | }; |
818 | 847 | ||
819 | /* kmalloc only guarantees 8 byte alignment, but we need cmbe | 848 | /* |
849 | * kmalloc only guarantees 8 byte alignment, but we need cmbe | ||
820 | * pointers to be naturally aligned. Make sure to allocate | 850 | * pointers to be naturally aligned. Make sure to allocate |
821 | * enough space for two cmbes */ | 851 | * enough space for two cmbes. |
822 | static inline struct cmbe* cmbe_align(struct cmbe *c) | 852 | */ |
853 | static inline struct cmbe *cmbe_align(struct cmbe *c) | ||
823 | { | 854 | { |
824 | unsigned long addr; | 855 | unsigned long addr; |
825 | addr = ((unsigned long)c + sizeof (struct cmbe) - sizeof(long)) & | 856 | addr = ((unsigned long)c + sizeof (struct cmbe) - sizeof(long)) & |
@@ -827,7 +858,7 @@ static inline struct cmbe* cmbe_align(struct cmbe *c) | |||
827 | return (struct cmbe*)addr; | 858 | return (struct cmbe*)addr; |
828 | } | 859 | } |
829 | 860 | ||
830 | static int alloc_cmbe (struct ccw_device *cdev) | 861 | static int alloc_cmbe(struct ccw_device *cdev) |
831 | { | 862 | { |
832 | struct cmbe *cmbe; | 863 | struct cmbe *cmbe; |
833 | struct cmb_data *cmb_data; | 864 | struct cmb_data *cmb_data; |
@@ -873,7 +904,7 @@ out_free: | |||
873 | return ret; | 904 | return ret; |
874 | } | 905 | } |
875 | 906 | ||
876 | static void free_cmbe (struct ccw_device *cdev) | 907 | static void free_cmbe(struct ccw_device *cdev) |
877 | { | 908 | { |
878 | struct cmb_data *cmb_data; | 909 | struct cmb_data *cmb_data; |
879 | 910 | ||
@@ -912,7 +943,7 @@ static int set_cmbe(struct ccw_device *cdev, u32 mme) | |||
912 | } | 943 | } |
913 | 944 | ||
914 | 945 | ||
915 | static u64 read_cmbe (struct ccw_device *cdev, int index) | 946 | static u64 read_cmbe(struct ccw_device *cdev, int index) |
916 | { | 947 | { |
917 | struct cmbe *cmb; | 948 | struct cmbe *cmb; |
918 | struct cmb_data *cmb_data; | 949 | struct cmb_data *cmb_data; |
@@ -970,7 +1001,7 @@ out: | |||
970 | return ret; | 1001 | return ret; |
971 | } | 1002 | } |
972 | 1003 | ||
973 | static int readall_cmbe (struct ccw_device *cdev, struct cmbdata *data) | 1004 | static int readall_cmbe(struct ccw_device *cdev, struct cmbdata *data) |
974 | { | 1005 | { |
975 | struct cmbe *cmb; | 1006 | struct cmbe *cmb; |
976 | struct cmb_data *cmb_data; | 1007 | struct cmb_data *cmb_data; |
@@ -1047,17 +1078,16 @@ static struct cmb_operations cmbops_extended = { | |||
1047 | .align = align_cmbe, | 1078 | .align = align_cmbe, |
1048 | .attr_group = &cmf_attr_group_ext, | 1079 | .attr_group = &cmf_attr_group_ext, |
1049 | }; | 1080 | }; |
1050 | |||
1051 | 1081 | ||
1052 | static ssize_t | 1082 | static ssize_t cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx) |
1053 | cmb_show_attr(struct device *dev, char *buf, enum cmb_index idx) | ||
1054 | { | 1083 | { |
1055 | return sprintf(buf, "%lld\n", | 1084 | return sprintf(buf, "%lld\n", |
1056 | (unsigned long long) cmf_read(to_ccwdev(dev), idx)); | 1085 | (unsigned long long) cmf_read(to_ccwdev(dev), idx)); |
1057 | } | 1086 | } |
1058 | 1087 | ||
1059 | static ssize_t | 1088 | static ssize_t cmb_show_avg_sample_interval(struct device *dev, |
1060 | cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, char *buf) | 1089 | struct device_attribute *attr, |
1090 | char *buf) | ||
1061 | { | 1091 | { |
1062 | struct ccw_device *cdev; | 1092 | struct ccw_device *cdev; |
1063 | long interval; | 1093 | long interval; |
@@ -1079,8 +1109,9 @@ cmb_show_avg_sample_interval(struct device *dev, struct device_attribute *attr, | |||
1079 | return sprintf(buf, "%ld\n", interval); | 1109 | return sprintf(buf, "%ld\n", interval); |
1080 | } | 1110 | } |
1081 | 1111 | ||
1082 | static ssize_t | 1112 | static ssize_t cmb_show_avg_utilization(struct device *dev, |
1083 | cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char *buf) | 1113 | struct device_attribute *attr, |
1114 | char *buf) | ||
1084 | { | 1115 | { |
1085 | struct cmbdata data; | 1116 | struct cmbdata data; |
1086 | u64 utilization; | 1117 | u64 utilization; |
@@ -1112,14 +1143,16 @@ cmb_show_avg_utilization(struct device *dev, struct device_attribute *attr, char | |||
1112 | } | 1143 | } |
1113 | 1144 | ||
1114 | #define cmf_attr(name) \ | 1145 | #define cmf_attr(name) \ |
1115 | static ssize_t show_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \ | 1146 | static ssize_t show_##name(struct device *dev, \ |
1116 | { return cmb_show_attr((dev), buf, cmb_ ## name); } \ | 1147 | struct device_attribute *attr, char *buf) \ |
1117 | static DEVICE_ATTR(name, 0444, show_ ## name, NULL); | 1148 | { return cmb_show_attr((dev), buf, cmb_##name); } \ |
1149 | static DEVICE_ATTR(name, 0444, show_##name, NULL); | ||
1118 | 1150 | ||
1119 | #define cmf_attr_avg(name) \ | 1151 | #define cmf_attr_avg(name) \ |
1120 | static ssize_t show_avg_ ## name (struct device * dev, struct device_attribute *attr, char * buf) \ | 1152 | static ssize_t show_avg_##name(struct device *dev, \ |
1121 | { return cmb_show_attr((dev), buf, cmb_ ## name); } \ | 1153 | struct device_attribute *attr, char *buf) \ |
1122 | static DEVICE_ATTR(avg_ ## name, 0444, show_avg_ ## name, NULL); | 1154 | { return cmb_show_attr((dev), buf, cmb_##name); } \ |
1155 | static DEVICE_ATTR(avg_##name, 0444, show_avg_##name, NULL); | ||
1123 | 1156 | ||
1124 | cmf_attr(ssch_rsch_count); | 1157 | cmf_attr(ssch_rsch_count); |
1125 | cmf_attr(sample_count); | 1158 | cmf_attr(sample_count); |
@@ -1131,7 +1164,8 @@ cmf_attr_avg(device_active_only_time); | |||
1131 | cmf_attr_avg(device_busy_time); | 1164 | cmf_attr_avg(device_busy_time); |
1132 | cmf_attr_avg(initial_command_response_time); | 1165 | cmf_attr_avg(initial_command_response_time); |
1133 | 1166 | ||
1134 | static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval, NULL); | 1167 | static DEVICE_ATTR(avg_sample_interval, 0444, cmb_show_avg_sample_interval, |
1168 | NULL); | ||
1135 | static DEVICE_ATTR(avg_utilization, 0444, cmb_show_avg_utilization, NULL); | 1169 | static DEVICE_ATTR(avg_utilization, 0444, cmb_show_avg_utilization, NULL); |
1136 | 1170 | ||
1137 | static struct attribute *cmf_attributes[] = { | 1171 | static struct attribute *cmf_attributes[] = { |
@@ -1172,12 +1206,16 @@ static struct attribute_group cmf_attr_group_ext = { | |||
1172 | .attrs = cmf_attributes_ext, | 1206 | .attrs = cmf_attributes_ext, |
1173 | }; | 1207 | }; |
1174 | 1208 | ||
1175 | static ssize_t cmb_enable_show(struct device *dev, struct device_attribute *attr, char *buf) | 1209 | static ssize_t cmb_enable_show(struct device *dev, |
1210 | struct device_attribute *attr, | ||
1211 | char *buf) | ||
1176 | { | 1212 | { |
1177 | return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0); | 1213 | return sprintf(buf, "%d\n", to_ccwdev(dev)->private->cmb ? 1 : 0); |
1178 | } | 1214 | } |
1179 | 1215 | ||
1180 | static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t c) | 1216 | static ssize_t cmb_enable_store(struct device *dev, |
1217 | struct device_attribute *attr, const char *buf, | ||
1218 | size_t c) | ||
1181 | { | 1219 | { |
1182 | struct ccw_device *cdev; | 1220 | struct ccw_device *cdev; |
1183 | int ret; | 1221 | int ret; |
@@ -1202,9 +1240,16 @@ static ssize_t cmb_enable_store(struct device *dev, struct device_attribute *att | |||
1202 | 1240 | ||
1203 | DEVICE_ATTR(cmb_enable, 0644, cmb_enable_show, cmb_enable_store); | 1241 | DEVICE_ATTR(cmb_enable, 0644, cmb_enable_show, cmb_enable_store); |
1204 | 1242 | ||
1205 | /* enable_cmf/disable_cmf: module interface for cmf (de)activation */ | 1243 | /** |
1206 | int | 1244 | * enable_cmf() - switch on the channel measurement for a specific device |
1207 | enable_cmf(struct ccw_device *cdev) | 1245 | * @cdev: The ccw device to be enabled |
1246 | * | ||
1247 | * Returns %0 for success or a negative error value. | ||
1248 | * | ||
1249 | * Context: | ||
1250 | * non-atomic | ||
1251 | */ | ||
1252 | int enable_cmf(struct ccw_device *cdev) | ||
1208 | { | 1253 | { |
1209 | int ret; | 1254 | int ret; |
1210 | 1255 | ||
@@ -1225,8 +1270,16 @@ enable_cmf(struct ccw_device *cdev) | |||
1225 | return ret; | 1270 | return ret; |
1226 | } | 1271 | } |
1227 | 1272 | ||
1228 | int | 1273 | /** |
1229 | disable_cmf(struct ccw_device *cdev) | 1274 | * disable_cmf() - switch off the channel measurement for a specific device |
1275 | * @cdev: The ccw device to be disabled | ||
1276 | * | ||
1277 | * Returns %0 for success or a negative error value. | ||
1278 | * | ||
1279 | * Context: | ||
1280 | * non-atomic | ||
1281 | */ | ||
1282 | int disable_cmf(struct ccw_device *cdev) | ||
1230 | { | 1283 | { |
1231 | int ret; | 1284 | int ret; |
1232 | 1285 | ||
@@ -1238,14 +1291,32 @@ disable_cmf(struct ccw_device *cdev) | |||
1238 | return ret; | 1291 | return ret; |
1239 | } | 1292 | } |
1240 | 1293 | ||
1241 | u64 | 1294 | /** |
1242 | cmf_read(struct ccw_device *cdev, int index) | 1295 | * cmf_read() - read one value from the current channel measurement block |
1296 | * @cdev: the channel to be read | ||
1297 | * @index: the index of the value to be read | ||
1298 | * | ||
1299 | * Returns the value read or %0 if the value cannot be read. | ||
1300 | * | ||
1301 | * Context: | ||
1302 | * any | ||
1303 | */ | ||
1304 | u64 cmf_read(struct ccw_device *cdev, int index) | ||
1243 | { | 1305 | { |
1244 | return cmbops->read(cdev, index); | 1306 | return cmbops->read(cdev, index); |
1245 | } | 1307 | } |
1246 | 1308 | ||
1247 | int | 1309 | /** |
1248 | cmf_readall(struct ccw_device *cdev, struct cmbdata *data) | 1310 | * cmf_readall() - read the current channel measurement block |
1311 | * @cdev: the channel to be read | ||
1312 | * @data: a pointer to a data block that will be filled | ||
1313 | * | ||
1314 | * Returns %0 on success, a negative error value otherwise. | ||
1315 | * | ||
1316 | * Context: | ||
1317 | * any | ||
1318 | */ | ||
1319 | int cmf_readall(struct ccw_device *cdev, struct cmbdata *data) | ||
1249 | { | 1320 | { |
1250 | return cmbops->readall(cdev, data); | 1321 | return cmbops->readall(cdev, data); |
1251 | } | 1322 | } |
@@ -1257,15 +1328,16 @@ int cmf_reenable(struct ccw_device *cdev) | |||
1257 | return cmbops->set(cdev, 2); | 1328 | return cmbops->set(cdev, 2); |
1258 | } | 1329 | } |
1259 | 1330 | ||
1260 | static int __init | 1331 | static int __init init_cmf(void) |
1261 | init_cmf(void) | ||
1262 | { | 1332 | { |
1263 | char *format_string; | 1333 | char *format_string; |
1264 | char *detect_string = "parameter"; | 1334 | char *detect_string = "parameter"; |
1265 | 1335 | ||
1266 | /* We cannot really autoprobe this. If the user did not give a parameter, | 1336 | /* |
1267 | see if we are running on z990 or up, otherwise fall back to basic mode. */ | 1337 | * If the user did not give a parameter, see if we are running on a |
1268 | 1338 | * machine supporting extended measurement blocks, otherwise fall back | |
1339 | * to basic mode. | ||
1340 | */ | ||
1269 | if (format == CMF_AUTODETECT) { | 1341 | if (format == CMF_AUTODETECT) { |
1270 | if (!css_characteristics_avail || | 1342 | if (!css_characteristics_avail || |
1271 | !css_general_characteristics.ext_mb) { | 1343 | !css_general_characteristics.ext_mb) { |
@@ -1284,7 +1356,7 @@ init_cmf(void) | |||
1284 | cmbops = &cmbops_basic; | 1356 | cmbops = &cmbops_basic; |
1285 | break; | 1357 | break; |
1286 | case CMF_EXTENDED: | 1358 | case CMF_EXTENDED: |
1287 | format_string = "extended"; | 1359 | format_string = "extended"; |
1288 | cmbops = &cmbops_extended; | 1360 | cmbops = &cmbops_extended; |
1289 | break; | 1361 | break; |
1290 | default: | 1362 | default: |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 5635e656c1a3..5d83dd471461 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/list.h> | 15 | #include <linux/list.h> |
16 | #include <linux/reboot.h> | ||
16 | 17 | ||
17 | #include "css.h" | 18 | #include "css.h" |
18 | #include "cio.h" | 19 | #include "cio.h" |
@@ -27,7 +28,7 @@ int css_init_done = 0; | |||
27 | static int need_reprobe = 0; | 28 | static int need_reprobe = 0; |
28 | static int max_ssid = 0; | 29 | static int max_ssid = 0; |
29 | 30 | ||
30 | struct channel_subsystem *css[__MAX_CSSID + 1]; | 31 | struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; |
31 | 32 | ||
32 | int css_characteristics_avail = 0; | 33 | int css_characteristics_avail = 0; |
33 | 34 | ||
@@ -177,7 +178,7 @@ static int css_register_subchannel(struct subchannel *sch) | |||
177 | int ret; | 178 | int ret; |
178 | 179 | ||
179 | /* Initialize the subchannel structure */ | 180 | /* Initialize the subchannel structure */ |
180 | sch->dev.parent = &css[0]->device; | 181 | sch->dev.parent = &channel_subsystems[0]->device; |
181 | sch->dev.bus = &css_bus_type; | 182 | sch->dev.bus = &css_bus_type; |
182 | sch->dev.release = &css_subchannel_release; | 183 | sch->dev.release = &css_subchannel_release; |
183 | sch->dev.groups = subch_attr_groups; | 184 | sch->dev.groups = subch_attr_groups; |
@@ -606,30 +607,55 @@ static int __init setup_css(int nr) | |||
606 | { | 607 | { |
607 | u32 tod_high; | 608 | u32 tod_high; |
608 | int ret; | 609 | int ret; |
610 | struct channel_subsystem *css; | ||
609 | 611 | ||
610 | memset(css[nr], 0, sizeof(struct channel_subsystem)); | 612 | css = channel_subsystems[nr]; |
611 | css[nr]->pseudo_subchannel = | 613 | memset(css, 0, sizeof(struct channel_subsystem)); |
612 | kzalloc(sizeof(*css[nr]->pseudo_subchannel), GFP_KERNEL); | 614 | css->pseudo_subchannel = |
613 | if (!css[nr]->pseudo_subchannel) | 615 | kzalloc(sizeof(*css->pseudo_subchannel), GFP_KERNEL); |
616 | if (!css->pseudo_subchannel) | ||
614 | return -ENOMEM; | 617 | return -ENOMEM; |
615 | css[nr]->pseudo_subchannel->dev.parent = &css[nr]->device; | 618 | css->pseudo_subchannel->dev.parent = &css->device; |
616 | css[nr]->pseudo_subchannel->dev.release = css_subchannel_release; | 619 | css->pseudo_subchannel->dev.release = css_subchannel_release; |
617 | sprintf(css[nr]->pseudo_subchannel->dev.bus_id, "defunct"); | 620 | sprintf(css->pseudo_subchannel->dev.bus_id, "defunct"); |
618 | ret = cio_create_sch_lock(css[nr]->pseudo_subchannel); | 621 | ret = cio_create_sch_lock(css->pseudo_subchannel); |
619 | if (ret) { | 622 | if (ret) { |
620 | kfree(css[nr]->pseudo_subchannel); | 623 | kfree(css->pseudo_subchannel); |
621 | return ret; | 624 | return ret; |
622 | } | 625 | } |
623 | mutex_init(&css[nr]->mutex); | 626 | mutex_init(&css->mutex); |
624 | css[nr]->valid = 1; | 627 | css->valid = 1; |
625 | css[nr]->cssid = nr; | 628 | css->cssid = nr; |
626 | sprintf(css[nr]->device.bus_id, "css%x", nr); | 629 | sprintf(css->device.bus_id, "css%x", nr); |
627 | css[nr]->device.release = channel_subsystem_release; | 630 | css->device.release = channel_subsystem_release; |
628 | tod_high = (u32) (get_clock() >> 32); | 631 | tod_high = (u32) (get_clock() >> 32); |
629 | css_generate_pgid(css[nr], tod_high); | 632 | css_generate_pgid(css, tod_high); |
630 | return 0; | 633 | return 0; |
631 | } | 634 | } |
632 | 635 | ||
636 | static int css_reboot_event(struct notifier_block *this, | ||
637 | unsigned long event, | ||
638 | void *ptr) | ||
639 | { | ||
640 | int ret, i; | ||
641 | |||
642 | ret = NOTIFY_DONE; | ||
643 | for (i = 0; i <= __MAX_CSSID; i++) { | ||
644 | struct channel_subsystem *css; | ||
645 | |||
646 | css = channel_subsystems[i]; | ||
647 | if (css->cm_enabled) | ||
648 | if (chsc_secm(css, 0)) | ||
649 | ret = NOTIFY_BAD; | ||
650 | } | ||
651 | |||
652 | return ret; | ||
653 | } | ||
654 | |||
655 | static struct notifier_block css_reboot_notifier = { | ||
656 | .notifier_call = css_reboot_event, | ||
657 | }; | ||
658 | |||
633 | /* | 659 | /* |
634 | * Now that the driver core is running, we can setup our channel subsystem. | 660 | * Now that the driver core is running, we can setup our channel subsystem. |
635 | * The struct subchannel's are created during probing (except for the | 661 | * The struct subchannel's are created during probing (except for the |
@@ -670,51 +696,63 @@ init_channel_subsystem (void) | |||
670 | } | 696 | } |
671 | /* Setup css structure. */ | 697 | /* Setup css structure. */ |
672 | for (i = 0; i <= __MAX_CSSID; i++) { | 698 | for (i = 0; i <= __MAX_CSSID; i++) { |
673 | css[i] = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); | 699 | struct channel_subsystem *css; |
674 | if (!css[i]) { | 700 | |
701 | css = kmalloc(sizeof(struct channel_subsystem), GFP_KERNEL); | ||
702 | if (!css) { | ||
675 | ret = -ENOMEM; | 703 | ret = -ENOMEM; |
676 | goto out_unregister; | 704 | goto out_unregister; |
677 | } | 705 | } |
706 | channel_subsystems[i] = css; | ||
678 | ret = setup_css(i); | 707 | ret = setup_css(i); |
679 | if (ret) | 708 | if (ret) |
680 | goto out_free; | 709 | goto out_free; |
681 | ret = device_register(&css[i]->device); | 710 | ret = device_register(&css->device); |
682 | if (ret) | 711 | if (ret) |
683 | goto out_free_all; | 712 | goto out_free_all; |
684 | if (css_characteristics_avail && | 713 | if (css_characteristics_avail && |
685 | css_chsc_characteristics.secm) { | 714 | css_chsc_characteristics.secm) { |
686 | ret = device_create_file(&css[i]->device, | 715 | ret = device_create_file(&css->device, |
687 | &dev_attr_cm_enable); | 716 | &dev_attr_cm_enable); |
688 | if (ret) | 717 | if (ret) |
689 | goto out_device; | 718 | goto out_device; |
690 | } | 719 | } |
691 | ret = device_register(&css[i]->pseudo_subchannel->dev); | 720 | ret = device_register(&css->pseudo_subchannel->dev); |
692 | if (ret) | 721 | if (ret) |
693 | goto out_file; | 722 | goto out_file; |
694 | } | 723 | } |
724 | ret = register_reboot_notifier(&css_reboot_notifier); | ||
725 | if (ret) | ||
726 | goto out_pseudo; | ||
695 | css_init_done = 1; | 727 | css_init_done = 1; |
696 | 728 | ||
697 | ctl_set_bit(6, 28); | 729 | ctl_set_bit(6, 28); |
698 | 730 | ||
699 | for_each_subchannel(__init_channel_subsystem, NULL); | 731 | for_each_subchannel(__init_channel_subsystem, NULL); |
700 | return 0; | 732 | return 0; |
733 | out_pseudo: | ||
734 | device_unregister(&channel_subsystems[i]->pseudo_subchannel->dev); | ||
701 | out_file: | 735 | out_file: |
702 | device_remove_file(&css[i]->device, &dev_attr_cm_enable); | 736 | device_remove_file(&channel_subsystems[i]->device, |
737 | &dev_attr_cm_enable); | ||
703 | out_device: | 738 | out_device: |
704 | device_unregister(&css[i]->device); | 739 | device_unregister(&channel_subsystems[i]->device); |
705 | out_free_all: | 740 | out_free_all: |
706 | kfree(css[i]->pseudo_subchannel->lock); | 741 | kfree(channel_subsystems[i]->pseudo_subchannel->lock); |
707 | kfree(css[i]->pseudo_subchannel); | 742 | kfree(channel_subsystems[i]->pseudo_subchannel); |
708 | out_free: | 743 | out_free: |
709 | kfree(css[i]); | 744 | kfree(channel_subsystems[i]); |
710 | out_unregister: | 745 | out_unregister: |
711 | while (i > 0) { | 746 | while (i > 0) { |
747 | struct channel_subsystem *css; | ||
748 | |||
712 | i--; | 749 | i--; |
713 | device_unregister(&css[i]->pseudo_subchannel->dev); | 750 | css = channel_subsystems[i]; |
751 | device_unregister(&css->pseudo_subchannel->dev); | ||
714 | if (css_characteristics_avail && css_chsc_characteristics.secm) | 752 | if (css_characteristics_avail && css_chsc_characteristics.secm) |
715 | device_remove_file(&css[i]->device, | 753 | device_remove_file(&css->device, |
716 | &dev_attr_cm_enable); | 754 | &dev_attr_cm_enable); |
717 | device_unregister(&css[i]->device); | 755 | device_unregister(&css->device); |
718 | } | 756 | } |
719 | out_bus: | 757 | out_bus: |
720 | bus_unregister(&css_bus_type); | 758 | bus_unregister(&css_bus_type); |
diff --git a/drivers/s390/cio/css.h b/drivers/s390/cio/css.h index 5d65e83ca66e..81215ef32435 100644 --- a/drivers/s390/cio/css.h +++ b/drivers/s390/cio/css.h | |||
@@ -167,7 +167,7 @@ struct channel_subsystem { | |||
167 | #define to_css(dev) container_of(dev, struct channel_subsystem, device) | 167 | #define to_css(dev) container_of(dev, struct channel_subsystem, device) |
168 | 168 | ||
169 | extern struct bus_type css_bus_type; | 169 | extern struct bus_type css_bus_type; |
170 | extern struct channel_subsystem *css[]; | 170 | extern struct channel_subsystem *channel_subsystems[]; |
171 | 171 | ||
172 | /* Some helper functions for disconnected state. */ | 172 | /* Some helper functions for disconnected state. */ |
173 | int device_is_disconnected(struct subchannel *); | 173 | int device_is_disconnected(struct subchannel *); |
@@ -191,6 +191,5 @@ int sch_is_pseudo_sch(struct subchannel *); | |||
191 | 191 | ||
192 | extern struct workqueue_struct *slow_path_wq; | 192 | extern struct workqueue_struct *slow_path_wq; |
193 | 193 | ||
194 | int subchannel_add_files (struct device *); | ||
195 | extern struct attribute_group *subch_attr_groups[]; | 194 | extern struct attribute_group *subch_attr_groups[]; |
196 | #endif | 195 | #endif |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 606bb53e9fae..7ee57f084a89 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/ccwdev.h> | 21 | #include <asm/ccwdev.h> |
22 | #include <asm/cio.h> | 22 | #include <asm/cio.h> |
23 | #include <asm/param.h> /* HZ */ | 23 | #include <asm/param.h> /* HZ */ |
24 | #include <asm/cmb.h> | ||
24 | 25 | ||
25 | #include "cio.h" | 26 | #include "cio.h" |
26 | #include "cio_debug.h" | 27 | #include "cio_debug.h" |
@@ -346,8 +347,18 @@ ccw_device_remove_disconnected(struct ccw_device *cdev) | |||
346 | cdev->private->dev_id.devno); | 347 | cdev->private->dev_id.devno); |
347 | } | 348 | } |
348 | 349 | ||
349 | int | 350 | /** |
350 | ccw_device_set_offline(struct ccw_device *cdev) | 351 | * ccw_device_set_offline() - disable a ccw device for I/O |
352 | * @cdev: target ccw device | ||
353 | * | ||
354 | * This function calls the driver's set_offline() function for @cdev, if | ||
355 | * given, and then disables @cdev. | ||
356 | * Returns: | ||
357 | * %0 on success and a negative error value on failure. | ||
358 | * Context: | ||
359 | * enabled, ccw device lock not held | ||
360 | */ | ||
361 | int ccw_device_set_offline(struct ccw_device *cdev) | ||
351 | { | 362 | { |
352 | int ret; | 363 | int ret; |
353 | 364 | ||
@@ -385,8 +396,19 @@ ccw_device_set_offline(struct ccw_device *cdev) | |||
385 | return ret; | 396 | return ret; |
386 | } | 397 | } |
387 | 398 | ||
388 | int | 399 | /** |
389 | ccw_device_set_online(struct ccw_device *cdev) | 400 | * ccw_device_set_online() - enable a ccw device for I/O |
401 | * @cdev: target ccw device | ||
402 | * | ||
403 | * This function first enables @cdev and then calls the driver's set_online() | ||
404 | * function for @cdev, if given. If set_online() returns an error, @cdev is | ||
405 | * disabled again. | ||
406 | * Returns: | ||
407 | * %0 on success and a negative error value on failure. | ||
408 | * Context: | ||
409 | * enabled, ccw device lock not held | ||
410 | */ | ||
411 | int ccw_device_set_online(struct ccw_device *cdev) | ||
390 | { | 412 | { |
391 | int ret; | 413 | int ret; |
392 | 414 | ||
@@ -936,8 +958,7 @@ out: | |||
936 | wake_up(&ccw_device_init_wq); | 958 | wake_up(&ccw_device_init_wq); |
937 | } | 959 | } |
938 | 960 | ||
939 | void | 961 | static void ccw_device_call_sch_unregister(struct work_struct *work) |
940 | ccw_device_call_sch_unregister(struct work_struct *work) | ||
941 | { | 962 | { |
942 | struct ccw_device_private *priv; | 963 | struct ccw_device_private *priv; |
943 | struct ccw_device *cdev; | 964 | struct ccw_device *cdev; |
@@ -1090,6 +1111,7 @@ io_subchannel_probe (struct subchannel *sch) | |||
1090 | * device, e.g. the console. | 1111 | * device, e.g. the console. |
1091 | */ | 1112 | */ |
1092 | cdev = sch->dev.driver_data; | 1113 | cdev = sch->dev.driver_data; |
1114 | cdev->dev.groups = ccwdev_attr_groups; | ||
1093 | device_initialize(&cdev->dev); | 1115 | device_initialize(&cdev->dev); |
1094 | ccw_device_register(cdev); | 1116 | ccw_device_register(cdev); |
1095 | /* | 1117 | /* |
@@ -1315,8 +1337,19 @@ __ccwdev_check_busid(struct device *dev, void *id) | |||
1315 | } | 1337 | } |
1316 | 1338 | ||
1317 | 1339 | ||
1318 | struct ccw_device * | 1340 | /** |
1319 | get_ccwdev_by_busid(struct ccw_driver *cdrv, const char *bus_id) | 1341 | * get_ccwdev_by_busid() - obtain device from a bus id |
1342 | * @cdrv: driver the device is owned by | ||
1343 | * @bus_id: bus id of the device to be searched | ||
1344 | * | ||
1345 | * This function searches all devices owned by @cdrv for a device with a bus | ||
1346 | * id matching @bus_id. | ||
1347 | * Returns: | ||
1348 | * If a match is found, its reference count of the found device is increased | ||
1349 | * and it is returned; else %NULL is returned. | ||
1350 | */ | ||
1351 | struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv, | ||
1352 | const char *bus_id) | ||
1320 | { | 1353 | { |
1321 | struct device *dev; | 1354 | struct device *dev; |
1322 | struct device_driver *drv; | 1355 | struct device_driver *drv; |
@@ -1390,16 +1423,34 @@ ccw_device_remove (struct device *dev) | |||
1390 | return 0; | 1423 | return 0; |
1391 | } | 1424 | } |
1392 | 1425 | ||
1426 | static void ccw_device_shutdown(struct device *dev) | ||
1427 | { | ||
1428 | struct ccw_device *cdev; | ||
1429 | |||
1430 | cdev = to_ccwdev(dev); | ||
1431 | if (cdev->drv && cdev->drv->shutdown) | ||
1432 | cdev->drv->shutdown(cdev); | ||
1433 | disable_cmf(cdev); | ||
1434 | } | ||
1435 | |||
1393 | struct bus_type ccw_bus_type = { | 1436 | struct bus_type ccw_bus_type = { |
1394 | .name = "ccw", | 1437 | .name = "ccw", |
1395 | .match = ccw_bus_match, | 1438 | .match = ccw_bus_match, |
1396 | .uevent = ccw_uevent, | 1439 | .uevent = ccw_uevent, |
1397 | .probe = ccw_device_probe, | 1440 | .probe = ccw_device_probe, |
1398 | .remove = ccw_device_remove, | 1441 | .remove = ccw_device_remove, |
1442 | .shutdown = ccw_device_shutdown, | ||
1399 | }; | 1443 | }; |
1400 | 1444 | ||
1401 | int | 1445 | /** |
1402 | ccw_driver_register (struct ccw_driver *cdriver) | 1446 | * ccw_driver_register() - register a ccw driver |
1447 | * @cdriver: driver to be registered | ||
1448 | * | ||
1449 | * This function is mainly a wrapper around driver_register(). | ||
1450 | * Returns: | ||
1451 | * %0 on success and a negative error value on failure. | ||
1452 | */ | ||
1453 | int ccw_driver_register(struct ccw_driver *cdriver) | ||
1403 | { | 1454 | { |
1404 | struct device_driver *drv = &cdriver->driver; | 1455 | struct device_driver *drv = &cdriver->driver; |
1405 | 1456 | ||
@@ -1409,8 +1460,13 @@ ccw_driver_register (struct ccw_driver *cdriver) | |||
1409 | return driver_register(drv); | 1460 | return driver_register(drv); |
1410 | } | 1461 | } |
1411 | 1462 | ||
1412 | void | 1463 | /** |
1413 | ccw_driver_unregister (struct ccw_driver *cdriver) | 1464 | * ccw_driver_unregister() - deregister a ccw driver |
1465 | * @cdriver: driver to be deregistered | ||
1466 | * | ||
1467 | * This function is mainly a wrapper around driver_unregister(). | ||
1468 | */ | ||
1469 | void ccw_driver_unregister(struct ccw_driver *cdriver) | ||
1414 | { | 1470 | { |
1415 | driver_unregister(&cdriver->driver); | 1471 | driver_unregister(&cdriver->driver); |
1416 | } | 1472 | } |
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index b66338b76579..0d4089600439 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -80,7 +80,6 @@ void io_subchannel_recog_done(struct ccw_device *cdev); | |||
80 | int ccw_device_cancel_halt_clear(struct ccw_device *); | 80 | int ccw_device_cancel_halt_clear(struct ccw_device *); |
81 | 81 | ||
82 | void ccw_device_do_unreg_rereg(struct work_struct *); | 82 | void ccw_device_do_unreg_rereg(struct work_struct *); |
83 | void ccw_device_call_sch_unregister(struct work_struct *); | ||
84 | void ccw_device_move_to_orphanage(struct work_struct *); | 83 | void ccw_device_move_to_orphanage(struct work_struct *); |
85 | int ccw_device_is_orphan(struct ccw_device *); | 84 | int ccw_device_is_orphan(struct ccw_device *); |
86 | 85 | ||
diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8633dc537695..8867443b8060 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c | |||
@@ -446,7 +446,8 @@ static void __ccw_device_get_common_pgid(struct ccw_device *cdev) | |||
446 | if (cdev->private->pgid[last].inf.ps.state1 == | 446 | if (cdev->private->pgid[last].inf.ps.state1 == |
447 | SNID_STATE1_RESET) | 447 | SNID_STATE1_RESET) |
448 | /* No previous pgid found */ | 448 | /* No previous pgid found */ |
449 | memcpy(&cdev->private->pgid[0], &css[0]->global_pgid, | 449 | memcpy(&cdev->private->pgid[0], |
450 | &channel_subsystems[0]->global_pgid, | ||
450 | sizeof(struct pgid)); | 451 | sizeof(struct pgid)); |
451 | else | 452 | else |
452 | /* Use existing pgid */ | 453 | /* Use existing pgid */ |
@@ -543,51 +544,6 @@ ccw_device_recog_timeout(struct ccw_device *cdev, enum dev_event dev_event) | |||
543 | } | 544 | } |
544 | 545 | ||
545 | 546 | ||
546 | static void | ||
547 | ccw_device_nopath_notify(struct work_struct *work) | ||
548 | { | ||
549 | struct ccw_device_private *priv; | ||
550 | struct ccw_device *cdev; | ||
551 | struct subchannel *sch; | ||
552 | int ret; | ||
553 | unsigned long flags; | ||
554 | |||
555 | priv = container_of(work, struct ccw_device_private, kick_work); | ||
556 | cdev = priv->cdev; | ||
557 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
558 | sch = to_subchannel(cdev->dev.parent); | ||
559 | /* Extra sanity. */ | ||
560 | if (sch->lpm) | ||
561 | goto out_unlock; | ||
562 | if (sch->driver && sch->driver->notify) { | ||
563 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
564 | ret = sch->driver->notify(&sch->dev, CIO_NO_PATH); | ||
565 | spin_lock_irqsave(cdev->ccwlock, flags); | ||
566 | } else | ||
567 | ret = 0; | ||
568 | if (!ret) { | ||
569 | if (get_device(&sch->dev)) { | ||
570 | /* Driver doesn't want to keep device. */ | ||
571 | cio_disable_subchannel(sch); | ||
572 | if (get_device(&cdev->dev)) { | ||
573 | PREPARE_WORK(&cdev->private->kick_work, | ||
574 | ccw_device_call_sch_unregister); | ||
575 | queue_work(ccw_device_work, | ||
576 | &cdev->private->kick_work); | ||
577 | } else | ||
578 | put_device(&sch->dev); | ||
579 | } | ||
580 | } else { | ||
581 | cio_disable_subchannel(sch); | ||
582 | ccw_device_set_timeout(cdev, 0); | ||
583 | cdev->private->flags.fake_irb = 0; | ||
584 | cdev->private->state = DEV_STATE_DISCONNECTED; | ||
585 | wake_up(&cdev->private->wait_q); | ||
586 | } | ||
587 | out_unlock: | ||
588 | spin_unlock_irqrestore(cdev->ccwlock, flags); | ||
589 | } | ||
590 | |||
591 | void | 547 | void |
592 | ccw_device_verify_done(struct ccw_device *cdev, int err) | 548 | ccw_device_verify_done(struct ccw_device *cdev, int err) |
593 | { | 549 | { |
@@ -631,12 +587,9 @@ ccw_device_verify_done(struct ccw_device *cdev, int err) | |||
631 | default: | 587 | default: |
632 | /* Reset oper notify indication after verify error. */ | 588 | /* Reset oper notify indication after verify error. */ |
633 | cdev->private->flags.donotify = 0; | 589 | cdev->private->flags.donotify = 0; |
634 | if (cdev->online) { | 590 | if (cdev->online) |
635 | PREPARE_WORK(&cdev->private->kick_work, | 591 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); |
636 | ccw_device_nopath_notify); | 592 | else |
637 | queue_work(ccw_device_notify_work, | ||
638 | &cdev->private->kick_work); | ||
639 | } else | ||
640 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); | 593 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); |
641 | break; | 594 | break; |
642 | } | 595 | } |
@@ -690,11 +643,7 @@ ccw_device_disband_done(struct ccw_device *cdev, int err) | |||
690 | break; | 643 | break; |
691 | default: | 644 | default: |
692 | cdev->private->flags.donotify = 0; | 645 | cdev->private->flags.donotify = 0; |
693 | if (get_device(&cdev->dev)) { | 646 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); |
694 | PREPARE_WORK(&cdev->private->kick_work, | ||
695 | ccw_device_call_sch_unregister); | ||
696 | queue_work(ccw_device_work, &cdev->private->kick_work); | ||
697 | } | ||
698 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); | 647 | ccw_device_done(cdev, DEV_STATE_NOT_OPER); |
699 | break; | 648 | break; |
700 | } | 649 | } |
@@ -765,59 +714,16 @@ ccw_device_recog_notoper(struct ccw_device *cdev, enum dev_event dev_event) | |||
765 | } | 714 | } |
766 | 715 | ||
767 | /* | 716 | /* |
768 | * Handle not operational event while offline. | 717 | * Handle not operational event in non-special state. |
769 | */ | 718 | */ |
770 | static void | 719 | static void ccw_device_generic_notoper(struct ccw_device *cdev, |
771 | ccw_device_offline_notoper(struct ccw_device *cdev, enum dev_event dev_event) | 720 | enum dev_event dev_event) |
772 | { | 721 | { |
773 | struct subchannel *sch; | 722 | struct subchannel *sch; |
774 | 723 | ||
775 | cdev->private->state = DEV_STATE_NOT_OPER; | 724 | cdev->private->state = DEV_STATE_NOT_OPER; |
776 | sch = to_subchannel(cdev->dev.parent); | 725 | sch = to_subchannel(cdev->dev.parent); |
777 | if (get_device(&cdev->dev)) { | 726 | css_schedule_eval(sch->schid); |
778 | PREPARE_WORK(&cdev->private->kick_work, | ||
779 | ccw_device_call_sch_unregister); | ||
780 | queue_work(ccw_device_work, &cdev->private->kick_work); | ||
781 | } | ||
782 | wake_up(&cdev->private->wait_q); | ||
783 | } | ||
784 | |||
785 | /* | ||
786 | * Handle not operational event while online. | ||
787 | */ | ||
788 | static void | ||
789 | ccw_device_online_notoper(struct ccw_device *cdev, enum dev_event dev_event) | ||
790 | { | ||
791 | struct subchannel *sch; | ||
792 | int ret; | ||
793 | |||
794 | sch = to_subchannel(cdev->dev.parent); | ||
795 | if (sch->driver->notify) { | ||
796 | spin_unlock_irq(cdev->ccwlock); | ||
797 | ret = sch->driver->notify(&sch->dev, | ||
798 | sch->lpm ? CIO_GONE : CIO_NO_PATH); | ||
799 | spin_lock_irq(cdev->ccwlock); | ||
800 | } else | ||
801 | ret = 0; | ||
802 | if (ret) { | ||
803 | ccw_device_set_timeout(cdev, 0); | ||
804 | cdev->private->flags.fake_irb = 0; | ||
805 | cdev->private->state = DEV_STATE_DISCONNECTED; | ||
806 | wake_up(&cdev->private->wait_q); | ||
807 | return; | ||
808 | } | ||
809 | cdev->private->state = DEV_STATE_NOT_OPER; | ||
810 | cio_disable_subchannel(sch); | ||
811 | if (sch->schib.scsw.actl != 0) { | ||
812 | // FIXME: not-oper indication to device driver ? | ||
813 | ccw_device_call_handler(cdev); | ||
814 | } | ||
815 | if (get_device(&cdev->dev)) { | ||
816 | PREPARE_WORK(&cdev->private->kick_work, | ||
817 | ccw_device_call_sch_unregister); | ||
818 | queue_work(ccw_device_work, &cdev->private->kick_work); | ||
819 | } | ||
820 | wake_up(&cdev->private->wait_q); | ||
821 | } | 727 | } |
822 | 728 | ||
823 | /* | 729 | /* |
@@ -915,18 +821,9 @@ ccw_device_online_timeout(struct ccw_device *cdev, enum dev_event dev_event) | |||
915 | cdev->private->state = DEV_STATE_TIMEOUT_KILL; | 821 | cdev->private->state = DEV_STATE_TIMEOUT_KILL; |
916 | return; | 822 | return; |
917 | } | 823 | } |
918 | if (ret == -ENODEV) { | 824 | if (ret == -ENODEV) |
919 | struct subchannel *sch; | 825 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); |
920 | 826 | else if (cdev->handler) | |
921 | sch = to_subchannel(cdev->dev.parent); | ||
922 | if (!sch->lpm) { | ||
923 | PREPARE_WORK(&cdev->private->kick_work, | ||
924 | ccw_device_nopath_notify); | ||
925 | queue_work(ccw_device_notify_work, | ||
926 | &cdev->private->kick_work); | ||
927 | } else | ||
928 | dev_fsm_event(cdev, DEV_EVENT_NOTOPER); | ||
929 | } else if (cdev->handler) | ||
930 | cdev->handler(cdev, cdev->private->intparm, | 827 | cdev->handler(cdev, cdev->private->intparm, |
931 | ERR_PTR(-ETIMEDOUT)); | 828 | ERR_PTR(-ETIMEDOUT)); |
932 | } | 829 | } |
@@ -1233,7 +1130,7 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { | |||
1233 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1130 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1234 | }, | 1131 | }, |
1235 | [DEV_STATE_SENSE_PGID] = { | 1132 | [DEV_STATE_SENSE_PGID] = { |
1236 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1133 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1237 | [DEV_EVENT_INTERRUPT] = ccw_device_sense_pgid_irq, | 1134 | [DEV_EVENT_INTERRUPT] = ccw_device_sense_pgid_irq, |
1238 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, | 1135 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, |
1239 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1136 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
@@ -1245,50 +1142,50 @@ fsm_func_t *dev_jumptable[NR_DEV_STATES][NR_DEV_EVENTS] = { | |||
1245 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1142 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1246 | }, | 1143 | }, |
1247 | [DEV_STATE_OFFLINE] = { | 1144 | [DEV_STATE_OFFLINE] = { |
1248 | [DEV_EVENT_NOTOPER] = ccw_device_offline_notoper, | 1145 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1249 | [DEV_EVENT_INTERRUPT] = ccw_device_offline_irq, | 1146 | [DEV_EVENT_INTERRUPT] = ccw_device_offline_irq, |
1250 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, | 1147 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, |
1251 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1148 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1252 | }, | 1149 | }, |
1253 | [DEV_STATE_VERIFY] = { | 1150 | [DEV_STATE_VERIFY] = { |
1254 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1151 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1255 | [DEV_EVENT_INTERRUPT] = ccw_device_verify_irq, | 1152 | [DEV_EVENT_INTERRUPT] = ccw_device_verify_irq, |
1256 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, | 1153 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, |
1257 | [DEV_EVENT_VERIFY] = ccw_device_delay_verify, | 1154 | [DEV_EVENT_VERIFY] = ccw_device_delay_verify, |
1258 | }, | 1155 | }, |
1259 | [DEV_STATE_ONLINE] = { | 1156 | [DEV_STATE_ONLINE] = { |
1260 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1157 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1261 | [DEV_EVENT_INTERRUPT] = ccw_device_irq, | 1158 | [DEV_EVENT_INTERRUPT] = ccw_device_irq, |
1262 | [DEV_EVENT_TIMEOUT] = ccw_device_online_timeout, | 1159 | [DEV_EVENT_TIMEOUT] = ccw_device_online_timeout, |
1263 | [DEV_EVENT_VERIFY] = ccw_device_online_verify, | 1160 | [DEV_EVENT_VERIFY] = ccw_device_online_verify, |
1264 | }, | 1161 | }, |
1265 | [DEV_STATE_W4SENSE] = { | 1162 | [DEV_STATE_W4SENSE] = { |
1266 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1163 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1267 | [DEV_EVENT_INTERRUPT] = ccw_device_w4sense, | 1164 | [DEV_EVENT_INTERRUPT] = ccw_device_w4sense, |
1268 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, | 1165 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, |
1269 | [DEV_EVENT_VERIFY] = ccw_device_online_verify, | 1166 | [DEV_EVENT_VERIFY] = ccw_device_online_verify, |
1270 | }, | 1167 | }, |
1271 | [DEV_STATE_DISBAND_PGID] = { | 1168 | [DEV_STATE_DISBAND_PGID] = { |
1272 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1169 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1273 | [DEV_EVENT_INTERRUPT] = ccw_device_disband_irq, | 1170 | [DEV_EVENT_INTERRUPT] = ccw_device_disband_irq, |
1274 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, | 1171 | [DEV_EVENT_TIMEOUT] = ccw_device_onoff_timeout, |
1275 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1172 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1276 | }, | 1173 | }, |
1277 | [DEV_STATE_BOXED] = { | 1174 | [DEV_STATE_BOXED] = { |
1278 | [DEV_EVENT_NOTOPER] = ccw_device_offline_notoper, | 1175 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1279 | [DEV_EVENT_INTERRUPT] = ccw_device_stlck_done, | 1176 | [DEV_EVENT_INTERRUPT] = ccw_device_stlck_done, |
1280 | [DEV_EVENT_TIMEOUT] = ccw_device_stlck_done, | 1177 | [DEV_EVENT_TIMEOUT] = ccw_device_stlck_done, |
1281 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1178 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1282 | }, | 1179 | }, |
1283 | /* states to wait for i/o completion before doing something */ | 1180 | /* states to wait for i/o completion before doing something */ |
1284 | [DEV_STATE_CLEAR_VERIFY] = { | 1181 | [DEV_STATE_CLEAR_VERIFY] = { |
1285 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1182 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1286 | [DEV_EVENT_INTERRUPT] = ccw_device_clear_verify, | 1183 | [DEV_EVENT_INTERRUPT] = ccw_device_clear_verify, |
1287 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, | 1184 | [DEV_EVENT_TIMEOUT] = ccw_device_nop, |
1288 | [DEV_EVENT_VERIFY] = ccw_device_nop, | 1185 | [DEV_EVENT_VERIFY] = ccw_device_nop, |
1289 | }, | 1186 | }, |
1290 | [DEV_STATE_TIMEOUT_KILL] = { | 1187 | [DEV_STATE_TIMEOUT_KILL] = { |
1291 | [DEV_EVENT_NOTOPER] = ccw_device_online_notoper, | 1188 | [DEV_EVENT_NOTOPER] = ccw_device_generic_notoper, |
1292 | [DEV_EVENT_INTERRUPT] = ccw_device_killing_irq, | 1189 | [DEV_EVENT_INTERRUPT] = ccw_device_killing_irq, |
1293 | [DEV_EVENT_TIMEOUT] = ccw_device_killing_timeout, | 1190 | [DEV_EVENT_TIMEOUT] = ccw_device_killing_timeout, |
1294 | [DEV_EVENT_VERIFY] = ccw_device_nop, //FIXME | 1191 | [DEV_EVENT_VERIFY] = ccw_device_nop, //FIXME |
diff --git a/drivers/s390/cio/device_ops.c b/drivers/s390/cio/device_ops.c index 14eba854b155..7fd2dadc3297 100644 --- a/drivers/s390/cio/device_ops.c +++ b/drivers/s390/cio/device_ops.c | |||
@@ -25,6 +25,16 @@ | |||
25 | #include "device.h" | 25 | #include "device.h" |
26 | #include "chp.h" | 26 | #include "chp.h" |
27 | 27 | ||
28 | /** | ||
29 | * ccw_device_set_options_mask() - set some options and unset the rest | ||
30 | * @cdev: device for which the options are to be set | ||
31 | * @flags: options to be set | ||
32 | * | ||
33 | * All flags specified in @flags are set, all flags not specified in @flags | ||
34 | * are cleared. | ||
35 | * Returns: | ||
36 | * %0 on success, -%EINVAL on an invalid flag combination. | ||
37 | */ | ||
28 | int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) | 38 | int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) |
29 | { | 39 | { |
30 | /* | 40 | /* |
@@ -40,6 +50,15 @@ int ccw_device_set_options_mask(struct ccw_device *cdev, unsigned long flags) | |||
40 | return 0; | 50 | return 0; |
41 | } | 51 | } |
42 | 52 | ||
53 | /** | ||
54 | * ccw_device_set_options() - set some options | ||
55 | * @cdev: device for which the options are to be set | ||
56 | * @flags: options to be set | ||
57 | * | ||
58 | * All flags specified in @flags are set, the remainder is left untouched. | ||
59 | * Returns: | ||
60 | * %0 on success, -%EINVAL if an invalid flag combination would ensue. | ||
61 | */ | ||
43 | int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) | 62 | int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) |
44 | { | 63 | { |
45 | /* | 64 | /* |
@@ -59,6 +78,13 @@ int ccw_device_set_options(struct ccw_device *cdev, unsigned long flags) | |||
59 | return 0; | 78 | return 0; |
60 | } | 79 | } |
61 | 80 | ||
81 | /** | ||
82 | * ccw_device_clear_options() - clear some options | ||
83 | * @cdev: device for which the options are to be cleared | ||
84 | * @flags: options to be cleared | ||
85 | * | ||
86 | * All flags specified in @flags are cleared, the remainder is left untouched. | ||
87 | */ | ||
62 | void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) | 88 | void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) |
63 | { | 89 | { |
64 | cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0; | 90 | cdev->private->options.fast &= (flags & CCWDEV_EARLY_NOTIFICATION) == 0; |
@@ -67,8 +93,22 @@ void ccw_device_clear_options(struct ccw_device *cdev, unsigned long flags) | |||
67 | cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0; | 93 | cdev->private->options.force &= (flags & CCWDEV_ALLOW_FORCE) == 0; |
68 | } | 94 | } |
69 | 95 | ||
70 | int | 96 | /** |
71 | ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | 97 | * ccw_device_clear() - terminate I/O request processing |
98 | * @cdev: target ccw device | ||
99 | * @intparm: interruption parameter; value is only used if no I/O is | ||
100 | * outstanding, otherwise the intparm associated with the I/O request | ||
101 | * is returned | ||
102 | * | ||
103 | * ccw_device_clear() calls csch on @cdev's subchannel. | ||
104 | * Returns: | ||
105 | * %0 on success, | ||
106 | * -%ENODEV on device not operational, | ||
107 | * -%EINVAL on invalid device state. | ||
108 | * Context: | ||
109 | * Interrupts disabled, ccw device lock held | ||
110 | */ | ||
111 | int ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | ||
72 | { | 112 | { |
73 | struct subchannel *sch; | 113 | struct subchannel *sch; |
74 | int ret; | 114 | int ret; |
@@ -89,10 +129,33 @@ ccw_device_clear(struct ccw_device *cdev, unsigned long intparm) | |||
89 | return ret; | 129 | return ret; |
90 | } | 130 | } |
91 | 131 | ||
92 | int | 132 | /** |
93 | ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | 133 | * ccw_device_start_key() - start a s390 channel program with key |
94 | unsigned long intparm, __u8 lpm, __u8 key, | 134 | * @cdev: target ccw device |
95 | unsigned long flags) | 135 | * @cpa: logical start address of channel program |
136 | * @intparm: user specific interruption parameter; will be presented back to | ||
137 | * @cdev's interrupt handler. Allows a device driver to associate | ||
138 | * the interrupt with a particular I/O request. | ||
139 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
140 | * value of 0 will make cio use the opm. | ||
141 | * @key: storage key to be used for the I/O | ||
142 | * @flags: additional flags; defines the action to be performed for I/O | ||
143 | * processing. | ||
144 | * | ||
145 | * Start a S/390 channel program. When the interrupt arrives, the | ||
146 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
147 | * or sense required) or never (no IRQ handler registered). | ||
148 | * Returns: | ||
149 | * %0, if the operation was successful; | ||
150 | * -%EBUSY, if the device is busy, or status pending; | ||
151 | * -%EACCES, if no path specified in @lpm is operational; | ||
152 | * -%ENODEV, if the device is not operational. | ||
153 | * Context: | ||
154 | * Interrupts disabled, ccw device lock held | ||
155 | */ | ||
156 | int ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | ||
157 | unsigned long intparm, __u8 lpm, __u8 key, | ||
158 | unsigned long flags) | ||
96 | { | 159 | { |
97 | struct subchannel *sch; | 160 | struct subchannel *sch; |
98 | int ret; | 161 | int ret; |
@@ -135,11 +198,38 @@ ccw_device_start_key(struct ccw_device *cdev, struct ccw1 *cpa, | |||
135 | return ret; | 198 | return ret; |
136 | } | 199 | } |
137 | 200 | ||
138 | 201 | /** | |
139 | int | 202 | * ccw_device_start_timeout_key() - start a s390 channel program with timeout and key |
140 | ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, | 203 | * @cdev: target ccw device |
141 | unsigned long intparm, __u8 lpm, __u8 key, | 204 | * @cpa: logical start address of channel program |
142 | unsigned long flags, int expires) | 205 | * @intparm: user specific interruption parameter; will be presented back to |
206 | * @cdev's interrupt handler. Allows a device driver to associate | ||
207 | * the interrupt with a particular I/O request. | ||
208 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
209 | * value of 0 will make cio use the opm. | ||
210 | * @key: storage key to be used for the I/O | ||
211 | * @flags: additional flags; defines the action to be performed for I/O | ||
212 | * processing. | ||
213 | * @expires: timeout value in jiffies | ||
214 | * | ||
215 | * Start a S/390 channel program. When the interrupt arrives, the | ||
216 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
217 | * or sense required) or never (no IRQ handler registered). | ||
218 | * This function notifies the device driver if the channel program has not | ||
219 | * completed during the time specified by @expires. If a timeout occurs, the | ||
220 | * channel program is terminated via xsch, hsch or csch, and the device's | ||
221 | * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT). | ||
222 | * Returns: | ||
223 | * %0, if the operation was successful; | ||
224 | * -%EBUSY, if the device is busy, or status pending; | ||
225 | * -%EACCES, if no path specified in @lpm is operational; | ||
226 | * -%ENODEV, if the device is not operational. | ||
227 | * Context: | ||
228 | * Interrupts disabled, ccw device lock held | ||
229 | */ | ||
230 | int ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, | ||
231 | unsigned long intparm, __u8 lpm, __u8 key, | ||
232 | unsigned long flags, int expires) | ||
143 | { | 233 | { |
144 | int ret; | 234 | int ret; |
145 | 235 | ||
@@ -152,18 +242,67 @@ ccw_device_start_timeout_key(struct ccw_device *cdev, struct ccw1 *cpa, | |||
152 | return ret; | 242 | return ret; |
153 | } | 243 | } |
154 | 244 | ||
155 | int | 245 | /** |
156 | ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, | 246 | * ccw_device_start() - start a s390 channel program |
157 | unsigned long intparm, __u8 lpm, unsigned long flags) | 247 | * @cdev: target ccw device |
248 | * @cpa: logical start address of channel program | ||
249 | * @intparm: user specific interruption parameter; will be presented back to | ||
250 | * @cdev's interrupt handler. Allows a device driver to associate | ||
251 | * the interrupt with a particular I/O request. | ||
252 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
253 | * value of 0 will make cio use the opm. | ||
254 | * @flags: additional flags; defines the action to be performed for I/O | ||
255 | * processing. | ||
256 | * | ||
257 | * Start a S/390 channel program. When the interrupt arrives, the | ||
258 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
259 | * or sense required) or never (no IRQ handler registered). | ||
260 | * Returns: | ||
261 | * %0, if the operation was successful; | ||
262 | * -%EBUSY, if the device is busy, or status pending; | ||
263 | * -%EACCES, if no path specified in @lpm is operational; | ||
264 | * -%ENODEV, if the device is not operational. | ||
265 | * Context: | ||
266 | * Interrupts disabled, ccw device lock held | ||
267 | */ | ||
268 | int ccw_device_start(struct ccw_device *cdev, struct ccw1 *cpa, | ||
269 | unsigned long intparm, __u8 lpm, unsigned long flags) | ||
158 | { | 270 | { |
159 | return ccw_device_start_key(cdev, cpa, intparm, lpm, | 271 | return ccw_device_start_key(cdev, cpa, intparm, lpm, |
160 | PAGE_DEFAULT_KEY, flags); | 272 | PAGE_DEFAULT_KEY, flags); |
161 | } | 273 | } |
162 | 274 | ||
163 | int | 275 | /** |
164 | ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, | 276 | * ccw_device_start_timeout() - start a s390 channel program with timeout |
165 | unsigned long intparm, __u8 lpm, unsigned long flags, | 277 | * @cdev: target ccw device |
166 | int expires) | 278 | * @cpa: logical start address of channel program |
279 | * @intparm: user specific interruption parameter; will be presented back to | ||
280 | * @cdev's interrupt handler. Allows a device driver to associate | ||
281 | * the interrupt with a particular I/O request. | ||
282 | * @lpm: defines the channel path to be used for a specific I/O request. A | ||
283 | * value of 0 will make cio use the opm. | ||
284 | * @flags: additional flags; defines the action to be performed for I/O | ||
285 | * processing. | ||
286 | * @expires: timeout value in jiffies | ||
287 | * | ||
288 | * Start a S/390 channel program. When the interrupt arrives, the | ||
289 | * IRQ handler is called, either immediately, delayed (dev-end missing, | ||
290 | * or sense required) or never (no IRQ handler registered). | ||
291 | * This function notifies the device driver if the channel program has not | ||
292 | * completed during the time specified by @expires. If a timeout occurs, the | ||
293 | * channel program is terminated via xsch, hsch or csch, and the device's | ||
294 | * interrupt handler will be called with an irb containing ERR_PTR(-%ETIMEDOUT). | ||
295 | * Returns: | ||
296 | * %0, if the operation was successful; | ||
297 | * -%EBUSY, if the device is busy, or status pending; | ||
298 | * -%EACCES, if no path specified in @lpm is operational; | ||
299 | * -%ENODEV, if the device is not operational. | ||
300 | * Context: | ||
301 | * Interrupts disabled, ccw device lock held | ||
302 | */ | ||
303 | int ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, | ||
304 | unsigned long intparm, __u8 lpm, | ||
305 | unsigned long flags, int expires) | ||
167 | { | 306 | { |
168 | return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, | 307 | return ccw_device_start_timeout_key(cdev, cpa, intparm, lpm, |
169 | PAGE_DEFAULT_KEY, flags, | 308 | PAGE_DEFAULT_KEY, flags, |
@@ -171,8 +310,23 @@ ccw_device_start_timeout(struct ccw_device *cdev, struct ccw1 *cpa, | |||
171 | } | 310 | } |
172 | 311 | ||
173 | 312 | ||
174 | int | 313 | /** |
175 | ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | 314 | * ccw_device_halt() - halt I/O request processing |
315 | * @cdev: target ccw device | ||
316 | * @intparm: interruption parameter; value is only used if no I/O is | ||
317 | * outstanding, otherwise the intparm associated with the I/O request | ||
318 | * is returned | ||
319 | * | ||
320 | * ccw_device_halt() calls hsch on @cdev's subchannel. | ||
321 | * Returns: | ||
322 | * %0 on success, | ||
323 | * -%ENODEV on device not operational, | ||
324 | * -%EINVAL on invalid device state, | ||
325 | * -%EBUSY on device busy or interrupt pending. | ||
326 | * Context: | ||
327 | * Interrupts disabled, ccw device lock held | ||
328 | */ | ||
329 | int ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | ||
176 | { | 330 | { |
177 | struct subchannel *sch; | 331 | struct subchannel *sch; |
178 | int ret; | 332 | int ret; |
@@ -193,8 +347,20 @@ ccw_device_halt(struct ccw_device *cdev, unsigned long intparm) | |||
193 | return ret; | 347 | return ret; |
194 | } | 348 | } |
195 | 349 | ||
196 | int | 350 | /** |
197 | ccw_device_resume(struct ccw_device *cdev) | 351 | * ccw_device_resume() - resume channel program execution |
352 | * @cdev: target ccw device | ||
353 | * | ||
354 | * ccw_device_resume() calls rsch on @cdev's subchannel. | ||
355 | * Returns: | ||
356 | * %0 on success, | ||
357 | * -%ENODEV on device not operational, | ||
358 | * -%EINVAL on invalid device state, | ||
359 | * -%EBUSY on device busy or interrupt pending. | ||
360 | * Context: | ||
361 | * Interrupts disabled, ccw device lock held | ||
362 | */ | ||
363 | int ccw_device_resume(struct ccw_device *cdev) | ||
198 | { | 364 | { |
199 | struct subchannel *sch; | 365 | struct subchannel *sch; |
200 | 366 | ||
@@ -260,11 +426,21 @@ ccw_device_call_handler(struct ccw_device *cdev) | |||
260 | return 1; | 426 | return 1; |
261 | } | 427 | } |
262 | 428 | ||
263 | /* | 429 | /** |
264 | * Search for CIW command in extended sense data. | 430 | * ccw_device_get_ciw() - Search for CIW command in extended sense data. |
431 | * @cdev: ccw device to inspect | ||
432 | * @ct: command type to look for | ||
433 | * | ||
434 | * During SenseID, command information words (CIWs) describing special | ||
435 | * commands available to the device may have been stored in the extended | ||
436 | * sense data. This function searches for CIWs of a specified command | ||
437 | * type in the extended sense data. | ||
438 | * Returns: | ||
439 | * %NULL if no extended sense data has been stored or if no CIW of the | ||
440 | * specified command type could be found, | ||
441 | * else a pointer to the CIW of the specified command type. | ||
265 | */ | 442 | */ |
266 | struct ciw * | 443 | struct ciw *ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) |
267 | ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) | ||
268 | { | 444 | { |
269 | int ciw_cnt; | 445 | int ciw_cnt; |
270 | 446 | ||
@@ -276,8 +452,14 @@ ccw_device_get_ciw(struct ccw_device *cdev, __u32 ct) | |||
276 | return NULL; | 452 | return NULL; |
277 | } | 453 | } |
278 | 454 | ||
279 | __u8 | 455 | /** |
280 | ccw_device_get_path_mask(struct ccw_device *cdev) | 456 | * ccw_device_get_path_mask() - get currently available paths |
457 | * @cdev: ccw device to be queried | ||
458 | * Returns: | ||
459 | * %0 if no subchannel for the device is available, | ||
460 | * else the mask of currently available paths for the ccw device's subchannel. | ||
461 | */ | ||
462 | __u8 ccw_device_get_path_mask(struct ccw_device *cdev) | ||
281 | { | 463 | { |
282 | struct subchannel *sch; | 464 | struct subchannel *sch; |
283 | 465 | ||
@@ -357,8 +539,7 @@ out_unlock: | |||
357 | return ret; | 539 | return ret; |
358 | } | 540 | } |
359 | 541 | ||
360 | void * | 542 | void *ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) |
361 | ccw_device_get_chp_desc(struct ccw_device *cdev, int chp_no) | ||
362 | { | 543 | { |
363 | struct subchannel *sch; | 544 | struct subchannel *sch; |
364 | struct chp_id chpid; | 545 | struct chp_id chpid; |
diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index d8d479876ec7..40a3208c7cf3 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c | |||
@@ -1024,9 +1024,9 @@ __qdio_outbound_processing(struct qdio_q *q) | |||
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | static void | 1026 | static void |
1027 | qdio_outbound_processing(struct qdio_q *q) | 1027 | qdio_outbound_processing(unsigned long q) |
1028 | { | 1028 | { |
1029 | __qdio_outbound_processing(q); | 1029 | __qdio_outbound_processing((struct qdio_q *) q); |
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | /************************* INBOUND ROUTINES *******************************/ | 1032 | /************************* INBOUND ROUTINES *******************************/ |
@@ -1449,9 +1449,10 @@ out: | |||
1449 | } | 1449 | } |
1450 | 1450 | ||
1451 | static void | 1451 | static void |
1452 | tiqdio_inbound_processing(struct qdio_q *q) | 1452 | tiqdio_inbound_processing(unsigned long q) |
1453 | { | 1453 | { |
1454 | __tiqdio_inbound_processing(q, atomic_read(&spare_indicator_usecount)); | 1454 | __tiqdio_inbound_processing((struct qdio_q *) q, |
1455 | atomic_read(&spare_indicator_usecount)); | ||
1455 | } | 1456 | } |
1456 | 1457 | ||
1457 | static void | 1458 | static void |
@@ -1494,9 +1495,9 @@ again: | |||
1494 | } | 1495 | } |
1495 | 1496 | ||
1496 | static void | 1497 | static void |
1497 | qdio_inbound_processing(struct qdio_q *q) | 1498 | qdio_inbound_processing(unsigned long q) |
1498 | { | 1499 | { |
1499 | __qdio_inbound_processing(q); | 1500 | __qdio_inbound_processing((struct qdio_q *) q); |
1500 | } | 1501 | } |
1501 | 1502 | ||
1502 | /************************* MAIN ROUTINES *******************************/ | 1503 | /************************* MAIN ROUTINES *******************************/ |
@@ -1760,12 +1761,15 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, | |||
1760 | q->handler=input_handler; | 1761 | q->handler=input_handler; |
1761 | q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind; | 1762 | q->dev_st_chg_ind=irq_ptr->dev_st_chg_ind; |
1762 | 1763 | ||
1763 | q->tasklet.data=(unsigned long)q; | ||
1764 | /* q->is_thinint_q isn't valid at this time, but | 1764 | /* q->is_thinint_q isn't valid at this time, but |
1765 | * irq_ptr->is_thinint_irq is */ | 1765 | * irq_ptr->is_thinint_irq is |
1766 | q->tasklet.func=(void(*)(unsigned long)) | 1766 | */ |
1767 | ((irq_ptr->is_thinint_irq)?&tiqdio_inbound_processing: | 1767 | if (irq_ptr->is_thinint_irq) |
1768 | &qdio_inbound_processing); | 1768 | tasklet_init(&q->tasklet, tiqdio_inbound_processing, |
1769 | (unsigned long) q); | ||
1770 | else | ||
1771 | tasklet_init(&q->tasklet, qdio_inbound_processing, | ||
1772 | (unsigned long) q); | ||
1769 | 1773 | ||
1770 | /* actually this is not used for inbound queues. yet. */ | 1774 | /* actually this is not used for inbound queues. yet. */ |
1771 | atomic_set(&q->busy_siga_counter,0); | 1775 | atomic_set(&q->busy_siga_counter,0); |
@@ -1836,13 +1840,10 @@ qdio_fill_qs(struct qdio_irq *irq_ptr, struct ccw_device *cdev, | |||
1836 | q->last_move_ftc=0; | 1840 | q->last_move_ftc=0; |
1837 | q->handler=output_handler; | 1841 | q->handler=output_handler; |
1838 | 1842 | ||
1839 | q->tasklet.data=(unsigned long)q; | 1843 | tasklet_init(&q->tasklet, qdio_outbound_processing, |
1840 | q->tasklet.func=(void(*)(unsigned long)) | 1844 | (unsigned long) q); |
1841 | &qdio_outbound_processing; | 1845 | setup_timer(&q->timer, qdio_outbound_processing, |
1842 | q->timer.function=(void(*)(unsigned long)) | 1846 | (unsigned long) q); |
1843 | &qdio_outbound_processing; | ||
1844 | q->timer.data = (long)q; | ||
1845 | init_timer(&q->timer); | ||
1846 | 1847 | ||
1847 | atomic_set(&q->busy_siga_counter,0); | 1848 | atomic_set(&q->busy_siga_counter,0); |
1848 | q->timing.busy_start=0; | 1849 | q->timing.busy_start=0; |
@@ -3726,7 +3727,7 @@ qdio_performance_stats_store(struct bus_type *bus, const char *buf, size_t count | |||
3726 | #endif /* CONFIG_64BIT */ | 3727 | #endif /* CONFIG_64BIT */ |
3727 | } | 3728 | } |
3728 | } else { | 3729 | } else { |
3729 | QDIO_PRINT_WARN("QDIO performance_stats: write 0 or 1 to this file!\n"); | 3730 | QDIO_PRINT_ERR("QDIO performance_stats: write 0 or 1 to this file!\n"); |
3730 | return -EINVAL; | 3731 | return -EINVAL; |
3731 | } | 3732 | } |
3732 | return count; | 3733 | return count; |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index e99713041591..67aaff3e668d 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -1225,8 +1225,9 @@ static void ap_reset_domain(void) | |||
1225 | { | 1225 | { |
1226 | int i; | 1226 | int i; |
1227 | 1227 | ||
1228 | for (i = 0; i < AP_DEVICES; i++) | 1228 | if (ap_domain_index != -1) |
1229 | ap_reset_queue(AP_MKQID(i, ap_domain_index)); | 1229 | for (i = 0; i < AP_DEVICES; i++) |
1230 | ap_reset_queue(AP_MKQID(i, ap_domain_index)); | ||
1230 | } | 1231 | } |
1231 | 1232 | ||
1232 | static void ap_reset_all(void) | 1233 | static void ap_reset_all(void) |
diff --git a/drivers/s390/crypto/zcrypt_mono.c b/drivers/s390/crypto/zcrypt_mono.c index 2a9349ad68b7..44253fdd4136 100644 --- a/drivers/s390/crypto/zcrypt_mono.c +++ b/drivers/s390/crypto/zcrypt_mono.c | |||
@@ -45,7 +45,7 @@ | |||
45 | /** | 45 | /** |
46 | * The module initialization code. | 46 | * The module initialization code. |
47 | */ | 47 | */ |
48 | int __init zcrypt_init(void) | 48 | static int __init zcrypt_init(void) |
49 | { | 49 | { |
50 | int rc; | 50 | int rc; |
51 | 51 | ||
@@ -86,7 +86,7 @@ out: | |||
86 | /** | 86 | /** |
87 | * The module termination code. | 87 | * The module termination code. |
88 | */ | 88 | */ |
89 | void __exit zcrypt_exit(void) | 89 | static void __exit zcrypt_exit(void) |
90 | { | 90 | { |
91 | zcrypt_cex2a_exit(); | 91 | zcrypt_cex2a_exit(); |
92 | zcrypt_pcixcc_exit(); | 92 | zcrypt_pcixcc_exit(); |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.c b/drivers/s390/crypto/zcrypt_pcixcc.c index 64948788d301..70b9ddc8cf9d 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.c +++ b/drivers/s390/crypto/zcrypt_pcixcc.c | |||
@@ -277,7 +277,7 @@ static int XCRB_msg_to_type6CPRB_msgX(struct zcrypt_device *zdev, | |||
277 | }; | 277 | }; |
278 | struct { | 278 | struct { |
279 | struct type6_hdr hdr; | 279 | struct type6_hdr hdr; |
280 | struct ica_CPRBX cprbx; | 280 | struct CPRBX cprbx; |
281 | } __attribute__((packed)) *msg = ap_msg->message; | 281 | } __attribute__((packed)) *msg = ap_msg->message; |
282 | 282 | ||
283 | int rcblen = CEIL4(xcRB->request_control_blk_length); | 283 | int rcblen = CEIL4(xcRB->request_control_blk_length); |
@@ -432,14 +432,17 @@ static int convert_type86_ica(struct zcrypt_device *zdev, | |||
432 | } | 432 | } |
433 | if (service_rc == 8 && service_rs == 770) { | 433 | if (service_rc == 8 && service_rs == 770) { |
434 | PDEBUG("Invalid key length on PCIXCC/CEX2C\n"); | 434 | PDEBUG("Invalid key length on PCIXCC/CEX2C\n"); |
435 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; | 435 | return -EINVAL; |
436 | return -EAGAIN; | ||
437 | } | 436 | } |
438 | if (service_rc == 8 && service_rs == 783) { | 437 | if (service_rc == 8 && service_rs == 783) { |
439 | PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n"); | 438 | PDEBUG("Extended bitlengths not enabled on PCIXCC/CEX2C\n"); |
440 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; | 439 | zdev->min_mod_size = PCIXCC_MIN_MOD_SIZE_OLD; |
441 | return -EAGAIN; | 440 | return -EAGAIN; |
442 | } | 441 | } |
442 | if (service_rc == 12 && service_rs == 769) { | ||
443 | PDEBUG("Invalid key on PCIXCC/CEX2C\n"); | ||
444 | return -EINVAL; | ||
445 | } | ||
443 | PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n", | 446 | PRINTK("Unknown service rc/rs (PCIXCC/CEX2C): %d/%d\n", |
444 | service_rc, service_rs); | 447 | service_rc, service_rs); |
445 | zdev->online = 0; | 448 | zdev->online = 0; |
diff --git a/drivers/s390/crypto/zcrypt_pcixcc.h b/drivers/s390/crypto/zcrypt_pcixcc.h index a78ff307fd19..8cb7d7a6973b 100644 --- a/drivers/s390/crypto/zcrypt_pcixcc.h +++ b/drivers/s390/crypto/zcrypt_pcixcc.h | |||
@@ -28,51 +28,6 @@ | |||
28 | #ifndef _ZCRYPT_PCIXCC_H_ | 28 | #ifndef _ZCRYPT_PCIXCC_H_ |
29 | #define _ZCRYPT_PCIXCC_H_ | 29 | #define _ZCRYPT_PCIXCC_H_ |
30 | 30 | ||
31 | /** | ||
32 | * CPRBX | ||
33 | * Note that all shorts and ints are big-endian. | ||
34 | * All pointer fields are 16 bytes long, and mean nothing. | ||
35 | * | ||
36 | * A request CPRB is followed by a request_parameter_block. | ||
37 | * | ||
38 | * The request (or reply) parameter block is organized thus: | ||
39 | * function code | ||
40 | * VUD block | ||
41 | * key block | ||
42 | */ | ||
43 | struct CPRBX { | ||
44 | unsigned short cprb_len; /* CPRB length 220 */ | ||
45 | unsigned char cprb_ver_id; /* CPRB version id. 0x02 */ | ||
46 | unsigned char pad_000[3]; /* Alignment pad bytes */ | ||
47 | unsigned char func_id[2]; /* function id 0x5432 */ | ||
48 | unsigned char cprb_flags[4]; /* Flags */ | ||
49 | unsigned int req_parml; /* request parameter buffer len */ | ||
50 | unsigned int req_datal; /* request data buffer */ | ||
51 | unsigned int rpl_msgbl; /* reply message block length */ | ||
52 | unsigned int rpld_parml; /* replied parameter block len */ | ||
53 | unsigned int rpl_datal; /* reply data block len */ | ||
54 | unsigned int rpld_datal; /* replied data block len */ | ||
55 | unsigned int req_extbl; /* request extension block len */ | ||
56 | unsigned char pad_001[4]; /* reserved */ | ||
57 | unsigned int rpld_extbl; /* replied extension block len */ | ||
58 | unsigned char req_parmb[16]; /* request parm block 'address' */ | ||
59 | unsigned char req_datab[16]; /* request data block 'address' */ | ||
60 | unsigned char rpl_parmb[16]; /* reply parm block 'address' */ | ||
61 | unsigned char rpl_datab[16]; /* reply data block 'address' */ | ||
62 | unsigned char req_extb[16]; /* request extension block 'addr'*/ | ||
63 | unsigned char rpl_extb[16]; /* reply extension block 'addres'*/ | ||
64 | unsigned short ccp_rtcode; /* server return code */ | ||
65 | unsigned short ccp_rscode; /* server reason code */ | ||
66 | unsigned int mac_data_len; /* Mac Data Length */ | ||
67 | unsigned char logon_id[8]; /* Logon Identifier */ | ||
68 | unsigned char mac_value[8]; /* Mac Value */ | ||
69 | unsigned char mac_content_flgs;/* Mac content flag byte */ | ||
70 | unsigned char pad_002; /* Alignment */ | ||
71 | unsigned short domain; /* Domain */ | ||
72 | unsigned char pad_003[12]; /* Domain masks */ | ||
73 | unsigned char pad_004[36]; /* reserved */ | ||
74 | } __attribute__((packed)); | ||
75 | |||
76 | int zcrypt_pcixcc_init(void); | 31 | int zcrypt_pcixcc_init(void); |
77 | void zcrypt_pcixcc_exit(void); | 32 | void zcrypt_pcixcc_exit(void); |
78 | 33 | ||
diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index 1c8f71a59855..c0d1c0eb3209 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c | |||
@@ -28,7 +28,7 @@ static void zfcp_ccw_remove(struct ccw_device *); | |||
28 | static int zfcp_ccw_set_online(struct ccw_device *); | 28 | static int zfcp_ccw_set_online(struct ccw_device *); |
29 | static int zfcp_ccw_set_offline(struct ccw_device *); | 29 | static int zfcp_ccw_set_offline(struct ccw_device *); |
30 | static int zfcp_ccw_notify(struct ccw_device *, int); | 30 | static int zfcp_ccw_notify(struct ccw_device *, int); |
31 | static void zfcp_ccw_shutdown(struct device *); | 31 | static void zfcp_ccw_shutdown(struct ccw_device *); |
32 | 32 | ||
33 | static struct ccw_device_id zfcp_ccw_device_id[] = { | 33 | static struct ccw_device_id zfcp_ccw_device_id[] = { |
34 | {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE, | 34 | {CCW_DEVICE_DEVTYPE(ZFCP_CONTROL_UNIT_TYPE, |
@@ -51,9 +51,7 @@ static struct ccw_driver zfcp_ccw_driver = { | |||
51 | .set_online = zfcp_ccw_set_online, | 51 | .set_online = zfcp_ccw_set_online, |
52 | .set_offline = zfcp_ccw_set_offline, | 52 | .set_offline = zfcp_ccw_set_offline, |
53 | .notify = zfcp_ccw_notify, | 53 | .notify = zfcp_ccw_notify, |
54 | .driver = { | 54 | .shutdown = zfcp_ccw_shutdown, |
55 | .shutdown = zfcp_ccw_shutdown, | ||
56 | }, | ||
57 | }; | 55 | }; |
58 | 56 | ||
59 | MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id); | 57 | MODULE_DEVICE_TABLE(ccw, zfcp_ccw_device_id); |
@@ -277,12 +275,12 @@ zfcp_ccw_register(void) | |||
277 | * Makes sure that QDIO queues are down when the system gets stopped. | 275 | * Makes sure that QDIO queues are down when the system gets stopped. |
278 | */ | 276 | */ |
279 | static void | 277 | static void |
280 | zfcp_ccw_shutdown(struct device *dev) | 278 | zfcp_ccw_shutdown(struct ccw_device *cdev) |
281 | { | 279 | { |
282 | struct zfcp_adapter *adapter; | 280 | struct zfcp_adapter *adapter; |
283 | 281 | ||
284 | down(&zfcp_data.config_sema); | 282 | down(&zfcp_data.config_sema); |
285 | adapter = dev_get_drvdata(dev); | 283 | adapter = dev_get_drvdata(&cdev->dev); |
286 | zfcp_erp_adapter_shutdown(adapter, 0); | 284 | zfcp_erp_adapter_shutdown(adapter, 0); |
287 | zfcp_erp_wait(adapter); | 285 | zfcp_erp_wait(adapter); |
288 | up(&zfcp_data.config_sema); | 286 | up(&zfcp_data.config_sema); |
diff --git a/drivers/s390/scsi/zfcp_dbf.c b/drivers/s390/scsi/zfcp_dbf.c index 5f3212440f68..ffa3bf756943 100644 --- a/drivers/s390/scsi/zfcp_dbf.c +++ b/drivers/s390/scsi/zfcp_dbf.c | |||
@@ -19,8 +19,8 @@ | |||
19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 | */ | 20 | */ |
21 | 21 | ||
22 | #include <asm/debug.h> | ||
23 | #include <linux/ctype.h> | 22 | #include <linux/ctype.h> |
23 | #include <asm/debug.h> | ||
24 | #include "zfcp_ext.h" | 24 | #include "zfcp_ext.h" |
25 | 25 | ||
26 | static u32 dbfsize = 4; | 26 | static u32 dbfsize = 4; |
@@ -35,17 +35,17 @@ static int | |||
35 | zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) | 35 | zfcp_dbf_stck(char *out_buf, const char *label, unsigned long long stck) |
36 | { | 36 | { |
37 | unsigned long long sec; | 37 | unsigned long long sec; |
38 | struct timespec xtime; | 38 | struct timespec dbftime; |
39 | int len = 0; | 39 | int len = 0; |
40 | 40 | ||
41 | stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); | 41 | stck -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); |
42 | sec = stck >> 12; | 42 | sec = stck >> 12; |
43 | do_div(sec, 1000000); | 43 | do_div(sec, 1000000); |
44 | xtime.tv_sec = sec; | 44 | dbftime.tv_sec = sec; |
45 | stck -= (sec * 1000000) << 12; | 45 | stck -= (sec * 1000000) << 12; |
46 | xtime.tv_nsec = ((stck * 1000) >> 12); | 46 | dbftime.tv_nsec = ((stck * 1000) >> 12); |
47 | len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n", | 47 | len += sprintf(out_buf + len, "%-24s%011lu:%06lu\n", |
48 | label, xtime.tv_sec, xtime.tv_nsec); | 48 | label, dbftime.tv_sec, dbftime.tv_nsec); |
49 | 49 | ||
50 | return len; | 50 | return len; |
51 | } | 51 | } |
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index d8cd75ce2d9a..16b4418ab257 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c | |||
@@ -54,7 +54,7 @@ static int zfcp_erp_strategy_check_adapter(struct zfcp_adapter *, int); | |||
54 | static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *, | 54 | static int zfcp_erp_strategy_statechange(int, u32, struct zfcp_adapter *, |
55 | struct zfcp_port *, | 55 | struct zfcp_port *, |
56 | struct zfcp_unit *, int); | 56 | struct zfcp_unit *, int); |
57 | static inline int zfcp_erp_strategy_statechange_detected(atomic_t *, u32); | 57 | static int zfcp_erp_strategy_statechange_detected(atomic_t *, u32); |
58 | static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *, | 58 | static int zfcp_erp_strategy_followup_actions(int, struct zfcp_adapter *, |
59 | struct zfcp_port *, | 59 | struct zfcp_port *, |
60 | struct zfcp_unit *, int); | 60 | struct zfcp_unit *, int); |
@@ -106,8 +106,8 @@ static void zfcp_erp_action_cleanup(int, struct zfcp_adapter *, | |||
106 | static void zfcp_erp_action_ready(struct zfcp_erp_action *); | 106 | static void zfcp_erp_action_ready(struct zfcp_erp_action *); |
107 | static int zfcp_erp_action_exists(struct zfcp_erp_action *); | 107 | static int zfcp_erp_action_exists(struct zfcp_erp_action *); |
108 | 108 | ||
109 | static inline void zfcp_erp_action_to_ready(struct zfcp_erp_action *); | 109 | static void zfcp_erp_action_to_ready(struct zfcp_erp_action *); |
110 | static inline void zfcp_erp_action_to_running(struct zfcp_erp_action *); | 110 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *); |
111 | 111 | ||
112 | static void zfcp_erp_memwait_handler(unsigned long); | 112 | static void zfcp_erp_memwait_handler(unsigned long); |
113 | 113 | ||
@@ -952,7 +952,7 @@ zfcp_erp_memwait_handler(unsigned long data) | |||
952 | * action gets an appropriate flag and will be processed | 952 | * action gets an appropriate flag and will be processed |
953 | * accordingly | 953 | * accordingly |
954 | */ | 954 | */ |
955 | void zfcp_erp_timeout_handler(unsigned long data) | 955 | static void zfcp_erp_timeout_handler(unsigned long data) |
956 | { | 956 | { |
957 | struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; | 957 | struct zfcp_erp_action *erp_action = (struct zfcp_erp_action *) data; |
958 | struct zfcp_adapter *adapter = erp_action->adapter; | 958 | struct zfcp_adapter *adapter = erp_action->adapter; |
@@ -1491,7 +1491,7 @@ zfcp_erp_strategy_statechange(int action, | |||
1491 | return retval; | 1491 | return retval; |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | static inline int | 1494 | static int |
1495 | zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) | 1495 | zfcp_erp_strategy_statechange_detected(atomic_t * target_status, u32 erp_status) |
1496 | { | 1496 | { |
1497 | return | 1497 | return |
@@ -2001,7 +2001,7 @@ zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close) | |||
2001 | * returns: 0 - successful setup | 2001 | * returns: 0 - successful setup |
2002 | * !0 - failed setup | 2002 | * !0 - failed setup |
2003 | */ | 2003 | */ |
2004 | int | 2004 | static int |
2005 | zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) | 2005 | zfcp_erp_adapter_strategy_open_qdio(struct zfcp_erp_action *erp_action) |
2006 | { | 2006 | { |
2007 | int retval; | 2007 | int retval; |
@@ -3248,8 +3248,7 @@ static void zfcp_erp_action_dismiss_unit(struct zfcp_unit *unit) | |||
3248 | zfcp_erp_action_dismiss(&unit->erp_action); | 3248 | zfcp_erp_action_dismiss(&unit->erp_action); |
3249 | } | 3249 | } |
3250 | 3250 | ||
3251 | static inline void | 3251 | static void zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) |
3252 | zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | ||
3253 | { | 3252 | { |
3254 | struct zfcp_adapter *adapter = erp_action->adapter; | 3253 | struct zfcp_adapter *adapter = erp_action->adapter; |
3255 | 3254 | ||
@@ -3258,8 +3257,7 @@ zfcp_erp_action_to_running(struct zfcp_erp_action *erp_action) | |||
3258 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); | 3257 | list_move(&erp_action->list, &erp_action->adapter->erp_running_head); |
3259 | } | 3258 | } |
3260 | 3259 | ||
3261 | static inline void | 3260 | static void zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) |
3262 | zfcp_erp_action_to_ready(struct zfcp_erp_action *erp_action) | ||
3263 | { | 3261 | { |
3264 | struct zfcp_adapter *adapter = erp_action->adapter; | 3262 | struct zfcp_adapter *adapter = erp_action->adapter; |
3265 | 3263 | ||