diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-01-10 22:45:50 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-01-10 22:45:50 -0500 |
commit | e8b722f487589a1f60ca27adc695494f188d404e (patch) | |
tree | be3897dceb9b7c0949a8917ab11eea2752375e3b /drivers/char | |
parent | 01d07820a0df6b6134c1bb75b1e84c9d0cdab3be (diff) | |
parent | c59765042f53a79a7a65585042ff463b69cb248c (diff) |
Merge commit 'v2.6.29-rc1' into irq/urgent
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/Kconfig | 1 | ||||
-rw-r--r-- | drivers/char/epca.c | 2 | ||||
-rw-r--r-- | drivers/char/hvc_beat.c | 4 | ||||
-rw-r--r-- | drivers/char/hvc_iucv.c | 420 | ||||
-rw-r--r-- | drivers/char/hw_random/n2-drv.c | 2 | ||||
-rw-r--r-- | drivers/char/pty.c | 2 | ||||
-rw-r--r-- | drivers/char/rtc.c | 17 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_bios.c | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_nsc.c | 35 | ||||
-rw-r--r-- | drivers/char/vt.c | 3 |
10 files changed, 303 insertions, 185 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 35914b6e1d2a..f5be8081cd81 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -616,6 +616,7 @@ config HVC_ISERIES | |||
616 | default y | 616 | default y |
617 | select HVC_DRIVER | 617 | select HVC_DRIVER |
618 | select HVC_IRQ | 618 | select HVC_IRQ |
619 | select VIOPATH | ||
619 | help | 620 | help |
620 | iSeries machines support a hypervisor virtual console. | 621 | iSeries machines support a hypervisor virtual console. |
621 | 622 | ||
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 39ad820b2350..af7c13ca9493 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
@@ -769,7 +769,7 @@ static int pc_open(struct tty_struct *tty, struct file *filp) | |||
769 | /* Check status of board configured in system. */ | 769 | /* Check status of board configured in system. */ |
770 | 770 | ||
771 | /* | 771 | /* |
772 | * I check to see if the epca_setup routine detected an user error. It | 772 | * I check to see if the epca_setup routine detected a user error. It |
773 | * might be better to put this in pc_init, but for the moment it goes | 773 | * might be better to put this in pc_init, but for the moment it goes |
774 | * here. | 774 | * here. |
775 | */ | 775 | */ |
diff --git a/drivers/char/hvc_beat.c b/drivers/char/hvc_beat.c index 91cdb35a9204..0afc8b82212e 100644 --- a/drivers/char/hvc_beat.c +++ b/drivers/char/hvc_beat.c | |||
@@ -44,7 +44,7 @@ static int hvc_beat_get_chars(uint32_t vtermno, char *buf, int cnt) | |||
44 | static unsigned char q[sizeof(unsigned long) * 2] | 44 | static unsigned char q[sizeof(unsigned long) * 2] |
45 | __attribute__((aligned(sizeof(unsigned long)))); | 45 | __attribute__((aligned(sizeof(unsigned long)))); |
46 | static int qlen = 0; | 46 | static int qlen = 0; |
47 | unsigned long got; | 47 | u64 got; |
48 | 48 | ||
49 | again: | 49 | again: |
50 | if (qlen) { | 50 | if (qlen) { |
@@ -63,7 +63,7 @@ again: | |||
63 | } | 63 | } |
64 | } | 64 | } |
65 | if (beat_get_term_char(vtermno, &got, | 65 | if (beat_get_term_char(vtermno, &got, |
66 | ((unsigned long *)q), ((unsigned long *)q) + 1) == 0) { | 66 | ((u64 *)q), ((u64 *)q) + 1) == 0) { |
67 | qlen = got; | 67 | qlen = got; |
68 | goto again; | 68 | goto again; |
69 | } | 69 | } |
diff --git a/drivers/char/hvc_iucv.c b/drivers/char/hvc_iucv.c index 5ea7d7713fca..a53496828b76 100644 --- a/drivers/char/hvc_iucv.c +++ b/drivers/char/hvc_iucv.c | |||
@@ -1,26 +1,30 @@ | |||
1 | /* | 1 | /* |
2 | * hvc_iucv.c - z/VM IUCV back-end for the Hypervisor Console (HVC) | 2 | * hvc_iucv.c - z/VM IUCV hypervisor console (HVC) device driver |
3 | * | 3 | * |
4 | * This back-end for HVC provides terminal access via | 4 | * This HVC device driver provides terminal access using |
5 | * z/VM IUCV communication paths. | 5 | * z/VM IUCV communication paths. |
6 | * | 6 | * |
7 | * Copyright IBM Corp. 2008. | 7 | * Copyright IBM Corp. 2008 |
8 | * | 8 | * |
9 | * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> | 9 | * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com> |
10 | */ | 10 | */ |
11 | #define KMSG_COMPONENT "hvc_iucv" | 11 | #define KMSG_COMPONENT "hvc_iucv" |
12 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
12 | 13 | ||
13 | #include <linux/types.h> | 14 | #include <linux/types.h> |
14 | #include <asm/ebcdic.h> | 15 | #include <asm/ebcdic.h> |
16 | #include <linux/delay.h> | ||
17 | #include <linux/init.h> | ||
15 | #include <linux/mempool.h> | 18 | #include <linux/mempool.h> |
16 | #include <linux/module.h> | 19 | #include <linux/module.h> |
17 | #include <linux/tty.h> | 20 | #include <linux/tty.h> |
21 | #include <linux/wait.h> | ||
18 | #include <net/iucv/iucv.h> | 22 | #include <net/iucv/iucv.h> |
19 | 23 | ||
20 | #include "hvc_console.h" | 24 | #include "hvc_console.h" |
21 | 25 | ||
22 | 26 | ||
23 | /* HVC backend for z/VM IUCV */ | 27 | /* General device driver settings */ |
24 | #define HVC_IUCV_MAGIC 0xc9e4c3e5 | 28 | #define HVC_IUCV_MAGIC 0xc9e4c3e5 |
25 | #define MAX_HVC_IUCV_LINES HVC_ALLOC_TTY_ADAPTERS | 29 | #define MAX_HVC_IUCV_LINES HVC_ALLOC_TTY_ADAPTERS |
26 | #define MEMPOOL_MIN_NR (PAGE_SIZE / sizeof(struct iucv_tty_buffer)/4) | 30 | #define MEMPOOL_MIN_NR (PAGE_SIZE / sizeof(struct iucv_tty_buffer)/4) |
@@ -33,14 +37,14 @@ | |||
33 | #define MSG_TYPE_WINSIZE 0x08 /* Terminal window size update */ | 37 | #define MSG_TYPE_WINSIZE 0x08 /* Terminal window size update */ |
34 | #define MSG_TYPE_DATA 0x10 /* Terminal data */ | 38 | #define MSG_TYPE_DATA 0x10 /* Terminal data */ |
35 | 39 | ||
36 | #define MSG_SIZE(s) ((s) + offsetof(struct iucv_tty_msg, data)) | ||
37 | struct iucv_tty_msg { | 40 | struct iucv_tty_msg { |
38 | u8 version; /* Message version */ | 41 | u8 version; /* Message version */ |
39 | u8 type; /* Message type */ | 42 | u8 type; /* Message type */ |
40 | #define MSG_MAX_DATALEN (~(u16)0) | 43 | #define MSG_MAX_DATALEN ((u16)(~0)) |
41 | u16 datalen; /* Payload length */ | 44 | u16 datalen; /* Payload length */ |
42 | u8 data[]; /* Payload buffer */ | 45 | u8 data[]; /* Payload buffer */ |
43 | } __attribute__((packed)); | 46 | } __attribute__((packed)); |
47 | #define MSG_SIZE(s) ((s) + offsetof(struct iucv_tty_msg, data)) | ||
44 | 48 | ||
45 | enum iucv_state_t { | 49 | enum iucv_state_t { |
46 | IUCV_DISCONN = 0, | 50 | IUCV_DISCONN = 0, |
@@ -54,19 +58,26 @@ enum tty_state_t { | |||
54 | }; | 58 | }; |
55 | 59 | ||
56 | struct hvc_iucv_private { | 60 | struct hvc_iucv_private { |
57 | struct hvc_struct *hvc; /* HVC console struct reference */ | 61 | struct hvc_struct *hvc; /* HVC struct reference */ |
58 | u8 srv_name[8]; /* IUCV service name (ebcdic) */ | 62 | u8 srv_name[8]; /* IUCV service name (ebcdic) */ |
63 | unsigned char is_console; /* Linux console usage flag */ | ||
59 | enum iucv_state_t iucv_state; /* IUCV connection status */ | 64 | enum iucv_state_t iucv_state; /* IUCV connection status */ |
60 | enum tty_state_t tty_state; /* TTY status */ | 65 | enum tty_state_t tty_state; /* TTY status */ |
61 | struct iucv_path *path; /* IUCV path pointer */ | 66 | struct iucv_path *path; /* IUCV path pointer */ |
62 | spinlock_t lock; /* hvc_iucv_private lock */ | 67 | spinlock_t lock; /* hvc_iucv_private lock */ |
68 | #define SNDBUF_SIZE (PAGE_SIZE) /* must be < MSG_MAX_DATALEN */ | ||
69 | void *sndbuf; /* send buffer */ | ||
70 | size_t sndbuf_len; /* length of send buffer */ | ||
71 | #define QUEUE_SNDBUF_DELAY (HZ / 25) | ||
72 | struct delayed_work sndbuf_work; /* work: send iucv msg(s) */ | ||
73 | wait_queue_head_t sndbuf_waitq; /* wait for send completion */ | ||
63 | struct list_head tty_outqueue; /* outgoing IUCV messages */ | 74 | struct list_head tty_outqueue; /* outgoing IUCV messages */ |
64 | struct list_head tty_inqueue; /* incoming IUCV messages */ | 75 | struct list_head tty_inqueue; /* incoming IUCV messages */ |
65 | }; | 76 | }; |
66 | 77 | ||
67 | struct iucv_tty_buffer { | 78 | struct iucv_tty_buffer { |
68 | struct list_head list; /* list pointer */ | 79 | struct list_head list; /* list pointer */ |
69 | struct iucv_message msg; /* store an incoming IUCV message */ | 80 | struct iucv_message msg; /* store an IUCV message */ |
70 | size_t offset; /* data buffer offset */ | 81 | size_t offset; /* data buffer offset */ |
71 | struct iucv_tty_msg *mbuf; /* buffer to store input/output data */ | 82 | struct iucv_tty_msg *mbuf; /* buffer to store input/output data */ |
72 | }; | 83 | }; |
@@ -78,11 +89,12 @@ static void hvc_iucv_msg_pending(struct iucv_path *, struct iucv_message *); | |||
78 | static void hvc_iucv_msg_complete(struct iucv_path *, struct iucv_message *); | 89 | static void hvc_iucv_msg_complete(struct iucv_path *, struct iucv_message *); |
79 | 90 | ||
80 | 91 | ||
81 | /* Kernel module parameters */ | 92 | /* Kernel module parameter: use one terminal device as default */ |
82 | static unsigned long hvc_iucv_devices; | 93 | static unsigned long hvc_iucv_devices = 1; |
83 | 94 | ||
84 | /* Array of allocated hvc iucv tty lines... */ | 95 | /* Array of allocated hvc iucv tty lines... */ |
85 | static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; | 96 | static struct hvc_iucv_private *hvc_iucv_table[MAX_HVC_IUCV_LINES]; |
97 | #define IUCV_HVC_CON_IDX (0) | ||
86 | 98 | ||
87 | /* Kmem cache and mempool for iucv_tty_buffer elements */ | 99 | /* Kmem cache and mempool for iucv_tty_buffer elements */ |
88 | static struct kmem_cache *hvc_iucv_buffer_cache; | 100 | static struct kmem_cache *hvc_iucv_buffer_cache; |
@@ -112,7 +124,7 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) | |||
112 | } | 124 | } |
113 | 125 | ||
114 | /** | 126 | /** |
115 | * alloc_tty_buffer() - Returns a new struct iucv_tty_buffer element. | 127 | * alloc_tty_buffer() - Return a new struct iucv_tty_buffer element. |
116 | * @size: Size of the internal buffer used to store data. | 128 | * @size: Size of the internal buffer used to store data. |
117 | * @flags: Memory allocation flags passed to mempool. | 129 | * @flags: Memory allocation flags passed to mempool. |
118 | * | 130 | * |
@@ -120,7 +132,6 @@ struct hvc_iucv_private *hvc_iucv_get_private(uint32_t num) | |||
120 | * allocates an internal data buffer with the specified size @size. | 132 | * allocates an internal data buffer with the specified size @size. |
121 | * Note: The total message size arises from the internal buffer size and the | 133 | * Note: The total message size arises from the internal buffer size and the |
122 | * members of the iucv_tty_msg structure. | 134 | * members of the iucv_tty_msg structure. |
123 | * | ||
124 | * The function returns NULL if memory allocation has failed. | 135 | * The function returns NULL if memory allocation has failed. |
125 | */ | 136 | */ |
126 | static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) | 137 | static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) |
@@ -130,7 +141,7 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) | |||
130 | bufp = mempool_alloc(hvc_iucv_mempool, flags); | 141 | bufp = mempool_alloc(hvc_iucv_mempool, flags); |
131 | if (!bufp) | 142 | if (!bufp) |
132 | return NULL; | 143 | return NULL; |
133 | memset(bufp, 0, sizeof(struct iucv_tty_buffer)); | 144 | memset(bufp, 0, sizeof(*bufp)); |
134 | 145 | ||
135 | if (size > 0) { | 146 | if (size > 0) { |
136 | bufp->msg.length = MSG_SIZE(size); | 147 | bufp->msg.length = MSG_SIZE(size); |
@@ -149,9 +160,6 @@ static struct iucv_tty_buffer *alloc_tty_buffer(size_t size, gfp_t flags) | |||
149 | /** | 160 | /** |
150 | * destroy_tty_buffer() - destroy struct iucv_tty_buffer element. | 161 | * destroy_tty_buffer() - destroy struct iucv_tty_buffer element. |
151 | * @bufp: Pointer to a struct iucv_tty_buffer element, SHALL NOT be NULL. | 162 | * @bufp: Pointer to a struct iucv_tty_buffer element, SHALL NOT be NULL. |
152 | * | ||
153 | * The destroy_tty_buffer() function frees the internal data buffer and returns | ||
154 | * the struct iucv_tty_buffer element back to the mempool for freeing. | ||
155 | */ | 163 | */ |
156 | static void destroy_tty_buffer(struct iucv_tty_buffer *bufp) | 164 | static void destroy_tty_buffer(struct iucv_tty_buffer *bufp) |
157 | { | 165 | { |
@@ -161,11 +169,7 @@ static void destroy_tty_buffer(struct iucv_tty_buffer *bufp) | |||
161 | 169 | ||
162 | /** | 170 | /** |
163 | * destroy_tty_buffer_list() - call destroy_tty_buffer() for each list element. | 171 | * destroy_tty_buffer_list() - call destroy_tty_buffer() for each list element. |
164 | * @list: List head pointer to a list containing struct iucv_tty_buffer | 172 | * @list: List containing struct iucv_tty_buffer elements. |
165 | * elements. | ||
166 | * | ||
167 | * Calls destroy_tty_buffer() for each struct iucv_tty_buffer element in the | ||
168 | * list @list. | ||
169 | */ | 173 | */ |
170 | static void destroy_tty_buffer_list(struct list_head *list) | 174 | static void destroy_tty_buffer_list(struct list_head *list) |
171 | { | 175 | { |
@@ -178,24 +182,24 @@ static void destroy_tty_buffer_list(struct list_head *list) | |||
178 | } | 182 | } |
179 | 183 | ||
180 | /** | 184 | /** |
181 | * hvc_iucv_write() - Receive IUCV message write data to HVC console buffer. | 185 | * hvc_iucv_write() - Receive IUCV message & write data to HVC buffer. |
182 | * @priv: Pointer to hvc_iucv_private structure. | 186 | * @priv: Pointer to struct hvc_iucv_private |
183 | * @buf: HVC console buffer for writing received terminal data. | 187 | * @buf: HVC buffer for writing received terminal data. |
184 | * @count: HVC console buffer size. | 188 | * @count: HVC buffer size. |
185 | * @has_more_data: Pointer to an int variable. | 189 | * @has_more_data: Pointer to an int variable. |
186 | * | 190 | * |
187 | * The function picks up pending messages from the input queue and receives | 191 | * The function picks up pending messages from the input queue and receives |
188 | * the message data that is then written to the specified buffer @buf. | 192 | * the message data that is then written to the specified buffer @buf. |
189 | * If the buffer size @count is less than the data message size, then the | 193 | * If the buffer size @count is less than the data message size, the |
190 | * message is kept on the input queue and @has_more_data is set to 1. | 194 | * message is kept on the input queue and @has_more_data is set to 1. |
191 | * If the message data has been entirely written, the message is removed from | 195 | * If all message data has been written, the message is removed from |
192 | * the input queue. | 196 | * the input queue. |
193 | * | 197 | * |
194 | * The function returns the number of bytes written to the terminal, zero if | 198 | * The function returns the number of bytes written to the terminal, zero if |
195 | * there are no pending data messages available or if there is no established | 199 | * there are no pending data messages available or if there is no established |
196 | * IUCV path. | 200 | * IUCV path. |
197 | * If the IUCV path has been severed, then -EPIPE is returned to cause a | 201 | * If the IUCV path has been severed, then -EPIPE is returned to cause a |
198 | * hang up (that is issued by the HVC console layer). | 202 | * hang up (that is issued by the HVC layer). |
199 | */ | 203 | */ |
200 | static int hvc_iucv_write(struct hvc_iucv_private *priv, | 204 | static int hvc_iucv_write(struct hvc_iucv_private *priv, |
201 | char *buf, int count, int *has_more_data) | 205 | char *buf, int count, int *has_more_data) |
@@ -204,12 +208,12 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, | |||
204 | int written; | 208 | int written; |
205 | int rc; | 209 | int rc; |
206 | 210 | ||
207 | /* Immediately return if there is no IUCV connection */ | 211 | /* immediately return if there is no IUCV connection */ |
208 | if (priv->iucv_state == IUCV_DISCONN) | 212 | if (priv->iucv_state == IUCV_DISCONN) |
209 | return 0; | 213 | return 0; |
210 | 214 | ||
211 | /* If the IUCV path has been severed, return -EPIPE to inform the | 215 | /* if the IUCV path has been severed, return -EPIPE to inform the |
212 | * hvc console layer to hang up the tty device. */ | 216 | * HVC layer to hang up the tty device. */ |
213 | if (priv->iucv_state == IUCV_SEVERED) | 217 | if (priv->iucv_state == IUCV_SEVERED) |
214 | return -EPIPE; | 218 | return -EPIPE; |
215 | 219 | ||
@@ -217,7 +221,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, | |||
217 | if (list_empty(&priv->tty_inqueue)) | 221 | if (list_empty(&priv->tty_inqueue)) |
218 | return 0; | 222 | return 0; |
219 | 223 | ||
220 | /* receive a iucv message and flip data to the tty (ldisc) */ | 224 | /* receive an iucv message and flip data to the tty (ldisc) */ |
221 | rb = list_first_entry(&priv->tty_inqueue, struct iucv_tty_buffer, list); | 225 | rb = list_first_entry(&priv->tty_inqueue, struct iucv_tty_buffer, list); |
222 | 226 | ||
223 | written = 0; | 227 | written = 0; |
@@ -260,7 +264,7 @@ static int hvc_iucv_write(struct hvc_iucv_private *priv, | |||
260 | case MSG_TYPE_WINSIZE: | 264 | case MSG_TYPE_WINSIZE: |
261 | if (rb->mbuf->datalen != sizeof(struct winsize)) | 265 | if (rb->mbuf->datalen != sizeof(struct winsize)) |
262 | break; | 266 | break; |
263 | hvc_resize(priv->hvc, *((struct winsize *)rb->mbuf->data)); | 267 | hvc_resize(priv->hvc, *((struct winsize *) rb->mbuf->data)); |
264 | break; | 268 | break; |
265 | 269 | ||
266 | case MSG_TYPE_ERROR: /* ignored ... */ | 270 | case MSG_TYPE_ERROR: /* ignored ... */ |
@@ -284,10 +288,9 @@ out_written: | |||
284 | * @buf: Pointer to a buffer to store data | 288 | * @buf: Pointer to a buffer to store data |
285 | * @count: Size of buffer available for writing | 289 | * @count: Size of buffer available for writing |
286 | * | 290 | * |
287 | * The hvc_console thread calls this method to read characters from | 291 | * The HVC thread calls this method to read characters from the back-end. |
288 | * the terminal backend. If an IUCV communication path has been established, | 292 | * If an IUCV communication path has been established, pending IUCV messages |
289 | * pending IUCV messages are received and data is copied into buffer @buf | 293 | * are received and data is copied into buffer @buf up to @count bytes. |
290 | * up to @count bytes. | ||
291 | * | 294 | * |
292 | * Locking: The routine gets called under an irqsave() spinlock; and | 295 | * Locking: The routine gets called under an irqsave() spinlock; and |
293 | * the routine locks the struct hvc_iucv_private->lock to call | 296 | * the routine locks the struct hvc_iucv_private->lock to call |
@@ -318,66 +321,122 @@ static int hvc_iucv_get_chars(uint32_t vtermno, char *buf, int count) | |||
318 | } | 321 | } |
319 | 322 | ||
320 | /** | 323 | /** |
321 | * hvc_iucv_send() - Send an IUCV message containing terminal data. | 324 | * hvc_iucv_queue() - Buffer terminal data for sending. |
322 | * @priv: Pointer to struct hvc_iucv_private instance. | 325 | * @priv: Pointer to struct hvc_iucv_private instance. |
323 | * @buf: Buffer containing data to send. | 326 | * @buf: Buffer containing data to send. |
324 | * @size: Size of buffer and amount of data to send. | 327 | * @count: Size of buffer and amount of data to send. |
328 | * | ||
329 | * The function queues data for sending. To actually send the buffered data, | ||
330 | * a work queue function is scheduled (with QUEUE_SNDBUF_DELAY). | ||
331 | * The function returns the number of data bytes that has been buffered. | ||
325 | * | 332 | * |
326 | * If an IUCV communication path is established, the function copies the buffer | 333 | * If the device is not connected, data is ignored and the function returns |
327 | * data to a newly allocated struct iucv_tty_buffer element, sends the data and | 334 | * @count. |
328 | * puts the element to the outqueue. | 335 | * If the buffer is full, the function returns 0. |
336 | * If an existing IUCV communicaton path has been severed, -EPIPE is returned | ||
337 | * (that can be passed to HVC layer to cause a tty hangup). | ||
338 | */ | ||
339 | static int hvc_iucv_queue(struct hvc_iucv_private *priv, const char *buf, | ||
340 | int count) | ||
341 | { | ||
342 | size_t len; | ||
343 | |||
344 | if (priv->iucv_state == IUCV_DISCONN) | ||
345 | return count; /* ignore data */ | ||
346 | |||
347 | if (priv->iucv_state == IUCV_SEVERED) | ||
348 | return -EPIPE; | ||
349 | |||
350 | len = min_t(size_t, count, SNDBUF_SIZE - priv->sndbuf_len); | ||
351 | if (!len) | ||
352 | return 0; | ||
353 | |||
354 | memcpy(priv->sndbuf + priv->sndbuf_len, buf, len); | ||
355 | priv->sndbuf_len += len; | ||
356 | |||
357 | if (priv->iucv_state == IUCV_CONNECTED) | ||
358 | schedule_delayed_work(&priv->sndbuf_work, QUEUE_SNDBUF_DELAY); | ||
359 | |||
360 | return len; | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * hvc_iucv_send() - Send an IUCV message containing terminal data. | ||
365 | * @priv: Pointer to struct hvc_iucv_private instance. | ||
329 | * | 366 | * |
330 | * If there is no IUCV communication path established, the function returns 0. | 367 | * If an IUCV communication path has been established, the buffered output data |
331 | * If an existing IUCV communicaton path has been severed, the function returns | 368 | * is sent via an IUCV message and the number of bytes sent is returned. |
332 | * -EPIPE (can be passed to HVC layer to cause a tty hangup). | 369 | * Returns 0 if there is no established IUCV communication path or |
370 | * -EPIPE if an existing IUCV communicaton path has been severed. | ||
333 | */ | 371 | */ |
334 | static int hvc_iucv_send(struct hvc_iucv_private *priv, const char *buf, | 372 | static int hvc_iucv_send(struct hvc_iucv_private *priv) |
335 | int count) | ||
336 | { | 373 | { |
337 | struct iucv_tty_buffer *sb; | 374 | struct iucv_tty_buffer *sb; |
338 | int rc; | 375 | int rc, len; |
339 | u16 len; | ||
340 | 376 | ||
341 | if (priv->iucv_state == IUCV_SEVERED) | 377 | if (priv->iucv_state == IUCV_SEVERED) |
342 | return -EPIPE; | 378 | return -EPIPE; |
343 | 379 | ||
344 | if (priv->iucv_state == IUCV_DISCONN) | 380 | if (priv->iucv_state == IUCV_DISCONN) |
345 | return 0; | 381 | return -EIO; |
346 | 382 | ||
347 | len = min_t(u16, MSG_MAX_DATALEN, count); | 383 | if (!priv->sndbuf_len) |
384 | return 0; | ||
348 | 385 | ||
349 | /* allocate internal buffer to store msg data and also compute total | 386 | /* allocate internal buffer to store msg data and also compute total |
350 | * message length */ | 387 | * message length */ |
351 | sb = alloc_tty_buffer(len, GFP_ATOMIC); | 388 | sb = alloc_tty_buffer(priv->sndbuf_len, GFP_ATOMIC); |
352 | if (!sb) | 389 | if (!sb) |
353 | return -ENOMEM; | 390 | return -ENOMEM; |
354 | 391 | ||
355 | sb->mbuf->datalen = len; | 392 | memcpy(sb->mbuf->data, priv->sndbuf, priv->sndbuf_len); |
356 | memcpy(sb->mbuf->data, buf, len); | 393 | sb->mbuf->datalen = (u16) priv->sndbuf_len; |
394 | sb->msg.length = MSG_SIZE(sb->mbuf->datalen); | ||
357 | 395 | ||
358 | list_add_tail(&sb->list, &priv->tty_outqueue); | 396 | list_add_tail(&sb->list, &priv->tty_outqueue); |
359 | 397 | ||
360 | rc = __iucv_message_send(priv->path, &sb->msg, 0, 0, | 398 | rc = __iucv_message_send(priv->path, &sb->msg, 0, 0, |
361 | (void *) sb->mbuf, sb->msg.length); | 399 | (void *) sb->mbuf, sb->msg.length); |
362 | if (rc) { | 400 | if (rc) { |
401 | /* drop the message here; however we might want to handle | ||
402 | * 0x03 (msg limit reached) by trying again... */ | ||
363 | list_del(&sb->list); | 403 | list_del(&sb->list); |
364 | destroy_tty_buffer(sb); | 404 | destroy_tty_buffer(sb); |
365 | len = 0; | ||
366 | } | 405 | } |
406 | len = priv->sndbuf_len; | ||
407 | priv->sndbuf_len = 0; | ||
367 | 408 | ||
368 | return len; | 409 | return len; |
369 | } | 410 | } |
370 | 411 | ||
371 | /** | 412 | /** |
413 | * hvc_iucv_sndbuf_work() - Send buffered data over IUCV | ||
414 | * @work: Work structure. | ||
415 | * | ||
416 | * This work queue function sends buffered output data over IUCV and, | ||
417 | * if not all buffered data could be sent, reschedules itself. | ||
418 | */ | ||
419 | static void hvc_iucv_sndbuf_work(struct work_struct *work) | ||
420 | { | ||
421 | struct hvc_iucv_private *priv; | ||
422 | |||
423 | priv = container_of(work, struct hvc_iucv_private, sndbuf_work.work); | ||
424 | if (!priv) | ||
425 | return; | ||
426 | |||
427 | spin_lock_bh(&priv->lock); | ||
428 | hvc_iucv_send(priv); | ||
429 | spin_unlock_bh(&priv->lock); | ||
430 | } | ||
431 | |||
432 | /** | ||
372 | * hvc_iucv_put_chars() - HVC put_chars operation. | 433 | * hvc_iucv_put_chars() - HVC put_chars operation. |
373 | * @vtermno: HVC virtual terminal number. | 434 | * @vtermno: HVC virtual terminal number. |
374 | * @buf: Pointer to an buffer to read data from | 435 | * @buf: Pointer to an buffer to read data from |
375 | * @count: Size of buffer available for reading | 436 | * @count: Size of buffer available for reading |
376 | * | 437 | * |
377 | * The hvc_console thread calls this method to write characters from | 438 | * The HVC thread calls this method to write characters to the back-end. |
378 | * to the terminal backend. | 439 | * The function calls hvc_iucv_queue() to queue terminal data for sending. |
379 | * The function calls hvc_iucv_send() under the lock of the | ||
380 | * struct hvc_iucv_private instance that corresponds to the tty @vtermno. | ||
381 | * | 440 | * |
382 | * Locking: The method gets called under an irqsave() spinlock; and | 441 | * Locking: The method gets called under an irqsave() spinlock; and |
383 | * locks struct hvc_iucv_private->lock. | 442 | * locks struct hvc_iucv_private->lock. |
@@ -385,7 +444,7 @@ static int hvc_iucv_send(struct hvc_iucv_private *priv, const char *buf, | |||
385 | static int hvc_iucv_put_chars(uint32_t vtermno, const char *buf, int count) | 444 | static int hvc_iucv_put_chars(uint32_t vtermno, const char *buf, int count) |
386 | { | 445 | { |
387 | struct hvc_iucv_private *priv = hvc_iucv_get_private(vtermno); | 446 | struct hvc_iucv_private *priv = hvc_iucv_get_private(vtermno); |
388 | int sent; | 447 | int queued; |
389 | 448 | ||
390 | if (count <= 0) | 449 | if (count <= 0) |
391 | return 0; | 450 | return 0; |
@@ -394,10 +453,10 @@ static int hvc_iucv_put_chars(uint32_t vtermno, const char *buf, int count) | |||
394 | return -ENODEV; | 453 | return -ENODEV; |
395 | 454 | ||
396 | spin_lock(&priv->lock); | 455 | spin_lock(&priv->lock); |
397 | sent = hvc_iucv_send(priv, buf, count); | 456 | queued = hvc_iucv_queue(priv, buf, count); |
398 | spin_unlock(&priv->lock); | 457 | spin_unlock(&priv->lock); |
399 | 458 | ||
400 | return sent; | 459 | return queued; |
401 | } | 460 | } |
402 | 461 | ||
403 | /** | 462 | /** |
@@ -406,7 +465,7 @@ static int hvc_iucv_put_chars(uint32_t vtermno, const char *buf, int count) | |||
406 | * @id: Additional data (originally passed to hvc_alloc): the index of an struct | 465 | * @id: Additional data (originally passed to hvc_alloc): the index of an struct |
407 | * hvc_iucv_private instance. | 466 | * hvc_iucv_private instance. |
408 | * | 467 | * |
409 | * The function sets the tty state to TTY_OPEN for the struct hvc_iucv_private | 468 | * The function sets the tty state to TTY_OPENED for the struct hvc_iucv_private |
410 | * instance that is derived from @id. Always returns 0. | 469 | * instance that is derived from @id. Always returns 0. |
411 | * | 470 | * |
412 | * Locking: struct hvc_iucv_private->lock, spin_lock_bh | 471 | * Locking: struct hvc_iucv_private->lock, spin_lock_bh |
@@ -427,12 +486,8 @@ static int hvc_iucv_notifier_add(struct hvc_struct *hp, int id) | |||
427 | } | 486 | } |
428 | 487 | ||
429 | /** | 488 | /** |
430 | * hvc_iucv_cleanup() - Clean up function if the tty portion is finally closed. | 489 | * hvc_iucv_cleanup() - Clean up and reset a z/VM IUCV HVC instance. |
431 | * @priv: Pointer to the struct hvc_iucv_private instance. | 490 | * @priv: Pointer to the struct hvc_iucv_private instance. |
432 | * | ||
433 | * The functions severs the established IUCV communication path (if any), and | ||
434 | * destroy struct iucv_tty_buffer elements from the in- and outqueue. Finally, | ||
435 | * the functions resets the states to TTY_CLOSED and IUCV_DISCONN. | ||
436 | */ | 491 | */ |
437 | static void hvc_iucv_cleanup(struct hvc_iucv_private *priv) | 492 | static void hvc_iucv_cleanup(struct hvc_iucv_private *priv) |
438 | { | 493 | { |
@@ -441,25 +496,62 @@ static void hvc_iucv_cleanup(struct hvc_iucv_private *priv) | |||
441 | 496 | ||
442 | priv->tty_state = TTY_CLOSED; | 497 | priv->tty_state = TTY_CLOSED; |
443 | priv->iucv_state = IUCV_DISCONN; | 498 | priv->iucv_state = IUCV_DISCONN; |
499 | |||
500 | priv->sndbuf_len = 0; | ||
444 | } | 501 | } |
445 | 502 | ||
446 | /** | 503 | /** |
447 | * hvc_iucv_notifier_hangup() - HVC notifier for tty hangups. | 504 | * tty_outqueue_empty() - Test if the tty outq is empty |
448 | * @hp: Pointer to the HVC device (struct hvc_struct) | 505 | * @priv: Pointer to struct hvc_iucv_private instance. |
449 | * @id: Additional data (originally passed to hvc_alloc): the index of an struct | 506 | */ |
450 | * hvc_iucv_private instance. | 507 | static inline int tty_outqueue_empty(struct hvc_iucv_private *priv) |
508 | { | ||
509 | int rc; | ||
510 | |||
511 | spin_lock_bh(&priv->lock); | ||
512 | rc = list_empty(&priv->tty_outqueue); | ||
513 | spin_unlock_bh(&priv->lock); | ||
514 | |||
515 | return rc; | ||
516 | } | ||
517 | |||
518 | /** | ||
519 | * flush_sndbuf_sync() - Flush send buffer and wait for completion | ||
520 | * @priv: Pointer to struct hvc_iucv_private instance. | ||
451 | * | 521 | * |
452 | * This routine notifies the HVC backend that a tty hangup (carrier loss, | 522 | * The routine cancels a pending sndbuf work, calls hvc_iucv_send() |
453 | * virtual or otherwise) has occured. | 523 | * to flush any buffered terminal output data and waits for completion. |
524 | */ | ||
525 | static void flush_sndbuf_sync(struct hvc_iucv_private *priv) | ||
526 | { | ||
527 | int sync_wait; | ||
528 | |||
529 | cancel_delayed_work_sync(&priv->sndbuf_work); | ||
530 | |||
531 | spin_lock_bh(&priv->lock); | ||
532 | hvc_iucv_send(priv); /* force sending buffered data */ | ||
533 | sync_wait = !list_empty(&priv->tty_outqueue); /* anything queued ? */ | ||
534 | spin_unlock_bh(&priv->lock); | ||
535 | |||
536 | if (sync_wait) | ||
537 | wait_event_timeout(priv->sndbuf_waitq, | ||
538 | tty_outqueue_empty(priv), HZ); | ||
539 | } | ||
540 | |||
541 | /** | ||
542 | * hvc_iucv_notifier_hangup() - HVC notifier for TTY hangups. | ||
543 | * @hp: Pointer to the HVC device (struct hvc_struct) | ||
544 | * @id: Additional data (originally passed to hvc_alloc): | ||
545 | * the index of an struct hvc_iucv_private instance. | ||
454 | * | 546 | * |
455 | * The HVC backend for z/VM IUCV ignores virtual hangups (vhangup()), to keep | 547 | * This routine notifies the HVC back-end that a tty hangup (carrier loss, |
456 | * an existing IUCV communication path established. | 548 | * virtual or otherwise) has occured. |
549 | * The z/VM IUCV HVC device driver ignores virtual hangups (vhangup()) | ||
550 | * to keep an existing IUCV communication path established. | ||
457 | * (Background: vhangup() is called from user space (by getty or login) to | 551 | * (Background: vhangup() is called from user space (by getty or login) to |
458 | * disable writing to the tty by other applications). | 552 | * disable writing to the tty by other applications). |
459 | * | 553 | * If the tty has been opened and an established IUCV path has been severed |
460 | * If the tty has been opened (e.g. getty) and an established IUCV path has been | 554 | * (we caused the tty hangup), the function calls hvc_iucv_cleanup(). |
461 | * severed (we caused the tty hangup in that case), then the functions invokes | ||
462 | * hvc_iucv_cleanup() to clean up. | ||
463 | * | 555 | * |
464 | * Locking: struct hvc_iucv_private->lock | 556 | * Locking: struct hvc_iucv_private->lock |
465 | */ | 557 | */ |
@@ -471,12 +563,12 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id) | |||
471 | if (!priv) | 563 | if (!priv) |
472 | return; | 564 | return; |
473 | 565 | ||
566 | flush_sndbuf_sync(priv); | ||
567 | |||
474 | spin_lock_bh(&priv->lock); | 568 | spin_lock_bh(&priv->lock); |
475 | /* NOTE: If the hangup was scheduled by ourself (from the iucv | 569 | /* NOTE: If the hangup was scheduled by ourself (from the iucv |
476 | * path_servered callback [IUCV_SEVERED]), then we have to | 570 | * path_servered callback [IUCV_SEVERED]), we have to clean up |
477 | * finally clean up the tty backend structure and set state to | 571 | * our structure and to set state to TTY_CLOSED. |
478 | * TTY_CLOSED. | ||
479 | * | ||
480 | * If the tty was hung up otherwise (e.g. vhangup()), then we | 572 | * If the tty was hung up otherwise (e.g. vhangup()), then we |
481 | * ignore this hangup and keep an established IUCV path open... | 573 | * ignore this hangup and keep an established IUCV path open... |
482 | * (...the reason is that we are not able to connect back to the | 574 | * (...the reason is that we are not able to connect back to the |
@@ -494,10 +586,9 @@ static void hvc_iucv_notifier_hangup(struct hvc_struct *hp, int id) | |||
494 | * @id: Additional data (originally passed to hvc_alloc): | 586 | * @id: Additional data (originally passed to hvc_alloc): |
495 | * the index of an struct hvc_iucv_private instance. | 587 | * the index of an struct hvc_iucv_private instance. |
496 | * | 588 | * |
497 | * This routine notifies the HVC backend that the last tty device file | 589 | * This routine notifies the HVC back-end that the last tty device fd has been |
498 | * descriptor has been closed. | 590 | * closed. The function calls hvc_iucv_cleanup() to clean up the struct |
499 | * The function calls hvc_iucv_cleanup() to clean up the struct hvc_iucv_private | 591 | * hvc_iucv_private instance. |
500 | * instance. | ||
501 | * | 592 | * |
502 | * Locking: struct hvc_iucv_private->lock | 593 | * Locking: struct hvc_iucv_private->lock |
503 | */ | 594 | */ |
@@ -510,6 +601,8 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) | |||
510 | if (!priv) | 601 | if (!priv) |
511 | return; | 602 | return; |
512 | 603 | ||
604 | flush_sndbuf_sync(priv); | ||
605 | |||
513 | spin_lock_bh(&priv->lock); | 606 | spin_lock_bh(&priv->lock); |
514 | path = priv->path; /* save reference to IUCV path */ | 607 | path = priv->path; /* save reference to IUCV path */ |
515 | priv->path = NULL; | 608 | priv->path = NULL; |
@@ -527,20 +620,18 @@ static void hvc_iucv_notifier_del(struct hvc_struct *hp, int id) | |||
527 | /** | 620 | /** |
528 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. | 621 | * hvc_iucv_path_pending() - IUCV handler to process a connection request. |
529 | * @path: Pending path (struct iucv_path) | 622 | * @path: Pending path (struct iucv_path) |
530 | * @ipvmid: Originator z/VM system identifier | 623 | * @ipvmid: z/VM system identifier of originator |
531 | * @ipuser: User specified data for this path | 624 | * @ipuser: User specified data for this path |
532 | * (AF_IUCV: port/service name and originator port) | 625 | * (AF_IUCV: port/service name and originator port) |
533 | * | 626 | * |
534 | * The function uses the @ipuser data to check to determine if the pending | 627 | * The function uses the @ipuser data to determine if the pending path belongs |
535 | * path belongs to a terminal managed by this HVC backend. | 628 | * to a terminal managed by this device driver. |
536 | * If the check is successful, then an additional check is done to ensure | 629 | * If the path belongs to this driver, ensure that the terminal is not accessed |
537 | * that a terminal cannot be accessed multiple times (only one connection | 630 | * multiple times (only one connection to a terminal is allowed). |
538 | * to a terminal is allowed). In that particular case, the pending path is | 631 | * If the terminal is not yet connected, the pending path is accepted and is |
539 | * severed. If it is the first connection, the pending path is accepted and | 632 | * associated to the appropriate struct hvc_iucv_private instance. |
540 | * associated to the struct hvc_iucv_private. The iucv state is updated to | ||
541 | * reflect that a communication path has been established. | ||
542 | * | 633 | * |
543 | * Returns 0 if the path belongs to a terminal managed by the this HVC backend; | 634 | * Returns 0 if @path belongs to a terminal managed by the this device driver; |
544 | * otherwise returns -ENODEV in order to dispatch this path to other handlers. | 635 | * otherwise returns -ENODEV in order to dispatch this path to other handlers. |
545 | * | 636 | * |
546 | * Locking: struct hvc_iucv_private->lock | 637 | * Locking: struct hvc_iucv_private->lock |
@@ -559,7 +650,6 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
559 | priv = hvc_iucv_table[i]; | 650 | priv = hvc_iucv_table[i]; |
560 | break; | 651 | break; |
561 | } | 652 | } |
562 | |||
563 | if (!priv) | 653 | if (!priv) |
564 | return -ENODEV; | 654 | return -ENODEV; |
565 | 655 | ||
@@ -588,6 +678,9 @@ static int hvc_iucv_path_pending(struct iucv_path *path, | |||
588 | priv->path = path; | 678 | priv->path = path; |
589 | priv->iucv_state = IUCV_CONNECTED; | 679 | priv->iucv_state = IUCV_CONNECTED; |
590 | 680 | ||
681 | /* flush buffered output data... */ | ||
682 | schedule_delayed_work(&priv->sndbuf_work, 5); | ||
683 | |||
591 | out_path_handled: | 684 | out_path_handled: |
592 | spin_unlock(&priv->lock); | 685 | spin_unlock(&priv->lock); |
593 | return 0; | 686 | return 0; |
@@ -603,8 +696,7 @@ out_path_handled: | |||
603 | * sets the iucv state to IUCV_SEVERED for the associated struct | 696 | * sets the iucv state to IUCV_SEVERED for the associated struct |
604 | * hvc_iucv_private instance. Later, the IUCV_SEVERED state triggers a tty | 697 | * hvc_iucv_private instance. Later, the IUCV_SEVERED state triggers a tty |
605 | * hangup (hvc_iucv_get_chars() / hvc_iucv_write()). | 698 | * hangup (hvc_iucv_get_chars() / hvc_iucv_write()). |
606 | * | 699 | * If tty portion of the HVC is closed, clean up the outqueue. |
607 | * If tty portion of the HVC is closed then clean up the outqueue in addition. | ||
608 | * | 700 | * |
609 | * Locking: struct hvc_iucv_private->lock | 701 | * Locking: struct hvc_iucv_private->lock |
610 | */ | 702 | */ |
@@ -615,15 +707,25 @@ static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16]) | |||
615 | spin_lock(&priv->lock); | 707 | spin_lock(&priv->lock); |
616 | priv->iucv_state = IUCV_SEVERED; | 708 | priv->iucv_state = IUCV_SEVERED; |
617 | 709 | ||
618 | /* NOTE: If the tty has not yet been opened by a getty program | 710 | /* If the tty has not yet been opened, clean up the hvc_iucv_private |
619 | * (e.g. to see console messages), then cleanup the | 711 | * structure to allow re-connects. |
620 | * hvc_iucv_private structure to allow re-connects. | 712 | * This is also done for our console device because console hangups |
713 | * are handled specially and no notifier is called by HVC. | ||
714 | * The tty session is active (TTY_OPEN) and ready for re-connects... | ||
621 | * | 715 | * |
622 | * If the tty has been opened, the get_chars() callback returns | 716 | * If it has been opened, let get_chars() return -EPIPE to signal the |
623 | * -EPIPE to signal the hvc console layer to hang up the tty. */ | 717 | * HVC layer to hang up the tty. |
718 | * If so, we need to wake up the HVC thread to call get_chars()... | ||
719 | */ | ||
624 | priv->path = NULL; | 720 | priv->path = NULL; |
625 | if (priv->tty_state == TTY_CLOSED) | 721 | if (priv->tty_state == TTY_CLOSED) |
626 | hvc_iucv_cleanup(priv); | 722 | hvc_iucv_cleanup(priv); |
723 | else | ||
724 | if (priv->is_console) { | ||
725 | hvc_iucv_cleanup(priv); | ||
726 | priv->tty_state = TTY_OPENED; | ||
727 | } else | ||
728 | hvc_kick(); | ||
627 | spin_unlock(&priv->lock); | 729 | spin_unlock(&priv->lock); |
628 | 730 | ||
629 | /* finally sever path (outside of priv->lock due to lock ordering) */ | 731 | /* finally sever path (outside of priv->lock due to lock ordering) */ |
@@ -636,9 +738,9 @@ static void hvc_iucv_path_severed(struct iucv_path *path, u8 ipuser[16]) | |||
636 | * @path: Pending path (struct iucv_path) | 738 | * @path: Pending path (struct iucv_path) |
637 | * @msg: Pointer to the IUCV message | 739 | * @msg: Pointer to the IUCV message |
638 | * | 740 | * |
639 | * The function stores an incoming message on the input queue for later | 741 | * The function puts an incoming message on the input queue for later |
640 | * processing (by hvc_iucv_get_chars() / hvc_iucv_write()). | 742 | * processing (by hvc_iucv_get_chars() / hvc_iucv_write()). |
641 | * However, if the tty has not yet been opened, the message is rejected. | 743 | * If the tty has not yet been opened, the message is rejected. |
642 | * | 744 | * |
643 | * Locking: struct hvc_iucv_private->lock | 745 | * Locking: struct hvc_iucv_private->lock |
644 | */ | 746 | */ |
@@ -648,6 +750,12 @@ static void hvc_iucv_msg_pending(struct iucv_path *path, | |||
648 | struct hvc_iucv_private *priv = path->private; | 750 | struct hvc_iucv_private *priv = path->private; |
649 | struct iucv_tty_buffer *rb; | 751 | struct iucv_tty_buffer *rb; |
650 | 752 | ||
753 | /* reject messages that exceed max size of iucv_tty_msg->datalen */ | ||
754 | if (msg->length > MSG_SIZE(MSG_MAX_DATALEN)) { | ||
755 | iucv_message_reject(path, msg); | ||
756 | return; | ||
757 | } | ||
758 | |||
651 | spin_lock(&priv->lock); | 759 | spin_lock(&priv->lock); |
652 | 760 | ||
653 | /* reject messages if tty has not yet been opened */ | 761 | /* reject messages if tty has not yet been opened */ |
@@ -656,7 +764,7 @@ static void hvc_iucv_msg_pending(struct iucv_path *path, | |||
656 | goto unlock_return; | 764 | goto unlock_return; |
657 | } | 765 | } |
658 | 766 | ||
659 | /* allocate buffer an empty buffer element */ | 767 | /* allocate tty buffer to save iucv msg only */ |
660 | rb = alloc_tty_buffer(0, GFP_ATOMIC); | 768 | rb = alloc_tty_buffer(0, GFP_ATOMIC); |
661 | if (!rb) { | 769 | if (!rb) { |
662 | iucv_message_reject(path, msg); | 770 | iucv_message_reject(path, msg); |
@@ -666,7 +774,7 @@ static void hvc_iucv_msg_pending(struct iucv_path *path, | |||
666 | 774 | ||
667 | list_add_tail(&rb->list, &priv->tty_inqueue); | 775 | list_add_tail(&rb->list, &priv->tty_inqueue); |
668 | 776 | ||
669 | hvc_kick(); /* wakup hvc console thread */ | 777 | hvc_kick(); /* wake up hvc thread */ |
670 | 778 | ||
671 | unlock_return: | 779 | unlock_return: |
672 | spin_unlock(&priv->lock); | 780 | spin_unlock(&priv->lock); |
@@ -677,10 +785,10 @@ unlock_return: | |||
677 | * @path: Pending path (struct iucv_path) | 785 | * @path: Pending path (struct iucv_path) |
678 | * @msg: Pointer to the IUCV message | 786 | * @msg: Pointer to the IUCV message |
679 | * | 787 | * |
680 | * The function is called upon completion of message delivery and the | 788 | * The function is called upon completion of message delivery to remove the |
681 | * message is removed from the outqueue. Additional delivery information | 789 | * message from the outqueue. Additional delivery information can be found |
682 | * can be found in msg->audit: rejected messages (0x040000 (IPADRJCT)) and | 790 | * msg->audit: rejected messages (0x040000 (IPADRJCT)), and |
683 | * purged messages (0x010000 (IPADPGNR)). | 791 | * purged messages (0x010000 (IPADPGNR)). |
684 | * | 792 | * |
685 | * Locking: struct hvc_iucv_private->lock | 793 | * Locking: struct hvc_iucv_private->lock |
686 | */ | 794 | */ |
@@ -697,6 +805,7 @@ static void hvc_iucv_msg_complete(struct iucv_path *path, | |||
697 | list_move(&ent->list, &list_remove); | 805 | list_move(&ent->list, &list_remove); |
698 | break; | 806 | break; |
699 | } | 807 | } |
808 | wake_up(&priv->sndbuf_waitq); | ||
700 | spin_unlock(&priv->lock); | 809 | spin_unlock(&priv->lock); |
701 | destroy_tty_buffer_list(&list_remove); | 810 | destroy_tty_buffer_list(&list_remove); |
702 | } | 811 | } |
@@ -713,13 +822,14 @@ static struct hv_ops hvc_iucv_ops = { | |||
713 | 822 | ||
714 | /** | 823 | /** |
715 | * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance | 824 | * hvc_iucv_alloc() - Allocates a new struct hvc_iucv_private instance |
716 | * @id: hvc_iucv_table index | 825 | * @id: hvc_iucv_table index |
826 | * @is_console: Flag if the instance is used as Linux console | ||
717 | * | 827 | * |
718 | * This function allocates a new hvc_iucv_private struct and put the | 828 | * This function allocates a new hvc_iucv_private structure and stores |
719 | * instance into hvc_iucv_table at index @id. | 829 | * the instance in hvc_iucv_table at index @id. |
720 | * Returns 0 on success; otherwise non-zero. | 830 | * Returns 0 on success; otherwise non-zero. |
721 | */ | 831 | */ |
722 | static int __init hvc_iucv_alloc(int id) | 832 | static int __init hvc_iucv_alloc(int id, unsigned int is_console) |
723 | { | 833 | { |
724 | struct hvc_iucv_private *priv; | 834 | struct hvc_iucv_private *priv; |
725 | char name[9]; | 835 | char name[9]; |
@@ -732,18 +842,33 @@ static int __init hvc_iucv_alloc(int id) | |||
732 | spin_lock_init(&priv->lock); | 842 | spin_lock_init(&priv->lock); |
733 | INIT_LIST_HEAD(&priv->tty_outqueue); | 843 | INIT_LIST_HEAD(&priv->tty_outqueue); |
734 | INIT_LIST_HEAD(&priv->tty_inqueue); | 844 | INIT_LIST_HEAD(&priv->tty_inqueue); |
845 | INIT_DELAYED_WORK(&priv->sndbuf_work, hvc_iucv_sndbuf_work); | ||
846 | init_waitqueue_head(&priv->sndbuf_waitq); | ||
847 | |||
848 | priv->sndbuf = (void *) get_zeroed_page(GFP_KERNEL); | ||
849 | if (!priv->sndbuf) { | ||
850 | kfree(priv); | ||
851 | return -ENOMEM; | ||
852 | } | ||
853 | |||
854 | /* set console flag */ | ||
855 | priv->is_console = is_console; | ||
735 | 856 | ||
736 | /* Finally allocate hvc */ | 857 | /* finally allocate hvc */ |
737 | priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, | 858 | priv->hvc = hvc_alloc(HVC_IUCV_MAGIC + id, /* PAGE_SIZE */ |
738 | HVC_IUCV_MAGIC + id, &hvc_iucv_ops, PAGE_SIZE); | 859 | HVC_IUCV_MAGIC + id, &hvc_iucv_ops, 256); |
739 | if (IS_ERR(priv->hvc)) { | 860 | if (IS_ERR(priv->hvc)) { |
740 | rc = PTR_ERR(priv->hvc); | 861 | rc = PTR_ERR(priv->hvc); |
862 | free_page((unsigned long) priv->sndbuf); | ||
741 | kfree(priv); | 863 | kfree(priv); |
742 | return rc; | 864 | return rc; |
743 | } | 865 | } |
744 | 866 | ||
867 | /* notify HVC thread instead of using polling */ | ||
868 | priv->hvc->irq_requested = 1; | ||
869 | |||
745 | /* setup iucv related information */ | 870 | /* setup iucv related information */ |
746 | snprintf(name, 9, "ihvc%-4d", id); | 871 | snprintf(name, 9, "lnxhvc%-2d", id); |
747 | memcpy(priv->srv_name, name, 8); | 872 | memcpy(priv->srv_name, name, 8); |
748 | ASCEBC(priv->srv_name, 8); | 873 | ASCEBC(priv->srv_name, 8); |
749 | 874 | ||
@@ -752,15 +877,16 @@ static int __init hvc_iucv_alloc(int id) | |||
752 | } | 877 | } |
753 | 878 | ||
754 | /** | 879 | /** |
755 | * hvc_iucv_init() - Initialization of HVC backend for z/VM IUCV | 880 | * hvc_iucv_init() - z/VM IUCV HVC device driver initialization |
756 | */ | 881 | */ |
757 | static int __init hvc_iucv_init(void) | 882 | static int __init hvc_iucv_init(void) |
758 | { | 883 | { |
759 | int rc, i; | 884 | int rc; |
885 | unsigned int i; | ||
760 | 886 | ||
761 | if (!MACHINE_IS_VM) { | 887 | if (!MACHINE_IS_VM) { |
762 | pr_warning("The z/VM IUCV Hypervisor console cannot be " | 888 | pr_info("The z/VM IUCV HVC device driver cannot " |
763 | "used without z/VM.\n"); | 889 | "be used without z/VM\n"); |
764 | return -ENODEV; | 890 | return -ENODEV; |
765 | } | 891 | } |
766 | 892 | ||
@@ -774,26 +900,33 @@ static int __init hvc_iucv_init(void) | |||
774 | sizeof(struct iucv_tty_buffer), | 900 | sizeof(struct iucv_tty_buffer), |
775 | 0, 0, NULL); | 901 | 0, 0, NULL); |
776 | if (!hvc_iucv_buffer_cache) { | 902 | if (!hvc_iucv_buffer_cache) { |
777 | pr_err("Not enough memory for driver initialization " | 903 | pr_err("Allocating memory failed with reason code=%d\n", 1); |
778 | "(rs=%d).\n", 1); | ||
779 | return -ENOMEM; | 904 | return -ENOMEM; |
780 | } | 905 | } |
781 | 906 | ||
782 | hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, | 907 | hvc_iucv_mempool = mempool_create_slab_pool(MEMPOOL_MIN_NR, |
783 | hvc_iucv_buffer_cache); | 908 | hvc_iucv_buffer_cache); |
784 | if (!hvc_iucv_mempool) { | 909 | if (!hvc_iucv_mempool) { |
785 | pr_err("Not enough memory for driver initialization " | 910 | pr_err("Allocating memory failed with reason code=%d\n", 2); |
786 | "(rs=%d).\n", 2); | ||
787 | kmem_cache_destroy(hvc_iucv_buffer_cache); | 911 | kmem_cache_destroy(hvc_iucv_buffer_cache); |
788 | return -ENOMEM; | 912 | return -ENOMEM; |
789 | } | 913 | } |
790 | 914 | ||
915 | /* register the first terminal device as console | ||
916 | * (must be done before allocating hvc terminal devices) */ | ||
917 | rc = hvc_instantiate(HVC_IUCV_MAGIC, IUCV_HVC_CON_IDX, &hvc_iucv_ops); | ||
918 | if (rc) { | ||
919 | pr_err("Registering HVC terminal device as " | ||
920 | "Linux console failed\n"); | ||
921 | goto out_error_memory; | ||
922 | } | ||
923 | |||
791 | /* allocate hvc_iucv_private structs */ | 924 | /* allocate hvc_iucv_private structs */ |
792 | for (i = 0; i < hvc_iucv_devices; i++) { | 925 | for (i = 0; i < hvc_iucv_devices; i++) { |
793 | rc = hvc_iucv_alloc(i); | 926 | rc = hvc_iucv_alloc(i, (i == IUCV_HVC_CON_IDX) ? 1 : 0); |
794 | if (rc) { | 927 | if (rc) { |
795 | pr_err("Could not create new z/VM IUCV HVC backend " | 928 | pr_err("Creating a new HVC terminal device " |
796 | "rc=%d.\n", rc); | 929 | "failed with error code=%d\n", rc); |
797 | goto out_error_hvc; | 930 | goto out_error_hvc; |
798 | } | 931 | } |
799 | } | 932 | } |
@@ -801,7 +934,8 @@ static int __init hvc_iucv_init(void) | |||
801 | /* register IUCV callback handler */ | 934 | /* register IUCV callback handler */ |
802 | rc = iucv_register(&hvc_iucv_handler, 0); | 935 | rc = iucv_register(&hvc_iucv_handler, 0); |
803 | if (rc) { | 936 | if (rc) { |
804 | pr_err("Could not register iucv handler (rc=%d).\n", rc); | 937 | pr_err("Registering IUCV handlers failed with error code=%d\n", |
938 | rc); | ||
805 | goto out_error_iucv; | 939 | goto out_error_iucv; |
806 | } | 940 | } |
807 | 941 | ||
@@ -816,22 +950,13 @@ out_error_hvc: | |||
816 | hvc_remove(hvc_iucv_table[i]->hvc); | 950 | hvc_remove(hvc_iucv_table[i]->hvc); |
817 | kfree(hvc_iucv_table[i]); | 951 | kfree(hvc_iucv_table[i]); |
818 | } | 952 | } |
953 | out_error_memory: | ||
819 | mempool_destroy(hvc_iucv_mempool); | 954 | mempool_destroy(hvc_iucv_mempool); |
820 | kmem_cache_destroy(hvc_iucv_buffer_cache); | 955 | kmem_cache_destroy(hvc_iucv_buffer_cache); |
821 | return rc; | 956 | return rc; |
822 | } | 957 | } |
823 | 958 | ||
824 | /** | 959 | /** |
825 | * hvc_iucv_console_init() - Early console initialization | ||
826 | */ | ||
827 | static int __init hvc_iucv_console_init(void) | ||
828 | { | ||
829 | if (!MACHINE_IS_VM || !hvc_iucv_devices) | ||
830 | return -ENODEV; | ||
831 | return hvc_instantiate(HVC_IUCV_MAGIC, 0, &hvc_iucv_ops); | ||
832 | } | ||
833 | |||
834 | /** | ||
835 | * hvc_iucv_config() - Parsing of hvc_iucv= kernel command line parameter | 960 | * hvc_iucv_config() - Parsing of hvc_iucv= kernel command line parameter |
836 | * @val: Parameter value (numeric) | 961 | * @val: Parameter value (numeric) |
837 | */ | 962 | */ |
@@ -841,10 +966,5 @@ static int __init hvc_iucv_config(char *val) | |||
841 | } | 966 | } |
842 | 967 | ||
843 | 968 | ||
844 | module_init(hvc_iucv_init); | 969 | device_initcall(hvc_iucv_init); |
845 | console_initcall(hvc_iucv_console_init); | ||
846 | __setup("hvc_iucv=", hvc_iucv_config); | 970 | __setup("hvc_iucv=", hvc_iucv_config); |
847 | |||
848 | MODULE_LICENSE("GPL"); | ||
849 | MODULE_DESCRIPTION("HVC back-end for z/VM IUCV."); | ||
850 | MODULE_AUTHOR("Hendrik Brueckner <brueckner@linux.vnet.ibm.com>"); | ||
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 8859aeac2d25..9b3e09cd41f9 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
@@ -482,7 +482,7 @@ static void n2rng_dump_test_buffer(struct n2rng *np) | |||
482 | int i; | 482 | int i; |
483 | 483 | ||
484 | for (i = 0; i < SELFTEST_BUFFER_WORDS; i++) | 484 | for (i = 0; i < SELFTEST_BUFFER_WORDS; i++) |
485 | dev_err(&np->op->dev, "Test buffer slot %d [0x%016lx]\n", | 485 | dev_err(&np->op->dev, "Test buffer slot %d [0x%016llx]\n", |
486 | i, np->test_buffer[i]); | 486 | i, np->test_buffer[i]); |
487 | } | 487 | } |
488 | 488 | ||
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 112a6ba9a96f..146c97613da0 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | /* These are global because they are accessed in tty_io.c */ | 33 | /* These are global because they are accessed in tty_io.c */ |
34 | #ifdef CONFIG_UNIX98_PTYS | 34 | #ifdef CONFIG_UNIX98_PTYS |
35 | struct tty_driver *ptm_driver; | 35 | static struct tty_driver *ptm_driver; |
36 | static struct tty_driver *pts_driver; | 36 | static struct tty_driver *pts_driver; |
37 | #endif | 37 | #endif |
38 | 38 | ||
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 20d6efb6324e..e0d0f8b2696b 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -48,9 +48,10 @@ | |||
48 | * CONFIG_HPET_EMULATE_RTC | 48 | * CONFIG_HPET_EMULATE_RTC |
49 | * 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly. | 49 | * 1.12a Maciej W. Rozycki: Handle memory-mapped chips properly. |
50 | * 1.12ac Alan Cox: Allow read access to the day of week register | 50 | * 1.12ac Alan Cox: Allow read access to the day of week register |
51 | * 1.12b David John: Remove calls to the BKL. | ||
51 | */ | 52 | */ |
52 | 53 | ||
53 | #define RTC_VERSION "1.12ac" | 54 | #define RTC_VERSION "1.12b" |
54 | 55 | ||
55 | /* | 56 | /* |
56 | * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with | 57 | * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with |
@@ -73,7 +74,6 @@ | |||
73 | #include <linux/proc_fs.h> | 74 | #include <linux/proc_fs.h> |
74 | #include <linux/seq_file.h> | 75 | #include <linux/seq_file.h> |
75 | #include <linux/spinlock.h> | 76 | #include <linux/spinlock.h> |
76 | #include <linux/smp_lock.h> | ||
77 | #include <linux/sysctl.h> | 77 | #include <linux/sysctl.h> |
78 | #include <linux/wait.h> | 78 | #include <linux/wait.h> |
79 | #include <linux/bcd.h> | 79 | #include <linux/bcd.h> |
@@ -182,8 +182,8 @@ static int rtc_proc_open(struct inode *inode, struct file *file); | |||
182 | 182 | ||
183 | /* | 183 | /* |
184 | * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is | 184 | * rtc_status is never changed by rtc_interrupt, and ioctl/open/close is |
185 | * protected by the big kernel lock. However, ioctl can still disable the timer | 185 | * protected by the spin lock rtc_lock. However, ioctl can still disable the |
186 | * in rtc_status and then with del_timer after the interrupt has read | 186 | * timer in rtc_status and then with del_timer after the interrupt has read |
187 | * rtc_status but before mod_timer is called, which would then reenable the | 187 | * rtc_status but before mod_timer is called, which would then reenable the |
188 | * timer (but you would need to have an awful timing before you'd trip on it) | 188 | * timer (but you would need to have an awful timing before you'd trip on it) |
189 | */ | 189 | */ |
@@ -720,9 +720,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) | |||
720 | static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 720 | static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
721 | { | 721 | { |
722 | long ret; | 722 | long ret; |
723 | lock_kernel(); | ||
724 | ret = rtc_do_ioctl(cmd, arg, 0); | 723 | ret = rtc_do_ioctl(cmd, arg, 0); |
725 | unlock_kernel(); | ||
726 | return ret; | 724 | return ret; |
727 | } | 725 | } |
728 | 726 | ||
@@ -731,12 +729,8 @@ static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
731 | * Also clear the previous interrupt data on an open, and clean | 729 | * Also clear the previous interrupt data on an open, and clean |
732 | * up things on a close. | 730 | * up things on a close. |
733 | */ | 731 | */ |
734 | |||
735 | /* We use rtc_lock to protect against concurrent opens. So the BKL is not | ||
736 | * needed here. Or anywhere else in this driver. */ | ||
737 | static int rtc_open(struct inode *inode, struct file *file) | 732 | static int rtc_open(struct inode *inode, struct file *file) |
738 | { | 733 | { |
739 | lock_kernel(); | ||
740 | spin_lock_irq(&rtc_lock); | 734 | spin_lock_irq(&rtc_lock); |
741 | 735 | ||
742 | if (rtc_status & RTC_IS_OPEN) | 736 | if (rtc_status & RTC_IS_OPEN) |
@@ -746,12 +740,10 @@ static int rtc_open(struct inode *inode, struct file *file) | |||
746 | 740 | ||
747 | rtc_irq_data = 0; | 741 | rtc_irq_data = 0; |
748 | spin_unlock_irq(&rtc_lock); | 742 | spin_unlock_irq(&rtc_lock); |
749 | unlock_kernel(); | ||
750 | return 0; | 743 | return 0; |
751 | 744 | ||
752 | out_busy: | 745 | out_busy: |
753 | spin_unlock_irq(&rtc_lock); | 746 | spin_unlock_irq(&rtc_lock); |
754 | unlock_kernel(); | ||
755 | return -EBUSY; | 747 | return -EBUSY; |
756 | } | 748 | } |
757 | 749 | ||
@@ -800,7 +792,6 @@ no_irq: | |||
800 | } | 792 | } |
801 | 793 | ||
802 | #ifdef RTC_IRQ | 794 | #ifdef RTC_IRQ |
803 | /* Called without the kernel lock - fine */ | ||
804 | static unsigned int rtc_poll(struct file *file, poll_table *wait) | 795 | static unsigned int rtc_poll(struct file *file, poll_table *wait) |
805 | { | 796 | { |
806 | unsigned long l; | 797 | unsigned long l; |
diff --git a/drivers/char/tpm/tpm_bios.c b/drivers/char/tpm/tpm_bios.c index 68f052b42ed7..ed306eb1057f 100644 --- a/drivers/char/tpm/tpm_bios.c +++ b/drivers/char/tpm/tpm_bios.c | |||
@@ -23,8 +23,6 @@ | |||
23 | #include <linux/security.h> | 23 | #include <linux/security.h> |
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <acpi/acpi.h> | 25 | #include <acpi/acpi.h> |
26 | #include <acpi/actypes.h> | ||
27 | #include <acpi/actbl.h> | ||
28 | #include "tpm.h" | 26 | #include "tpm.h" |
29 | 27 | ||
30 | #define TCG_EVENT_NAME_LEN_MAX 255 | 28 | #define TCG_EVENT_NAME_LEN_MAX 255 |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index ab18c1e7b115..70efba2ee053 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
@@ -273,12 +273,23 @@ static void tpm_nsc_remove(struct device *dev) | |||
273 | } | 273 | } |
274 | } | 274 | } |
275 | 275 | ||
276 | static struct device_driver nsc_drv = { | 276 | static int tpm_nsc_suspend(struct platform_device *dev, pm_message_t msg) |
277 | .name = "tpm_nsc", | 277 | { |
278 | .bus = &platform_bus_type, | 278 | return tpm_pm_suspend(&dev->dev, msg); |
279 | .owner = THIS_MODULE, | 279 | } |
280 | .suspend = tpm_pm_suspend, | 280 | |
281 | .resume = tpm_pm_resume, | 281 | static int tpm_nsc_resume(struct platform_device *dev) |
282 | { | ||
283 | return tpm_pm_resume(&dev->dev); | ||
284 | } | ||
285 | |||
286 | static struct platform_driver nsc_drv = { | ||
287 | .suspend = tpm_nsc_suspend, | ||
288 | .resume = tpm_nsc_resume, | ||
289 | .driver = { | ||
290 | .name = "tpm_nsc", | ||
291 | .owner = THIS_MODULE, | ||
292 | }, | ||
282 | }; | 293 | }; |
283 | 294 | ||
284 | static int __init init_nsc(void) | 295 | static int __init init_nsc(void) |
@@ -297,7 +308,7 @@ static int __init init_nsc(void) | |||
297 | return -ENODEV; | 308 | return -ENODEV; |
298 | } | 309 | } |
299 | 310 | ||
300 | err = driver_register(&nsc_drv); | 311 | err = platform_driver_register(&nsc_drv); |
301 | if (err) | 312 | if (err) |
302 | return err; | 313 | return err; |
303 | 314 | ||
@@ -308,17 +319,15 @@ static int __init init_nsc(void) | |||
308 | /* enable the DPM module */ | 319 | /* enable the DPM module */ |
309 | tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); | 320 | tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01); |
310 | 321 | ||
311 | pdev = kzalloc(sizeof(struct platform_device), GFP_KERNEL); | 322 | pdev = platform_device_alloc("tpm_nscl0", -1); |
312 | if (!pdev) { | 323 | if (!pdev) { |
313 | rc = -ENOMEM; | 324 | rc = -ENOMEM; |
314 | goto err_unreg_drv; | 325 | goto err_unreg_drv; |
315 | } | 326 | } |
316 | 327 | ||
317 | pdev->name = "tpm_nscl0"; | ||
318 | pdev->id = -1; | ||
319 | pdev->num_resources = 0; | 328 | pdev->num_resources = 0; |
329 | pdev->dev.driver = &nsc_drv.driver; | ||
320 | pdev->dev.release = tpm_nsc_remove; | 330 | pdev->dev.release = tpm_nsc_remove; |
321 | pdev->dev.driver = &nsc_drv; | ||
322 | 331 | ||
323 | if ((rc = platform_device_register(pdev)) < 0) | 332 | if ((rc = platform_device_register(pdev)) < 0) |
324 | goto err_free_dev; | 333 | goto err_free_dev; |
@@ -377,7 +386,7 @@ err_unreg_dev: | |||
377 | err_free_dev: | 386 | err_free_dev: |
378 | kfree(pdev); | 387 | kfree(pdev); |
379 | err_unreg_drv: | 388 | err_unreg_drv: |
380 | driver_unregister(&nsc_drv); | 389 | platform_driver_unregister(&nsc_drv); |
381 | return rc; | 390 | return rc; |
382 | } | 391 | } |
383 | 392 | ||
@@ -390,7 +399,7 @@ static void __exit cleanup_nsc(void) | |||
390 | pdev = NULL; | 399 | pdev = NULL; |
391 | } | 400 | } |
392 | 401 | ||
393 | driver_unregister(&nsc_drv); | 402 | platform_driver_unregister(&nsc_drv); |
394 | } | 403 | } |
395 | 404 | ||
396 | module_init(init_nsc); | 405 | module_init(init_nsc); |
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 80014213fb53..7900bd63b36d 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -969,8 +969,7 @@ int vc_resize(struct vc_data *vc, unsigned int cols, unsigned int rows) | |||
969 | * Takes the console sem and the called methods then take the tty | 969 | * Takes the console sem and the called methods then take the tty |
970 | * termios_mutex and the tty ctrl_lock in that order. | 970 | * termios_mutex and the tty ctrl_lock in that order. |
971 | */ | 971 | */ |
972 | 972 | static int vt_resize(struct tty_struct *tty, struct winsize *ws) | |
973 | int vt_resize(struct tty_struct *tty, struct winsize *ws) | ||
974 | { | 973 | { |
975 | struct vc_data *vc = tty->driver_data; | 974 | struct vc_data *vc = tty->driver_data; |
976 | int ret; | 975 | int ret; |